Attribute Macro staged_builder::staged_builder

source ·
#[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.
  • update - The completed stage of the builder will have setters for all fields, and a From impl will be created to allow an instance of the struct to be converted back into the builder type for further updates.
  • crate - Indicates the path to the staged_builder crate root. Useful when reexporting the macro from another crate. Defaults to ::staged_builder.
  • mod - The name of the submodule that will contain the generated builder types. Defaults to the struct’s name converted to snake_case.
  • inline - Causes the generated builder types to be defined in the same module as the struct, rather than a submodule.
  • builder - Sets the name of the generated builder type. Defaults to Builder.
  • complete - Sets the name of the generated complete stage type. Defaults to Complete.

§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)))].
  • stage- Sets the name of the generated stage type. Defaults to the name of the field converted to PascalCase with Stage appended.

§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::Builder<my_struct::RequiredFieldStage> {
        // ...
    }
}

pub mod my_struct {
    pub struct Builder<T> {
        // ...
    }

    impl Default for Builder<RequiredFieldStage> {
        fn default() -> Self {
            // ...
        }
    }

    impl Builder<RequiredFieldStage> {
        pub fn required_field(self, required_field: u32) -> Builder<IntoRequiredFieldStage> {
            // ...
        }
    }

    impl Builder<IntoRequiredFieldStage> {
        pub fn into_required_field(self, into_required_field: impl Into<String>) -> Builder<FinalStage> {
            // ...
        }
    }

    impl Builder<FinalStage> {
        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 {
            // ...
        }
    }

    pub struct RequiredFieldStage {
        // ...
    }

    pub struct IntoRequiredFieldStage {
        // ...
    }

    pub struct FinalStage {
        // ...
    }
}