derail_report/
buffer.rs

1//! Buffers for generating reports.
2
3#[cfg(feature = "alloc")]
4use alloc::{vec, vec::Vec};
5use core::array;
6
7use crate::sealed::Sealed;
8
9/// A factory that creates buffers.
10pub trait BufferFactory {
11    /// The buffer this factory produces.
12    ///
13    /// Not public API.
14    #[doc(hidden)]
15    #[expect(private_bounds)]
16    type Buffer<T>: Buffer<T>
17    where
18        T: Default;
19
20    /// Create a new buffer.
21    ///
22    /// Not public API.
23    #[doc(hidden)]
24    #[expect(private_interfaces)]
25    fn new<T>(_: Sealed) -> Self::Buffer<T>
26    where
27        T: Default;
28}
29
30/// A [`BufferFactory`] that creates stack-allocated buffers.
31pub struct StackFactory<const LEN: usize>;
32
33impl<const LEN: usize> BufferFactory for StackFactory<LEN> {
34    type Buffer<T>
35        = Stack<LEN, T>
36    where
37        T: Default;
38
39    #[expect(private_interfaces)]
40    fn new<T>(_: Sealed) -> Self::Buffer<T>
41    where
42        T: Default,
43    {
44        Stack {
45            // `Visitor::push` is not called before the first `Visitor::visit`
46            // call, so we need to start with a length of 1.
47            length: 1,
48            stack: array::from_fn::<_, LEN, _>(|_| T::default()),
49        }
50    }
51}
52
53/// A [`BufferFactory`] that creates heap-allocated buffers.
54#[cfg(feature = "alloc")]
55pub struct HeapFactory;
56
57#[cfg(feature = "alloc")]
58impl BufferFactory for HeapFactory {
59    type Buffer<T>
60        = Heap<T>
61    where
62        T: Default;
63
64    #[expect(private_interfaces)]
65    fn new<T>(_: Sealed) -> Self::Buffer<T>
66    where
67        T: Default,
68    {
69        Heap {
70            // `Visitor::push` is not called before the first `Visitor::visit`
71            // call, so we need to start with a length of 1.
72            stack: vec![T::default()],
73        }
74    }
75}
76
77/// A buffer.
78pub(crate) trait Buffer<T> {
79    /// Push `x` onto the buffer.
80    fn push(&mut self, _: Sealed);
81
82    /// Pop the last element off of the buffer.
83    fn pop(&mut self, _: Sealed);
84
85    /// Get the last element from the buffer.
86    fn last_mut(&mut self, _: Sealed) -> Option<&mut T>;
87
88    /// Get a particular element from the buffer.
89    fn get_mut(&mut self, x: usize, _: Sealed) -> Option<&mut T>;
90
91    /// Get the current depth of the buffer.
92    fn depth(&self, _: Sealed) -> usize;
93
94    /// Get the maximum depth of the buffer.
95    fn max_depth(&self, _: Sealed) -> usize;
96}
97
98/// A stack-allocated buffer.
99///
100/// Not public API.
101#[doc(hidden)]
102pub struct Stack<const LEN: usize, T> {
103    /// Length of the stack.
104    length: usize,
105
106    /// The stack.
107    stack: [T; LEN],
108}
109
110impl<const LEN: usize, T> Buffer<T> for Stack<LEN, T>
111where
112    T: Default,
113{
114    fn push(&mut self, _: Sealed) {
115        self.length = self.length.saturating_add(1);
116        if let Some(y) = self.stack.get_mut(self.length) {
117            *y = T::default();
118        }
119    }
120
121    fn pop(&mut self, _: Sealed) {
122        self.length = self.length.saturating_sub(1);
123    }
124
125    fn get_mut(&mut self, x: usize, _: Sealed) -> Option<&mut T> {
126        self.stack.get_mut(x)
127    }
128
129    fn last_mut(&mut self, _: Sealed) -> Option<&mut T> {
130        let depth = self.depth(Sealed);
131        self.stack.get_mut(depth)
132    }
133
134    fn depth(&self, _: Sealed) -> usize {
135        // The depth into the tree is one less than the length of the stack.
136        self.length.saturating_sub(1)
137    }
138
139    fn max_depth(&self, _: Sealed) -> usize {
140        LEN
141    }
142}
143
144/// A heap-allocated buffer.
145///
146/// Not public API.
147#[doc(hidden)]
148#[cfg(feature = "alloc")]
149pub struct Heap<T> {
150    /// The stack.
151    stack: Vec<T>,
152}
153
154#[cfg(feature = "alloc")]
155impl<T> Buffer<T> for Heap<T>
156where
157    T: Default,
158{
159    fn push(&mut self, _: Sealed) {
160        self.stack.push(T::default());
161    }
162
163    fn pop(&mut self, _: Sealed) {
164        self.stack.pop();
165    }
166
167    fn get_mut(&mut self, x: usize, _: Sealed) -> Option<&mut T> {
168        self.stack.get_mut(x)
169    }
170
171    fn last_mut(&mut self, _: Sealed) -> Option<&mut T> {
172        self.stack.last_mut()
173    }
174
175    fn depth(&self, _: Sealed) -> usize {
176        // The depth into the tree is one less than the length of the stack.
177        self.stack.len().saturating_sub(1)
178    }
179
180    fn max_depth(&self, _: Sealed) -> usize {
181        unreachable!()
182    }
183}