exec_time 0.1.5

Print execution time of a function
Documentation
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
extern crate darling;
extern crate proc_macro;
use darling::FromMeta;

#[derive(Debug, FromMeta)]
#[darling(derive_syn_parse)]
struct MacroArgs {
    #[darling(default)]
    print: Option<String>,
    #[darling(default)]
    prefix: Option<String>,
    #[darling(default)]
    suffix: Option<String>,
}

#[proc_macro_attribute]
pub fn exec_time(
    metadata: proc_macro::TokenStream,
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    let args: MacroArgs = match syn::parse(metadata) {
        Ok(v) => v,
        Err(e) => {
            return e.to_compile_error().into();
        }
    };

    let print_arg = args.print.unwrap_or("always".to_string());

    if print_arg.eq(&"always".to_string())
        || (print_arg.eq(&"debug".to_string()) && cfg!(debug_assertions))
    {
        let input_fn: syn::ItemFn = parse_macro_input!(input as syn::ItemFn);
        let visibility = input_fn.vis;
        let ident = input_fn.sig.ident;
        let inputs = input_fn.sig.inputs;
        let output = input_fn.sig.output;
        let generics = &input_fn.sig.generics;
        let where_clause = &input_fn.sig.generics.where_clause;
        let block = input_fn.block;
        let asyncness = input_fn.sig.asyncness;
        let mut print_str = "".to_string();
        if let Some(pre) = args.prefix {
            print_str.push_str(&format!("{}::", pre));
        }
        print_str.push_str(&ident.to_string());
        if let Some(suffix) = args.suffix {
            print_str.push_str(&format!("::{}", suffix));
        }

        if asyncness.is_some() {
            (quote!(
                #visibility #asyncness fn #ident #generics (#inputs) #output #where_clause {
                    let start_time = std::time::Instant::now();
                    let f = || async { #block };
                    let r = f().await;
                    println!("Time {}: {} ms", #print_str, start_time.elapsed().as_millis());
                    r
                }
            ))
            .into()
        } else {
            (quote!(
                #visibility fn #ident #generics (#inputs) #output #where_clause {
                    let start_time = std::time::Instant::now();
                    let f = || { #block };
                    let r = f();
                    println!("Time {}: {} ms", #print_str, start_time.elapsed().as_millis());
                    r
                }
            ))
            .into()
        }
    } else {
        proc_macro::TokenStream::from(input).into()
    }
}