use proc_macro2::{Span, TokenStream}; use syn::{Data, DeriveInput}; pub fn derive_as_message_impl(input_item: TokenStream) -> syn::Result { let input = syn::parse2::(input_item).unwrap(); let data = match input.data { Data::Enum(data) => data, _ => return Err(syn::Error::new(Span::call_site(), "Tried to derive AsMessage for non-enum")), }; let input_type = input.ident; let (globs, names) = data .variants .iter() .map(|var| { let var_name = &var.ident; let var_name_s = var.ident.to_string(); if var.attrs.iter().any(|a| a.path().is_ident("child")) { ( quote::quote! { #input_type::#var_name(child) }, quote::quote! { format!("{}.{}", #var_name_s, child.local_name()) }, ) } else { ( quote::quote! { #input_type::#var_name { .. } }, quote::quote! { #var_name_s.to_string() }, ) } }) .unzip::<_, _, Vec<_>, Vec<_>>(); let res = quote::quote! { impl AsMessage for #input_type { fn local_name(self) -> String { match self { #( #globs => #names ),* } } } }; Ok(res) }