use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Expr, ItemFn};
#[proc_macro_attribute]
pub fn time_this(_args: TokenStream, input: TokenStream) -> TokenStream {
let ItemFn {
attrs,
vis,
sig,
block,
} = parse_macro_input!(input as ItemFn);
if sig.constness.is_some() {
panic!("This macro does not work with `const fn`.")
}
let fn_name = sig.ident.to_string();
quote! {
#(#attrs)*
#vis #sig {
let __fn_name = #fn_name;
#sig {
#block
}
let __start_time = ::std::time::Instant::now();
let res = { #block };
let __elapsed_time = __start_time.elapsed();
let __elapsed_msg = if __elapsed_time.checked_sub(::std::time::Duration::from_micros(1)).is_none() {
format!("function '{}()' took {}ns", __fn_name, __elapsed_time.as_nanos())
} else if __elapsed_time.checked_sub(::std::time::Duration::from_millis(1)).is_none() {
format!("function '{}()' took {}μs", __fn_name, __elapsed_time.as_micros())
} else if __elapsed_time.checked_sub(::std::time::Duration::from_millis(1000)).is_none() {
format!("function '{}()' took {}ms", __fn_name, __elapsed_time.as_millis())
} else {
format!("function '{}()' took {:.2}s", __fn_name, __elapsed_time.as_secs_f64())
};
println!("{}", __elapsed_msg);
res
}
}.into()
}
#[proc_macro]
pub fn time(input: TokenStream) -> TokenStream {
let __token_disp = format!("{}", input);
let expr = parse_macro_input!(input as Expr);
quote! {{
let __str_expr = format!("[{}:{}] {}", file!(), line!(), #__token_disp);
let __start_time = ::std::time::Instant::now();
let res = #expr;
let __elapsed_time = __start_time.elapsed();
let __elapsed_msg = if __elapsed_time.checked_sub(::std::time::Duration::from_micros(1)).is_none() {
format!("{} took {}ns", __str_expr, __elapsed_time.as_nanos())
} else if __elapsed_time.checked_sub(::std::time::Duration::from_millis(1)).is_none() {
format!("{} took {}μs", __str_expr, __elapsed_time.as_micros())
} else if __elapsed_time.checked_sub(::std::time::Duration::from_millis(1000)).is_none() {
format!("{} took {}ms", __str_expr, __elapsed_time.as_millis())
} else {
format!("{} took {:.2}s", __str_expr, __elapsed_time.as_secs_f64())
};
println!("{}", __elapsed_msg);
res
}}.into()
}