有没有像field_count()
这样的API,或者只有通过宏才能实现?
没有这样的内置API允许您在运行时获取这些信息.Rust没有运行时反射(更多信息请参见this question).但这确实可以通过proc宏实现!
注:proc宏不同于"示例宏"(通过macro_rules!
声明).后者不如proc宏强大.
如果宏可以实现这一点,应该如何实现?
(This is not an introduction into proc-macros; if the topic is completely new to you, first read an introduction elsewhere.)
在proc宏(例如自定义派生)中,您可能需要将 struct 定义设置为TokenStream
.使用TokenStream
with Rust语法的实际解决方案是通过syn
解析它:
#[proc_macro_derive(FieldCount)]
pub fn derive_field_count(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
// ...
}
input
型是ItemStruct
型.如你所见,它有Fields
类型的字段fields
.在该字段上,您可以调用iter()
来获取 struct 的所有字段的迭代器,然后在该字段上调用count()
:
let field_count = input.fields.iter().count();
现在你有你想要的了.
也许你想把这个field_count()
方法添加到你的类型中.您可以通过自定义派生(使用quote
crate ):
let name = &input.ident;
let output = quote! {
impl #name {
pub fn field_count() -> usize {
#field_count
}
}
};
// Return output tokenstream
TokenStream::from(output)
然后,在应用程序中,您可以编写:
#[derive(FieldCount)]
struct MyStruct {
first_field: i32,
second_field: String,
third_field: u16,
}
MyStruct::field_count(); // returns 3