//! This module contains internal collections for the const builder.
usesuper::super::branch_meta::BranchMeta;
/// A const-friendly slice type. It is backed by a full slice but is primarily intended /// to represent subslices of the full slice. We need this only because we can't take /// subslices in const Rust. #[derive(Debug, Copy, Clone)] pub(crate) struct ConstSlice<'a, T> { /// The full slice.
full_slice: &'a [T], /// The start index of the slice represented by this [`ConstSlice`].
start: usize, /// The non-inclusive end index of the slice represented by this [`ConstSlice`].
limit: usize,
}
/// Non-const function that returns this [`ConstSlice`] as a regular slice. #[cfg(any(test, feature = "alloc"))] pubfn as_slice(&self) -> &'a [T] {
&self.full_slice[self.start..self.limit]
}
}
impl<const N: usize, T> ConstArrayBuilder<N, T> { /// Creates a new, empty builder of the given size. `cursor` indicates where in the /// array new elements will be inserted first. Since we use a lot of prepend operations, /// it is common to set `cursor` to `N`. pubconstfn new_empty(full_array: [T; N], cursor: usize) -> Self {
assert!(cursor <= N); Self {
full_array,
start: cursor,
limit: cursor,
}
}
/// Creates a new builder with some initial content in `[start, limit)`. pubconstfn from_manual_slice(full_array: [T; N], start: usize, limit: usize) -> Self {
assert!(start <= limit);
assert!(limit <= N); Self {
full_array,
start,
limit,
}
}
/// Returns the number of initialized elements in the builder. pubconstfn len(&self) -> usize { self.limit - self.start
}
/// Whether there are no initialized elements in the builder. #[allow(dead_code)] pubconstfn is_empty(&self) -> bool { self.len() == 0
}
/// Returns the initialized elements as a [`ConstSlice`]. pubconstfn as_const_slice(&self) -> ConstSlice<T> {
ConstSlice::from_manual_slice(&self.full_array, self.start, self.limit)
}
/// Non-const function that returns a slice of the initialized elements. #[cfg(any(test, feature = "alloc"))] pubfn as_slice(&self) -> &[T] {
&self.full_array[self.start..self.limit]
}
}
// Certain functions that involve dropping `T` require that it be `Copy` impl<const N: usize, T: Copy> ConstArrayBuilder<N, T> { /// Takes a fully initialized builder as an array. Panics if the builder is not /// fully initialized. pubconstfn const_build_or_panic(self) -> [T; N] { ifself.start != 0 || self.limit != N { let actual_len = self.limit - self.start; const PREFIX: &[u8; 31] = b"Buffer too large. Size needed: "; let len_bytes: [u8; PREFIX.len() + crate::helpers::MAX_USIZE_LEN_AS_DIGITS] = crate::helpers::const_fmt_int(*PREFIX, actual_len); let Ok(len_str) = core::str::from_utf8(&len_bytes) else {
unreachable!()
};
panic!("{}", len_str);
} self.full_array
}
/// Prepends an element to the front of the builder, panicking if there is no room. pubconstfn const_push_front_or_panic(mutself, value: T) -> Self { ifself.start == 0 {
panic!("Buffer too small");
} self.start -= 1; self.full_array[self.start] = value; self
}
/// Prepends multiple elements to the front of the builder, panicking if there is no room. pubconstfn const_extend_front_or_panic(mutself, other: ConstSlice<T>) -> Self { ifself.start < other.len() {
panic!("Buffer too small");
} self.start -= other.len(); letmut i = self.start;
const_for_each!(other, byte, { self.full_array[i] = *byte;
i += 1;
}); self
}
}
impl<const N: usize, T: Copy> ConstArrayBuilder<N, T> { /// Swaps the elements at positions `i` and `j`. #[cfg(feature = "alloc")] pubfn swap_or_panic(mutself, i: usize, j: usize) -> Self { self.full_array.swap(self.start + i, self.start + j); self
}
}
/// Evaluates a block over each element of a const slice. Takes three arguments: /// /// 1. Expression that resolves to the [`ConstSlice`]. /// 2. Token that will be assigned the value of the element. /// 3. Block to evaluate for each element.
macro_rules! const_for_each {
($safe_const_slice:expr, $item:tt, $inner:expr) => {{ letmut i = 0; while i < $safe_const_slice.len() { let $item = $safe_const_slice.get_or_panic(i);
$inner;
i += 1;
}
}};
}
pub(crate) use const_for_each;
/// A data structure that holds up to K [`BranchMeta`] items. /// /// Note: It should be possible to store the required data in the builder buffer itself, /// which would eliminate the need for this helper struct and the limit it imposes. pub(crate) struct ConstLengthsStack<const K: usize> {
data: [Option<BranchMeta>; K],
idx: usize,
}
/// Returns whether the stack is empty. pubconstfn is_empty(&self) -> bool { self.idx == 0
}
/// Adds a [`BranchMeta`] to the stack, panicking if there is no room. #[must_use] pubconstfn push_or_panic(mutself, meta: BranchMeta) -> Self { ifself.idx >= K {
panic!(concat!( "AsciiTrie Builder: Need more stack (max ",
stringify!(K), ")"
));
} self.data[self.idx] = Some(meta); self.idx += 1; self
}
/// Returns a copy of the [`BranchMeta`] on the top of the stack, panicking if /// the stack is empty. pubconstfn peek_or_panic(&self) -> BranchMeta { ifself.idx == 0 {
panic!("AsciiTrie Builder: Attempted to peek from an empty stack");
} self.get_or_panic(0)
}
/// Returns a copy of the [`BranchMeta`] at the specified index. constfn get_or_panic(&self, index: usize) -> BranchMeta { ifself.idx <= index {
panic!("AsciiTrie Builder: Attempted to get too deep in a stack");
} matchself.data[self.idx - index - 1] {
Some(x) => x,
None => unreachable!(),
}
}
/// Removes many [`BranchMeta`]s from the stack, returning them in a [`ConstArrayBuilder`]. pubconstfn pop_many_or_panic( mutself,
len: usize,
) -> (Self, ConstArrayBuilder<256, BranchMeta>) {
debug_assert!(len <= 256); letmut result = ConstArrayBuilder::new_empty([BranchMeta::default(); 256], 256); letmut ix = 0; loop { if ix == len { break;
} let i = self.idx - ix - 1;
result = result.const_push_front_or_panic(matchself.data[i] {
Some(x) => x,
None => panic!("Not enough items in the ConstLengthsStack"),
});
ix += 1;
} self.idx -= len;
(self, result)
}
/// Non-const function that returns the initialized elements as a slice. fn as_slice(&self) -> &[Option<BranchMeta>] {
&self.data[0..self.idx]
}
}
impl<const K: usize> ConstArrayBuilder<K, BranchMeta> { /// Converts this builder-array of [`BranchMeta`] to one of the `ascii` fields. pubconstfn map_to_ascii_bytes(&self) -> ConstArrayBuilder<K, u8> { letmut result = ConstArrayBuilder::new_empty([0; K], K); let self_as_slice = self.as_const_slice();
const_for_each!(self_as_slice, value, {
result = result.const_push_front_or_panic(value.ascii);
});
result
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet am 2026-08-25)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.