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 get_by<Q>(&self, key: &Q) -> Option<&V>
472 where
473 K: core::borrow::Borrow<Q>,
474 Q: Ord + ?Sized,
475 {
476 let mut node: &Arc<BNode<K, V>> = &self.root;
477 loop {
478 match &**node {
479 BNode::Leaf { entries } => {
480 return linear_find_entry_by(entries, key).map(|i| &entries[i].1);
481 }
482 BNode::Internal { entries, children } => {
483 match linear_position_internal_by(entries, key) {
484 FoundOrDescend::Found(i) => return Some(&entries[i].1),
485 FoundOrDescend::Descend(i) => node = &children[i],
486 }
487 }
488 }
489 }
490 }
491
492 pub fn get_mut_by<Q>(&mut self, key: &Q) -> Option<&mut V>
494 where
495 K: core::borrow::Borrow<Q> + Clone,
496 V: Clone,
497 Q: Ord + ?Sized,
498 {
499 get_mut_by_helper(&mut self.root, key)
500 }
501
502 pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
520 get_mut_helper(&mut self.root, key)
521 }
522
523 pub fn insert_mut(&mut self, key: K, value: V) -> Option<V> {
524 let (split, prev_v) = insert_transient_helper(&mut self.root, key, value);
525 if let Some((right, median)) = split {
526 let old_root = core::mem::replace(
532 &mut self.root,
533 Arc::new(BNode::Leaf {
534 entries: Vec::new(),
535 }),
536 );
537 self.root = Arc::new(BNode::Internal {
538 entries: alloc::vec![median],
539 children: alloc::vec![old_root, right],
540 });
541 }
542 if prev_v.is_none() {
543 self.len += 1;
544 }
545 prev_v
546 }
547
548 pub fn remove_mut(&mut self, key: &K) -> Option<V> {
569 let removed = remove_transient_helper(&mut self.root, key)?;
570 let collapse = match self.root.as_ref() {
574 BNode::Internal { entries, children } if entries.is_empty() => {
575 debug_assert_eq!(children.len(), 1);
576 children.first().cloned()
577 }
578 _ => None,
579 };
580 if let Some(only) = collapse {
581 self.root = only;
582 }
583 self.len -= 1;
584 Some(removed)
585 }
586
587 #[must_use]
590 pub fn remove(&self, key: &K) -> (Self, Option<V>) {
591 let mut next = self.clone();
592 let prev = next.remove_mut(key);
593 (next, prev)
594 }
595}
596
597const MIN_ENTRIES: usize = ORDER / 2 - 1; impl<K, V> BNode<K, V> {
602 fn entry_count(&self) -> usize {
603 match self {
604 BNode::Leaf { entries } | BNode::Internal { entries, .. } => entries.len(),
605 }
606 }
607}
608
609fn remove_transient_helper<K: Ord + Clone, V: Clone>(
612 node: &mut Arc<BNode<K, V>>,
613 key: &K,
614) -> Option<V> {
615 let (found, idx) = match node.as_ref() {
617 BNode::Leaf { entries } | BNode::Internal { entries, .. } => {
618 match entries.binary_search_by(|(ek, _)| ek.cmp(key)) {
619 Ok(i) => (true, i),
620 Err(i) => (false, i),
621 }
622 }
623 };
624 if !found && matches!(node.as_ref(), BNode::Leaf { .. }) {
625 return None;
626 }
627 let inner = Arc::make_mut(node);
628 match inner {
629 BNode::Leaf { entries } => Some(entries.remove(idx).1),
630 BNode::Internal { entries, children } => {
631 if found {
632 let pred = remove_max(&mut children[idx]);
636 let old = core::mem::replace(&mut entries[idx], pred);
637 fix_child(entries, children, idx);
638 Some(old.1)
639 } else {
640 let removed = remove_transient_helper(&mut children[idx], key)?;
641 fix_child(entries, children, idx);
642 Some(removed)
643 }
644 }
645 }
646}
647
648fn remove_max<K: Ord + Clone, V: Clone>(node: &mut Arc<BNode<K, V>>) -> (K, V) {
651 let inner = Arc::make_mut(node);
652 match inner {
653 BNode::Leaf { entries } => entries.pop().expect("a B-tree leaf is never empty"),
654 BNode::Internal { entries, children } => {
655 let last = children.len() - 1;
656 let kv = remove_max(&mut children[last]);
657 fix_child(entries, children, last);
658 kv
659 }
660 }
661}
662
663fn fix_child<K: Ord + Clone, V: Clone>(
666 entries: &mut Vec<(K, V)>,
667 children: &mut Vec<Arc<BNode<K, V>>>,
668 i: usize,
669) {
670 if children[i].entry_count() >= MIN_ENTRIES {
671 return;
672 }
673 if i > 0 && children[i - 1].entry_count() > MIN_ENTRIES {
674 rotate_from_left(entries, children, i);
675 } else if i + 1 < children.len() && children[i + 1].entry_count() > MIN_ENTRIES {
676 rotate_from_right(entries, children, i);
677 } else if i > 0 {
678 merge_children(entries, children, i - 1);
679 } else {
680 merge_children(entries, children, i);
681 }
682}
683
684fn rotate_from_left<K: Ord + Clone, V: Clone>(
687 entries: &mut [(K, V)],
688 children: &mut [Arc<BNode<K, V>>],
689 i: usize,
690) {
691 let (moved_entry, moved_child) = match Arc::make_mut(&mut children[i - 1]) {
692 BNode::Leaf { entries: le } => (le.pop().expect("sibling has entries to spare"), None),
693 BNode::Internal {
694 entries: le,
695 children: lc,
696 } => (
697 le.pop().expect("sibling has entries to spare"),
698 Some(
699 lc.pop()
700 .expect("internal node has entries.len()+1 children"),
701 ),
702 ),
703 };
704 let separator = core::mem::replace(&mut entries[i - 1], moved_entry);
705 match Arc::make_mut(&mut children[i]) {
706 BNode::Leaf { entries: ce } => {
707 debug_assert!(moved_child.is_none());
708 ce.insert(0, separator);
709 }
710 BNode::Internal {
711 entries: ce,
712 children: cc,
713 } => {
714 ce.insert(0, separator);
715 cc.insert(
716 0,
717 moved_child.expect("sibling of an internal node is internal"),
718 );
719 }
720 }
721}
722
723fn rotate_from_right<K: Ord + Clone, V: Clone>(
725 entries: &mut [(K, V)],
726 children: &mut [Arc<BNode<K, V>>],
727 i: usize,
728) {
729 let (moved_entry, moved_child) = match Arc::make_mut(&mut children[i + 1]) {
730 BNode::Leaf { entries: re } => (re.remove(0), None),
731 BNode::Internal {
732 entries: re,
733 children: rc,
734 } => (re.remove(0), Some(rc.remove(0))),
735 };
736 let separator = core::mem::replace(&mut entries[i], moved_entry);
737 match Arc::make_mut(&mut children[i]) {
738 BNode::Leaf { entries: ce } => {
739 debug_assert!(moved_child.is_none());
740 ce.push(separator);
741 }
742 BNode::Internal {
743 entries: ce,
744 children: cc,
745 } => {
746 ce.push(separator);
747 cc.push(moved_child.expect("sibling of an internal node is internal"));
748 }
749 }
750}
751
752fn merge_children<K: Ord + Clone, V: Clone>(
755 entries: &mut Vec<(K, V)>,
756 children: &mut Vec<Arc<BNode<K, V>>>,
757 sep: usize,
758) {
759 let separator = entries.remove(sep);
760 let right = children.remove(sep + 1);
761 let right = Arc::try_unwrap(right).unwrap_or_else(|shared| (*shared).clone());
762 match (Arc::make_mut(&mut children[sep]), right) {
763 (BNode::Leaf { entries: le }, BNode::Leaf { entries: re }) => {
764 le.push(separator);
765 le.extend(re);
766 }
767 (
768 BNode::Internal {
769 entries: le,
770 children: lc,
771 },
772 BNode::Internal {
773 entries: re,
774 children: rc,
775 },
776 ) => {
777 le.push(separator);
778 le.extend(re);
779 lc.extend(rc);
780 }
781 (BNode::Leaf { entries: le }, BNode::Internal { .. })
785 | (BNode::Internal { entries: le, .. }, BNode::Leaf { .. }) => {
786 debug_assert!(false, "B-tree siblings must be at the same depth");
787 le.push(separator);
788 }
789 }
790}
791
792fn linear_find_entry_by<K, V, Q>(entries: &[(K, V)], key: &Q) -> Option<usize>
796where
797 K: core::borrow::Borrow<Q>,
798 Q: Ord + ?Sized,
799{
800 for (i, (k, _)) in entries.iter().enumerate() {
801 match k.borrow().cmp(key) {
802 core::cmp::Ordering::Equal => return Some(i),
803 core::cmp::Ordering::Greater => return None,
804 core::cmp::Ordering::Less => continue,
805 }
806 }
807 None
808}
809
810fn linear_position_internal_by<K, V, Q>(entries: &[(K, V)], key: &Q) -> FoundOrDescend
811where
812 K: core::borrow::Borrow<Q>,
813 Q: Ord + ?Sized,
814{
815 for (i, (k, _)) in entries.iter().enumerate() {
816 match k.borrow().cmp(key) {
817 core::cmp::Ordering::Equal => return FoundOrDescend::Found(i),
818 core::cmp::Ordering::Greater => return FoundOrDescend::Descend(i),
819 core::cmp::Ordering::Less => continue,
820 }
821 }
822 FoundOrDescend::Descend(entries.len())
823}
824
825fn get_mut_by_helper<'a, K, V, Q>(node: &'a mut Arc<BNode<K, V>>, key: &Q) -> Option<&'a mut V>
826where
827 K: core::borrow::Borrow<Q> + Clone,
828 V: Clone,
829 Q: Ord + ?Sized,
830{
831 match Arc::make_mut(node) {
832 BNode::Leaf { entries } => {
833 let i = linear_find_entry_by(entries, key)?;
834 Some(&mut entries[i].1)
835 }
836 BNode::Internal { entries, children } => match linear_position_internal_by(entries, key) {
837 FoundOrDescend::Found(i) => Some(&mut entries[i].1),
838 FoundOrDescend::Descend(i) => get_mut_by_helper(&mut children[i], key),
839 },
840 }
841}
842
843fn get_mut_helper<'a, K: Ord + Clone, V: Clone>(
847 node: &'a mut Arc<BNode<K, V>>,
848 key: &K,
849) -> Option<&'a mut V> {
850 match Arc::make_mut(node) {
851 BNode::Leaf { entries } => {
852 let i = linear_find_entry(entries, key)?;
853 Some(&mut entries[i].1)
854 }
855 BNode::Internal { entries, children } => match linear_position_internal(entries, key) {
856 FoundOrDescend::Found(i) => Some(&mut entries[i].1),
857 FoundOrDescend::Descend(i) => get_mut_helper(&mut children[i], key),
858 },
859 }
860}
861
862fn insert_transient_helper<K: Ord + Clone, V: Clone>(
867 node: &mut Arc<BNode<K, V>>,
868 k: K,
869 v: V,
870) -> (Option<(Arc<BNode<K, V>>, (K, V))>, Option<V>) {
871 let inner = Arc::make_mut(node);
872 match inner {
873 BNode::Leaf { entries } => {
874 let pos = entries.binary_search_by(|(ek, _)| ek.cmp(&k));
875 let prev_v = match pos {
876 Ok(idx) => Some(core::mem::replace(&mut entries[idx].1, v)),
877 Err(idx) => {
878 entries.insert(idx, (k, v));
879 None
880 }
881 };
882 if entries.len() <= MAX_ENTRIES {
883 return (None, prev_v);
884 }
885 let mid = entries.len() / 2;
887 let right_entries = entries.split_off(mid + 1);
888 let median = entries.pop().expect("mid was in-bounds");
889 let right = Arc::new(BNode::Leaf {
890 entries: right_entries,
891 });
892 (Some((right, median)), prev_v)
893 }
894 BNode::Internal { entries, children } => {
895 let pos = entries.binary_search_by(|(ek, _)| ek.cmp(&k));
896 match pos {
897 Ok(idx) => {
898 let prev_v = core::mem::replace(&mut entries[idx].1, v);
899 (None, Some(prev_v))
900 }
901 Err(idx) => {
902 let (split, prev_v) = insert_transient_helper(&mut children[idx], k, v);
903 if let Some((right_sibling, median)) = split {
904 entries.insert(idx, median);
905 children.insert(idx + 1, right_sibling);
906 }
907 if children.len() <= MAX_CHILDREN {
908 return (None, prev_v);
909 }
910 let mid = entries.len() / 2;
911 let right_entries = entries.split_off(mid + 1);
912 let median = entries.pop().expect("mid was in-bounds");
913 let right_children = children.split_off(mid + 1);
914 let right = Arc::new(BNode::Internal {
915 entries: right_entries,
916 children: right_children,
917 });
918 (Some((right, median)), prev_v)
919 }
920 }
921 }
922 }
923}
924
925fn insert_helper<K: Ord + Clone, V: Clone>(
929 node: &Arc<BNode<K, V>>,
930 k: K,
931 v: V,
932) -> (
933 Arc<BNode<K, V>>,
934 Option<(Arc<BNode<K, V>>, (K, V))>,
935 Option<V>,
936) {
937 match &**node {
938 BNode::Leaf { entries } => {
939 let pos = entries.binary_search_by(|(ek, _)| ek.cmp(&k));
940 let mut new_entries = entries.clone();
941 let prev_v = match pos {
942 Ok(idx) => Some(core::mem::replace(&mut new_entries[idx].1, v)),
943 Err(idx) => {
944 new_entries.insert(idx, (k, v));
945 None
946 }
947 };
948 if new_entries.len() <= MAX_ENTRIES {
949 return (
950 Arc::new(BNode::Leaf {
951 entries: new_entries,
952 }),
953 None,
954 prev_v,
955 );
956 }
957 let mid = new_entries.len() / 2; let right_entries = new_entries.split_off(mid + 1);
962 let median = new_entries.pop().expect("mid was in-bounds");
963 let left = Arc::new(BNode::Leaf {
964 entries: new_entries,
965 });
966 let right = Arc::new(BNode::Leaf {
967 entries: right_entries,
968 });
969 (left, Some((right, median)), prev_v)
970 }
971 BNode::Internal { entries, children } => {
972 let pos = entries.binary_search_by(|(ek, _)| ek.cmp(&k));
973 match pos {
974 Ok(idx) => {
975 let mut new_entries = entries.clone();
977 let prev_v = core::mem::replace(&mut new_entries[idx].1, v);
978 (
979 Arc::new(BNode::Internal {
980 entries: new_entries,
981 children: children.clone(),
982 }),
983 None,
984 Some(prev_v),
985 )
986 }
987 Err(idx) => {
988 let (new_child, split, prev_v) = insert_helper(&children[idx], k, v);
990 let mut new_entries = entries.clone();
991 let mut new_children = children.clone();
992 new_children[idx] = new_child;
993 if let Some((right_sibling, median)) = split {
994 new_entries.insert(idx, median);
995 new_children.insert(idx + 1, right_sibling);
996 }
997 if new_children.len() <= MAX_CHILDREN {
998 return (
999 Arc::new(BNode::Internal {
1000 entries: new_entries,
1001 children: new_children,
1002 }),
1003 None,
1004 prev_v,
1005 );
1006 }
1007 let mid = new_entries.len() / 2; let right_entries = new_entries.split_off(mid + 1);
1013 let median = new_entries.pop().expect("mid was in-bounds");
1014 let right_children = new_children.split_off(mid + 1);
1015 let left = Arc::new(BNode::Internal {
1016 entries: new_entries,
1017 children: new_children,
1018 });
1019 let right = Arc::new(BNode::Internal {
1020 entries: right_entries,
1021 children: right_children,
1022 });
1023 (left, Some((right, median)), prev_v)
1024 }
1025 }
1026 }
1027 }
1028}
1029
1030#[derive(Debug)]
1033pub struct Iter<'a, K, V> {
1034 stack: Vec<(&'a Arc<BNode<K, V>>, usize)>,
1035}
1036
1037impl<'a, K, V> Iterator for Iter<'a, K, V> {
1038 type Item = (&'a K, &'a V);
1039 fn next(&mut self) -> Option<(&'a K, &'a V)> {
1040 loop {
1041 let (node, idx) = *self.stack.last()?;
1042 match &**node {
1043 BNode::Leaf { entries } => {
1044 if idx < entries.len() {
1045 let (k, v) = &entries[idx];
1046 self.stack.last_mut().unwrap().1 = idx + 1;
1047 return Some((k, v));
1048 }
1049 self.stack.pop();
1050 }
1051 BNode::Internal { entries, children } => {
1052 let phase = idx & 1;
1057 let slot = idx >> 1;
1058 if phase == 0 {
1059 if slot < children.len() {
1061 self.stack.last_mut().unwrap().1 = idx + 1;
1062 self.stack.push((&children[slot], 0));
1063 continue;
1064 }
1065 self.stack.pop();
1066 } else {
1067 if slot < entries.len() {
1069 let (k, v) = &entries[slot];
1070 self.stack.last_mut().unwrap().1 = idx + 1;
1071 return Some((k, v));
1072 }
1073 self.stack.pop();
1074 }
1075 }
1076 }
1077 }
1078 }
1079}
1080
1081#[derive(Debug)]
1085pub struct RangeIter<'a, K, V> {
1086 inner: Iter<'a, K, V>,
1087 hi_key: Option<K>,
1088 hi_incl: bool,
1089 done: bool,
1090}
1091
1092impl<'a, K: Ord, V> Iterator for RangeIter<'a, K, V> {
1093 type Item = (&'a K, &'a V);
1094 fn next(&mut self) -> Option<(&'a K, &'a V)> {
1095 if self.done {
1096 return None;
1097 }
1098 let (k, v) = self.inner.next()?;
1099 if let Some(h) = &self.hi_key {
1100 let past = if self.hi_incl { k > h } else { k >= h };
1101 if past {
1102 self.done = true;
1103 return None;
1104 }
1105 }
1106 Some((k, v))
1107 }
1108}
1109
1110#[derive(Debug)]
1118pub struct IterRev<'a, K, V> {
1119 stack: Vec<(&'a Arc<BNode<K, V>>, usize)>,
1127}
1128
1129impl<'a, K, V> Iterator for IterRev<'a, K, V> {
1130 type Item = (&'a K, &'a V);
1131 fn next(&mut self) -> Option<(&'a K, &'a V)> {
1132 loop {
1133 let (node, pos) = *self.stack.last()?;
1134 match &**node {
1135 BNode::Leaf { entries } => {
1136 if pos <= entries.len() {
1137 let i = entries.len() - pos;
1138 self.stack.last_mut().unwrap().1 = pos + 1;
1139 let (k, v) = &entries[i];
1140 return Some((k, v));
1141 }
1142 self.stack.pop();
1143 }
1144 BNode::Internal { entries, children } => {
1145 let n_steps = 2 * entries.len() + 1;
1146 if pos <= n_steps {
1147 self.stack.last_mut().unwrap().1 = pos + 1;
1148 if pos % 2 == 1 {
1149 let child_idx = entries.len() - (pos - 1) / 2;
1151 self.stack.push((&children[child_idx], 1));
1152 continue;
1153 }
1154 let entry_idx = entries.len() - pos / 2;
1156 let (k, v) = &entries[entry_idx];
1157 return Some((k, v));
1158 }
1159 self.stack.pop();
1160 }
1161 }
1162 }
1163 }
1164}
1165
1166impl<'a, K: Ord, V> IntoIterator for &'a PersistentBTreeMap<K, V> {
1167 type Item = (&'a K, &'a V);
1168 type IntoIter = Iter<'a, K, V>;
1169 fn into_iter(self) -> Self::IntoIter {
1170 self.iter()
1171 }
1172}
1173
1174#[cfg(test)]
1175#[allow(
1176 clippy::cast_possible_truncation,
1177 clippy::cast_possible_wrap,
1178 clippy::cast_sign_loss,
1179 clippy::cast_lossless,
1180 clippy::needless_range_loop,
1181 clippy::items_after_statements,
1182 clippy::manual_range_patterns,
1183 clippy::unreadable_literal,
1184 clippy::similar_names
1185)]
1186mod tests {
1187 use super::*;
1188 use alloc::collections::BTreeMap;
1189 use alloc::vec;
1190
1191 fn check_node<K: Ord + core::fmt::Debug, V>(
1197 node: &BNode<K, V>,
1198 is_root: bool,
1199 depth: usize,
1200 ) -> usize {
1201 let entries = match node {
1202 BNode::Leaf { entries } | BNode::Internal { entries, .. } => entries,
1203 };
1204 assert!(
1205 entries.len() <= MAX_ENTRIES,
1206 "node overfull: {} entries",
1207 entries.len()
1208 );
1209 if !is_root {
1210 assert!(
1211 entries.len() >= MIN_ENTRIES,
1212 "non-root node underfull: {} entries",
1213 entries.len()
1214 );
1215 }
1216 for w in entries.windows(2) {
1217 assert!(w[0].0 < w[1].0, "entries out of order inside a node");
1218 }
1219 match node {
1220 BNode::Leaf { .. } => depth,
1221 BNode::Internal { entries, children } => {
1222 assert_eq!(
1223 children.len(),
1224 entries.len() + 1,
1225 "internal node must have entries.len()+1 children"
1226 );
1227 let mut seen: Option<usize> = None;
1228 for c in children {
1229 let d = check_node(c, false, depth + 1);
1230 match seen {
1231 None => seen = Some(d),
1232 Some(prev) => assert_eq!(prev, d, "leaves at different depths"),
1233 }
1234 }
1235 seen.expect("internal node has children")
1236 }
1237 }
1238 }
1239
1240 fn check_map<K: Ord + Clone + core::fmt::Debug, V: Clone>(m: &PersistentBTreeMap<K, V>) {
1241 check_node(m.root.as_ref(), true, 0);
1242 let keys: Vec<&K> = m.iter().map(|(k, _)| k).collect();
1244 for w in keys.windows(2) {
1245 assert!(w[0] < w[1], "iteration order is not globally sorted");
1246 }
1247 assert_eq!(keys.len(), m.len(), "len disagrees with iteration");
1248 }
1249
1250 fn lcg(state: &mut u64) -> u64 {
1253 *state = state
1254 .wrapping_mul(6_364_136_223_846_793_005)
1255 .wrapping_add(1);
1256 *state >> 33
1257 }
1258
1259 #[test]
1260 fn round465_remove_absent_key_is_a_no_op() {
1261 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1262 for i in 0..50_i64 {
1263 pb.insert_mut(i * 2, i);
1264 }
1265 let before = pb.len();
1266 assert_eq!(pb.remove_mut(&7), None);
1267 assert_eq!(pb.remove_mut(&-1), None);
1268 assert_eq!(pb.remove_mut(&1000), None);
1269 assert_eq!(pb.len(), before);
1270 check_map(&pb);
1271 }
1272
1273 #[test]
1274 fn round465_remove_every_key_empties_the_map() {
1275 for n in [1_i64, 7, 8, 9, 100, 500] {
1276 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1277 for i in 0..n {
1278 pb.insert_mut(i, i * 3);
1279 }
1280 for i in 0..n {
1281 assert_eq!(pb.remove_mut(&i), Some(i * 3), "n={n} i={i}");
1282 assert_eq!(pb.len() as i64, n - i - 1);
1283 check_map(&pb);
1284 for j in (i + 1)..n {
1286 assert_eq!(
1287 pb.get(&j),
1288 Some(&(j * 3)),
1289 "n={n} lost {j} after removing {i}"
1290 );
1291 }
1292 }
1293 assert!(pb.is_empty());
1294 }
1295 }
1296
1297 #[test]
1298 fn round465_remove_in_reverse_order_empties_the_map() {
1299 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1302 for i in 0..300_i64 {
1303 pb.insert_mut(i, i);
1304 }
1305 for i in (0..300_i64).rev() {
1306 assert_eq!(pb.remove_mut(&i), Some(i));
1307 check_map(&pb);
1308 }
1309 assert!(pb.is_empty());
1310 }
1311
1312 #[test]
1313 fn round465_matches_btreemap_under_mixed_traffic() {
1314 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1315 let mut model: BTreeMap<i64, i64> = BTreeMap::new();
1316 let mut seed = 0x5eed_1234_u64;
1317 for step in 0..4000 {
1318 let k = (lcg(&mut seed) % 300) as i64;
1319 if lcg(&mut seed) % 3 == 0 {
1320 assert_eq!(
1321 pb.remove_mut(&k),
1322 model.remove(&k),
1323 "step {step} remove {k}"
1324 );
1325 } else {
1326 let v = (lcg(&mut seed) % 1000) as i64;
1327 assert_eq!(
1328 pb.insert_mut(k, v),
1329 model.insert(k, v),
1330 "step {step} insert {k}"
1331 );
1332 }
1333 assert_eq!(pb.len(), model.len(), "step {step}");
1334 if step % 97 == 0 {
1335 check_map(&pb);
1336 let got: Vec<(i64, i64)> = pb.iter().map(|(k, v)| (*k, *v)).collect();
1337 let want: Vec<(i64, i64)> = model.iter().map(|(k, v)| (*k, *v)).collect();
1338 assert_eq!(got, want, "step {step}");
1339 }
1340 }
1341 check_map(&pb);
1342 let got: Vec<(i64, i64)> = pb.iter().map(|(k, v)| (*k, *v)).collect();
1343 let want: Vec<(i64, i64)> = model.iter().map(|(k, v)| (*k, *v)).collect();
1344 assert_eq!(got, want);
1345 }
1346
1347 #[test]
1348 fn round465_remove_leaves_a_shared_snapshot_untouched() {
1349 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1352 for i in 0..200_i64 {
1353 pb.insert_mut(i, i * 5);
1354 }
1355 let snapshot = pb.clone();
1356 for i in 0..100_i64 {
1357 pb.remove_mut(&(i * 2));
1358 }
1359 check_map(&pb);
1360 check_map(&snapshot);
1361 assert_eq!(snapshot.len(), 200);
1362 for i in 0..200_i64 {
1363 assert_eq!(snapshot.get(&i), Some(&(i * 5)), "snapshot lost {i}");
1364 }
1365 for i in 0..100_i64 {
1366 assert_eq!(pb.get(&(i * 2)), None);
1367 assert_eq!(pb.get(&(i * 2 + 1)), Some(&(i * 10 + 5)));
1368 }
1369 }
1370
1371 #[test]
1372 fn round465_immutable_remove_does_not_touch_the_receiver() {
1373 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1374 for i in 0..60_i64 {
1375 pb.insert_mut(i, i);
1376 }
1377 let (next, prev) = pb.remove(&30);
1378 assert_eq!(prev, Some(30));
1379 assert_eq!(pb.get(&30), Some(&30), "receiver must be untouched");
1380 assert_eq!(next.get(&30), None);
1381 assert_eq!(pb.len(), 60);
1382 assert_eq!(next.len(), 59);
1383 check_map(&pb);
1384 check_map(&next);
1385 }
1386
1387 #[test]
1388 fn round465_range_and_predecessor_still_work_after_removals() {
1389 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1391 for i in 0..400_i64 {
1392 pb.insert_mut(i, i);
1393 }
1394 for i in 0..400_i64 {
1395 if i % 3 == 0 {
1396 pb.remove_mut(&i);
1397 }
1398 }
1399 check_map(&pb);
1400 let in_range: Vec<i64> = pb
1401 .range(Bound::Included(&100), Bound::Excluded(&120))
1402 .map(|(k, _)| *k)
1403 .collect();
1404 let want: Vec<i64> = (100..120).filter(|i| i % 3 != 0).collect();
1405 assert_eq!(in_range, want);
1406 assert_eq!(pb.predecessor(&100).map(|(k, _)| *k), Some(98));
1408 let rev: Vec<i64> = pb.iter_rev().map(|(k, _)| *k).take(3).collect();
1409 assert_eq!(rev, vec![398, 397, 395]);
1410 }
1411
1412 #[test]
1413 fn empty_map_is_empty() {
1414 let pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1415 assert_eq!(pb.len(), 0);
1416 assert!(pb.is_empty());
1417 assert!(pb.get(&42).is_none());
1418 }
1419
1420 #[test]
1421 fn insert_single_into_empty_works() {
1422 let (pb, prev) = PersistentBTreeMap::<i64, i64>::new().insert(1, 100);
1423 assert_eq!(prev, None);
1424 assert_eq!(pb.len(), 1);
1425 assert_eq!(pb.get(&1), Some(&100));
1426 assert_eq!(pb.get(&2), None);
1427 }
1428
1429 #[test]
1430 fn insert_replace_returns_prev_keeps_len() {
1431 let (pb, p1) = PersistentBTreeMap::<i64, i64>::new().insert(7, 10);
1432 assert_eq!(p1, None);
1433 let (pb, p2) = pb.insert(7, 99);
1434 assert_eq!(p2, Some(10));
1435 assert_eq!(pb.len(), 1);
1436 assert_eq!(pb.get(&7), Some(&99));
1437 }
1438
1439 #[test]
1440 fn insert_crosses_leaf_split_boundary() {
1441 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1443 for i in 0..20_i64 {
1444 pb = pb.insert(i, i * 7).0;
1445 }
1446 for i in 0..20_i64 {
1447 assert_eq!(pb.get(&i), Some(&(i * 7)));
1448 }
1449 assert!(pb.get(&20).is_none());
1450 assert_eq!(pb.len(), 20);
1451 }
1452
1453 #[test]
1454 fn insert_grows_through_multiple_internal_splits() {
1455 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1457 for i in 0..200_i64 {
1458 pb = pb.insert(i, i * 11).0;
1459 }
1460 for i in 0..200_i64 {
1461 assert_eq!(pb.get(&i), Some(&(i * 11)));
1462 }
1463 assert_eq!(pb.len(), 200);
1464 }
1465
1466 #[test]
1467 fn clone_then_insert_preserves_original() {
1468 let mut a: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1469 for i in 0..100_i64 {
1470 a = a.insert(i, i).0;
1471 }
1472 let b = a.clone();
1473 let (b, _) = b.insert(999, 999);
1474 assert_eq!(a.len(), 100);
1475 assert!(a.get(&999).is_none());
1476 assert_eq!(b.len(), 101);
1477 assert_eq!(b.get(&999), Some(&999));
1478 for i in 0..100_i64 {
1479 assert_eq!(a.get(&i), Some(&i), "A drift at {i}");
1480 assert_eq!(b.get(&i), Some(&i), "B drift at {i}");
1481 }
1482 }
1483
1484 #[test]
1485 fn iter_yields_sorted_order() {
1486 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1487 for &k in &[7_i64, 3, 11, 1, 9, 5, 14, 2, 8, 12, 4, 6, 10, 13] {
1489 pb = pb.insert(k, k * 2).0;
1490 }
1491 let collected: Vec<(i64, i64)> = pb.iter().map(|(k, v)| (*k, *v)).collect();
1492 let expected: Vec<(i64, i64)> = (1..=14).map(|k| (k, k * 2)).collect();
1493 assert_eq!(collected, expected);
1494 }
1495
1496 #[test]
1497 fn iter_handles_taller_tree() {
1498 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1499 for i in 0..500_i64 {
1500 pb = pb.insert(i, i).0;
1501 }
1502 let collected: Vec<i64> = pb.iter().map(|(k, _)| *k).collect();
1503 let expected: Vec<i64> = (0..500).collect();
1504 assert_eq!(collected, expected);
1505 }
1506
1507 #[test]
1508 fn range_basic_bounds() {
1509 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1510 for i in 0..100_i64 {
1511 pb = pb.insert(i, i * 10).0;
1512 }
1513 let keys = |lo: Bound<&i64>, hi: Bound<&i64>| -> Vec<i64> {
1514 pb.range(lo, hi).map(|(k, _)| *k).collect()
1515 };
1516 assert_eq!(
1517 keys(Bound::Included(&20), Bound::Included(&24)),
1518 vec![20, 21, 22, 23, 24]
1519 );
1520 assert_eq!(
1521 keys(Bound::Excluded(&20), Bound::Excluded(&24)),
1522 vec![21, 22, 23]
1523 );
1524 assert_eq!(keys(Bound::Unbounded, Bound::Excluded(&3)), vec![0, 1, 2]);
1525 assert_eq!(
1526 keys(Bound::Included(&97), Bound::Unbounded),
1527 vec![97, 98, 99]
1528 );
1529 assert!(keys(Bound::Included(&50), Bound::Included(&49)).is_empty());
1530 assert_eq!(
1532 keys(Bound::Included(&-5), Bound::Included(&2)),
1533 vec![0, 1, 2]
1534 );
1535 assert_eq!(
1536 keys(Bound::Included(&200), Bound::Unbounded),
1537 Vec::<i64>::new()
1538 );
1539 }
1540
1541 #[test]
1546 fn fuzz_range_against_btreemap() {
1547 let mut rng = Splitmix::new(0x5EED_1234_u64);
1548 const KEY_RANGE: i64 = 512;
1549 for &n_inserts in &[0usize, 5, 40, 300, 2000] {
1551 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1552 let mut oracle: BTreeMap<i64, i64> = BTreeMap::new();
1553 for _ in 0..n_inserts {
1554 let key = (rng.next() as i64).rem_euclid(KEY_RANGE);
1555 let val = rng.next() as i64;
1556 pb = pb.insert(key, val).0;
1557 oracle.insert(key, val);
1558 }
1559 for _ in 0..2000 {
1560 let a = (rng.next() as i64).rem_euclid(KEY_RANGE + 40) - 20;
1561 let b = (rng.next() as i64).rem_euclid(KEY_RANGE + 40) - 20;
1562 let (lo_raw, hi_raw) = if a <= b { (a, b) } else { (b, a) };
1563 let mk = |raw: i64, sel: u64| -> Bound<i64> {
1564 match sel % 3 {
1565 0 => Bound::Included(raw),
1566 1 => Bound::Excluded(raw),
1567 _ => Bound::Unbounded,
1568 }
1569 };
1570 let lo = mk(lo_raw, rng.next());
1571 let hi = mk(hi_raw, rng.next());
1572 if lo_raw == hi_raw
1575 && matches!(lo, Bound::Excluded(_))
1576 && matches!(hi, Bound::Excluded(_))
1577 {
1578 continue;
1579 }
1580 let lo_ref = match &lo {
1581 Bound::Included(k) => Bound::Included(k),
1582 Bound::Excluded(k) => Bound::Excluded(k),
1583 Bound::Unbounded => Bound::Unbounded,
1584 };
1585 let hi_ref = match &hi {
1586 Bound::Included(k) => Bound::Included(k),
1587 Bound::Excluded(k) => Bound::Excluded(k),
1588 Bound::Unbounded => Bound::Unbounded,
1589 };
1590 let got: Vec<(i64, i64)> =
1591 pb.range(lo_ref, hi_ref).map(|(k, v)| (*k, *v)).collect();
1592 let want: Vec<(i64, i64)> = oracle.range((lo, hi)).map(|(k, v)| (*k, *v)).collect();
1593 assert_eq!(
1594 got, want,
1595 "range drift n={n_inserts} lo={lo_raw:?} hi={hi_raw:?}"
1596 );
1597 }
1598 }
1599 }
1600
1601 #[test]
1604 fn fuzz_predecessor_against_btreemap() {
1605 let mut rng = Splitmix::new(0x9E37_79B9_7F4A_7C15_u64);
1606 const KEY_RANGE: i64 = 512;
1607 for &n_inserts in &[0usize, 5, 40, 300, 2000] {
1608 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1609 let mut oracle: BTreeMap<i64, i64> = BTreeMap::new();
1610 for _ in 0..n_inserts {
1611 let key = (rng.next() as i64).rem_euclid(KEY_RANGE);
1612 let val = rng.next() as i64;
1613 pb = pb.insert(key, val).0;
1614 oracle.insert(key, val);
1615 }
1616 for _ in 0..2000 {
1617 let probe = (rng.next() as i64).rem_euclid(KEY_RANGE + 40) - 20;
1618 let got = pb.predecessor(&probe).map(|(k, v)| (*k, *v));
1619 let want = oracle.range(..probe).next_back().map(|(k, v)| (*k, *v));
1620 assert_eq!(got, want, "predecessor drift n={n_inserts} probe={probe}");
1621 }
1622 }
1623 }
1624
1625 #[test]
1626 fn iter_rev_yields_descending() {
1627 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1628 for &k in &[7_i64, 3, 11, 1, 9, 5, 14, 2, 8, 12, 4, 6, 10, 13] {
1629 pb = pb.insert(k, k * 2).0;
1630 }
1631 let collected: Vec<(i64, i64)> = pb.iter_rev().map(|(k, v)| (*k, *v)).collect();
1632 let expected: Vec<(i64, i64)> = (1..=14).rev().map(|k| (k, k * 2)).collect();
1633 assert_eq!(collected, expected);
1634 }
1635
1636 #[test]
1637 fn iter_rev_handles_taller_tree() {
1638 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1639 for i in 0..500_i64 {
1640 pb = pb.insert(i, i).0;
1641 }
1642 let collected: Vec<i64> = pb.iter_rev().map(|(k, _)| *k).collect();
1643 let expected: Vec<i64> = (0..500).rev().collect();
1644 assert_eq!(collected, expected);
1645 }
1646
1647 #[test]
1648 fn iter_rev_empty_map_returns_nothing() {
1649 let pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1650 assert_eq!(pb.iter_rev().count(), 0);
1651 }
1652
1653 #[test]
1654 fn iter_rev_lazy_stops_at_take() {
1655 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1658 for i in 0..10000_i64 {
1659 pb = pb.insert(i, i).0;
1660 }
1661 let top5: Vec<i64> = pb.iter_rev().take(5).map(|(k, _)| *k).collect();
1662 assert_eq!(top5, vec![9999, 9998, 9997, 9996, 9995]);
1663 }
1664
1665 struct Splitmix(u64);
1667 impl Splitmix {
1668 fn new(seed: u64) -> Self {
1669 Self(seed)
1670 }
1671 fn next(&mut self) -> u64 {
1672 self.0 = self.0.wrapping_add(0x9E37_79B9_7F4A_7C15);
1673 let mut x = self.0;
1674 x = (x ^ (x >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
1675 x = (x ^ (x >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
1676 x ^ (x >> 31)
1677 }
1678 }
1679
1680 #[test]
1683 fn fuzz_oracle_against_std_btreemap() {
1684 let mut pb: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1685 let mut oracle: BTreeMap<i64, i64> = BTreeMap::new();
1686 let mut rng = Splitmix::new(0xC0FFEE_u64);
1687 const STEPS: usize = 100_000;
1688 const KEY_RANGE: i64 = 4096;
1690 for step in 0..STEPS {
1691 let op = rng.next() % 3; let key = (rng.next() as i64) % KEY_RANGE;
1693 match op {
1694 0 | 1 => {
1695 let val = rng.next() as i64;
1696 let (new_pb, prev_pb) = pb.insert(key, val);
1697 let prev_oracle = oracle.insert(key, val);
1698 assert_eq!(prev_pb, prev_oracle, "prev drift @ step {step}, key {key}");
1699 pb = new_pb;
1700 assert_eq!(pb.len(), oracle.len(), "len drift @ step {step}");
1701 }
1702 2 => {
1703 let pb_v = pb.get(&key).copied();
1704 let oracle_v = oracle.get(&key).copied();
1705 assert_eq!(pb_v, oracle_v, "get drift @ step {step}, key {key}");
1706 }
1707 _ => unreachable!(),
1708 }
1709 }
1710 for (k, v) in &oracle {
1712 assert_eq!(pb.get(k), Some(v), "final drift at key {k}");
1713 }
1714 let pb_collected: Vec<(i64, i64)> = pb.iter().map(|(k, v)| (*k, *v)).collect();
1716 let oracle_collected: Vec<(i64, i64)> = oracle.iter().map(|(k, v)| (*k, *v)).collect();
1717 assert_eq!(pb_collected, oracle_collected);
1718 }
1719
1720 #[test]
1723 fn fuzz_oracle_clone_isolation() {
1724 let mut a: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1725 let mut oracle_a: BTreeMap<i64, i64> = BTreeMap::new();
1726 let mut rng = Splitmix::new(0xDECAFBAD_u64);
1727 for _ in 0..1_000 {
1728 let k = (rng.next() as i64) % 1000;
1729 let v = rng.next() as i64;
1730 a = a.insert(k, v).0;
1731 oracle_a.insert(k, v);
1732 }
1733 let mut b = a.clone();
1735 let mut oracle_b = oracle_a.clone();
1736 let mut c = a.clone();
1737 let mut oracle_c = oracle_a.clone();
1738 for _ in 0..500 {
1739 let k = (rng.next() as i64) % 2000;
1740 let v = rng.next() as i64;
1741 b = b.insert(k, v).0;
1742 oracle_b.insert(k, v);
1743 }
1744 for _ in 0..300 {
1745 let k = (rng.next() as i64) % 500;
1746 let v = rng.next() as i64;
1747 c = c.insert(k, v).0;
1748 oracle_c.insert(k, v);
1749 }
1750 for (k, v) in &oracle_a {
1751 assert_eq!(a.get(k), Some(v), "A drift at {k}");
1752 }
1753 for (k, v) in &oracle_b {
1754 assert_eq!(b.get(k), Some(v), "B drift at {k}");
1755 }
1756 for (k, v) in &oracle_c {
1757 assert_eq!(c.get(k), Some(v), "C drift at {k}");
1758 }
1759 }
1760
1761 #[test]
1762 fn partial_eq_compares_by_elements() {
1763 let mut a: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1764 let mut b: PersistentBTreeMap<i64, i64> = PersistentBTreeMap::new();
1765 for &k in &[5_i64, 2, 8, 1, 7, 3, 6, 4] {
1768 a = a.insert(k, k * 10).0;
1769 }
1770 for &k in &[1_i64, 2, 3, 4, 5, 6, 7, 8] {
1771 b = b.insert(k, k * 10).0;
1772 }
1773 assert_eq!(a, b);
1774 let (a, _) = a.insert(9, 90);
1775 assert_ne!(a, b);
1776 }
1777}