#builder #macro-derive #setter #struct #derive #macro

no-std derive_builder

Rust 宏,用于自动为任意结构体实现构建器模式

32 个版本

0.20.0 2024年2月14日
0.13.0 2024年1月22日
0.12.0 2022年11月28日
0.11.2 2022年4月20日
0.2.1 2016年9月24日

Rust 模式 中排名 11

Download history 311795/week @ 2024-04-14 328096/week @ 2024-04-21 306986/week @ 2024-04-28 309755/week @ 2024-05-05 335091/week @ 2024-05-12 341224/week @ 2024-05-19 312285/week @ 2024-05-26 335634/week @ 2024-06-02 335300/week @ 2024-06-09 336507/week @ 2024-06-16 354057/week @ 2024-06-23 311021/week @ 2024-06-30 350494/week @ 2024-07-07 335399/week @ 2024-07-14 349381/week @ 2024-07-21 340015/week @ 2024-07-28

每月下载量 1,397,726
1,923 包(715 个直接)中使用

MIT/Apache

38KB

Build Rust version Documentation Latest version All downloads Downloads of latest version

构建器模式派生

Rust 宏,用于自动为任意结构体实现 构建器模式。一个简单的 #[derive(Builder)] 将为您生成一个 FooBuilder,其中包含所有设置方法和一个构建方法。

工作原理

#[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 包在编译时生成必要的代码,作用在 #[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 等特质在作用域中,并使用完整路径来访问它们。

开始使用

只需三个步骤即可

  1. derive_builder 添加到您的 Cargo.toml 中,手动或使用 cargo-edit
  • cargoadd derive_builder
  1. 添加 use derive_builder::Builder;
  2. 使用以下方式对结构体进行注释:#[derive(Builder)]

使用方法和功能

  • 链式调用:由于默认情况下setter调用会消耗并返回&mut self,因此setter调用可以链式调用。
  • 构建器模式:您可以通过在结构体(或字段)前添加#[builder(pattern = "owned")]#[builder(pattern = "immutable")]来选择其他构建器模式。
  • 可扩展性:您仍然可以为自己的构建器结构体定义实现并定义额外的方法。只需确保它们的名称与setter和build方法不同即可。
  • 文档和属性:可以通过简单地注释相应的字段来注释setter方法。同样,#[cfg(...)]#[allow(...)]属性也应用于setter方法。
  • 隐藏字段:您可以通过在每个字段上单独使用#[builder(setter(skip))]来跳过setter。
  • setter可见性:您可以通过在结构体前添加#[builder(private)]来选择私有setter。
  • setter类型转换:使用#[builder(setter(into))],setter方法将针对输入类型进行泛型化 - 您可以为此字段类型提供实现Into特质的每个参数。
  • 设置器条带选项:使用#[builder(setter(strip_option))],设置器方法将以T作为类型参数,为类型为Option<T>的字段。
  • 集合设置器:将#[builder(setter(each(name = "method_name")))]添加到实现DefaultExtend的字段,将为该字段生成一个设置器,该设置器会将项目添加到构建器的集合中。这些设置器还可以针对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, ...))] 来使构建器派生额外的特征。所有构建器都派生了 DefaultClone,因此您不应在此属性中声明这些。
  • 透传属性:使用 #[builder_struct_attr(...)]#[builder_impl_attr(...)]#[builder_field_attr(...)]#[builder_setter_attr(...)] 来声明将被添加到生成的构建器相关部分的属性。
  • 支持 no_std:只需在您的结构体中添加 #[builder(no_std)],使用功能 alloc,并将 extern crate alloc 添加到您的 crate 中。
  • 不支持 alloc 和 no_std:不使用 alloc 功能,然后在您的结构体中添加 #[builder(no_std, build_fn(error(validation_error = false)))]#[builder(no_std, build_fn(error = "path::to::Error"))]
  • 重命名和重新导出支持:使用 #[builder(crate = "...")] 设置 derive_builder 的根。如果您想在 Cargo.toml 中重命名 derive_builder 或您的 crate 正在重新导出 derive_builder::Builder 并且需要生成的代码不直接引用 derive_builder crate,这将非常有用。

有关更多信息示例,请参阅我们的 文档

注意事项

  • 元组结构和单元结构不支持,因为它们没有字段名。我们不打算支持它们。
  • 在定义泛型结构体时,不能将VALUE用作泛型参数,因为所有设置器都在使用它。

文档

所有功能的详细说明和故障排除技巧。您还可以找到关于不同构建模式的讨论。

变更日志

是的,我们保留变更日志。

许可

许可方式如下

任选其一。

贡献

除非您明确表示,否则您提交的任何贡献,根据Apache-2.0许可证的定义,有意包含在作品中,均将根据上述条款双重许可,不附加任何其他条款或条件。

依赖项

~0.8–1.2MB
~27K SLoC