#builder-pattern #macro-derive #derive-builder #annotated #m4cro

builder_m4cro

实现建造者模式的简单派生宏

5个版本 (3个重大更改)

0.4.0 2024年7月1日
0.3.1 2024年5月3日
0.3.0 2024年5月3日
0.2.0 2024年4月21日
0.1.0 2024年1月27日

#868 in 过程宏

Download history 47/week @ 2024-04-15 128/week @ 2024-04-22 266/week @ 2024-04-29 15/week @ 2024-05-06 8/week @ 2024-05-20 5/week @ 2024-06-03 5/week @ 2024-06-10 236/week @ 2024-07-01 4/week @ 2024-07-08

每月240次下载
用于 tquest

MIT/Apache

18KB
317

ci crates.io

这是一个crate,提供了两个简单的宏

  • Builder - 工厂模式的实现
  • BuilderFromDefault - 依赖于Default特质的实现,以提供定制初始化值

更多示例请参阅

  • Builder: examples/builder/src/main.rs
  • BuilderFromDefault: examples/builder_from_default/src/main.rs
use builder_m4cro::Builder;

/// Custom type that's annotated with the Builder macro
#[derive(Builder, Debug)]
pub struct TestType {
    pub a_unsigned: u32,
    pub a_opt_unsigned: Option<u32>,
    pub a_string: String,
    pub a_opt_string: Option<String>,
}

/// The macro expandes to the following code
impl TestType {
    pub fn builder() -> TestTypeBuilder {
        TestTypeBuilder::new()
    }
}
pub struct TestTypeBuilder {
    a_unsigned: Option<u32>,
    a_string: Option<String>,
    a_opt_unsigned: Option<u32>,
    a_opt_string: Option<String>,
}
// ...

impl TestTypeBuilder {
    pub fn new() -> TestTypeBuilder {
        TestTypeBuilder::default()
    }
    pub fn a_unsigned(&mut self, a_unsigned: u32) -> &mut Self {
        self.a_unsigned = Some(a_unsigned);
        self
    }
    pub fn a_string(&mut self, a_string: &str) -> &mut Self {
        self.a_string = Some(a_string.to_string());
        self
    }
    pub fn a_opt_unsigned(&mut self, a_opt_unsigned: u32) -> &mut Self {
        self.a_opt_unsigned = Some(a_opt_unsigned);
        self
    }
    pub fn a_opt_string(&mut self, a_opt_string: &str) -> &mut Self {
        self.a_opt_string = Some(a_opt_string.to_string());
        self
    }
    pub fn build(&self) -> Result<TestType, String> {
        Ok(TestType {
            a_unsigned: self
                .a_unsigned
                .clone()
                .ok_or_else(|| {
                    let res = ::alloc::fmt::format(
                        format_args!("{0} is not set", "a_unsigned"),
                    );
                    res
                })?,
            a_string: self
                .a_string
                .clone()
                .ok_or_else(|| {
                    let res = ::alloc::fmt::format(
                        format_args!("{0} is not set", "a_string"),
                    );
                    res
                })?,
            a_opt_unsigned: self.a_opt_unsigned.clone(),
            a_opt_string: self.a_opt_string.clone(),
        })
    }
}

支持宏开发的辅助工具

# Install cargo expand
# https://github.com/dtolnay/cargo-expand
cargo install cargo-expand

# e. g. ...
cd examples/result_builder
cargo expand

依赖关系

~260–700KB
~17K SLoC