4 个版本 (1 个稳定版本)
| 1.0.1-beta.1 | 2024年7月14日 |
|---|---|
| 1.0.1-beta.0 | 2024年4月7日 |
| 1.0.0 | 2024年2月2日 |
| 0.3.0 |
|
| 0.2.0 | 2023年12月11日 |
#343 in Rust 模式
在 translators 中使用
340KB
262 行
另一个基于构建宏的生成器,拥有自己的语法。
用法
#[macro_use] extern crate macon;
#[derive(Builder)]
struct MyType {
integer: i32,
string: String,
optional: Option<String>,
}
let _mytype: MyType = MyType::builder()
.integer(42)
.string("foobar")
.build();
- 添加一个构建结构体 (
<TargetStruct>Builder) - 构建结构体实现了
Default - 向目标结构体添加一个
builder()函数以初始化新的构建器 - 每个目标结构体字段都可以使用同名的函数和相同类型的参数进行设置
- 使用
build()函数创建新的目标结构体实例 - 任何未设置的字段将导致
build()调用无法编译(默认值) - setter 参数泛型于
Into Option字段不是必需的。并且设置器使用包装类型。
设置
使用 #[builder()] 属性来设置设置。
结构体
-
模式=<值>
更改构建器和相关build()函数的行为。支持值:Typestate(默认),Panic或Result。 -
选项=!
禁用整个结构体对自动Option检测。参见 "Option字段"。 -
默认=!
禁用结构体对自动Defaultderive 检测。参见 "Default结构体"。 -
默认
强制结构体对Default支持。参见 "Default结构体"。
字段
-
选项=!
禁用特定字段的自动Option检测。生成的设置器将依赖于声明的字段类型。参见 "Option字段"。 -
选项=包装类型
强制特定字段的Option支持。生成的设置器将依赖于WrappedType。参见 "Option字段"。 -
默认=!
禁用特定字段的自动Default检测。参见 "Default字段"。 -
默认
强制特定字段对Default支持。参见 "Default字段"。
配置
可以通过在 crate 根目录添加 macon-config.yaml 来传递一些额外的配置(也支持 .yml 和 .json 扩展名)。
内容示例
version: "1" # Ignored
default_types:
defaults: true
includes:
- my_crate::a_module::Foobar
excludes:
- usize
option_types:
defaults: true
includes:
- my_crate::a_module::MyOption # Must have a generic parameter
- path: Flag # An alias for Option<bool>
wrapped: bool
excludes:
- core::option::Option
语法描述(所有键都是可选的)
-
版本
定义配置语法版本。目前被忽略。 -
默认类型
配置自动Default类型。 -
默认类型.默认值
包括(或不包括)default_types的默认值。支持的值:true(默认)或false。 -
默认类型.排除
要排除的路径列表(例如std::string::String)。默认为空。 -
默认类型.包含
要包含的路径列表(例如my_crate::a_module::Foobar)。默认为空。 -
选项类型
配置自动Default类型。 -
选项类型.默认值
包括(或不包括)default_types的默认值。支持的值:true(默认)或false。 -
选项类型.排除
要排除的路径列表(例如std::string::String)。默认为空。 -
选项类型.包含
路径列表(例如my_crate::a_module::MyOption)作为String或结构化类型。默认为空。 -
选项类型.包含.路径
应被视为Option的路径。必需。 -
选项类型.包含.包装
包装类型的路径。可选,如果缺失,则使用第一个类型参数。
特性
对于任何特性,您可以在 [./tests 目录)测试 中找到蓝图,展示宏生成的代码。
类型状态模式(默认)
蓝图
blueprint_typestate_named.rsblueprint_typestate_tuple.rsblueprint_typestate_option.rsblueprint_typestate_default_field.rsblueprint_typestate_default_struct.rs
默认情况下,构建器依赖于类型状态模式。这意味着状态被编码在类型(使用泛型)中。只有当状态(类型)匹配时,适用的函数才会实现(可调用)
- 当所有属性都已设置时,执行
build()函数 - 每个属性设置函数只要属性尚未设置
可选地,您可以明确设置它
#[macro_use] extern crate macon;
#[derive(Builder)]
#[builder(mode=Typestate)]
struct MyType {
integer: i32,
string: String,
}
在 build() 上引发恐慌
蓝图
blueprint_panic_named.rsblueprint_panic_tuple.rsblueprint_panic_option.rsblueprint_panic_default_field.rsblueprint_panic_default_struct.rs
默认情况下,构建器通过添加编译约束来避免通过类型状态模式添加错误配置。您可以切换到在错误配置时引发恐慌的构建器
#[macro_use] extern crate macon;
use std::path::PathBuf;
#[derive(Builder)]
#[builder(mode=Panic)]
struct MyType {
integer: i32,
path: PathBuf,
}
let _mytype: MyType = MyType::builder()
.integer(42)
.build();
在 build() 上返回结果
蓝图
blueprint_result_named.rsblueprint_result_tuple.rsblueprint_result_option.rsblueprint_result_default_field.rsblueprint_result_default_struct.rs
默认情况下,构建器通过添加编译约束来避免通过类型状态模式添加错误配置。您可以切换到返回一个 Result 的构建器
#[macro_use] extern crate macon;
use std::path::PathBuf;
#[derive(Builder)]
#[builder(mode=Result)]
struct MyType {
integer: i32,
string: String,
}
let myTypeResult: Result<MyType,String> = MyType::builder()
.integer(42)
.build();
assert_eq!(
Err(String::from("Field path is missing")),
myTypeResult.map(|_| ())
);
元组
蓝图
元组是未命名字段的 struct。然后使用 set<ordinal>() 作为设置器
#[macro_use] extern crate macon;
#[derive(Builder)]
struct MyTuple(
i32,
Option<String>,
String,
);
let _mytuple: MyTuple = MyTuple::builder()
.set0(42)
.set2(String::from("foobar"))
.build();
仅适用于 Typestate 模式,您可以使用 set()、none()、keep() 和 default() 调用来按顺序分配值
#[macro_use] extern crate macon;
#[derive(Builder)]
struct MyTuple(
i32,
Option<String>,
String,
);
let _mytuple: MyTuple = MyTuple::builder()
.set(42)
.none()
.set(String::from("foobar"))
.build();
Into 参数
蓝图
设置函数参数泛型于 Into 以简化转换(尤其是对于 &str)
#[macro_use] extern crate macon;
#[derive(Builder)]
struct MyTuple(
String,
);
let _mytuple: MyTuple = MyTuple::builder()
.set("foobar")
.build();
实现 Into
蓝图
构建器为目标类型实现 Into(以及反向的 From)。除了使用 TryInto / TryFrom 的 Result 模式之外。
#[macro_use] extern crate macon;
#[derive(Builder)]
struct MyStruct {
value: String,
};
let _mytuple: MyStruct = MyStruct::builder()
.value("foobar")
.into();
Option 字段
蓝图
正如其名所示,Option 字段是可选的:您可以不显式设置它们来构建实例。
设置参数仍然泛型于 Into 但对于包装类型。无需将其包装在一个 Option 中。
#[macro_use] extern crate macon;
#[derive(Builder)]
struct WithOptional {
mandatory: String,
optional: Option<String>,
}
let built = WithOptional::builder()
.optional("optional value")
.mandatory("some value")
.build();
assert_eq!(Some(String::from("optional value")), built.optional);
您可以使用 <field>_none() 或 none() 对有序设置器显式地将它们设置为 None
#[macro_use] extern crate macon;
#[derive(Builder)]
pub struct WithOptional {
mandatory: String,
optional: Option<String>,
}
let built = WithOptional::builder()
.optional_none()
.mandatory("some value")
.build();
assert_eq!(None, built.optional);
注意:为了检测可选字段,字段类型 名称 必须匹配
core::option::选项::core::option::选项std::option::选项::std::option::选项选项
您可以使用在结构体或字段级别使用 #[builder(Option=!)] 来禁用 Option 支持
#[macro_use] extern crate macon;
#[derive(Builder)]
#[builder(Option=!)]
struct DisableOptionStruct {
optional: Option<String>,
}
let built = DisableOptionStruct::builder()
.optional(Some(String::from("mandatory value")))
.build();
assert_eq!(Some(String::from("mandatory value")), built.optional);
如果您使用别名,请在字段级别使用 #[builder(Option=<WrappedType>)] 来启用 Option 支持
#[macro_use] extern crate macon;
type OptString = Option<String>;
#[derive(Builder)]
struct AliasedOptionStruct {
#[builder(Option=String)]
optional: OptString,
}
let built = AliasedOptionStruct::builder()
.optional("aliased value")
.build();
assert_eq!(Some(String::from("aliased value")), built.optional);
Default 结构体
蓝图
blueprint_typestate_default_struct.rsblueprint_panic_default_struct.rsblueprint_result_default_struct.rs
如果结构体实现了 Default,则所有字段都变为可选的,并且值从默认实例中保留
注意:为了检测 Default 实现,必须在其他 derive 属性之前放置 Builder derive 属性。
#[macro_use] extern crate macon;
#[derive(Builder,)]
#[derive(PartialEq,Debug,)]
#[builder(Default,)]
struct DeriveDefaultStruct {
integer: usize,
string: String,
optional: Option<String>,
}
impl Default for DeriveDefaultStruct {
fn default() -> Self {
DeriveDefaultStruct {
integer: 42,
string: String::from("plop!"),
optional: Some(String::from("some")),
}
}
}
let built = DeriveDefaultStruct::builder()
.build();
assert_eq!(
DeriveDefaultStruct {
integer: 42,
string: String::from("plop!"),
optional: Some(String::from("some")),
},
built,
);
如果不需要检测 Default 实现,您可以使用 #[builder(Default=!)] 来禁用它。
另一方面,如果您有自己的 Default 实现,您可以添加 #[builder(Default)] 来启用支持。
#[macro_use] extern crate macon;
#[derive(Builder,)]
#[derive(PartialEq,Debug,)]
#[builder(Default,)]
struct CustomDefaultStruct {
integer: usize,
string: String,
optional: Option<String>,
}
impl Default for CustomDefaultStruct {
fn default() -> Self {
CustomDefaultStruct {
integer: 42,
string: String::from("plop!"),
optional: Some(String::from("some")),
}
}
}
let built = CustomDefaultStruct::builder()
.build();
assert_eq!(
CustomDefaultStruct {
integer: 42,
string: String::from("plop!"),
optional: Some(String::from("some")),
},
built,
);
您可以使用 <field>_keep() 或 keep() 对有序设置器显式地保留默认值(来自默认构建实例)
let built = CustomDefaultStruct::builder()
.integer_keep()
.string("overriden")
.optional_none()
.build();
assert_eq!(
CustomDefaultStruct {
integer: 42,
string: String::from("overriden"),
optional: None,
},
built,
);
Default 字段
蓝图
blueprint_typestate_default_field.rsblueprint_panic_default_field.rsblueprint_result_default_field.rs
如果字段实现了 Default,则它是可选的,并且值
- 如果结构体实现了
Default,则从默认实例中保留, - 或者,使用默认值初始化。
#[macro_use] extern crate macon;
#[derive(Builder)]
#[derive(Debug,PartialEq,)]
struct WithDefaultFields {
integer: usize,
string: String,
optional: Option<String>,
}
let built = WithDefaultFields::builder()
.build();
assert_eq!(
WithDefaultFields {
integer: 0,
string: String::from(""),
optional: None,
},
built,
);
您可以使用 <field>_default() 或 default() 显式地将它们设置为默认值,用于有序设置器(例如,重写默认实例值)
#[macro_use] extern crate macon;
#[derive(Builder)]
#[derive(Debug,PartialEq,)]
struct WithDefaultFields {
integer: usize,
string: String,
optional: Option<String>,
}
let built = WithDefaultFields::builder()
.integer_default()
.string_default()
.optional_default()
.build();
assert_eq!(
WithDefaultFields {
integer: 0,
string: String::from(""),
optional: None,
},
built,
);
为了检测默认字段,字段类型 名称 必须匹配(前缀 :: 和模块路径是可选的)
boolcharf32f64i8i16i32i64i128isizestru8u16u32u64u128usizestd::string::Stringcore::option::选项std::option::选项std::vec::Vecalloc::vec::Vecstd::collections::HashMapstd::collections::hash_map::HashMapstd::collections::HashSetstd::collections::hash_set::HashSet
如果您使用别名或不受支持的类型,请在字段级别使用 #[builder(Default)] 启用 Default 支持
#[macro_use] extern crate macon;
#[derive(Builder)]
#[derive(Debug,PartialEq,)]
struct ExplicitDefaultOnField {
#[builder(Default)]
boxed: Box<usize>,
}
let built = ExplicitDefaultOnField::builder()
.build();
assert_eq!(
ExplicitDefaultOnField {
boxed: Box::from(0),
},
built,
);
您可以通过在字段级别使用 #[builder(Default=!)] 禁用 Default 支持
// Don't compile
#[macro_use] extern crate macon;
#[derive(Builder)]
struct DisableDefaultOnField {
#[builder(Default=!)]
integer: usize,
}
DisableDefaultOnField::builder()
.integer_default()
.build();
依赖关系
~2–2.8MB
~60K SLoC