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 variants = match &input.data {
16 Data::Enum(data) => &data.variants,
17 _ => {
18 return Err(syn::Error::new_spanned(
19 &input,
20 "Enumable can only be derived for enums",
21 ))
22 }
23 };
24
25 let variants = variants
26 .iter()
27 .map(|v| {
28 if !matches!(v.fields, syn::Fields::Unit) {
29 return Err(syn::Error::new_spanned(
30 v,
31 "Enumable can only be derived for unit variants",
32 ));
33 }
34 Ok(&v.ident)
35 })
36 .collect::<Result<Vec<_>>>()?;
37
38 let ident = &input.ident;
39 let expanded = quote! {
40 impl enum_table::Enumable for #ident {
41 const VARIANTS: &'static [#ident] = &[#(Self::#variants),*];
42 }
43 };
44
45 Ok(expanded)
46}