首页 > 解决方案 > 在procmacro中的所有字段和子字段上递归调用函数

问题描述

我有一个派生样式程序宏,我想在其中计算结构的序列化版本的潜在最大长度。例如,给定TestStruct下面的结构,我想调用一些包含所有字段的函数来计算最坏情况的长度。

#[derive(MyLengthProcMacro)]
struct TestStruct {
    f1: u32,
    f2: i64,
    f3: SomeOtherStruct
}

对于原语,这可能类似于:

fn get_string_length(ty: &Type) -> usize {
    let type_string = quote! { #ty }.to_string();
    match type_string.replace(" ", "").as_str() {
        "str" => panic!("String slices must be annotated with a length using #[at_arg()]"),
        "tuple" => panic!("Tuples are not supported!"),
        "char" => "a".len(),
        "bool" => "false".len(),
        "isize" => format!("{:?}", std::isize::MAX).len(),
        "usize" => format!("{:?}", std::usize::MAX).len(),
        "u8" => format!("{:?}", std::u8::MAX).len(),
        "u16" => format!("{:?}", std::u16::MAX).len(),
        "u32" => format!("{:?}", std::u32::MAX).len(),
        "u64" => format!("{:?}", std::u64::MAX).len(),
        "u128" => format!("{:?}", std::u128::MAX).len(),
        "i8" => format!("{:?}", std::i8::MIN).len(),
        "i16" => format!("{:?}", std::i16::MIN).len(),
        "i32" => format!("{:?}", std::i32::MIN).len(),
        "i64" => format!("{:?}", std::i64::MIN).len(),
        "i128" => format!("{:?}", std::i128::MIN).len(),
        "f32" => format!("{:?}", std::f32::MIN).len(),
        "f64" => format!("{:?}", std::f64::MIN).len(),
        _ => {
            // println!("Unexpected type: {:?}", type_string);
            0
        }
    }
}

我在这里问的问题是关于任何非原始字段,例如。f3: SomeOtherStruct. 有没有办法在 proc-macro 中访问字段的字段?

标签: rustrust-proc-macros

解决方案


不。

在完成这种分析之前,宏会被扩展,因此编译器不知道SomeOtherStruct此时是什么。


但是,这不是您应该实现该宏的方式!您的方式不允许用户使用类型别名。

您应该做的只是递归地使用您的特征并使用 sum<T as MyLength>::my_length()T表示每个字段的字段类型。

他们手动实现原始类型的特征。


推荐阅读