#builder

macro typed-builder

Compile-time type-checked builder derive

3 unstable releases

0.1.1 Jul 25, 2018
0.1.0 Oct 5, 2017
0.0.0 Oct 4, 2017

#73 in Rust patterns

Download history 17/week @ 2018-08-22 12/week @ 2018-08-29 99/week @ 2018-09-05 14/week @ 2018-09-12 22/week @ 2018-09-19 8/week @ 2018-09-26 222/week @ 2018-10-03 63/week @ 2018-10-10 115/week @ 2018-10-17 95/week @ 2018-10-24 31/week @ 2018-10-31 62/week @ 2018-11-07 9/week @ 2018-11-14

454 downloads per month
Used in 1 crate

MIT license

21KB
337 lines

Build Status Latest Version Rust Documentation

Rust Typed Builder

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

Features

  • 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.

Limitations

  • 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.

Alternatives - and why typed-builder is better

  • 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.

Dependencies

~1MB
~22K SLoC