1 个不稳定版本
使用旧的 Rust 2015
0.11.2 | 2022 年 5 月 6 日 |
---|
#1244 在 Rust 模式
8,826 每月下载次数
用于 34 个 crate(17 直接使用)
43KB
74 行
Builder 模式派生
Rust 宏,用于自动为任意结构体实现 builder 模式。一个简单的 #[derive(Builder)]
会为你的结构体 Foo
生成一个 FooBuilder
,包含所有 setter 方法和一个 build 方法。
这是一个分支版本
此版本的 derive_builder
有一个额外的 sub_builder
功能,该功能 尚未被上游接受。我们可能会添加更多额外的功能。
在其他方面,这个分支可能落后于上游 crate。
它如何工作
#[macro_use]
extern crate derive_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);
}
注意,我们没有编写任何关于 ChannelBuilder
的定义或实现。相反,derive_builder
crate 在编译时根据 #[derive(Builder)]
生成必要的代码。
这是你不需要编写的自动生成的样板代码。:-)
#[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"),
),
)
}
},
})
}
}
注意:本文档为便于阅读而进行了编辑。生成的代码不假设如 Into
这样的特性在作用域内,并且使用完整路径来访问它们。
开始使用
只需三个步骤即可完成
- 将
derive_builder
添加到您的Cargo.toml
文件中,可以是手动添加或者使用 cargo-edit
cargoadd derive_builder
- 添加
use derive_builder::Builder;
- 使用
#[derive(Builder)]
注释您的结构体
用法和特性
- 链式调用:默认情况下,设置器调用可以链式调用,因为它们会消耗并返回
&mut self
。 - 构建器模式:您可以通过在结构体(或字段)前加上
#[builder(pattern = "owned")]
或#[builder(pattern = "immutable")]
来选择其他构建器模式。 - 可扩展性:您仍然可以定义自己的构建器结构体实现并定义额外的方法。只需确保它们的名称与设置器和构建方法不同即可。
- 文档和属性:可以通过注释相应的字段来注释设置器方法。同样,
#[cfg(...)]
和#[allow(...)]
属性也应用于设置器方法。 - 隐藏字段:您可以通过在各个字段上使用
#[builder(setter(skip))]
跳过设置器。 - 设置器可见性:您可以通过在结构体前加上
#[builder(private)]
来选择私有设置器。 - 设置器类型转换:使用
#[builder(setter(into))]
,设置器方法将对输入类型进行泛型处理 - 您可以为字段类型提供实现了Into
特性的每个参数。 - 设置器剥离选项:使用
#[builder(setter(strip_option))]
,设置器方法将以T
作为参数类型来处理Option<T>
类型的字段。 - 集合设置器:将
#[builder(setter(each(name = "method_name")))]
添加到实现了Default
和Extend
的字段类型,将为该字段生成一个设置器,该设置器将项目添加到该字段的构建器集合中。这些设置器也可以对这些Into<T>
特性进行泛型处理,如下所示:#[builder(setter(each(name = "foo", into)))]
。 - 构建器字段可见性:您可以使用
#[builder(field(private))]
或..(public)
,来设置您的构建器字段的可见性。 - 泛型结构体:也受到支持,但如果您还启用了设置器类型转换,则 不能 使用名为
VALUE
的类型参数。 - 默认值:您可以使用
#[builder(default)]
来委托给Default
实现或通过= ".."
使用任何显式值。这在结构体和字段级别都适用。 - 预构建验证:您可以使用
#[builder(build_fn(validate = "path::to::fn"))]
在目标结构体生成之前添加您自己的验证。 - 抑制构建方法:您可以使用
#[builder(build_fn(skip))]
来禁用自动实现的构建方法并自行提供。 - 自定义构建方法错误类型:您可以使用
#[builder(build_fn(error = "path::to::Error"))]
让构建器返回您选择的错误类型。默认情况下,宏将在构建器旁边发出错误类型。 - 构建器推导:您可以使用
#[builder(derive(Trait1, Trait2, ...))]
来让构建器添加额外的特性。所有构建器都推导Default
和Clone
特性,因此您不应在此属性中声明这些。 - 透传属性:使用
#[builder_struct_attr(...)]
、#[builder_impl_attr(...)]
、#[builder_field_attr(...)]
和#[builder_setter_attr(...)]
来声明将被添加到生成的构建器相关部分的属性。 - no_std 支持:只需在你的结构体中添加
#[builder(no_std)]
,并在你的 crate 中添加extern crate alloc
。
有关更多信息示例,请参阅我们的 文档。
注意事项
- 在
Cargo.toml
中重命名derive_builder
不受支持。 - 元组和单位结构体不受支持,因为它们没有字段名称。我们无意支持它们。
- 在定义泛型结构体时,您不能使用
VALUE
作为泛型参数,因为这正是所有设置器所使用的。
文档
所有功能的详细说明和故障排除技巧。您还可以找到不同构建模式讨论。
变更日志
是的,我们保留变更日志。
许可证
根据您的选择,许可为以下之一
- Apache License,版本 2.0,(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证(LICENSE-MIT 或 http://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则您有意提交的任何贡献,根据 Apache-2.0 许可证定义,应如上所述双重许可,不附加任何额外条款或条件。
依赖关系
~2MB
~45K SLoC