Skip to main content

codspeed_divan_compat_macros/
lib.rs

1mod args;
2
3use args::AttrOptions;
4use proc_macro::TokenStream;
5use proc_macro_crate::{crate_name, FoundCrate};
6use quote::{format_ident, quote, ToTokens};
7use syn::{parse_macro_input, Expr, ItemFn, Meta};
8
9#[proc_macro_attribute]
10pub fn bench_compat(attr: TokenStream, item: TokenStream) -> TokenStream {
11    let input = parse_macro_input!(item as ItemFn);
12
13    let attr_options = match AttrOptions::parse(attr) {
14        Ok(attr_options) => attr_options,
15        Err(error) => return error,
16    };
17
18    if attr_options.crate_ {
19        return quote! {
20            compile_error!("`crate` argument is yet supported with codspeed_divan_compat");
21        }
22        .into();
23    }
24
25    let codspeed_divan_crate_ident = format_ident!(
26        "{}",
27        crate_name("codspeed-divan-compat")
28            .map(|found_crate| match found_crate {
29                FoundCrate::Itself => "crate".to_string(),
30                FoundCrate::Name(name) => name,
31            })
32            .unwrap_or("codspeed_divan_compat".to_string())
33    );
34
35    let mut transfered_args = attr_options.other_args;
36
37    transfered_args.push(syn::parse_quote!(crate = ::#codspeed_divan_crate_ident));
38
39    if let Some(types) = attr_options.types {
40        transfered_args.push(Meta::NameValue(syn::MetaNameValue {
41            path: syn::parse_quote!(types),
42            eq_token: Default::default(),
43            value: Expr::Verbatim(types.into_token_stream()),
44        }));
45    }
46
47    // WARN: keep macro name in sync with re-exported macro name in divan-compat lib
48    let expanded = quote! {
49        #[::#codspeed_divan_crate_ident::bench_original(#(#transfered_args),*)]
50        #input
51    };
52
53    TokenStream::from(expanded)
54}