extern crate proc_macro;
use {quote::quote, syn::parse_macro_input};
#[proc_macro_attribute]
pub fn access_control(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let mut args = args.to_string();
args.retain(|c| !c.is_whitespace());
let access_control: Vec<proc_macro2::TokenStream> = args
.split(')')
.filter(|ac| !ac.is_empty())
.map(|ac| format!("{ac})")) .map(|ac| format!("{ac}?;")) .map(|ac| {
ac.parse::<proc_macro2::TokenStream>().map_err(|_| {
syn::Error::new(
proc_macro2::Span::call_site(),
format!("`#[access_control]` argument `{ac} is not valid Rust syntax"),
)
.into_compile_error()
})
})
.collect::<Result<Vec<_>, _>>()
.unwrap_or_else(|err| vec![err]);
let item_fn = parse_macro_input!(input as syn::ItemFn);
let fn_attrs = item_fn.attrs;
let fn_vis = item_fn.vis;
let fn_sig = item_fn.sig;
let fn_block = item_fn.block;
let fn_stmts = fn_block.stmts;
proc_macro::TokenStream::from(quote! {
#(#fn_attrs)*
#fn_vis #fn_sig {
#(#access_control)*
#(#fn_stmts)*
}
})
}