提问人:Roman Liutko 提问时间:10/8/2023 最后编辑:BiagioFRoman Liutko 更新时间:10/8/2023 访问量:81
匹配 Rust 中枚举中的非变量值
Match non variant values in enum in Rust
问:
假设我有以下枚举 - 混合 c 样式赋值和变体枚举:
enum Command {
Control(ControlSubcommand) = 0x00,
Temperature = 0x02,
Voltage = 0x04,
...
}
enum ControlSubcommand {
Status = 0x00,
DeviceType = 0x01,
....
}
然后,当我尝试将给定命令解构为单个值时,我将其传递给函数。对于直接分配值(温度、电压等)的 c 样式命令,我想获取它的相应值 - 所以0x02、0x04等。
对于“变体”命令(Control),我想获取它的值和子命令 - 因此0x00 0x00,0x01等。
我正在尝试编写以下匹配结构来做到这一点:
match command {
Command::Control(subcommand) => {
println!("control command with subcommand {}", subcommand as u32);
}
simple => {
println!("simple command {}", simple as u32);
}
}
但问题是,从技术上讲,它仍然是一个非原始类型,所以 cast 不能使用它。尽管之前已经处理过变体情况并且不会出现在 中,但 Rust 仍然不允许我执行投射。simple
Command
as
simple
是否可以在不更改枚举布局的情况下以某种方式修复此代码?
- 使用 if-let 语法无济于事。
- 简单的投射不起作用
as
答:
2赞
Chayim Friedman
10/8/2023
#1
没有安全的方法可以做到这一点。如果枚举是(必须是枚举才能定义判别器)。#[repr(integer)]
但是您可以使用不安全代码读取判别器,如文档中所述:
#[repr(u32)]
enum Command {
Control(ControlSubcommand) = 0x00,
Temperature = 0x02,
Voltage = 0x04,
// ...
}
enum ControlSubcommand {
Status = 0x00,
DeviceType = 0x01,
// ....
}
fn get_discriminant(v: Command) -> u32 {
match v {
Command::Control(v) => v as u32,
// SAFETY: Because of `#[repr(u32)]`, the first field is the `u32` discriminant.
_ => unsafe { *(&v as *const Command as *const u32) },
}
}
评论
0赞
cafce25
10/8/2023
难道不是比 2 倍铸造更可取吗?(实际上不确定)*<*const Command>::cast(&v)
as
0赞
Chayim Friedman
10/8/2023
@cafce25 这是主观的(你的变体充满了印记)。虽然老实说,我没有考虑过这个选项。
0赞
rodrigo
10/9/2023
为了增加自行车棚,现在我更喜欢.(&v as *const Command).cast::<u32>().read()
评论
From<Command> for u32