1use super::super::branch_meta::BranchMeta;
8
9#[derive(Debug, Copy, Clone)]
13pub(crate) struct ConstSlice<'a, T> {
14 full_slice: &'a [T],
16 start: usize,
18 limit: usize,
20}
21
22impl<'a, T> ConstSlice<'a, T> {
23 pub const fn from_slice(other: &'a [T]) -> Self {
25 ConstSlice {
26 full_slice: other,
27 start: 0,
28 limit: other.len(),
29 }
30 }
31
32 pub const fn from_manual_slice(full_slice: &'a [T], start: usize, limit: usize) -> Self {
34 ConstSlice {
35 full_slice,
36 start,
37 limit,
38 }
39 }
40
41 pub const fn len(&self) -> usize {
43 self.limit - self.start
44 }
45
46 pub const fn get_or_panic(&self, index: usize) -> &T {
48 &self.full_slice[index + self.start]
49 }
50
51 #[cfg(test)]
53 pub const fn first(&self) -> Option<&T> {
54 if self.len() == 0 {
55 None
56 } else {
57 Some(self.get_or_panic(0))
58 }
59 }
60
61 pub const fn last(&self) -> Option<&T> {
63 if self.len() == 0 {
64 None
65 } else {
66 Some(self.get_or_panic(self.len() - 1))
67 }
68 }
69
70 #[cfg(test)]
72 pub const fn get_subslice_or_panic(
73 &self,
74 new_start: usize,
75 new_limit: usize,
76 ) -> ConstSlice<'a, T> {
77 assert!(new_start <= new_limit);
78 assert!(new_limit <= self.len());
79 ConstSlice {
80 full_slice: self.full_slice,
81 start: self.start + new_start,
82 limit: self.start + new_limit,
83 }
84 }
85
86 #[cfg(any(test, feature = "alloc"))]
88 pub fn as_slice(&self) -> &'a [T] {
89 &self.full_slice[self.start..self.limit]
90 }
91}
92
93impl<'a, T> From<&'a [T]> for ConstSlice<'a, T> {
94 fn from(other: &'a [T]) -> Self {
95 Self::from_slice(other)
96 }
97}
98
99#[derive(Debug, Copy, Clone)]
101pub(crate) struct ConstArrayBuilder<const N: usize, T> {
102 full_array: [T; N],
103 start: usize,
104 limit: usize,
105}
106
107impl<const N: usize, T: Default> Default for ConstArrayBuilder<N, T> {
108 fn default() -> Self {
109 Self::new_empty([(); N].map(|_| Default::default()), 0)
110 }
111}
112
113impl<const N: usize, T> ConstArrayBuilder<N, T> {
114 pub const fn new_empty(full_array: [T; N], cursor: usize) -> Self {
118 assert!(cursor <= N);
119 Self {
120 full_array,
121 start: cursor,
122 limit: cursor,
123 }
124 }
125
126 pub const fn from_manual_slice(full_array: [T; N], start: usize, limit: usize) -> Self {
128 assert!(start <= limit);
129 assert!(limit <= N);
130 Self {
131 full_array,
132 start,
133 limit,
134 }
135 }
136
137 pub const fn len(&self) -> usize {
139 self.limit - self.start
140 }
141
142 #[allow(dead_code)]
144 pub const fn is_empty(&self) -> bool {
145 self.len() == 0
146 }
147
148 pub const fn as_const_slice(&self) -> ConstSlice<T> {
150 ConstSlice::from_manual_slice(&self.full_array, self.start, self.limit)
151 }
152
153 #[cfg(any(test, feature = "alloc"))]
155 pub fn as_slice(&self) -> &[T] {
156 &self.full_array[self.start..self.limit]
157 }
158}
159
160impl<const N: usize, T: Copy> ConstArrayBuilder<N, T> {
162 pub const fn const_build_or_panic(self) -> [T; N] {
165 if self.start != 0 || self.limit != N {
166 let actual_len = self.limit - self.start;
167 const PREFIX: &[u8; 31] = b"Buffer too large. Size needed: ";
168 let len_bytes: [u8; PREFIX.len() + crate::helpers::MAX_USIZE_LEN_AS_DIGITS] =
169 crate::helpers::const_fmt_int(*PREFIX, actual_len);
170 let Ok(len_str) = core::str::from_utf8(&len_bytes) else {
171 unreachable!()
172 };
173 panic!("{}", len_str);
174 }
175 self.full_array
176 }
177
178 pub const fn const_push_front_or_panic(mut self, value: T) -> Self {
180 if self.start == 0 {
181 panic!("Buffer too small");
182 }
183 self.start -= 1;
184 self.full_array[self.start] = value;
185 self
186 }
187
188 pub const fn const_extend_front_or_panic(mut self, other: ConstSlice<T>) -> Self {
190 if self.start < other.len() {
191 panic!("Buffer too small");
192 }
193 self.start -= other.len();
194 let mut i = self.start;
195 const_for_each!(other, byte, {
196 self.full_array[i] = *byte;
197 i += 1;
198 });
199 self
200 }
201}
202
203impl<const N: usize> ConstArrayBuilder<N, u8> {
204 pub const fn const_bitor_assign(mut self, index: usize, bits: u8) -> Self {
206 self.full_array[self.start + index] |= bits;
207 self
208 }
209}
210
211impl<const N: usize, T: Copy> ConstArrayBuilder<N, T> {
212 #[cfg(feature = "alloc")]
214 pub fn swap_or_panic(mut self, i: usize, j: usize) -> Self {
215 self.full_array.swap(self.start + i, self.start + j);
216 self
217 }
218}
219
220macro_rules! const_for_each {
226 ($safe_const_slice:expr, $item:tt, $inner:expr) => {{
227 let mut i = 0;
228 while i < $safe_const_slice.len() {
229 let $item = $safe_const_slice.get_or_panic(i);
230 $inner;
231 i += 1;
232 }
233 }};
234}
235
236pub(crate) use const_for_each;
237
238pub(crate) struct ConstLengthsStack<const K: usize> {
243 data: [Option<BranchMeta>; K],
244 idx: usize,
245}
246
247impl<const K: usize> core::fmt::Debug for ConstLengthsStack<K> {
248 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
249 self.as_slice().fmt(f)
250 }
251}
252
253impl<const K: usize> ConstLengthsStack<K> {
254 pub const fn new() -> Self {
256 Self {
257 data: [None; K],
258 idx: 0,
259 }
260 }
261
262 pub const fn is_empty(&self) -> bool {
264 self.idx == 0
265 }
266
267 #[must_use]
269 pub const fn push_or_panic(mut self, meta: BranchMeta) -> Self {
270 if self.idx >= K {
271 panic!(concat!(
272 "AsciiTrie Builder: Need more stack (max ",
273 stringify!(K),
274 ")"
275 ));
276 }
277 self.data[self.idx] = Some(meta);
278 self.idx += 1;
279 self
280 }
281
282 pub const fn peek_or_panic(&self) -> BranchMeta {
285 if self.idx == 0 {
286 panic!("AsciiTrie Builder: Attempted to peek from an empty stack");
287 }
288 self.get_or_panic(0)
289 }
290
291 const fn get_or_panic(&self, index: usize) -> BranchMeta {
293 if self.idx <= index {
294 panic!("AsciiTrie Builder: Attempted to get too deep in a stack");
295 }
296 match self.data[self.idx - index - 1] {
297 Some(x) => x,
298 None => unreachable!(),
299 }
300 }
301
302 pub const fn pop_many_or_panic(
304 mut self,
305 len: usize,
306 ) -> (Self, ConstArrayBuilder<256, BranchMeta>) {
307 debug_assert!(len <= 256);
308 let mut result = ConstArrayBuilder::new_empty([BranchMeta::default(); 256], 256);
309 let mut ix = 0;
310 loop {
311 if ix == len {
312 break;
313 }
314 let i = self.idx - ix - 1;
315 result = result.const_push_front_or_panic(match self.data[i] {
316 Some(x) => x,
317 None => panic!("Not enough items in the ConstLengthsStack"),
318 });
319 ix += 1;
320 }
321 self.idx -= len;
322 (self, result)
323 }
324
325 fn as_slice(&self) -> &[Option<BranchMeta>] {
327 &self.data[0..self.idx]
328 }
329}
330
331impl<const K: usize> ConstArrayBuilder<K, BranchMeta> {
332 pub const fn map_to_ascii_bytes(&self) -> ConstArrayBuilder<K, u8> {
334 let mut result = ConstArrayBuilder::new_empty([0; K], K);
335 let self_as_slice = self.as_const_slice();
336 const_for_each!(self_as_slice, value, {
337 result = result.const_push_front_or_panic(value.ascii);
338 });
339 result
340 }
341}