7 个版本
| 0.1.6 | 2023 年 1 月 30 日 | 
|---|---|
| 0.1.5 | 2023 年 1 月 29 日 | 
| 0.1.2 | 2022 年 12 月 26 日 | 
#62 在 #crates
38 每月下载量
在 engineer 中使用
24KB
428 行
Engineer
Engineer 是基于 Optional 的大师级构建者。
它仅生成一个用于数据模型的 Engineer (Builder) 类。
安装
将以下内容添加为依赖项
[dependencies]
engineer = "0.1.3"
入门
use engineer::Engineer;
#[derive(Engineer)]
struct Identity {
    id: usize,
    username: String,
    first_name: Option<String>,
    last_name: Option<String>,
    lang_code: Option<String>,
}
可选字段在初始化期间不是必需的。
// Option fields are set to None.
let identity = Identity::engineer(0, "immmdreza".to_string()).done();
但是,您也可以为 Option 字段设置一个值。
let identity = Identity::engineer(0, "immmdreza".to_string()) // IdentityEngineer
    .first_name("Arash".to_string()) // IdentityEngineer
    .last_name("Tofani".to_string()) // IdentityEngineer
    .done(); // Identity
这就是基础知识,但是您可以进行一些自定义。
自定义
Engineer 结构名称
默认情况下,Engineer 结构名为 {struct}Engineer(《IdentityEngineer》对于《Identity》),但您可以更改它。
// ~~~ sniff ~~~
#[derive(Engineer)]
#[engineer(engineer_name = "IdentityBuilder")]
struct Identity {
    // ~~~ sniff ~~~
}
// ~~~ sniff ~~~
    let identity = Identity::engineer(0, "immmdreza".to_string()) // IdentityBuilder
        .first_name("Arash".to_string()) // IdentityBuilder
        .last_name("Tofani".to_string()) // IdentityBuilder
        .done(); // Identity
Builder 函数名称
默认情况下,builder 函数的名称为 engineer,但您知道吗?
// ~~~ sniff ~~~
#[derive(Engineer)]
#[engineer(builder_func = "builder")]
struct Identity {
    // ~~~ sniff ~~~
}
// ~~~ sniff ~~~
    let identity = Identity::builder(0, "immmdreza".to_string())
    // ~~~ sniff ~~~
您想将其用作 new 函数
// ~~~ sniff ~~~
#[derive(Engineer)]
#[engineer(builder_func = "new")]
struct Identity {
    // ~~~ sniff ~~~
}
// ~~~ sniff ~~~
    let identity = Identity::new(0, "immmdreza".to_string())
    // ~~~ sniff ~~~
这可以简化为特殊的 new 名称作为 builder 函数
#[derive(Engineer)]
#[engineer(new)]
struct Identity {
    // ~~~ sniff ~~~
}
Options 的默认值
您可以设置选项字段的默认值。
如果没有设置其他值,将使用此值。
// ~~~ sniff ~~~
#[derive(Engineer)]
#[engineer(new)]
struct Identity {
    // ~~~ sniff ~~~
    #[engineer(default_value = r#"String::from("fa")"#)]
    lang_code: Option<String>,
}
// ~~~ sniff ~~~
    let identity = Identity::new(0, "immmdreza".to_string());
    identity.lang_code // Some("fa")
或者,您可以使用 default 来设置 Some(Default::default) 替代 None,如果未提供其他值。
    // ~~~ sniff ~~~
    #[engineer(default)]
    luck_number: Option<i32>, // Some(0)
    // ~~~ sniff ~~~
重打字
您可以更改构建过程中请求的类型。
// ~~~ sniff ~~~
#[derive(Engineer)]
#[engineer(new)]
struct Identity {
    // ~~~ sniff ~~~
    #[engineer(retype(to = "impl Into<String>", re = ".into()"))]
    //                      ^                         ^
    //                      | Requested type in public.
    //                                                |
    //                                                | How we recover to original type.
    username: String,
    // ~~~ sniff ~~~
}
// ~~~ sniff ~~~
    let identity = Identity::new(0, "immmdreza"); // .to_string() is not needed.
    // ~~~ sniff ~~~
或者,对于 str 重打字(如上面的示例),您可以使用缩写 str_retype。
    // ~~~ sniff ~~~
    #[engineer(str_retype)]
    username: String,
    // ~~~ sniff ~~~
您还可以在全局范围内使用重打字。
#[derive(Engineer)]
#[engineer(new, retype(from = "String", to = "impl Into<String>", re = ".into()"))]
struct Identity {
    // ~~~ sniff ~~~
}
或者,对于 String 重打字
#[derive(Engineer)]
#[engineer(new, str_retype)]
struct Identity {
    // ~~~ sniff ~~~
}
上述两种代码都将 全部 String 字段重打字为公开 API 中的 impl Into<String>
最终结果
#[derive(Engineer)]
#[engineer(new, str_retype)]
struct Identity {
    id: usize,
    username: String,
    first_name: String,
    last_name: Option<String>,
    #[engineer(str_retype, default_value = "\"fa\".to_string()")]
    lang_code: Option<String>,
}
fn print_identity(ident: impl Into<Identity>) {
    let ident: Identity = ident.into();
    println!("{ident:#?}");
}
fn main() {
    let ident = Identity::new(1, "immmdreza", "Arash").last_name("Tofani");
    print_identity(ident);
    // Identity {
    //     id: 1,
    //     username: "immmdreza",
    //     first_name: "Arash",
    //     last_name: Some(
    //         "Tofani",
    //     ),
    //     lang_code: Some(
    //         "fa",
    //     ),
    // }
}
更多关于特质的介绍
这个crate有两个主要特性: Builder<T> where T: Engineer 和 Engineer。
Engineer 特性有两个关联类型: Params 和 Builder。
- Params是一个包含所需字段类型的元组(不是- Option<_>的字段)
- Builder是Builder/Engineer类的类型。
使用 Engineer 宏,可以让您的数据类实现 Engineer 特性,并创建一个实现 Builder<T> 的Builder结构体(通常命名为 {struct_name}Engineer - 我正在考虑重命名),其中T是您的自己的结构体。
这使您可以在这些特性周围做一些泛型操作,例如
fn build_any<E>(required: E::Params) -> E
where
    E: Engineer,
{
    E::build(required)
}
// Or
fn get_builder<E>(required: E::Params) -> E::Builder
where
    E: Engineer,
{
    E::builder(required)
}
注意,E::Params 是一个元组。
如果所有所需字段(E::Param)都实现了Default,另一个函数 build_default 将在您的结构体上可用,该函数创建一个不需要输入的默认实例。
此外,Engineer 特性有两个常量字段
- const NORMAL_FIELDS: usize;
- const OPTIONAL_FIELDS: usize;
🧀
依赖
~2MB
~42K SLoC