如何将C虚拟化枚举转换为Rust枚举并处理值范围判断
C虚拟化枚举转Rust实现及问题解决
1. 转换为Rust枚举
C枚举本质是整数常量集合,Rust中可通过#[repr(i32)]指定底层类型匹配C的int,同时处理C中的别名(如VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST)——Rust枚举变体不支持直接别名,可通过关联常量补充,再定义类型安全的枚举:
use std::os::raw::c_int; // 定义与C一致的整数常量,处理别名 const VIRTUALIZATION_NONE: i32 = 0; const VIRTUALIZATION_VM_FIRST: i32 = 1; const VIRTUALIZATION_KVM: i32 = VIRTUALIZATION_VM_FIRST; const VIRTUALIZATION_AMAZON: i32 = 2; const VIRTUALIZATION_QEMU: i32 = 3; const VIRTUALIZATION_BOCHS: i32 = 4; const VIRTUALIZATION_XEN: i32 = 5; const VIRTUALIZATION_UML: i32 = 6; const VIRTUALIZATION_VMWARE: i32 = 7; const VIRTUALIZATION_ORACLE: i32 = 8; const VIRTUALIZATION_MICROSOFT: i32 = 9; const VIRTUALIZATION_ZVM: i32 = 10; const VIRTUALIZATION_PARALLELS: i32 = 11; const VIRTUALIZATION_BHYVE: i32 = 12; const VIRTUALIZATION_QNX: i32 = 13; const VIRTUALIZATION_ACRN: i32 = 14; const VIRTUALIZATION_POWERVM: i32 = 15; const VIRTUALIZATION_VM_OTHER: i32 = 16; const VIRTUALIZATION_VM_LAST: i32 = VIRTUALIZATION_VM_OTHER; const VIRTUALIZATION_CONTAINER_FIRST: i32 = 17; const VIRTUALIZATION_SYSTEMD_NSPAWN: i32 = VIRTUALIZATION_CONTAINER_FIRST; const VIRTUALIZATION_LXC_LIBVIRT: i32 = 18; const VIRTUALIZATION_LXC: i32 = 19; const VIRTUALIZATION_OPENVZ: i32 = 20; const VIRTUALIZATION_DOCKER: i32 = 21; const VIRTUALIZATION_PODMAN: i32 = 22; const VIRTUALIZATION_RKT: i32 = 23; const VIRTUALIZATION_WSL: i32 = 24; const VIRTUALIZATION_PROOT: i32 = 25; const VIRTUALIZATION_POUCH: i32 = 26; const VIRTUALIZATION_CONTAINER_OTHER: i32 = 27; const VIRTUALIZATION_CONTAINER_LAST: i32 = VIRTUALIZATION_CONTAINER_OTHER; const _VIRTUALIZATION_MAX: i32 = 28; const _VIRTUALIZATION_INVALID: i32 = -22; // C中EINVAL的标准值为-22 // 类型安全的Rust枚举,对应有效变体 #[repr(i32)] #[non_exhaustive] enum Virtualization { None = VIRTUALIZATION_NONE, Kvm = VIRTUALIZATION_KVM, Amazon = VIRTUALIZATION_AMAZON, Qemu = VIRTUALIZATION_QEMU, Bochs = VIRTUALIZATION_BOCHS, Xen = VIRTUALIZATION_XEN, Uml = VIRTUALIZATION_UML, Vmware = VIRTUALIZATION_VMWARE, Oracle = VIRTUALIZATION_ORACLE, Microsoft = VIRTUALIZATION_MICROSOFT, Zvm = VIRTUALIZATION_ZVM, Parallels = VIRTUALIZATION_PARALLELS, Bhyve = VIRTUALIZATION_BHYVE, Qnx = VIRTUALIZATION_QNX, Acrn = VIRTUALIZATION_ACRN, Powervm = VIRTUALIZATION_POWERVM, VmOther = VIRTUALIZATION_VM_OTHER, SystemdNspawn = VIRTUALIZATION_SYSTEMD_NSPAWN, LxcLibvirt = VIRTUALIZATION_LXC_LIBVIRT, Lxc = VIRTUALIZATION_LXC, Openvz = VIRTUALIZATION_OPENVZ, Docker = VIRTUALIZATION_DOCKER, Podman = VIRTUALIZATION_PODMAN, Rkt = VIRTUALIZATION_RKT, Wsl = VIRTUALIZATION_WSL, Proot = VIRTUALIZATION_PROOT, Pouch = VIRTUALIZATION_POUCH, ContainerOther = VIRTUALIZATION_CONTAINER_OTHER, } // 实现从i32到枚举的转换,处理无效值 impl TryFrom<i32> for Virtualization { type Error = (); fn try_from(value: i32) -> Result<Self, Self::Error> { match value { VIRTUALIZATION_NONE => Ok(Self::None), VIRTUALIZATION_KVM => Ok(Self::Kvm), VIRTUALIZATION_AMAZON => Ok(Self::Amazon), VIRTUALIZATION_QEMU => Ok(Self::Qemu), VIRTUALIZATION_BOCHS => Ok(Self::Bochs), VIRTUALIZATION_XEN => Ok(Self::Xen), VIRTUALIZATION_UML => Ok(Self::Uml), VIRTUALIZATION_VMWARE => Ok(Self::Vmware), VIRTUALIZATION_ORACLE => Ok(Self::Oracle), VIRTUALIZATION_MICROSOFT => Ok(Self::Microsoft), VIRTUALIZATION_ZVM => Ok(Self::Zvm), VIRTUALIZATION_PARALLELS => Ok(Self::Parallels), VIRTUALIZATION_BHYVE => Ok(Self::Bhyve), VIRTUALIZATION_QNX => Ok(Self::Qnx), VIRTUALIZATION_ACRN => Ok(Self::Acrn), VIRTUALIZATION_POWERVM => Ok(Self::Powervm), VIRTUALIZATION_VM_OTHER => Ok(Self::VmOther), VIRTUALIZATION_SYSTEMD_NSPAWN => Ok(Self::SystemdNspawn), VIRTUALIZATION_LXC_LIBVIRT => Ok(Self::LxcLibvirt), VIRTUALIZATION_LXC => Ok(Self::Lxc), VIRTUALIZATION_OPENVZ => Ok(Self::Openvz), VIRTUALIZATION_DOCKER => Ok(Self::Docker), VIRTUALIZATION_PODMAN => Ok(Self::Podman), VIRTUALIZATION_RKT => Ok(Self::Rkt), VIRTUALIZATION_WSL => Ok(Self::Wsl), VIRTUALIZATION_PROOT => Ok(Self::Proot), VIRTUALIZATION_POUCH => Ok(Self::Pouch), VIRTUALIZATION_CONTAINER_OTHER => Ok(Self::ContainerOther), _ => Err(()), } } }
2. 枚举值范围确定
根据C枚举的定义,各区间范围如下:
- 无虚拟化:
0(仅VIRTUALIZATION_NONE) - VM类虚拟化:
1(VIRTUALIZATION_VM_FIRST)到16(VIRTUALIZATION_VM_LAST) - 容器类虚拟化:
17(VIRTUALIZATION_CONTAINER_FIRST)到27(VIRTUALIZATION_CONTAINER_LAST) - 无效值:
-22(_VIRTUALIZATION_INVALID) - 最大值标记:
28(_VIRTUALIZATION_MAX,表示有效枚举值的总数量)
3. 解决枚举无法直接比较大小的问题
Rust枚举默认未实现PartialOrd/Ord trait,无法直接使用>=/<=比较,有两种实用解决方式:
方式一:转换为底层整数比较
利用#[repr(i32)]的特性,将枚举转为i32后再比较:
let virt = Virtualization::Kvm; let val = virt as i32; if val >= VIRTUALIZATION_VM_FIRST && val <= VIRTUALIZATION_VM_LAST { println!("属于VM类虚拟化"); }
方式二:手动实现比较trait
如果需要直接对枚举变体比较,可为枚举实现PartialOrd和Ord:
use std::cmp::Ordering; impl PartialOrd for Virtualization { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) } } impl Ord for Virtualization { fn cmp(&self, other: &Self) -> Ordering { let self_val = *self as i32; let other_val = *other as i32; self_val.cmp(&other_val) } } impl PartialEq for Virtualization { fn eq(&self, other: &Self) -> bool { (*self as i32) == (*other as i32) } } impl Eq for Virtualization {}
实现后即可直接用>=/<=比较枚举变体:
if Virtualization::Kvm >= Virtualization::None { // 执行逻辑 }
方式三:添加范围判断方法
也可以给枚举添加封装好的方法,直接判断所属类别:
impl Virtualization { pub fn is_vm(&self) -> bool { let val = *self as i32; val >= VIRTUALIZATION_VM_FIRST && val <= VIRTUALIZATION_VM_LAST } pub fn is_container(&self) -> bool { let val = *self as i32; val >= VIRTUALIZATION_CONTAINER_FIRST && val <= VIRTUALIZATION_CONTAINER_LAST } }
内容的提问来源于stack exchange,提问作者huyubiao
相关产品推荐
相关产品推荐

