8个不稳定版本 (3个破坏性更新)
0.4.2 | 2024年7月29日 |
---|---|
0.4.1 | 2024年7月28日 |
0.3.1 | 2024年7月13日 |
0.2.2 | 2024年7月3日 |
0.1.0 | 2023年10月12日 |
250 在 Rust模式 中
每月634次下载
38KB
640 行
模型映射器
此库提供宏来实现类型之间的转换函数(枚举和结构体),无需样板代码。
它还提供了一个包含一些类型转换实用工具的 with
模块,这些工具不实现 Into
特性。
只要您不使用 with
模块(禁用默认功能)并且不派生 try_into
或 try_form
,此库就可以在 #![no_std]
链接中使用。
示例
此库最常见的使用案例是在服务和面向外部的模型或DTO之间映射领域实体。
#[derive(Mapper)]
#[mapper(from, ty = Entity)]
pub struct Model {
id: i64,
name: String,
}
上面的宏展开将生成类似以下内容
impl From<Entity> for Model {
fn from(Entity { id, name }: Entity) -> Self {
Self {
id: Into::into(id),
name: Into::into(name),
}
}
}
因为类型并不总是完美匹配,您可以在运行时提供额外的字段,但这将牺牲使用 From
特性的能力
pub mod service {
pub struct UpdateUserInput {
pub user_id: i64,
pub name: Option<String>,
pub surname: Option<String>,
}
}
#[derive(Mapper)]
#[mapper(
into(custom = "into_update_user"),
ty = service::UpdateUserInput,
add(field = user_id, ty = i64),
add(field = surname, default(value = None))
)]
pub struct UpdateProfileRequest {
pub name: String,
}
将生成类似以下内容
impl UpdateProfileRequest {
/// Builds a new [service::UpdateUserInput] from a [UpdateProfileRequest]
pub fn into_update_user(self, user_id: i64) -> service::UpdateUserInput {
let UpdateProfileRequest { name } = self;
service::UpdateUserInput {
user_id,
surname: None,
name: Into::into(name),
}
}
}
其他高级用例可以在 示例文件夹 中找到。
用法
在类型级别需要 mapper
属性,在字段或变体级别是可选的。
以下属性可用。
-
类型级别属性
ty = PathType
(必填):要派生转换的另一个类型from
(可选):是否为自身派生From
的另一个类型custom
(可选):派生自定义函数而不是特型custom = from_other
(可选):派生自定义函数而不是特型,使用给定的名称
into
(可选):是否为另一个类型派生From
自身custom
(可选):派生自定义函数而不是特型custom = from_other
(可选):派生自定义函数而不是特型,使用给定的名称
try_from
(可选):是否为自身派生TryFrom
的另一个类型custom
(可选):派生自定义函数而不是特型custom = from_other
(可选):派生自定义函数而不是特型,使用给定的名称
try_into
(可选):是否为其他类型派生TryFrom
selfcustom
(可选):派生自定义函数而不是特型custom = from_other
(可选):派生自定义函数而不是特型,使用给定的名称
add
(可选,多个):其他类型有而本类型没有的额外字段(对于具有命名字段的 struct)或变体(对于 enum)¹field = other_field
(必填):字段或变体名称ty = bool
(可选):字段类型,对于没有提供默认值的into
和try_into
是必填的default
(可选):将使用Default::default()
来填充字段或变体(对于 enum,无论是否有值都是必填的)value = true
(可选):将使用给定的表达式来填充字段或变体
ignore_extra
(可选):是否忽略其他类型的所有额外字段(对于 struct)或变体(对于 enum)²
-
变体级别的属性
rename = OtherVariant
(可选):在另一个 enum 上重命名此变体add
(可选,多个):变体的额外字段,其他类型的变体有而本类型没有的 ¹field = other_field
(必填):字段名称ty = bool
(可选):字段类型,对于没有提供默认值的into
和try_into
是必填的default
(可选):将使用Default::default()
来填充字段或变体value = true
(可选):将使用给定的表达式来填充字段或变体
skip
(可选):是否跳过此变体,因为其他 enum 没有它default
(必填):将使用Default::default()
来填充字段或变体value = get_default_value()
(可选):将使用给定的表达式来填充字段或变体
ignore_extra
(可选):是否忽略其他变体的所有额外字段(仅对 from 和 try_from 有效)²
-
字段级别的属性
rename = other_name
(可选):在另一个类型上重命名此字段skip
(可选):是否跳过此字段,因为其他类型没有它default
(可选):将使用Default::default()
来填充字段或变体value = get_default_value()
(可选):将使用给定的表达式来填充字段或变体
with = mod::my_function
(可选):如果字段类型没有实现Into
或TryInto
的其他类型,这个属性允许你通过提供转换函数来自定义行为into_with = mod::my_function
(可选):与上面相同,但仅适用于into
或try_into
派生from_with = mod::my_function
(可选):与上面相同,但仅适用于from
或try_from
派生
¹ 当提供没有默认值的额外字段时,From
和 TryFrom
特性无法被推导,因此需要使用自定义函数。当推导 into
或 try_into
时,必须提供 ty
。
² 忽略字段或变体时,可能需要枚举或结构体实现 Default
,以便正确填充它。
多重推导
当为单个类型推导转换时,可以直接设置属性
#[mapper(from, into, ty = OtherType, add(field = field_1, default), add(field = field_2, default))]
但也可以通过在 derive
属性上包装属性来为多个类型推导转换
#[mapper(derive(try_into, ty = OtherType, add(field = field_1, default)))]
#[mapper(derive(from, ty = YetAnotherType))]
如果涉及多个转换,也可以在 when
属性中包装变体级和字段级属性,并且必须设置它们所引用的 ty
#[mapper(when(ty = OtherType, with = TryIntoMapper::try_map_removing_option))]
#[mapper(when(ty = YetAnotherType, skip(default)))]
依赖关系
~0.7–1.7MB
~35K SLoC