enumcapsulate_macros/
lib.rs

1use proc_macro::TokenStream;
2use syn::parse_macro_input;
3
4use crate::utils::tokenstream;
5
6mod config;
7mod enum_deriver;
8mod type_visitor;
9mod utils;
10
11use self::{config::*, enum_deriver::*, type_visitor::*, utils::*};
12
13/// Derive macro generating an impl of the trait `From<T>`.
14///
15/// It generates an impl for each of the enum's
16/// newtype variants, where `Inner` is the variant's field type
17/// and `Outer` is the enclosing enum's type.
18///
19/// ```ignore
20/// struct Inner;
21///
22/// enum Outer {
23///     Inner(Inner),
24///     // ...
25/// }
26///
27/// // The generated impls look something along these lines:
28///
29/// impl From<Inner> for Outer {
30///     fn from(inner: Inner) -> Self {
31///         Outer::Inner(inner)
32///     }
33/// }
34///
35/// // ...
36/// ```
37///
38#[proc_macro_derive(From, attributes(enumcapsulate))]
39pub fn derive_from(input: TokenStream) -> TokenStream {
40    let item = parse_macro_input!(input as syn::ItemEnum);
41
42    tokenstream(|| {
43        let deriver = EnumDeriver::from(item);
44        deriver.derive_from()
45    })
46}
47
48/// Derive macro generating an impl of the trait `TryFrom<T>`.
49///
50/// It generates an impl for each of the enum's newtype variants,
51/// where `Inner` is the variant's field type and `Outer`
52/// is the enclosing enum's type.
53///
54/// ```ignore
55/// struct Inner;
56///
57/// enum Outer {
58///     Inner(Inner),
59///     // ...
60/// }
61///
62/// // The generated impls look something along these lines:
63///
64/// impl TryFrom<Outer> for Inner {
65///     type Error = Outer;
66///
67///     fn try_from(outer: Outer) -> Result<Self, Self::Error> {
68///         match outer {
69///             Outer::Inner(inner) => Ok(inner),
70///             err => Err(err),
71///         }
72///     }
73/// }
74///
75/// // ...
76/// ```
77///
78/// Note: Despite the derive macro's name it's actually `TryFrom<T>`
79/// that's being derives, not `TryInto<T>`.
80/// But since the macro is derived on the enum the latter feels
81/// more appropriate as the derive's name.
82#[proc_macro_derive(TryInto, attributes(enumcapsulate))]
83pub fn derive_try_from(input: TokenStream) -> TokenStream {
84    let item = parse_macro_input!(input as syn::ItemEnum);
85
86    tokenstream(|| {
87        let deriver = EnumDeriver::from(item);
88        deriver.derive_try_into()
89    })
90}
91
92/// Derive macro generating an impl of the trait `FromVariant<T>`.
93///
94/// It generates an impl for each of the enum's
95/// newtype variants, where `Inner` is the variant's field type
96/// and `Outer` is the enclosing enum's type.
97///
98/// ```ignore
99/// # use enumcapsulate::FromVariant;
100/// #
101/// # struct Inner;
102///
103/// enum Outer {
104///     Inner(Inner),
105///     // ...
106/// }
107///
108/// // The generated impls look something along these lines:
109///
110/// impl FromVariant<Inner> for Outer {
111///     fn from_variant(inner: Inner) -> Self {
112///         Outer::Inner(inner)
113///     }
114/// }
115///
116/// // ...
117/// ```
118///
119#[proc_macro_derive(FromVariant, attributes(enumcapsulate))]
120pub fn derive_from_variant(input: TokenStream) -> TokenStream {
121    let item = parse_macro_input!(input as syn::ItemEnum);
122
123    tokenstream(|| {
124        let deriver = EnumDeriver::from(item);
125        deriver.derive_from_variant()
126    })
127}
128
129/// Derive macro generating an impl of the trait `FromVariant<T>`.
130///
131/// It generates an impl for each of the enum's
132/// newtype variants, where `Inner` is the variant's field type
133/// and `Outer` is the enclosing enum's type.
134///
135/// ```ignore
136/// # use enumcapsulate::AsVariant;
137///
138/// #[derive(Clone)]
139/// struct Inner;
140///
141/// enum Outer {
142///     Inner(Inner),
143///     // ...
144/// }
145///
146/// // The generated impls look something along these lines:
147///
148/// impl AsVariant<Inner> for Outer where Inner: Clone {
149///     fn as_variant(&self) -> Option<Inner> {
150///         match self {
151///             Outer::Inner(inner) => Some(inner.clone()),
152///             _ => None,
153///         }
154///     }
155/// }
156///
157/// // ...
158/// ```
159///
160#[proc_macro_derive(AsVariant, attributes(enumcapsulate))]
161pub fn derive_as_variant(input: TokenStream) -> TokenStream {
162    let item = parse_macro_input!(input as syn::ItemEnum);
163
164    tokenstream(|| {
165        let deriver = EnumDeriver::from(item);
166        deriver.derive_as_variant()
167    })
168}
169
170/// Derive macro generating an impl of the trait `FromVariant<T>`.
171///
172/// It generates an impl for each of the enum's
173/// newtype variants, where `Inner` is the variant's field type
174/// and `Outer` is the enclosing enum's type.
175///
176/// ```ignore
177/// # use enumcapsulate::AsVariantRef;
178///
179/// struct Inner;
180///
181/// enum Outer {
182///     Inner(Inner),
183///     // ...
184/// }
185///
186/// // The generated impls look something along these lines:
187///
188/// impl AsVariantRef<Inner> for Outer {
189///     fn as_variant_ref(&self) -> Option<&Inner> {
190///         match self {
191///             Outer::Inner(inner) => Some(inner),
192///             _ => None,
193///         }
194///     }
195/// }
196///
197/// // ...
198/// ```
199///
200#[proc_macro_derive(AsVariantRef, attributes(enumcapsulate))]
201pub fn derive_as_variant_ref(input: TokenStream) -> TokenStream {
202    let item = parse_macro_input!(input as syn::ItemEnum);
203
204    tokenstream(|| {
205        let deriver = EnumDeriver::from(item);
206        deriver.derive_as_variant_ref()
207    })
208}
209
210/// Derive macro generating an impl of the trait `From<T>`.
211///
212/// It generates an impl for each of the enum's
213/// newtype variants, where `Inner` is the variant's field type
214/// and `Outer` is the enclosing enum's type.
215///
216/// ```ignore
217/// # use enumcapsulate::AsVariantMut;
218///
219/// struct Inner;
220///
221/// enum Outer {
222///     Inner(Inner),
223///     // ...
224/// }
225///
226/// // The generated impls look something along these lines:
227///
228/// impl AsVariantMut<Inner> for Outer {
229///     fn as_variant_mut(&mut self) -> Option<&mut Inner> {
230///         match self {
231///             Outer::Inner(inner) => Some(inner),
232///             _ => None,
233///         }
234///     }
235/// }
236///
237/// // ...
238/// ```
239///
240#[proc_macro_derive(AsVariantMut, attributes(enumcapsulate))]
241pub fn derive_as_variant_mut(input: TokenStream) -> TokenStream {
242    let item = parse_macro_input!(input as syn::ItemEnum);
243
244    tokenstream(|| {
245        let deriver = EnumDeriver::from(item);
246        deriver.derive_as_variant_mut()
247    })
248}
249
250/// Derive macro generating an impl of the trait `IntoVariant<T>`.
251///
252/// It generates an impl for each of the enum's
253/// newtype variants, where `Inner` is the variant's field type
254/// and `Outer` is the enclosing enum's type.
255///
256/// ```ignore
257/// # use enumcapsulate::IntoVariant;
258///
259/// struct Inner;
260///
261/// enum Outer {
262///     Inner(Inner),
263///     // ...
264/// }
265///
266/// // The generated impls look something along these lines:
267///
268/// impl IntoVariant<Inner> for Outer {
269///     fn into_variant(self) -> Result<T, Self> {
270///         match self {
271///             Outer::Inner(inner) => Ok(inner),
272///             err => Err(err),
273///         }
274///     }
275/// }
276///
277/// // ...
278/// ```
279///
280/// Note: Despite the derive macro's name it's actually `TryFrom<T>`
281/// that's being derives, not `TryInto<T>`.
282/// But since the macro is derived on the enum the latter feels
283/// more appropriate as the derive's name.
284#[proc_macro_derive(IntoVariant, attributes(enumcapsulate))]
285pub fn derive_into_variant(input: TokenStream) -> TokenStream {
286    let item = parse_macro_input!(input as syn::ItemEnum);
287
288    tokenstream(|| {
289        let deriver = EnumDeriver::from(item);
290        deriver.derive_into_variant()
291    })
292}
293
294/// Derive macro generating an impl of the trait `VariantDowncast`.
295///
296/// ```ignore
297/// struct Inner;
298///
299/// enum Outer {
300///     Inner(Inner),
301///     // ...
302/// }
303///
304/// // The generated impl looks something along these lines:
305///
306/// impl VariantDowncast for Outer {}
307/// ```
308///
309#[proc_macro_derive(VariantDowncast, attributes(enumcapsulate))]
310pub fn derive_variant_downcast(input: TokenStream) -> TokenStream {
311    let item = parse_macro_input!(input as syn::ItemEnum);
312
313    tokenstream(|| {
314        let deriver = EnumDeriver::from(item);
315        deriver.derive_variant_downcast()
316    })
317}
318
319/// Derive macro generating an impl of the trait `VariantDiscriminant`.
320///
321/// ```ignore
322/// struct Inner;
323///
324/// enum Outer {
325///     Inner(Inner),
326///     // ...
327/// }
328///
329/// // The generated discriminant type looks something along these lines:
330///
331/// #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
332/// pub enum OuterDiscriminant {
333///     Inner,
334///     // ...
335/// }
336///
337/// // The generated impl looks something along these lines:
338///
339/// impl VariantDiscriminant for Outer {
340///     type Discriminant = OuterDiscriminant;
341///
342///     fn variant_discriminant(&self) -> Self::Discriminant {
343///         match self {
344///            Outer::Inner(_) => OuterDiscriminant::Inner,
345///            // ...
346///        }
347///     }
348/// }
349/// ```
350///
351#[proc_macro_derive(VariantDiscriminant, attributes(enumcapsulate))]
352pub fn derive_variant_discriminant(input: TokenStream) -> TokenStream {
353    let item = parse_macro_input!(input as syn::ItemEnum);
354
355    tokenstream(|| {
356        let deriver = EnumDeriver::from(item);
357        deriver.derive_variant_discriminant()
358    })
359}
360
361/// Umbrella derive macro.
362///
363/// The following use of the `Encapsulate` umbrella derive macro:
364///
365/// ```ignore
366/// use enumcapsulate::Encapsulate;
367///
368/// #[derive(Encapsulate)
369/// enum Enum {
370///     // ...
371/// }
372/// ```
373///
374/// is equivalent to the following:
375///
376/// ```ignore
377/// // ...
378///
379/// #[derive(
380///     From,
381///     TryInto,
382///     FromVariant,
383///     IntoVariant,
384///     AsVariant,
385///     AsVariantMut,
386///     AsVariantRef,
387///     VariantDowncast,
388/// )]
389/// enum Enum {
390///     // ...
391/// }
392/// ```
393///
394/// If you wish to opt out of a select few of `Encapsulate`'s trait derives,
395/// then you can do so by use of an `#[enumcapsulate(exclude(…))]` attribute
396/// on the enum itself, such as if you wanted to exclude `From` and `TryInto`:
397///
398/// ```rust
399/// #[derive(Encapsulate)]
400/// #[enumcapsulate(exclude(From, TryInto))]
401/// enum Enum {
402///     // ...
403/// }
404/// ```
405#[proc_macro_derive(Encapsulate, attributes(enumcapsulate))]
406pub fn derive_encapsulate(input: TokenStream) -> TokenStream {
407    let item = parse_macro_input!(input as syn::ItemEnum);
408
409    tokenstream(|| {
410        let deriver = EnumDeriver::from(item);
411        deriver.derive_encapsulate()
412    })
413}