2个版本
新版本 0.1.11 | 2024年8月22日 |
---|---|
0.1.10 | 2024年7月15日 |
968 在 过程宏 中
每月 38次下载
18KB
212 行
FieldnameAccess 派生宏
当不知道确切需要哪个字段时,我们可以根据其他数据匹配并执行一些操作,此时使用它可以安全地从结构体中通过字段名获取值
容器属性
#fieldname_enum(name = "NewName")
- 生成可能值枚举的名称
use fieldname_access::FieldnameAccess;
#[derive(FieldnameAccess, Default)]
#[fieldname_enum(name = "NewName")]
struct NamedFieldname {
name: String,
age: i64,
}
let mut instance = NamedFieldname::default();
match instance.field("name").unwrap() {
NewName::String(val) => {}
NewName::I64(val) => {},
}
match instance.field_mut("name").unwrap() {
NewNameMut::String(val) => {}
NewNameMut::I64(val) => {},
}
#fieldname_enum(derive = [Debug, Clone], derive_mut = [Debug])
- 为生成的枚举生成派生宏。derive
仅对不可变引用的枚举有效,derive_mut
仅对可变引用的枚举有效。当您只想对不可变引用派生Clone
时,这可能很有用,因为可变引用不可克隆
use fieldname_access::FieldnameAccess;
#[derive(FieldnameAccess)]
#[fieldname_enum(derive = [Debug, Clone], derive_mut = [Debug])]
struct NamedFieldname {
name: String,
age: i64,
}
#fieldname_enum(derive_all = [Debug])
- 为不可变和可变生成的枚举生成派生宏
use fieldname_access::FieldnameAccess;
#[derive(FieldnameAccess)]
#[fieldname_enum(derive_all = [Debug])]
struct NamedFieldname {
name: String,
age: i64,
}
字段属性
#fieldname = "AmazingAge"
- 生成枚举中字段变体的名称。当您想使用特定变体名称“标记”字段时,这可能很有用
use fieldname_access::FieldnameAccess;
#[derive(FieldnameAccess, Default)]
struct NamedFieldname {
name: String,
#[fieldname = "MyAge"]
age: i64,
dog_age: i64
}
let mut instance = NamedFieldname::default();
match instance.field("name").unwrap() {
NamedFieldnameField::String(val) => {}
NamedFieldnameField::MyAge(val) => {}
NamedFieldnameField::I64(val) => {}
}
match instance.field_mut("name").unwrap() {
NamedFieldnameFieldMut::String(val) => {}
NamedFieldnameFieldMut::MyAge(val) => {}
NamedFieldnameFieldMut::I64(val) => {}
}
实际示例
假设我们有一个User结构体和针对它的Crit准则。
use fieldname_access::FieldnameAccess;
#[derive(FieldnameAccess)]
struct User {
name: String,
age: u64,
does_love_ranni: bool, // important
}
struct Crit {
value: String,
field: String,
kind: CritKind,
}
enum CritKind {
Contains,
Equals,
BiggerThan,
}
基于这些信息,FieldnameAccess
将生成所有可能的类型和为 User
结构体提供的方法,以便通过名称访问它们
enum UserField<'a> {
String(&'a String),
U64(&'a u64),
Bool(&'a bool)
}
enum UserFieldMut<'a> {
String(&'a mut String),
U64(&'a mut u64),
Bool(&'a mut bool)
}
有了这两个元素的信息,我们可以确定我们的下一步行动。
let user = User {
age: 2022,
name: String::from("Radahn"),
does_love_ranni: true,
};
let crits = vec![
Crit {
value: String::from("Ra"),
field: String::from("name"),
kind: CritKind::Contains,
},
Crit {
value: String::from("true"),
field: String::from("does_love_ranni"), // important
kind: CritKind::Equals,
},
Crit {
value: String::from("18"),
field: String::from("age"),
kind: CritKind::BiggerThan,
},
];
let its_ok = crits.into_iter().all(|crit| {
let user_field =
user.field(&crit.field).expect("Criteria has wrong fieldname");
match crit.kind {
CritKind::Contains => match user_field {
UserField::String(str) => str.contains(&crit.value),
_ => panic!("Criteria has wrong value"),
},
CritKind::Equals => match user_field {
UserField::String(str) => str.eq(&crit.value),
UserField::U64(int) => int.eq(&crit.value.parse::<u64>().unwrap()),
UserField::Bool(boolean) => {
boolean.eq(&crit.value.parse::<bool>().unwrap())
}
},
CritKind::BiggerThan => match user_field {
UserField::U64(int) => int > &crit.value.parse::<u64>().unwrap(),
_ => panic!("Criteria has wrong value"),
},
}
});
assert!(its_ok);
您还可以修改字段
if let Some(UserFieldMut::Bool(does_love_ranni)) =
user.field_mut("does_love_ranni") // important
{
*does_love_ranni = false; // HARAM
}
assert!(!user.does_love_ranni); //important
依赖项
~2MB
~52K SLoC