anodized_core/instrument/
mod.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::Meta;
4pub mod function;
5
6pub struct Backend {
7    pub build_check: fn(Option<&Meta>, &TokenStream, &str, &TokenStream) -> TokenStream,
8}
9
10impl Backend {
11    pub const CHECK_AND_PANIC: Backend = Backend {
12        build_check: build_assert,
13    };
14
15    pub const CHECK_AND_PRINT: Backend = Backend {
16        build_check: build_eprint,
17    };
18
19    pub const NO_CHECK: Backend = Backend {
20        build_check: build_inert,
21    };
22}
23
24fn build_assert(
25    cfg: Option<&Meta>,
26    expr: &TokenStream,
27    message: &str,
28    repr: &TokenStream,
29) -> TokenStream {
30    let repr_str = repr.to_string();
31    let check = quote! { assert!(#expr, #message, #repr_str); };
32    guard_check(cfg, check)
33}
34
35fn build_eprint(
36    cfg: Option<&Meta>,
37    expr: &TokenStream,
38    message: &str,
39    repr: &TokenStream,
40) -> TokenStream {
41    let repr_str = repr.to_string();
42    let check = quote! {
43        if !(#expr) {
44            eprintln!(#message, #repr_str);
45        }
46    };
47    guard_check(cfg, check)
48}
49
50fn build_inert(
51    // The check will not be present at runtime regardless of the `#[cfg]` setting.
52    _cfg: Option<&Meta>,
53    expr: &TokenStream,
54    message: &str,
55    repr: &TokenStream,
56) -> TokenStream {
57    let repr_str = repr.to_string();
58    quote! {
59        if false {
60            assert!(#expr, #message, #repr_str);
61        }
62    }
63}
64
65fn guard_check(cfg: Option<&Meta>, check: TokenStream) -> TokenStream {
66    if let Some(cfg) = cfg {
67        quote! { if cfg!(#cfg) { #check } }
68    } else {
69        check
70    }
71}