首页 > 解决方案 > 在枚举与结构之间转换

问题描述

我正在尝试设计一个具有许多不同子系统的系统,每个子系统都可以有多个可能的实现,并且每个子系统都由公共代码路径调用。像这样(注意每个子系统可以有相同的 A、B 和 C 实现):

                          /--- ASubSystem1
          /--- SubSystem1 ---- BSubSystem1
         /                \--- CSubSystem1
        /
       /                  /--- ASubSystem2
System ------- SubSystem2 ---- BSubSystem2
       \                  \--- CSubSystem2
        \
         \                /--- ASubSystem3
          \--- SubSystem3 ---- BSubSystem3
                          \--- CSubSystem3

为了配置系统,我创建了一个枚举来存储 A、B 和 C 的一般配置,如下所示:

// Copyright 2020 Google LLC.
// SPDX-License-Identifier: Apache-2.0

pub enum SystemConfig {
  A(AConfig),
  B(BConfig),
  C(CConfig),
}

但是,在调用公共代码路径中的每个子系统时,除了 Config 结构之外,我还想在调用中添加一些子系统特定的参数,如下所示:

// Copyright 2020 Google LLC.
// SPDX-License-Identifier: Apache-2.0

pub enum SubSystem1Params {
  A(ASubSystem1Params),
  B(BSubSystem1Params),
  C(CSubSystem1Params),
}

pub struct ASubSystem1Params {
  config: AConfig,
  ... other params required to call ASubSystem1
}
...

在这两个枚举之间进行转换的最佳方法是什么?从 SystemConfig 到 SubSystem1Params 以及从 SubSystem1Params 到 SystemConfig?有没有比使用匹配手动实现(和调用)这样的功能更清洁的方法?

// Copyright 2020 Google LLC.
// SPDX-License-Identifier: Apache-2.0

fn to_system_config(sub_system1_params: SubSystem1Params) -> System {
  match sub_system1_params {
    A(a) => a.config,
    B(b) => b.config,
    C(c) => c.config,
  }
}

fn to_sub_system1_params(system_config: SystemConfig) -> SubSystem1Config {
  match system {
    A(a) => SubSystem1Params { config: a, ...other params for a },
    B(b) => SubSystem1Params { config: b, ...other params for b },
    C(c) => SubSystem1Params { config: c, ...other params for c },
  }
}

明确想要避免的是这样的:

// Copyright 2020 Google LLC.
// SPDX-License-Identifier: Apache-2.0

pub struct SubSystem1CallParams {
  config: SystemConfig,
  params: SubSystem1Params,
}

因为无法确保 config 和 params 具有相同的枚举值 - 我想让 config 成为一种类型(比如 A)和另一种类型的 params(比如 B)成为不可能(编译失败) .

标签: rust

解决方案


推荐阅读