use crate::*;
fn apply_macro(macro_meta: &Meta, item_stream: TokenStream, position: Position) -> TokenStream {
let (macro_name, macro_attr) = match macro_meta {
Meta::Path(path) => (
path.get_ident()
.expect("Macro path should have an identifier")
.to_string(),
TokenStream::new(),
),
Meta::List(meta_list) => (
meta_list
.path
.get_ident()
.expect("Macro path should have an identifier")
.to_string(),
meta_list.tokens.clone().into(),
),
_ => panic!("Unsupported macro format in inject macro"),
};
for injectable_macro in INJECTABLE_MACROS {
if injectable_macro.name == macro_name {
return match injectable_macro.handler {
Handler::WithAttr(handler) => handler(macro_attr, item_stream),
Handler::NoAttrPosition(handler) => {
if !macro_attr.is_empty() {
panic!("Macro {macro_name} does not take attributes");
}
handler(item_stream, position)
}
Handler::WithAttrPosition(handler) => handler(macro_attr, item_stream, position),
};
}
}
panic!("Unsupported macro: {macro_name}");
}
pub(crate) fn prologue_macros_macro(attr: TokenStream, item: TokenStream) -> TokenStream {
let metas: Punctuated<Meta, Comma> = Punctuated::<Meta, Token![,]>::parse_terminated
.parse(attr)
.expect("Failed to parse macro attributes");
let mut current_stream: TokenStream = item;
for meta in metas.iter().rev() {
current_stream = apply_macro(meta, current_stream, Position::Prologue);
}
current_stream
}
pub(crate) fn epilogue_macros_macro(attr: TokenStream, item: TokenStream) -> TokenStream {
let metas: Punctuated<Meta, Comma> = Punctuated::<Meta, Token![,]>::parse_terminated
.parse(attr)
.expect("Failed to parse macro attributes");
let mut current_stream: TokenStream = item;
for meta in metas.iter() {
current_stream = apply_macro(meta, current_stream, Position::Epilogue);
}
current_stream
}