1use std::ops::Range;
11
12use gapbuf::{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 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 .filter_map(|r| (!r.is_empty()).then_some(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 .drain(m_range)
240 .map(|range| range.start as usize..range.end as usize)
241 }
242
243 #[track_caller]
247 pub fn merge(&mut self, other: Self) -> bool {
248 let mut has_changed = false;
249 for range in other.list {
250 has_changed |= self.add(range.start as usize..range.end as usize);
251 }
252 has_changed
253 }
254
255 pub fn shift_by(&mut self, from: usize, shift: i32) {
263 let from = from as i32;
264
265 let m_range = merging_range_by_guess_and_lazy_shift(
267 (&self.list, self.list.len()),
268 (self.from, [from, from - shift.min(0)]),
269 (self.from, self.shift, 0, std::ops::Add::add),
270 (|r| r.start, |r| r.end),
271 );
272
273 if self.from < m_range.end && self.shift != 0 {
277 for range in self.list.range_mut(self.from..m_range.end).iter_mut() {
278 range.start += self.shift;
279 range.end += self.shift;
280 }
281 } else if self.from > m_range.end && self.shift != 0 {
286 for range in &mut self.list.range_mut(m_range.end..self.from) {
287 range.start -= self.shift;
288 range.end -= self.shift;
289 }
290 }
291
292 let range_left = {
293 let slice = self.list.range(m_range.clone());
294 let mut iter = slice.iter();
295
296 iter.next().and_then(|first| {
297 let last = iter.next_back().unwrap_or(first);
298 let range = first.start.min(from)..(last.end + shift).max(from);
299
300 (range.len() >= self.min_len).then_some(range)
301 })
302 };
303
304 let new_from = m_range.start + range_left.is_some() as usize;
305
306 self.list.splice(m_range.clone(), range_left);
307
308 if new_from < self.list.len() {
309 self.from = new_from;
310 self.shift += shift;
311 } else {
312 self.from = 0;
313 self.shift = 0;
314 }
315 }
316
317 pub fn len(&self) -> usize {
319 self.list.len()
320 }
321
322 pub fn is_empty(&self) -> bool {
324 self.list.is_empty()
325 }
326
327 pub fn iter(&self) -> impl Iterator<Item = Range<usize>> {
329 self.list.iter().enumerate().map(move |(i, range)| {
330 if i >= self.from {
331 (range.start + self.shift) as usize..(range.end + self.shift) as usize
332 } else {
333 range.start as usize..range.end as usize
334 }
335 })
336 }
337
338 #[track_caller]
347 pub fn iter_over(&self, within: Range<usize>) -> impl Iterator<Item = Range<usize>> {
348 self.iter_intersecting(within.clone())
349 .map(move |range| range.start.max(within.start)..range.end.min(within.end))
350 .filter(|range| !range.is_empty())
351 }
352
353 #[track_caller]
362 pub fn iter_intersecting(&self, within: Range<usize>) -> impl Iterator<Item = Range<usize>> {
363 assert_range(&within);
364 let m_range = merging_range_by_guess_and_lazy_shift(
365 (&self.list, self.list.len()),
366 (self.from, [within.start as i32, within.end as i32]),
367 (self.from, self.shift, 0, std::ops::Add::add),
368 (|r| r.start, |r| r.end),
369 );
370
371 let (s0, s1) = self.list.range(m_range.clone()).as_slices();
372 s0.iter().chain(s1).enumerate().map(move |(i, range)| {
373 let range = if i + m_range.start >= self.from {
374 range.start + self.shift..range.end + self.shift
375 } else {
376 range.clone()
377 };
378
379 range.start as usize..range.end as usize
380 })
381 }
382
383 #[track_caller]
386 pub fn intersects_with(&self, range: Range<usize>) -> bool {
387 assert_range(&range);
388
389 let m_range = merging_range_by_guess_and_lazy_shift(
390 (&self.list, self.list.len()),
391 (self.from, [range.start as i32, range.end as i32]),
392 (self.from, self.shift, 0, std::ops::Add::add),
393 (|r| r.start, |r| r.end),
394 );
395
396 !m_range.is_empty()
397 }
398}
399
400impl IntoIterator for Ranges {
401 type IntoIter = IntoIter;
402 type Item = Range<usize>;
403
404 fn into_iter(self) -> Self::IntoIter {
405 IntoIter {
406 iter: self.list.into_iter().enumerate(),
407 from: self.from,
408 shift: self.shift,
409 }
410 }
411}
412
413pub struct IntoIter {
414 iter: std::iter::Enumerate<gapbuf::IntoIter<Range<i32>>>,
415 from: usize,
416 shift: i32,
417}
418
419impl Iterator for IntoIter {
420 type Item = Range<usize>;
421
422 fn next(&mut self) -> Option<Self::Item> {
423 self.iter.next().map(|(i, range)| {
424 if i >= self.from {
425 (range.start + self.shift) as usize..(range.end + self.shift) as usize
426 } else {
427 range.start as usize..range.end as usize
428 }
429 })
430 }
431}
432
433impl ExactSizeIterator for IntoIter {}
434
435impl PartialEq for Ranges {
436 fn eq(&self, other: &Self) -> bool {
437 self.len() == other.len() && self.iter().eq(other.iter())
438 }
439}
440
441impl Eq for Ranges {}
442
443impl PartialOrd for Ranges {
444 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
445 Some(self.cmp(other))
446 }
447}
448
449impl Ord for Ranges {
450 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
451 let cmp = |r: Range<usize>| [r.start, r.end];
452 self.iter().flat_map(cmp).cmp(other.iter().flat_map(cmp))
453 }
454}
455
456#[track_caller]
457pub fn assert_range(range: &Range<usize>) {
458 assert!(
459 range.start <= range.end,
460 "range starts at {} but ends at {}",
461 range.start,
462 range.end
463 );
464}