1#[cfg(not(feature = "std"))]
4use alloc::collections::BTreeSet;
5#[cfg(feature = "std")]
6use std::collections::HashSet;
7
8use crate::InspectLimits;
9
10#[derive(Debug)]
15pub struct InspectCx<'a> {
16 limits: InspectLimits,
17 depth: usize,
18 nodes_visited: usize,
19 #[cfg(feature = "std")]
20 visited_addrs: HashSet<usize>,
21 #[cfg(not(feature = "std"))]
22 visited_addrs: BTreeSet<usize>,
23 _marker: core::marker::PhantomData<&'a ()>,
24}
25
26impl<'a> InspectCx<'a> {
27 pub fn new() -> Self {
29 Self::with_limits(InspectLimits::default())
30 }
31
32 pub fn with_limits(limits: InspectLimits) -> Self {
34 Self {
35 limits,
36 depth: 0,
37 nodes_visited: 0,
38 #[cfg(feature = "std")]
39 visited_addrs: HashSet::new(),
40 #[cfg(not(feature = "std"))]
41 visited_addrs: BTreeSet::new(),
42 _marker: core::marker::PhantomData,
43 }
44 }
45
46 pub fn limits(&self) -> &InspectLimits {
48 &self.limits
49 }
50
51 pub fn depth(&self) -> usize {
53 self.depth
54 }
55
56 pub fn depth_exceeded(&self) -> bool {
58 self.depth >= self.limits.max_depth
59 }
60
61 pub fn nodes_exceeded(&self) -> bool {
63 self.nodes_visited >= self.limits.max_nodes
64 }
65
66 pub fn visit_node(&mut self) {
68 self.nodes_visited += 1;
69 }
70
71 pub fn enter(&mut self) -> DepthGuard<'_, 'a> {
73 self.depth += 1;
74 DepthGuard { cx: self }
75 }
76
77 pub fn is_visited(&self, addr: usize) -> bool {
79 self.visited_addrs.contains(&addr)
80 }
81
82 pub fn mark_visited(&mut self, addr: usize) {
84 self.visited_addrs.insert(addr);
85 }
86}
87
88impl Default for InspectCx<'_> {
89 fn default() -> Self {
90 Self::new()
91 }
92}
93
94#[derive(Debug)]
96pub struct DepthGuard<'cx, 'a> {
97 cx: &'cx mut InspectCx<'a>,
98}
99
100impl Drop for DepthGuard<'_, '_> {
101 fn drop(&mut self) {
102 self.cx.depth -= 1;
103 }
104}
105
106impl<'cx, 'a> core::ops::Deref for DepthGuard<'cx, 'a> {
107 type Target = InspectCx<'a>;
108
109 fn deref(&self) -> &Self::Target {
110 self.cx
111 }
112}
113
114impl core::ops::DerefMut for DepthGuard<'_, '_> {
115 fn deref_mut(&mut self) -> &mut Self::Target {
116 self.cx
117 }
118}