enum_ref_macro/
lib.rs

1use proc_macro::TokenStream;
2use syn::{parse_macro_input, DeriveInput};
3
4#[macro_use]
5mod error;
6mod derive;
7mod utils;
8
9/// Proc. macro to derive [`EnumRef`] trait for the Rust `enum`.
10///
11/// This generates a new `enum` that mirrors all variants of the
12/// original `enum` type but wraps all variant field in a shared
13/// reference.
14/// Furthermore it implement the [`EnumRef`] trait for the original
15/// `enum` in order to make the generated `enum` accessible.
16///
17/// # Example
18///
19/// ```
20/// use enum_ref::EnumRef;
21///
22/// #[derive(EnumRef)]
23/// #[repr(u8)] // Rust requires this for `B = 42`
24/// enum Test {
25///     A,
26///     B = 42,
27///     C(i32),
28///     D(i32, i64),
29///     E { a: i32 },
30///     F { a: i32, b: i64 },
31/// }
32///
33/// // Access and name the generated `enum` as follows:
34/// type TestRef<'a> = <Test as EnumRef>::Ref<'a>;
35///
36/// // Creates reference wrappers of `enum` instances as follows:
37/// let test = Test::C(42);
38/// let test_ref: TestRef = <Test as EnumRef>::as_ref(&test);
39/// match (&test, test_ref) {
40///     (Test::C(a0), TestRef::C(a1)) => assert_eq!(a0, a1),
41///     _ => panic!("something wen't wrong ..."),
42/// }
43/// ```
44///
45/// The `#[derive(EnumRef)]` in the above example will generate roughly the following Rust code.
46///
47/// ```
48/// # #[repr(u8)] // Rust requires this for `B = 42`
49/// # enum Test {
50/// #     A,
51/// #     B = 42,
52/// #     C(i32),
53/// #     D(i32, i64),
54/// #     E { a: i32 },
55/// #     F { a: i32, b: i64 },
56/// # }
57/// #
58/// const _: () = {
59///     #[derive(::core::fmt::Debug)]
60///     #[repr(u8)]
61///     pub enum TestRef<'__enum_ref_lt> {
62///         A,
63///         B = 42,
64///         C(&'__enum_ref_lt i32),
65///         D(&'__enum_ref_lt i32, &'__enum_ref_lt i64),
66///         E {
67///             a: &'__enum_ref_lt i32,
68///         },
69///         F {
70///             a: &'__enum_ref_lt i32,
71///             b: &'__enum_ref_lt i64,
72///         },
73///     }
74///
75///     impl ::enum_ref::EnumRef for Test {
76///         type Ref<'__enum_ref_lt> where Self: '__enum_ref_lt =
77///                 TestRef<'__enum_ref_lt> where Self: '__enum_ref_lt;
78///         fn as_ref(&self) -> <Self as ::enum_ref::EnumRef>::Ref<'_> {
79///             type __enum_ref_EnumRef_Ref<'__enum_ref_lt> =
80///                 <Test as ::enum_ref::EnumRef>::Ref<'__enum_ref_lt>;
81///             match self {
82///                 Self::A => __enum_ref_EnumRef_Ref::A,
83///                 Self::B => __enum_ref_EnumRef_Ref::B,
84///                 Self::C(_0) => __enum_ref_EnumRef_Ref::C(_0),
85///                 Self::D(_0, _1) => __enum_ref_EnumRef_Ref::D(_0, _1),
86///                 Self::E { a } => __enum_ref_EnumRef_Ref::E { a },
87///                 Self::F { a, b } => __enum_ref_EnumRef_Ref::F { a, b },
88///             }
89///         }
90///     }
91/// };
92/// ```
93#[proc_macro_derive(EnumRef)]
94pub fn enum_ref(input: TokenStream) -> TokenStream {
95    derive::enum_ref(parse_macro_input!(input as DeriveInput)).into()
96}
97
98/// Proc. macro to derive [`EnumMut`] trait for the Rust `enum`.
99///
100/// This generates a new `enum` that mirrors all variants of the
101/// original `enum` type but wraps all variant field in an exclusive
102/// reference.
103/// Furthermore it implement the [`EnumMut`] trait for the original
104/// `enum` in order to make the generated `enum` accessible.
105///
106/// # Example
107///
108/// ```
109/// use enum_ref::EnumMut;
110///
111/// # #[derive(Clone)]
112/// #[derive(EnumMut)]
113/// #[repr(u8)] // Rust requires this for `B = 42`
114/// enum Test {
115///     A,
116///     B = 42,
117///     C(i32),
118///     D(i32, i64),
119///     E { a: i32 },
120///     F { a: i32, b: i64 },
121/// }
122///
123/// // Access and name the generated `enum` as follows:
124/// type TestMut<'a> = <Test as EnumMut>::Mut<'a>;
125///
126/// // Creates reference wrappers of `enum` instances as follows:
127/// let mut test0 = Test::C(42);
128/// let mut test1 = test0.clone();
129/// let test_ref: TestMut = <Test as EnumMut>::as_mut(&mut test0);
130/// match (&mut test1, test_ref) {
131///     (Test::C(a0), TestMut::C(a1)) => assert_eq!(a0, a1),
132///     _ => panic!("something wen't wrong ..."),
133/// }
134/// ```
135///
136/// The `#[derive(EnumMut)]` in the above example will generate roughly the following Rust code.
137///
138/// ```
139/// # #[repr(u8)] // Rust requires this for `B = 42`
140/// # enum Test {
141/// #     A,
142/// #     B = 42,
143/// #     C(i32),
144/// #     D(i32, i64),
145/// #     E { a: i32 },
146/// #     F { a: i32, b: i64 },
147/// # }
148/// #
149/// const _: () = {
150///     #[derive(::core::fmt::Debug)]
151///     #[repr(u8)]
152///     pub enum TestMut<'__enum_ref_lt> {
153///         A,
154///         B = 42,
155///         C(&'__enum_ref_lt mut i32),
156///         D(&'__enum_ref_lt mut i32, &'__enum_ref_lt mut i64),
157///         E {
158///             a: &'__enum_ref_lt mut i32,
159///         },
160///         F {
161///             a: &'__enum_ref_lt mut i32,
162///             b: &'__enum_ref_lt mut i64,
163///         },
164///     }
165///
166///     impl ::enum_ref::EnumMut for Test {
167///         type Mut<'__enum_ref_lt> where Self: '__enum_ref_lt =
168///                 TestMut<'__enum_ref_lt> where Self: '__enum_ref_lt;
169///         fn as_mut(&mut self) -> <Self as ::enum_ref::EnumMut>::Mut<'_> {
170///             type __enum_ref_EnumMut_Mut<'__enum_ref_lt> =
171///                 <Test as ::enum_ref::EnumMut>::Mut<'__enum_ref_lt>;
172///             match self {
173///                 Self::A => __enum_ref_EnumMut_Mut::A,
174///                 Self::B => __enum_ref_EnumMut_Mut::B,
175///                 Self::C(_0) => __enum_ref_EnumMut_Mut::C(_0),
176///                 Self::D(_0, _1) => __enum_ref_EnumMut_Mut::D(_0, _1),
177///                 Self::E { a } => __enum_ref_EnumMut_Mut::E { a },
178///                 Self::F { a, b } => __enum_ref_EnumMut_Mut::F { a, b },
179///             }
180///         }
181///     }
182/// };
183/// ```
184#[proc_macro_derive(EnumMut)]
185pub fn enum_mut(input: TokenStream) -> TokenStream {
186    derive::enum_mut(parse_macro_input!(input as DeriveInput)).into()
187}