| Crates.io | derive_builder |
| lib.rs | derive_builder |
| version | 0.20.2 |
| created_at | 2016-08-07 20:28:43.953501+00 |
| updated_at | 2024-10-08 16:55:17.031148+00 |
| description | Rust macro to automatically implement the builder pattern for arbitrary structs. |
| homepage | |
| repository | https://github.com/colin-kiegel/rust-derive-builder |
| max_upload_size | |
| id | 5918 |
| size | 139,342 |
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.
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.
It's as simple as three steps:
derive_builder to your Cargo.toml either manually or
with cargo-edit:cargo add derive_builderuse derive_builder::Builder;#[derive(Builder)]&mut self by default.#[builder(pattern = "owned")] or #[builder(pattern = "immutable")].#[cfg(...)] and #[allow(...)] attributes are also applied to the setter methods.#[builder(setter(skip))] on each field individually.#[builder(private)].#[builder(setter(into))], setter methods will be generic over the input types – you can then supply every argument that implements the Into trait for the field type.#[builder(setter(strip_option))], setter methods will take T as parameter'type for field of type Option<T>.#[builder(setter(each(name = "method_name")))] to fields whose types implement Default and Extend will generate a setter which adds items to the builder collection for that field. It's possible for these setters to be generic over the Into<T> trait too, like so: #[builder(setter(each(name = "foo", into)))].#[builder(field(private))] or ..(public), to set field visibility of your builder.VALUE, if you also activate setter type conversions.#[builder(default)] to delegate to the Default implementation or any explicit value via = "..". This works both on the struct and field level.#[builder(build_fn(validate = "path::to::fn"))] to add your own validation before the target struct is generated.#[builder(build_fn(skip))] to disable auto-implementation of the build method and provide your own.#[builder(build_fn(error = "path::to::Error"))] to have your builder return an error type of your choosing. By default, the macro will emit an error type alongside the builder.#[builder(derive(Trait1, Trait2, ...))] to have the builder derive additonal traits. All builders derive Default and Clone, so you should not declare those in this attribute.#[builder_struct_attr(...)], #[builder_impl_attr(...)], #[builder_field_attr(...)], and #[builder_setter_attr(...)] to declare attributes that will be added to the relevant part of the generated builder.#[builder(no_std)] to your struct, use feature alloc, and add extern crate alloc to your crate.alloc feature and then either add #[builder(no_std, build_fn(error(validation_error = false)))] or #[builder(no_std, build_fn(error = "path::to::Error"))] to your struct.#[builder(crate = "...")] to set the root for derive_builder. This is useful if you want to rename derive_builder in Cargo.toml or if your crate is re-exporting derive_builder::Builder and needs the generated code to not directly reference the derive_builder crate.For more information and examples please take a look at our documentation.
VALUE as a generic parameter as this is what all setters are using.Detailed explaination of all features and tips for troubleshooting. You'll also find a discussion of different builder patterns.
Yes, we keep a changelog.
Licensed under either of
at your option.
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.