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;