more_convert_derive_internal/
enum_array.rs

1use proc_macro2::TokenStream;
2use syn::Ident;
3
4use crate::require_enum;
5
6struct EnumArrayData<'a> {
7    ident: &'a Ident,
8    impl_generics: syn::ImplGenerics<'a>,
9    ty_generics: syn::TypeGenerics<'a>,
10    where_clause: Option<&'a syn::WhereClause>,
11    variants: Vec<&'a Ident>,
12}
13
14impl<'a> EnumArrayData<'a> {
15    fn from_input(input: &'a syn::DeriveInput) -> syn::Result<Self> {
16        let variants = require_enum(input)?;
17        let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
18
19        Ok(Self {
20            ident: &input.ident,
21            impl_generics,
22            ty_generics,
23            where_clause,
24            variants: variants.iter().map(|f| &f.ident).collect(),
25        })
26    }
27}
28
29fn generate_code(data: EnumArrayData) -> TokenStream {
30    let EnumArrayData {
31        ident,
32        impl_generics,
33        ty_generics,
34        where_clause,
35        variants,
36    } = data;
37
38    let count = variants.len();
39
40    quote::quote! {
41        impl #impl_generics #ident #ty_generics #where_clause {
42            pub const COUNT: usize = #count;
43            pub const VARIANTS: &[Self] = &[#(Self::#variants),*];
44        }
45    }
46}
47
48pub fn derive_enum_array(input: syn::DeriveInput) -> syn::Result<TokenStream> {
49    let data = EnumArrayData::from_input(&input)?;
50    Ok(generate_code(data))
51}