1#![allow(
7 clippy::doc_markdown,
8 clippy::many_single_char_names,
9 clippy::type_complexity
10)]
11
12use alloc::sync::Arc;
45use alloc::vec::Vec;
46use core::ops::Bound;
47
48const ORDER: usize = 8;
53const MAX_ENTRIES: usize = ORDER - 1; const MAX_CHILDREN: usize = ORDER; #[derive(Debug)]
57enum BNode<K, V> {
58 Leaf {
59 entries: Vec<(K, V)>,
60 },
61 Internal {
62 entries: Vec<(K, V)>,
63 children: Vec<Arc<BNode<K, V>>>,
64 },
65}
66
67impl<K: Clone, V: Clone> Clone for BNode<K, V> {
71 fn clone(&self) -> Self {
72 match self {
73 Self::Leaf { entries } => Self::Leaf {
74 entries: entries.clone(),
75 },
76 Self::Internal { entries, children } => Self::Internal {
77 entries: entries.clone(),
78 children: children.clone(),
79 },
80 }
81 }
82}
83
84#[derive(Debug)]
87pub struct PersistentBTreeMap<K, V> {
88 root: Arc<BNode<K, V>>,
89 len: usize,
90}
91
92impl<K, V> Default for PersistentBTreeMap<K, V> {
93 fn default() -> Self {
94 Self::new()
95 }
96}
97
98impl<K, V> Clone for PersistentBTreeMap<K, V> {
99 fn clone(&self) -> Self {
103 Self {
104 root: self.root.clone(),
105 len: self.len,
106 }
107 }
108}
109
110impl<K: PartialEq, V: PartialEq> PartialEq for PersistentBTreeMap<K, V>
111where
112 K: Ord,
113{
114 fn eq(&self, other: &Self) -> bool {
115 self.len == other.len && self.iter().eq(other.iter())
116 }
117}
118
119impl<K: Eq + Ord, V: Eq> Eq for PersistentBTreeMap<K, V> {}
120
121impl<K, V> PersistentBTreeMap<K, V> {
122 #[must_use]
125 pub fn new() -> Self {
126 Self {
127 root: Arc::new(BNode::Leaf {
128 entries: Vec::new(),
129 }),
130 len: 0,
131 }
132 }
133
134 #[must_use]
135 pub const fn len(&self) -> usize {
136 self.len
137 }
138
139 #[must_use]
140 pub const fn is_empty(&self) -> bool {
141 self.len == 0
142 }
143}
144
145enum FoundOrDescend {
149 Found(usize),
150 Descend(usize),
151}
152
153#[inline]
158fn linear_find_entry<K: Ord, V>(entries: &[(K, V)], key: &K) -> Option<usize> {
159 for (i, (k, _)) in entries.iter().enumerate() {
160 match k.cmp(key) {
161 core::cmp::Ordering::Equal => return Some(i),
162 core::cmp::Ordering::Greater => return None,
163 core::cmp::Ordering::Less => continue,
164 }
165 }
166 None
167}
168
169#[inline]
173fn linear_position_internal<K: Ord, V>(entries: &[(K, V)], key: &K) -> FoundOrDescend {
174 for (i, (k, _)) in entries.iter().enumerate() {
175 match k.cmp(key) {
176 core::cmp::Ordering::Equal => return FoundOrDescend::Found(i),
177 core::cmp::Ordering::Greater => return FoundOrDescend::Descend(i),
178 core::cmp::Ordering::Less => continue,
179 }
180 }
181 FoundOrDescend::Descend(entries.len())
182}
183
184impl<K: Ord, V> PersistentBTreeMap<K, V> {
185 pub fn get(&self, key: &K) -> Option<&V> {
197 let mut node: &Arc<BNode<K, V>> = &self.root;
198 loop {
199 match &**node {
200 BNode::Leaf { entries } => {
201 return linear_find_entry(entries, key).map(|i| &entries[i].1);
202 }
203 BNode::Internal { entries, children } => {
204 match linear_position_internal(entries, key) {
205 FoundOrDescend::Found(i) => return Some(&entries[i].1),
206 FoundOrDescend::Descend(i) => {
207 node = &children[i];
208 }
209 }
210 }
211 }
212 }
213 }
214
215 pub fn predecessor(&self, key: &K) -> Option<(&K, &V)> {
224 let mut node: &Arc<BNode<K, V>> = &self.root;
225 let mut best: Option<(&K, &V)> = None;
226 loop {
227 match &**node {
228 BNode::Leaf { entries } => {
229 let i = entries.partition_point(|e| &e.0 < key);
230 if i > 0 {
231 let (k, v) = &entries[i - 1];
232 best = Some((k, v));
233 }
234 return best;
235 }
236 BNode::Internal { entries, children } => {
237 let i = entries.partition_point(|e| &e.0 < key);
238 if i > 0 {
239 let (k, v) = &entries[i - 1];
240 best = Some((k, v));
241 }
242 node = &children[i];
243 }
244 }
245 }
246 }
247
248 #[must_use]
261 pub fn from_sorted(entries: Vec<(K, V)>) -> Self
262 where
263 K: Ord + Clone,
264 V: Clone,
265 {
266 #[cfg(debug_assertions)]
267 for w in entries.windows(2) {
268 debug_assert!(w[0].0 < w[1].0, "from_sorted requires strictly sorted keys");
269 }
270 let len = entries.len();
271 if len <= MAX_ENTRIES {
272 return Self {
273 root: Arc::new(BNode::Leaf { entries }),
274 len,
275 };
276 }
277 let mut nodes: Vec<Arc<BNode<K, V>>> = Vec::new();
281 let mut seps: Vec<(K, V)> = Vec::new();
282 {
283 let g = (len + 1).div_ceil(MAX_ENTRIES + 1);
286 let mut it = entries.into_iter();
287 let mut remaining = len;
288 for gi in 0..g {
289 let groups_left = g - gi;
290 let seps_left = groups_left - 1;
292 let take = (remaining - seps_left).div_ceil(groups_left);
293 let leaf: Vec<(K, V)> = (&mut it).take(take).collect();
294 remaining -= leaf.len();
295 nodes.push(Arc::new(BNode::Leaf { entries: leaf }));
296 if gi + 1 < g {
297 let sep = it.next().expect("separator exists");
298 remaining -= 1;
299 seps.push(sep);
300 }
301 }
302 }
303 while nodes.len() > 1 {
307 let g = nodes.len().div_ceil(MAX_CHILDREN);
308 let per = nodes.len().div_ceil(g);
309 let mut up_nodes: Vec<Arc<BNode<K, V>>> = Vec::with_capacity(g);
310 let mut up_seps: Vec<(K, V)> = Vec::with_capacity(g - 1);
311 let mut node_it = nodes.into_iter();
312 let mut sep_it = seps.into_iter();
313 let mut children: Vec<Arc<BNode<K, V>>> = Vec::with_capacity(per);
314 let mut inner: Vec<(K, V)> = Vec::with_capacity(per - 1);
315 loop {
316 match node_it.next() {
317 Some(n) => {
318 if !children.is_empty() {
319 let sep = sep_it.next().expect("separator per boundary");
322 if children.len() < per {
323 inner.push(sep);
324 } else {
325 up_nodes.push(Arc::new(BNode::Internal {
326 entries: core::mem::take(&mut inner),
327 children: core::mem::take(&mut children),
328 }));
329 up_seps.push(sep);
330 }
331 }
332 children.push(n);
333 }
334 None => {
335 up_nodes.push(Arc::new(BNode::Internal {
336 entries: inner,
337 children,
338 }));
339 break;
340 }
341 }
342 }
343 nodes = up_nodes;
344 seps = up_seps;
345 }
346 Self {
347 root: nodes.pop().expect("one root"),
348 len,
349 }
350 }
351
352 pub fn iter(&self) -> Iter<'_, K, V> {
353 let mut stack: Vec<(&Arc<BNode<K, V>>, usize)> = Vec::with_capacity(8);
354 stack.push((&self.root, 0));
355 Iter { stack }
356 }
357
358 pub fn iter_rev(&self) -> IterRev<'_, K, V> {
364 let mut stack: Vec<(&Arc<BNode<K, V>>, usize)> = Vec::with_capacity(8);
365 stack.push((&self.root, 1));
366 IterRev { stack }
367 }
368
369 pub fn range<'a>(&'a self, lo: Bound<&K>, hi: Bound<&K>) -> RangeIter<'a, K, V>
377 where
378 K: Clone,
379 {
380 let mut stack: Vec<(&'a Arc<BNode<K, V>>, usize)> = Vec::with_capacity(8);
381 let mut node = &self.root;
382 loop {
383 match &**node {
384 BNode::Leaf { entries } => {
385 stack.push((node, lower_index(entries, lo)));
387 break;
388 }
389 BNode::Internal { entries, children } => {
390 let i = lower_index(entries, lo);
391 stack.push((node, 2 * i + 1));
396 node = &children[i];
397 }
398 }
399 }
400 let (hi_key, hi_incl) = match hi {
401 Bound::Unbounded => (None, false),
402 Bound::Included(k) => (Some(k.clone()), true),
403 Bound::Excluded(k) => (Some(k.clone()), false),
404 };
405 RangeIter {
406 inner: Iter { stack },
407 hi_key,
408 hi_incl,
409 done: false,
410 }
411 }
412}
413
414fn lower_index<K: Ord, V>(entries: &[(K, V)], lo: Bound<&K>) -> usize {
417 match lo {
418 Bound::Unbounded => 0,
419 Bound::Included(k) => entries.partition_point(|e| &e.0 < k),
420 Bound::Excluded(k) => entries.partition_point(|e| &e.0 <= k),
421 }
422}
423
424impl<K: Ord + Clone, V: Clone> PersistentBTreeMap<K, V> {
425 #[must_use]
428 pub fn insert(&self, key: K, value: V) -> (Self, Option<V>) {
429 let (new_left, split, prev_v) = insert_helper(&self.root, key, value);
430 let new_root = if let Some((right, median)) = split {
431 Arc::new(BNode::Internal {
432 entries: alloc::vec![median],
433 children: alloc::vec![new_left, right],
434 })
435 } else {
436 new_left
437 };
438 let new_len = if prev_v.is_none() {
439 self.len + 1
440 } else {
441 self.len
442 };
443 (
444 Self {
445 root: new_root,
446 len: new_len,
447 },
448 prev_v,
449 )
450 }
451
452 pub fn insert_mut(&mut self, key: K, value: V) -> Option<V> {
461 let (split, prev_v) = insert_transient_helper(&mut self.root, key, value);
462 if let Some((right, median)) = split {
463 let old_root = core::mem::replace(
469 &mut self.root,
470 Arc::new(BNode::Leaf {
471 entries: Vec::new(),
472 }),
473 );
474 self.root = Arc::new(BNode::Internal {
475 entries: alloc::vec![median],
476 children: alloc::vec![old_root, right],
477 });
478 }
479 if prev_v.is_none() {
480 self.len += 1;
481 }
482 prev_v
483 }
484
485 pub fn remove_mut(&mut self, key: &K) -> Option<V> {
506 let removed = remove_transient_helper(&mut self.root, key)?;
507 let collapse = match self.root.as_ref() {
511 BNode::Internal { entries, children } if entries.is_empty() => {
512 debug_assert_eq!(children.len(), 1);
513 children.first().cloned()
514 }
515 _ => None,
516 };
517 if let Some(only) = collapse {
518 self.root = only;
519 }
520 self.len -= 1;
521 Some(removed)
522 }
523
524 #[must_use]
527 pub fn remove(&self, key: &K) -> (Self, Option<V>) {
528 let mut next = self.clone();
529 let prev = next.remove_mut(key);
530 (next, prev)
531 }
532}
533
534const MIN_ENTRIES: usize = ORDER / 2 - 1; impl<K, V> BNode<K, V> {
539 fn entry_count(&self) -> usize {
540 match self {
541 BNode::Leaf { entries } | BNode::Internal { entries, .. } => entries.len(),
542 }
543 }
544}
545
546fn remove_transient_helper<K: Ord + Clone, V: Clone>(
549 node: &mut Arc<BNode<K, V>>,
550 key: &K,
551) -> Option<V> {
552 let (found, idx) = match node.as_ref() {
554 BNode::Leaf { entries } | BNode::Internal { entries, .. } => {
555 match entries.binary_search_by(|(ek, _)| ek.cmp(key)) {
556 Ok(i) => (true, i),
557 Err(i) => (false, i),
558 }
559 }
560 };
561 if !found && matches!(node.as_ref(), BNode::Leaf { .. }) {
562 return None;
563 }
564 let inner = Arc::make_mut(node);
565 match inner {
566 BNode::Leaf { entries } => Some(entries.remove(idx).1),
567 BNode::Internal { entries, children } => {
568 if found {
569 let pred = remove_max(&mut children[idx]);
573 let old = core::mem::replace(&mut entries[idx], pred);
574 fix_child(entries, children, idx);
575 Some(old.1)
576 } else {
577 let removed = remove_transient_helper(&mut children[idx], key)?;
578 fix_child(entries, children, idx);
579 Some(removed)
580 }
581 }
582 }
583}
584
585fn remove_max<K: Ord + Clone, V: Clone>(node: &mut Arc<BNode<K, V>>) -> (K, V) {
588 let inner = Arc::make_mut(node);
589 match inner {
590 BNode::Leaf { entries } => entries.pop().expect("a B-tree leaf is never empty"),
591 BNode::Internal { entries, children } => {
592 let last = children.len() - 1;
593 let kv = remove_max(&mut children[last]);
594 fix_child(entries, children, last);
595 kv
596 }
597 }
598}
599
600fn fix_child<K: Ord + Clone, V: Clone>(
603 entries: &mut Vec<(K, V)>,
604 children: &mut Vec<Arc<BNode<K, V>>>,
605 i: usize,
606) {
607 if children[i].entry_count() >= MIN_ENTRIES {
608 return;
609 }
610 if i > 0 && children[i - 1].entry_count() > MIN_ENTRIES {
611 rotate_from_left(entries, children, i);
612 } else if i + 1 < children.len() && children[i + 1].entry_count() > MIN_ENTRIES {
613 rotate_from_right(entries, children, i);
614 } else if i > 0 {
615 merge_children(entries, children, i - 1);
616 } else {
617 merge_children(entries, children, i);
618 }
619}
620
621fn rotate_from_left<K: Ord + Clone, V: Clone>(
624 entries: &mut [(K, V)],
625 children: &mut [Arc<BNode<K, V>>],
626 i: usize,
627) {
628 let (moved_entry, moved_child) = match Arc::make_mut(&mut children[i - 1]) {
629 BNode::Leaf { entries: le } => (le.pop().expect("sibling has entries to spare"), None),
630 BNode::Internal {
631 entries: le,
632 children: lc,
633 } => (
634 le.pop().expect("sibling has entries to spare"),
635 Some(
636 lc.pop()
637 .expect("internal node has entries.len()+1 children"),
638 ),
639 ),
640 };
641 let separator = core::mem::replace(&mut entries[i - 1], moved_entry);
642 match Arc::make_mut(&mut children[i]) {
643 BNode::Leaf { entries: ce } => {
644 debug_assert!(moved_child.is_none());
645 ce.insert(0, separator);
646 }
647 BNode::Internal {
648 entries: ce,
649 children: cc,
650 } => {
651 ce.insert(0, separator);
652 cc.insert(
653 0,
654 moved_child.expect("sibling of an internal node is internal"),
655 );
656 }
657 }
658}
659
660fn rotate_from_right<K: Ord + Clone, V: Clone>(
662 entries: &mut [(K, V)],
663 children: &mut [Arc<BNode<K, V>>],
664 i: usize,
665) {
666 let (moved_entry, moved_child) = match Arc::make_mut(&mut children[i + 1]) {
667 BNode::Leaf { entries: re } => (re.remove(0), None),
668 BNode::Internal {
669 entries: re,
670 children: rc,
671 } => (re.remove(0), Some(rc.remove(0))),
672 };
673 let separator = core::mem::replace(&mut entries[i], moved_entry);
674 match Arc::make_mut(&mut children[i]) {
675 BNode::Leaf { entries: ce } => {
676 debug_assert!(moved_child.is_none());
677 ce.push(separator);
678 }
679 BNode::Internal {
680 entries: ce,
681 children: cc,
682 } => {
683 ce.push(separator);
684 cc.push(moved_child.expect("sibling of an internal node is internal"));
685 }
686 }
687}
688
689fn merge_children<K: Ord + Clone, V: Clone>(
692 entries: &mut Vec<(K, V)>,
693 children: &mut Vec<Arc<BNode<K, V>>>,
694 sep: usize,
695) {
696 let separator = entries.remove(sep);
697 let right = children.remove(sep + 1);
698 let right = Arc::try_unwrap(right).unwrap_or_else(|shared| (*shared).clone());
699 match (Arc::make_mut(&mut children[sep]), right) {
700 (BNode::Leaf { entries: le }, BNode::Leaf { entries: re }) => {
701 le.push(separator);
702 le.extend(re);
703 }
704 (
705 BNode::Internal {
706 entries: le,
707 children: lc,
708 },
709 BNode::Internal {
710 entries: re,
711 children: rc,
712 },
713 ) => {
714 le.push(separator);
715 le.extend(re);
716 lc.extend(rc);
717 }
718 (BNode::Leaf { entries: le }, BNode::Internal { .. })
722 | (BNode::Internal { entries: le, .. }, BNode::Leaf { .. }) => {
723 debug_assert!(false, "B-tree siblings must be at the same depth");
724 le.push(separator);
725 }
726 }
727}
728
729fn insert_transient_helper<K: Ord + Clone, V: Clone>(
734 node: &mut Arc<BNode<K, V>>,
735 k: K,
736 v: V,
737) -> (Option<(Arc<BNode<K, V>>, (K, V))>, Option<V>) {
738 let inner = Arc::make_mut(node);
739 match inner {
740 BNode::Leaf { entries } => {
741 let pos = entries.binary_search_by(|(ek, _)| ek.cmp(&k));
742 let prev_v = match pos {
743 Ok(idx) => Some(core::mem::replace(&mut entries[idx].1, v)),
744 Err(idx) => {
745 entries.insert(idx, (k, v));
746 None
747 }
748 };
749 if entries.len() <= MAX_ENTRIES {
750 return (None, prev_v);
751 }
752 let mid = entries.len() / 2;
754 let right_entries = entries.split_off(mid + 1);
755 let median = entries.pop().expect("mid was in-bounds");
756 let right = Arc::new(BNode::Leaf {
757 entries: right_entries,
758 });
759 (Some((right, median)), prev_v)
760 }
761 BNode::Internal { entries, children } => {
762 let pos = entries.binary_search_by(|(ek, _)| ek.cmp(&k));
763 match pos {
764 Ok(idx) => {
765 let prev_v = core::mem::replace(&mut entries[idx].1, v);
766 (None, Some(prev_v))
767 }
768 Err(idx) => {
769 let (split, prev_v) = insert_transient_helper(&mut children[idx], k, v);
770 if let Some((right_sibling, median)) = split {
771 entries.insert(idx, median);
772 children.insert(idx + 1, right_sibling);
773 }
774 if children.len() <= MAX_CHILDREN {
775 return (None, prev_v);
776 }
777 let mid = entries.len() / 2;
778 let right_entries = entries.split_off(mid + 1);
779 let median = entries.pop().expect("mid was in-bounds");
780 let right_children = children.split_off(mid + 1);
781 let right = Arc::new(BNode::Internal {
782 entries: right_entries,
783 children: right_children,
784 });
785 (Some((right, median)), prev_v)
786 }
787 }
788 }
789 }
790}
791
792fn insert_helper<K: Ord + Clone, V: Clone>(
796 node: &Arc<BNode<K, V>>,
797 k: K,
798 v: V,
799) -> (
800 Arc<BNode<K, V>>,
801 Option<(Arc<BNode<K, V>>, (K, V))>,
802 Option<V>,
803) {
804 match &**node {
805 BNode::Leaf { entries } => {
806 let pos = entries.binary_search_by(|(ek, _)| ek.cmp(&k));
807 let mut new_entries = entries.clone();
808 let prev_v = match pos {
809 Ok(idx) => Some(core::mem::replace(&mut new_entries[idx].1, v)),
810 Err(idx) => {
811 new_entries.insert(idx, (k, v));
812 None
813 }
814 };
815 if new_entries.len() <= MAX_ENTRIES {
816 return (
817 Arc::new(BNode::Leaf {
818 entries: new_entries,
819 }),
820 None,
821 prev_v,
822 );
823 }
824 let mid = new_entries.len() / 2; let right_entries = new_entries.split_off(mid + 1);
829 let median = new_entries.pop().expect("mid was in-bounds");
830 let left = Arc::new(BNode::Leaf {
831 entries: new_entries,
832 });
833 let right = Arc::new(BNode::Leaf {
834 entries: right_entries,
835 });
836 (left, Some((right, median)), prev_v)
837 }
838 BNode::Internal { entries, children } => {
839 let pos = entries.binary_search_by(|(ek, _)| ek.cmp(&k));
840 match pos {
841 Ok(idx) => {
842 let mut new_entries = entries.clone();
844 let prev_v = core::mem::replace(&mut new_entries[idx].1, v);
845 (
846 Arc::new(BNode::Internal {
847 entries: new_entries,
848 children: children.clone(),
849 }),
850 None,
851 Some(prev_v),
852 )
853 }
854 Err(idx) => {
855 let (new_child, split, prev_v) = insert_helper(&children[idx], k, v);
857 let mut new_entries = entries.clone();
858 let mut new_children = children.clone();
859 new_children[idx] = new_child;
860 if let Some((right_sibling, median)) = split {
861 new_entries.insert(idx, median);
862 new_children.insert(idx + 1, right_sibling);
863 }
864 if new_children.len() <= MAX_CHILDREN {
865 return (
866 Arc::new(BNode::Internal {
867 entries: new_entries,
868 children: new_children,
869 }),
870 None,
871 prev_v,
872 );
873 }
874 let mid = new_entries.len() / 2; let right_entries = new_entries.split_off(mid + 1);
880 let median = new_entries.pop().expect("mid was in-bounds");
881 let right_children = new_children.split_off(mid + 1);
882 let left = Arc::new(BNode::Internal {
883 entries: new_entries,
884 children: new_children,
885 });
886 let right = Arc::new(BNode::Internal {
887 entries: right_entries,
888 children: right_children,
889 });
890 (left, Some((right, median)), prev_v)
891 }
892 }
893 }
894 }
895}
896
897#[derive(Debug)]
900pub struct Iter<'a, K, V> {
901 stack: Vec<(&'a Arc<BNode<K, V>>, usize)>,
902}
903
904impl<'a, K, V> Iterator for Iter<'a, K, V> {
905 type Item = (&'a K, &'a V);
906 fn next(&mut self) -> Option<(&'a K, &'a V)> {
907 loop {
908 let (node, idx) = *self.stack.last()?;
909 match &**node {
910 BNode::Leaf { entries } => {
911 if idx < entries.len() {
912 let (k, v) = &entries[idx];
913 self.stack.last_mut().unwrap().1 = idx + 1;
914 return Some((k, v));
915 }
916 self.stack.pop();
917 }
918 BNode::Internal { entries, children } => {
919 let phase = idx & 1;
924 let slot = idx >> 1;
925 if phase == 0 {
926 if slot < children.len() {
928 self.stack.last_mut().unwrap().1 = idx + 1;
929 self.stack.push((&children[slot], 0));
930 continue;
931 }
932 self.stack.pop();
933 } else {
934 if slot < entries.len() {
936 let (k, v) = &entries[slot];
937 self.stack.last_mut().unwrap().1 = idx + 1;
938 return Some((k, v));
939 }
940 self.stack.pop();
941 }
942 }
943 }
944 }
945 }
946}
947
948#[derive(Debug)]
952pub struct RangeIter<'a, K, V> {
953 inner: Iter<'a, K, V>,
954 hi_key: Option<K>,
955 hi_incl: bool,
956 done: bool,
957}
958
959impl<'a, K: Ord, V> Iterator for RangeIter<'a, K, V> {
960 type Item = (&'a K, &'a V);
961 fn next(&mut self) -> Option<(&'a K, &'a V)> {
962 if self.done {
963 return None;
964 }
965 let (k, v) = self.inner.next()?;
966 if let Some(h) = &self.hi_key {
967 let past = if self.hi_incl { k > h } else { k >= h };
968 if past {
969 self.done = true;
970 return None;
971 }
972 }
973 Some((k, v))
974 }
975}
976
977#[derive(Debug)]
985pub struct IterRev<'a, K, V> {
986 stack: Vec<(&'a Arc<BNode<K, V>>, usize)>,
994}
995
996impl<'a, K, V> Iterator for IterRev<'a, K, V> {
997 type Item = (&'a K, &'a V);
998 fn next(&mut self) -> Option<(&'a K, &'a V)> {
999 loop {
1000 let (node, pos) = *self.stack.last()?;
1001 match &**node {
1002 BNode::Leaf { entries } => {
1003 if pos <= entries.len() {
1004 let i = entries.len() - pos;
1005 self.stack.last_mut().unwrap().1 = pos + 1;
1006 let (k, v) = &entries[i];
1007 return Some((k, v));
1008 }
1009 self.stack.pop();
1010 }
1011 BNode::Internal { entries, children } => {
1012 let n_steps = 2 * entries.len() + 1;
1013 if pos <= n_steps {
1014 self.stack.last_mut().unwrap().1 = pos + 1;
1015 if pos % 2 == 1 {
1016 let child_idx = entries.len() - (pos - 1) / 2;
1018 self.stack.push((&children[child_idx], 1));
1019 continue;
1020 }
1021 let entry_idx = entries.len() - pos / 2;
1023 let (k, v) = &entries[entry_idx];
1024 return Some((k, v));
1025 }
1026 self.stack.pop();
1027 }
1028 }
1029 }
1030 }
1031}
1032
1033impl<'a, K: Ord, V> IntoIterator for &'a PersistentBTreeMap<K, V> {
1034 type Item = (&'a K, &'a V);
1035 type IntoIter = Iter<'a, K, V>;
1036 fn into_iter(self) -> Self::IntoIter {
1037 self.iter()
1038 }
1039}
1040
1041#[cfg(test)]
1042#[allow(
1043 clippy::cast_possible_truncation,
1044 clippy::cast_possible_wrap,
1045 clippy::cast_sign_loss,
1046 clippy::cast_lossless,
1047 clippy::needless_range_loop,
1048 clippy::items_after_statements,
1049 clippy::manual_range_patterns,
1050 clippy::unreadable_literal,
1051 clippy::similar_names
1052)]
1053mod tests {
1054 use super::*;
1055 use alloc::collections::BTreeMap;
1056 use alloc::vec;
1057
1058 fn check_node<K: Ord + core::fmt::Debug, V>(
1064 node: &BNode<K, V>,
1065 is_root: bool,
1066 depth: usize,
1067 ) -> usize {
1068 let entries = match node {
1069 BNode::Leaf { entries } | BNode::Internal { entries, .. } => entries,
1070 };
1071 assert!(
1072 entries.len() <= MAX_ENTRIES,
1073 "node overfull: {} entries",
1074 entries.len()
1075 );
1076 if !is_root {
1077 assert!(
1078 entries.len() >= MIN_ENTRIES,
1079 "non-root node underfull: {} entries",
1080 entries.len()
1081 );
1082 }
1083 for w in entries.windows(2) {
1084 assert!(w[0].0 < w[1].0, "entries out of order inside a node");
1085 }
1086 match node {
1087 BNode::Leaf { .. } => depth,
1088 BNode::Internal { entries, children } => {
1089 assert_eq!(
1090 children.len(),
1091 entries.len() + 1,
1092 "internal node must have entries.len()+1 children"
1093 );
1094 let mut seen: Option<usize> = None;
1095 for c in children {
1096 let d = check_node(c, false, depth + 1);
1097 match seen {
1098 None => seen = Some(d),
1099 Some(prev) => assert_eq!(prev, d, "leaves at different depths"),
1100 }
1101 }
1102 seen.expect("internal node has children")
1103 }
1104 }
1105 }
1106
1107 fn check_map<K: Ord + Clone + core::fmt::Debug, V: Clone>(m: &PersistentBTreeMap<K, V>) {
1108 check_node(m.root.as_ref(), true, 0);
1109 let keys: Vec<&K> = m.iter().map(|(k, _)| k).collect();
1111 for w in keys.windows(2) {
1112 assert!(w[0] < w[1], "iteration order is not globally sorted");
1113 }
1114 assert_eq!(keys.len(), m.len(), "len disagrees with iteration");
1115 }
1116
1117 fn lcg(state: &mut u64) -> u64 {
1120 *state = state
1121 .wrapping_mul(6_364_136_223_846_793_005)
1122 .wrapping_add(1);
1123 *state >> 33
1124 }
1125
1126 #[test]
1127 fn round465_remove_absent_key_is_a_no_op() {
1128 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1129 for i in 0..50_i64 {
1130 pb.insert_mut(i * 2, i);
1131 }
1132 let before = pb.len();
1133 assert_eq!(pb.remove_mut(&7), None);
1134 assert_eq!(pb.remove_mut(&-1), None);
1135 assert_eq!(pb.remove_mut(&1000), None);
1136 assert_eq!(pb.len(), before);
1137 check_map(&pb);
1138 }
1139
1140 #[test]
1141 fn round465_remove_every_key_empties_the_map() {
1142 for n in [1_i64, 7, 8, 9, 100, 500] {
1143 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1144 for i in 0..n {
1145 pb.insert_mut(i, i * 3);
1146 }
1147 for i in 0..n {
1148 assert_eq!(pb.remove_mut(&i), Some(i * 3), "n={n} i={i}");
1149 assert_eq!(pb.len() as i64, n - i - 1);
1150 check_map(&pb);
1151 for j in (i + 1)..n {
1153 assert_eq!(
1154 pb.get(&j),
1155 Some(&(j * 3)),
1156 "n={n} lost {j} after removing {i}"
1157 );
1158 }
1159 }
1160 assert!(pb.is_empty());
1161 }
1162 }
1163
1164 #[test]
1165 fn round465_remove_in_reverse_order_empties_the_map() {
1166 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1169 for i in 0..300_i64 {
1170 pb.insert_mut(i, i);
1171 }
1172 for i in (0..300_i64).rev() {
1173 assert_eq!(pb.remove_mut(&i), Some(i));
1174 check_map(&pb);
1175 }
1176 assert!(pb.is_empty());
1177 }
1178
1179 #[test]
1180 fn round465_matches_btreemap_under_mixed_traffic() {
1181 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1182 let mut model: BTreeMap<i64, i64> = BTreeMap::new();
1183 let mut seed = 0x5eed_1234_u64;
1184 for step in 0..4000 {
1185 let k = (lcg(&mut seed) % 300) as i64;
1186 if lcg(&mut seed) % 3 == 0 {
1187 assert_eq!(
1188 pb.remove_mut(&k),
1189 model.remove(&k),
1190 "step {step} remove {k}"
1191 );
1192 } else {
1193 let v = (lcg(&mut seed) % 1000) as i64;
1194 assert_eq!(
1195 pb.insert_mut(k, v),
1196 model.insert(k, v),
1197 "step {step} insert {k}"
1198 );
1199 }
1200 assert_eq!(pb.len(), model.len(), "step {step}");
1201 if step % 97 == 0 {
1202 check_map(&pb);
1203 let got: Vec<(i64, i64)> = pb.iter().map(|(k, v)| (*k, *v)).collect();
1204 let want: Vec<(i64, i64)> = model.iter().map(|(k, v)| (*k, *v)).collect();
1205 assert_eq!(got, want, "step {step}");
1206 }
1207 }
1208 check_map(&pb);
1209 let got: Vec<(i64, i64)> = pb.iter().map(|(k, v)| (*k, *v)).collect();
1210 let want: Vec<(i64, i64)> = model.iter().map(|(k, v)| (*k, *v)).collect();
1211 assert_eq!(got, want);
1212 }
1213
1214 #[test]
1215 fn round465_remove_leaves_a_shared_snapshot_untouched() {
1216 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1219 for i in 0..200_i64 {
1220 pb.insert_mut(i, i * 5);
1221 }
1222 let snapshot = pb.clone();
1223 for i in 0..100_i64 {
1224 pb.remove_mut(&(i * 2));
1225 }
1226 check_map(&pb);
1227 check_map(&snapshot);
1228 assert_eq!(snapshot.len(), 200);
1229 for i in 0..200_i64 {
1230 assert_eq!(snapshot.get(&i), Some(&(i * 5)), "snapshot lost {i}");
1231 }
1232 for i in 0..100_i64 {
1233 assert_eq!(pb.get(&(i * 2)), None);
1234 assert_eq!(pb.get(&(i * 2 + 1)), Some(&(i * 10 + 5)));
1235 }
1236 }
1237
1238 #[test]
1239 fn round465_immutable_remove_does_not_touch_the_receiver() {
1240 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1241 for i in 0..60_i64 {
1242 pb.insert_mut(i, i);
1243 }
1244 let (next, prev) = pb.remove(&30);
1245 assert_eq!(prev, Some(30));
1246 assert_eq!(pb.get(&30), Some(&30), "receiver must be untouched");
1247 assert_eq!(next.get(&30), None);
1248 assert_eq!(pb.len(), 60);
1249 assert_eq!(next.len(), 59);
1250 check_map(&pb);
1251 check_map(&next);
1252 }
1253
1254 #[test]
1255 fn round465_range_and_predecessor_still_work_after_removals() {
1256 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1258 for i in 0..400_i64 {
1259 pb.insert_mut(i, i);
1260 }
1261 for i in 0..400_i64 {
1262 if i % 3 == 0 {
1263 pb.remove_mut(&i);
1264 }
1265 }
1266 check_map(&pb);
1267 let in_range: Vec<i64> = pb
1268 .range(Bound::Included(&100), Bound::Excluded(&120))
1269 .map(|(k, _)| *k)
1270 .collect();
1271 let want: Vec<i64> = (100..120).filter(|i| i % 3 != 0).collect();
1272 assert_eq!(in_range, want);
1273 assert_eq!(pb.predecessor(&100).map(|(k, _)| *k), Some(98));
1275 let rev: Vec<i64> = pb.iter_rev().map(|(k, _)| *k).take(3).collect();
1276 assert_eq!(rev, vec![398, 397, 395]);
1277 }
1278
1279 #[test]
1280 fn empty_map_is_empty() {
1281 let pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1282 assert_eq!(pb.len(), 0);
1283 assert!(pb.is_empty());
1284 assert!(pb.get(&42).is_none());
1285 }
1286
1287 #[test]
1288 fn insert_single_into_empty_works() {
1289 let (pb, prev) = PersistentBTreeMap::<i64, i64>::new().insert(1, 100);
1290 assert_eq!(prev, None);
1291 assert_eq!(pb.len(), 1);
1292 assert_eq!(pb.get(&1), Some(&100));
1293 assert_eq!(pb.get(&2), None);
1294 }
1295
1296 #[test]
1297 fn insert_replace_returns_prev_keeps_len() {
1298 let (pb, p1) = PersistentBTreeMap::<i64, i64>::new().insert(7, 10);
1299 assert_eq!(p1, None);
1300 let (pb, p2) = pb.insert(7, 99);
1301 assert_eq!(p2, Some(10));
1302 assert_eq!(pb.len(), 1);
1303 assert_eq!(pb.get(&7), Some(&99));
1304 }
1305
1306 #[test]
1307 fn insert_crosses_leaf_split_boundary() {
1308 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1310 for i in 0..20_i64 {
1311 pb = pb.insert(i, i * 7).0;
1312 }
1313 for i in 0..20_i64 {
1314 assert_eq!(pb.get(&i), Some(&(i * 7)));
1315 }
1316 assert!(pb.get(&20).is_none());
1317 assert_eq!(pb.len(), 20);
1318 }
1319
1320 #[test]
1321 fn insert_grows_through_multiple_internal_splits() {
1322 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1324 for i in 0..200_i64 {
1325 pb = pb.insert(i, i * 11).0;
1326 }
1327 for i in 0..200_i64 {
1328 assert_eq!(pb.get(&i), Some(&(i * 11)));
1329 }
1330 assert_eq!(pb.len(), 200);
1331 }
1332
1333 #[test]
1334 fn clone_then_insert_preserves_original() {
1335 let mut a: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1336 for i in 0..100_i64 {
1337 a = a.insert(i, i).0;
1338 }
1339 let b = a.clone();
1340 let (b, _) = b.insert(999, 999);
1341 assert_eq!(a.len(), 100);
1342 assert!(a.get(&999).is_none());
1343 assert_eq!(b.len(), 101);
1344 assert_eq!(b.get(&999), Some(&999));
1345 for i in 0..100_i64 {
1346 assert_eq!(a.get(&i), Some(&i), "A drift at {i}");
1347 assert_eq!(b.get(&i), Some(&i), "B drift at {i}");
1348 }
1349 }
1350
1351 #[test]
1352 fn iter_yields_sorted_order() {
1353 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1354 for &k in &[7_i64, 3, 11, 1, 9, 5, 14, 2, 8, 12, 4, 6, 10, 13] {
1356 pb = pb.insert(k, k * 2).0;
1357 }
1358 let collected: Vec<(i64, i64)> = pb.iter().map(|(k, v)| (*k, *v)).collect();
1359 let expected: Vec<(i64, i64)> = (1..=14).map(|k| (k, k * 2)).collect();
1360 assert_eq!(collected, expected);
1361 }
1362
1363 #[test]
1364 fn iter_handles_taller_tree() {
1365 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1366 for i in 0..500_i64 {
1367 pb = pb.insert(i, i).0;
1368 }
1369 let collected: Vec<i64> = pb.iter().map(|(k, _)| *k).collect();
1370 let expected: Vec<i64> = (0..500).collect();
1371 assert_eq!(collected, expected);
1372 }
1373
1374 #[test]
1375 fn range_basic_bounds() {
1376 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1377 for i in 0..100_i64 {
1378 pb = pb.insert(i, i * 10).0;
1379 }
1380 let keys = |lo: Bound<&i64>, hi: Bound<&i64>| -> Vec<i64> {
1381 pb.range(lo, hi).map(|(k, _)| *k).collect()
1382 };
1383 assert_eq!(
1384 keys(Bound::Included(&20), Bound::Included(&24)),
1385 vec![20, 21, 22, 23, 24]
1386 );
1387 assert_eq!(
1388 keys(Bound::Excluded(&20), Bound::Excluded(&24)),
1389 vec![21, 22, 23]
1390 );
1391 assert_eq!(keys(Bound::Unbounded, Bound::Excluded(&3)), vec![0, 1, 2]);
1392 assert_eq!(
1393 keys(Bound::Included(&97), Bound::Unbounded),
1394 vec![97, 98, 99]
1395 );
1396 assert!(keys(Bound::Included(&50), Bound::Included(&49)).is_empty());
1397 assert_eq!(
1399 keys(Bound::Included(&-5), Bound::Included(&2)),
1400 vec![0, 1, 2]
1401 );
1402 assert_eq!(
1403 keys(Bound::Included(&200), Bound::Unbounded),
1404 Vec::<i64>::new()
1405 );
1406 }
1407
1408 #[test]
1413 fn fuzz_range_against_btreemap() {
1414 let mut rng = Splitmix::new(0x5EED_1234_u64);
1415 const KEY_RANGE: i64 = 512;
1416 for &n_inserts in &[0usize, 5, 40, 300, 2000] {
1418 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1419 let mut oracle: BTreeMap<i64, i64> = BTreeMap::new();
1420 for _ in 0..n_inserts {
1421 let key = (rng.next() as i64).rem_euclid(KEY_RANGE);
1422 let val = rng.next() as i64;
1423 pb = pb.insert(key, val).0;
1424 oracle.insert(key, val);
1425 }
1426 for _ in 0..2000 {
1427 let a = (rng.next() as i64).rem_euclid(KEY_RANGE + 40) - 20;
1428 let b = (rng.next() as i64).rem_euclid(KEY_RANGE + 40) - 20;
1429 let (lo_raw, hi_raw) = if a <= b { (a, b) } else { (b, a) };
1430 let mk = |raw: i64, sel: u64| -> Bound<i64> {
1431 match sel % 3 {
1432 0 => Bound::Included(raw),
1433 1 => Bound::Excluded(raw),
1434 _ => Bound::Unbounded,
1435 }
1436 };
1437 let lo = mk(lo_raw, rng.next());
1438 let hi = mk(hi_raw, rng.next());
1439 if lo_raw == hi_raw
1442 && matches!(lo, Bound::Excluded(_))
1443 && matches!(hi, Bound::Excluded(_))
1444 {
1445 continue;
1446 }
1447 let lo_ref = match &lo {
1448 Bound::Included(k) => Bound::Included(k),
1449 Bound::Excluded(k) => Bound::Excluded(k),
1450 Bound::Unbounded => Bound::Unbounded,
1451 };
1452 let hi_ref = match &hi {
1453 Bound::Included(k) => Bound::Included(k),
1454 Bound::Excluded(k) => Bound::Excluded(k),
1455 Bound::Unbounded => Bound::Unbounded,
1456 };
1457 let got: Vec<(i64, i64)> =
1458 pb.range(lo_ref, hi_ref).map(|(k, v)| (*k, *v)).collect();
1459 let want: Vec<(i64, i64)> = oracle.range((lo, hi)).map(|(k, v)| (*k, *v)).collect();
1460 assert_eq!(
1461 got, want,
1462 "range drift n={n_inserts} lo={lo_raw:?} hi={hi_raw:?}"
1463 );
1464 }
1465 }
1466 }
1467
1468 #[test]
1471 fn fuzz_predecessor_against_btreemap() {
1472 let mut rng = Splitmix::new(0x9E37_79B9_7F4A_7C15_u64);
1473 const KEY_RANGE: i64 = 512;
1474 for &n_inserts in &[0usize, 5, 40, 300, 2000] {
1475 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1476 let mut oracle: BTreeMap<i64, i64> = BTreeMap::new();
1477 for _ in 0..n_inserts {
1478 let key = (rng.next() as i64).rem_euclid(KEY_RANGE);
1479 let val = rng.next() as i64;
1480 pb = pb.insert(key, val).0;
1481 oracle.insert(key, val);
1482 }
1483 for _ in 0..2000 {
1484 let probe = (rng.next() as i64).rem_euclid(KEY_RANGE + 40) - 20;
1485 let got = pb.predecessor(&probe).map(|(k, v)| (*k, *v));
1486 let want = oracle.range(..probe).next_back().map(|(k, v)| (*k, *v));
1487 assert_eq!(got, want, "predecessor drift n={n_inserts} probe={probe}");
1488 }
1489 }
1490 }
1491
1492 #[test]
1493 fn iter_rev_yields_descending() {
1494 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1495 for &k in &[7_i64, 3, 11, 1, 9, 5, 14, 2, 8, 12, 4, 6, 10, 13] {
1496 pb = pb.insert(k, k * 2).0;
1497 }
1498 let collected: Vec<(i64, i64)> = pb.iter_rev().map(|(k, v)| (*k, *v)).collect();
1499 let expected: Vec<(i64, i64)> = (1..=14).rev().map(|k| (k, k * 2)).collect();
1500 assert_eq!(collected, expected);
1501 }
1502
1503 #[test]
1504 fn iter_rev_handles_taller_tree() {
1505 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1506 for i in 0..500_i64 {
1507 pb = pb.insert(i, i).0;
1508 }
1509 let collected: Vec<i64> = pb.iter_rev().map(|(k, _)| *k).collect();
1510 let expected: Vec<i64> = (0..500).rev().collect();
1511 assert_eq!(collected, expected);
1512 }
1513
1514 #[test]
1515 fn iter_rev_empty_map_returns_nothing() {
1516 let pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1517 assert_eq!(pb.iter_rev().count(), 0);
1518 }
1519
1520 #[test]
1521 fn iter_rev_lazy_stops_at_take() {
1522 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1525 for i in 0..10000_i64 {
1526 pb = pb.insert(i, i).0;
1527 }
1528 let top5: Vec<i64> = pb.iter_rev().take(5).map(|(k, _)| *k).collect();
1529 assert_eq!(top5, vec![9999, 9998, 9997, 9996, 9995]);
1530 }
1531
1532 struct Splitmix(u64);
1534 impl Splitmix {
1535 fn new(seed: u64) -> Self {
1536 Self(seed)
1537 }
1538 fn next(&mut self) -> u64 {
1539 self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15);
1540 let mut x = self.0;
1541 x = (x ^ (x >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
1542 x = (x ^ (x >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
1543 x ^ (x >> 31)
1544 }
1545 }
1546
1547 #[test]
1550 fn fuzz_oracle_against_std_btreemap() {
1551 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1552 let mut oracle: BTreeMap<i64, i64> = BTreeMap::new();
1553 let mut rng = Splitmix::new(0xC0FFEE_u64);
1554 const STEPS: usize = 100_000;
1555 const KEY_RANGE: i64 = 4096;
1557 for step in 0..STEPS {
1558 let op = rng.next() % 3; let key = (rng.next() as i64) % KEY_RANGE;
1560 match op {
1561 0 | 1 => {
1562 let val = rng.next() as i64;
1563 let (new_pb, prev_pb) = pb.insert(key, val);
1564 let prev_oracle = oracle.insert(key, val);
1565 assert_eq!(prev_pb, prev_oracle, "prev drift @ step {step}, key {key}");
1566 pb = new_pb;
1567 assert_eq!(pb.len(), oracle.len(), "len drift @ step {step}");
1568 }
1569 2 => {
1570 let pb_v = pb.get(&key).copied();
1571 let oracle_v = oracle.get(&key).copied();
1572 assert_eq!(pb_v, oracle_v, "get drift @ step {step}, key {key}");
1573 }
1574 _ => unreachable!(),
1575 }
1576 }
1577 for (k, v) in &oracle {
1579 assert_eq!(pb.get(k), Some(v), "final drift at key {k}");
1580 }
1581 let pb_collected: Vec<(i64, i64)> = pb.iter().map(|(k, v)| (*k, *v)).collect();
1583 let oracle_collected: Vec<(i64, i64)> = oracle.iter().map(|(k, v)| (*k, *v)).collect();
1584 assert_eq!(pb_collected, oracle_collected);
1585 }
1586
1587 #[test]
1590 fn fuzz_oracle_clone_isolation() {
1591 let mut a: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1592 let mut oracle_a: BTreeMap<i64, i64> = BTreeMap::new();
1593 let mut rng = Splitmix::new(0xDECAFBAD_u64);
1594 for _ in 0..1_000 {
1595 let k = (rng.next() as i64) % 1000;
1596 let v = rng.next() as i64;
1597 a = a.insert(k, v).0;
1598 oracle_a.insert(k, v);
1599 }
1600 let mut b = a.clone();
1602 let mut oracle_b = oracle_a.clone();
1603 let mut c = a.clone();
1604 let mut oracle_c = oracle_a.clone();
1605 for _ in 0..500 {
1606 let k = (rng.next() as i64) % 2000;
1607 let v = rng.next() as i64;
1608 b = b.insert(k, v).0;
1609 oracle_b.insert(k, v);
1610 }
1611 for _ in 0..300 {
1612 let k = (rng.next() as i64) % 500;
1613 let v = rng.next() as i64;
1614 c = c.insert(k, v).0;
1615 oracle_c.insert(k, v);
1616 }
1617 for (k, v) in &oracle_a {
1618 assert_eq!(a.get(k), Some(v), "A drift at {k}");
1619 }
1620 for (k, v) in &oracle_b {
1621 assert_eq!(b.get(k), Some(v), "B drift at {k}");
1622 }
1623 for (k, v) in &oracle_c {
1624 assert_eq!(c.get(k), Some(v), "C drift at {k}");
1625 }
1626 }
1627
1628 #[test]
1629 fn partial_eq_compares_by_elements() {
1630 let mut a: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1631 let mut b: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1632 for &k in &[5_i64, 2, 8, 1, 7, 3, 6, 4] {
1635 a = a.insert(k, k * 10).0;
1636 }
1637 for &k in &[1_i64, 2, 3, 4, 5, 6, 7, 8] {
1638 b = b.insert(k, k * 10).0;
1639 }
1640 assert_eq!(a, b);
1641 let (a, _) = a.insert(9, 90);
1642 assert_ne!(a, b);
1643 }
1644}