use quote::{ToTokens, quote}; use syn::spanned::Spanned; pub struct All { name: syn::Ident, variants: Box<[syn::Ident]>, } impl All { pub fn parse(input: syn::DeriveInput) -> Result { let data = match input.data { syn::Data::Enum(enu) => enu, _ => { return Err(syn::Error::new( input.span(), "All can only be used on enums", )); } }; let variants = data .variants .into_iter() .map(|v| match &v.fields { syn::Fields::Named(_) | syn::Fields::Unnamed(_) => Err(syn::Error::new( v.ident.span(), "All can only be used on enums with only unit fields", )), syn::Fields::Unit => Ok(v.ident), }) .collect::, _>>()?; let name = input.ident; Ok(Self { name, variants }) } } impl ToTokens for All { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { let name = &self.name; let variants = &self.variants; let count = self.variants.len(); tokens.extend(quote! { impl #name { pub const ALL: [#name; #count] = [#(#name::#variants),*]; } }); } }