是否有任何可能的 API,field_count()
或者只能通过宏获得?
没有这样的内置 API 可以让您在运行时获取此信息。Rust 没有运行时反射(有关更多信息,请参阅此问题)。但这确实可以通过 proc-macros 实现!
注意:proc-macros 不同于“macro by example”(通过 声明macro_rules!
)。后者不如 proc-macros 强大。
如果这可以通过宏实现,应该如何实现?
(这不是对 proc-macros 的介绍;如果该主题对您来说是全新的,请先阅读其他地方的介绍。)
在 proc-macro(例如自定义派生)中,您需要以某种方式将结构定义获取为TokenStream
. 使用 with Rust 语法的实际解决方案TokenStream
是通过以下方式解析它syn
:
#[proc_macro_derive(FieldCount)]
pub fn derive_field_count(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemStruct);
// ...
}
的类型input
是ItemStruct
。如您所见,它具有fields
type的字段Fields
。在该字段上,您可以调用iter()
以获取结构所有字段的迭代器,然后您可以调用count()
:
let field_count = input.fields.iter().count();
现在你有你想要的了。
也许您想将此field_count()
方法添加到您的类型中。您可以通过自定义派生来做到这一点(通过使用quote
此处的板条箱):
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