1use ::core::borrow::Borrow;
2use ::core::fmt::Debug;
3use ::core::iter::FusedIterator;
4use ::core::marker::PhantomData;
5use ::core::ops::{Bound, RangeBounds};
6use alloc::vec::Vec;
7
8use crate::core::node::NodeLike;
9use crate::{
10 cdc::change::ChangeEvent,
11 core::multipair::{MultiPair, MultiPairInsertHelper, MultiPairLike, MultiPairRemoveHelper, OrdMultiPair},
12};
13
14use super::set::BTreeSet;
15
16#[derive(Debug)]
17pub struct BTreeMultiMap<K, V, Node = Vec<MultiPair<K, V>>, M = MultiPair<K, V>>
18where
19 K: Debug + Send + Ord + Clone + 'static,
20 V: Debug + Send + Clone + 'static,
21 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
22 Node: NodeLike<M> + Send + 'static,
23{
24 pub(crate) set: BTreeSet<M, Node>,
25 marker: PhantomData<(K, V)>,
26}
27
28pub type OrderedBTreeMultiMap<K, V> = BTreeMultiMap<K, V, Vec<OrdMultiPair<K, V>>, OrdMultiPair<K, V>>;
45
46impl<K, V, Node, M> Default for BTreeMultiMap<K, V, Node, M>
47where
48 K: Debug + Send + Ord + Clone + 'static,
49 V: Debug + Send + Clone + 'static,
50 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
51 Node: NodeLike<M> + Send + 'static,
52{
53 fn default() -> Self {
54 Self {
55 set: BTreeSet::default().with_grouped_borrow_routing(),
56 marker: PhantomData,
57 }
58 }
59}
60
61pub struct Iter<'a, K, V, Node, M>
62where
63 K: Debug + Send + Ord + Clone + 'static,
64 V: Debug + Send + Clone + 'static,
65 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
66 Node: NodeLike<M> + Send + 'static,
67{
68 inner: super::set::Iter<'a, M, Node>,
69 marker: PhantomData<(K, V)>,
70}
71
72impl<'a, K, V, Node, M> Iterator for Iter<'a, K, V, Node, M>
73where
74 K: Debug + Send + Ord + Clone + 'static,
75 V: Debug + Send + Clone + 'static,
76 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
77 Node: NodeLike<M> + Send + 'static,
78{
79 type Item = (K, V);
80
81 fn next(&mut self) -> Option<Self::Item> {
82 if let Some(entry) = self.inner.next() {
83 return Some(entry.into());
84 }
85
86 None
87 }
88}
89
90impl<'a, K, V, Node, M> DoubleEndedIterator for Iter<'a, K, V, Node, M>
91where
92 K: Debug + Send + Ord + Clone + 'static,
93 V: Debug + Send + Clone + 'static,
94 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
95 Node: NodeLike<M> + Send + 'static,
96{
97 fn next_back(&mut self) -> Option<Self::Item> {
98 if let Some(entry) = self.inner.next_back() {
99 return Some(entry.into());
100 }
101
102 None
103 }
104}
105
106impl<'a, K, V, Node, M> FusedIterator for Iter<'a, K, V, Node, M>
107where
108 K: Debug + Send + Ord + Clone + 'static,
109 V: Debug + Send + Clone + 'static,
110 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
111 Node: NodeLike<M> + Send + 'static,
112{
113}
114
115pub struct Range<'a, K, V, Node, M>
116where
117 K: Debug + Send + Ord + Clone + 'static,
118 V: Debug + Send + Clone + 'static,
119 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
120 Node: NodeLike<M> + Send + 'static,
121{
122 inner: super::set::Range<'a, M, Node>,
123 marker: PhantomData<(K, V)>,
124}
125
126impl<'a, K, V, Node, M> Iterator for Range<'a, K, V, Node, M>
127where
128 K: Debug + Send + Ord + Clone + 'static,
129 V: Debug + Send + Clone + 'static,
130 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
131 Node: NodeLike<M> + Send + 'static,
132{
133 type Item = (K, V);
134
135 fn next(&mut self) -> Option<Self::Item> {
136 self.inner.next().map(Into::into)
137 }
138}
139
140impl<'a, K, V, Node, M> DoubleEndedIterator for Range<'a, K, V, Node, M>
141where
142 K: Debug + Send + Ord + Clone + 'static,
143 V: Debug + Send + Clone + 'static,
144 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
145 Node: NodeLike<M> + Send + 'static,
146{
147 fn next_back(&mut self) -> Option<Self::Item> {
148 self.inner.next_back().map(Into::into)
149 }
150}
151
152impl<'a, K, V, Node, M> FusedIterator for Range<'a, K, V, Node, M>
153where
154 K: Debug + Send + Ord + Clone + 'static,
155 V: Debug + Send + Clone + 'static,
156 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
157 Node: NodeLike<M> + Send + 'static,
158{
159}
160
161impl<K, V, Node, M> BTreeMultiMap<K, V, Node, M>
162where
163 K: Debug + Send + Ord + Clone + 'static,
164 V: Debug + Send + Clone + 'static,
165 M: MultiPairLike<K, V> + Debug + Clone + Send + 'static,
166 Node: NodeLike<M> + Send + 'static,
167{
168 pub fn new() -> Self {
183 Self {
184 set: BTreeSet::default().with_grouped_borrow_routing(),
185 marker: PhantomData,
186 }
187 }
188 pub fn with_maximum_node_size(node_capacity: usize) -> Self {
198 Self {
199 set: BTreeSet::with_maximum_node_size(node_capacity).with_grouped_borrow_routing(),
200 marker: PhantomData,
201 }
202 }
203 #[cfg(feature = "cdc")]
206 pub fn attach_multi_node(&self, node: Node) {
207 self.set.attach_node(node)
208 }
209 #[cfg(feature = "cdc")]
211 pub fn attach_multi_nodes(&self, nodes: impl IntoIterator<Item = Node>) {
212 self.set.attach_nodes(nodes)
213 }
214
215 #[cfg(feature = "cdc")]
220 pub fn snapshot_nodes(&self) -> Vec<Node>
221 where
222 Node: Clone,
223 {
224 self.set
225 .index
226 .read()
227 .values()
228 .map(|node| (*node.read()).clone())
229 .collect()
230 }
231 pub fn contains_key<Q>(&self, key: &Q) -> bool
250 where
251 M: Borrow<Q>,
252 Q: Ord + ?Sized,
253 {
254 self.set.contains(key)
255 }
256 fn _range<Q, R>(&self, range: R) -> Range<'_, K, V, Node, M>
257 where
258 M: Borrow<Q>,
259 Q: Ord + ?Sized,
260 R: RangeBounds<Q>,
261 {
262 Range {
263 inner: super::set::BTreeSet::range(&self.set, range),
264 marker: PhantomData,
265 }
266 }
267 pub fn get(&self, key: &K) -> Range<'_, K, V, Node, M>
284 where
285 M: Borrow<K>,
286 {
287 self._range((Bound::Included(key), Bound::Included(key)))
288 }
289 pub fn remove_some<Q>(&self, key: &Q) -> Option<(K, V)>
314 where
315 M: Borrow<Q>,
316 Q: Ord + ?Sized,
317 {
318 self.set.remove(key).map(Into::into)
319 }
320 #[cfg(feature = "cdc")]
324 pub fn remove_some_cdc<Q>(&self, key: &Q) -> (Option<(K, V)>, Vec<ChangeEvent<M>>)
325 where
326 M: Borrow<Q>,
327 Q: Ord + ?Sized,
328 {
329 let (old_value, cdc) = self.set.remove_cdc(key);
330
331 (old_value.map(Into::into), cdc)
332 }
333 pub fn len(&self) -> usize {
348 self.set.len()
349 }
350 pub fn is_empty(&self) -> bool {
365 self.set.is_empty()
366 }
367 pub fn capacity(&self) -> usize {
388 self.set.capacity()
389 }
390 pub fn node_count(&self) -> usize {
408 self.set.node_count()
409 }
410 pub fn iter(&self) -> Iter<'_, K, V, Node, M> {
432 Iter {
433 inner: self.set.iter(),
434 marker: PhantomData,
435 }
436 }
437 pub fn range<R>(&self, range: R) -> Range<'_, K, V, Node, M>
467 where
468 M: Borrow<K>,
469 R: RangeBounds<K>,
470 {
471 self._range(range)
472 }
473}
474
475impl<K, V, Node, M> BTreeMultiMap<K, V, Node, M>
476where
477 K: Debug + Send + Ord + Clone + 'static,
478 V: Debug + Send + Clone + 'static,
479 M: MultiPairLike<K, V> + MultiPairInsertHelper<K, V> + Debug + Clone + Send + 'static,
480 Node: NodeLike<M> + Send + 'static,
481{
482 pub fn insert(&self, key: K, value: V) -> Option<V> {
506 M::insert_into(&self.set, key, value).map(|(_, value)| value)
507 }
508
509 #[cfg(feature = "cdc")]
513 pub fn insert_cdc(&self, key: K, value: V) -> (Option<V>, Vec<ChangeEvent<M>>) {
514 let (old_value, cdc) = M::insert_cdc_into(&self.set, key, value);
515
516 (old_value.map(|(_, value)| value), cdc)
517 }
518}
519
520impl<K, V, Node, M> BTreeMultiMap<K, V, Node, M>
521where
522 K: Debug + Send + Ord + Clone + 'static,
523 V: Debug + Send + Clone + 'static,
524 M: MultiPairLike<K, V> + MultiPairRemoveHelper<K, V> + Debug + Clone + Send + 'static,
525 Node: NodeLike<M> + Send + 'static,
526{
527 pub fn remove(&self, key: &K, value: &V) -> Option<(K, V)> {
545 M::remove_from(&self.set, key, value)
546 }
547
548 #[cfg(feature = "cdc")]
552 pub fn remove_cdc(&self, key: &K, value: &V) -> (Option<(K, V)>, Vec<ChangeEvent<M>>) {
553 M::remove_cdc_from(&self.set, key, value)
554 }
555}
556
557#[cfg(test)]
558mod tests {
559 use super::BTreeMultiMap;
560 use crate::core::multipair::{MultiPairLike, OrdMultiPair};
561 use crate::BTreeSet;
562 use std::borrow::Borrow;
563 use std::fmt::Debug;
564 use std::ops::Bound::{Excluded, Unbounded};
565 use std::sync::atomic::{AtomicUsize, Ordering};
566 use std::sync::{Arc, Barrier};
567 use std::thread;
568
569 #[test]
570 fn test_insert_works_as_expected() {
571 let maximum_node_size = 3;
572 let multi_map = BTreeMultiMap::<usize, &str>::with_maximum_node_size(maximum_node_size);
573
574 multi_map.insert(1usize, "a");
575 multi_map.insert(1usize, "b");
576 multi_map.insert(2usize, "c");
577 multi_map.insert(2usize, "d");
578 multi_map.insert(3usize, "e");
579 multi_map.insert(4usize, "f");
580 multi_map.insert(4usize, "g");
581
582 let expected_pairs = vec![(1, "b"), (1, "a"), (2, "d"), (2, "c"), (3, "e"), (4, "f"), (4, "g")]
583 .into_iter()
584 .collect::<BTreeSet<_>>();
585
586 let all_pairs = multi_map.iter().collect::<BTreeSet<_>>();
587 assert_eq!(all_pairs, expected_pairs);
588 }
589
590 #[test]
591 fn test_insert_all_same_key_works_as_expected() {
592 let maximum_node_size = 3;
593 let map = BTreeMultiMap::<usize, &str>::with_maximum_node_size(maximum_node_size);
594
595 map.insert(1usize, "a");
596 map.insert(1usize, "b");
597 map.insert(1usize, "c");
598 map.insert(1usize, "d");
599 map.insert(1usize, "e");
600 map.insert(1usize, "f");
601
602 let all_actual_pairs = map.iter().collect::<BTreeSet<_>>();
603 let all_expected_pairs = vec![(1, "f"), (1, "e"), (1, "d"), (1, "c"), (1, "b"), (1, "a")]
604 .into_iter()
605 .collect::<BTreeSet<_>>();
606 assert_eq!(all_actual_pairs, all_expected_pairs);
607
608 let all_ranged_pairs = map.range(1..2).collect::<BTreeSet<_>>();
609 assert_eq!(all_ranged_pairs, all_expected_pairs);
610 assert!(map.range(1..1).next().is_none());
611 }
612
613 fn assert_concurrent_remove_reinsert_preserves_exact_pairs(
614 records: usize,
615 buckets: usize,
616 threads: usize,
617 operations: usize,
618 ) {
619 let map = Arc::new(BTreeMultiMap::<usize, usize>::new());
620 let expected = Arc::new(
621 (0..records)
622 .map(|id| AtomicUsize::new(id % buckets))
623 .collect::<Vec<_>>(),
624 );
625 let start = Arc::new(Barrier::new(threads));
626 let mut handles = Vec::with_capacity(threads);
627
628 for id in 0..records {
629 map.insert(id % buckets, id);
630 }
631
632 for worker in 0..threads {
633 let map = Arc::clone(&map);
634 let expected = Arc::clone(&expected);
635 let start = Arc::clone(&start);
636 handles.push(thread::spawn(move || {
637 let owned = (worker..records).step_by(threads).collect::<Vec<_>>();
638 let worker_operations = operations / threads + usize::from(worker < operations % threads);
639 start.wait();
640
641 for sequence in 0..worker_operations {
642 let id = owned[sequence % owned.len()];
643 let old_bucket = expected[id].load(Ordering::Relaxed);
644 let new_bucket = (old_bucket + 1) % buckets;
645
646 assert_eq!(map.remove(&old_bucket, &id), Some((old_bucket, id)));
647 assert_eq!(map.insert(new_bucket, id), None);
648 expected[id].store(new_bucket, Ordering::Relaxed);
649 }
650 }));
651 }
652
653 for handle in handles {
654 handle.join().unwrap();
655 }
656
657 let mut occurrences = vec![0usize; records];
658 for (bucket, id) in map.iter() {
659 assert_eq!(bucket, expected[id].load(Ordering::Relaxed));
660 occurrences[id] += 1;
661 }
662
663 assert_eq!(map.len(), records);
664 assert!(occurrences.into_iter().all(|count| count == 1));
665 }
666
667 #[test]
668 fn test_concurrent_remove_reinsert_preserves_exact_pairs() {
669 assert_concurrent_remove_reinsert_preserves_exact_pairs(1_000, 16, 16, 10_000);
670 }
671
672 #[test]
673 fn test_concurrent_multimap_remove_reinsert_stress() {
674 assert_concurrent_remove_reinsert_preserves_exact_pairs(1_000, 16, 32, 100_000);
675 }
676
677 #[test]
681 fn same_key_churn_keeps_logical_pair_count_exact() {
682 let map = BTreeMultiMap::<usize, usize>::with_maximum_node_size(4);
683
684 for i in 0..250 {
685 let replaced = map.insert(1, i % 5);
686 if i < 5 {
687 assert_eq!(replaced, None, "first insert of value {} must be fresh", i % 5);
688 } else {
689 assert_eq!(replaced, Some(i % 5), "repeat insert of value {} must replace", i % 5);
690 }
691 }
692
693 assert_eq!(map.len(), 5, "same-key churn must not accumulate duplicates");
694 let mut values = map.get(&1).map(|(_, value)| value).collect::<Vec<_>>();
695 values.sort();
696 assert_eq!(values, vec![0, 1, 2, 3, 4]);
697
698 for value in 0..5 {
699 assert_eq!(map.remove(&1, &value), Some((1, value)));
700 }
701 assert!(map.is_empty());
702 }
703
704 #[test]
711 fn same_key_node_splits_keep_routing_lawful() {
712 let map = BTreeMultiMap::<usize, usize>::with_maximum_node_size(4);
713
714 for value in 0..200 {
715 assert_eq!(map.insert(7, value), None);
716 }
717
718 assert_eq!(map.len(), 200);
719 assert!(map.node_count() > 1, "fixture must actually split");
720
721 let mut values = map.get(&7).map(|(_, value)| value).collect::<Vec<_>>();
722 values.sort();
723 assert_eq!(values, (0..200).collect::<Vec<_>>());
724
725 for value in 0..200 {
726 assert_eq!(map.remove(&7, &value), Some((7, value)));
727 }
728 assert!(map.is_empty());
729 }
730
731 #[test]
732 fn test_range_edge_cast() {
733 let maximum_node_size = 3;
734 let map = BTreeMultiMap::<usize, &str>::with_maximum_node_size(maximum_node_size);
735
736 map.insert(1usize, "a");
737 map.insert(1usize, "b");
738 map.insert(2usize, "c");
739 map.insert(2usize, "d");
740 map.insert(3usize, "e");
741 map.insert(4usize, "f");
742 map.insert(4usize, "g");
743
744 let mid_range = map.range(2..3).collect::<BTreeSet<_>>();
745 assert_eq!(
746 mid_range,
747 vec![(2, "c"), (2, "d"),].into_iter().collect::<BTreeSet<_>>()
748 );
749 }
750
751 fn assert_range_works_as_expected<M>()
752 where
753 M: MultiPairLike<usize, &'static str>
754 + crate::core::multipair::MultiPairInsertHelper<usize, &'static str>
755 + Borrow<usize>
756 + Debug
757 + Clone
758 + Send
759 + 'static,
760 {
761 let maximum_node_size = 3;
762 let map = BTreeMultiMap::<usize, &'static str, Vec<M>, M>::with_maximum_node_size(maximum_node_size);
763
764 map.insert(1usize, "a");
765 map.insert(1usize, "b");
766 map.insert(2usize, "c");
767 map.insert(2usize, "d");
768 map.insert(3usize, "e");
769 map.insert(4usize, "f");
770 map.insert(4usize, "g");
771
772 let truly_all_pairs = map.iter().collect::<BTreeSet<_>>();
773 let all_pairs = map.range(..).collect::<BTreeSet<_>>();
774 assert_eq!(all_pairs, truly_all_pairs);
775
776 let mid_range = map.range(2..3).collect::<BTreeSet<_>>();
777 assert_eq!(
778 mid_range,
779 vec![(2, "c"), (2, "d"),].into_iter().collect::<BTreeSet<_>>()
780 );
781
782 let reverse_range = map.range(1..4).rev().collect::<BTreeSet<_>>();
783 assert_eq!(
784 reverse_range,
785 vec![(3, "e"), (2, "d"), (2, "c"), (1, "b"), (1, "a"),]
786 .into_iter()
787 .collect::<BTreeSet<_>>()
788 );
789
790 let empty_range = map.range(5..).collect::<BTreeSet<_>>();
791 assert_eq!(empty_range, vec![].into_iter().collect::<BTreeSet<_>>());
792 }
793
794 #[test]
795 fn test_range_works_as_expected() {
796 assert_range_works_as_expected::<OrdMultiPair<usize, &'static str>>();
797 }
798
799 fn assert_range_excludes_values_at_bounds<M>()
800 where
801 M: MultiPairLike<usize, &'static str>
802 + crate::core::multipair::MultiPairInsertHelper<usize, &'static str>
803 + Borrow<usize>
804 + Debug
805 + Clone
806 + Send
807 + 'static,
808 {
809 let map = BTreeMultiMap::<usize, &'static str, Vec<M>, M>::with_maximum_node_size(10);
810
811 map.insert(1usize, "a");
812 map.insert(1usize, "b");
813 map.insert(2usize, "c");
814 map.insert(2usize, "d");
815 map.insert(3usize, "e");
816 map.insert(3usize, "f");
817
818 assert_eq!(
819 map.range((Excluded(&1), Unbounded)).collect::<BTreeSet<_>>(),
820 vec![(2, "c"), (2, "d"), (3, "e"), (3, "f")]
821 .into_iter()
822 .collect::<BTreeSet<_>>(),
823 );
824 assert_eq!(
825 map.range((Unbounded, Excluded(&3))).collect::<BTreeSet<_>>(),
826 vec![(1, "a"), (1, "b"), (2, "c"), (2, "d")]
827 .into_iter()
828 .collect::<BTreeSet<_>>(),
829 );
830 }
831
832 #[test]
833 fn test_range_excludes_all_values_at_bounds() {
834 assert_range_excludes_values_at_bounds::<OrdMultiPair<usize, &'static str>>();
835 }
836
837 fn assert_get_works_as_expected<M>()
838 where
839 M: MultiPairLike<usize, &'static str>
840 + crate::core::multipair::MultiPairInsertHelper<usize, &'static str>
841 + Borrow<usize>
842 + Debug
843 + Clone
844 + Send
845 + 'static,
846 {
847 let maximum_node_size = 10;
848 let map = BTreeMultiMap::<usize, &'static str, Vec<M>, M>::with_maximum_node_size(maximum_node_size);
849
850 map.insert(1usize, "a");
851 map.insert(1usize, "b");
852 map.insert(2usize, "c");
853 map.insert(2usize, "d");
854 map.insert(3usize, "e");
855 map.insert(4usize, "f");
856 map.insert(4usize, "g");
857
858 let range = map.get(&1).collect::<BTreeSet<_>>();
859
860 assert_eq!(range, vec![(1, "b"), (1, "a"),].into_iter().collect::<BTreeSet<_>>());
861
862 let range = map.get(&2).collect::<BTreeSet<_>>();
863 assert_eq!(range, vec![(2, "d"), (2, "c"),].into_iter().collect::<BTreeSet<_>>());
864
865 let range = map.get(&3).collect::<BTreeSet<_>>();
866 assert_eq!(range, vec![(3, "e"),].into_iter().collect::<BTreeSet<_>>());
867
868 let range = map.get(&4).collect::<BTreeSet<_>>();
869 assert_eq!(range, vec![(4, "g"), (4, "f"),].into_iter().collect::<BTreeSet<_>>());
870 }
871
872 #[test]
873 fn test_get_works_as_expected() {
874 assert_get_works_as_expected::<OrdMultiPair<usize, &'static str>>();
875 }
876
877 #[test]
878 fn test_get_works_as_expected_at_big_amounts() {
879 let maximum_node_size = 100;
880 let map = BTreeMultiMap::<String, usize>::with_maximum_node_size(maximum_node_size);
881
882 for i in 1..2000 {
883 map.insert(format!("ValueNum{}", i), i);
884 }
885
886 for i in 1..2000 {
887 let range = map.get(&format!("ValueNum{}", i)).collect::<BTreeSet<_>>();
888 assert_eq!(
889 range,
890 vec![(format!("ValueNum{}", i), i),]
891 .into_iter()
892 .collect::<BTreeSet<_>>()
893 );
894 }
895 }
896}