use proc_macro::TokenStream;
use quote::quote;
use syn::{
braced, parse::Parse, parse::ParseStream, parse_macro_input, punctuated::Punctuated,
Ident, Token, Type, Visibility,
};
struct Field {
name: Ident,
_c: Token![:],
ty: Type,
}
impl Parse for Field {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(Self {
name: input.parse()?,
_c: input.parse()?,
ty: input.parse()?,
})
}
}
struct PublicAll {
name: Ident,
fields: Punctuated<Field, Token![,]>,
}
impl Parse for PublicAll {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
input.parse::<Visibility>()?;
input.parse::<Token![struct]>()?;
let name: Ident = input.parse()?;
let content;
braced!(content in input);
let fields = content.parse_terminated(Field::parse)?;
Ok(Self { name, fields })
}
}
#[proc_macro]
pub fn pub_all(input: TokenStream) -> TokenStream {
let PublicAll { name, fields } = parse_macro_input!(input as PublicAll);
let recurse = fields.iter().map(|field| {
let name = &field.name;
let ty = &field.ty;
quote!(
pub #name: #ty
)
});
let expanded = quote! {
pub struct #name {
#(#recurse,)*
}
};
TokenStream::from(expanded)
}