1extern crate proc_macro;
2use proc_macro::TokenStream;
3use quote::quote;
4
5fn generate_logger_impl(level: &str, args: TokenStream) -> TokenStream {
6 let args_tokens = proc_macro2::TokenStream::from(args);
7 let level_ident = syn::Ident::new(level, proc_macro2::Span::call_site());
8
9 let mut statements: Vec<proc_macro2::TokenStream> = Vec::new();
10
11 #[cfg(feature = "tracing")]
12 statements.push(quote! {
13 tracing::#level_ident!("{}", args);
14 });
15 #[cfg(feature = "log")]
16 statements.push(quote! {
17 log::#level_ident!("{}", args);
18 });
19 #[cfg(feature = "defmt")]
20 statements.push(quote! {
21 defmt::#level_ident!("{}", defmt::Display2Format(&args));
22 });
23
24 #[cfg(any(feature = "tracing", feature = "log", feature = "defmt"))]
25 let expanded = quote! {{
26 #[allow(unused_variables)]
27 let args = format_args!(#args_tokens);
28 #(#statements)*
29 }};
30 #[cfg(not(any(feature = "tracing", feature = "log", feature = "defmt")))]
31 let expanded = quote! {};
32
33 TokenStream::from(expanded)
34}
35
36#[proc_macro]
37pub fn error(input: TokenStream) -> TokenStream {
38 generate_logger_impl("error", input)
39}
40
41#[proc_macro]
42pub fn warn(input: TokenStream) -> TokenStream {
43 generate_logger_impl("warn", input)
44}
45
46#[proc_macro]
47pub fn info(input: TokenStream) -> TokenStream {
48 generate_logger_impl("info", input)
49}
50
51#[proc_macro]
52pub fn debug(input: TokenStream) -> TokenStream {
53 generate_logger_impl("debug", input)
54}
55
56#[proc_macro]
57pub fn trace(input: TokenStream) -> TokenStream {
58 generate_logger_impl("trace", input)
59}