试图创建自己的Serialize特征和派生宏时,当我需要访问枚举的字段时,我被困住了.

例如,在枚举变量上:

enum MyEnum {
    MyVariant(f32, u16, u16)
}

我想要做的是:

fn Serialize(self) -> Vec<u8> {
    match self {
        MyEnum::MyVariant(field0, field1, field2) => {
            let mut result = Vec::<u8>::new();
            result.append(&mut field0.Serialize());
            result.append(&mut field1.Serialize());
            result.append(&mut field1.Serialize());
            result
        }
    }
}

其 idea 是,我将在基本数据类型上实现序列化特征,然后可以将其扩展到各种 struct 和枚举.

但我不知道如何为派生宏中的字段(field0、field1、field2)创建变量名,然后使用它们.

这就是我到目前为止要做的:

// create the fields argument tokens (this is "field0, field1, field2")
let mut fields_name = TokenStream2::new();
// operation of fields (this is result.append(field0.Serialize(); [...])
let mut fields_serialization = TokenStream2::new();
// counter to create numbered names for fields
let mut counter = 0;
for _field in &fields.unnamed { // fields is of type &FieldsUnnamed here
    if counter == 0 {
        fields_name.extend(quote!{
            format!("field{}", #counter)
        })
    }
    else {
        fields_name.extend(quote!{
            , format!("field{}", #counter)
        })
    }
    
    fields_serialization.extend(quote_spanned! {variant.span()=>
        result.append(&mut format!("field{}", #counter).Serialize());
    });

    counter += 1;
}

quote_spanned! {variant.span()=>
    #name::#variant_name (#fields_name) => {
        let mut result = Vec::new();
        #fields_serialization
        result
    },
}

我知道,使用FORMAT宏时,我会得到一个字符串令牌,但它不起作用.但我不知道如何获取我所有的枚举变量字段并对其进行操作,因为我在网上找到的信息很少.

推荐答案

我建议使用.enumerate(),并利用QUOTE的重复功能:

let mut field_name: Vec<_> = fields.unnamed.iter().enumerate().map(|(i, _)| {
    format_ident!("field{}", i)
}).collect();

quote_spanned! {variant.span()=>
    #name::#variant_name (#(#field_name,)*) => {
        let mut result = Vec::new();

        #(
            result.append(&mut #field_name.Serialize());
        )*

        result
    },
}

顺便说一句,在Rust中,标准样式是只将类型大写.所有方法都应为lower_snake_case.

Rust相关问答推荐

为什么函数不接受选项T参数的所有权?

重新导出proc宏导致未解决的extern crate错误""

rust 蚀将动力特性浇到混凝土 struct 上是行不通的

在函数内定义impl和在函数外定义impl的区别

MutexGuard中的过滤载体不需要克隆

支持TLS的模拟HTTP服务器

如何用Axum/Tower压缩Html内容?

无法从流中读取Redis请求

在IntoIter上调用.by_ref().Take().rev()时会发生什么情况

如何修复&q;无法返回引用函数参数的值在异步规则中返回引用当前函数&q;拥有的数据的值?

为什么Option类型try块需要类型注释?

在为第三方 struct 实现第三方特征时避免包装器的任何方法

详尽的匹配模式绑定

当锁被释放时,将锁包装到作用域中是否会发生变化?

Rust 编译器不统一在 if let 表达式的分支中都 impl Future 的类型

在多核嵌入式 Rust 中,我可以使用静态 mut 进行单向数据共享吗?

当 T 不是副本时,为什么取消引用 Box 不会抱怨移出共享引用?

为什么 Rust 允许写入不可变的 RwLock?

试图理解 Rust 中的可变闭包

在传输不可复制的值时实现就地枚举修改