Skip to content

Proc. macro for generating reference wrappers for Rust `enum` types.

License

Notifications You must be signed in to change notification settings

Robbepop/enum-ref

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Continuous Integration Documentation Crates.io
ci docs crates

#[derive(EnumRef)] and #[derive(EnumMut)]

This crate provides the #[derive(EnumRef)] and #[derive(EnumMut)] proc. macros that generate reference wrappers for Rust enum types. Deriving EnumRef or EnumMut will also implement the respective trait which allows to access and instantiate the generated reference wrappers.

Motivation

The generated reference types are a bit different from default references to Rust enum instances in that only the enum data is a reference while the enum discriminant remains inline. When there is a need for having enum reference wrappers this crate is especially useful for when a user has enum types with a big number of variants that would make it labor intense to maintain a mirroring between original enum type and reference wrapper.

This might even yield a performance improvement if users mostly are interested in querying the enum discriminant. However, performance is not the primary use case of this crate.

My personal motivation for this crate is to allow for more space efficient enum encodings. Usually enum instances are encoded with an aligned discriminant and all variants share the same size_of with the biggest enum variant. This has the downside that the default Rust enum encoding potentially wastes a lot of space. When trying to encode Rust enum instances space-efficiently we still want to access the encoded enum instances, however we cannot use normal references to them since those references assume the aligned enum encoding which won't be the case. This is where our new reference wrapper types come into play since we can use them for our new encoding.

Usage

Below we demonstrate how to use the proc. macros provided by this crate.

#[derive(EnumRef, EnumMut)]
#[repr(u8)] // Rust requires this for `B = 42`
enum Test {
    A,
    B = 42,
    C(i32),
    D(i32, i64),
    E { a: i32 },
    F { a: i32, b: i64 },
}

// Access and name the generated `enum` reference wrapper types as follows:
type TestRef<'a> = <Test as EnumRef>::Ref<'a>;
type TestMut<'a> = <Test as EnumMut>::Mut<'a>;

// Creates reference wrappers of `enum` instances as follows:
let test = Test::C(42);
let test_ref: TestRef = <Test as EnumRef>::as_ref(&test);
match (&test, test_ref) {
    (Test::C(a0), TestRef::C(a1)) => assert_eq!(a0, a1),
    _ => panic!("something wen't wrong ..."),
}

Generated Code

The above #[derive(EnumRef)] for example will generate roughly the following Rust code:

const _: () = {
    #[derive(::core::fmt::Debug)]
    #[repr(u8)]
    pub enum TestRef<'__enum_ref_lt> {
        A,
        B = 42,
        C(&'__enum_ref_lt i32),
        D(&'__enum_ref_lt i32, &'__enum_ref_lt i64),
        E {
            a: &'__enum_ref_lt i32,
        },
        F {
            a: &'__enum_ref_lt i32,
            b: &'__enum_ref_lt i64,
        },
    }

    impl ::enum_ref::EnumRef for Test {
        type Ref<'__enum_ref_lt> where Self: '__enum_ref_lt =
                TestRef<'__enum_ref_lt> where Self: '__enum_ref_lt;
        fn as_ref(&self) -> <Self as ::enum_ref::EnumRef>::Ref<'_> {
            type __enum_ref_EnumRef_Ref<'__enum_ref_lt> =
                <Test as ::enum_ref::EnumRef>::Ref<'__enum_ref_lt>;
            match self {
                Self::A => __enum_ref_EnumRef_Ref::A,
                Self::B => __enum_ref_EnumRef_Ref::B,
                Self::C(_0) => __enum_ref_EnumRef_Ref::C(_0),
                Self::D(_0, _1) => __enum_ref_EnumRef_Ref::D(_0, _1),
                Self::E { a } => __enum_ref_EnumRef_Ref::E { a },
                Self::F { a, b } => __enum_ref_EnumRef_Ref::F { a, b },
            }
        }
    }
};

About

Proc. macro for generating reference wrappers for Rust `enum` types.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages