Crate encap_enum

Source
Expand description

A type-safe encapsulated enum useful for interacting with C bitmasks, abbreviating a group of constants with the same type, and an enumerator instance that can be safely assigned too regardless of whether it is in the enum.

Internally encap_enum uses a struct, therefore to access the value of a variant use .raw.

Terms such as enum, and variant are used throughout the doc even though the internal representation can be different, and the reason is because rust’s canonical enum is used internally when omitting explicit declarations of data. In other words it acts like an enum, yet it is composed of many different constructs.

§Example

The encap_enum! allows for bit flags and other common manipulations of data. When the enum’s type is omitted such as the example below, the type defaults to isize.

encap_enum!{
    enum Flags {
        A = 1 + 4 + 8,
        B = 2,
        C = A | B, // C = 15
    }
}

The flags can be assigned to constants outside the enum since all the enum members are internally constants:

const VALUE: isize = MoreFlags::Omega.raw;
const OTHER: MoreFlags = MoreFlags::Sigma;
encap_enum!{
    enum MoreFlags {
        Omega = 1,
        Sigma = 2,
        Delta = 3,
        Charlie = (-Delta), // Charlie = -3
    }
}

Constants outside the enum can be used to initialize variants:

const VALUE: i32 = 56;
const OTHER: i32 = 72;
encap_enum!{
    enum TakenFlags: i32 {
        Omega = (enum TakenFlags) VALUE, // Omega = 56
        Sigma = (enum TakenFlags) OTHER, // Sigma = 72
        Delta = (enum TakenFlags) VALUE + (enum TakenFlags) OTHER, // Delta = 128
        Negative = (enum TakenFlags) -VALUE, // Negative = -56
    }
}

The enum_encap! macro also supports enumeration like a normal fieldless enum by tapping into rust’s own enum. A name must be provided to ensure namespace collision does not occur due to the limitations of interacting with rust’s enum

#[macro_use]
extern crate encap_enum;

encap_enum!{
    pub mod flag {
        pub enum OtherFlags: pub isize {
            Alpha,
            Beta,
            Charlie,
        }
    }
}
fn main() {
    println!("{}", flag::OtherFlags::Alpha.raw);
}

The internal rust enum, which the struct constants draws values from, is under the namespace you set.

§Visibility

The visibility for both the enum and variants can be changed:

encap_enum!{
    pub mod flag {
        pub enum PublicFlags: pub(in crate) u32 {
            Alpha,
            Beta,
            Charlie,
        }
    }
}

§Attributes

Attributes can be used pretty much anywhere in the macro except right under the declaration (See Corner Cases section at the bottom for more details).

§Traits

§Derived Traits

The following traits are derived:

  • Debug
  • Copy
  • Clone
  • PartialEq
  • Eq
  • PartialOrd
  • Hash

§Operators

The following operators are implemented:

  • BitOr
  • Add
  • BitAnd
  • BitXor
  • Div
  • Mul
  • Shl
  • Shr
  • Sub
  • Rem
  • Not
  • Neg
  • From
  • AddAssign
  • SubAssign
  • MulAssign
  • BitAndAssign
  • BitOrAssign
  • BitXorAssign
  • DivAssign
  • RemAssign

§Methods

  • iter() -> Iter: An iterator over all the variants.
  • get_bit(bit:u8)->bool: query the state of the specified bit.
    • Only available if inner visibility is public to the module using it.
  • new(data: [type]): initialize with arbitrary data.
    • Only available if inner visibility is public to the module using it.

§Corner Cases

Attributes cannot be placed before the first variant and there are no plans to fix this.

encap_enum!{    
    enum Flag: u32 {
        /// This doc comment causes errors.
        Gamma = -54,
    }
}

The #[repr(C)] attribute will work and make the enum more ffi compatible, however #[repr(u8)], #[repr(u16)], etc. will not compile because the internal representation that it will apply to is a struct. The equivalent of #[repr(u32)], which would apply on an enum would look like this on an encap_enum! declaration:

encap_enum!{
    #[repr(C)]
    enum Flag: u32 {
        // variants here.
    }
}

Macros§