enum_ref_macro

Derive Macro EnumRef

Source
#[derive(EnumRef)]
Expand description

Proc. macro to derive EnumRef trait for the Rust enum.

This generates a new enum that mirrors all variants of the original enum type but wraps all variant field in a shared reference. Furthermore it implement the EnumRef trait for the original enum in order to make the generated enum accessible.

ยงExample

use enum_ref::EnumRef;

#[derive(EnumRef)]
#[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` as follows:
type TestRef<'a> = <Test as EnumRef>::Ref<'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 ..."),
}

The #[derive(EnumRef)] in the above 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 },
            }
        }
    }
};