|
use proc_macro2::{Span, TokenStream}; |
|
use syn::{Data, DeriveInput}; |
|
|
|
pub fn derive_as_message_impl(input_item: TokenStream) -> syn::Result<TokenStream> { |
|
let input = syn::parse2::<DeriveInput>(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) |
|
} |
|
|