Skip to main content

reth_trie_common/
utils.rs

1use alloc::vec::Vec;
2use core::cmp::Ordering;
3use itertools::Itertools;
4
5/// Merge sorted slices into a sorted `Vec`. First occurrence wins for duplicate keys.
6///
7/// Callers pass slices in priority order (index 0 = highest priority), so the first
8/// slice's value for a key takes precedence over later slices.
9pub(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        // Merge by reference: (priority, &K, &V) - avoids cloning all elements upfront
21        .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        // Clone only surviving elements after dedup
25        .map(|(_, k, v)| (k.clone(), v.clone()))
26        .collect()
27}
28
29/// Merge sorted left slices, excluding keys present in any right slice unless one of the right
30/// values is equal to the selected left value.
31/// Retained keys and values are cloned as the returned iterator is consumed.
32///
33/// Callers pass left slices in priority order (index 0 = highest priority), so the first
34/// left slice's value for a key takes precedence over later slices. Right slice order is ignored.
35pub(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
87/// Extend a sorted vector with another sorted vector using 2 pointer merge.
88/// Values from `other` take precedence for duplicate keys.
89pub(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    // Fast path: non-overlapping ranges - just append
104    if target.last().map(|(k, _)| k) < other.first().map(|(k, _)| k) {
105        target.extend_from_slice(other);
106        return;
107    }
108
109    // Move ownership of target to avoid cloning owned elements
110    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                // `other` takes precedence for duplicate keys - reuse key from `a`
126                let (k, _) = a.next().unwrap();
127                out.push((k, b.next().unwrap().1.clone()));
128            }
129        }
130    }
131
132    // Drain remaining: `a` moves, `b` clones
133    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        // other takes precedence
194        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        // First occurrence wins: key 1 -> a1 (slice1), key 3 -> c1 (slice1)
229        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        // First occurrence wins (slice1 has highest priority)
250        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}