Expand description

A simple macro to define FFI-safe enums that support unknown values.

Rust’s enum types trigger undefined behavior when they are assigned unknown discriminant values (e.g., through a pointer cast or transmutation). While this enables useful complier optimizations, it also means that enums are not safe for use in FFI, since C treats enums as integral types that can take any value within range of the underlying integer type.

This crate offers an alternative kind of enumeration which is more similar to C. Enumerations defined with the c_enum macro are simple wrappers for an integer type. Known variants are defined as constants, and can be associated with their names defined in code (e.g., for Debug output), but unknown values are fully supported. Since they have transparent representations, they do not trigger undefined behavior when transmuting from arbitrary values (as long as you use a built-in integer type) and are safe to use in FFI structs and functions.

c_enum! {
    pub enum Example(u16) {
        Foo,
        Bar = 2,
        Quux,
        Baz = 0xffff,
    }
}

// Known value
let x = Example::Bar;
assert_eq!(x, Example::from(2));
assert_eq!(u16::from(x), 2);
assert_eq!(x.name(), Some("Bar"));

// Omitted variant values assigned in sequence
assert_eq!(u16::from(Example::Foo), 0);
assert_eq!(u16::from(Example::Quux), 3);

// Unknown value
let y = Example::from(0xcafe);
assert_eq!(u16::from(y), 0xcafe);
assert_eq!(y.name(), None);

// Use in an FFI-safe struct
#[repr(C)]
#[derive(Debug, PartialEq)]
pub struct Quux(Example, u8, u8);
unsafe {
    assert_eq!(
        core::mem::transmute::<[u8; 4], Quux>([0xff, 0xff, 0x8c, 0xf2]),
        Quux(Example::Baz, 0x8c, 0xf2),
    );
    assert_eq!(
        core::mem::transmute::<[u8; 4], Quux>([0xab, 0xab, 0x05, 0x3b]),
        Quux(Example::from(0xabab), 0x05, 0x3b),
    );
}

For lots more examples, see the Tartan OS project that this crate was spun off from. This macro also works well in combination with the Tartan Bitfield crate.

Macros

Define a struct that wraps an integer type and acts like a C-style enum.

Traits

Trait implemented by all c_enum types.