匹配 Rust 中枚举中的非变体值

问题描述 投票:0回答:1

假设我有以下枚举 - 混合 c 风格赋值和变体枚举:

enum Command {
    Control(ControlSubcommand) = 0x00,
    Temperature = 0x02,
    Voltage = 0x04,
    ...
}

enum ControlSubcommand {
     Status = 0x00,
     DeviceType = 0x01,
     ....
}

然后,当我尝试将给定命令解构为单个值时,我将其传递给函数。对于直接分配值(温度、电压等)的 C 风格命令,我想获取它的相应值 - 所以 0x02、0x04 等等。

对于“变体”命令(控制),我想获取它的值和子命令 - 所以 0x00 与 0x00、0x01 等等。

我正在尝试编写以下匹配结构来执行此操作:

match command {
    Command::Control(subcommand) => {
        println!("control command with subcommand {}", subcommand as u32);
    }
    simple => {
        println!("simple command {}", simple as u32);
    }
}

但问题是,从技术上讲,

simple
仍然是
Command
,它是非原始类型,因此
as
强制转换不适用于它。即使变体案例之前已经处理过并且不会出现在
simple
中,Rust 仍然不允许我执行强制转换。

是否可以在不更改枚举布局的情况下以某种方式修复此代码?

  • 使用 if-let 语法没有帮助。
  • 简单的
    as
    演员阵容不起作用
rust enums casting pattern-matching match
1个回答
0
投票

如果您不想一一匹配变体,而是希望尽快回退到判别式的数值,则可以在

unsafe
的帮助下实现(是的,它很难看)。

据我所知(我可能是错的)没有安全的方法来提取

Discriminant
返回的
std::mem::discriminant()
的数值。 由于我们用
#[repr(u32)]
指定判别式的形状,因此我们可以假设应用
std::mem::transmute()
运算以获得底层
u32

#[repr(u32)]
enum Command {
    Control(ControlSubcommand) = 0x00,
    Temperature = 0x02,
    Voltage = 0x04,
    //...
}

#[repr(u32)]
enum ControlSubcommand {
    Status = 0x00,
    DeviceType = 0x01,
    //....
}
fn main() {
    let cmds = [
        Command::Control(ControlSubcommand::Status),
        Command::Control(ControlSubcommand::DeviceType),
        Command::Temperature,
        Command::Voltage,
    ];
    for command in cmds {
        let d1: u32 =
            unsafe { std::mem::transmute(std::mem::discriminant(&command)) };
        match command {
            Command::Control(subcommand) => {
                let d2 = subcommand as u32;
                println!("control command ({}) with subcommand {}", d1, d2);
            }
            _ => {
                println!("simple command {:?}", d1);
            }
        }
    }
}
/*
control command (0) with subcommand 0
control command (0) with subcommand 1
simple command 2
simple command 4
*/
© www.soinside.com 2019 - 2024. All rights reserved.