Crate enum_ptr

source ·
Expand description

Examples

use enum_ptr::{Aligned, Compact, EnumPtr, ShiftUsize, Unit};

#[derive(EnumPtr)]
#[repr(C, usize)] // required
enum Foo<'a, T: Aligned> {
    A(T),             // supports any `T: Aligned`
    B(&'a u64),
    C(Unit),          // use `Unit` for unit variants
    D(ShiftUsize<3>), // you can even use non-pointers
    E(Box<i64>),
}

let compact_foo: Compact<_> = Foo::A(&1u64).into();
let original_foo: Foo<_> = compact_foo.into();

Usage

This crate provides multiple APIs with different flavors.

Flavor 1: CompactCopy

If your enum type is Copy (e.g., consists of only &Ts), you can convert it to CompactCopy. Each time you need to use it, just copy and extract it. Easy-peasy!

Sadly, due to language limitations, we cannot combine Compact and CompactCopy into one type.

Flavor 2: get_ref & get_mut

If your enum type is not Copy, and you happens to only have references to the compact value, you can use get_ref and get_mut to get references to the object that it points to.

For example, if you hold a compact Box<T>, you can use these APIs to access &T and &mut T. Since there’s no Box<T> in the memory (but only its compact form), we cannot create &Box<T> and &mut Box<T>. Check FieldDeref and FieldDerefMut for more details.

Flavor 3: borrow & borrow_mut

get_ref and get_mut can be troublesome if you want to deal with multiple variants at together. In that case, you can use borrow and borrow_mut. They will return derived reference types that you can match.

Flavor 4: map_ref & map_mut (legacy)

map_ref and map_mut will create temporary objects that drop as soon as your closure ends. They can sometimes be useful if you don’t want to derive reference objects.

Extension

All important traits are public. You can implement them for your own types.

Limitations

Suppose we are deriving from Foo, then

  • Foo must have a #[repr(C, usize)].
    • According to the RFC and the Rust Reference, #[repr(C, usize)] guarantees the memory layout and discriminant values. Thus, we can safely transmute between two representations.
  • Each variant of Foo must have exactly one field.
    • Unit variants are not allowed due to performance concerns.
    • If you need a unit variant, use Unit.
  • Each variant of Foo must have enough alignment to store the tag.
    • Currently this crate cannot utilize high bits.

Any violation of these rules will either trigger a compilation error or a run-time panic. Passed assertions will be optimized out. That is to say, rule checks won’t affect the run-time performance.

Features

  • alloc (default)Box, Rc and Arc support

Macros

Structs

Traits

Derive Macros