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