builder_pattern/lib.rs
1//! A derivable macro for declaring a builder pattern.
2//! This crate is highly inspired by [derive_builder](https://crates.io/crates/derive-builder).
3//!
4//! ## Usage
5//!
6//! ```
7//! use builder_pattern::Builder;
8//! # enum Gender {
9//! # Male,
10//! # Female,
11//! # Nonbinary
12//! # }
13//!
14//! #[derive(Builder)]
15//! struct Person {
16//! #[into]
17//! name: String,
18//! age: i32,
19//! #[default(Gender::Nonbinary)]
20//! #[setter(value, async)]
21//! gender: Gender,
22//! }
23//!
24//! let p1 = Person::new() // PersonBuilder<(), (), (), ...>
25//! .name(String::from("Joe")) // PersonBuilder<String, (), (), ...>
26//! .age(27) // PersonBuilder<String, i32, (), ...>
27//! .build(); // Person
28//!
29//! // Order does not matter.
30//! let p2 = Person::new() // PersonBuilder<(), (), (), ...>
31//! .age(32) // PersonBuilder<(), i32, (), ...>
32//! // `&str` is implicitly converted into `String`
33//! // because of `into` attribute!
34//! .name("Jack") // PersonBuilder<String, i32, (), ...>
35//! .gender(Gender::Male) // PersonBuilder<String, i32, Gender, ...>
36//! .build(); // Person
37//!
38//! // Asynchronously evaluated
39//! # tokio_test::block_on(async {
40//! let p3 = Person::new() // PersonBuilder<(), (), (), ...>
41//! .age(32) // PersonBuilder<(), i32, (), ...>
42//! // `&str` is implicitly converted into `String`
43//! // because of `into` attribute!
44//! .name("Jack") // PersonBuilder<String, i32, (), ...>
45//! .gender_async(|| async {
46//! Gender::Male
47//! }) // PersonBuilder<String, i32, Gender, ...>
48//! .build() // Future<Person>
49//! .await; // Person
50//! # });
51//! # // cont
52//! ```
53//! ```compile_fail
54//! # // cont
55//! # use builder_pattern::Builder;
56//! # enum Gender {
57//! # Male,
58//! # Female,
59//! # Nonbinary
60//! # }
61//! #
62//! # #[derive(Builder)]
63//! # struct Person {
64//! # #[into]
65//! # name: String,
66//! # age: i32,
67//! # #[default(Gender::Nonbinary)]
68//! # gender: Gender,
69//! # }
70//! // `name` field required - Compilation error.
71//! let p4 = Person::new() // PersonBuilder<(), (), (), ...>
72//! .age(15) // PersonBuilder<(), i32, (), ...>
73//! .build();
74//! ```
75//!
76//! ## Features
77//!
78//! - **Chaining**: Can make structure with chained setters.
79//! - **Complex types are supported**: Lifetime, trait bounds, and where clauses are well supported.
80//! - **Type safety**: Autocompletion tools can suggest correct setters to build the struct. Also, `build`
81//! function is allowed only the all of required fields are provided. **No Result**, **No Unwrap**. Just use it.
82//! - **Lazy evaluation and asynchronous**: Lazy evaluation and asynchronous are supported.
83//! The values will be evaluated when the structure is built.
84//! - **No additional tasks**: There's no additional constraints to use the macro. Any structures and fields are allowed.
85//! - **Auto-generated documentation**: Documentation for the builder functions are automatically generated.
86//!
87//! ## Attributes
88//!
89//! ### `#[default(expr)]`
90//!
91//! A field having this attribute will be considered as optional, and the `expr` will be evaluated
92//! as a default value of the field. `build` function can be called without providing this field.
93//!
94//! ```
95//! # use builder_pattern::Builder;
96//! #[derive(Builder)]
97//! struct Test {
98//! #[default(5)]
99//! pub a: i32,
100//! pub b: &'static str,
101//! }
102//!
103//! let t1 = Test::new().b("Hello").build(); // The structure can be built without `a`.
104//! let t2 = Test::new().b("Hi").a(3).build();
105//! ```
106//! ### `#[default_lazy(expr)]`
107//!
108//! A field having this attribute will be considered as optional, and the `expr`
109//! will be lazily evaluated as a default value of the field. `expr` should be
110//! a function or a closure having no arguments.
111//!
112//! ```
113//! # use builder_pattern::Builder;
114//! # fn some_heavy_task() -> i32 { 3 }
115//! #[derive(Builder)]
116//! struct Test {
117//! #[default_lazy(|| some_heavy_task() + 3)]
118//! pub a: i32,
119//! #[default_lazy(some_heavy_task)]
120//! pub b: i32,
121//! }
122//!
123//! // The structure can be built without `a` and `b`.
124//! let t1 = Test::new().build();
125//! let t2 = Test::new().a(3).build();
126//! ```
127//!
128//! ### `#[hidden]`
129//!
130//! If this attribute is present, the builder function would not be generated for the field.
131//! This field requires `default` or `default_lazy` attribute.
132//!
133//! Example:
134//!
135//! ```
136//! # use builder_pattern::Builder;
137//! # use uuid::Uuid;
138//! #[derive(Builder)]
139//! struct Test {
140//! #[default(Uuid::new_v4())]
141//! #[hidden]
142//! id: Uuid,
143//! name: String,
144//! }
145//!
146//! let test1 = Test::new() // TestBuilder<(), (), ...>
147//! .name(String::from("Joe")) // TestBuilder<String, (), ...>
148//! .build(); // Test
149//! # // cont
150//! ```
151//! ```compile_fail
152//! # // cont
153//! # use builder_pattern::Builder;
154//! # use uuid::Uuid;
155//! # #[derive(Builder)]
156//! # struct Test {
157//! # #[default(Uuid::new_v4())]
158//! # #[hidden]
159//! # id: Uuid,
160//! # name: String,
161//! # }
162//! let test2 = Test::new() // TestBuilder<(), (), ...>
163//! .name(String::from("Jack")) // TestBuilder<String, (), ...>
164//! // Error: `id` function is not generated.
165//! .id(Uuid::parse_str("46ebd0ee-0e6d-43c9-b90d-ccc35a913f3e").unwrap())
166//! .build();
167//! ```
168//!
169//! ### `#[public]`
170//!
171//! If this attribute is present, a field would be exposed with setter functions even though the
172//! field is private. It provides a way to access private fields during the building.
173//!
174//! Example:
175//!
176//! ```
177//! # use uuid::Uuid;
178//! mod test {
179//! # use builder_pattern::Builder;
180//! # use uuid::Uuid;
181//! #[derive(Builder)]
182//! pub struct Test {
183//! #[public]
184//! id: Uuid,
185//! pub name: &'static str,
186//! }
187//! }
188//! use test::Test;
189//!
190//! let test1 = Test::new() // TestBuilder<(), (), ...>
191//! .id(Uuid::new_v4()) // TestBuilder<Uuid, (), ...>
192//! .name("Joe") // TestBuilder<Uuid, &'static str, ...>
193//! .build(); // Test
194//! assert_eq!(test1.name, "Joe");
195//! # // cont
196//! ```
197//! ```compile_fail
198//! # //cont
199//! # use uuid::Uuid;
200//! # mod test {
201//! # use builder_pattern::Builder;
202//! # use uuid::Uuid;
203//! # #[derive(Builder)]
204//! # pub struct Test {
205//! # #[public]
206//! # id: Uuid,
207//! # pub name: &'static str,
208//! # }
209//! # }
210//! # use test::Test;
211//! # let test1 = Test::new()
212//! # .id(Uuid::new_v4())
213//! # .name("Joe")
214//! # .build();
215//! println!("{}", test1.id); // Error: `id` is a private field.
216//! ```
217//!
218//! ### `#[setter(value | lazy | async)]`
219//!
220//! If this attribute presents, it provides specified setters.
221//! If it doesn't, only the value setter is provided.
222//!
223//! ```
224//! # use builder_pattern::Builder;
225//! #[derive(Builder, Debug)]
226//! struct Person {
227//! // All kinds of setters are provided.
228//! #[setter(value, lazy, async)]
229//! name: String,
230//! // Only value setter is provided.
231//! age: u8,
232//! // Only lazy setter is provided.
233//! #[setter(lazy)]
234//! address: &'static str,
235//! }
236//!
237//! # tokio_test::block_on(async {
238//! let p1 = Person::new()
239//! .name_async(|| async { String::from("Joe") })
240//! .age(15)
241//! .address_lazy(|| "123 Main St")
242//! .build() // `address` is validated here
243//! .await; // `name` is validated here
244//! # });
245//! ```
246//!
247//! ### `#[into]`
248//!
249//! A setter function for a field having this attribute will accept `Into`
250//! trait as a parameter. You can use this setter with implicit conversion.
251//!
252//! Example:
253//!
254//! ```
255//! # use builder_pattern::Builder;
256//! #[derive(Builder)]
257//! struct Test {
258//! #[into]
259//! #[setter(value, lazy)]
260//! pub name: String,
261//! }
262//!
263//! let test1 = Test::new() // TestBuilder<(), ...>
264//! // `&str` is implicitly converted into `String`.
265//! .name("Hello") // TestBuilder<String, ...>
266//! .build(); // Test
267//!
268//! let test2 = Test::new() // TestBuilder<(), ...>
269//! // `&str` is implicitly converted into `String`.
270//! .name_lazy(|| "Hello") // TestBuilder<String, ...>
271//! .build(); // Test
272//! ```
273//!
274//! ### `#[validator(expr)]`
275//!
276//! Implement a validator for a field. `expr` could be a validating function that takes the field's
277//! type and returns `Result`.
278//!
279//! ```
280//! # use builder_pattern::Builder;
281//! #[derive(Builder)]
282//! struct Test {
283//! #[validator(is_not_empty)]
284//! #[into]
285//! pub name: String,
286//! }
287//!
288//! fn is_not_empty(name: String) -> Result<String, &'static str> {
289//! if name.is_empty() {
290//! Err("Name cannot be empty.")
291//! } else {
292//! Ok(name)
293//! }
294//! }
295//!
296//! let test1 = Test::new() // TestBuilder<(), ...>
297//! .name(String::from("Hello")) // Ok(TestBuilder<String, ...>)
298//! .unwrap() // TestBuilder<String, ...>
299//! .build(); // Test
300//! # // cont
301//! ```
302//! ```should_panic
303//! # // cont
304//! # use builder_pattern::Builder;
305//! # #[derive(Builder)]
306//! # struct Test {
307//! # #[validator(is_not_empty)]
308//! # #[into]
309//! # pub name: String,
310//! # }
311//! #
312//! # fn is_not_empty(name: String) -> Result<String, &'static str> {
313//! # if name.is_empty() {
314//! # Err("Name cannot be empty.")
315//! # } else {
316//! # Ok(name)
317//! # }
318//! # }
319//! #
320//! let test2 = Test::new() // TestBuilder<(), ...>
321//! .name("") // Err(String{ "Validation failed: Name cannot be empty." })
322//! .unwrap() // panic!
323//! .build();
324//! ```
325//!
326//! If a `validator` is used with `lazy` or `async` setters,
327//! it will also validated lazily or asynchronously. So, the
328//! setter doesn't return `Result` but it is returned when it is built.
329//!
330//! ```
331//! # use builder_pattern::Builder;
332//! #[derive(Builder)]
333//! struct Test {
334//! #[validator(is_not_empty)]
335//! #[setter(lazy, async)]
336//! pub name: &'static str,
337//! }
338//! # fn is_not_empty(name: &'static str) -> Result<&'static str, &'static str> {
339//! # if name.is_empty() {
340//! # Err("Name cannot be empty.")
341//! # } else {
342//! # Ok(name)
343//! # }
344//! # }
345//! #
346//!
347//! let test1 = Test::new() // TestBuilder<(), ...>
348//! .name_lazy(|| "Hello") // TestBuilder<String, ...>
349//! .build() // Ok(Test)
350//! .unwrap(); // Test
351//!
352//! # tokio_test::block_on(async {
353//! let test2 = Test::new() // TestBuilder<(), ...>
354//! .name_async(|| async { "Hello" }) // TestBuilder<String, ...>
355//! .build() // Future<Result<Test, String>>
356//! .await // Ok(Test)
357//! .unwrap(); // Test
358//! # });
359//! ```
360//!
361//! ## Auto-Generated Documentation
362//!
363//! This crate generates documentation for the builder functions. If you document fields,
364//! the builder functions for them also copy the documentation.
365//!
366//! ### Example
367//!
368//! Example code:
369//!
370//! ```
371//! # use builder_pattern::Builder;
372//! #[derive(Builder)]
373//! struct Test {
374//! /// A positive integer.
375//! pub positive: i32,
376//!
377//! /// An integer having zero as a default value.
378//! #[default(0)]
379//! pub zero: i32,
380//! }
381//! ```
382//!
383//! Generated code:
384//!
385//! ```
386//! # use core::marker::PhantomData;
387//! # use builder_pattern::setter::*;
388//! # struct Test {
389//! # pub positive: i32,
390//! # pub zero: i32,
391//! # }
392//! impl Test {
393//! /// Creating a builder.
394//! /// ## Required fields
395//! /// ### `positive`
396//! /// - Type: `i32`
397//! ///
398//! /// A positive integer.
399//! ///
400//! /// ## Optional fields
401//! /// ### `zero`
402//! /// - Type: `i32`
403//! /// - Default: `0`
404//! ///
405//! /// An integer having zero as a default value.
406//! fn new<'a>() -> TestBuilder<'a, (), (), (), ()> {
407//! TestBuilder {
408//! _phantom: PhantomData,
409//! positive: None,
410//! zero: Some(Setter::Value(0)),
411//! }
412//! }
413//! }
414//!
415//! /// A builder for `Test`.
416//! struct TestBuilder<
417//! 'a,
418//! T1,
419//! T2,
420//! AsyncFieldMarker,
421//! ValidatorOption,
422//! > {
423//! _phantom: PhantomData<(
424//! T1,
425//! T2,
426//! AsyncFieldMarker,
427//! ValidatorOption,
428//! )>,
429//! positive: Option<Setter<'a, i32>>,
430//! zero: Option<Setter<'a, i32>>,
431//! }
432//!
433//! impl<'a, T2, AsyncFieldMarker, ValidatorOption>
434//! TestBuilder<'a, (), T2, AsyncFieldMarker, ValidatorOption>
435//! {
436//! /// # positive
437//! /// - Type: `i32`
438//! ///
439//! /// A positive integer.
440//! pub fn positive(
441//! self,
442//! value: i32
443//! ) -> TestBuilder<'a, i32, T2, AsyncFieldMarker, ValidatorOption> {
444//! TestBuilder {
445//! _phantom: PhantomData,
446//! positive: Some(Setter::Value(value)),
447//! zero: self.zero,
448//! }
449//! }
450//! }
451//!
452//! impl<'a, T1, AsyncFieldMarker, ValidatorOption>
453//! TestBuilder<'a, T1, (), AsyncFieldMarker, ValidatorOption>
454//! {
455//! /// # zero
456//! /// - Type: `i32`
457//! /// - Default: `0`
458//! ///
459//! /// An integer having zero as a default value.
460//! pub fn zero(
461//! self,
462//! value: i32
463//! ) -> TestBuilder<'a, T1, i32, AsyncFieldMarker, ValidatorOption> {
464//! TestBuilder {
465//! _phantom: PhantomData,
466//! positive: self.positive,
467//! zero: Some(Setter::Value(value)),
468//! }
469//! }
470//! }
471//! ```
472//! ## How it works
473//!
474//! The following code
475//!
476//! ```
477//! # use builder_pattern::Builder;
478//! # enum Gender {
479//! # Male,
480//! # Female,
481//! # Nonbinary
482//! # }
483//! # fn is_not_empty(val: String) -> Result<String, ()> {
484//! # Ok(val)
485//! # }
486//! #[derive(Builder)]
487//! struct Person {
488//! #[into]
489//! #[validator(is_not_empty)]
490//! name: String,
491//! age: i32,
492//! #[default(Gender::Nonbinary)]
493//! gender: Gender,
494//! }
495//! ```
496//!
497//! will generates:
498//!
499//! ```
500//! # use core::marker::PhantomData;
501//! # use builder_pattern::setter::*;
502//! # enum Gender {
503//! # Male,
504//! # Female,
505//! # Nonbinary
506//! # }
507//! # fn is_not_empty(val: String) -> Result<String, ()> {
508//! # Ok(val)
509//! # }
510//! # struct Person {
511//! # name: String,
512//! # age: i32,
513//! # gender: Gender,
514//! # }
515//! impl Person {
516//! // Create an empty builder
517//! fn new<'a>() -> PersonBuilder<'a, (), (), (), (), ()> {
518//! PersonBuilder {
519//! _phantom: PhantomData,
520//! age: None,
521//! name: None,
522//! gender: Some(Setter::Value(Gender::Nonbinary)),
523//! }
524//! }
525//! }
526//! // A builder structure for `Person`.
527//! struct PersonBuilder<
528//! 'a, T1, T2, T3,
529//! AsyncFieldMarker, // A generic for checking async fields
530//! ValidatorOption, // A generic for checking lazy validators
531//! > {
532//! _phantom: PhantomData<(
533//! T1, T2, T3,
534//! AsyncFieldMarker,
535//! ValidatorOption,
536//! )>,
537//! // Fields are wrapped in `Option`s.
538//! age: Option<Setter<'a, i32>>,
539//! name: Option<Setter<'a, String>>,
540//! gender: Option<Setter<'a, Gender>>,
541//! }
542//! // Implementation for `build` function
543//! impl<'a, T3>
544//! // It can be called regardless of whether `T3` is `()` or `Gender`.
545//! PersonBuilder<'a, i32, String, T3, (), ()>
546//! {
547//! fn build(self) -> Person {
548//! let age = match self.age.unwrap() {
549//! Setter::Value(v) => v,
550//! Setter::Lazy(f) => f(),
551//! _ => unimplemented!(),
552//! };
553//! let name = match self.name.unwrap() {
554//! Setter::Value(v) => v,
555//! Setter::Lazy(f) => f(),
556//! _ => unimplemented!(),
557//! };
558//! let gender = match self.gender.unwrap() {
559//! Setter::Value(v) => v,
560//! Setter::Lazy(f) => f(),
561//! _ => unimplemented!(),
562//! };
563//! Person { age, name, gender }
564//! }
565//! }
566//! impl<'a, T2, T3, AsyncFieldMarker, ValidatorOption>
567//! PersonBuilder<
568//! 'a, (), T2, T3,
569//! AsyncFieldMarker,
570//! ValidatorOption,
571//! >
572//! {
573//! // Setter for `age`
574//! fn age(
575//! self,
576//! value: i32,
577//! ) -> PersonBuilder<
578//! 'a, i32, T2, T3,
579//! AsyncFieldMarker,
580//! ValidatorOption,
581//! > {
582//! PersonBuilder {
583//! _phantom: PhantomData,
584//! age: Some(Setter::Value(value.into())),
585//! name: self.name,
586//! gender: self.gender,
587//! }
588//! }
589//! }
590//! impl<'a, T1, T3, AsyncFieldMarker, ValidatorOption>
591//! PersonBuilder<
592//! 'a, T1, (), T3,
593//! AsyncFieldMarker,
594//! ValidatorOption,
595//! >
596//! {
597//! // Setter for `name`
598//! fn name<IntoType: Into<String>>(
599//! self,
600//! value: IntoType,
601//! ) -> Result<
602//! PersonBuilder<
603//! 'a, T1, String, T3,
604//! AsyncFieldMarker,
605//! ValidatorOption,
606//! >,
607//! String,
608//! > {
609//! // Validate the value
610//! match is_not_empty(value.into()) {
611//! Ok(value) => Ok(PersonBuilder {
612//! _phantom: PhantomData,
613//! age: self.age,
614//! name: Some(Setter::Value(value)),
615//! gender: self.gender,
616//! }),
617//! Err(e) => Err(format!("Validation failed: {:?}", e)),
618//! }
619//! }
620//! }
621//! impl<'a, T1, T2, AsyncFieldMarker, ValidatorOption>
622//! PersonBuilder<
623//! 'a, T1, T2, (),
624//! AsyncFieldMarker,
625//! ValidatorOption,
626//! >
627//! {
628//! // Setter for `gender`
629//! fn gender(
630//! self,
631//! value: Gender,
632//! ) -> PersonBuilder<
633//! 'a, T1, T2, Gender,
634//! AsyncFieldMarker,
635//! ValidatorOption,
636//! > {
637//! PersonBuilder {
638//! _phantom: PhantomData,
639//! age: self.age,
640//! name: self.name,
641//! gender: Some(Setter::Value(value.into())),
642//! }
643//! }
644//! }
645//! ```
646
647pub use builder_pattern_macro::Builder;
648
649#[doc(hidden)]
650pub mod setter;