Skip to main content

zyn_core/extract/
variants.rs

1use syn::punctuated::Punctuated;
2use syn::spanned::Spanned;
3
4use crate::mark;
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(mark::error("expected enum input for Variants extractor")
49                    .span(d.span())
50                    .build()),
51            },
52            Input::Item(syn::Item::Enum(e)) => Ok(Variants(e.variants.clone())),
53            _ => Err(mark::error("expected enum input for Variants extractor")
54                .span(input.span())
55                .build()),
56        }
57    }
58}