8个版本 (4个重大更新)
0.5.0 | 2023年8月4日 |
---|---|
0.4.2 | 2023年7月15日 |
0.3.0 | 2023年6月24日 |
0.2.1 | 2023年6月10日 |
0.1.0 | 2023年5月27日 |
#1842 in 过程宏
7,345 每月下载量
用于 15 个 包(2 个直接使用)
30KB
411 行
默认结构体构建器
为结构体每个字段生成构建器方法。它旨在用于实现 Default
的结构体。没有生成单独的构建器结构体,也不需要在结束时调用 build()
方法或 .unwrap()
。
此包由 leptos-use
包用于传递给各种函数的选项结构体。
安装
在您的项目文件夹中运行
cargo add default-struct-builder
使用方法
使用非常简单
use default_struct_builder::DefaultBuilder;
#[derive(DefaultBuilder, Default)]
pub struct SomeOptions {
throttle: f64,
#[builder(into)]
offset: Option<f64>,
#[builder(skip)]
not_included: u32,
}
然后您可以使用结构体如下
let options = SomeOptions::default().offset(4.0);
assert_eq!(options.offset, Some(4.0));
assert_eq!(options.throttle, 0.0);
assert_eq!(options.not_included, 0);
泛型
该宏已准备好用于泛型结构体。
use default_struct_builder::DefaultBuilder;
#[derive(DefaultBuilder, Default)]
pub struct SomeOptions<T>
where
T: Default,
{
some_field: T,
}
文档注释
所有字段的文档注释都直接传递给其生成的设置方法。
它是如何工作的
派生宏生成以下代码
impl SomeOptions {
// setter methods are given that consume `self` and return a new `Self` with the field value changed
pub fn throttle(self, value: f64) -> Self {
Self {
throttle: value,
..self
}
}
// because `into` was specified this method is generic and calls `.into()` when setting the value
pub fn offset<T>(self, value: T) -> Self
where
T: Into<Option<f64>>,
{
Self {
offset: value.into(),
..self
}
}
// no method for field `not_included` because `skip` was specified
}
泛型
对于泛型字段,生成的方法稍微复杂一些,因为调用方法后类型参数的类型可能与之前不同。
让我们看看以下示例。
use default_struct_builder::DefaultBuilder;
#[derive(DefaultBuilder, Default)]
pub struct SomeOptions<T>
where
T: Default,
{
some_field: T,
other_field: i16,
}
impl SomeOptions<f32> {
pub fn new() -> Self {
Self {
some_field: 42.0,
other_field: 0,
}
}
}
这会生成以下设置方法。
impl<T> SomeOptions<T>
where
T: Default,
{
pub fn some_field<NewT>(self, value: NewT) -> SomeOptions<NewT>
where
NewT: Default,
{
SomeOptions::<NewT> {
some_field: value,
other_field: self.other_field,
}
}
}
fn main() {
let options = SomeOptions::new() // at first SomeOptions<f32>
.some_field("string"); // changed to SomeOptions<&str>
}
如果不想让泛型字段能够改变泛型类型,可以对其进行 keep_type
注解。
#[derive(DefaultBuilder)]
struct SomeOptions<T> {
#[builder(keep_type)]
the_field: T,
}
这将生成一个标准的构建器方法,就像 T
没有泛型一样。
Box
,Rc
和 Arc
该宏检测一个字段是否为Box
(或Rc
或Arc
),并生成一个接受内部类型(不包括Box
、Rc
或Arc
)并在主体中添加外部类型的构建方法。
如果是Box<dyn Trait>
,则构建方法将有一个类型为impl Trait
的参数。对于Rc
和Arc
也是如此。
如果您想防止这种自动解包,可以使用#[builder(keep_outer)]
属性。
trait Test {}
#[derive(DefaultBuilder)]
struct SomeOptions {
the_field: Box<dyn Test>,
other_field: Rc<String>,
#[builder(keep_outer)]
keep: Box<String>,
}
这将生成以下代码
impl SomeOptions {
pub fn the_field(self, value: impl Test + 'static) -> Self {
Self {
the_field: Box::new(value),
..self
}
}
pub fn other_field(self, value: String) -> Self {
Self {
other_field: Rc::new(value),
..self
}
}
pub fn keep(self, value: Box<String>) -> Self {
Self {
keep: value,
..self
}
}
}
相关工作
对于更通用目的,请查看功能更强大的derive_builder
crate。
依赖项
~0.6–1MB
~25K SLoC