arcs_logging_rs_proc_macro/
lib.rs

1use std::str::FromStr;
2
3use proc_macro::TokenStream;
4use quote::{quote, __private::TokenStream as QuoteTokenStream};
5use syn::Ident;
6
7
8fn parse_into_ident(ident: &str) -> Result<Ident, QuoteTokenStream> {
9    syn::parse::<Ident>(
10        TokenStream
11            ::from_str(ident)
12            .map_err(|error| ToString::to_string(&error))
13            .map_err(|error| quote!{
14                compile_error!(#error);
15            })?,
16    ).map_err(
17        |err| err.to_compile_error(),
18    )
19}
20
21fn parse_into_idents(idents: (&str, &str, &str)) -> Result<(Ident, Ident, Ident), QuoteTokenStream> {
22    match (parse_into_ident(idents.0), parse_into_ident(idents.1), parse_into_ident(idents.2)) {
23        (Ok(ident_1), Ok(ident_2), Ok(ident_3)) => Ok((ident_1, ident_2, ident_3)),
24        (Err(e_1), Err(e_2), Err(e_3)) => Err(quote!{ #e_1 #e_2 #e_3 }),
25        (Err(e_1), Err(e_2), Ok(_)) => Err(quote!{ #e_1 #e_2 }),
26        (Err(e_1), Ok(_), Err(e_3)) => Err(quote!{ #e_1 #e_3 }),
27        (Err(e_1), Ok(_), Ok(_)) => Err(quote!{ #e_1 }),
28        (Ok(_), Err(e_2), Err(e_3)) => Err(quote!{ #e_2 #e_3 }),
29        (Ok(_), Err(e_2), Ok(_)) => Err(quote!{ #e_2 }),
30        (Ok(_), Ok(_), Err(e_3)) => Err(quote!{ #e_3 }),
31    }
32}
33
34#[proc_macro]
35pub fn with_target(input: TokenStream) -> TokenStream {
36    let lit: Result<syn::LitStr, _> = syn::parse(input);
37
38    match lit {
39        Ok(lit) => {
40            let macros = [
41                ("error", "error", "log_error"),
42                ("warn", "warn", "log_warn"),
43                ("info", "info", "log_info"),
44                ("debug", "debug", "log_debug"),
45                ("trace", "trace", "log_trace"),
46            ];
47            let inner_stream: QuoteTokenStream = macros
48                .into_iter()
49                .map(parse_into_idents)
50                .map(|name| match name {
51                    Ok(idents) => {
52                        let (orig_macro_name, export_name, this_macro_name) = idents;
53                        quote! {
54                            #[macro_export]
55                            macro_rules! #this_macro_name {
56                                (target: $target:expr, $($arg:tt)+) => {
57                                    arcs_logging_rs::__internal_redirects::#orig_macro_name!(target: $target, $($arg)+)
58                                };
59                                ($($arg:tt)+) => {
60                                    arcs_logging_rs::__internal_redirects::#orig_macro_name!(target: #lit, $($arg)+)
61                                };
62                            }
63                            pub use #this_macro_name as #export_name;
64                        }
65                    },
66                    Err(err) => err
67                })
68                .collect();
69
70            
71            let macro_names = [
72                "error",
73                "warn",
74                "info",
75                "debug",
76                "trace",
77            ];
78            let use_stream: QuoteTokenStream = macro_names
79                .into_iter()
80                .map(parse_into_ident)
81                .map(|result| match result {
82                    Ok(ident) => quote!{ #ident, },
83                    Err(err) => err
84                })
85                .collect();
86
87            quote!{
88                #[doc(hidden)]
89                mod __internal_logging_macros {
90                    #inner_stream
91                }
92
93                pub use __internal_logging_macros::{#use_stream};
94
95                pub static DEFAULT_TARGET_NAME: &str = #lit;
96
97            }.into()
98        },
99        Err(err) => {
100            let compile_error_tokens = err.to_compile_error();
101            quote!{ 
102                #compile_error_tokens
103            }
104        }.into()
105    }
106}