You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust过程宏技术求助:如何为已有枚举追加成员

Rust过程宏实现动态追加枚举成员问题

背景

使用rustdds crate实现DDS,通过枚举自定义领域参与者对接自定义主题(CustomTopic),枚举每个成员对应关联自定义可序列化数据类型的DataReader和DataWriter。最初尝试用HashMap<CustomTopic, DataReader<dyn Any>>(DataWriter同理),但因dyn Any或自定义可序列化 trait 的类型大小编译期无法确定,编译器报错。

临时解决方案

采用枚举实现,效果良好:既可以通过HashMap访问读写器,也能通过match匹配获取具体类型:

pub enum CustomDataReader {
    String(DataReader(String)),
    MyCustomDatatype(DataReader(MyCustomDatatype)), // MyCustomDatatype已实现序列化
}

// 存储到HashMap
let data_readers_hashmap = HashMap::<CustomTopic, CustomDataReader>::new();

匹配示例:

match datareader {
    CustomDataReader::String(dr) => {
        // dr类型为DataReader<String>
    },
    CustomDataReader::MyCustomDatatype(dr) => {
        // dr类型为DataReader<MyCustomDatatype>
    },
}

但这种方式存在大量样板代码,因此尝试用过程宏优化。

理想效果

希望通过在结构体上添加#[derive(CustomDatatype)]派生宏,自动将结构体作为成员追加到预定义的CustomDataReader和CustomDataWriter枚举中:

#[derive(CustomDatatype)]
struct Car {
    make: String,
    model: String,
    num_wheels: u8,
}

#[derive(CustomDatatype)]
struct Building {
    name: String,
    location: (f32, f32),
}

// 预定义空枚举
pub enum CustomDataReader {}
pub enum CustomDataWriter {}

宏自动生成后的枚举:

pub enum CustomDataReader {
    Car(DataReader(Car)),
    Building(DataReader(Building)),
}
pub enum CustomDataWriter {
    Car(DataWriter(Car)),
    Building(DataWriter(Building)),
}

之后可通过CustomDataReader::Car等方式访问对应读写器。

失败尝试

实现的派生宏无法实现“追加到已有枚举”的功能,当前代码会重复定义枚举:

#[proc_macro_derive(CustomDatatype)]
pub fn custom_datatype_derive(input: TokenStream) -> TokenStream {
    let input: DeriveInput = parse_macro_input!(input);
    let struct_name = &input.ident;
    let output = quote! {
        #input

        pub enum CustomDataReader {
            #struct_name(rustdds::no_key::DataReader<#struct_name>),
        }
        pub enum CustomDataWriter {
            #struct_name(rustdds::no_key::DataWriter<#struct_name>),
        }
    }
    output.into()
}

生成的代码会重复定义枚举:

// 处理Car时生成
pub enum CustomDataReader {
    Car(DataReader(Car)),
}
pub enum CustomDataWriter {
    Car(DataWriter(Car)),
}

// 处理Building时生成
pub enum CustomDataReader {
    Building(DataReader(Building)),
}
pub enum CustomDataWriter {
    Building(DataWriter(Building)),
}

不符合需求,尝试过其他宏类型仍无进展。

补充说明

曾尝试使用泛型和自定义 trait:

pub trait DDS_Msg: Serialize + for<'a> Deserialize<'a> + fmt::Display + Clone {}

struct CustomDatatype {};
impl DDS_Msg for CustomDatatype {}

pub struct Messenger {
    pub reader: Box<DataReader<dyn DDS_Msg>>,
    pub writer: Box<DataWriter<dyn DDS_Msg>>,
}

但出现编译错误:

error[E0277]: the size for values of type `(dyn ddstypes::DDS_Msg + 'static)` cannot be known at compilation time
   --> src/utils/ddstypes.rs:123:17
    |
123 |     pub reader: Box<DataReader<dyn DDS_Msg>>,
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn ddstypes::DDS_Msg + 'static)`
note: required by a bound in `rustdds::no_key::DataReader`
   --> /home/user/.cargo/registry/src/github.com/rustdds-0.7.11/src/dds/no_key/datareader.rs:49:23
    |
49  | pub struct DataReader<D: DeserializeOwned, DA: DeserializerAdapter<D> = CDRDeserializerAdapter<D>> {
    |                       ^ required by this bound in `rustdds::no_key::DataReader`

因此必须在编译期预定义数据类型,静态类型枚举是可行方案。

内容的提问来源于stack exchange,提问作者Arpad Voros

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 01:17:49