derive_name_macros/
lib.rs1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{self, parse_quote, Arm, Data};
4
5#[proc_macro_derive(Name)]
6pub fn name(input: TokenStream) -> TokenStream {
7 let ast: syn::DeriveInput = syn::parse_macro_input!(input);
8 let ident = &ast.ident;
9 let gen = quote! {
10 impl derive_name::Name for #ident {
11 fn name() -> &'static str {
12 stringify!(#ident)
13 }
14 }
15 };
16 gen.into()
17}
18
19#[proc_macro_derive(VariantName)]
20pub fn variant(input: TokenStream) -> TokenStream {
21 let ast: syn::DeriveInput = syn::parse_macro_input!(input);
22
23 if let Data::Enum(r#enum) = &ast.data {
24 let ident = &ast.ident;
25 let mut match_arms = Vec::<Arm>::with_capacity(r#enum.variants.len());
26
27 for variant in r#enum.variants.iter() {
28 let variant_ident = &variant.ident;
29 let match_pattern = match &variant.fields {
30 syn::Fields::Named(_) => {
31 quote!( Self::#variant_ident {..} )
32 }
33 syn::Fields::Unnamed(_) => {
34 quote!( Self::#variant_ident (..) )
35 }
36 syn::Fields::Unit => quote!( Self::#variant_ident ),
37 };
38
39 match_arms.push(parse_quote! {
40 #match_pattern => stringify!(#variant_ident)
41 });
42 }
43 let gen = quote! {
44 impl derive_name::VariantName for #ident {
45 fn variant_name(&self) -> &'static str {
46 match self {
47 #(#match_arms),*
48 }
49 }
50 }
51 };
52 gen.into()
53 } else {
54 quote!(
55 compile_error!("Can only implement 'VariantName' on a enum");
56 )
57 .into()
58 }
59}