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/// Extend a sorted vector with another sorted vector using 2 pointer merge.
30/// Values from `other` take precedence for duplicate keys.
31pub(crate) fn extend_sorted_vec<K, V>(target: &mut Vec<(K, V)>, other: &[(K, V)])
32where
33    K: Clone + Ord,
34    V: Clone,
35{
36    if other.is_empty() {
37        return;
38    }
39
40    if target.is_empty() {
41        target.extend_from_slice(other);
42        return;
43    }
44
45    // Fast path: non-overlapping ranges - just append
46    if target.last().map(|(k, _)| k) < other.first().map(|(k, _)| k) {
47        target.extend_from_slice(other);
48        return;
49    }
50
51    // Move ownership of target to avoid cloning owned elements
52    let left = core::mem::take(target);
53    let mut out = Vec::with_capacity(left.len() + other.len());
54
55    let mut a = left.into_iter().peekable();
56    let mut b = other.iter().peekable();
57
58    while let (Some(aa), Some(bb)) = (a.peek(), b.peek()) {
59        match aa.0.cmp(&bb.0) {
60            Ordering::Less => {
61                out.push(a.next().unwrap());
62            }
63            Ordering::Greater => {
64                out.push(b.next().unwrap().clone());
65            }
66            Ordering::Equal => {
67                // `other` takes precedence for duplicate keys - reuse key from `a`
68                let (k, _) = a.next().unwrap();
69                out.push((k, b.next().unwrap().1.clone()));
70            }
71        }
72    }
73
74    // Drain remaining: `a` moves, `b` clones
75    out.extend(a);
76    out.extend(b.cloned());
77
78    *target = out;
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_extend_sorted_vec() {
87        let mut target = vec![(1, "a"), (3, "c")];
88        let other = vec![(2, "b"), (3, "c_new")];
89        extend_sorted_vec(&mut target, &other);
90        assert_eq!(target, vec![(1, "a"), (2, "b"), (3, "c_new")]);
91    }
92
93    #[test]
94    fn test_extend_sorted_vec_empty_target() {
95        let mut target: Vec<(i32, &str)> = vec![];
96        let other = vec![(1, "a"), (2, "b")];
97        extend_sorted_vec(&mut target, &other);
98        assert_eq!(target, vec![(1, "a"), (2, "b")]);
99    }
100
101    #[test]
102    fn test_extend_sorted_vec_empty_other() {
103        let mut target = vec![(1, "a"), (2, "b")];
104        let other: Vec<(i32, &str)> = vec![];
105        extend_sorted_vec(&mut target, &other);
106        assert_eq!(target, vec![(1, "a"), (2, "b")]);
107    }
108
109    #[test]
110    fn test_extend_sorted_vec_all_duplicates() {
111        let mut target = vec![(1, "old1"), (2, "old2"), (3, "old3")];
112        let other = vec![(1, "new1"), (2, "new2"), (3, "new3")];
113        extend_sorted_vec(&mut target, &other);
114        // other takes precedence
115        assert_eq!(target, vec![(1, "new1"), (2, "new2"), (3, "new3")]);
116    }
117
118    #[test]
119    fn test_extend_sorted_vec_interleaved() {
120        let mut target = vec![(1, "a"), (3, "c"), (5, "e")];
121        let other = vec![(2, "b"), (4, "d"), (6, "f")];
122        extend_sorted_vec(&mut target, &other);
123        assert_eq!(target, vec![(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e"), (6, "f")]);
124    }
125
126    #[test]
127    fn test_extend_sorted_vec_other_all_smaller() {
128        let mut target = vec![(5, "e"), (6, "f")];
129        let other = vec![(1, "a"), (2, "b")];
130        extend_sorted_vec(&mut target, &other);
131        assert_eq!(target, vec![(1, "a"), (2, "b"), (5, "e"), (6, "f")]);
132    }
133
134    #[test]
135    fn test_extend_sorted_vec_other_all_larger() {
136        let mut target = vec![(1, "a"), (2, "b")];
137        let other = vec![(5, "e"), (6, "f")];
138        extend_sorted_vec(&mut target, &other);
139        assert_eq!(target, vec![(1, "a"), (2, "b"), (5, "e"), (6, "f")]);
140    }
141
142    #[test]
143    fn test_kway_merge_sorted_basic() {
144        let slice1 = vec![(1, "a1"), (3, "c1")];
145        let slice2 = vec![(2, "b2"), (3, "c2")];
146        let slice3 = vec![(1, "a3"), (4, "d3")];
147
148        let result = kway_merge_sorted([slice1.as_slice(), slice2.as_slice(), slice3.as_slice()]);
149        // First occurrence wins: key 1 -> a1 (slice1), key 3 -> c1 (slice1)
150        assert_eq!(result, vec![(1, "a1"), (2, "b2"), (3, "c1"), (4, "d3")]);
151    }
152
153    #[test]
154    fn test_kway_merge_sorted_empty_slices() {
155        let slice1: Vec<(i32, &str)> = vec![];
156        let slice2 = vec![(1, "a")];
157        let slice3: Vec<(i32, &str)> = vec![];
158
159        let result = kway_merge_sorted([slice1.as_slice(), slice2.as_slice(), slice3.as_slice()]);
160        assert_eq!(result, vec![(1, "a")]);
161    }
162
163    #[test]
164    fn test_kway_merge_sorted_all_same_key() {
165        let slice1 = vec![(5, "first")];
166        let slice2 = vec![(5, "middle")];
167        let slice3 = vec![(5, "last")];
168
169        let result = kway_merge_sorted([slice1.as_slice(), slice2.as_slice(), slice3.as_slice()]);
170        // First occurrence wins (slice1 has highest priority)
171        assert_eq!(result, vec![(5, "first")]);
172    }
173
174    #[test]
175    fn test_kway_merge_sorted_single_slice() {
176        let slice = vec![(1, "a"), (2, "b"), (3, "c")];
177        let result = kway_merge_sorted([slice.as_slice()]);
178        assert_eq!(result, vec![(1, "a"), (2, "b"), (3, "c")]);
179    }
180
181    #[test]
182    fn test_kway_merge_sorted_no_slices() {
183        let result: Vec<(i32, &str)> = kway_merge_sorted(Vec::<&[(i32, &str)]>::new());
184        assert!(result.is_empty());
185    }
186}