【问题标题】:Rust macro generate enum from another enumRust 宏从另一个枚举生成枚举
【发布时间】:2021-01-04 15:16:32
【问题描述】:

我正在尝试解决代码重复问题,以减少出错的可能性。

我正在使用不同的数据源,每个数据源都有一些特定的属性。这是我的数据模型的样子:

mod sources {
    pub struct Ds1;
    pub struct Ds2;
    //hundreds more

    pub trait DsTypeTrait{
        type Input;
        type Output;
    }

    impl DsTypeTrait for Ds1 {
        type Input = u32;
        type Output = u32;
    }

    impl DsTypeTrait for Ds2 {
        type Input = String;
        type Output = String;
    }

    //etc...

    enum DataSource{
        Ds1(Ds1),
        Ds2(Ds2),
        //...
    }
}

因此,任何时候有人想要添加对新数据源的支持,他们都需要将其添加到enum DataSource。解决方案的问题是,如果另一个模块包含一些自定义数据格式,例如DataSource 通信需要在两个非常容易出错的地方添加数据源。例如:

mod some_other {
    use super::sources::*;

    struct DataSourceDataInputOutput<Ds: DsTypeTrait>{
        input: <Ds as DsTypeTrait>::Input,
        output: <Ds as DsTypeTrait>::Output
    }

    enum DataSourceIO{
        Ds1(DataSourceDataInputOutput<Ds1>),
        Ds2(DataSourceDataInputOutput<Ds2>)
        //Extremely easy to forget to add here
    }
}

问题:鉴于enum DataSource,是否可以编写一个宏来自动生成enum DataSourceIO,避免每次添加new DataSource 时手动修改enum DataSourceIO

【问题讨论】:

    标签: enums rust macros metaprogramming


    【解决方案1】:

    枚举解析似乎是一个复杂的问题,因此在宏本身中移动 DataSource 实际声明是合理的。这是我想出的:

    #[macro_use]
    mod sources {
        macro_rules! data_sources {
            ($name:ident, $type:tt) => {
                enum $name{
                    Ds1($type<Ds1>),
                    Ds2($type<Ds2>)
                }
            }
        }
    
        //...
    }
    
    mod some_other {
    
        struct DataSourceDataInputOutput<Ds: DsTypeTrait>{
            input: <Ds as DsTypeTrait>::Input,
            output: <Ds as DsTypeTrait>::Output
        }
        
        data_sources!(Test, DataSourceDataInputOutput);
    
        fn test_fn() {
            let ds1io: DataSourceDataInputOutput<Ds1> = DataSourceDataInputOutput{
                input: 1,
                output: 2
            };
            let test = DataSourceIO::Ds1(ds1io);  //works ok
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2023-01-03
      • 2014-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-04
      • 1970-01-01
      • 2022-11-14
      • 2010-09-11
      相关资源
      最近更新 更多