Skip to main content

zyn_core/extract/
variants.rs

1use syn::punctuated::Punctuated;
2use syn::spanned::Spanned;
3
4use crate::diagnostic::Diagnostics;
5use crate::types::Input;
6
7use super::FromInput;
8
9/// Element extractor that pulls enum variants from the input.
10///
11/// Errors at compile time if the input is not an enum. Access the inner
12/// `Punctuated<syn::Variant, syn::token::Comma>` via `Deref` or the `inner()` method.
13///
14/// ```ignore
15/// #[zyn::element]
16/// fn my_element(#[zyn(input)] variants: zyn::Variants) -> proc_macro2::TokenStream {
17///     // variants.iter() — accessed via Deref to Punctuated<syn::Variant, syn::token::Comma>
18/// }
19/// ```
20pub struct Variants(Punctuated<syn::Variant, syn::token::Comma>);
21
22impl Variants {
23    /// Consumes the wrapper and returns the inner `Punctuated<syn::Variant, syn::token::Comma>`.
24    pub fn inner(self) -> Punctuated<syn::Variant, syn::token::Comma> {
25        self.0
26    }
27}
28
29impl std::ops::Deref for Variants {
30    type Target = Punctuated<syn::Variant, syn::token::Comma>;
31
32    fn deref(&self) -> &Self::Target {
33        &self.0
34    }
35}
36
37impl std::ops::DerefMut for Variants {
38    fn deref_mut(&mut self) -> &mut Self::Target {
39        &mut self.0
40    }
41}
42
43impl FromInput for Variants {
44    fn from_input(input: &Input) -> crate::Result<Self> {
45        match input {
46            Input::Derive(d) => match &d.data {
47                syn::Data::Enum(e) => Ok(Variants(e.variants.clone())),
48                _ => Err(Diagnostics::error(
49                    d.ident.span(),
50                    "expected enum input for Variants extractor",
51                )),
52            },
53            Input::Item(syn::Item::Enum(e)) => Ok(Variants(e.variants.clone())),
54            _ => Err(Diagnostics::error(
55                input.span(),
56                "expected enum input for Variants extractor",
57            )),
58        }
59    }
60}