use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Data, Fields, LitStr};
#[proc_macro_attribute]
pub fn add_gen_core(attr: TokenStream, item: TokenStream) -> TokenStream {
let ext = parse_macro_input!(attr as LitStr);
let input = parse_macro_input!(item as DeriveInput);
let name = &input.ident;
let generics = &input.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let ext = ext.value();
let ext_value = ext.as_str();
let generator_base_impl = quote! {
impl #impl_generics GeneratorBase for #name #ty_generics #where_clause {
const EXT: &'static str = #ext_value;
fn core(&self) -> &GeneratorCore {
&self.core
}
fn core_mut(&mut self) -> &mut GeneratorCore {
&mut self.core
}
}
};
match &input.data {
Data::Struct(data_struct) => {
match &data_struct.fields {
Fields::Named(fields) => {
let fields = &fields.named;
let expanded = quote! {
pub struct #name #impl_generics #where_clause {
pub core: GeneratorCore,
#fields
}
#generator_base_impl
};
TokenStream::from(expanded)
},
Fields::Unit => {
let expanded = quote! {
pub struct #name #impl_generics #where_clause {
pub core: GeneratorCore
}
#generator_base_impl
};
TokenStream::from(expanded)
},
Fields::Unnamed(_) => {
let error = quote! {
compile_error!("add_gen_core can only be used on structs");
};
TokenStream::from(error)
},
}
},
_ => {
let error = quote! {
compile_error!("add_gen_core can only be used on structs");
};
TokenStream::from(error)
}
}
}