use proc_macro::TokenStream;
use quote::quote;
use syn::spanned::Spanned;
use syn::{Data, DeriveInput, Error, Fields, LitStr, parse_macro_input};
#[proc_macro_derive(DictKey)]
pub fn derive_dict_key(input: TokenStream) -> TokenStream {
let input: DeriveInput = parse_macro_input!(input);
let ident = &input.ident;
let mut ident_names = vec![];
match &input.data {
Data::Enum(data) => {
for variant in &data.variants {
let ident = &variant.ident;
let name = LitStr::new(&ident.to_string(), ident.span());
ident_names.push(quote! { #name });
match &variant.fields {
Fields::Unit => {}
_ => {
return Error::new(variant.span(), "DictKey can only be derived for unit variants")
.to_compile_error()
.into();
}
}
}
}
_ => {
return Error::new(input.span(), "DictKey can only be derived for enums")
.to_compile_error()
.into();
}
}
quote! {
impl DictKey for #ident {
const FIELDS: &'static [&'static str] = &[#(#ident_names),*];
fn into_usize(self) -> usize {
self as usize
}
}
}
.into()
}