1use alloc::vec::Vec;
2use core::cmp::Ordering;
3use itertools::Itertools;
4
5pub(crate) fn kway_merge_sorted<'a, K, V>(
10 slices: impl IntoIterator<Item = &'a [(K, V)]>,
11) -> Vec<(K, V)>
12where
13 K: Ord + Clone + 'a,
14 V: Clone + 'a,
15{
16 slices
17 .into_iter()
18 .filter(|s| !s.is_empty())
19 .enumerate()
20 .map(|(i, s)| s.iter().map(move |(k, v)| (i, k, v)))
22 .kmerge_by(|(i1, k1, _), (i2, k2, _)| (k1, i1) < (k2, i2))
23 .dedup_by(|(_, k1, _), (_, k2, _)| *k1 == *k2)
24 .map(|(_, k, v)| (k.clone(), v.clone()))
26 .collect()
27}
28
29pub(crate) fn kway_merge_disjoint_sorted<'a, K, V>(
36 left_slices: impl IntoIterator<Item = &'a [(K, V)]>,
37 right_slices: impl IntoIterator<Item = &'a [(K, V)]>,
38) -> impl Iterator<Item = (K, V)>
39where
40 K: Ord + Clone + 'a,
41 V: Clone + PartialEq + 'a,
42{
43 let mut right_entries = right_slices
44 .into_iter()
45 .filter(|s| !s.is_empty())
46 .map(|s| s.iter())
47 .kmerge_by(|(left_key, _), (right_key, _)| left_key < right_key)
48 .peekable();
49
50 left_slices
51 .into_iter()
52 .filter(|s| !s.is_empty())
53 .enumerate()
54 .map(|(i, s)| s.iter().map(move |(k, v)| (i, k, v)))
55 .kmerge_by(|(i1, k1, _), (i2, k2, _)| (k1, i1) < (k2, i2))
56 .dedup_by(|(_, k1, _), (_, k2, _)| *k1 == *k2)
57 .filter_map(move |(_, key, value)| {
58 while let Some((right_key, _)) = right_entries.peek().copied() {
59 if right_key >= key {
60 break
61 }
62 right_entries.next();
63 }
64
65 let mut has_mask = false;
66 let mut has_equal_mask = false;
67 while let Some((right_key, right_value)) = right_entries.peek().copied() {
68 if right_key != key {
69 break
70 }
71
72 has_mask = true;
73 if !has_equal_mask {
74 has_equal_mask = right_value == value;
75 }
76 right_entries.next();
77 }
78
79 if has_mask && !has_equal_mask {
80 return None
81 }
82
83 Some((key.clone(), value.clone()))
84 })
85}
86
87pub(crate) fn extend_sorted_vec<K, V>(target: &mut Vec<(K, V)>, other: &[(K, V)])
90where
91 K: Clone + Ord,
92 V: Clone,
93{
94 if other.is_empty() {
95 return;
96 }
97
98 if target.is_empty() {
99 target.extend_from_slice(other);
100 return;
101 }
102
103 if target.last().map(|(k, _)| k) < other.first().map(|(k, _)| k) {
105 target.extend_from_slice(other);
106 return;
107 }
108
109 let left = core::mem::take(target);
111 let mut out = Vec::with_capacity(left.len() + other.len());
112
113 let mut a = left.into_iter().peekable();
114 let mut b = other.iter().peekable();
115
116 while let (Some(aa), Some(bb)) = (a.peek(), b.peek()) {
117 match aa.0.cmp(&bb.0) {
118 Ordering::Less => {
119 out.push(a.next().unwrap());
120 }
121 Ordering::Greater => {
122 out.push(b.next().unwrap().clone());
123 }
124 Ordering::Equal => {
125 let (k, _) = a.next().unwrap();
127 out.push((k, b.next().unwrap().1.clone()));
128 }
129 }
130 }
131
132 out.extend(a);
134 out.extend(b.cloned());
135
136 *target = out;
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142 use alloc::rc::Rc;
143 use core::cell::Cell;
144
145 #[derive(Debug)]
146 struct CloneCounter {
147 value: u8,
148 count: Rc<Cell<usize>>,
149 }
150
151 impl Clone for CloneCounter {
152 fn clone(&self) -> Self {
153 self.count.set(self.count.get() + 1);
154 Self { value: self.value, count: Rc::clone(&self.count) }
155 }
156 }
157
158 impl PartialEq for CloneCounter {
159 fn eq(&self, other: &Self) -> bool {
160 self.value == other.value
161 }
162 }
163
164 #[test]
165 fn test_extend_sorted_vec() {
166 let mut target = vec![(1, "a"), (3, "c")];
167 let other = vec![(2, "b"), (3, "c_new")];
168 extend_sorted_vec(&mut target, &other);
169 assert_eq!(target, vec![(1, "a"), (2, "b"), (3, "c_new")]);
170 }
171
172 #[test]
173 fn test_extend_sorted_vec_empty_target() {
174 let mut target: Vec<(i32, &str)> = vec![];
175 let other = vec![(1, "a"), (2, "b")];
176 extend_sorted_vec(&mut target, &other);
177 assert_eq!(target, vec![(1, "a"), (2, "b")]);
178 }
179
180 #[test]
181 fn test_extend_sorted_vec_empty_other() {
182 let mut target = vec![(1, "a"), (2, "b")];
183 let other: Vec<(i32, &str)> = vec![];
184 extend_sorted_vec(&mut target, &other);
185 assert_eq!(target, vec![(1, "a"), (2, "b")]);
186 }
187
188 #[test]
189 fn test_extend_sorted_vec_all_duplicates() {
190 let mut target = vec![(1, "old1"), (2, "old2"), (3, "old3")];
191 let other = vec![(1, "new1"), (2, "new2"), (3, "new3")];
192 extend_sorted_vec(&mut target, &other);
193 assert_eq!(target, vec![(1, "new1"), (2, "new2"), (3, "new3")]);
195 }
196
197 #[test]
198 fn test_extend_sorted_vec_interleaved() {
199 let mut target = vec![(1, "a"), (3, "c"), (5, "e")];
200 let other = vec![(2, "b"), (4, "d"), (6, "f")];
201 extend_sorted_vec(&mut target, &other);
202 assert_eq!(target, vec![(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e"), (6, "f")]);
203 }
204
205 #[test]
206 fn test_extend_sorted_vec_other_all_smaller() {
207 let mut target = vec![(5, "e"), (6, "f")];
208 let other = vec![(1, "a"), (2, "b")];
209 extend_sorted_vec(&mut target, &other);
210 assert_eq!(target, vec![(1, "a"), (2, "b"), (5, "e"), (6, "f")]);
211 }
212
213 #[test]
214 fn test_extend_sorted_vec_other_all_larger() {
215 let mut target = vec![(1, "a"), (2, "b")];
216 let other = vec![(5, "e"), (6, "f")];
217 extend_sorted_vec(&mut target, &other);
218 assert_eq!(target, vec![(1, "a"), (2, "b"), (5, "e"), (6, "f")]);
219 }
220
221 #[test]
222 fn test_kway_merge_sorted_basic() {
223 let slice1 = vec![(1, "a1"), (3, "c1")];
224 let slice2 = vec![(2, "b2"), (3, "c2")];
225 let slice3 = vec![(1, "a3"), (4, "d3")];
226
227 let result = kway_merge_sorted([slice1.as_slice(), slice2.as_slice(), slice3.as_slice()]);
228 assert_eq!(result, vec![(1, "a1"), (2, "b2"), (3, "c1"), (4, "d3")]);
230 }
231
232 #[test]
233 fn test_kway_merge_sorted_empty_slices() {
234 let slice1: Vec<(i32, &str)> = vec![];
235 let slice2 = vec![(1, "a")];
236 let slice3: Vec<(i32, &str)> = vec![];
237
238 let result = kway_merge_sorted([slice1.as_slice(), slice2.as_slice(), slice3.as_slice()]);
239 assert_eq!(result, vec![(1, "a")]);
240 }
241
242 #[test]
243 fn test_kway_merge_sorted_all_same_key() {
244 let slice1 = vec![(5, "first")];
245 let slice2 = vec![(5, "middle")];
246 let slice3 = vec![(5, "last")];
247
248 let result = kway_merge_sorted([slice1.as_slice(), slice2.as_slice(), slice3.as_slice()]);
249 assert_eq!(result, vec![(5, "first")]);
251 }
252
253 #[test]
254 fn test_kway_merge_sorted_single_slice() {
255 let slice = vec![(1, "a"), (2, "b"), (3, "c")];
256 let result = kway_merge_sorted([slice.as_slice()]);
257 assert_eq!(result, vec![(1, "a"), (2, "b"), (3, "c")]);
258 }
259
260 #[test]
261 fn test_kway_merge_sorted_no_slices() {
262 let result: Vec<(i32, &str)> = kway_merge_sorted(Vec::<&[(i32, &str)]>::new());
263 assert!(result.is_empty());
264 }
265
266 #[test]
267 fn test_kway_merge_disjoint_sorted() {
268 let left_old = vec![(1, "old"), (2, "drop"), (4, "keep")];
269 let left_new = vec![(1, "new"), (3, "new_only")];
270 let right_a = vec![(2, "ignored"), (5, "ignored")];
271 let right_b = vec![(3, "ignored")];
272
273 let result = kway_merge_disjoint_sorted(
274 [left_new.as_slice(), left_old.as_slice()],
275 [right_a.as_slice(), right_b.as_slice()],
276 )
277 .collect::<Vec<_>>();
278
279 assert_eq!(result, vec![(1, "new"), (4, "keep")]);
280 }
281
282 #[test]
283 fn test_kway_merge_disjoint_sorted_keeps_equal_overlaps() {
284 let left = vec![(1, "equal"), (2, "equal"), (3, "drop")];
285 let right_a = vec![(1, "different"), (2, "equal"), (3, "different")];
286 let right_b = vec![(1, "equal"), (2, "different")];
287
288 let result =
289 kway_merge_disjoint_sorted([left.as_slice()], [right_a.as_slice(), right_b.as_slice()])
290 .collect::<Vec<_>>();
291 let reversed =
292 kway_merge_disjoint_sorted([left.as_slice()], [right_b.as_slice(), right_a.as_slice()])
293 .collect::<Vec<_>>();
294
295 assert_eq!(result, vec![(1, "equal"), (2, "equal")]);
296 assert_eq!(reversed, result);
297 }
298
299 #[test]
300 fn test_kway_merge_disjoint_sorted_clones_lazily() {
301 let clone_count = Rc::new(Cell::new(0));
302 let left = vec![
303 (1, CloneCounter { value: 1, count: Rc::clone(&clone_count) }),
304 (2, CloneCounter { value: 2, count: Rc::clone(&clone_count) }),
305 (3, CloneCounter { value: 3, count: Rc::clone(&clone_count) }),
306 ];
307 let mut result = kway_merge_disjoint_sorted(
308 [left.as_slice()],
309 core::iter::empty::<&[(i32, CloneCounter)]>(),
310 );
311
312 assert_eq!(clone_count.get(), 0);
313 assert_eq!(result.next().map(|(key, _)| key), Some(1));
314 assert_eq!(clone_count.get(), 1);
315 drop(result);
316 assert_eq!(clone_count.get(), 1);
317 }
318}