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
字段"。 -
默认=!
禁用结构体对自动Default
derive 检测。参见 "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.rs
blueprint_typestate_tuple.rs
blueprint_typestate_option.rs
blueprint_typestate_default_field.rs
blueprint_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.rs
blueprint_panic_tuple.rs
blueprint_panic_option.rs
blueprint_panic_default_field.rs
blueprint_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.rs
blueprint_result_tuple.rs
blueprint_result_option.rs
blueprint_result_default_field.rs
blueprint_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.rs
blueprint_panic_default_struct.rs
blueprint_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.rs
blueprint_panic_default_field.rs
blueprint_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,
);
为了检测默认字段,字段类型 名称 必须匹配(前缀 ::
和模块路径是可选的)
bool
char
f32
f64
i8
i16
i32
i64
i128
isize
str
u8
u16
u32
u64
u128
usize
std::string::String
core::option::选项
std::option::选项
std::vec::Vec
alloc::vec::Vec
std::collections::HashMap
std::collections::hash_map::HashMap
std::collections::HashSet
std::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