huyubiao
huyubiao

Reputation: 21

How to Convert C Enum to Rust Enum and Determine the Size

The enumeration definitions in C are as follows:

    enum {
        VIRTUALIZATION_NONE = 0,

        VIRTUALIZATION_VM_FIRST,
        VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST,
        VIRTUALIZATION_AMAZON,
        VIRTUALIZATION_QEMU,
        VIRTUALIZATION_BOCHS,
        VIRTUALIZATION_XEN,
        VIRTUALIZATION_UML,
        VIRTUALIZATION_VMWARE,
        VIRTUALIZATION_ORACLE,
        VIRTUALIZATION_MICROSOFT,
        VIRTUALIZATION_ZVM,
        VIRTUALIZATION_PARALLELS,
        VIRTUALIZATION_BHYVE,
        VIRTUALIZATION_QNX,
        VIRTUALIZATION_ACRN,
        VIRTUALIZATION_POWERVM,
        VIRTUALIZATION_VM_OTHER,
        VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER,

        VIRTUALIZATION_CONTAINER_FIRST,
        VIRTUALIZATION_SYSTEMD_NSPAWN = VIRTUALIZATION_CONTAINER_FIRST,
        VIRTUALIZATION_LXC_LIBVIRT,
        VIRTUALIZATION_LXC,
        VIRTUALIZATION_OPENVZ,
        VIRTUALIZATION_DOCKER,
        VIRTUALIZATION_PODMAN,
        VIRTUALIZATION_RKT,
        VIRTUALIZATION_WSL,
        VIRTUALIZATION_PROOT,
        VIRTUALIZATION_POUCH,
        VIRTUALIZATION_CONTAINER_OTHER,
        VIRTUALIZATION_CONTAINER_LAST = VIRTUALIZATION_CONTAINER_OTHER,

        _VIRTUALIZATION_MAX,
        _VIRTUALIZATION_INVALID = -EINVAL,
};

How do I convert this to Rust and size the enumeration values? Because I find that Rust doesn't seem to be able to make a greater than or equal to judgment.

Upvotes: 0

Views: 1007

Answers (1)

PauMAVA
PauMAVA

Reputation: 1243

In order to achieve this you will need to use:

  • Tag values
  • Implement constants
  • PartialEq and PartialOrd traits.

Tag values

Rust enums can have a tag value such as:

enum Virtualization {
        VirtualizationNone = 0,
        VirtualizationVMFirst = 1,
        VirtualizationAmazon = 2,
        VirtualizationQEMU = 3,
        ...
        VirtualizationInvalid = -22
}

Implement Constants

A problem will occur for variants such as VIRTUALIZATION_KVM = VIRTUALIZATION_VM_FIRST as in rust two enum variants cannot have the same tag value.

error[E0081]: discriminant value `1` already exists
 --> src/main.rs:5:22
  |
4 |     VirtualizationVMFirst = 1,
  |                             - first use of `1`
5 |     VirtualizationKVM = 1,
  |                         ^ enum already has `1`

In order to solve this, you can use impl constants for the repeated values:

#[allow(non_upper_case_globals)]
impl Virtualization {
    pub const VirtualizationKVM: Self = Self::VirtualizationVMFirst;
    pub const VirtualizationVMLast: Self = Self::VirtualizationVMOther;
    ...
}

Comparison traits

Finally, in order to compare the tagged rust constants, you can derive implements for PartialEq and PartialOrd:

#[derive(PartialEq, PartialOrd)]
enum Virtualization {
    ...
}

Now you can compare all the enum variants and implement constants. For example:

fn main() {
    println!("Virtualization::VirtualizationNone < Virtualization::VirtualizationVMFirst {}", (Virtualization::VirtualizationNone < Virtualization::VirtualizationVMFirst));
    println!("Virtualization::VirtualizationNone > Virtualization::VirtualizationVMFirst {}", (Virtualization::VirtualizationNone > Virtualization::VirtualizationVMFirst));
}

// Virtualization::VirtualizationNone < Virtualization::VirtualizationVMFirst true
// Virtualization::VirtualizationNone > Virtualization::VirtualizationVMFirst false

Upvotes: 2

Related Questions