1pub(crate) struct TraceScope {
2 text: String,
3 style: anstyle::Style,
4 guard: DebugDepthGuard,
5}
6
7impl TraceScope {
8 pub(crate) fn new(text: impl core::fmt::Display) -> Self {
9 let text = text.to_string();
10 let style = anstyle::Style::new();
11 trace(&format!("> {text}"), style);
12 Self {
13 text,
14 style,
15 guard: DEBUG_DEPTH.scoped(),
16 }
17 }
18}
19
20impl Drop for TraceScope {
21 fn drop(&mut self) {
22 let text = &self.text;
23 let style = self.style;
24 drop(self.guard.take());
25 trace(&format!("< {text}"), style);
26 }
27}
28
29pub(crate) fn trace(text: &str, style: anstyle::Style) {
30 #![allow(unexpected_cfgs)] let depth = DEBUG_DEPTH.depth();
32 anstream::eprintln!("{:depth$}{style}{text}{style:#}", "");
33}
34
35pub(crate) struct DebugDepth(core::sync::atomic::AtomicUsize);
36
37impl DebugDepth {
38 pub(crate) fn scoped(&self) -> DebugDepthGuard {
39 DebugDepthGuard::new()
40 }
41
42 pub(crate) fn enter_unchecked(&self) -> usize {
43 self.0.fetch_add(1, core::sync::atomic::Ordering::SeqCst)
44 }
45
46 pub(crate) fn exit_unchecked(&self) {
47 let _ = self.0.fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
48 }
49
50 pub(crate) fn depth(&self) -> usize {
51 self.0.load(core::sync::atomic::Ordering::SeqCst)
52 }
53}
54
55static DEBUG_DEPTH: DebugDepth = DebugDepth(core::sync::atomic::AtomicUsize::new(0));
56
57pub(crate) struct DebugDepthGuard {
58 depth: usize,
59 inc: bool,
60}
61
62impl DebugDepthGuard {
63 pub(crate) fn new() -> Self {
64 let depth = DEBUG_DEPTH.enter_unchecked();
65 Self { depth, inc: true }
66 }
67
68 fn take(&mut self) -> Self {
69 let depth = self.depth;
70 let inc = self.inc;
71 self.inc = false;
72 Self { depth, inc }
73 }
74}
75
76impl Drop for DebugDepthGuard {
77 fn drop(&mut self) {
78 if self.inc {
79 DEBUG_DEPTH.exit_unchecked();
80 }
81 }
82}
83
84impl AsRef<usize> for DebugDepthGuard {
85 #[inline(always)]
86 fn as_ref(&self) -> &usize {
87 &self.depth
88 }
89}
90
91impl core::ops::Deref for DebugDepthGuard {
92 type Target = usize;
93
94 #[inline(always)]
95 fn deref(&self) -> &Self::Target {
96 &self.depth
97 }
98}