![](/img/trans.png)
[英]Rust proc_macro_derive (with syn crate) generating enum variant for matching
[英]Rust proc_macro_derive: How do I check if a field is of a primitive type, like boolean?
我正在嘗試過濾掉結構中所有bool
類型的字段。 但是syn::Type
枚舉似乎沒有案例,或者我錯誤地閱讀了定義:
pub enum Type {
Array(TypeArray),
BareFn(TypeBareFn),
Group(TypeGroup),
ImplTrait(TypeImplTrait),
Infer(TypeInfer),
Macro(TypeMacro),
Never(TypeNever),
Paren(TypeParen),
Path(TypePath),
Ptr(TypePtr),
Reference(TypeReference),
Slice(TypeSlice),
TraitObject(TypeTraitObject),
Tuple(TypeTuple),
Verbatim(TokenStream),
// some variants omitted
}
我查看了syn::Types
源,以檢查省略了哪些變體,但這並沒有讓我更進一步。 這是我到目前為止所擁有的:
#[proc_macro_derive(Creator)]
pub fn derive_creator(_item: TokenStream) -> TokenStream {
let item = parse_macro_input!(_item as syn::DeriveInput);
let item_ident = item.ident;
let fields = if let syn::Data::Struct(syn::DataStruct {
fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }),
..
}) = item.data
{
named
} else {
panic!("You can derive Creator only on a struct!")
};
let bool_fields = fields.iter().filter(|field|
match field.ty {
// case when field type is bool => true
_ => false
}
);
unimplemented!()
}
我走錯路了嗎? 或者這根本不可能? 還是我錯過了什么?
我覺得可能有一種更清潔的方式(無需克隆和分配字符串),但過去我做過類似的事情:
match field.ty {
Type::Path(type_path) if type_path.clone().into_token_stream().to_string() == "bool" => {
true
}
_ => false
}
您也許可以定義一次bool
類型,然后比較它是否相等:
let bool_ty = Type::Path(TypePath {
qself: None,
path: Path::from(Ident::new("bool", Span::call_site())),
});
if field.ty == bool_ty {
// it's a bool
}
但我不確定跨度的差異是否會影響平等。 Span
似乎沒有實現PartialEq
,所以我猜這沒問題。*
*歡迎編輯澄清這一點。
另一種方式:
let bool_fields = fields.iter().filter(|field| {
if let Type::Path(tp) = &field.ty {
let segments = &tp.path.segments;
// Check len to avoid "bool::SomeOtherType".
if segments.len() == 1 {
return segments[0].ident == "bool";
}
}
false
});
記住:
值得指出的是,這會按名稱檢查是否相等。 類型別名、單字段元組或 core::primitive::bool 將不匹配,盡管它們在類型解析后都是 bool。 – 用戶2722968
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.