1use core::cmp::Ordering;
2use core::ops::Range;
3
4pub(crate) struct MatchedRanges<'a> {
6 ranges: &'a mut Vec<Range<usize>>,
7 initial_len: usize,
8}
9
10impl<'a> From<&'a mut Vec<Range<usize>>> for MatchedRanges<'a> {
11 #[inline(always)]
12 fn from(ranges: &'a mut Vec<Range<usize>>) -> Self {
13 let initial_len = ranges.len();
14 Self { ranges, initial_len }
15 }
16}
17
18impl core::fmt::Debug for MatchedRanges<'_> {
19 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
20 use core::fmt::Write;
21
22 let (initial, this) = self.ranges.split_at(self.initial_len);
23
24 if this.is_empty() {
25 return initial.fmt(f);
26 }
27
28 f.write_char('[')?;
29
30 for (idx, initial) in initial.iter().enumerate() {
31 write!(f, "{initial:?}")?;
32 if idx + 1 < initial.len() {
33 f.write_str(", ")?;
34 }
35 }
36
37 f.write_str(" | ")?;
38
39 for (idx, this) in this.iter().enumerate() {
40 write!(f, "{this:?}")?;
41 if idx + 1 < this.len() {
42 f.write_str(", ")?;
43 }
44 }
45
46 f.write_char(']')?;
47
48 Ok(())
49 }
50}
51
52impl<'a> MatchedRanges<'a> {
53 #[inline(always)]
55 fn binary_search_by<'r, F>(&'r self, fun: F) -> Result<usize, usize>
56 where
57 F: FnMut(&'r Range<usize>) -> Ordering,
58 {
59 self.ranges[self.initial_len..].binary_search_by(fun)
60 }
61
62 #[inline(always)]
64 fn get_mut(&mut self, idx: usize) -> Option<&mut Range<usize>> {
65 self.ranges.get_mut(self.initial_len + idx)
66 }
67
68 #[inline(always)]
70 pub(crate) fn insert(&mut self, new_range: Range<usize>) {
71 let insert_idx = match self
72 .binary_search_by(|range| range.start.cmp(&new_range.start))
73 {
74 Err(idx) => idx,
75
76 Ok(idx) => {
78 let (range, next_range) = {
79 let (left, right) = self.split_at_mut(idx + 1);
80 (&mut left[idx], right.get_mut(0))
81 };
82
83 if range.end >= new_range.end {
84 return;
87 }
88
89 if let Some(next_range) = next_range {
90 if new_range.end >= next_range.start {
91 range.end = next_range.end;
94 self.remove(idx + 1);
95 return;
96 }
97 }
98
99 range.end = new_range.end;
100
101 return;
102 },
103 };
104
105 if insert_idx == 0 {
106 let Some(first_range) = self.get_mut(0) else {
107 self.push(new_range);
109 return;
110 };
111
112 if new_range.end >= first_range.start {
113 first_range.start = new_range.start;
114 } else {
115 self.insert_at(0, new_range);
116 }
117
118 return;
119 }
120
121 if insert_idx == self.len() {
122 let last_range = self.last_mut().unwrap();
123
124 if new_range.start <= last_range.end {
125 last_range.end = last_range.end.max(new_range.end);
126 } else {
127 self.push(new_range);
128 }
129
130 return;
131 }
132
133 let (prev_range, next_range) = {
134 let (left, right) = self.split_at_mut(insert_idx);
135 (&mut left[insert_idx - 1], &mut right[0])
136 };
137
138 match (
139 new_range.start <= prev_range.end,
140 new_range.end >= next_range.start,
141 ) {
142 (true, true) => {
148 prev_range.end = next_range.end;
149 self.remove(insert_idx);
150 },
151
152 (true, false) if new_range.end > prev_range.end => {
158 prev_range.end = new_range.end;
159 },
160
161 (false, true) => {
168 next_range.start = new_range.start;
169 },
170
171 (false, false) => {
176 self.insert_at(insert_idx, new_range);
177 },
178
179 _ => {},
180 }
181 }
182
183 #[inline(always)]
185 fn insert_at(&mut self, idx: usize, range: Range<usize>) {
186 self.ranges.insert(self.initial_len + idx, range);
187 }
188
189 #[inline(always)]
191 fn last_mut(&mut self) -> Option<&mut Range<usize>> {
192 self.ranges.last_mut()
193 }
194
195 #[inline(always)]
197 fn len(&self) -> usize {
198 self.ranges.len() - self.initial_len
199 }
200
201 #[inline(always)]
203 fn push(&mut self, range: Range<usize>) {
204 self.ranges.push(range);
205 }
206
207 #[inline(always)]
209 fn remove(&mut self, idx: usize) -> Range<usize> {
210 self.ranges.remove(self.initial_len + idx)
211 }
212
213 #[inline(always)]
215 fn split_at_mut(
216 &mut self,
217 idx: usize,
218 ) -> (&mut [Range<usize>], &mut [Range<usize>]) {
219 let len = self.initial_len;
220 let (left, right) = self.ranges.split_at_mut(len + idx);
221 let left = &mut left[len..];
222 (left, right)
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 #![allow(clippy::single_range_in_vec_init)]
229
230 use super::*;
231
232 impl<'a> MatchedRanges<'a> {
233 fn as_slice(&self) -> &[Range<usize>] {
234 &self.ranges[..]
235 }
236 }
237
238 fn ranges() -> MatchedRanges<'static> {
239 let vec = Box::leak(Box::default());
240 MatchedRanges::from(vec)
241 }
242
243 #[test]
244 fn matched_ranges_insert_same_start_increasing_end() {
245 let mut ranges = ranges();
246 ranges.insert(0..1);
247 ranges.insert(0..2);
248 ranges.insert(0..3);
249 assert_eq!(ranges.as_slice(), [0..3]);
250 ranges.insert(0..2);
251 assert_eq!(ranges.as_slice(), [0..3]);
252 }
253
254 #[test]
255 fn matched_ranges_insert_consecutive_1() {
256 let mut ranges = ranges();
257 ranges.insert(0..1);
258 ranges.insert(1..2);
259 ranges.insert(2..3);
260 assert_eq!(ranges.as_slice(), [0..3]);
261 }
262
263 #[test]
264 fn matched_ranges_insert_consecutive_2() {
265 let mut ranges = ranges();
266 ranges.insert(2..3);
267 ranges.insert(1..2);
268 ranges.insert(0..1);
269 assert_eq!(ranges.as_slice(), [0..3]);
270 }
271
272 #[test]
273 fn matched_ranges_insert_fill_gap() {
274 let mut ranges = ranges();
275 ranges.insert(0..1);
276 ranges.insert(2..3);
277 assert_eq!(ranges.as_slice(), [0..1, 2..3]);
278 ranges.insert(1..2);
279 assert_eq!(ranges.as_slice(), [0..3]);
280 }
281
282 #[test]
283 fn matched_ranges_insert_extend_end() {
284 let mut ranges = ranges();
285 ranges.insert(0..2);
286 ranges.insert(4..6);
287 ranges.insert(1..3);
288 assert_eq!(ranges.as_slice(), [0..3, 4..6]);
289 }
290
291 #[test]
292 fn matched_ranges_insert_extend_start() {
293 let mut ranges = ranges();
294 ranges.insert(0..2);
295 ranges.insert(4..6);
296 ranges.insert(3..5);
297 assert_eq!(ranges.as_slice(), [0..2, 3..6]);
298 }
299
300 #[test]
301 fn matched_ranges_insert_in_gap() {
302 let mut ranges = ranges();
303 ranges.insert(0..4);
304 ranges.insert(6..8);
305 ranges.insert(10..14);
306 assert_eq!(ranges.as_slice(), [0..4, 6..8, 10..14]);
307 }
308
309 #[test]
310 fn matched_ranges_insert_smaller_1() {
311 let mut ranges = ranges();
312 ranges.insert(3..8);
313 ranges.insert(4..7);
314 assert_eq!(ranges.as_slice(), [3..8]);
315 ranges.insert(5..6);
316 assert_eq!(ranges.as_slice(), [3..8]);
317 }
318
319 #[test]
320 fn matched_ranges_insert_smaller_2() {
321 let mut ranges = ranges();
322 ranges.insert(1..2);
323 ranges.insert(3..8);
324 ranges.insert(4..7);
325 assert_eq!(ranges.as_slice(), [1..2, 3..8]);
326 ranges.insert(5..6);
327 assert_eq!(ranges.as_slice(), [1..2, 3..8]);
328 }
329
330 #[test]
331 fn matched_ranges_insert_smaller_3() {
332 let mut ranges = ranges();
333 ranges.insert(10..11);
334 ranges.insert(3..8);
335 ranges.insert(4..7);
336 assert_eq!(ranges.as_slice(), [3..8, 10..11]);
337 ranges.insert(5..6);
338 assert_eq!(ranges.as_slice(), [3..8, 10..11]);
339 }
340
341 #[test]
342 fn matched_ranges_insert_smaller_4() {
343 let mut ranges = ranges();
344 ranges.insert(1..2);
345 ranges.insert(10..11);
346 ranges.insert(3..8);
347 ranges.insert(4..7);
348 assert_eq!(ranges.as_slice(), [1..2, 3..8, 10..11]);
349 ranges.insert(5..6);
350 assert_eq!(ranges.as_slice(), [1..2, 3..8, 10..11]);
351 }
352}