Creates a compile-time verified builder:
#[macro_use]
extern crate typed_builder;
#[derive(TypedBuilder)]
struct Foo {
// Mandatory Field:
x: i32,
// #[default] without parameter - use the type's default
#[default]
y: Option<i32>,
// Or you can set the default(encoded as string)
#[default="20"]
z: i32,
}
Build in any order:
Foo::builder().x(1).y(2).z(3).build();
Foo::builder().z(1).x(2).y(3).build();
Omit optional fields(the one marked with #[default]
):
Foo::builder().x(1).build()
But you can't omit non-optional arguments - or it won't compile:
Foo::builder().build(); // missing x
Foo::builder().x(1).y(2).y(3); // y is specified twice
- Custom derive for generating the builder pattern.
- All setters are accepting
Into
values. - Compile time verification that all fields are set before calling
.build()
. - Compile time verification that no field is set more than once.
- Ability to annotate fields with
#[default]
to make them optional and specify a default value when the user does not set them. - Generates simple documentation for the
.builder()
method.
- No custom build error - if you neglect to set a field or set a field twice you'll get regular
no method
error that doesn't tell you what you did wrong.- If there is a way to generate proper errors I'll gladly implement it.
- The generated builder type has ugly internal name and many generic parameters. It is not meant for passing around and doing fancy builder tricks - only for nicer object creation syntax(constructor with named arguments and optional arguments).
- For the that reason, all builder methods are call-by-move and the builder is not cloneable. Saves the trouble of determining if the fields are cloneable...
- If you want a builder you can pass around, check out derive-builder. It's API does not conflict with typed-builder's so you can be able to implement them both on the same type.
- derive-builder - does all the checks in runtime, returning a
Result
you need to unwrap. - safe-builder-derive - this one does compile-time checks - by generating a type for each possible state of the builder. Rust can remove the dead code, but your build time will still be exponential. typed-builder is encoding the builder's state in the generics arguments - so Rust will only generate the path you actually use.