colin-kiegel / rust-derive-builder

derive builder implementation for rust structs
https://colin-kiegel.github.io/rust-derive-builder/
Apache License 2.0
1.28k stars 82 forks source link
builder-pattern macros rust setter-methods

Build [Rust version]() Documentation Latest version All downloads Downloads of latest version

Builder Pattern Derive

Rust macro to automatically implement the builder pattern for arbitrary structs. A simple #[derive(Builder)] will generate a FooBuilder for your struct Foo with all setter-methods and a build method.

How it Works

use derive_builder::Builder;

#[derive(Default, Builder, Debug)]
#[builder(setter(into))]
struct Channel {
    token: i32,
    special_info: i32,
    // .. a whole bunch of other fields ..
}

fn main() {
    // builder pattern, go, go, go!...
    let ch = ChannelBuilder::default()
        .special_info(42u8)
        .token(19124)
        .build()
        .unwrap();
    println!("{:?}", ch);
}

Note that we did not write any definition or implementation of ChannelBuilder. Instead the derive_builder crate acts on #[derive(Builder)] and generates the necessary code at compile time.

This is the generated boilerplate code you didn't need to write. :-)

#[derive(Clone, Default)]
struct ChannelBuilder {
    token: Option<i32>,
    special_info: Option<i32>,
}

#[allow(dead_code)]
impl ChannelBuilder {
    pub fn token<VALUE: Into<i32>>(&mut self, value: VALUE) -> &mut Self {
        let mut new = self;
        new.token = Some(value.into());
        new
    }
    pub fn special_info<VALUE: Into<i32>>(&mut self, value: VALUE) -> &mut Self {
        let mut new = self;
        new.special_info = Some(value.into());
        new
    }
    fn build(
        &self,
    ) -> Result<Channel, ChannelBuilderError> {
        Ok(Channel {
            id: match self.id {
                Some(ref value) => Clone::clone(value),
                None => {
                    return Err(
                        Into::into(
                            ::derive_builder::UninitializedFieldError::from("id"),
                        ),
                    )
                }
            },
            token: match self.token {
                Some(ref value) => Clone::clone(value),
                None => {
                    return Err(
                        Into::into(
                            ::derive_builder::UninitializedFieldError::from("token"),
                        ),
                    )
                }
            },
            special_info: match self.special_info {
                Some(ref value) => Clone::clone(value),
                None => {
                    return Err(
                        Into::into(
                            ::derive_builder::UninitializedFieldError::from("special_info"),
                        ),
                    )
                }
            },
        })
    }
}

Note: This is edited for readability. The generated code doesn't assume traits such as Into are in-scope, and uses full paths to access them.

Get Started

It's as simple as three steps:

  1. Add derive_builder to your Cargo.toml either manually or with cargo-edit:
  1. Add use derive_builder::Builder;
  2. Annotate your struct with #[derive(Builder)]

Usage and Features

For more information and examples please take a look at our documentation.

Gotchas

Documentation

Detailed explaination of all features and tips for troubleshooting. You'll also find a discussion of different builder patterns.

Changelog

Yes, we keep a changelog.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.