utils/
slice.rs

1//! Slice helpers.
2use std::cmp::Ordering;
3
4/// Merges a sorted deduped [`Vec`] in place with a sorted deduped slice.
5///
6/// This is equivalent to a set union on sorted data.
7///
8/// Both inputs **must** be sorted and contain no duplicates.
9///
10/// # Examples
11/// ```
12/// # use utils::slice::merge_sorted_deduped_in_place;
13/// let mut v = vec![1, 3, 5];
14/// merge_sorted_deduped_in_place(&mut v, &[2, 3, 4]);
15/// assert_eq!(v, [1, 2, 3, 4, 5]);
16///
17/// // Elements at start and end
18/// let mut v = vec![1, 2, 3, 4, 5];
19/// merge_sorted_deduped_in_place(&mut v, &[0, 6]);
20/// assert_eq!(v, [0, 1, 2, 3, 4, 5, 6]);
21///
22/// // Complete overlap
23/// let mut v = vec![1, 2, 3];
24/// merge_sorted_deduped_in_place(&mut v, &[1, 2, 3]);
25/// assert_eq!(v, [1, 2, 3]);
26///
27/// // No overlap
28/// let mut v = vec![1, 2];
29/// merge_sorted_deduped_in_place(&mut v, &[3, 4]);
30/// assert_eq!(v, [1, 2, 3, 4]);
31///
32/// let mut v = vec![24, 53];
33/// merge_sorted_deduped_in_place(&mut v, &[6]);
34/// assert_eq!(v, [6, 24, 53]);
35///
36/// // Partial overlap
37/// let mut v = vec![10, 11, 12, 13];
38/// merge_sorted_deduped_in_place(&mut v, &[13, 14]);
39/// assert_eq!(v, [10, 11, 12, 13, 14]);
40///
41/// let mut v = vec![300, 400, 500];
42/// merge_sorted_deduped_in_place(&mut v, &[100, 200, 300]);
43/// assert_eq!(v, [100, 200, 300, 400, 500]);
44///
45/// // Empty inputs
46/// let mut v = Vec::new();
47/// merge_sorted_deduped_in_place(&mut v, &[5]);
48/// assert_eq!(v, [5]);
49///
50/// let mut v = vec![6];
51/// merge_sorted_deduped_in_place(&mut v, &[]);
52/// assert_eq!(v, [6]);
53///
54/// let mut v: Vec<u32> = Vec::new();
55/// merge_sorted_deduped_in_place(&mut v, &[]);
56/// assert_eq!(v, []);
57/// ```
58#[inline]
59pub fn merge_sorted_deduped_in_place<T: Copy + Ord + Default>(a: &mut Vec<T>, b: &[T]) {
60    debug_assert!(a.windows(2).all(|w| w[0] < w[1]));
61    debug_assert!(b.windows(2).all(|w| w[0] < w[1]));
62
63    let mut new = 0;
64    let (mut i, mut j) = (0, 0);
65    while i < a.len() && j < b.len() {
66        match a[i].cmp(&b[j]) {
67            Ordering::Less => i += 1,
68            Ordering::Equal => {
69                i += 1;
70                j += 1;
71            }
72            Ordering::Greater => {
73                new += 1;
74                j += 1;
75            }
76        }
77    }
78    new += b.len() - j;
79
80    if new == 0 {
81        return;
82    }
83
84    let (mut i, mut j, mut write) = (a.len(), b.len(), a.len() + new);
85    a.resize(a.len() + new, T::default());
86
87    while i > 0 && j > 0 {
88        write -= 1;
89        a[write] = match a[i - 1].cmp(&b[j - 1]) {
90            Ordering::Less => {
91                j -= 1;
92                b[j]
93            }
94            Ordering::Equal => {
95                i -= 1;
96                j -= 1;
97                a[i]
98            }
99            Ordering::Greater => {
100                i -= 1;
101                a[i]
102            }
103        }
104    }
105
106    a[..j].copy_from_slice(&b[..j]);
107}