derive_builder Documentation

repository·master·Indexed 23 days ago

https://github.com/colin-kiegel/rust-derive-builder

A Rust procedural macro that automatically implements the builder pattern for arbitrary structs to reduce boilerplate for complex object construction. Version 0.20.2 provides features for customizing setter behavior, builder patterns (owned, immutable, mutable), field visibility, default values, and pre-build validation. It includes support for no_std environments and allows for custom error types during the build process.

Tokens
7.1K
Snippets
13
Records
36
Agent score
80%

What's inside derive_builder

  1. Configure builder patterns and visibility

    master

    You can customize the behavior and visibility of the generated builder using struct-level attributes:

    • Builder Patterns: Change the pattern using #[builder(pattern = "owned")] or #[builder(pattern = "immutable")].
    • Private Setters: Make all setter methods private using #[builder(private)] on the struct.
    • Builder Field Visibility: Control the visibility of the fields within the builder struct using #[builder(field(private))] or #[builder(field(public))].
  2. Configure no_std and crate re-exporting

    master

    Advanced configuration for specialized environments:

    • no_std support: Add #[builder(no_std)] to your struct. If you need an allocator, use the alloc feature and add extern crate alloc to your crate. For a no_std environment without an allocator, use #[builder(no_std, build_fn(error(validation_error = false)))] or provide a custom error type via build_fn(error = "...").
    • Renaming and Re-exporting: If you have renamed the derive_builder crate in Cargo.toml or are re-exporting the Builder trait, use #[builder(crate = "...")] to set the correct root path for the macro's generated code.
  3. Configure default values and extra derivations

    master

    Use these attributes to enhance the generated builder:

    • Default Values: Use #[builder(default)] to use the type's Default implementation, or #[builder(default = "expr")] to specify an explicit value. This works at both the struct and field level.
    • Additional Derivations: Use #[builder(derive(Trait1, Trait2))] to have the generated builder derive additional traits. Note that Default and Clone are always derived automatically.
    • Pass-through Attributes: Use #[builder_struct_attr(...)], #[builder_impl_attr(...)], #[builder_field_attr(...)], and #[builder_setter_attr(...)] to pass attributes directly to the generated struct, implementation, fields, or setter methods.
  4. Customize setter behavior

    master

    Use field-level or struct-level attributes to modify how setters function:

    • Type Conversions: Use #[builder(setter(into))] to make setters generic over any type that implements Into<FieldType>.
    • Skip Setters: Use #[builder(setter(skip))] on a specific field to prevent a setter from being generated.
    • Strip Options: Use #[builder(setter(strip_option))] so that for a field of type Option<T>, the setter accepts T instead of Option<T>.
    • Collection Setters: For types implementing Default and Extend, use #[builder(setter(each(name = "method_name")))] to generate a method that adds items to the collection. You can also use into with this: #[builder(setter(each(name = "foo", into)))].
  5. Customize the build process and errors

    master

    Control how the final struct is constructed and what errors are returned:

    • Pre-build Validation: Add a custom validation function by using #[builder(build_fn(validate = "path::to::fn"))].
    • Custom Error Types: Specify a custom error type for the .build() method using #[builder(build_fn(error = "path::to::Error"))].
    • Suppress Build Method: If you want to provide your own implementation of the build method, use #[builder(build_fn(skip))] to disable the auto-generated one.
  6. Use `derive_builder` instead of `derive_builder_core`

    master

    The derive_builder_core crate is an internal helper library for derive_builder. It is primarily used to facilitate code generation techniques and break dependency cycles within the derive_builder ecosystem.

    Warning for end-users:

    • The API of derive_builder_core may change frequently and is not considered stable.
    • For most use cases, you should use the derive_builder crate instead, as it is more ergonomic and provides a stable API.
    • Only use derive_builder_core if derive_builder does not depend on your crate and you have a specific need for the underlying core logic.
  7. Install and get started with derive_builder

    master

    To use derive_builder in your Rust project, follow these three steps:

    1. Add the dependency to your Cargo.toml:
      cargo add derive_builder
    2. Import the Builder trait:
      use derive_builder::Builder;
    3. Annotate your struct with #[derive(Builder)] to automatically generate a builder struct (e.g., FooBuilder for Foo).
    cargo add derive_builder
  8. Configure the builder setter pattern with BuilderPattern

    master

    The BuilderPattern enum controls the signature of setter methods (and potentially the build() method) generated by the derive macro. It determines how self is passed to and returned from the setter functions.

    Available patterns:

    • Owned: The setter takes ownership and returns ownership. Example: fn bar(self, bar: Bar) -> Self.
    • Mutable: The setter takes a mutable reference and returns a mutable reference. Example: fn bar(&mut self, bar: Bar) -> &mut Self. This is the default pattern.
    • Immutable: The setter takes an immutable reference and returns a new instance. Example: fn bar(&self, bar: Bar) -> Self. Note that this requires the builder to be able to clone its fields to return an updated instance. In release mode, LLVM often optimizes these clone calls away.
  9. How the generated Builder struct and error type are structured

    master

    When derive_builder expands, it generates a builder struct and an associated error enum.

    Builder Struct:

    • Inherits visibility, generics, and attributes from the target struct.
    • Implements Default (if impl_default is true) by calling the inherent create_empty method.
    • Includes an inherent method (default name create_empty) that initializes all fields to None or PhantomData.
    • Can automatically derive additional traits (like Clone) via the derives configuration.

    Error Enum:

    • Named {TargetStruct}Error.
    • Contains UninitializedField(&'static str) to indicate which field was missing during .build().
    • Contains ValidationError(String) if generate_validation_error is enabled.
    • Implements std::error::Error if the std feature is enabled.
    // Conceptual expansion of a builder
    #[derive(Clone)]
    pub struct FooBuilder {
        foo: u32,
    }
    
    #[doc="Error type for FooBuilder"]
    #[derive(Debug)]
    #[non_exhaustive]
    pub enum FooBuilderError {
        /// Uninitialized field
        UninitializedField(&'static str),
        /// Custom validation error
        ValidationError(::derive_builder::export::core::string::String),
    }
    
    impl FooBuilder {
        fn create_empty() -> Self {
            Self { foo: Default::default() }
        }
    }
    
    impl Default for FooBuilder {
        fn default() -> Self {
            Self::create_empty()
        }
    }
  10. Use the `derive_builder` crate instead of `derive_builder_core`

    master

    The derive_builder_core crate is an internal helper library designed to decouple builder creation logic from the procedural macro entry point. It is not intended for direct end-user consumption.

    If you want to use the builder pattern derivation in your Rust projects, you should use the [derive_builder] crate, which provides a much more ergonomic interface.

  11. FieldConversion strategies for builder fields

    master

    When generating the build() method, you can control how the builder's internal Option<T> is converted into the target field's type using FieldConversion:

    • OptionOrDefault: The standard behavior. It attempts to unwrap the Option or falls back to a default value/error if the field is None.
    • Move: Directly moves the value out of the builder's field. This is typically used with the Owned builder pattern.
    • Block: Allows for a custom conversion logic defined by a block of code (useful for sub-builders where you might need to call .build() on a nested builder).