1const NODE4_MAX: usize = 4;
37const NODE16_MAX: usize = 16;
39const NODE48_MAX: usize = 48;
41
42#[derive(Debug, Clone)]
44pub struct AdaptiveRadixTree<V> {
45 root: Option<Box<ArtNode<V>>>,
46 len: usize,
47}
48
49#[derive(Debug, Clone)]
51#[allow(clippy::large_enum_variant)]
52enum ArtNode<V> {
53 Leaf { key: String, value: V },
55 Inner {
57 prefix: Vec<u8>,
59 children: Children<V>,
61 value: Option<V>,
63 terminal_key: Option<String>,
65 },
66}
67
68#[derive(Debug, Clone)]
70#[allow(clippy::large_enum_variant)]
71enum Children<V> {
72 Node4 {
74 keys: Vec<u8>,
75 children: Vec<Box<ArtNode<V>>>,
76 },
77 Node16 {
79 keys: Vec<u8>,
80 children: Vec<Box<ArtNode<V>>>,
81 },
82 Node48 {
84 index: [u8; 256],
85 children: Vec<Option<Box<ArtNode<V>>>>,
86 count: usize,
87 },
88 Node256 {
90 children: Vec<Option<Box<ArtNode<V>>>>,
91 },
92}
93
94impl<V: Clone> AdaptiveRadixTree<V> {
95 pub fn new() -> Self {
97 Self { root: None, len: 0 }
98 }
99
100 pub fn len(&self) -> usize {
102 self.len
103 }
104
105 pub fn is_empty(&self) -> bool {
107 self.len == 0
108 }
109
110 pub fn insert(&mut self, key: &str, value: V) -> Option<V> {
112 if self.root.is_none() {
113 self.root = Some(Box::new(ArtNode::Leaf {
114 key: key.to_string(),
115 value,
116 }));
117 self.len += 1;
118 return None;
119 }
120
121 let result = insert_recursive(self.root.as_mut().unwrap(), key.as_bytes(), key, value, 0);
122 if result.is_none() {
123 self.len += 1;
124 }
125 result
126 }
127
128 pub fn get(&self, key: &str) -> Option<&V> {
130 let node = self.root.as_ref()?;
131 get_recursive(node, key.as_bytes(), 0)
132 }
133
134 pub fn prefix_scan(&self, prefix: &str) -> Vec<(&str, &V)> {
137 let mut results = Vec::new();
138 if let Some(ref root) = self.root {
139 prefix_scan_recursive(root, prefix.as_bytes(), 0, &mut results);
140 }
141 results.sort_by_key(|(k, _)| *k);
142 results
143 }
144
145 pub fn delete(&mut self, key: &str) -> Option<V> {
147 let result = {
148 let root = self.root.as_mut()?;
149 delete_recursive(root, key.as_bytes(), 0)
150 };
151
152 if result.removed.is_some() {
153 self.len -= 1;
154 if result.prune || self.root.as_ref().is_some_and(|root| is_empty_node(root)) {
155 self.root = None;
156 }
157 }
158 result.removed
159 }
160
161 pub fn iter(&self) -> Vec<(&str, &V)> {
163 let mut results = Vec::new();
164 if let Some(ref root) = self.root {
165 collect_all(root, &mut results);
166 }
167 results.sort_by_key(|(k, _)| *k);
168 results
169 }
170
171 pub fn node_distribution(&self) -> NodeDistribution {
173 let mut dist = NodeDistribution::default();
174 if let Some(ref root) = self.root {
175 count_nodes(root, &mut dist);
176 }
177 dist
178 }
179}
180
181impl<V: Clone> Default for AdaptiveRadixTree<V> {
182 fn default() -> Self {
183 Self::new()
184 }
185}
186
187#[derive(Debug, Clone, Default)]
189pub struct NodeDistribution {
190 pub leaves: usize,
191 pub node4: usize,
192 pub node16: usize,
193 pub node48: usize,
194 pub node256: usize,
195}
196
197#[derive(Debug)]
198struct DeleteResult<V> {
199 removed: Option<V>,
200 prune: bool,
201}
202
203impl<V> DeleteResult<V> {
204 const fn not_found() -> Self {
205 Self {
206 removed: None,
207 prune: false,
208 }
209 }
210}
211
212fn insert_recursive<V: Clone>(
217 node: &mut ArtNode<V>,
218 key_bytes: &[u8],
219 full_key: &str,
220 value: V,
221 depth: usize,
222) -> Option<V> {
223 match node {
224 ArtNode::Leaf {
225 key: existing_key,
226 value: existing_value,
227 } => {
228 if existing_key == full_key {
229 let old = existing_value.clone();
231 *existing_value = value;
232 return Some(old);
233 }
234
235 let existing_bytes = existing_key.as_bytes();
237 let common_prefix_len =
238 common_prefix_length(&existing_bytes[depth..], &key_bytes[depth..]);
239
240 let prefix = existing_bytes[depth..depth + common_prefix_len].to_vec();
241
242 let old_key = existing_key.clone();
243 let old_val = existing_value.clone();
244
245 let split_depth = depth + common_prefix_len;
246
247 if split_depth >= existing_bytes.len() && split_depth >= key_bytes.len() {
248 *existing_value = value;
250 return Some(old_val);
251 }
252
253 let mut children = Children::Node4 {
254 keys: Vec::new(),
255 children: Vec::new(),
256 };
257
258 if split_depth < existing_bytes.len() {
259 let old_child = Box::new(ArtNode::Leaf {
260 key: old_key.clone(),
261 value: old_val.clone(),
262 });
263 children_insert(&mut children, existing_bytes[split_depth], old_child);
264 }
265
266 let mut inner_value = None;
267 let mut terminal_key = None;
268 if split_depth < key_bytes.len() {
269 let new_child = Box::new(ArtNode::Leaf {
270 key: full_key.to_string(),
271 value,
272 });
273 children_insert(&mut children, key_bytes[split_depth], new_child);
274 } else {
275 inner_value = Some(value);
276 terminal_key = Some(full_key.to_string());
277 }
278
279 if split_depth >= existing_bytes.len() {
280 inner_value = Some(old_val);
281 terminal_key = Some(old_key);
282 }
283
284 *node = ArtNode::Inner {
285 prefix,
286 children,
287 value: inner_value,
288 terminal_key,
289 };
290 None
291 }
292 ArtNode::Inner {
293 prefix,
294 children,
295 value: node_value,
296 terminal_key,
297 } => {
298 let remaining = &key_bytes[depth..];
299 let prefix_match = common_prefix_length(remaining, prefix);
300
301 if prefix_match < prefix.len() {
302 let common = prefix[..prefix_match].to_vec();
304 let old_suffix = prefix[prefix_match..].to_vec();
305 let old_first_byte = old_suffix[0];
306
307 let old_inner = ArtNode::Inner {
309 prefix: old_suffix[1..].to_vec(),
310 children: std::mem::replace(
311 children,
312 Children::Node4 {
313 keys: Vec::new(),
314 children: Vec::new(),
315 },
316 ),
317 value: node_value.take(),
318 terminal_key: terminal_key.take(),
319 };
320
321 let mut new_children = Children::Node4 {
322 keys: Vec::new(),
323 children: Vec::new(),
324 };
325 children_insert(&mut new_children, old_first_byte, Box::new(old_inner));
326
327 let new_depth = depth + prefix_match;
328 let mut inner_value = None;
329 let mut new_terminal_key = None;
330 if new_depth < key_bytes.len() {
331 let new_child = Box::new(ArtNode::Leaf {
332 key: full_key.to_string(),
333 value,
334 });
335 children_insert(&mut new_children, key_bytes[new_depth], new_child);
336 } else {
337 inner_value = Some(value);
338 new_terminal_key = Some(full_key.to_string());
339 }
340
341 *prefix = common;
342 *children = new_children;
343 *node_value = inner_value;
344 *terminal_key = new_terminal_key;
345 return None;
346 }
347
348 let next_depth = depth + prefix.len();
349 if next_depth >= key_bytes.len() {
350 let old = node_value.take();
352 *node_value = Some(value);
353 *terminal_key = Some(full_key.to_string());
354 return old;
355 }
356
357 let byte = key_bytes[next_depth];
358 if let Some(child) = children_get_mut(children, byte) {
359 insert_recursive(child, key_bytes, full_key, value, next_depth + 1)
360 } else {
361 let new_child = Box::new(ArtNode::Leaf {
362 key: full_key.to_string(),
363 value,
364 });
365 children_insert(children, byte, new_child);
366 None
367 }
368 }
369 }
370}
371
372fn get_recursive<'a, V>(node: &'a ArtNode<V>, key_bytes: &[u8], depth: usize) -> Option<&'a V> {
373 match node {
374 ArtNode::Leaf { key, value } => {
375 if key.as_bytes() == key_bytes {
376 Some(value)
377 } else {
378 None
379 }
380 }
381 ArtNode::Inner {
382 prefix,
383 children,
384 value,
385 terminal_key: _,
386 } => {
387 let remaining = &key_bytes[depth..];
388 if remaining.len() < prefix.len() || &remaining[..prefix.len()] != prefix.as_slice() {
389 return None;
390 }
391 let next_depth = depth + prefix.len();
392 if next_depth >= key_bytes.len() {
393 return value.as_ref();
394 }
395 let byte = key_bytes[next_depth];
396 children_get(children, byte)
397 .and_then(|child| get_recursive(child, key_bytes, next_depth + 1))
398 }
399 }
400}
401
402fn prefix_scan_recursive<'a, V>(
403 node: &'a ArtNode<V>,
404 prefix_bytes: &[u8],
405 depth: usize,
406 results: &mut Vec<(&'a str, &'a V)>,
407) {
408 match node {
409 ArtNode::Leaf { key, value } => {
410 if key.as_bytes().starts_with(prefix_bytes) {
411 results.push((key.as_str(), value));
412 }
413 }
414 ArtNode::Inner {
415 prefix,
416 children,
417 value: _,
418 terminal_key: _,
419 } => {
420 let remaining_prefix = if depth < prefix_bytes.len() {
421 &prefix_bytes[depth..]
422 } else {
423 &[]
424 };
425
426 let match_len = common_prefix_length(remaining_prefix, prefix);
428
429 if match_len < remaining_prefix.len() && match_len < prefix.len() {
430 return;
432 }
433
434 let next_depth = depth + prefix.len();
435
436 if remaining_prefix.len() <= prefix.len() {
437 if depth + match_len >= prefix_bytes.len() {
439 collect_all_inner(node, results);
441 return;
442 }
443 }
444
445 if next_depth > prefix_bytes.len() {
446 collect_all_inner(node, results);
448 return;
449 }
450
451 if next_depth == prefix_bytes.len() {
452 collect_all_inner(node, results);
454 return;
455 }
456
457 let byte = prefix_bytes[next_depth];
459 if let Some(child) = children_get(children, byte) {
460 prefix_scan_recursive(child, prefix_bytes, next_depth + 1, results);
461 }
462 }
463 }
464}
465
466fn collect_all_inner<'a, V>(node: &'a ArtNode<V>, results: &mut Vec<(&'a str, &'a V)>) {
467 match node {
468 ArtNode::Leaf { key, value } => {
469 results.push((key.as_str(), value));
470 }
471 ArtNode::Inner {
472 children,
473 value,
474 terminal_key,
475 ..
476 } => {
477 if let (Some(key), Some(value)) = (terminal_key.as_deref(), value.as_ref()) {
478 results.push((key, value));
479 }
480 for child in children_iter(children) {
481 collect_all_inner(child, results);
482 }
483 }
484 }
485}
486
487fn collect_all<'a, V>(node: &'a ArtNode<V>, results: &mut Vec<(&'a str, &'a V)>) {
488 collect_all_inner(node, results);
489}
490
491fn delete_recursive<V: Clone>(
492 node: &mut ArtNode<V>,
493 key_bytes: &[u8],
494 depth: usize,
495) -> DeleteResult<V> {
496 match node {
497 ArtNode::Leaf { key, value } => {
498 if key.as_bytes() == key_bytes {
499 DeleteResult {
500 removed: Some(value.clone()),
501 prune: true,
502 }
503 } else {
504 DeleteResult::not_found()
505 }
506 }
507 ArtNode::Inner {
508 prefix,
509 children,
510 value: node_value,
511 terminal_key,
512 } => {
513 let remaining = &key_bytes[depth..];
514 if remaining.len() < prefix.len() || &remaining[..prefix.len()] != prefix.as_slice() {
515 return DeleteResult::not_found();
516 }
517 let next_depth = depth + prefix.len();
518 if next_depth >= key_bytes.len() {
519 let removed = node_value.take();
520 if removed.is_some() {
521 *terminal_key = None;
522 }
523 let prune = removed.is_some() && children_count(children) == 0;
524 return DeleteResult { removed, prune };
525 }
526 let byte = key_bytes[next_depth];
527 let child_result = if let Some(child) = children_get_mut(children, byte) {
528 delete_recursive(child, key_bytes, next_depth + 1)
529 } else {
530 DeleteResult::not_found()
531 };
532
533 if child_result.prune {
534 children_remove(children, byte);
535 }
536 let removed = child_result.removed;
537 DeleteResult {
538 prune: removed.is_some() && node_value.is_none() && children_count(children) == 0,
539 removed,
540 }
541 }
542 }
543}
544
545fn is_empty_node<V>(node: &ArtNode<V>) -> bool {
546 match node {
547 ArtNode::Leaf { .. } => false, ArtNode::Inner {
549 children, value, ..
550 } => value.is_none() && children_count(children) == 0,
551 }
552}
553
554fn count_nodes<V>(node: &ArtNode<V>, dist: &mut NodeDistribution) {
555 match node {
556 ArtNode::Leaf { .. } => dist.leaves += 1,
557 ArtNode::Inner { children, .. } => {
558 match children {
559 Children::Node4 { .. } => dist.node4 += 1,
560 Children::Node16 { .. } => dist.node16 += 1,
561 Children::Node48 { .. } => dist.node48 += 1,
562 Children::Node256 { .. } => dist.node256 += 1,
563 }
564 for child in children_iter(children) {
565 count_nodes(child, dist);
566 }
567 }
568 }
569}
570
571fn children_insert<V>(children: &mut Children<V>, byte: u8, child: Box<ArtNode<V>>) {
576 match children {
577 Children::Node4 { keys, children: ch } => {
578 if ch.len() < NODE4_MAX {
579 let pos = keys.iter().position(|&k| k > byte).unwrap_or(keys.len());
580 keys.insert(pos, byte);
581 ch.insert(pos, child);
582 } else {
583 let mut new_keys = keys.clone();
585 let mut new_ch: Vec<Box<ArtNode<V>>> = std::mem::take(ch);
586 let pos = new_keys
587 .iter()
588 .position(|&k| k > byte)
589 .unwrap_or(new_keys.len());
590 new_keys.insert(pos, byte);
591 new_ch.insert(pos, child);
592 *children = Children::Node16 {
593 keys: new_keys,
594 children: new_ch,
595 };
596 }
597 }
598 Children::Node16 { keys, children: ch } => {
599 if ch.len() < NODE16_MAX {
600 let pos = keys.iter().position(|&k| k > byte).unwrap_or(keys.len());
601 keys.insert(pos, byte);
602 ch.insert(pos, child);
603 } else {
604 let mut index = [u8::MAX; 256];
606 let mut new_ch: Vec<Option<Box<ArtNode<V>>>> = Vec::with_capacity(NODE48_MAX);
607 for (i, (&k, c)) in keys.iter().zip(ch.drain(..)).enumerate() {
608 index[k as usize] = i as u8;
609 new_ch.push(Some(c));
610 }
611 let idx = new_ch.len();
612 index[byte as usize] = idx as u8;
613 new_ch.push(Some(child));
614 *children = Children::Node48 {
615 index,
616 children: new_ch,
617 count: idx + 1,
618 };
619 }
620 }
621 Children::Node48 {
622 index,
623 children: ch,
624 count,
625 } => {
626 if *count < NODE48_MAX {
627 let idx = *count;
628 index[byte as usize] = idx as u8;
629 if idx < ch.len() {
630 ch[idx] = Some(child);
631 } else {
632 ch.push(Some(child));
633 }
634 *count += 1;
635 } else {
636 let mut new_ch: Vec<Option<Box<ArtNode<V>>>> = (0..256).map(|_| None).collect();
638 for (b, &idx) in index.iter().enumerate() {
639 if idx != u8::MAX && (idx as usize) < ch.len() {
640 new_ch[b] = ch[idx as usize].take();
641 }
642 }
643 new_ch[byte as usize] = Some(child);
644 *children = Children::Node256 { children: new_ch };
645 }
646 }
647 Children::Node256 { children: ch } => {
648 ch[byte as usize] = Some(child);
649 }
650 }
651}
652
653fn children_get<V>(children: &Children<V>, byte: u8) -> Option<&ArtNode<V>> {
654 match children {
655 Children::Node4 { keys, children: ch } => {
656 keys.iter().position(|&k| k == byte).map(|i| ch[i].as_ref())
657 }
658 Children::Node16 { keys, children: ch } => {
659 keys.iter().position(|&k| k == byte).map(|i| ch[i].as_ref())
660 }
661 Children::Node48 {
662 index,
663 children: ch,
664 ..
665 } => {
666 let idx = index[byte as usize];
667 if idx != u8::MAX && (idx as usize) < ch.len() {
668 ch[idx as usize].as_ref().map(|c| c.as_ref())
669 } else {
670 None
671 }
672 }
673 Children::Node256 { children: ch } => ch[byte as usize].as_ref().map(|c| c.as_ref()),
674 }
675}
676
677fn children_get_mut<V>(children: &mut Children<V>, byte: u8) -> Option<&mut ArtNode<V>> {
678 match children {
679 Children::Node4 { keys, children: ch } => keys
680 .iter()
681 .position(|&k| k == byte)
682 .map(move |i| ch[i].as_mut()),
683 Children::Node16 { keys, children: ch } => keys
684 .iter()
685 .position(|&k| k == byte)
686 .map(move |i| ch[i].as_mut()),
687 Children::Node48 {
688 index,
689 children: ch,
690 ..
691 } => {
692 let idx = index[byte as usize];
693 if idx != u8::MAX && (idx as usize) < ch.len() {
694 ch[idx as usize].as_mut().map(|c| c.as_mut())
695 } else {
696 None
697 }
698 }
699 Children::Node256 { children: ch } => ch[byte as usize].as_mut().map(|c| c.as_mut()),
700 }
701}
702
703fn children_remove<V>(children: &mut Children<V>, byte: u8) {
704 match children {
705 Children::Node4 { keys, children: ch } => {
706 if let Some(pos) = keys.iter().position(|&k| k == byte) {
707 keys.remove(pos);
708 ch.remove(pos);
709 }
710 }
711 Children::Node16 { keys, children: ch } => {
712 if let Some(pos) = keys.iter().position(|&k| k == byte) {
713 keys.remove(pos);
714 ch.remove(pos);
715 }
716 if ch.len() <= NODE4_MAX {
718 *children = Children::Node4 {
719 keys: keys.clone(),
720 children: std::mem::take(ch),
721 };
722 }
723 }
724 Children::Node48 {
725 index,
726 children: ch,
727 count,
728 } => {
729 let idx = index[byte as usize];
730 if idx != u8::MAX && (idx as usize) < ch.len() {
731 ch[idx as usize] = None;
732 index[byte as usize] = u8::MAX;
733 *count = count.saturating_sub(1);
734 }
735 }
736 Children::Node256 { children: ch } => {
737 ch[byte as usize] = None;
738 }
739 }
740}
741
742fn children_count<V>(children: &Children<V>) -> usize {
743 match children {
744 Children::Node4 { children: ch, .. } => ch.len(),
745 Children::Node16 { children: ch, .. } => ch.len(),
746 Children::Node48 { count, .. } => *count,
747 Children::Node256 { children: ch } => ch.iter().filter(|c| c.is_some()).count(),
748 }
749}
750
751fn children_iter<'a, V>(
752 children: &'a Children<V>,
753) -> Box<dyn Iterator<Item = &'a ArtNode<V>> + 'a> {
754 match children {
755 Children::Node4 { children: ch, .. } => Box::new(ch.iter().map(|c| c.as_ref())),
756 Children::Node16 { children: ch, .. } => Box::new(ch.iter().map(|c| c.as_ref())),
757 Children::Node48 { children: ch, .. } => {
758 Box::new(ch.iter().filter_map(|c| c.as_ref().map(|c| c.as_ref())))
759 }
760 Children::Node256 { children: ch } => {
761 Box::new(ch.iter().filter_map(|c| c.as_ref().map(|c| c.as_ref())))
762 }
763 }
764}
765
766fn common_prefix_length(a: &[u8], b: &[u8]) -> usize {
767 a.iter().zip(b.iter()).take_while(|(x, y)| x == y).count()
768}
769
770#[cfg(test)]
771mod tests {
772 use super::*;
773
774 #[test]
775 fn empty_tree() {
776 let art: AdaptiveRadixTree<u32> = AdaptiveRadixTree::new();
777 assert!(art.is_empty());
778 assert_eq!(art.len(), 0);
779 assert_eq!(art.get("anything"), None);
780 }
781
782 #[test]
783 fn single_insert_and_get() {
784 let mut art = AdaptiveRadixTree::new();
785 art.insert("hello", 42);
786 assert_eq!(art.get("hello"), Some(&42));
787 assert_eq!(art.get("hell"), None);
788 assert_eq!(art.get("helloo"), None);
789 assert_eq!(art.len(), 1);
790 }
791
792 #[test]
793 fn multiple_inserts() {
794 let mut art = AdaptiveRadixTree::new();
795 art.insert("file:open", 1);
796 art.insert("file:save", 2);
797 art.insert("file:close", 3);
798 art.insert("edit:undo", 4);
799 art.insert("edit:redo", 5);
800
801 assert_eq!(art.len(), 5);
802 assert_eq!(art.get("file:open"), Some(&1));
803 assert_eq!(art.get("file:save"), Some(&2));
804 assert_eq!(art.get("file:close"), Some(&3));
805 assert_eq!(art.get("edit:undo"), Some(&4));
806 assert_eq!(art.get("edit:redo"), Some(&5));
807 }
808
809 #[test]
810 fn prefix_scan_basic() {
811 let mut art = AdaptiveRadixTree::new();
812 art.insert("file:open", 1);
813 art.insert("file:save", 2);
814 art.insert("file:close", 3);
815 art.insert("edit:undo", 4);
816
817 let results = art.prefix_scan("file:");
818 assert_eq!(results.len(), 3);
819
820 let edit_results = art.prefix_scan("edit:");
821 assert_eq!(edit_results.len(), 1);
822 }
823
824 #[test]
825 fn prefix_scan_sorted() {
826 let mut art = AdaptiveRadixTree::new();
827 art.insert("c", 3);
828 art.insert("b", 2);
829 art.insert("a", 1);
830
831 let results = art.prefix_scan("");
832 let keys: Vec<&str> = results.iter().map(|(k, _)| *k).collect();
833 assert_eq!(keys, vec!["a", "b", "c"]);
834 }
835
836 #[test]
837 fn update_existing_key() {
838 let mut art = AdaptiveRadixTree::new();
839 assert_eq!(art.insert("key", 1), None);
840 assert_eq!(art.insert("key", 2), Some(1));
841 assert_eq!(art.get("key"), Some(&2));
842 assert_eq!(art.len(), 1);
843 }
844
845 #[test]
846 fn delete_existing() {
847 let mut art = AdaptiveRadixTree::new();
848 art.insert("hello", 42);
849 assert_eq!(art.delete("hello"), Some(42));
850 assert_eq!(art.get("hello"), None);
851 assert_eq!(art.len(), 0);
852 }
853
854 #[test]
855 fn delete_nonexistent() {
856 let mut art = AdaptiveRadixTree::new();
857 art.insert("hello", 42);
858 assert_eq!(art.delete("world"), None);
859 assert_eq!(art.len(), 1);
860 }
861
862 #[test]
863 fn many_inserts_promote_node_types() {
864 let mut art = AdaptiveRadixTree::new();
865 for i in 0..50u32 {
867 art.insert(&format!("key_{i:03}"), i);
868 }
869 assert_eq!(art.len(), 50);
870
871 for i in 0..50u32 {
873 assert_eq!(art.get(&format!("key_{i:03}")), Some(&i));
874 }
875
876 let dist = art.node_distribution();
877 assert!(dist.leaves >= 50);
878 }
879
880 #[test]
881 fn iter_returns_all_sorted() {
882 let mut art = AdaptiveRadixTree::new();
883 art.insert("z", 26);
884 art.insert("a", 1);
885 art.insert("m", 13);
886
887 let entries = art.iter();
888 let keys: Vec<&str> = entries.iter().map(|(k, _)| *k).collect();
889 assert_eq!(keys, vec!["a", "m", "z"]);
890 }
891
892 #[test]
893 fn shared_prefix_keys() {
894 let mut art = AdaptiveRadixTree::new();
895 art.insert("test", 1);
896 art.insert("testing", 2);
897 art.insert("tested", 3);
898 art.insert("tester", 4);
899
900 assert_eq!(art.len(), 4);
901 assert_eq!(art.get("test"), Some(&1));
902 assert_eq!(art.get("testing"), Some(&2));
903 assert_eq!(art.get("tested"), Some(&3));
904 assert_eq!(art.get("tester"), Some(&4));
905
906 let scan = art.prefix_scan("test");
907 assert_eq!(scan.len(), 4);
908 }
909
910 #[test]
911 fn iter_includes_keys_stored_on_compressed_inner_nodes() {
912 let mut art = AdaptiveRadixTree::new();
913 art.insert("file:save", 1);
914 art.insert("file:save-as", 2);
915
916 let entries = art.iter();
917 let keys: Vec<&str> = entries.iter().map(|(key, _)| *key).collect();
918 assert_eq!(keys, vec!["file:save", "file:save-as"]);
919 }
920
921 #[test]
922 fn deleting_prefix_key_preserves_longer_descendants() {
923 let mut art = AdaptiveRadixTree::new();
924 art.insert("test", 1);
925 art.insert("testing", 2);
926 art.insert("tester", 3);
927
928 assert_eq!(art.delete("test"), Some(1));
929 assert_eq!(art.get("test"), None);
930 assert_eq!(art.get("testing"), Some(&2));
931 assert_eq!(art.get("tester"), Some(&3));
932
933 let keys: Vec<&str> = art
934 .prefix_scan("test")
935 .into_iter()
936 .map(|(key, _)| key)
937 .collect();
938 assert_eq!(keys, vec!["tester", "testing"]);
939 }
940
941 #[test]
942 fn empty_prefix_scan_returns_all() {
943 let mut art = AdaptiveRadixTree::new();
944 art.insert("a", 1);
945 art.insert("b", 2);
946
947 let results = art.prefix_scan("");
948 assert_eq!(results.len(), 2);
949 }
950
951 #[test]
952 fn node_distribution() {
953 let mut art = AdaptiveRadixTree::new();
954 art.insert("a", 1);
955 art.insert("b", 2);
956 art.insert("c", 3);
957
958 let dist = art.node_distribution();
959 assert!(dist.leaves >= 3);
960 }
961
962 #[test]
963 fn command_palette_scenario() {
964 let mut art = AdaptiveRadixTree::new();
965 let commands = [
966 "file:open",
967 "file:save",
968 "file:save-as",
969 "file:close",
970 "file:new",
971 "edit:undo",
972 "edit:redo",
973 "edit:cut",
974 "edit:copy",
975 "edit:paste",
976 "view:sidebar",
977 "view:terminal",
978 "view:explorer",
979 "view:minimap",
980 "go:line",
981 "go:file",
982 "go:symbol",
983 "go:definition",
984 ];
985 for (i, cmd) in commands.iter().enumerate() {
986 art.insert(cmd, i);
987 }
988
989 assert_eq!(art.prefix_scan("file:").len(), 5);
991 assert_eq!(art.prefix_scan("edit:").len(), 5);
993 assert_eq!(art.prefix_scan("view:").len(), 4);
995 assert_eq!(art.prefix_scan("go:").len(), 4);
997 assert_eq!(art.prefix_scan("f").len(), 5);
999 }
1000}