#[staged_builder]
Expand description

Creates a staged builder interface for structs.

The macro will create a submodule with the snake_case version of the type’s name containing the builder types, and add a builder constructor function to the type. Each required field of the struct will correspond to a builder type named after it, with an additional “final” stage to set optional fields and construct the final value.

By default, all fields are considered required and their setters will simply take their declared type by-value. This behavior can be customized with field options.

Struct options

Options can be applied at the struct level via the #[builder(...)] attribute as a comma-separated sequence:

  • validate - The final build method will return a Result, calling the type’s Validate implementation before returning the constructed value.

Field options

Options can be applied to individual fields via the #[builder(...)] attribute as a comma-separated sequence:

  • default - Causes the field to be considered optional. The Default trait is normally used to generate the default field value. A custom default can be specified with default = <expr>, where <expr> is an expression.
  • into - Causes the setter method for the field to take impl Into<FieldType> rather than FieldType directly.
  • custom - Causes the setter method to perform an arbitrary conversion for the field. The option expects a type which will be used as the argument type in the setter, and a convert callable expression which will be invoked by the setter. For example, the annotation #[builder(into)] on a field of type T is equivalent to the annotation #[builder(custom(type = impl Into<T>, convert = Into::into))].
  • list - Causes the field to be treated as a “list style” type. It will default to an empty collection, and three setter methods will be generated: push_foo to add a single value, foo to set the contents, and extend_foo to exend the collection with new values. The underlying type must have a push method, a FromIterator implementation, and an Extend implementation. The item type must be configured in the attribute: #[builder(list(item(type = YourItemType)))].
  • set - Causes the field to be treated as a “set style” type. It will default to an empty collection, and three setter methods will be generated: insert_foo to add a single value, foo to set the contents, and extend_foo to exend the collection with new values. The underlying type must have an insert method, a FromIterator implementation, and an Extend implementation. The item type must be configured in the attribute: #[builder(set(item(type = YourItemType)))].
  • map - Causes the field to be treated as a “map style” type. It will default to an empty collection, and three setter methods will be generated: insert_foo to add a single entry, foo to set the contents, and extend_foo to exend the collection with new entries. The underlying type must have an insert method, a FromIterator implementation, and an Extend implementation. The key and value types must be configured in the attribute: #[builder(map(key(type = YourKeyType), value(type = YourValueType)))].

Collection type options

Options can be applied to the item types of collections as a comma-separated sequence:

  • type - Indicates the type of the item in the collection. Required unless using custom.
  • into - Causes setter methods to take impl<Into<ItemType>> rather than ItemType directly.
  • custom - Causes the setter methods to perform an arbitrary conversion for the field.

Example expansion

use staged_builder::staged_builder;

#[staged_builder]
pub struct MyStruct {
    required_field: u32,
    #[builder(into)]
    into_required_field: String,
    #[builder(default)]
    standard_optional_field: bool,
    #[builder(default = "foobar".to_string())]
    custom_default_field: String,
    #[builder(list(item(type = i32)))]
    list_field: Vec<i32>,
}

Will expand into:

pub struct MyStruct {
    required_field: u32,
    into_required_field: String,
    standard_optional_field: bool,
    custom_default_field: String,
    list_field: Vec<i32>,
}

impl MyStruct {
    pub fn builder() -> my_struct::BuilderRequiredFieldStage {
        // ...
    }
}

pub struct my_struct {
    pub struct BuilderRequiredFieldStage {}

    impl BuilderRequiredFieldStage {
        pub fn required_field(self, required_field: u32) -> BuilderIntoRequiredFieldStage {
            // ...
        }
    }

    pub struct BuilderIntoRequiredFieldStage {
        // ...
    }

    impl BuilderIntoRequiredFieldStage {
        pub fn into_required_field(self, into_required_field: impl Into<String>) -> BuilderFinal {
            // ...
        }
    }

    pub struct BuilderFinal {
        // ...
    }

    impl BuilderFinal {
        pub fn standard_optional_field(self, standard_optional_field: bool) -> Self {
            // ...
        }

        pub fn custom_default_field(self, custom_default_field: String) -> Self {
            // ...
        }

        pub fn push_list_field(self, list_field: i32) -> Self {
            // ...
        }

        pub fn list_field(self, list_field: impl IntoIterator<Item = i32>) -> Self {
            // ...
        }

        pub fn extend_list_field(self, list_field: impl IntoIterator<Item = i32>) -> Self {
            // ...
        }

        pub fn build(self) -> super::MyStruct {
            // ...
        }
    }
}