Rust 的派生宏允许 helper 属性,例如
#[derive(HelperAttr)]
struct Struct {
#[helper] field: ()
}
syn
文档,属性可以采用名称-值形式,其中值是 Rust 表达式:
Meta::NameValue — 路径后面带有 = 符号的属性,后跟 Rust 表达式。例如#[path = "sys/windows.rs"].
所以我尝试了:
#[values = ["a", "b"]]
这不起作用。字符串起作用。数字起作用。布尔有效。数组,好像没有。编译器错误。
error: unexpected expression: `["a", "b"]`
--> tests/test1.rs:5:16
|
5 | #[values = ["a", "b"]]
|
但是
syn
文档的类型定义似乎表明应该支持任何 Rust 表达式。
哪里记录了支持的内容?名称-值属性中实际支持的值是什么?
尽管 Rust 语言参考将
Expression
声明为属性中 =
之后的 SimplePath
后面的有效标记。大多数表达式(元组、闭包也属于族)在这里无效,我想这应该是LiteralExpression
。
在库中,常见的模式是用
MetaList
术语代替数组之类的参数。
例如
#[derive(HelperAttr)]
struct MyStruct {
#[values(1, 2, 3)]
my_field: u32,
}
可以通过以下定义用
syn
来读取
#[proc_macro_derive(HelperAttr, attributes(values))]
pub fn derive_example(item: TokenStream) -> TokenStream {
let tokens = item.clone();
let ast = parse_macro_input!(tokens as DeriveInput);
let struct_: syn::DataStruct = match ast.data {
syn::Data::Struct(data) => data,
_ => panic!("Failed to parse HelperAttr, didn't parse struct"),
};
for field in struct_.fields.iter() {
for attr in field.attrs.iter() {
if attr.path().is_ident("values") {
let meta_list = attr.meta.require_list();
if let Ok(meta_list) = meta_list {
println!("{:#?}", meta_list.tokens);
}
}
}
}
TokenStream::new()
}