1use crate::nibble_trie::TrieIndex;
38use std::{fmt, simd::{Simd, cmp::SimdPartialEq}};
39
40#[derive(Copy, Clone)]
51pub(crate) struct NibNode<PTR: TrieIndex = u32, LEN: TrieIndex = u16> {
52 pub(crate) children: [PTR; 4], pub(crate) leaf: PTR, pub(crate) prefix_len: LEN, pub(crate) leaf_mask: u8, pub(crate) occupancy: u8, pub(crate) terminal: u8, }
59
60impl<PTR: TrieIndex, LEN: TrieIndex> NibNode<PTR, LEN> {
61 pub(crate) fn new() -> Self {
62 NibNode {
63 children: [PTR::max_value_sentinel(); 4],
64 leaf: PTR::max_value_sentinel(),
65 prefix_len: LEN::zero(),
66 leaf_mask: 0,
67 occupancy: 0,
68 terminal: 0,
69 }
70 }
71
72 #[inline]
74 pub(crate) fn is_terminal(&self) -> bool {
75 self.terminal != 0
76 }
77
78 #[inline]
80 fn set_terminal(&mut self, val: bool) {
81 if val {
82 self.terminal = 1;
83 } else {
84 self.terminal = 0;
85 }
86 }
87
88 #[inline]
90 pub(crate) fn is_leaf(&self, nib: usize) -> bool {
91 debug_assert!(nib < 4);
92 (self.leaf_mask >> nib) & 1 == 1
93 }
94
95 #[inline]
97 fn set_leaf(&mut self, nib: usize) {
98 debug_assert!(nib < 4);
99 self.leaf_mask |= 1 << nib;
100 }
101
102 #[inline]
104 fn clear_leaf(&mut self, nib: usize) {
105 debug_assert!(nib < 4);
106 self.leaf_mask &= !(1 << nib);
107 }
108
109 #[inline]
111 pub(crate) fn is_occupied(&self, nib: usize) -> bool {
112 debug_assert!(nib < 4);
113 (self.occupancy >> nib) & 1 == 1
114 }
115
116 #[inline]
118 fn set_occupied(&mut self, nib: usize) {
119 debug_assert!(nib < 4);
120 self.occupancy |= 1 << nib;
121 }
122
123 #[inline]
125 fn set_leaf_child(&mut self, nib: usize, key_index: PTR) {
126 debug_assert!(nib < 4);
127 debug_assert!(key_index != PTR::max_value_sentinel(), "sentinel key index");
128 self.set_leaf(nib);
129 self.set_occupied(nib);
130 self.children[nib] = key_index;
131 }
132
133 #[inline]
135 fn set_internal_child(&mut self, nib: usize, addr: PTR) {
136 debug_assert!(nib < 4);
137 debug_assert!(addr != PTR::max_value_sentinel(), "sentinel address");
138 self.clear_leaf(nib);
139 self.set_occupied(nib);
140 self.children[nib] = addr;
141 }
142
143 #[inline]
146 fn leaf_key_index(&self, nib: usize) -> Option<PTR> {
147 debug_assert!(nib < 4);
148 if self.is_leaf(nib) && self.is_occupied(nib) {
149 Some(self.children[nib])
150 } else {
151 None
152 }
153 }
154
155 #[allow(dead_code)]
157 #[inline]
158 pub(crate) fn children_mask(&self) -> u8 {
159 self.occupancy
160 }
161
162 pub(crate) fn promote<NewPTR: TrieIndex>(self) -> NibNode<NewPTR, LEN> {
164 let mut children = [NewPTR::max_value_sentinel(); 4];
165 for i in 0..4 {
166 if self.occupancy & (1 << i) != 0 {
167 children[i] = NewPTR::from_usize(self.children[i].as_usize());
168 }
169 }
170 NibNode {
171 children,
172 leaf: if self.leaf == PTR::max_value_sentinel() {
173 NewPTR::max_value_sentinel()
174 } else {
175 NewPTR::from_usize(self.leaf.as_usize())
176 },
177 prefix_len: self.prefix_len,
178 leaf_mask: self.leaf_mask,
179 occupancy: self.occupancy,
180 terminal: self.terminal,
181 }
182 }
183
184 pub(crate) fn demote<NewPTR: TrieIndex>(self) -> Result<NibNode<NewPTR, LEN>, Self> {
187 for i in 0..4 {
188 if self.occupancy & (1 << i) != 0 {
189 if self.children[i].as_usize() > NewPTR::max_value() {
190 return Err(self);
191 }
192 }
193 }
194 if self.leaf != PTR::max_value_sentinel() && self.leaf.as_usize() > NewPTR::max_value() {
195 return Err(self);
196 }
197 let mut children = [NewPTR::max_value_sentinel(); 4];
198 for i in 0..4 {
199 if self.occupancy & (1 << i) != 0 {
200 children[i] = NewPTR::from_usize(self.children[i].as_usize());
201 }
202 }
203 Ok(NibNode {
204 children,
205 leaf: if self.leaf == PTR::max_value_sentinel() {
206 NewPTR::max_value_sentinel()
207 } else {
208 NewPTR::from_usize(self.leaf.as_usize())
209 },
210 prefix_len: self.prefix_len,
211 leaf_mask: self.leaf_mask,
212 occupancy: self.occupancy,
213 terminal: self.terminal,
214 })
215 }
216}
217
218impl<PTR: TrieIndex, LEN: TrieIndex> fmt::Debug for NibNode<PTR, LEN> {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 let active: Vec<(usize, &str, PTR)> = (0..4)
221 .filter(|&n| self.occupancy & (1 << n) != 0)
222 .map(|n| {
223 let tag = if (self.leaf_mask >> n) & 1 == 1 { "L" } else { "I" };
224 (n, tag, self.children[n])
225 })
226 .collect();
227 f.debug_struct("NibNode")
228 .field("prefix_len", &self.prefix_len)
229 .field("leaf_mask", &format_args!("{:04b}", self.leaf_mask))
230 .field("occupancy", &format_args!("{:04b}", self.occupancy))
231 .field("terminal", &self.terminal)
232 .field("leaf", &self.leaf)
233 .field("children", &active)
234 .finish()
235 }
236}
237
238#[derive(Clone)]
243pub struct NibTrie<T, PTR: TrieIndex = u32, LEN: TrieIndex = u16> {
244 pub(crate) arena: Vec<NibNode<PTR, LEN>>,
245 pub(crate) buf: Vec<u8>, pub(crate) index: Vec<(usize, LEN)>, pub(crate) values: Vec<T>, }
249
250enum DivergeResult {
255 Duplicate,
257 At(usize),
259}
260
261enum PrefixCheck {
262 Matches,
264 Diverges(usize),
266}
267
268#[inline]
273fn simd_eq(a: &[u8], b: &[u8]) -> bool {
274 if a.len() != b.len() {
275 return false;
276 }
277 let len = a.len();
278 let mut i = 0;
279 while i + 16 <= len {
280 let va = Simd::<u8, 16>::from_slice(unsafe { a.get_unchecked(i..i + 16) });
281 let vb = Simd::<u8, 16>::from_slice(unsafe { b.get_unchecked(i..i + 16) });
282 if va.simd_ne(vb).any() {
283 return false;
284 }
285 i += 16;
286 }
287 while i < len {
288 if unsafe { *a.get_unchecked(i) != *b.get_unchecked(i) } {
289 return false;
290 }
291 i += 1;
292 }
293 true
294}
295
296
297#[inline]
311fn key_nib_at(key: &[u8], idx: usize) -> u8 {
312 let byte_idx = idx / 4;
313 if byte_idx < key.len() {
314 let shift = 6 - 2 * (idx % 4); (key[byte_idx] >> shift) & 0x03
316 } else {
317 0
318 }
319}
320
321#[inline]
326unsafe fn key_nib_at_unchecked(key: &[u8], idx: usize) -> u8 {
327 let byte_idx = idx / 4;
328 debug_assert!(byte_idx < key.len(), "nib {idx} out of bounds for key len {}", key.len());
329 let shift = 6 - 2 * (idx % 4);
330 (unsafe { *key.get_unchecked(byte_idx) } >> shift) & 0x03
331}
332
333#[inline]
334fn nib_count(key: &[u8]) -> usize {
335 key.len() * 4
336}
337
338#[inline]
342fn diverging_nib(xor: u8, byte_idx: usize) -> usize {
343 byte_idx * 4 + (xor.leading_zeros() as usize) / 2
344}
345
346#[inline]
348fn find_divergence(key_a: &[u8], key_b: &[u8], from: usize) -> DivergeResult {
349 let total_a = nib_count(key_a);
350 let total_b = nib_count(key_b);
351 let min = total_a.min(total_b);
352 let mut d = from;
353 while d < min {
354 if key_nib_at(key_a, d) != key_nib_at(key_b, d) {
355 return DivergeResult::At(d);
356 }
357 d += 1;
358 }
359 if total_a == total_b {
360 DivergeResult::Duplicate
361 } else {
362 DivergeResult::At(d)
363 }
364}
365
366fn simd_find_divergence<const N: usize>(key_a: &[u8], key_b: &[u8], from: usize) -> DivergeResult
367where
368{
369 let minlen = key_a.len().min(key_b.len());
370 let mut i = from / 4; while i + N <= minlen {
373 let a = Simd::<u8, N>::from_slice(unsafe { key_a.get_unchecked(i..i + N) });
374 let b = Simd::<u8, N>::from_slice(unsafe { key_b.get_unchecked(i..i + N) });
375 let mask = a.simd_ne(b);
376 if mask.any() {
377 let diff_byte_idx = i + mask.first_set().unwrap();
378 let xor = unsafe { *key_a.get_unchecked(diff_byte_idx) ^ *key_b.get_unchecked(diff_byte_idx) };
379 return DivergeResult::At(diverging_nib(xor, diff_byte_idx));
380 }
381 i += N;
382 }
383
384 find_divergence(key_a, key_b, i * 4)
386}
387
388#[inline]
391fn check_prefix(key_a: &[u8], key_b: &[u8], from: usize, to: usize) -> PrefixCheck {
392 for nib in from..to {
393 if key_nib_at(key_a, nib) != key_nib_at(key_b, nib) {
394 return PrefixCheck::Diverges(nib);
395 }
396 }
397 PrefixCheck::Matches
398}
399
400fn simd_check_prefix<const N: usize>(key_a: &[u8], key_b: &[u8], from: usize, to: usize) -> PrefixCheck
402where
403{
404 if from >= to {
405 return PrefixCheck::Matches;
406 }
407
408 let from_byte = from / 4;
409 let to_byte = (to + 3) / 4; let minlen = key_a.len().min(key_b.len()).min(to_byte);
411 let mut i = from_byte;
412
413 while i + N <= minlen {
414 let a = Simd::<u8, N>::from_slice(unsafe { key_a.get_unchecked(i..i + N) });
415 let b = Simd::<u8, N>::from_slice(unsafe { key_b.get_unchecked(i..i + N) });
416 let mask = a.simd_ne(b);
417 if mask.any() {
418 let diff_byte_idx = i + mask.first_set().unwrap();
419 let xor = unsafe { *key_a.get_unchecked(diff_byte_idx) ^ *key_b.get_unchecked(diff_byte_idx) };
420 let nib = diverging_nib(xor, diff_byte_idx);
421 if nib < to {
422 return PrefixCheck::Diverges(nib);
423 }
424 return PrefixCheck::Matches;
426 }
427 i += N;
428 }
429
430 check_prefix(key_a, key_b, i * 4, to)
432}
433
434impl<T, PTR: TrieIndex, LEN: TrieIndex> NibTrie<T, PTR, LEN> {
439 #[inline]
441 fn key_slice(&self, key_index: PTR) -> &[u8] {
442 let (off, len) = self.index[key_index.as_usize()];
443 &self.buf[off..off + len.as_usize()]
444 }
445
446 pub fn new() -> Self {
447 NibTrie {
448 arena: Vec::new(),
449 buf: vec![0], index: vec![(0, LEN::zero())], values: Vec::new(),
452 }
453 }
454
455 pub fn len(&self) -> usize {
456 self.index.len() - 1 }
458
459 pub fn is_empty(&self) -> bool {
460 self.index.len() == 1 }
462
463 pub fn get_index(&self, key: &[u8]) -> Option<usize> {
468 if self.arena.is_empty() {
469 return None;
470 }
471 let mut node_idx: usize = 0;
472 let max_nib = key.len() * 4;
473 loop {
474 let node = &self.arena[node_idx];
475 let prefix_len = node.prefix_len.as_usize();
476
477 if prefix_len >= max_nib {
479 if node.is_terminal() {
480 let ki = node.leaf;
481 let (off, len) = self.index[ki.as_usize()];
482 let key_in_buf = &self.buf[off..off + len.as_usize()];
483 if key.len() == len.as_usize() && simd_eq(&key_in_buf[..key.len()], key) {
484 return Some(ki.as_usize());
485 }
486 }
487 return None;
488 }
489
490 let nib = unsafe { key_nib_at_unchecked(key, prefix_len) } as usize;
492 let slot = node.children[nib];
493 if slot == PTR::max_value_sentinel() {
494 return None;
495 }
496 if (node.leaf_mask >> nib) & 1 == 1 {
497 let key_index = slot;
499 return if simd_eq(self.key_slice(key_index), key) {
500 Some(key_index.as_usize())
501 } else {
502 None
503 };
504 }
505 node_idx = slot.as_usize();
507 }
508 }
509
510 #[cfg(feature = "unchecked")]
515 unsafe fn get_index_unchecked(&self, key: &[u8]) -> Option<usize> {
516 if self.arena.is_empty() {
517 return None;
518 }
519 let mut node_idx: usize = 0;
520 let max_nib = key.len() * 4;
521 loop {
522 let node = unsafe { self.arena.get_unchecked(node_idx) };
523 let prefix_len = node.prefix_len.as_usize();
524 if prefix_len >= max_nib {
525 debug_assert!(node.is_terminal(), "get_unchecked: key not in set");
526 return Some(node.leaf.as_usize());
527 }
528 let nib = unsafe { key_nib_at_unchecked(key, prefix_len) } as usize;
529 let slot = unsafe { *node.children.get_unchecked(nib) };
530 if slot == PTR::max_value_sentinel() {
531 return None;
532 }
533 if (node.leaf_mask >> nib) & 1 == 1 {
534 return Some(slot.as_usize());
535 }
536 node_idx = slot.as_usize();
537 }
538 }
539
540 pub fn get(&self, key: &[u8]) -> Option<&T> {
541 self.get_index(key).map(|idx| &self.values[idx - 1])
542 }
543
544 pub fn get_mut(&mut self, key: &[u8]) -> Option<&mut T> {
545 self.get_index(key).map(|idx| &mut self.values[idx - 1])
546 }
547
548 #[cfg(feature = "unchecked")]
553 pub unsafe fn get_unchecked(&self, key: &[u8]) -> Option<&T> {
554 unsafe { self.get_index_unchecked(key).map(|idx| &self.values[idx - 1]) }
555 }
556
557 pub fn iter(&self) -> Cursor<'_, T, PTR, LEN> {
562 Cursor::new(self)
563 }
564
565 pub fn iter_last(&self) -> Cursor<'_, T, PTR, LEN> {
566 Cursor::new_last(self)
567 }
568
569 pub fn iter_mut(&mut self) -> CursorMut<'_, T, PTR, LEN> {
573 CursorMut::new(self)
574 }
575
576 pub fn iter_mut_last(&mut self) -> CursorMut<'_, T, PTR, LEN> {
579 CursorMut::new_last(self)
580 }
581
582 pub fn into_keys_values(self) -> (Vec<Vec<u8>>, Vec<T>) {
583 let buf = self.buf;
584 let keys: Vec<Vec<u8>> = self.index.into_iter().skip(1).map(|(off, len)| {
585 buf[off..off + len.as_usize()].to_vec()
586 }).collect();
587 (keys, self.values)
588 }
589
590 pub fn near_capacity(&self) -> bool {
595 self.arena.len() >= PTR::max_value() || self.index.len() >= PTR::max_value()
596 }
597
598 pub fn optimize(&mut self) {
604 if self.arena.is_empty() {
605 return;
606 }
607
608 let mut new_buf = vec![0u8; self.buf.len()];
609 let mut cursor: usize = 1; let mut remap: Vec<usize> = vec![0; self.arena.len()];
613
614 let mut new_arena: Vec<NibNode<PTR, LEN>> = Vec::new();
615
616 let mut dfs_key_order: Vec<PTR> = Vec::new();
618
619 self.walk_optimize(
620 0,
621 &mut new_buf, &mut cursor,
622 &mut remap, &mut new_arena,
623 &mut dfs_key_order,
624 );
625
626 new_buf.truncate(cursor);
627 self.buf = new_buf;
628 self.arena = new_arena;
629
630 for node in &mut self.arena {
632 for nib in 0..4 {
633 if node.occupancy & (1 << nib) != 0 && !node.is_leaf(nib) {
634 let old_addr = node.children[nib].as_usize();
635 debug_assert!(old_addr < remap.len(), "old_addr {} >= remap.len() {}", old_addr, remap.len());
636 debug_assert!(!(remap[old_addr] == 0 && old_addr != 0), "remap[{}] == 0 but old_addr != 0", old_addr);
637 node.children[nib] = PTR::from_usize(remap[old_addr]);
638 }
639 }
640 }
641
642 let num_keys = dfs_key_order.len();
645 let mut key_remap: Vec<usize> = vec![0; self.index.len()];
646 key_remap[0] = 0; for (new_ki, &old_ki) in dfs_key_order.iter().enumerate() {
648 key_remap[old_ki.as_usize()] = new_ki + 1; }
650
651 for node in &mut self.arena {
653 for nib in 0..4 {
654 if node.occupancy & (1 << nib) != 0 && node.is_leaf(nib) {
655 let old_ki = node.children[nib].as_usize();
656 let new_ki = key_remap[old_ki];
657 node.children[nib] = PTR::from_usize(new_ki);
658 }
659 }
660 let old_leaf = node.leaf;
662 if old_leaf != PTR::max_value_sentinel() {
663 let new_ki = key_remap[old_leaf.as_usize()];
664 node.leaf = PTR::from_usize(new_ki);
665 }
666 }
667
668 let mut new_index: Vec<(usize, LEN)> = vec![(0, LEN::zero()); num_keys + 1];
670 new_index[0] = self.index[0]; for (new_ki, &old_ki) in dfs_key_order.iter().enumerate() {
672 new_index[new_ki + 1] = self.index[old_ki.as_usize()];
673 }
674
675 let mut new_values = Vec::with_capacity(num_keys);
677 unsafe {
678 let old_values_ptr = self.values.as_ptr();
679 for &old_ki in &dfs_key_order {
680 let old_val = std::ptr::read(old_values_ptr.add(old_ki.as_usize() - 1));
681 new_values.push(old_val);
682 }
683 }
684 unsafe { self.values.set_len(0); }
685 std::mem::swap(&mut self.values, &mut new_values);
686 self.index = new_index;
687 }
688
689 fn walk_optimize(
690 &mut self,
691 old_idx: usize,
692 new_buf: &mut [u8],
693 cursor: &mut usize,
694 remap: &mut Vec<usize>,
695 new_arena: &mut Vec<NibNode<PTR, LEN>>,
696 dfs_key_order: &mut Vec<PTR>,
697 ) {
698 let node = self.arena[old_idx]; let occ = node.occupancy;
700 let is_term = node.is_terminal();
701
702 let new_idx = new_arena.len();
703 new_arena.push(NibNode::new());
704 remap[old_idx] = new_idx;
705
706 new_arena[new_idx].prefix_len = node.prefix_len;
708 new_arena[new_idx].occupancy = occ;
709 new_arena[new_idx].leaf_mask = node.leaf_mask;
710 if is_term {
711 new_arena[new_idx].set_terminal(true);
712 }
713
714 if is_term {
716 let ki = node.leaf;
717 let (old_off, len) = self.index[ki.as_usize()];
718 let start = *cursor;
719 new_buf[start..start + len.as_usize()].copy_from_slice(
720 &self.buf[old_off..old_off + len.as_usize()]
721 );
722 self.index[ki.as_usize()].0 = *cursor;
723 *cursor += len.as_usize();
724 new_arena[new_idx].leaf = ki;
725 dfs_key_order.push(ki);
726 }
727
728 for nib in 0..4 {
730 if (occ >> nib) & 1 == 0 {
731 continue;
732 }
733 if node.is_leaf(nib) {
734 let ki = node.children[nib];
736 let (old_off, len) = self.index[ki.as_usize()];
737 let start = *cursor;
738 new_buf[start..start + len.as_usize()].copy_from_slice(
739 &self.buf[old_off..old_off + len.as_usize()]
740 );
741 self.index[ki.as_usize()].0 = *cursor;
742 *cursor += len.as_usize();
743 new_arena[new_idx].children[nib] = ki;
744 dfs_key_order.push(ki);
745 } else {
746 let child_old_addr = node.children[nib].as_usize();
748 self.walk_optimize(
749 child_old_addr,
750 new_buf, cursor,
751 remap, new_arena,
752 dfs_key_order,
753 );
754 new_arena[new_idx].children[nib] = node.children[nib];
756 }
757 }
758
759 if !is_term && new_arena[new_idx].leaf == PTR::max_value_sentinel() {
761 let first_nib = occ.trailing_zeros() as usize;
762 if new_arena[new_idx].is_leaf(first_nib) {
763 new_arena[new_idx].leaf = new_arena[new_idx].children[first_nib];
764 } else {
765 let child_old_addr = node.children[first_nib].as_usize();
766 if child_old_addr < remap.len() {
767 let child_new_idx = remap[child_old_addr];
768 new_arena[new_idx].leaf = new_arena[child_new_idx].leaf;
769 }
770 }
771 }
772 }
773}
774
775impl<T, PTR: TrieIndex, LEN: TrieIndex> Default for NibTrie<T, PTR, LEN> {
776 fn default() -> Self { Self::new() }
777}
778
779impl<T, PTR: TrieIndex, LEN: TrieIndex> NibTrie<T, PTR, LEN> {
784 pub fn insert(&mut self, key: Vec<u8>, value: T) -> Result<usize, ()> {
785 if self.arena.len() >= PTR::max_value() || self.index.len() >= PTR::max_value() {
787 return Err(());
788 }
789 if key.len() * 4 > LEN::max_value() {
790 return Err(());
791 }
792
793 let new_index = PTR::from_usize(self.index.len());
794 let key_len = LEN::from_usize(key.len());
795 let offset = self.buf.len() as usize;
796 self.buf.extend_from_slice(&key);
797 self.index.push((offset, key_len));
798 self.values.push(value);
799
800 let max_nib = key.len() * 4;
801
802 if self.arena.is_empty() {
803 return Ok(self.insert_into_empty_trie(&key, new_index, max_nib));
804 }
805
806 let mut node_idx: usize = 0;
807 let mut confirmed: usize = 0;
808
809 loop {
810 let node = &self.arena[node_idx];
811 let ki = node.leaf;
812 let (off, ref_len) = self.index[ki.as_usize()];
813 let ref_key = &self.buf[off..off + ref_len.as_usize()];
814 let prefix_len = node.prefix_len.as_usize();
815
816 match simd_check_prefix::<8>(&key, ref_key, confirmed, prefix_len) {
817 PrefixCheck::Diverges(diverge) => {
818 return Ok(self.split_node_before_prefix(
819 node_idx, diverge, new_index, &key, max_nib,
820 ));
821 }
822 PrefixCheck::Matches => {
823 if max_nib == prefix_len {
824 if key.len() == ref_key.len() {
825 self.rollback_last_insert();
826 return Err(());
827 }
828 self.arena[node_idx].set_terminal(true);
829 self.arena[node_idx].leaf = new_index;
830 return Ok(new_index.as_usize());
831 }
832
833 confirmed = prefix_len + 1;
834 let nib = key_nib_at(&key, prefix_len) as usize;
835 if !node.is_occupied(nib) {
836 self.arena[node_idx].set_leaf_child(nib, new_index);
838 return Ok(new_index.as_usize());
839 }
840 let slot = node.children[nib];
841
842 if node.is_leaf(nib) {
843 return self.split_leaf_child(
844 nib, node_idx, slot, new_index, &key, max_nib, confirmed,
845 );
846 }
847
848 node_idx = slot.as_usize();
850 }
851 }
852 }
853 }
854
855 #[inline]
860 fn rollback_last_insert(&mut self) {
861 let (off, _len) = self.index.pop().unwrap();
862 self.buf.truncate(off);
863 let _ = self.values.pop();
864 }
865
866 #[inline]
867 fn insert_into_empty_trie(&mut self, key: &[u8], new_index: PTR, max_nib: usize) -> usize {
868 if max_nib == 0 {
869 let mut root = NibNode::new();
870 root.set_terminal(true);
871 root.leaf = new_index;
872 root.prefix_len = LEN::zero();
873 self.arena.push(root);
874 return new_index.as_usize();
875 }
876 let first_nib = key_nib_at(key, 0) as usize;
877 let mut root = NibNode::new();
878 root.set_leaf_child(first_nib, new_index);
879 root.leaf = new_index;
880 root.prefix_len = LEN::zero();
881 self.arena.push(root);
882 new_index.as_usize()
883 }
884
885 #[inline]
886 fn split_node_before_prefix(
887 &mut self,
888 node_idx: usize,
889 diverge: usize,
890 new_index: PTR,
891 key: &[u8],
892 max_nib: usize,
893 ) -> usize {
894 let node = &self.arena[node_idx];
895 let ki = node.leaf;
896 let (off, ref_len) = self.index[ki.as_usize()];
897 let ref_key = &self.buf[off..off + ref_len.as_usize()];
898
899 let new_nib = key_nib_at(key, diverge) as usize;
900 let ref_nib = key_nib_at(ref_key, diverge) as usize;
901
902 let mut new_parent = NibNode::new();
903 new_parent.prefix_len = LEN::from_usize(diverge);
904
905 if diverge >= max_nib {
906 new_parent.set_terminal(true);
907 new_parent.leaf = new_index;
908 } else {
909 new_parent.set_leaf_child(new_nib, new_index);
910 new_parent.leaf = new_index;
911 }
912
913 let old_node = std::mem::replace(&mut self.arena[node_idx], new_parent);
914 let old_addr = PTR::from_usize(self.arena.len()); self.arena.push(old_node);
916
917 self.arena[node_idx].set_internal_child(ref_nib, old_addr);
918
919 new_index.as_usize()
920 }
921
922 #[inline]
923 fn split_leaf_child(
924 &mut self,
925 nib: usize,
926 node_idx: usize,
927 existing_key_index: PTR,
928 new_index: PTR,
929 key: &[u8],
930 max_nib: usize,
931 confirmed: usize,
932 ) -> Result<usize, ()> {
933 let (existing_offset, existing_len) = self.index[existing_key_index.as_usize()];
934 let existing_key = &self.buf[existing_offset..existing_offset + existing_len.as_usize()];
935
936 match simd_find_divergence::<8>(key, existing_key, confirmed) {
937 DivergeResult::Duplicate => {
938 self.rollback_last_insert();
939 Err(())
940 }
941 DivergeResult::At(d) => {
942 let mut split_node = NibNode::new();
943 split_node.prefix_len = LEN::from_usize(d);
944
945 if d >= max_nib {
946 let exist_nib = key_nib_at(existing_key, d) as usize;
948 split_node.set_terminal(true);
949 split_node.leaf = new_index;
950 split_node.set_leaf_child(exist_nib, existing_key_index);
951 } else if d >= existing_key.len() * 4 {
952 let new_nib = key_nib_at(key, d) as usize;
954 split_node.set_terminal(true);
955 split_node.leaf = existing_key_index;
956 split_node.set_leaf_child(new_nib, new_index);
957 } else {
958 let new_nib = key_nib_at(key, d) as usize;
960 let exist_nib = key_nib_at(existing_key, d) as usize;
961 debug_assert_ne!(new_nib, exist_nib);
962 split_node.set_leaf_child(new_nib, new_index);
963 split_node.set_leaf_child(exist_nib, existing_key_index);
964 split_node.leaf = existing_key_index;
965 }
966
967 let split_addr = PTR::from_usize(self.arena.len());
968 self.arena.push(split_node);
969 self.arena[node_idx].set_internal_child(nib, split_addr);
970
971 Ok(new_index.as_usize())
972 }
973 }
974 }
975}
976
977impl<T, PTR: TrieIndex, LEN: TrieIndex> NibTrie<T, PTR, LEN> {
982 pub fn promote<NewPTR: TrieIndex>(self) -> NibTrie<T, NewPTR, LEN> {
984 let arena = self.arena.into_iter().map(|node| node.promote()).collect();
985 NibTrie {
986 arena,
987 buf: self.buf,
988 index: self.index,
989 values: self.values,
990 }
991 }
992
993 pub fn demote<NewPTR: TrieIndex>(self) -> Result<NibTrie<T, NewPTR, LEN>, Self> {
996 if self.arena.len() > NewPTR::max_value() || self.index.len() > NewPTR::max_value() {
997 return Err(self);
998 }
999 for node in &self.arena {
1000 if let Err(_) = node.demote::<NewPTR>() {
1001 return Err(self);
1002 }
1003 }
1004 let arena = self.arena.into_iter().map(|node| {
1005 node.demote().expect("demote capacity check should have caught this")
1006 }).collect();
1007 Ok(NibTrie {
1008 arena,
1009 buf: self.buf,
1010 index: self.index,
1011 values: self.values,
1012 })
1013 }
1014}
1015
1016const TERMINAL_NIB: usize = 4;
1022
1023pub struct Cursor<'a, T, PTR: TrieIndex, LEN: TrieIndex> {
1024 trie: &'a NibTrie<T, PTR, LEN>,
1025 stack: Vec<(usize, u8, usize)>,
1027}
1028
1029impl<'a, T, PTR: TrieIndex, LEN: TrieIndex> Cursor<'a, T, PTR, LEN> {
1030 fn new(trie: &'a NibTrie<T, PTR, LEN>) -> Self {
1031 if trie.arena.is_empty() {
1032 return Cursor { trie, stack: Vec::new() };
1033 }
1034 let mask = trie.arena[0].occupancy;
1035 let nib = if trie.arena[0].is_terminal() { TERMINAL_NIB } else { usize::MAX };
1036 Cursor { trie, stack: vec![(0, mask, nib)] }
1037 }
1038
1039 fn new_last(trie: &'a NibTrie<T, PTR, LEN>) -> Self {
1040 if trie.arena.is_empty() {
1041 return Cursor { trie, stack: Vec::new() };
1042 }
1043 let mut stack = Vec::new();
1044 let mut node_idx: usize = 0;
1045 loop {
1046 let node = &trie.arena[node_idx];
1047 let mask = node.occupancy;
1048 if mask != 0 {
1049 let nib = (mask as u32).ilog2() as usize; stack.push((node_idx, mask, nib));
1051 if node.is_leaf(nib) {
1052 break;
1053 } else {
1054 node_idx = node.children[nib].as_usize();
1055 }
1056 } else if node.is_terminal() {
1057 stack.push((node_idx, mask, TERMINAL_NIB));
1058 break;
1059 } else {
1060 break;
1061 }
1062 }
1063 Cursor { trie, stack }
1064 }
1065
1066 fn descend_first(&mut self, mut node_idx: usize) {
1067 loop {
1068 let node = &self.trie.arena[node_idx];
1069 if node.is_terminal() {
1070 let mask = node.occupancy;
1071 self.stack.push((node_idx, mask, TERMINAL_NIB));
1072 return;
1073 }
1074 let mask = node.occupancy;
1075 debug_assert!(mask != 0, "descend_first: non-terminal node with no children");
1076 let nib = mask.trailing_zeros() as usize;
1077 debug_assert!(nib < 4);
1078 self.stack.push((node_idx, mask, nib));
1079 if node.is_leaf(nib) {
1080 return;
1081 } else {
1082 node_idx = node.children[nib].as_usize();
1083 }
1084 }
1085 }
1086
1087 fn descend_last(&mut self, mut node_idx: usize) {
1088 loop {
1089 let node = &self.trie.arena[node_idx];
1090 if node.is_terminal() && node.occupancy == 0 {
1091 self.stack.push((node_idx, node.occupancy, TERMINAL_NIB));
1092 return;
1093 }
1094 let mask = node.occupancy;
1095 if mask == 0 {
1096 if node.is_terminal() {
1097 self.stack.push((node_idx, mask, TERMINAL_NIB));
1098 }
1099 return;
1100 }
1101 let nib = (mask as u32).ilog2() as usize;
1102 debug_assert!(nib < 4);
1103 self.stack.push((node_idx, mask, nib));
1104 if node.is_leaf(nib) {
1105 return;
1106 } else {
1107 node_idx = node.children[nib].as_usize();
1108 }
1109 }
1110 }
1111
1112 #[inline]
1113 fn push_next_child(&mut self, node_idx: usize, mask: u8, start_nib: usize) -> bool {
1114 let shifted = if start_nib >= 4 { 0u8 } else { mask >> start_nib };
1115 if shifted == 0 {
1116 return false;
1117 }
1118 let nib = start_nib + shifted.trailing_zeros() as usize;
1119 debug_assert!(nib < 4);
1120 debug_assert!(mask & (1 << nib) != 0);
1121 self.stack.push((node_idx, mask, nib));
1122 if !self.trie.arena[node_idx].is_leaf(nib) {
1123 let addr = self.trie.arena[node_idx].children[nib].as_usize();
1124 self.descend_first(addr);
1125 }
1126 true
1127 }
1128
1129 #[inline]
1130 fn backtrack_to_next(&mut self) -> Option<(&[u8], &T)> {
1131 loop {
1132 let (parent_idx, parent_mask, child_nib) = self.stack.pop()?;
1133 if self.push_next_child(parent_idx, parent_mask, child_nib + 1) {
1134 return self.current();
1135 }
1136 }
1137 }
1138
1139 pub fn current(&self) -> Option<(&[u8], &T)> {
1140 let (_, _, nib) = self.stack.last()?;
1141 if *nib == usize::MAX {
1142 return None;
1143 }
1144 let (node_idx, _, _) = self.stack.last()?;
1145 let node = &self.trie.arena[*node_idx];
1146 if *nib == TERMINAL_NIB {
1147 let ki = node.leaf;
1148 let (off, len) = self.trie.index[ki.as_usize()];
1149 let key = &self.trie.buf[off..off + len.as_usize()];
1150 let value = &self.trie.values[ki.as_usize() - 1];
1151 Some((key, value))
1152 } else if let Some(key_index) = node.leaf_key_index(*nib) {
1153 let key = self.trie.key_slice(key_index);
1154 let value = &self.trie.values[key_index.as_usize() - 1];
1155 Some((key, value))
1156 } else {
1157 None
1158 }
1159 }
1160
1161 pub fn current_index(&self) -> Option<usize> {
1162 let &(_, _, nib) = self.stack.last()?;
1163 if nib == usize::MAX {
1164 return None;
1165 }
1166 let (node_idx, _, _) = self.stack.last()?;
1167 let node = &self.trie.arena[*node_idx];
1168 if nib == TERMINAL_NIB {
1169 Some(node.leaf.as_usize())
1170 } else {
1171 node.leaf_key_index(nib).map(|ki| ki.as_usize())
1172 }
1173 }
1174
1175 #[inline]
1176 fn advance_next(&mut self) -> bool {
1177 loop {
1178 let (node_idx, mask, nib) = match self.stack.pop() {
1179 Some(v) => v,
1180 None => return false,
1181 };
1182
1183 if nib == TERMINAL_NIB {
1184 if self.push_next_child(node_idx, mask, 0) {
1185 return true;
1186 }
1187 continue;
1188 }
1189
1190 let search_start = if nib == usize::MAX { 0 } else { nib + 1 };
1191 if self.push_next_child(node_idx, mask, search_start) {
1192 return true;
1193 }
1194 }
1195 }
1196
1197 #[inline]
1198 fn advance_prev(&mut self) -> bool {
1199 loop {
1200 let (node_idx, mask, nib) = match self.stack.pop() {
1201 Some(v) => v,
1202 None => return false,
1203 };
1204
1205 if nib == TERMINAL_NIB {
1206 continue;
1207 }
1208
1209 if nib == 0 || nib == usize::MAX {
1210 let node = &self.trie.arena[node_idx];
1211 if node.is_terminal() {
1212 self.stack.push((node_idx, mask, TERMINAL_NIB));
1213 return true;
1214 }
1215 continue;
1216 }
1217
1218 let mask_below = mask & ((1 << nib) - 1);
1219 if mask_below != 0 {
1220 let prev_nib = (mask_below as u32).ilog2() as usize;
1222 self.stack.push((node_idx, mask, prev_nib));
1223 if !self.trie.arena[node_idx].is_leaf(prev_nib) {
1224 let addr = self.trie.arena[node_idx].children[prev_nib].as_usize();
1225 self.descend_last(addr);
1226 }
1227 return true;
1228 }
1229
1230 let node = &self.trie.arena[node_idx];
1231 if node.is_terminal() {
1232 self.stack.push((node_idx, mask, TERMINAL_NIB));
1233 return true;
1234 }
1235 }
1236 }
1237
1238 #[inline]
1239 pub fn next_index(&mut self) -> Option<usize> {
1240 if self.advance_next() { self.current_index() } else { None }
1241 }
1242
1243 #[inline]
1244 pub fn prev_index(&mut self) -> Option<usize> {
1245 if self.advance_prev() { self.current_index() } else { None }
1246 }
1247
1248 #[inline]
1249 pub fn next(&mut self) -> Option<(&[u8], &T)> {
1250 if self.advance_next() { self.current() } else { None }
1251 }
1252
1253 #[inline]
1254 pub fn prev(&mut self) -> Option<(&[u8], &T)> {
1255 if self.advance_prev() { self.current() } else { None }
1256 }
1257
1258 pub fn seek(&mut self, key: &[u8]) -> Option<(&[u8], &T)> {
1259 if self.trie.arena.is_empty() {
1260 self.stack.clear();
1261 return None;
1262 }
1263
1264 self.stack.clear();
1265 let mut node_idx: usize = 0;
1266 let max_nib = key.len() * 4;
1267
1268 loop {
1269 let node = &self.trie.arena[node_idx];
1270 let mask = node.occupancy;
1271
1272 if node.is_terminal() && node.prefix_len.as_usize() >= max_nib {
1273 let ki = node.leaf;
1274 let (off, len) = self.trie.index[ki.as_usize()];
1275 let node_key = &self.trie.buf[off..off + len.as_usize()];
1276 if node_key >= key {
1277 self.stack.push((node_idx, mask, TERMINAL_NIB));
1278 return self.current();
1279 }
1280 }
1281
1282 if node.prefix_len.as_usize() >= max_nib {
1283 if self.push_next_child(node_idx, mask, 0) {
1284 return self.current();
1285 }
1286 return self.backtrack_to_next();
1287 }
1288
1289 let nib = key_nib_at(key, node.prefix_len.as_usize()) as usize;
1290 if !node.is_occupied(nib) {
1291 if self.push_next_child(node_idx, mask, nib + 1) {
1293 return self.current();
1294 }
1295 return self.backtrack_to_next();
1296 }
1297
1298 self.stack.push((node_idx, mask, nib));
1299 let slot = node.children[nib];
1300 if node.is_leaf(nib) {
1301 let leaf_key = self.trie.key_slice(slot);
1302 if leaf_key >= key {
1303 return self.current();
1304 }
1305 return self.next();
1307 } else {
1308 node_idx = slot.as_usize();
1309 }
1310 }
1311 }
1312}
1313
1314pub struct CursorMut<'a, T, PTR: TrieIndex, LEN: TrieIndex> {
1341 trie: &'a mut NibTrie<T, PTR, LEN>,
1342 stack: Vec<(usize, u8, usize)>,
1345}
1346
1347impl<'a, T, PTR: TrieIndex, LEN: TrieIndex> CursorMut<'a, T, PTR, LEN> {
1348 pub fn new(trie: &'a mut NibTrie<T, PTR, LEN>) -> Self {
1350 if trie.arena.is_empty() {
1351 return CursorMut { trie, stack: Vec::new() };
1352 }
1353 let mask = trie.arena[0].occupancy;
1354 let nib = if trie.arena[0].is_terminal() { TERMINAL_NIB } else { usize::MAX };
1355 CursorMut { trie, stack: vec![(0, mask, nib)] }
1356 }
1357
1358 pub fn new_last(trie: &'a mut NibTrie<T, PTR, LEN>) -> Self {
1361 let mut c = CursorMut { trie, stack: Vec::new() };
1362 c.last();
1363 c
1364 }
1365
1366 fn descend_first(&mut self, mut node_idx: usize) {
1367 loop {
1368 let node = &self.trie.arena[node_idx];
1369 if node.is_terminal() {
1370 let mask = node.occupancy;
1371 self.stack.push((node_idx, mask, TERMINAL_NIB));
1372 return;
1373 }
1374 let mask = node.occupancy;
1375 debug_assert!(mask != 0, "descend_first: non-terminal node with no children");
1376 let nib = mask.trailing_zeros() as usize;
1377 debug_assert!(nib < 4);
1378 self.stack.push((node_idx, mask, nib));
1379 if node.is_leaf(nib) {
1380 return;
1381 } else {
1382 node_idx = node.children[nib].as_usize();
1383 }
1384 }
1385 }
1386
1387 fn descend_last(&mut self, mut node_idx: usize) {
1388 loop {
1389 let node = &self.trie.arena[node_idx];
1390 if node.is_terminal() && node.occupancy == 0 {
1391 self.stack.push((node_idx, node.occupancy, TERMINAL_NIB));
1392 return;
1393 }
1394 let mask = node.occupancy;
1395 if mask == 0 {
1396 if node.is_terminal() {
1397 self.stack.push((node_idx, mask, TERMINAL_NIB));
1398 }
1399 return;
1400 }
1401 let nib = (mask as u32).ilog2() as usize;
1402 debug_assert!(nib < 4);
1403 self.stack.push((node_idx, mask, nib));
1404 if node.is_leaf(nib) {
1405 return;
1406 } else {
1407 node_idx = node.children[nib].as_usize();
1408 }
1409 }
1410 }
1411
1412 #[inline]
1413 fn push_next_child(&mut self, node_idx: usize, mask: u8, start_nib: usize) -> bool {
1414 let shifted = if start_nib >= 4 { 0u8 } else { mask >> start_nib };
1415 if shifted == 0 {
1416 return false;
1417 }
1418 let nib = start_nib + shifted.trailing_zeros() as usize;
1419 debug_assert!(nib < 4);
1420 debug_assert!(mask & (1 << nib) != 0);
1421 self.stack.push((node_idx, mask, nib));
1422 if !self.trie.arena[node_idx].is_leaf(nib) {
1423 let addr = self.trie.arena[node_idx].children[nib].as_usize();
1424 self.descend_first(addr);
1425 }
1426 true
1427 }
1428
1429 #[inline]
1430 fn backtrack_to_next(&mut self) -> Option<(&[u8], &mut T)> {
1431 loop {
1432 let (parent_idx, parent_mask, child_nib) = self.stack.pop()?;
1433 if self.push_next_child(parent_idx, parent_mask, child_nib + 1) {
1434 return self.current();
1435 }
1436 }
1437 }
1438
1439 #[inline]
1449 pub fn current(&mut self) -> Option<(&[u8], &mut T)> {
1450 let (node_idx, _, nib) = *self.stack.last()?;
1451 if nib == usize::MAX {
1452 return None;
1453 }
1454 let ki: PTR = if nib == TERMINAL_NIB {
1455 self.trie.arena[node_idx].leaf
1456 } else {
1457 self.trie.arena[node_idx].leaf_key_index(nib)?
1458 };
1459 let (off, len) = self.trie.index[ki.as_usize()];
1460 let key = &self.trie.buf[off..off + len.as_usize()];
1461 let value = &mut self.trie.values[ki.as_usize() - 1];
1462 Some((key, value))
1463 }
1464
1465 #[inline]
1467 pub fn current_index(&self) -> Option<usize> {
1468 let &(_, _, nib) = self.stack.last()?;
1469 if nib == usize::MAX {
1470 return None;
1471 }
1472 let (node_idx, _, _) = *self.stack.last()?;
1473 let node = &self.trie.arena[node_idx];
1474 if nib == TERMINAL_NIB {
1475 Some(node.leaf.as_usize())
1476 } else {
1477 node.leaf_key_index(nib).map(|ki| ki.as_usize())
1478 }
1479 }
1480
1481 #[inline]
1482 fn advance_next(&mut self) -> bool {
1483 loop {
1484 let (node_idx, mask, nib) = match self.stack.pop() {
1485 Some(v) => v,
1486 None => return false,
1487 };
1488
1489 if nib == TERMINAL_NIB {
1490 if self.push_next_child(node_idx, mask, 0) {
1491 return true;
1492 }
1493 continue;
1494 }
1495
1496 let search_start = if nib == usize::MAX { 0 } else { nib + 1 };
1497 if self.push_next_child(node_idx, mask, search_start) {
1498 return true;
1499 }
1500 }
1501 }
1502
1503 #[inline]
1504 fn advance_prev(&mut self) -> bool {
1505 loop {
1506 let (node_idx, mask, nib) = match self.stack.pop() {
1507 Some(v) => v,
1508 None => return false,
1509 };
1510
1511 if nib == TERMINAL_NIB {
1512 continue;
1513 }
1514
1515 if nib == 0 || nib == usize::MAX {
1516 let node = &self.trie.arena[node_idx];
1517 if node.is_terminal() {
1518 self.stack.push((node_idx, mask, TERMINAL_NIB));
1519 return true;
1520 }
1521 continue;
1522 }
1523
1524 let mask_below = mask & ((1 << nib) - 1);
1525 if mask_below != 0 {
1526 let prev_nib = (mask_below as u32).ilog2() as usize;
1527 self.stack.push((node_idx, mask, prev_nib));
1528 if !self.trie.arena[node_idx].is_leaf(prev_nib) {
1529 let addr = self.trie.arena[node_idx].children[prev_nib].as_usize();
1530 self.descend_last(addr);
1531 }
1532 return true;
1533 }
1534
1535 let node = &self.trie.arena[node_idx];
1536 if node.is_terminal() {
1537 self.stack.push((node_idx, mask, TERMINAL_NIB));
1538 return true;
1539 }
1540 }
1541 }
1542
1543 pub fn first(&mut self) -> Option<(&[u8], &mut T)> {
1546 if self.trie.arena.is_empty() {
1547 self.stack.clear();
1548 return None;
1549 }
1550 let mask = self.trie.arena[0].occupancy;
1551 let nib = if self.trie.arena[0].is_terminal() { TERMINAL_NIB } else { usize::MAX };
1552 self.stack.clear();
1553 self.stack.push((0, mask, nib));
1554 if nib == TERMINAL_NIB {
1555 return self.current();
1557 }
1558 if self.advance_next() { self.current() } else { None }
1560 }
1561
1562 pub fn last(&mut self) -> Option<(&[u8], &mut T)> {
1565 if self.trie.arena.is_empty() {
1566 self.stack.clear();
1567 return None;
1568 }
1569 self.stack.clear();
1570 let mut node_idx: usize = 0;
1571 loop {
1572 let node = &self.trie.arena[node_idx];
1573 let mask = node.occupancy;
1574 if mask != 0 {
1575 let nib = (mask as u32).ilog2() as usize;
1576 self.stack.push((node_idx, mask, nib));
1577 if node.is_leaf(nib) {
1578 break;
1579 } else {
1580 node_idx = node.children[nib].as_usize();
1581 }
1582 } else if node.is_terminal() {
1583 self.stack.push((node_idx, mask, TERMINAL_NIB));
1584 break;
1585 } else {
1586 break;
1587 }
1588 }
1589 self.current()
1590 }
1591
1592 #[inline]
1593 pub fn next(&mut self) -> Option<(&[u8], &mut T)> {
1594 if self.advance_next() { self.current() } else { None }
1595 }
1596
1597 #[inline]
1598 pub fn prev(&mut self) -> Option<(&[u8], &mut T)> {
1599 if self.advance_prev() { self.current() } else { None }
1600 }
1601
1602 #[inline]
1603 pub fn next_index(&mut self) -> Option<usize> {
1604 if self.advance_next() { self.current_index() } else { None }
1605 }
1606
1607 #[inline]
1608 pub fn prev_index(&mut self) -> Option<usize> {
1609 if self.advance_prev() { self.current_index() } else { None }
1610 }
1611
1612 pub fn seek(&mut self, key: &[u8]) -> Option<(&[u8], &mut T)> {
1613 if self.trie.arena.is_empty() {
1614 self.stack.clear();
1615 return None;
1616 }
1617
1618 self.stack.clear();
1619 let mut node_idx: usize = 0;
1620 let max_nib = key.len() * 4;
1621
1622 loop {
1623 let node = &self.trie.arena[node_idx];
1624 let mask = node.occupancy;
1625
1626 if node.is_terminal() && node.prefix_len.as_usize() >= max_nib {
1627 let ki = node.leaf;
1628 let (off, len) = self.trie.index[ki.as_usize()];
1629 let node_key = &self.trie.buf[off..off + len.as_usize()];
1630 if node_key >= key {
1631 self.stack.push((node_idx, mask, TERMINAL_NIB));
1632 return self.current();
1633 }
1634 }
1635
1636 if node.prefix_len.as_usize() >= max_nib {
1637 if self.push_next_child(node_idx, mask, 0) {
1638 return self.current();
1639 }
1640 return self.backtrack_to_next();
1641 }
1642
1643 let nib = key_nib_at(key, node.prefix_len.as_usize()) as usize;
1644 if !node.is_occupied(nib) {
1645 if self.push_next_child(node_idx, mask, nib + 1) {
1646 return self.current();
1647 }
1648 return self.backtrack_to_next();
1649 }
1650
1651 self.stack.push((node_idx, mask, nib));
1652 let slot = node.children[nib];
1653 if node.is_leaf(nib) {
1654 let leaf_key = self.trie.key_slice(slot);
1655 if leaf_key >= key {
1656 return self.current();
1657 }
1658 return self.next();
1659 } else {
1660 node_idx = slot.as_usize();
1661 }
1662 }
1663 }
1664}
1665
1666#[cfg(test)]
1667#[path = "tests/nib_trie.rs"]
1668mod tests;