enum_table_derive/
lib.rs

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