enum_table_derive/
lib.rs

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}