typed_builder/lib.rs
1#![no_std]
2
3use core::ops::FnOnce;
4
5/// `TypedBuilder` is not a real type - deriving it will generate a `::builder()` method on your
6/// struct that will return a compile-time checked builder. Set the fields using setters with the
7/// same name as the struct's fields and call `.build()` when you are done to create your object.
8///
9/// Trying to set the same fields twice will generate a compile-time error. Trying to build without
10/// setting one of the fields will also generate a compile-time error - unless that field is marked
11/// as `#[builder(default)]`, in which case the `::default()` value of it's type will be picked. If
12/// you want to set a different default, use `#[builder(default=...)]`.
13///
14/// # Examples
15///
16/// ```
17/// use typed_builder::TypedBuilder;
18///
19/// #[derive(PartialEq, TypedBuilder)]
20/// struct Foo {
21/// // Mandatory Field:
22/// x: i32,
23///
24/// // #[builder(default)] without parameter - use the type's default
25/// // #[builder(setter(strip_option))] - wrap the setter argument with `Some(...)`
26/// #[builder(default, setter(strip_option))]
27/// y: Option<i32>,
28///
29/// // Or you can set the default
30/// #[builder(default=20)]
31/// z: i32,
32/// }
33///
34/// assert!(
35/// Foo::builder().x(1).y(2).z(3).build()
36/// == Foo { x: 1, y: Some(2), z: 3, });
37///
38/// // Change the order of construction:
39/// assert!(
40/// Foo::builder().z(1).x(2).y(3).build()
41/// == Foo { x: 2, y: Some(3), z: 1, });
42///
43/// // Optional fields are optional:
44/// assert!(
45/// Foo::builder().x(1).build()
46/// == Foo { x: 1, y: None, z: 20, });
47///
48/// // This will not compile - because we did not set x:
49/// // Foo::builder().build();
50///
51/// // This will not compile - because we set y twice:
52/// // Foo::builder().x(1).y(2).y(3);
53/// ```
54///
55/// # Customization with attributes
56///
57/// In addition to putting `#[derive(TypedBuilder)]` on a type, you can specify a `#[builder(...)]`
58/// attribute on the type, and on any fields in it.
59///
60/// On the **type**, the following values are permitted:
61///
62/// - `doc`: enable documentation of the builder type. By default, the builder type is given
63/// `#[doc(hidden)]`, so that the `builder()` method will show `FooBuilder` as its return type,
64/// but it won't be a link. If you turn this on, the builder type and its `build` method will get
65/// sane defaults. The field methods on the builder will be undocumented by default.
66///
67/// - `crate_module_path`: This is only needed when `typed_builder` is reexported from another
68/// crate - which usually happens when another macro uses it. In that case, it is the
69/// reponsibility of that macro to set the `crate_module_path` to the _unquoted_ module path from
70/// which the `typed_builder` crate can be accessed, so that the `TypedBuilder` macro will be
71/// able to access the typed declared in it.
72///
73/// Defaults to `#[builder(crate_module_path=::typed_builder)]`.
74///
75/// - The following subsections:
76/// - `builder_method(...)`: customize the builder method that creates the builder type
77/// - `builder_type(...)`: customize the builder type
78/// - `build_method(...)`: customize the final build method
79///
80/// All have the same fields:
81/// - `vis = "..."`: sets the visibility of the build method, default is `pub`
82/// - `name = ...`: sets the fn name of the build method, default is `build`
83/// - `doc = "..."` replaces the default documentation that will be generated for the
84/// `build()` method of the builder type. Setting this implies `doc`.
85///
86///
87/// - The `build_method(...)` subsection also has:
88/// - `into` or `into = ...`: change the output type of the builder. When a specific value/type
89/// is set via the assignment, this will be the output type of the builder. If no specific
90/// type is set, but `into` is specified, the return type will be generic and the user can
91/// decide which type shall be constructed. In both cases an [`Into`] conversion is required to
92/// be defined from the original type to the target type.
93///
94/// - `field_defaults(...)` is structured like the `#[builder(...)]` attribute you can put on the
95/// fields and sets default options for fields of the type. If specific field need to revert some
96/// options to the default defaults they can prepend `!` to the option they need to revert, and
97/// it would ignore the field defaults for that option in that field.
98///
99/// ```
100/// use typed_builder::TypedBuilder;
101///
102/// #[derive(TypedBuilder)]
103/// #[builder(field_defaults(default, setter(strip_option)))]
104/// struct Foo {
105/// // Defaults to None, options-stripping is performed:
106/// x: Option<i32>,
107///
108/// // Defaults to 0, option-stripping is not performed:
109/// #[builder(setter(!strip_option))]
110/// y: i32,
111///
112/// // Defaults to Some(13), option-stripping is performed:
113/// #[builder(default = Some(13))]
114/// z: Option<i32>,
115///
116/// // Accepts params `(x: f32, y: f32)`
117/// #[builder(setter(!strip_option, transform = |x: f32, y: f32| Point { x, y }))]
118/// w: Point,
119/// }
120///
121/// #[derive(Default)]
122/// struct Point { x: f32, y: f32 }
123/// ```
124///
125/// - `mutators(...)` takes functions, that can mutate fields inside of the builder.
126/// See [mutators](#mutators) for details.
127///
128/// On each **field**, the following values are permitted:
129///
130/// - `default`: make the field optional, defaulting to `Default::default()`. This requires that
131/// the field type implement `Default`. Mutually exclusive with any other form of default.
132///
133/// - `default = ...`: make the field optional, defaulting to the expression `...`.
134///
135/// - `default_code = "..."`: make the field optional, defaulting to the expression `...`. Note that
136/// you need to enclose it in quotes, which allows you to use it together with other custom
137/// derive proc-macro crates that complain about "expected literal". Note that if `...` contains
138/// a string, you can use raw string literals to avoid escaping the double quotes - e.g.
139/// `#[builder(default_code = r#""default text".to_owned()"#)]`.
140///
141/// - `via_mutators`: initialize the field when constructing the builder, useful in combination
142/// with [mutators](#mutators).
143///
144/// - `via_mutators = ...` or `via_mutators(init = ...)`: initialies the field with the expression `...`
145/// when constructing the builder, useful in combination with [mutators](#mutators).
146///
147/// - `mutators(...)` takes functions, that can mutate fields inside of the builder.
148/// Mutators specified on a field, mark this field as required, see [mutators](#mutators) for details.
149///
150/// - `setter(...)`: settings for the field setters. The following values are permitted inside:
151///
152/// - `doc = "..."`: sets the documentation for the field's setter on the builder type. This will be
153/// of no value unless you enable docs for the builder type with `#[builder(doc)]` or similar on
154/// the type.
155///
156/// - `skip`: do not define a method on the builder for this field. This requires that a default
157/// be set.
158///
159/// - `into`: automatically convert the argument of the setter method to the type of the field.
160/// Note that this conversion interferes with Rust's type inference and integer literal
161/// detection, so this may reduce ergonomics if the field type is generic or an unsigned integer.
162///
163/// - `strip_option`: for `Option<...>` fields only, this makes the setter wrap its argument with
164/// `Some(...)`, relieving the caller from having to do this. Note that with this setting on
165/// one cannot set the field to `None` with the setter - so the only way to get it to be `None`
166/// is by using `#[builder(default)]` and not calling the field's setter.
167///
168/// - `strip_option(fallback = field_opt)`: for `Option<...>` fields only. As above this
169/// still wraps the argument with `Some(...)`. The name given to the fallback method adds
170/// another method to the builder without wrapping the argument in `Some`. You can now call
171/// `field_opt(Some(...))` instead of `field(...)`.
172///
173/// The `setter(strip_option)` attribute supports several `field_defaults` features:
174///
175/// - `ignore_invalid`: Skip stripping for non-Option fields instead of causing a compile error
176/// - `fallback_prefix`: Add a prefix to every fallback method name
177/// - `fallback_suffix`: Add a suffix to every fallback method name
178///
179/// Example:
180///
181/// ```
182/// use typed_builder::TypedBuilder;
183///
184/// #[derive(TypedBuilder)]
185/// #[builder(field_defaults(setter(strip_option(
186/// ignore_invalid,
187/// fallback_prefix = "opt_",
188/// fallback_suffix = "_val"
189/// ))))]
190/// struct Foo {
191/// x: Option<i32>, // Can use .x(42) or .opt_x_val(None)
192/// y: i32, // Uses .y(42) only since it's not an Option
193/// }
194/// ```
195///
196/// - `strip_bool`: for `bool` fields only, this makes the setter receive no arguments and simply
197/// set the field's value to `true`. When used, the `default` is automatically set to `false`.
198///
199/// - `strip_bool(fallback = field_bool)`: for `bool` fields only. As above this allows passing
200/// the boolean value. The name given to the fallback method adds another method to the builder
201/// without where the bool value can be specified.
202///
203/// - `transform = |param1: Type1, param2: Type2 ...| expr`: this makes the setter accept
204/// `param1: Type1, param2: Type2 ...` instead of the field type itself. The parameters are
205/// transformed into the field type using the expression `expr`. The transformation is performed
206/// when the setter is called. `transform` can also be provided in full `fn` syntax,
207/// to allow custom lifetimes, a generic and a where clause.
208/// Example:
209/// ```rust
210/// #[builder(
211/// setter(
212/// fn transform<'a, M>(value: impl IntoValue<'a, String, M>) -> String
213/// where
214/// M: 'a,
215/// {
216/// value.into_value()
217/// },
218/// )
219/// )]
220/// ```
221///
222/// - `prefix = "..."` prepends the setter method with the specified prefix. For example, setting
223/// `prefix = "with_"` results in setters like `with_x` or `with_y`. This option is combinable
224/// with `suffix = "..."`.
225///
226/// - `suffix = "..."` appends the setter method with the specified suffix. For example, setting
227/// `suffix = "_value"` results in setters like `x_value` or `y_value`. This option is combinable
228/// with `prefix = "..."`.
229///
230/// - `mutable_during_default_resolution`: when expressions in `default = ...` field attributes
231/// are evaluated, this field will be mutable, allowing earlier-defined fields to be mutated by
232/// later-defined fields.
233/// **Warning** - Use this feature with care! If the field that mutates the previous field in
234/// its `default` expression is set via a setter, that mutation will not happen.
235///
236/// # Mutators
237/// Set fields can be mutated using mutators, these can be defind via `mutators(...)`.
238///
239/// Fields annotated with `#[builder(via_mutators)]` are always available to mutators. Additional fields,
240/// that the mutator accesses need to be delcared using `#[mutator(requires = [field1, field2, ...])]`.
241/// The mutator will only be availible to call when they are set.
242///
243/// Mutators on a field, result in them automatically making the field required, i.e., it needs to be
244/// marked as `via_mutators`, or its setter be called. Appart from that, they behave identically.
245///
246/// ```
247/// use typed_builder::TypedBuilder;
248///
249/// #[derive(PartialEq, Debug, TypedBuilder)]
250/// #[builder(mutators(
251/// // Mutator has only acces to fields marked as `via_mutators`.
252/// fn inc_a(&mut self, a: i32){
253/// self.a += a;
254/// }
255/// // Mutator has access to `x` additionally.
256/// #[mutator(requires = [x])]
257/// fn x_into_b(&mut self) {
258/// self.b.push(self.x)
259/// }
260/// ))]
261/// struct Struct {
262/// // Does not require explicit `requires = [x]`, as the field
263/// // the mutator is specifed on, is required implicitly.
264/// #[builder(mutators(
265/// fn x_into_b_field(self) {
266/// self.b.push(self.x)
267/// }
268/// ))]
269/// x: i32,
270/// #[builder(via_mutators(init = 1))]
271/// a: i32,
272/// #[builder(via_mutators)]
273/// b: Vec<i32>
274/// }
275///
276/// // Mutators do not enforce only being called once
277/// assert_eq!(
278/// Struct::builder().x(2).x_into_b().x_into_b().x_into_b_field().inc_a(2).build(),
279/// Struct {x: 2, a: 3, b: vec![2, 2, 2]});
280/// ```
281pub use typed_builder_macro::TypedBuilder;
282
283#[doc(hidden)]
284pub trait Optional<T> {
285 fn into_value<F: FnOnce() -> T>(self, default: F) -> T;
286}
287
288impl<T> Optional<T> for () {
289 fn into_value<F: FnOnce() -> T>(self, default: F) -> T {
290 default()
291 }
292}
293
294impl<T> Optional<T> for (T,) {
295 fn into_value<F: FnOnce() -> T>(self, _: F) -> T {
296 self.0
297 }
298}
299
300// It'd be nice for the compilation tests to live in tests/ with the rest, but short of pulling in
301// some other test runner for that purpose (e.g. compiletest_rs), rustdoc compile_fail in this
302// crate is all we can use.
303
304#[doc(hidden)]
305/// When a property is non-default, you can't ignore it:
306///
307/// ```compile_fail
308/// use typed_builder::TypedBuilder;
309///
310/// #[derive(TypedBuilder)]
311/// struct Foo {
312/// x: i8,
313/// }
314///
315/// let _ = Foo::builder().build();
316/// ```
317///
318/// When a property is skipped, you can't set it:
319/// (“method `y` not found for this”)
320///
321/// ```compile_fail
322/// use typed_builder::TypedBuilder;
323///
324/// #[derive(PartialEq, TypedBuilder)]
325/// struct Foo {
326/// #[builder(default, setter(skip))]
327/// y: i8,
328/// }
329///
330/// let _ = Foo::builder().y(1i8).build();
331/// ```
332///
333/// But you can build a record:
334///
335/// ```
336/// use typed_builder::TypedBuilder;
337///
338/// #[derive(PartialEq, TypedBuilder)]
339/// struct Foo {
340/// #[builder(default, setter(skip))]
341/// y: i8,
342/// }
343///
344/// let _ = Foo::builder().build();
345/// ```
346///
347/// `skip` without `default` is disallowed:
348/// (“error: #[builder(skip)] must be accompanied by default”)
349///
350/// ```compile_fail
351/// use typed_builder::TypedBuilder;
352///
353/// #[derive(PartialEq, TypedBuilder)]
354/// struct Foo {
355/// #[builder(setter(skip))]
356/// y: i8,
357/// }
358/// ```
359///
360/// `clone` does not work if non-Clone fields have already been set
361///
362/// ```compile_fail
363/// use typed_builder::TypedBuilder;
364///
365/// #[derive(Default)]
366/// struct Uncloneable;
367///
368/// #[derive(TypedBuilder)]
369/// struct Foo {
370/// x: Uncloneable,
371/// y: i32,
372/// }
373///
374/// let _ = Foo::builder().x(Uncloneable).clone();
375/// ```
376///
377/// Same, but with generics
378///
379/// ```compile_fail
380/// use typed_builder::TypedBuilder;
381///
382/// #[derive(Default)]
383/// struct Uncloneable;
384///
385/// #[derive(TypedBuilder)]
386/// struct Foo<T> {
387/// x: T,
388/// y: i32,
389/// }
390///
391/// let _ = Foo::builder().x(Uncloneable).clone();
392/// ```
393///
394/// Handling deprecated fields:
395///
396/// ```compile_fail
397/// use typed_builder::TypedBuilder;
398///
399/// #[derive(TypedBuilder)]
400/// struct Foo {
401/// #[deprecated = "Don't use this!"]
402/// #[allow(dead_code)]
403/// value: i32,
404/// }
405///
406/// #[deny(deprecated)]
407/// Foo::builder().value(42).build();
408/// ```
409///
410/// Handling invalid property for `strip_option`
411///
412/// ```compile_fail
413/// use typed_builder::TypedBuilder;
414///
415/// #[derive(TypedBuilder)]
416/// struct Foo {
417/// #[builder(setter(strip_option(invalid_field = "should_fail")))]
418/// value: Option<i32>,
419/// }
420/// ```
421///
422/// Handling multiple properties for `strip_option`
423///
424/// ```compile_fail
425/// use typed_builder::TypedBuilder;
426///
427/// #[derive(TypedBuilder)]
428/// struct Foo {
429/// #[builder(setter(strip_option(fallback = value_opt, fallback = value_opt2)))]
430/// value: Option<i32>,
431/// }
432/// ```
433///
434/// Handling alternative properties for `strip_option`
435///
436/// ```compile_fail
437/// use typed_builder::TypedBuilder;
438///
439/// #[derive(TypedBuilder)]
440/// struct Foo {
441/// #[builder(setter(strip_option(type = value_opt, fallback = value_opt2)))]
442/// value: Option<i32>,
443/// }
444/// ```
445///
446/// Handling invalid property for `strip_bool`
447///
448/// ```compile_fail
449/// use typed_builder::TypedBuilder;
450///
451/// #[derive(TypedBuilder)]
452/// struct Foo {
453/// #[builder(setter(strip_bool(invalid_field = should_fail)))]
454/// value: bool,
455/// }
456/// ```
457///
458/// Handling multiple propertes for `strip_bool`
459///
460/// ```compile_fail
461/// use typed_builder::TypedBuilder;
462///
463/// #[derive(TypedBuilder)]
464/// struct Foo {
465/// #[builder(setter(strip_bool(fallback = value_bool, fallback = value_bool2)))]
466/// value: bool,
467/// }
468/// ```
469///
470/// Handling alternative propertes for `strip_bool`
471///
472/// ```compile_fail
473/// use typed_builder::TypedBuilder;
474///
475/// #[derive(TypedBuilder)]
476/// struct Foo {
477/// #[builder(setter(strip_bool(invalid = value_bool, fallback = value_bool2)))]
478/// value: bool,
479/// }
480/// ```
481fn _compile_fail_tests() {}