#builder #macro #macro-derive #optional #parameters #constructor #optional-builder

optbuilder

一个可选构建器派生宏,帮助处理具有大量可选参数的大构造函数

3 个版本

0.1.2 2020年9月1日
0.1.1 2019年7月16日
0.1.0 2019年7月16日

622过程宏

MIT 许可证

10KB
118 代码行

Optbuilder

Build Status codecov

这个 crate 是在我实现 Telegram API 包装器时由于懒惰而诞生的。API 的许多方法都需要大多数为可选参数,这让我陷入了一种需要编写如下代码的情况

struct Foo {
    name: String,
    age: u32,
    address: Option<String>,
    job: Option<String>,
    pet_name: Option<String>
}

impl Foo {
    fn with_address(self, addr: String) -> self {
        self.address = Some(addr);
    }

    fn with_job(self, job: String) -> self {
        self.job = Some(job);
    }

    fn with_pet_name(self, pet_name: String) -> self {
        self.pet_name = Some(pet_name);
    }
}

而不是实现所有注入地址、职位和 pet_name 的方法,为此创建了一个宏来处理这种情况

extern crate optbuilder;
use optbuilder::OptionalBuilder;

#[derive(OptionalBuilder)]
struct Foo {
    name: String,
    age: u32,
    address: Option<String>,
    // We don't want to codegen job for some reason
    #[optbuilder(skip)]
    job: Option<String>,
    pet_name: Option<String>
}

如何使用它?

将以下行添加到您的 Cargo.toml 中

[dependencies]
optbuilder = "0.1.1"

为什么不使用构建器 crate?

基本上是因为我经常有一个默认实现,它将选项类型转换为 None

问题

由于在 crate 中广泛使用了 From 特性,编译器可能会对类型和错误进行投诉,这种情况可能会发生

use optbuilder::OptionalBuilder;

#[derive(Debug, Default, OptionalBuilder)]
struct Foo {
    name: String,
    id: Option<i32>,
    uid: Option<u32>,
}

fn main() {
    let f = Foo::default().with_id(2).with_uid(3);

    println!("{:?}", f);
}

error[E0277]: the trait bound `u32: std::convert::From<i32>` is not satisfied
  --> src/main.rs:11:39
   |
11 |     let f = Foo::default().with_id(2).with_uid(3);
   |                                       ^^^^^^^^ the trait `std::convert::From<i32>` is not implemented for `u32`

依赖项

~1.5MB
~35K SLoC