首页 > 解决方案 > Rust proc_macro_derive:如何检查字段是否为基本类型,如布尔值?

问题描述

我正在尝试过滤掉 struct 类型的所有字段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!()
}

我走错路了吗?或者这根本不可能?还是我错过了什么?

标签: rustrust-proc-macros

解决方案


我觉得可能有一种更清洁的方式(无需克隆和分配字符串),但过去我做过类似的事情:

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,所以我猜这没关系。*


*欢迎编辑澄清这一点。


推荐阅读