7 个版本 (破坏性更新)
0.7.0 | 2023 年 11 月 27 日 |
---|---|
0.6.0 | 2023 年 11 月 17 日 |
0.5.0 | 2023 年 11 月 16 日 |
0.4.0 | 2023 年 11 月 13 日 |
0.1.0 | 2023 年 11 月 13 日 |
734 在 Rust 模式
每月 2,520 次下载
25KB
357 行
枚举公共字段
概述
用于生成枚举中公共字段获取器/设置器的宏。也就是说,如果你的枚举的每个变体都有一些字段,你就可以通过 field() 和 field_mut() 访问器分别访问它。
例如,如果你有一个类型为 String 的公共字段 key
,你可以使用宏如下
#[derive(EnumCommonFields)]
#[common_field(mut key: String)]
enum MyEnum {
// Some variants
}
并拥有方法 .key()
和 .key_mut()
,分别返回 &String
和 &mut String
。如果你不想创建 .key_mut()
访问器,你可以在声明中省略 mut,如下所示
#[derive(EnumCommonFields)]
#[common_field(key: String)]
enum MyEnum {
// Some variants
}
背景
枚举变体具有公共字段的情况相当普遍,如下所示
struct CreateRequest {
id: String,
// other fields
}
struct UpdateRequest {
id: String,
// other fields
}
enum Request {
Create(CreateRequest),
Update(UpdateRequest),
}
但是,如果你有一个枚举实例,访问公共字段会很麻烦
fn handle(req: Request) {
let id = match req {
Update(r) => r.id,
Create(r) => r.id,
};
// ...
}
在这种情况下,常见的建议是将公共字段提取到封装的结构体中
struct CreateRequest {
// fields
}
struct UpdateRequest {
// fields
}
enum RequestKind {
Create(CreateRequest),
Update(UpdateRequest),
}
struct Request {
id: String,
req: RequestKind,
}
但这会使需要使用公共字段的具体处理函数复杂化。例如
fn create_handler(
id: String, // need to get id as a param by itself
req: CreateRequest
) {
// ...
}
此宏通过自动生成公共字段的访问器方法来解决此问题。例如
struct CreateRequest {
id: String,
// other fields
}
struct UpdateRequest {
id: String,
// other fields
}
#[derive(EnumCommonFields)]
#[common_field(id: String)]
enum Request {
Create(CreateRequest),
Update(UpdateRequest),
}
fn handle(req: Request) {
let id = req.id();
// ...
}
生成的访问器与以下等价
impl Request {
fn id(&self) -> &String {
match self {
Update(r) => r.id,
Create(r) => r.id,
}
}
}
安装
将以下内容添加到你的 Cargo.toml
enum_common_fields = "0.7.0"
使用方法
有关完整参考,请参阅 文档。
缺失的功能
有一些功能是可以实现的,但我认为添加它们的努力不值得。因此,如果您是少数真正需要其中之一的人,请在 issues 中随意打扰我。
批量重命名访问器
我在谈论既重命名访问器的 'base' 字段名称(因此对于字段 identifier
将生成 id()
和 id_mut()
),又更改访问器名称 'template'(因此所有不可变访问器都将为 get_field()
而不是仅仅是 field()
)。这是可能的,但我相信大多数人会完全接受我的约定。
复合所有者访问器
目前,所有者访问器的功能相当有限。如果您想获取枚举实例中多个公共字段的拥有权,则需要回退到使用具有许多相同分支的 match
。理论上我可以生成一个 into_common()
方法,该方法将返回所有具有所有者访问器的字段。问题是这个理论方法返回的类型。为所有公共字段生成结构体似乎太多,但如果许多字段具有相同类型,仅返回一个元组可能会非常令人困惑。
具有一个注解的访问器的奇怪组合
我真的不相信有人需要经常生成仅拥有和可变访问器的字段,以至于要讨论它。
转换
目前,宏执行的转换仅限于从 Deref
和 DerefMut
特性。例如,您可以使用 str
作为 String
字段 ref 访问器的类型。这样,访问器将返回 &str
和 &mut str
。但它不会调用 into()
或其他任何转换。
依赖关系
~295–750KB
~18K SLoC