Skip to main content

tiny_trie/
bit_trie.rs

1//! Bit Trie — a binary radix trie indexed by individual key bits.
2//!
3//! Each node has exactly two children (bit 0 and bit 1), stored inline as
4//! `[u32; 2]`. Because both children are always present in a binary trie,
5//! there are no empty slots and no mask needed for child enumeration —
6//! just `children[bit]`.
7//!
8//! # Terminal Nodes
9//!
10//! Keys that are prefixes of other keys (e.g. "ab" in {"ab", "abc"}) are
11//! represented by a `terminal` flag on the node where the key ends, rather
12//! than a null-byte leaf child. This eliminates null terminators, allows
13//! `0x00` bytes in keys, and makes `get()` accept plain `&[u8]`.
14//!
15//! # High-Bit Leaf Encoding
16//!
17//! Bit 31 of each `children[i]` indicates whether the value is a leaf key
18//! index (bit set) or an arena index (bit clear). Bit 31 of `leaf` indicates
19//! whether the node is terminal. This packs the leaf/terminal flags into
20//! existing fields, eliminating the separate `leaf_mask` byte.
21//!
22//! # Per-Child Prefix Lengths
23//!
24//! Each node stores `prefix_lens: [u16; 2]` — the prefix length (in bits) for
25//! each child. The node's own prefix length comes from its parent. The root's
26//! prefix length is stored in `BitTrie.root_prefix_len`.
27//!
28//! # Key Index Encoding
29//!
30//! A dummy entry at `index[0] = (0, 0)` points at `buf[0]` (empty key).
31//! Real keys start at index 1. This allows 0 to be used as a sentinel for
32//! "empty" in `children[]` slots.
33
34use crate::{KeyStore, TrieKey};
35use std::simd::{Simd, cmp::SimdPartialEq};
36
37// ---------------------------------------------------------------------------
38// Constants
39// ---------------------------------------------------------------------------
40
41/// Bit 31 of `children[i]` indicates the value is a leaf key index.
42const LEAF_BIT: u32 = 1u32 << 31;
43
44/// Bit 31 of `leaf` indicates the node is terminal (its own key ends here).
45const TERMINAL_BIT: u32 = 1u32 << 31;
46
47/// Sentinel for the iterator: "positioned at the terminal value of this node."
48/// In a binary trie, child positions are 0 and 1, so 2 is available as a sentinel.
49const TERMINAL_POS: u8 = 2;
50
51// ---------------------------------------------------------------------------
52// Core types
53// ---------------------------------------------------------------------------
54
55/// A single node in the bit trie arena.
56///
57/// Layout (16 bytes):
58/// - `children`: 2 slots indexed by bit value (0 or 1). Bit 31 = is_leaf;
59///   bits 0-30 = key index (if leaf) or arena index (if internal). Value 0
60///   means empty (transient during construction only).
61/// - `prefix_lens`: per-child prefix lengths in bits. `prefix_lens[0]` is the
62///   prefix length of the subtree rooted at `children[0]`, and likewise for [1].
63///   The node's own prefix length comes from its parent.
64/// - `leaf`: bit 31 = is_terminal (this node represents a key that ends here);
65///   bits 0-30 = key index for the reference/terminal key.
66#[derive(Clone, Copy)]
67struct Node {
68    children: [u32; 2],
69    prefix_lens: [u16; 2],
70    leaf: u32,
71}
72
73impl Node {
74    fn new() -> Self {
75        Node {
76            children: [0; 2],
77            prefix_lens: [0; 2],
78            leaf: 0,
79        }
80    }
81
82    // -------------------------------------------------------------------
83    // Child helpers
84    // -------------------------------------------------------------------
85
86    #[inline]
87    fn is_leaf(&self, bit: usize) -> bool {
88        debug_assert!(bit < 2);
89        (self.children[bit] & LEAF_BIT) != 0
90    }
91
92    #[inline]
93    fn child_index(&self, bit: usize) -> u32 {
94        debug_assert!(bit < 2);
95        self.children[bit] & !LEAF_BIT
96    }
97
98    #[inline]
99    fn is_empty(&self, bit: usize) -> bool {
100        debug_assert!(bit < 2);
101        self.children[bit] == 0
102    }
103
104    /// Store a leaf key index at `bit`. Key index must be ≥ 1
105    /// (index[0] is the dummy entry). Sets LEAF_BIT.
106    #[inline]
107    fn set_leaf_child(&mut self, bit: usize, key_index: u32, prefix_len: u16) {
108        debug_assert!(bit < 2);
109        debug_assert!(key_index > 0, "key index 0 is the dummy");
110        self.children[bit] = key_index | LEAF_BIT;
111        self.prefix_lens[bit] = prefix_len;
112    }
113
114    /// Store an arena index at `bit` (internal node reference).
115    /// Arena index must be ≥ 1 (root at index 0 is never a child).
116    /// Clears LEAF_BIT.
117    #[inline]
118    fn set_internal_child(&mut self, bit: usize, arena_index: u32, prefix_len: u16) {
119        debug_assert!(bit < 2);
120        debug_assert!(arena_index > 0);
121        self.children[bit] = arena_index; // no LEAF_BIT
122        self.prefix_lens[bit] = prefix_len;
123    }
124
125    /// Decode a leaf child at `bit` into a key index.
126    /// Returns `None` if the slot is empty or not a leaf.
127    #[inline]
128    fn leaf_key_index(&self, bit: usize) -> Option<u32> {
129        debug_assert!(bit < 2);
130        if self.is_leaf(bit) {
131            let idx = self.child_index(bit);
132            if idx != 0 {
133                return Some(idx);
134            }
135        }
136        None
137    }
138
139    // -------------------------------------------------------------------
140    // Terminal helpers
141    // -------------------------------------------------------------------
142
143    #[inline]
144    fn is_terminal(&self) -> bool {
145        (self.leaf & TERMINAL_BIT) != 0
146    }
147
148    #[inline]
149    fn set_terminal(&mut self, val: bool) {
150        if val {
151            self.leaf |= TERMINAL_BIT;
152        } else {
153            self.leaf &= !TERMINAL_BIT;
154        }
155    }
156
157    /// The key index stored in `leaf` (low 31 bits). For terminal nodes,
158    /// this is the node's own key. For non-terminal nodes, this is a
159    /// reference key used during insertion divergence comparison.
160    #[inline]
161    fn leaf_key_index_val(&self) -> u32 {
162        self.leaf & !TERMINAL_BIT
163    }
164
165    #[inline]
166    fn set_leaf_key_index(&mut self, idx: u32) {
167        debug_assert!(idx > 0, "key index 0 is the dummy");
168        self.leaf = (self.leaf & TERMINAL_BIT) | idx;
169    }
170}
171
172impl std::fmt::Debug for Node {
173    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174        let active: Vec<(usize, &str, u32, u16)> = (0..2)
175            .filter(|&b| self.children[b] != 0)
176            .map(|b| {
177                let tag = if self.is_leaf(b) { "L" } else { "I" };
178                let idx = self.child_index(b);
179                (b, tag, idx, self.prefix_lens[b])
180            })
181            .collect();
182        f.debug_struct("Node")
183            .field("prefix_lens", &self.prefix_lens)
184            .field("terminal", &self.is_terminal())
185            .field("leaf_idx", &self.leaf_key_index_val())
186            .field("children", &active)
187            .finish()
188    }
189}
190
191// ---------------------------------------------------------------------------
192// BitTrie
193// ---------------------------------------------------------------------------
194
195#[derive(Clone)]
196pub struct BitTrie<K: TrieKey, V> {
197    arena: Vec<Node>,
198    keys: K::Store,
199    values: Vec<V>,
200    /// The root node has no parent, so its prefix_len is stored here.
201    root_prefix_len: u16,
202}
203
204// ---------------------------------------------------------------------------
205// Divergence result
206// ---------------------------------------------------------------------------
207
208/// Outcome of comparing two keys for divergence starting from a given bit
209/// position. `from` lets callers skip already-confirmed-matching prefixes.
210enum DivergeResult {
211    /// The keys are identical (same bit count, same content).
212    Duplicate,
213    /// The keys diverge at this bit position, or one key is a prefix of the
214    /// other (position = bit count of the shorter key).
215    At(usize),
216}
217
218/// Bounded check: do the keys match from bit `from` to bit `to` (exclusive)?
219/// Returns `true` only if all bits in [from, to) are equal in both keys AND
220/// both keys are long enough to have bits in that range. If one key is a prefix
221/// of the other within [from, to), returns `false`.
222///
223/// This is the fast path for internal node descent: we only need to confirm
224/// that the new key shares the subtree prefix through the node's discriminating
225/// bit, without scanning the full key.
226#[inline]
227fn prefix_matches(key_a: &[u8], key_b: &[u8], from: usize, to: usize) -> bool {
228    // If `to` extends beyond the shorter key, one key is a prefix of the
229    // other — that's a divergence, not a match for descent.
230    if key_a.len() * 8 < to || key_b.len() * 8 < to {
231        return false;
232    }
233    // Compare byte-by-byte where possible, then bit-by-bit for the tail.
234    // Bits `from..to` span bytes from `from_byte` to `to_byte`.
235    let from_byte = from / 8;
236    let to_byte = (to + 7) / 8; // ceil(to / 8)
237    let min_len = key_a.len().min(key_b.len()).min(to_byte);
238    for i in from_byte..min_len {
239        if key_a[i] != key_b[i] {
240            // Check if the differing bit is within [from, to)
241            let xor = key_a[i] ^ key_b[i];
242            let first_diff_bit = i * 8 + xor.leading_zeros() as usize;
243            return first_diff_bit >= to;
244        }
245    }
246    true
247}
248
249/// Scan two keys from `from` onward to find the first diverging bit.
250#[inline]
251fn find_divergence(key_a: &[u8], key_b: &[u8], from: usize) -> DivergeResult {
252    let total_a = key_a.len() * 8;
253    let total_b = key_b.len() * 8;
254    let min = total_a.min(total_b);
255    let mut d = from;
256    while d < min {
257        if key_bit_at(key_a, d) != key_bit_at(key_b, d) {
258            return DivergeResult::At(d);
259        }
260        d += 1;
261    }
262    if total_a == total_b {
263        DivergeResult::Duplicate
264    } else {
265        DivergeResult::At(d)
266    }
267}
268
269/// Given two differing bytes, return the bit position of the first divergence.
270/// MSB-first: bit 0 = MSB of byte 0. The position of the first 1 bit in the
271/// XOR gives the bit index directly (since leading_zeros counts from MSB).
272#[inline]
273fn diverging_bit(xor: u8, byte_idx: usize) -> usize {
274    byte_idx * 8 + xor.leading_zeros() as usize
275}
276
277fn simd_find_divergence<const N: usize>(key_a: &[u8], key_b: &[u8], from: usize) -> DivergeResult
278{
279    let minlen = key_a.len().min(key_b.len());
280    let mut i = from / 8; // byte containing bit `from`
281
282    while i + N <= minlen {
283        let a = Simd::<u8, N>::from_slice(unsafe { key_a.get_unchecked(i..i + N) });
284        let b = Simd::<u8, N>::from_slice(unsafe { key_b.get_unchecked(i..i + N) });
285        let mask = a.simd_ne(b);
286        if mask.any() {
287            let diff_byte_idx = i + mask.first_set().unwrap();
288            let xor = unsafe { *key_a.get_unchecked(diff_byte_idx) ^ *key_b.get_unchecked(diff_byte_idx) };
289            return DivergeResult::At(diverging_bit(xor, diff_byte_idx));
290        }
291        i += N;
292    }
293
294    // Scalar tail
295    find_divergence(key_a, key_b, i * 8)
296}
297
298/// SIMD-accelerated byte equality check. Returns `true` if both slices have
299/// the same length and identical content.
300#[inline]
301fn simd_eq(a: &[u8], b: &[u8]) -> bool {
302    if a.len() != b.len() {
303        return false;
304    }
305    let len = a.len();
306    let mut i = 0;
307    while i + 16 <= len {
308        let va = Simd::<u8, 16>::from_slice(unsafe { a.get_unchecked(i..i + 16) });
309        let vb = Simd::<u8, 16>::from_slice(unsafe { b.get_unchecked(i..i + 16) });
310        if va.simd_ne(vb).any() {
311            return false;
312        }
313        i += 16;
314    }
315    // Scalar tail
316    while i < len {
317        if unsafe { *a.get_unchecked(i) != *b.get_unchecked(i) } {
318            return false;
319        }
320        i += 1;
321    }
322    true
323}
324
325// ---------------------------------------------------------------------------
326// Bit helpers
327// ---------------------------------------------------------------------------
328
329/// Extract bit at absolute position `idx` from `key`. MSB-first ordering:
330/// bit 0 = MSB of byte 0, bit 7 = LSB of byte 0, bit 8 = MSB of byte 1, etc.
331/// Past the end of the key, returns 0 (implicit null terminator for ordering:
332/// shorter keys sort before longer keys that extend them).
333#[inline]
334fn key_bit_at(key: &[u8], idx: usize) -> u8 {
335    let byte_idx = idx / 8;
336    if byte_idx < key.len() {
337        (key[byte_idx] >> (7 - idx % 8)) & 1
338    } else {
339        0
340    }
341}
342
343// ---------------------------------------------------------------------------
344// BitTrie implementation
345// ---------------------------------------------------------------------------
346
347impl<K: TrieKey, V> BitTrie<K, V> {
348    pub fn new() -> Self {
349        BitTrie {
350            arena: Vec::new(),
351            keys: K::Store::default(),
352            values: Vec::new(),
353            root_prefix_len: 0,
354        }
355    }
356
357    pub fn len(&self) -> usize {
358        self.keys.len()
359    }
360
361    pub fn is_empty(&self) -> bool {
362        self.keys.len() == 0
363    }
364
365    // -----------------------------------------------------------------------
366    // Lookup
367    // -----------------------------------------------------------------------
368
369    #[inline]
370    pub fn get_index(&self, key: &[u8]) -> Option<usize> {
371        if self.arena.is_empty() {
372            return None;
373        }
374        let max_bits = key.len() * 8;
375        let mut node_idx: u32 = 0;
376        let mut prefix_len = self.root_prefix_len as usize;
377
378        loop {
379            let node = &self.arena[node_idx as usize];
380
381            // Key bits exhausted — check if this node is terminal
382            if prefix_len >= max_bits {
383                if node.is_terminal() {
384                    let ki = node.leaf_key_index_val();
385                    let key_in_buf = self.keys.key_bytes(ki);
386                    if simd_eq(key_in_buf, key) {
387                        return Some(ki as usize);
388                    }
389                }
390                return None;
391            }
392
393            let bit = key_bit_at(key, prefix_len) as usize;
394            let child = node.children[bit];
395
396            // Empty child slot — no match
397            if child == 0 {
398                return None;
399            }
400
401            if child & LEAF_BIT != 0 {
402                // Leaf — verify full key match
403                let ki = child & !LEAF_BIT;
404                return if simd_eq(self.keys.key_bytes(ki), key) {
405                    Some(ki as usize)
406                } else {
407                    None
408                };
409            }
410
411            // Internal node — descend
412            prefix_len = node.prefix_lens[bit] as usize;
413            node_idx = child;
414        }
415    }
416
417    pub fn get(&self, key: &[u8]) -> Option<&V> {
418        self.get_index(key).map(|idx| &self.values[idx - 1])
419    }
420
421    pub fn get_mut(&mut self, key: &[u8]) -> Option<&mut V> {
422        self.get_index(key).map(|idx| &mut self.values[idx - 1])
423    }
424
425    // -----------------------------------------------------------------------
426    // Insertion
427    // -----------------------------------------------------------------------
428
429    pub fn insert(&mut self, key: K, value: V) -> Result<usize, ()> {
430        // No null byte rejection — 0x00 bytes are valid in keys.
431
432        let new_index = self.keys.push(key);
433        self.values.push(value);
434
435        let new_key = self.keys.key_bytes(new_index);
436        let max_bits = new_key.len() * 8;
437
438        if self.arena.is_empty() {
439            if max_bits == 0 {
440                // Empty key — root node itself is terminal
441                let mut root = Node::new();
442                root.set_terminal(true);
443                root.set_leaf_key_index(new_index);
444                self.arena.push(root);
445                self.root_prefix_len = 0;
446                return Ok(new_index as usize);
447            }
448            // First key: create root at bit 0
449            let first_bit = key_bit_at(new_key, 0) as usize;
450            let mut root = Node::new();
451            root.set_leaf_child(first_bit, new_index, max_bits as u16);
452            root.set_leaf_key_index(new_index);
453            self.arena.push(root);
454            self.root_prefix_len = 0;
455            return Ok(new_index as usize);
456        }
457
458        let mut node_idx: u32 = 0;
459        let mut confirmed: usize = 0;
460        let mut prefix_len = self.root_prefix_len as usize;
461        // Track parent so we can update prefix_lens when a node is split.
462        // parent_info = (parent_arena_index, which_child_bit)
463        let mut parent_info: Option<(u32, usize)> = None;
464
465        loop {
466            let node = &self.arena[node_idx as usize];
467            // Use leaf field for reference key (O(1), no find_any_leaf)
468            let ref_ki = node.leaf_key_index_val();
469            let ref_key = self.keys.key_bytes(ref_ki);
470
471            // Fast path: bounded comparison from confirmed to prefix_len.
472            // We only need to know if the new key matches the reference key
473            // through this node's discriminating bit position.
474            if prefix_matches(new_key, ref_key, confirmed, prefix_len) {
475                // Keys match from confirmed to prefix_len — descend or handle
476                // terminal/empty/leaf cases.
477
478                // Check if the new key is a prefix that ends at this node
479                if max_bits <= prefix_len {
480                    // Key bits exhausted at this node — mark terminal
481                    self.arena[node_idx as usize].set_terminal(true);
482                    self.arena[node_idx as usize].set_leaf_key_index(new_index);
483                    return Ok(new_index as usize);
484                }
485
486                let bit = key_bit_at(new_key, prefix_len) as usize;
487                let child = node.children[bit];
488
489                // Empty child slot — insert leaf directly
490                if child == 0 {
491                    self.arena[node_idx as usize]
492                        .set_leaf_child(bit, new_index, max_bits as u16);
493                    return Ok(new_index as usize);
494                }
495
496                if child & LEAF_BIT != 0 {
497                    // Leaf child — need full divergence scan for the split
498                    let existing_ki = child & !LEAF_BIT;
499                    let existing_key = self.keys.key_bytes(existing_ki);
500                    let existing_prefix = node.prefix_lens[bit];
501
502                    match simd_find_divergence::<8>(new_key, existing_key, confirmed) {
503                        DivergeResult::Duplicate => {
504                            // Should not happen — caught above via prefix_matches
505                            self.keys.rollback();
506                            let _ = self.values.pop();
507                            return Err(());
508                        }
509                        DivergeResult::At(d) => {
510                            let mut split_node = Node::new();
511
512                            if d >= max_bits {
513                                // New key ends at the split point — terminal
514                                let exist_bit = key_bit_at(existing_key, d) as usize;
515                                split_node.set_terminal(true);
516                                split_node.set_leaf_key_index(new_index);
517                                split_node.set_leaf_child(exist_bit, existing_ki, existing_prefix);
518                            } else if d >= existing_key.len() * 8 {
519                                // Existing key ends at the split point — terminal
520                                let new_child_bit = key_bit_at(new_key, d) as usize;
521                                split_node.set_terminal(true);
522                                split_node.set_leaf_key_index(existing_ki);
523                                split_node.set_leaf_child(new_child_bit, new_index, max_bits as u16);
524                            } else {
525                                // Neither key ends at the split point
526                                let new_child_bit = key_bit_at(new_key, d) as usize;
527                                let exist_bit = key_bit_at(existing_key, d) as usize;
528                                debug_assert_ne!(new_child_bit, exist_bit);
529                                split_node.set_leaf_child(new_child_bit, new_index, max_bits as u16);
530                                split_node.set_leaf_child(exist_bit, existing_ki, existing_prefix);
531                                split_node.set_leaf_key_index(existing_ki);
532                            }
533
534                            let split_idx = self.arena.len() as u32;
535                            self.arena.push(split_node);
536                            self.arena[node_idx as usize]
537                                .set_internal_child(bit, split_idx, d as u16);
538                        }
539                    }
540                    return Ok(new_index as usize);
541                }
542
543                // Internal child — descend
544                confirmed = prefix_len + 1;
545                parent_info = Some((node_idx, bit));
546                prefix_len = node.prefix_lens[bit] as usize;
547                node_idx = child;
548            } else {
549                // Keys diverge before prefix_len — need the exact divergence
550                // point for a node split. Full scan from confirmed.
551                match simd_find_divergence::<8>(new_key, ref_key, confirmed) {
552                    DivergeResult::Duplicate => {
553                        // Duplicate key — roll back
554                        self.keys.rollback();
555                        let _ = self.values.pop();
556                        return Err(());
557                    }
558                    DivergeResult::At(diverge) => {
559                        // Divergence before this node's discriminating bit —
560                        // create a new parent at the divergence point.
561                        debug_assert!(diverge < prefix_len, "prefix_matches said diverge but simd found no divergence before prefix_len");
562                        let new_bit = key_bit_at(new_key, diverge) as usize;
563                        let ref_bit = key_bit_at(ref_key, diverge) as usize;
564
565                        let mut new_parent = Node::new();
566                        new_parent.prefix_lens[ref_bit] = prefix_len as u16; // old node's prefix_len
567
568                        if diverge >= max_bits {
569                            // New key ends at the split point — terminal
570                            new_parent.set_terminal(true);
571                            new_parent.set_leaf_key_index(new_index);
572                        } else {
573                            new_parent.set_leaf_child(new_bit, new_index, max_bits as u16);
574                            new_parent.set_leaf_key_index(new_index);
575                        }
576
577                        let old_node = std::mem::replace(
578                            &mut self.arena[node_idx as usize],
579                            new_parent,
580                        );
581                        let old_idx = self.arena.len() as u32;
582                        self.arena.push(old_node);
583
584                        // Wire old node as internal child of new parent
585                        self.arena[node_idx as usize]
586                            .set_internal_child(ref_bit, old_idx, prefix_len as u16);
587
588                        // Update parent's prefix_lens to reflect the new prefix_len
589                        if let Some((pidx, pbit)) = parent_info {
590                            self.arena[pidx as usize].prefix_lens[pbit] = diverge as u16;
591                        } else {
592                            // We split the root
593                            self.root_prefix_len = diverge as u16;
594                        }
595
596                        return Ok(new_index as usize);
597                    }
598                }
599            }
600        }
601    }
602
603    // -----------------------------------------------------------------------
604    // Iteration
605    // -----------------------------------------------------------------------
606
607    pub fn iter(&self) -> Cursor<'_, K, V> {
608        Cursor::new(self)
609    }
610
611    pub fn iter_last(&self) -> Cursor<'_, K, V> {
612        Cursor::new_last(self)
613    }
614
615    /// Public forward mutable cursor: a lending tree-walk that hands out `&mut V`
616    /// borrows tied to the cursor (see [`CursorMut`]). Parked *before* the first
617    /// key — call `next()`/`first()` to position.
618    pub fn iter_mut(&mut self) -> CursorMut<'_, K, V> {
619        CursorMut::new(self)
620    }
621
622    /// Public reverse mutable cursor: a lending tree-walk parked *on* the last
623    /// key (see [`CursorMut`]).
624    pub fn iter_mut_last(&mut self) -> CursorMut<'_, K, V> {
625        CursorMut::new_last(self)
626    }
627
628    pub fn into_keys_values(self) -> (Vec<K>, Vec<V>) {
629        let keys = self.keys.into_keys();
630        (keys, self.values)
631    }
632}
633
634impl<K: TrieKey, V> Default for BitTrie<K, V> {
635    fn default() -> Self {
636        Self::new()
637    }
638}
639
640// ---------------------------------------------------------------------------
641// Iterator
642// ---------------------------------------------------------------------------
643
644pub struct Cursor<'a, K: TrieKey, V> {
645    trie: &'a BitTrie<K, V>,
646    /// Stack of (arena_index, which_child) pairs.
647    ///
648    /// - `arena_idx`: index into the arena (which node)
649    /// - `which_child`: 0 or 1 for child slots, `TERMINAL_POS` (2) for
650    ///   the terminal value, `u8::MAX` as a sentinel meaning "before first".
651    stack: Vec<(u32, u8)>,
652}
653
654impl<'a, K: TrieKey, V> Cursor<'a, K, V> {
655    fn new(trie: &'a BitTrie<K, V>) -> Self {
656        if trie.arena.is_empty() {
657            return Cursor { trie, stack: Vec::new() };
658        }
659        Cursor { trie, stack: vec![(0, u8::MAX)] }
660    }
661
662    fn new_last(trie: &'a BitTrie<K, V>) -> Self {
663        if trie.arena.is_empty() {
664            return Cursor { trie, stack: Vec::new() };
665        }
666        let mut iter = Cursor { trie, stack: Vec::new() };
667        iter.descend_last(0);
668        iter
669    }
670
671    /// Descend from internal node `idx` to its leftmost position.
672    /// If the first node encountered is terminal, position at its terminal value.
673    /// Otherwise find the leftmost child.
674    fn descend_first(&mut self, mut idx: u32) {
675        loop {
676            let node = &self.trie.arena[idx as usize];
677            if node.is_terminal() {
678                self.stack.push((idx, TERMINAL_POS));
679                return;
680            }
681            // Find leftmost non-empty child
682            if !node.is_empty(0) {
683                self.stack.push((idx, 0));
684                if node.is_leaf(0) {
685                    return;
686                } else {
687                    idx = node.child_index(0);
688                    continue;
689                }
690            }
691            if !node.is_empty(1) {
692                self.stack.push((idx, 1));
693                if node.is_leaf(1) {
694                    return;
695                } else {
696                    idx = node.child_index(1);
697                    continue;
698                }
699            }
700            // No children and not terminal — shouldn't happen in valid trie
701            return;
702        }
703    }
704
705    /// Descend from internal node `idx` to its rightmost position.
706    fn descend_last(&mut self, mut idx: u32) {
707        loop {
708            let node = &self.trie.arena[idx as usize];
709            // Try rightmost child first
710            if !node.is_empty(1) {
711                self.stack.push((idx, 1));
712                if node.is_leaf(1) {
713                    return;
714                } else {
715                    idx = node.child_index(1);
716                    continue;
717                }
718            }
719            if !node.is_empty(0) {
720                self.stack.push((idx, 0));
721                if node.is_leaf(0) {
722                    return;
723                } else {
724                    idx = node.child_index(0);
725                    continue;
726                }
727            }
728            // No children — terminal only
729            if node.is_terminal() {
730                self.stack.push((idx, TERMINAL_POS));
731            }
732            return;
733        }
734    }
735
736    /// Return the key and value at the current cursor position.
737    pub fn current(&self) -> Option<(&[u8], &V)> {
738        let ki = self.current_index()?;
739        let key = self.trie.keys.key_bytes(ki as u32);
740        let value = &self.trie.values[ki - 1];
741        Some((key, value))
742    }
743
744    /// Return just the key index at the current cursor position, skipping
745    /// key buffer and value reads. Useful when only the position matters.
746    pub fn current_index(&self) -> Option<usize> {
747        let &(arena_idx, which) = self.stack.last()?;
748        if which == u8::MAX {
749            return None;
750        }
751        let node = &self.trie.arena[arena_idx as usize];
752        if which == TERMINAL_POS {
753            Some(node.leaf_key_index_val() as usize)
754        } else {
755            node.leaf_key_index(which as usize).map(|ki| ki as usize)
756        }
757    }
758
759    /// Advance cursor to the next position. Returns `true` if positioned,
760    /// `false` if exhausted. Shared navigation for `next` and `next_index`.
761    #[inline]
762    fn advance_next(&mut self) -> bool {
763        loop {
764            let (arena_idx, which) = match self.stack.pop() {
765                Some(v) => v,
766                None => return false,
767            };
768
769            if which == TERMINAL_POS {
770                // After terminal — try children in order (bit 0, then bit 1)
771                let node = &self.trie.arena[arena_idx as usize];
772                if !node.is_empty(0) {
773                    self.stack.push((arena_idx, 0));
774                    if node.is_leaf(0) {
775                        return true;
776                    } else {
777                        self.descend_first(node.child_index(0));
778                        return true;
779                    }
780                }
781                if !node.is_empty(1) {
782                    self.stack.push((arena_idx, 1));
783                    if node.is_leaf(1) {
784                        return true;
785                    } else {
786                        self.descend_first(node.child_index(1));
787                        return true;
788                    }
789                }
790                // Terminal-only node with no children — pop up
791                continue;
792            }
793
794            if which == u8::MAX {
795                // Before-first — position at first entry
796                let node = &self.trie.arena[arena_idx as usize];
797                if node.is_terminal() {
798                    self.stack.push((arena_idx, TERMINAL_POS));
799                    return true;
800                }
801                for bit in 0..2u8 {
802                    if !node.is_empty(bit as usize) {
803                        self.stack.push((arena_idx, bit));
804                        if node.is_leaf(bit as usize) {
805                            return true;
806                        } else {
807                            self.descend_first(node.child_index(bit as usize));
808                            return true;
809                        }
810                    }
811                }
812                continue;
813            }
814
815            // After child `which` — try the next child or pop up
816            let search_bit = which as usize + 1;
817            if search_bit < 2 {
818                let node = &self.trie.arena[arena_idx as usize];
819                if !node.is_empty(search_bit) {
820                    self.stack.push((arena_idx, search_bit as u8));
821                    if node.is_leaf(search_bit) {
822                        return true;
823                    } else {
824                        self.descend_first(node.child_index(search_bit));
825                        return true;
826                    }
827                }
828            }
829            // No next child at this level — pop up
830        }
831    }
832
833    /// Advance cursor to the previous position. Returns `true` if positioned,
834    /// `false` if exhausted. Shared navigation for `prev` and `prev_index`.
835    #[inline]
836    fn advance_prev(&mut self) -> bool {
837        loop {
838            let (arena_idx, which) = match self.stack.pop() {
839                Some(v) => v,
840                None => return false,
841            };
842
843            if which == TERMINAL_POS {
844                // Before terminal in forward order = after terminal in backward.
845                // Going backward from terminal means going to parent's previous sibling.
846                continue;
847            }
848
849            if which == u8::MAX {
850                continue;
851            }
852
853            let bit = which as usize;
854
855            // Try the previous sibling
856            if bit > 0 {
857                let prev_bit = bit - 1;
858                let node = &self.trie.arena[arena_idx as usize];
859                if !node.is_empty(prev_bit) {
860                    self.stack.push((arena_idx, prev_bit as u8));
861                    if node.is_leaf(prev_bit) {
862                        return true;
863                    } else {
864                        self.descend_last(node.child_index(prev_bit));
865                        return true;
866                    }
867                }
868            }
869
870            // No previous sibling — check if this node is terminal.
871            // In backward order, terminal comes before children in forward,
872            // which means after children in backward.
873            if bit == 0 {
874                let node = &self.trie.arena[arena_idx as usize];
875                if node.is_terminal() {
876                    self.stack.push((arena_idx, TERMINAL_POS));
877                    return true;
878                }
879            }
880
881            // Pop up to parent
882        }
883    }
884
885    /// Advance to the next key in sorted order, returning key and value.
886    #[inline]
887    pub fn next(&mut self) -> Option<(&[u8], &V)> {
888        if self.advance_next() { self.current() } else { None }
889    }
890
891    /// Move to the previous key in sorted order, returning key and value.
892    #[inline]
893    pub fn prev(&mut self) -> Option<(&[u8], &V)> {
894        if self.advance_prev() { self.current() } else { None }
895    }
896
897    /// Advance to the next key, returning only its index.
898    #[inline]
899    pub fn next_index(&mut self) -> Option<usize> {
900        if self.advance_next() { self.current_index() } else { None }
901    }
902
903    /// Move to the previous key, returning only its index.
904    #[inline]
905    pub fn prev_index(&mut self) -> Option<usize> {
906        if self.advance_prev() { self.current_index() } else { None }
907    }
908
909    pub fn seek(&mut self, key: &[u8]) -> Option<(&[u8], &V)> {
910        if self.trie.arena.is_empty() {
911            self.stack.clear();
912            return None;
913        }
914
915        self.stack.clear();
916        let mut node_idx: u32 = 0;
917        let mut prefix_len = self.trie.root_prefix_len as usize;
918        let max_bits = key.len() * 8;
919
920        loop {
921            let node = &self.trie.arena[node_idx as usize];
922
923            // Check if key is exhausted at this node
924            if prefix_len >= max_bits {
925                if node.is_terminal() {
926                    self.stack.push((node_idx, TERMINAL_POS));
927                    return self.current();
928                }
929                // Key exhausted but node not terminal — find first child
930                for bit in 0..2u8 {
931                    if !node.is_empty(bit as usize) {
932                        self.stack.push((node_idx, bit));
933                        if node.is_leaf(bit as usize) {
934                            return self.current();
935                        } else {
936                            self.descend_first(node.child_index(bit as usize));
937                            return self.current();
938                        }
939                    }
940                }
941                // No children — need to advance forward
942                return self.next();
943            }
944
945            let bit = key_bit_at(key, prefix_len) as usize;
946            let child = node.children[bit];
947
948            if child != 0 {
949                self.stack.push((node_idx, bit as u8));
950                if child & LEAF_BIT != 0 {
951                    // Leaf — check if leaf key >= seek key
952                    let ki = child & !LEAF_BIT;
953                    let leaf_key = self.trie.keys.key_bytes(ki);
954                    if leaf_key >= key {
955                        return self.current();
956                    }
957                    // Leaf key < seek key — advance past it
958                    return self.next();
959                } else {
960                    // Internal — descend
961                    prefix_len = node.prefix_lens[bit] as usize;
962                    node_idx = child;
963                    continue;
964                }
965            }
966
967            // No child at this bit — try the other bit (higher)
968            let other_bit = 1 - bit;
969            let other_child = node.children[other_bit];
970            if other_child != 0 && other_bit > bit {
971                self.stack.push((node_idx, other_bit as u8));
972                if other_child & LEAF_BIT != 0 {
973                    return self.current();
974                } else {
975                    self.descend_first(other_child);
976                    return self.current();
977                }
978            }
979
980            // Check terminal before trying to go up
981            if node.is_terminal() && bit == 0 {
982                // Terminal key at this node — is it >= seek key?
983                let ki = node.leaf_key_index_val();
984                let term_key = self.trie.keys.key_bytes(ki);
985                if term_key >= key {
986                    self.stack.push((node_idx, TERMINAL_POS));
987                    return self.current();
988                }
989            }
990
991            // No higher child at this level — backtrack
992            loop {
993                let (parent_idx, parent_bit) = self.stack.pop()?;
994                if parent_bit == TERMINAL_POS || parent_bit == u8::MAX {
995                    // After terminal or before-first — try children from parent
996                    let parent = &self.trie.arena[parent_idx as usize];
997                    for next_bit in 0..2u8 {
998                        if !parent.is_empty(next_bit as usize) {
999                            self.stack.push((parent_idx, next_bit));
1000                            if parent.is_leaf(next_bit as usize) {
1001                                return self.current();
1002                            } else {
1003                                self.descend_first(parent.child_index(next_bit as usize));
1004                                return self.current();
1005                            }
1006                        }
1007                    }
1008                    continue;
1009                }
1010                if parent_bit == 0 {
1011                    // We came from child[0], try child[1]
1012                    let parent = &self.trie.arena[parent_idx as usize];
1013                    if !parent.is_empty(1) {
1014                        self.stack.push((parent_idx, 1));
1015                        if parent.is_leaf(1) {
1016                            return self.current();
1017                        } else {
1018                            self.descend_first(parent.child_index(1));
1019                            return self.current();
1020                        }
1021                    }
1022                }
1023                // Continue backtracking
1024            }
1025        }
1026    }
1027}
1028
1029// ---------------------------------------------------------------------------
1030// CursorMut — lending tree-walk iterator handing out &mut V
1031// ---------------------------------------------------------------------------
1032
1033/// Mutable counterpart to [`Cursor`]: a tree-walk iterator that lends out
1034/// `&mut V` borrows over the stored values, in sorted (DFS) key order.
1035///
1036/// Unlike [`Cursor`], the value reference is tied to `&mut self` (a *lending*
1037/// cursor), not to the trie lifetime `'a`. This is a soundness requirement, not
1038/// a stylistic choice: a cursor is re-positionable — `current()`, `seek()`,
1039/// `first()`, `last()` can all revisit a slot already visited. An `'a`-tied
1040/// `&mut V` (as the immutable cursor hands out `&'a V`) would let two such
1041/// calls return `&mut V` to the *same* element simultaneously — aliasing
1042/// undefined behavior. Tying the borrow to `&mut self` makes the borrow checker
1043/// enforce "one live `&mut V` at a time," which is the only sound rule for a
1044/// re-positionable mutable cursor. The practical consequence: you cannot
1045/// collect the `&mut V` into a `Vec` or hold two at once; each must be released
1046/// before the next `next()`/`prev()`/`current()`/`seek()` call. In-place
1047/// mutation loops (`while let Some((k, v)) = c.next() { *v += 1; }`) work as
1048/// expected.
1049///
1050/// The key is returned as `&[u8]` borrowing the trie's key store (zero
1051/// allocation, matching the immutable cursor's borrowed key). Both the key and
1052/// the `&mut V` are tied to `&mut self`. Only the stored *value* is mutated;
1053/// the cursor never alters key bytes, node structure, or slot occupancy, so
1054/// trie invariants are preserved.
1055pub struct CursorMut<'a, K: TrieKey, V> {
1056    trie: &'a mut BitTrie<K, V>,
1057    /// Stack of (arena_index, which_child) pairs — same shape as
1058    /// [`Cursor::stack`].
1059    stack: Vec<(u32, u8)>,
1060}
1061
1062impl<'a, K: TrieKey, V> CursorMut<'a, K, V> {
1063    /// Forward mutable cursor parked *before* the first key.
1064    pub fn new(trie: &'a mut BitTrie<K, V>) -> Self {
1065        if trie.arena.is_empty() {
1066            return CursorMut { trie, stack: Vec::new() };
1067        }
1068        CursorMut { trie, stack: vec![(0, u8::MAX)] }
1069    }
1070
1071    /// Reverse mutable cursor parked *on* the last key (or empty if the trie is
1072    /// empty).
1073    pub fn new_last(trie: &'a mut BitTrie<K, V>) -> Self {
1074        let mut c = CursorMut { trie, stack: Vec::new() };
1075        c.last();
1076        c
1077    }
1078
1079    fn descend_first(&mut self, mut idx: u32) {
1080        loop {
1081            let node = &self.trie.arena[idx as usize];
1082            if node.is_terminal() {
1083                self.stack.push((idx, TERMINAL_POS));
1084                return;
1085            }
1086            if !node.is_empty(0) {
1087                self.stack.push((idx, 0));
1088                if node.is_leaf(0) {
1089                    return;
1090                } else {
1091                    idx = node.child_index(0);
1092                    continue;
1093                }
1094            }
1095            if !node.is_empty(1) {
1096                self.stack.push((idx, 1));
1097                if node.is_leaf(1) {
1098                    return;
1099                } else {
1100                    idx = node.child_index(1);
1101                    continue;
1102                }
1103            }
1104            return;
1105        }
1106    }
1107
1108    fn descend_last(&mut self, mut idx: u32) {
1109        loop {
1110            let node = &self.trie.arena[idx as usize];
1111            if !node.is_empty(1) {
1112                self.stack.push((idx, 1));
1113                if node.is_leaf(1) {
1114                    return;
1115                } else {
1116                    idx = node.child_index(1);
1117                    continue;
1118                }
1119            }
1120            if !node.is_empty(0) {
1121                self.stack.push((idx, 0));
1122                if node.is_leaf(0) {
1123                    return;
1124                } else {
1125                    idx = node.child_index(0);
1126                    continue;
1127                }
1128            }
1129            if node.is_terminal() {
1130                self.stack.push((idx, TERMINAL_POS));
1131            }
1132            return;
1133        }
1134    }
1135
1136    /// The key/value the cursor is parked on, or `None` if not parked (before
1137    /// first, or exhausted). The key borrows the trie's key store and the
1138    /// `&mut V` reborrows the stored value — both tied to `&mut self`.
1139    ///
1140    /// `keys` and `values` are disjoint fields of the trie, so the shared key
1141    /// borrow (via `key_bytes`) and the mutable value borrow coexist without
1142    /// aliasing.
1143    #[inline]
1144    pub fn current(&mut self) -> Option<(&[u8], &mut V)> {
1145        let ki = self.current_index()?;
1146        let key = self.trie.keys.key_bytes(ki as u32);
1147        let value = &mut self.trie.values[ki - 1];
1148        Some((key, value))
1149    }
1150
1151    /// The key index the cursor is parked on, or `None` if not parked.
1152    #[inline]
1153    pub fn current_index(&self) -> Option<usize> {
1154        let &(arena_idx, which) = self.stack.last()?;
1155        if which == u8::MAX {
1156            return None;
1157        }
1158        let node = &self.trie.arena[arena_idx as usize];
1159        if which == TERMINAL_POS {
1160            Some(node.leaf_key_index_val() as usize)
1161        } else {
1162            node.leaf_key_index(which as usize).map(|ki| ki as usize)
1163        }
1164    }
1165
1166    #[inline]
1167    fn advance_next(&mut self) -> bool {
1168        loop {
1169            let (arena_idx, which) = match self.stack.pop() {
1170                Some(v) => v,
1171                None => return false,
1172            };
1173
1174            if which == TERMINAL_POS {
1175                let node = &self.trie.arena[arena_idx as usize];
1176                if !node.is_empty(0) {
1177                    self.stack.push((arena_idx, 0));
1178                    if node.is_leaf(0) {
1179                        return true;
1180                    } else {
1181                        self.descend_first(node.child_index(0));
1182                        return true;
1183                    }
1184                }
1185                if !node.is_empty(1) {
1186                    self.stack.push((arena_idx, 1));
1187                    if node.is_leaf(1) {
1188                        return true;
1189                    } else {
1190                        self.descend_first(node.child_index(1));
1191                        return true;
1192                    }
1193                }
1194                continue;
1195            }
1196
1197            if which == u8::MAX {
1198                let node = &self.trie.arena[arena_idx as usize];
1199                if node.is_terminal() {
1200                    self.stack.push((arena_idx, TERMINAL_POS));
1201                    return true;
1202                }
1203                for bit in 0..2u8 {
1204                    if !node.is_empty(bit as usize) {
1205                        self.stack.push((arena_idx, bit));
1206                        if node.is_leaf(bit as usize) {
1207                            return true;
1208                        } else {
1209                            self.descend_first(node.child_index(bit as usize));
1210                            return true;
1211                        }
1212                    }
1213                }
1214                continue;
1215            }
1216
1217            let search_bit = which as usize + 1;
1218            if search_bit < 2 {
1219                let node = &self.trie.arena[arena_idx as usize];
1220                if !node.is_empty(search_bit) {
1221                    self.stack.push((arena_idx, search_bit as u8));
1222                    if node.is_leaf(search_bit) {
1223                        return true;
1224                    } else {
1225                        self.descend_first(node.child_index(search_bit));
1226                        return true;
1227                    }
1228                }
1229            }
1230        }
1231    }
1232
1233    #[inline]
1234    fn advance_prev(&mut self) -> bool {
1235        loop {
1236            let (arena_idx, which) = match self.stack.pop() {
1237                Some(v) => v,
1238                None => return false,
1239            };
1240
1241            if which == TERMINAL_POS {
1242                continue;
1243            }
1244
1245            if which == u8::MAX {
1246                continue;
1247            }
1248
1249            let bit = which as usize;
1250
1251            if bit > 0 {
1252                let prev_bit = bit - 1;
1253                let node = &self.trie.arena[arena_idx as usize];
1254                if !node.is_empty(prev_bit) {
1255                    self.stack.push((arena_idx, prev_bit as u8));
1256                    if node.is_leaf(prev_bit) {
1257                        return true;
1258                    } else {
1259                        self.descend_last(node.child_index(prev_bit));
1260                        return true;
1261                    }
1262                }
1263            }
1264
1265            if bit == 0 {
1266                let node = &self.trie.arena[arena_idx as usize];
1267                if node.is_terminal() {
1268                    self.stack.push((arena_idx, TERMINAL_POS));
1269                    return true;
1270                }
1271            }
1272        }
1273    }
1274
1275    /// Jump to the first key (smallest in sorted order). Returns its key/value,
1276    /// or `None` if the trie is empty.
1277    pub fn first(&mut self) -> Option<(&[u8], &mut V)> {
1278        if self.trie.arena.is_empty() {
1279            self.stack.clear();
1280            return None;
1281        }
1282        self.stack.clear();
1283        self.stack.push((0, u8::MAX));
1284        if self.advance_next() { self.current() } else { None }
1285    }
1286
1287    /// Jump to the last key (largest in sorted order). Returns its key/value,
1288    /// or `None` if the trie is empty.
1289    pub fn last(&mut self) -> Option<(&[u8], &mut V)> {
1290        if self.trie.arena.is_empty() {
1291            self.stack.clear();
1292            return None;
1293        }
1294        self.stack.clear();
1295        self.descend_last(0);
1296        self.current()
1297    }
1298
1299    #[inline]
1300    pub fn next(&mut self) -> Option<(&[u8], &mut V)> {
1301        if self.advance_next() { self.current() } else { None }
1302    }
1303
1304    #[inline]
1305    pub fn prev(&mut self) -> Option<(&[u8], &mut V)> {
1306        if self.advance_prev() { self.current() } else { None }
1307    }
1308
1309    #[inline]
1310    pub fn next_index(&mut self) -> Option<usize> {
1311        if self.advance_next() { self.current_index() } else { None }
1312    }
1313
1314    #[inline]
1315    pub fn prev_index(&mut self) -> Option<usize> {
1316        if self.advance_prev() { self.current_index() } else { None }
1317    }
1318
1319    pub fn seek(&mut self, key: &[u8]) -> Option<(&[u8], &mut V)> {
1320        if self.trie.arena.is_empty() {
1321            self.stack.clear();
1322            return None;
1323        }
1324
1325        self.stack.clear();
1326        let mut node_idx: u32 = 0;
1327        let mut prefix_len = self.trie.root_prefix_len as usize;
1328        let max_bits = key.len() * 8;
1329
1330        loop {
1331            let node = &self.trie.arena[node_idx as usize];
1332
1333            if prefix_len >= max_bits {
1334                if node.is_terminal() {
1335                    self.stack.push((node_idx, TERMINAL_POS));
1336                    return self.current();
1337                }
1338                for bit in 0..2u8 {
1339                    if !node.is_empty(bit as usize) {
1340                        self.stack.push((node_idx, bit));
1341                        if node.is_leaf(bit as usize) {
1342                            return self.current();
1343                        } else {
1344                            self.descend_first(node.child_index(bit as usize));
1345                            return self.current();
1346                        }
1347                    }
1348                }
1349                return self.next();
1350            }
1351
1352            let bit = key_bit_at(key, prefix_len) as usize;
1353            let child = node.children[bit];
1354
1355            if child != 0 {
1356                self.stack.push((node_idx, bit as u8));
1357                if child & LEAF_BIT != 0 {
1358                    let ki = child & !LEAF_BIT;
1359                    let leaf_key = self.trie.keys.key_bytes(ki);
1360                    if leaf_key >= key {
1361                        return self.current();
1362                    }
1363                    return self.next();
1364                } else {
1365                    prefix_len = node.prefix_lens[bit] as usize;
1366                    node_idx = child;
1367                    continue;
1368                }
1369            }
1370
1371            let other_bit = 1 - bit;
1372            let other_child = node.children[other_bit];
1373            if other_child != 0 && other_bit > bit {
1374                self.stack.push((node_idx, other_bit as u8));
1375                if other_child & LEAF_BIT != 0 {
1376                    return self.current();
1377                } else {
1378                    self.descend_first(other_child);
1379                    return self.current();
1380                }
1381            }
1382
1383            if node.is_terminal() && bit == 0 {
1384                let ki = node.leaf_key_index_val();
1385                let term_key = self.trie.keys.key_bytes(ki);
1386                if term_key >= key {
1387                    self.stack.push((node_idx, TERMINAL_POS));
1388                    return self.current();
1389                }
1390            }
1391
1392            loop {
1393                let (parent_idx, parent_bit) = self.stack.pop()?;
1394                if parent_bit == TERMINAL_POS || parent_bit == u8::MAX {
1395                    let parent = &self.trie.arena[parent_idx as usize];
1396                    for next_bit in 0..2u8 {
1397                        if !parent.is_empty(next_bit as usize) {
1398                            self.stack.push((parent_idx, next_bit));
1399                            if parent.is_leaf(next_bit as usize) {
1400                                return self.current();
1401                            } else {
1402                                self.descend_first(parent.child_index(next_bit as usize));
1403                                return self.current();
1404                            }
1405                        }
1406                    }
1407                    continue;
1408                }
1409                if parent_bit == 0 {
1410                    let parent = &self.trie.arena[parent_idx as usize];
1411                    if !parent.is_empty(1) {
1412                        self.stack.push((parent_idx, 1));
1413                        if parent.is_leaf(1) {
1414                            return self.current();
1415                        } else {
1416                            self.descend_first(parent.child_index(1));
1417                            return self.current();
1418                        }
1419                    }
1420                }
1421            }
1422        }
1423    }
1424}
1425
1426// ---------------------------------------------------------------------------
1427// Tests
1428// ---------------------------------------------------------------------------
1429
1430#[cfg(test)]
1431#[path = "tests/bit_trie.rs"]
1432mod tests;