chj_util/
dt.rs

1//! Debug trace
2
3// Sadly there's no __func__ or __FUNCTION__ equivalent in Rust.
4
5use std::cell::Cell;
6
7thread_local! {
8    // Cell not working here in 1.63.0, thus go with RefCell anyway
9    static LEVEL: Cell<u32> = Cell::new(0);
10}
11
12const INDENT: &str = "                                                                                                                                                                                                        ";
13
14fn indent(n: u32) -> &'static str {
15    &INDENT[0..(n as usize)]
16}
17
18pub struct DtGuard {
19    pub string: String
20}
21
22impl Drop for DtGuard {
23    fn drop(&mut self) {
24        // leave
25        let l: u32 = LEVEL.with(|c: &Cell<u32>| {
26            let new = c.get() - 1;
27            c.set(new);
28            new
29        });
30        eprintln!("{}{}[90m<- ({}){}[30m",
31                  // ^ 37 is too bright; 30 assuming black is default
32                  indent(l),
33                  27 as char, // \033
34                  self.string,
35                  27 as char);
36    }
37}
38
39pub fn enter(s: &str) {
40    let l: u32 = LEVEL.with(|c: &std::cell::Cell<u32>| {
41        let old = c.get();
42        c.set(old + 1);
43        old
44    });
45    eprintln!("{}-> ({})",
46              indent(l),
47              s);
48}
49
50#[macro_export]
51macro_rules! dt {
52    ($namestr:expr $(,$arg:expr)*) => {
53        // let namestr = stringify!($name);
54        let mut guard = dt::DtGuard {
55            string: String::new()
56        };
57        guard.string.push_str($namestr);
58        $(
59            guard.string.push_str(&format!(" {:?}", $arg));
60        )*
61        dt::enter(&guard.string);
62    }
63}
64
65#[macro_export]
66macro_rules! nodt {
67    ($namestr:expr $(,$arg:expr)*) => {
68    }
69}
70