Derive Macro boulder::Buildable

source · []
#[derive(Buildable)]
{
    // Attributes available to this derive:
    #[boulder]
}
Expand description

Derive the Buildable trait for a type, creating a suitable Builder.

This is only implemented for structs with named fields; there is no implementation for either enums or structs with unnamed fields. All fields will be default constructed in the absence of other instructions. You can customise the construction process for your type by using the boulder attribute on its fields, as follows:

  • #[boulder(default=Foo)] The default value for this field is Foo, where an arbitrary well-formed Rust expression can be used in place of Foo.

  • #[boulder(buildable)] The type for this field implements Buildable itself, so new values should be constructed using T::builder().build().

  • #[boulder(buildable(a=5, b=10))] The type for this field implements Buildable, and new instances should be customised from the default by setting a=5 and b=10 where a and b are member names, and 5 and 10 can be replaced by arbitrary well-formed Rust expressions.

  • #[boulder(sequence=3)] This field is assumed to be a collection type (a type which can be the target of collect()). Generate 3 items and initialize a new collection from them, where 3 can be replaced by an arbitrary well-formed Rust expression. The generation mechanism will be taken from any generator specification (generator or generatable) if one is given; otherwise it will be from the builder specification (default or buildable, as described above) if one is given; otherwise the items will be default initialized.

Example:

use boulder::{Buildable, Generatable, Builder};

#[derive(Buildable)]
struct Foo {
  // This field will be default-initialized (a=0)
  a: i32,
  // This field will be initialized from the expression (b=5)
  #[boulder(default=6-1)]
  b: i32,
}

#[derive(Buildable)]
struct Bar {
  // This field will be initialized as Foo::builder().build()
  #[boulder(buildable)]
  f1: Foo,
  // This field will be initialized as Foo::builder().a(1).build()
  #[boulder(buildable(a=1))]
  f2: Foo,
  // This field will be initialized with two copies of Foo::builder().build()
  #[boulder(buildable, sequence=2)]
  f3: Vec<Foo>,
  // This field will be initialized with one zero
  #[boulder(sequence=1)]
  ary: Vec<i32>,
}

let foo = Foo::builder().build();
assert_eq!(foo.a, 0);
assert_eq!(foo.b, 5);
let bar = Bar::builder().build();
assert_eq!(bar.f1.a, 0);
assert_eq!(bar.f1.b, 5);
assert_eq!(bar.f2.a, 1);
assert_eq!(bar.f2.b, 5);
assert_eq!(bar.f3.len(), 2);
assert_eq!(bar.f3[0].a, 0);
assert_eq!(bar.f3[0].b, 5);
assert_eq!(bar.f3[1].a, 0);
assert_eq!(bar.f3[1].b, 5);
assert_eq!(bar.ary.len(), 1);
assert_eq!(bar.ary[0], 0);