This is very much a work-in-progress. PRs to bring this to production quality are welcome.
The Builder Pattern is a design pattern to allow the construction of complex types one field at a time by calling methods on a builder type. This crate provides a derive
macro that allows you to annotate any struct
to create a type-level state machine that requires all mandatory fields to be set once and only at compile-time (otherwise you won't be able to call .build()
on it).
use makeit::{Buildable, Builder};
#[derive(Builder)]
struct Foo<'a, T: std::fmt::Debug> {
bar: &'a T,
#[default(42)]
baz: i32,
}
// This is the expected use
let x = Foo::builder().set_bar(&()).set_baz(42).build();
// The following builds because of the `default` annotation on `baz`
let x = Foo::builder().set_bar(&()).build();
// The following won't build because `bar` hasn't been set
let x = Foo::builder().set_baz(0).build();
You can look at the examples
directory for a showcase of the available features.
The created Builder
type has zero-memory overhead because it uses a MaybeUninit
backed field of the type to be built.
One of the main downsides of the typestate pattern are inscrutable error messages. However, the since this crate generates type-state parameters with readable names, rustc can produce readable error messages: