use crate::COUNTER;
use proc_macro2::{Ident, TokenStream};
use quote::format_ident;
struct CreateTtReturnMacroDef {
name: Ident,
args: Vec<(Ident, TokenStream)>,
}
impl syn::parse::Parse for CreateTtReturnMacroDef {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let name = input.parse()?;
input.parse::<syn::Token![,]>()?;
let mut args = Vec::new();
while !input.is_empty() {
let mut value;
let key: Ident = input.parse()?;
input.parse::<syn::Token![=]>()?;
let _: syn::token::Bracket = syn::bracketed!(value in input);
let _: syn::token::Brace = syn::braced!(value in value);
let value: TokenStream = value.parse()?;
args.push((key, value))
}
Ok(Self { name, args })
}
}
pub fn create_tt_return_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let CreateTtReturnMacroDef { name, args } =
syn::parse_macro_input!(input as CreateTtReturnMacroDef);
let (keys, values): (Vec<_>, Vec<_>) = args.into_iter().unzip();
let count = COUNTER.with(|counter| counter.borrow_mut().inc());
let unique_name = format_ident!("{}_{}", name, count);
let decl_macro = quote::quote! {
#[macro_export]
#[doc(hidden)]
macro_rules! #unique_name {
{
$caller:tt
$(your_tt_return = [{ $my_tt_macro:path }])?
} => {
$my_tt_return! {
$caller
#(
#keys = [{ #values }]
)*
}
}
}
pub use #unique_name as #name;
};
decl_macro.into()
}