๐Ÿ“ฆ estebank / makeit

Zero-overhead type-safe builder pattern `derive` macro for your Rust structs

โ˜… 221 stars โ‘‚ 9 forks ๐Ÿ‘ 221 watching
๐Ÿ“ฅ Clone https://github.com/estebank/makeit.git
HTTPS git clone https://github.com/estebank/makeit.git
SSH git clone git@github.com:estebank/makeit.git
CLI gh repo clone estebank/makeit
Ari Seyhun Ari Seyhun Fix `r#` fields not working (#14) 5fb4e57 3 years ago ๐Ÿ“ History
๐Ÿ“‚ main View all commits โ†’
๐Ÿ“ makeit
๐Ÿ“ makeit-derive
๐Ÿ“„ .gitignore
๐Ÿ“„ Cargo.toml
๐Ÿ“„ README.md
๐Ÿ“„ README.md

Compile-time checked Builder pattern derive macro with zero-memory overhead

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.

Error messages

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: Screenshot of rustc error messages, showing how the compiler tells you when you have an unset or double-set field