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