Enums 如何查找枚举变量的参数数?
我有一个枚举,它表示8080处理器上所有可能的指令。一条指令的长度可以是1、2或3字节,这取决于它是否有与其相关的信息以及有多少信息。例如:Enums 如何查找枚举变量的参数数?,enums,rust,Enums,Rust,我有一个枚举,它表示8080处理器上所有可能的指令。一条指令的长度可以是1、2或3字节,这取决于它是否有与其相关的信息以及有多少信息。例如: #[allow(non_camel_case_types)] enum Instruction { None, NOP, LXI_B_D16(u8, u8), STAX_B, INX_B, MVI_B_D8(u8), MVI_C_D8(u8), RRC, LXI_D_D16(u8, u
#[allow(non_camel_case_types)]
enum Instruction {
None,
NOP,
LXI_B_D16(u8, u8),
STAX_B,
INX_B,
MVI_B_D8(u8),
MVI_C_D8(u8),
RRC,
LXI_D_D16(u8, u8),
MVI_D_D8(u8),
RAL,
DCR_E,
MVI_E_D8(u8),
LXI_H_D16(u8, u8),
SHLD(u16),
LHLD(u16),
// ...
}
在为指令分配内存地址时,我通过二进制文件逐个指令迭代,使用每条指令的长度来确保循环不会在指令中途到达,并给我带来垃圾。我使用一个巨大的匹配表达式执行此操作,该表达式返回一个包含正确指令及其长度的元组:
match value {
0x00 => (Instruction::NOP, 1),
0x01 => (Instruction::LXI_B_D16(d1, d2), 3),
0x02 => (Instruction::STAX_B, 1),
0x05 => (Instruction::DCR_B, 1),
0x06 => (Instruction::MVI_B_D8(d1), 2),
0x07 => (Instruction::RLC, 1),
0x0e => (Instruction::MVI_C_D8(d1), 2),
0x0f => (Instruction::RRC, 1),
0x11 => (Instruction::LXI_D_D16(d1, d2), 3),
0x19 => (Instruction::DAD_D, 1),
// ...
}
这很难看,但我不想将这个长度数字关联到类型中,因为只有在解析文件时,它才真正重要
看起来我应该能够从变体的形状推断出指令的长度。任何没有参数的都是长度1,任何有一个u8参数的都是长度2,任何有一个u16或两个u8参数的都是长度3
我还没能想出如何通过编程得到这个形状。例如,我不能像调用数组或向量那样调用len()
我不认为这是的重复,因为我不是在寻找一种方法来获取枚举中变量的数量,而是任何单个变量的参数数量。如注释中所述,您可以编写一个宏来为自己编写代码 出于懒惰的考虑,我将枚举定义简化为始终使用括号。这不是必需的,只是简化了我的工作 一旦宏解析了枚举,我们就可以生成一个impl块,其中包含一个匹配每个变量的函数。我们将每个变量的参数传递给一个内部宏,该宏为我们执行计数。此函数返回每个变量中的元素数:
macro_rules! instructions {
(enum $ename:ident {
$($vname:ident ( $($vty: ty),* )),*
}) => {
enum $ename {
$($vname ( $($vty),* )),*
}
impl $ename {
fn len(&self) -> usize {
match self {
$($ename::$vname(..) => instructions!(@count ($($vty),*))),*
}
}
}
};
(@count ()) => (0);
(@count ($a:ty)) => (1);
(@count ($a:ty, $b:ty)) => (2);
(@count ($a:ty, $b:ty, $c:ty)) => (3);
}
instructions! {
enum Instruction {
None(),
One(u8),
Two(u8, u8),
Three(u8, u8, u8)
}
}
fn main() {
println!("{}", Instruction::None().len());
println!("{}", Instruction::One(1).len());
println!("{}", Instruction::Two(1,2).len());
println!("{}", Instruction::Three(1,2,3).len());
}
您也可以编写具有相同功能的
另见: