use proc_macro::TokenStream;
use quote;
use syn;
const BAD_FIELDS_ERR: &'static str = "Fields of type must all have names to implement StringFields";
fn unwrap_fields(fields: syn::Fields)
-> syn::punctuated::Punctuated<syn::Field, syn::token::Comma> {
match fields {
syn::Fields::Named(fil) => fil.named,
syn::Fields::Unit => syn::punctuated::Punctuated::new(),
_ => panic!("Tuples cannot implement StringFields"),
}
}
#[proc_macro_derive(StringFields)]
pub fn named_enum_macro(input: TokenStream) -> TokenStream {
let ast = syn::parse_macro_input!(input as syn::DeriveInput);
let name = &ast.ident;
let type_fields: Vec<syn::Ident> = match ast.data {
syn::Data::Struct(dat) => unwrap_fields(dat.fields)
.iter()
.map(|val|
val.ident.clone().expect(BAD_FIELDS_ERR)
)
.collect(),
syn::Data::Union(dat) => dat
.fields
.named
.iter()
.map(|val|
val.ident.clone().expect(BAD_FIELDS_ERR)
)
.collect(),
syn::Data::Enum(dat) => dat
.variants
.iter()
.map(|val| val.ident.clone())
.collect(),
};
let type_fields_iter = type_fields.iter();
quote::quote!{
impl z80_forth_derive_internals::StringFields for #name {
fn fields() -> &'static[&'static str] {
return &[#(stringify!(#type_fields_iter)),*];
}
}
}.into()
}