1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
#[macro_use] extern crate quote; #[macro_use] extern crate syn; extern crate darling; extern crate proc_macro; use darling::FromMeta; #[derive(Debug, FromMeta)] 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 attr_args = parse_macro_input!(metadata as syn::AttributeArgs); let args: MacroArgs = match MacroArgs::from_list(&attr_args) { Ok(v) => v, Err(e) => { return e.write_errors().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.ident; let inputs = input_fn.decl.inputs; let output = input_fn.decl.output; let generics = &input_fn.decl.generics; let where_clause = &input_fn.decl.generics.where_clause; let block = input_fn.block; 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)); } (quote!( #visibility fn #ident #generics (#inputs) #output #where_clause { let start_time = std::time::Instant::now(); let f = || { #block }; let r = f(); println!("Time {}: {} mills", #print_str, (std::time::Instant::now() - start_time).as_millis()); r } )) .into() } else { proc_macro::TokenStream::from(input).into() } }