Skip to main content

toml/de/parser/
debug.rs

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)] // HACK: fixed in newer versions
31    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}