extern crate proc_macro;
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use syn::{parse_macro_input, Ident, ItemStruct};
#[proc_macro_attribute]
pub fn trait_var(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let (trait_path, trait_name) = match args.first().unwrap() {
syn::NestedMeta::Meta(syn::Meta::Path(path)) => (path, path.get_ident().unwrap()),
_ => panic!("Expected a trait name"),
};
let mut hidden_trait_path = trait_path.clone();
if let Some(last_segment) = hidden_trait_path.segments.last_mut() {
let ident = Ident::new(
&format!("_{}", last_segment.ident),
last_segment.ident.span(),
);
last_segment.ident = ident;
}
let input_struct = parse_macro_input!(input as ItemStruct);
let visible = &input_struct.vis;
let struct_name = &input_struct.ident;
let struct_fields = input_struct.fields.iter().map(ToTokens::to_token_stream);
let expanded = quote! {
trait_variable! {
(#trait_name)
(#hidden_trait_path)
#visible struct #struct_name {
#(#struct_fields),*
}
}
};
expanded.into()
}
#[proc_macro_attribute]
pub fn test_macro_output(args: TokenStream, _input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs);
let (trait_path, _trait_name) = match args.first().unwrap() {
syn::NestedMeta::Meta(syn::Meta::Path(path)) => (path, path.get_ident().unwrap()),
_ => panic!("Expected a trait name"),
};
let mut hidden_trait_path = trait_path.clone();
if let Some(last_segment) = hidden_trait_path.segments.last_mut() {
let ident = Ident::new(
&format!("_{}", last_segment.ident),
last_segment.ident.span(),
);
last_segment.ident = ident;
}
let expanded = quote! {
use #trait_path;
use crate::#hidden_trait_path; };
expanded.into()
}