1use std::ops::Range;
11
12use gap_buf::{GapBuffer, gap_buffer};
13
14use crate::utils::merging_range_by_guess_and_lazy_shift;
15
16#[derive(Clone, Default, Debug)]
27pub struct Ranges {
28 list: GapBuffer<Range<i32>>,
29 from: usize,
30 shift: i32,
31 min_len: usize,
32}
33
34impl Ranges {
35 pub fn new(range: Range<usize>) -> Self {
38 Self {
39 list: gap_buffer![range.start as i32..range.end as i32],
40 ..Self::empty()
41 }
42 }
43
44 pub const fn empty() -> Self {
46 Self {
47 list: GapBuffer::new(),
48 from: 0,
49 shift: 0,
50 min_len: 1,
51 }
52 }
53
54 pub fn set_min_len(&mut self, min: usize) {
56 self.min_len = min.max(1);
57
58 let mut i = 0;
59 self.list.retain(|range| {
60 i += 1;
61
62 if range.len() < self.min_len {
63 if i - 1 < self.from {
64 self.from -= 1;
65 }
66 false
67 } else {
68 true
69 }
70 });
71 }
72
73 #[track_caller]
83 pub fn add(&mut self, new: Range<usize>) -> bool {
84 assert_range(&new);
85 if new.len() < self.min_len {
86 return false;
87 }
88
89 let new = new.start as i32..new.end as i32;
90
91 let m_range = merging_range_by_guess_and_lazy_shift(
92 (&self.list, self.list.len()),
93 (self.from, [new.start, new.end]),
94 (self.from, self.shift, 0, std::ops::Add::add),
95 (|r| r.start, |r| r.end),
96 );
97
98 if self.from <= m_range.end {
100 for range in self.list.range_mut(self.from..m_range.end).iter_mut() {
101 range.start += self.shift;
102 range.end += self.shift;
103 }
104 }
105
106 let changed_ranges = if m_range.len() == 1 {
107 let range = self.list[m_range.start].clone();
108 !(range.start <= new.start && range.end >= new.end)
109 } else {
110 true
111 };
112
113 let added_range = {
114 let slice = self.list.range(m_range.clone());
115 let mut iter = slice.iter();
116
117 let first = iter.next().cloned().unwrap_or(new.clone());
118 let last = iter.next_back().cloned().unwrap_or(first.clone());
119
120 first.start.min(new.start)..last.end.max(new.end)
121 };
122
123 let new_from = self.from.saturating_sub(m_range.len()).max(m_range.start) + 1;
124 if new_from < self.list.len() + 1 - m_range.len() {
125 self.from = new_from;
126 } else {
127 self.from = 0;
128 self.shift = 0;
129 }
130
131 self.list.splice(m_range.clone(), [added_range]);
132
133 changed_ranges
134 }
135
136 pub fn extend(&mut self, ranges: impl IntoIterator<Item = Range<usize>>) -> bool {
141 let mut has_changed = false;
142 for range in ranges {
143 has_changed |= self.add(range);
144 }
145 has_changed
146 }
147
148 #[track_caller]
151 pub fn remove_on(&mut self, within: Range<usize>) -> impl Iterator<Item = Range<usize>> {
152 assert_range(&within);
153 let within = within.start as i32..within.end as i32;
154
155 let m_range = merging_range_by_guess_and_lazy_shift(
156 (&self.list, self.list.len()),
157 (self.from, [within.start, within.end]),
158 (self.from, self.shift, 0, std::ops::Add::add),
159 (|r| r.start, |r| r.end),
160 );
161
162 if self.from <= m_range.end {
164 for range in self.list.range_mut(self.from..m_range.end).iter_mut() {
165 range.start += self.shift;
166 range.end += self.shift;
167 }
168 }
169
170 let split_off = {
171 let slice = self.list.range(m_range.clone());
172
173 let first = slice.iter().next().cloned();
174 let last = slice.iter().next_back().cloned().or(first.clone());
175
176 let split_start = first.filter(|f| f.start < within.start).map(|first| {
177 self.list[m_range.start].start = within.start;
178 first.start..within.start
179 });
180 let split_end = last.filter(|l| l.end > within.end).map(|last| {
181 self.list[m_range.end - 1].end = within.end;
182 within.end..last.end
183 });
184
185 let min_len = |range: &Range<i32>| range.len() >= self.min_len;
186
187 [split_start.filter(min_len), split_end.filter(min_len)]
188 };
189
190 let added = split_off.iter().flatten().count();
191
192 let new_from = self.from.saturating_sub(m_range.len()).max(m_range.start) + added;
193 if new_from < self.list.len() + added - m_range.len() {
194 self.from = new_from;
195 } else {
196 self.from = 0;
197 self.shift = 0;
198 }
199
200 self.list
201 .splice(m_range, split_off.into_iter().flatten())
202 .map(|r| r.start as usize..r.end as usize)
203 }
204
205 #[track_caller]
208 pub fn remove_intersecting(
209 &mut self,
210 within: Range<usize>,
211 ) -> impl Iterator<Item = Range<usize>> {
212 assert_range(&within);
213 let within = within.start as i32..within.end as i32;
214
215 let m_range = merging_range_by_guess_and_lazy_shift(
216 (&self.list, self.list.len()),
217 (self.from, [within.start, within.end]),
218 (self.from, self.shift, 0, std::ops::Add::add),
219 (|r| r.start, |r| r.end),
220 );
221
222 if self.from <= m_range.end {
224 for range in self.list.range_mut(self.from..m_range.end).iter_mut() {
225 range.start += self.shift;
226 range.end += self.shift;
227 }
228 }
229
230 let new_from = self.from.saturating_sub(m_range.len()).max(m_range.start);
231 if new_from < self.list.len() - m_range.len() {
232 self.from = new_from;
233 } else {
234 self.from = 0;
235 self.shift = 0;
236 }
237
238 self.list
239 .extract_if(m_range, move |range| {
240 range.start != within.end && range.end != within.start
241 })
242 .map(|range| range.start as usize..range.end as usize)
243 }
244
245 #[track_caller]
249 pub fn merge(&mut self, other: Self) -> bool {
250 let mut has_changed = false;
251 for range in other.list {
252 has_changed |= self.add(range.start as usize..range.end as usize);
253 }
254 has_changed
255 }
256
257 pub fn shift_by(&mut self, from: usize, shift: i32) {
265 let from = from as i32;
266
267 let m_range = merging_range_by_guess_and_lazy_shift(
269 (&self.list, self.list.len()),
270 (self.from, [from, from - shift.min(0)]),
271 (self.from, self.shift, 0, std::ops::Add::add),
272 (|r| r.start, |r| r.end),
273 );
274
275 if self.from < m_range.end && self.shift != 0 {
279 for range in self.list.range_mut(self.from..m_range.end).iter_mut() {
280 range.start += self.shift;
281 range.end += self.shift;
282 }
283 } else if self.from > m_range.end && self.shift != 0 {
288 for range in &mut self.list.range_mut(m_range.end..self.from) {
289 range.start -= self.shift;
290 range.end -= self.shift;
291 }
292 }
293
294 let range_left = {
295 let slice = self.list.range(m_range.clone());
296 let mut iter = slice.iter();
297
298 iter.next().and_then(|first| {
299 let last = iter.next_back().unwrap_or(first);
300 let range = first.start.min(from)..(last.end + shift).max(from);
301
302 (range.len() >= self.min_len).then_some(range)
303 })
304 };
305
306 let new_from = m_range.start + range_left.is_some() as usize;
307
308 self.list.splice(m_range.clone(), range_left);
309
310 if new_from < self.list.len() {
311 self.from = new_from;
312 self.shift += shift;
313 } else {
314 self.from = 0;
315 self.shift = 0;
316 }
317 }
318
319 pub fn len(&self) -> usize {
321 self.list.len()
322 }
323
324 pub fn is_empty(&self) -> bool {
326 self.list.is_empty()
327 }
328
329 pub fn iter(&self) -> impl Iterator<Item = Range<usize>> {
331 self.list.iter().enumerate().map(move |(i, range)| {
332 if i >= self.from {
333 (range.start + self.shift) as usize..(range.end + self.shift) as usize
334 } else {
335 range.start as usize..range.end as usize
336 }
337 })
338 }
339
340 #[track_caller]
349 pub fn iter_over(&self, within: Range<usize>) -> impl Iterator<Item = Range<usize>> {
350 self.iter_intersecting(within.clone())
351 .map(move |range| range.start.max(within.start)..range.end.min(within.end))
352 .filter(|range| !range.is_empty())
353 }
354
355 #[track_caller]
364 pub fn iter_intersecting(&self, within: Range<usize>) -> impl Iterator<Item = Range<usize>> {
365 assert_range(&within);
366 let m_range = merging_range_by_guess_and_lazy_shift(
367 (&self.list, self.list.len()),
368 (self.from, [within.start as i32, within.end as i32]),
369 (self.from, self.shift, 0, std::ops::Add::add),
370 (|r| r.start, |r| r.end),
371 );
372
373 let (s0, s1) = self.list.range(m_range.clone()).as_slices();
374 s0.iter().chain(s1).enumerate().filter_map(move |(i, r)| {
375 let range = if i + m_range.start >= self.from {
376 (r.start + self.shift) as usize..(r.end + self.shift) as usize
377 } else {
378 r.start as usize..r.end as usize
379 };
380
381 (range.start != within.end && range.end != within.start).then_some(range)
382 })
383 }
384
385 #[track_caller]
388 pub fn intersects_with(&self, range: Range<usize>) -> bool {
389 assert_range(&range);
390
391 let m_range = merging_range_by_guess_and_lazy_shift(
392 (&self.list, self.list.len()),
393 (self.from, [range.start as i32, range.end as i32]),
394 (self.from, self.shift, 0, std::ops::Add::add),
395 (|r| r.start, |r| r.end),
396 );
397
398 !m_range.is_empty()
399 }
400}
401
402impl IntoIterator for Ranges {
403 type IntoIter = IntoIter;
404 type Item = Range<usize>;
405
406 fn into_iter(self) -> Self::IntoIter {
407 IntoIter {
408 iter: self.list.into_iter().enumerate(),
409 from: self.from,
410 shift: self.shift,
411 }
412 }
413}
414
415pub struct IntoIter {
416 iter: std::iter::Enumerate<gap_buf::IntoIter<Range<i32>>>,
417 from: usize,
418 shift: i32,
419}
420
421impl Iterator for IntoIter {
422 type Item = Range<usize>;
423
424 fn next(&mut self) -> Option<Self::Item> {
425 self.iter.next().map(|(i, range)| {
426 if i >= self.from {
427 (range.start + self.shift) as usize..(range.end + self.shift) as usize
428 } else {
429 range.start as usize..range.end as usize
430 }
431 })
432 }
433}
434
435impl ExactSizeIterator for IntoIter {}
436
437impl PartialEq for Ranges {
438 fn eq(&self, other: &Self) -> bool {
439 self.len() == other.len() && self.iter().eq(other.iter())
440 }
441}
442
443impl Eq for Ranges {}
444
445impl PartialOrd for Ranges {
446 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
447 Some(self.cmp(other))
448 }
449}
450
451impl Ord for Ranges {
452 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
453 let cmp = |r: Range<usize>| [r.start, r.end];
454 self.iter().flat_map(cmp).cmp(other.iter().flat_map(cmp))
455 }
456}
457
458#[track_caller]
459pub fn assert_range(range: &Range<usize>) {
460 assert!(
461 range.start <= range.end,
462 "range starts at {} but ends at {}",
463 range.start,
464 range.end
465 );
466}