1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::Data;
4use syn::Result;
5use syn::{parse_macro_input, DeriveInput};
6
7#[proc_macro_derive(Enumable)]
8pub fn derive_enumable(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
9 derive_enumable_internal(parse_macro_input!(input as DeriveInput))
10 .unwrap_or_else(syn::Error::into_compile_error)
11 .into()
12}
13
14fn derive_enumable_internal(input: DeriveInput) -> Result<TokenStream> {
15 let ident = &input.ident;
16 let variants = match &input.data {
17 Data::Enum(data) => &data.variants,
18 _ => {
19 return Err(syn::Error::new_spanned(
20 &input,
21 "Enumable can only be derived for enums",
22 ))
23 }
24 };
25
26 let mut variant_idents = Vec::new();
27 let mut variant_values = Vec::new();
28 for variant in variants {
29 let ident = &variant.ident;
30 variant_idents.push(ident.clone());
31 variant_values.push(quote! { Self::#ident });
32 }
33
34 let expanded = quote! {
35 impl enum_table::Enumable for #ident {
36 const VARIANTS: &'static [#ident] = &[#(#variant_values),*];
37 }
38 };
39
40 Ok(expanded)
41}