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]
80 pub fn add(&mut self, new: Range<usize>) {
81 assert_range(&new);
82 if new.len() < self.min_len {
83 return;
84 }
85
86 let new = new.start as i32..new.end as i32;
87
88 let m_range = merging_range_by_guess_and_lazy_shift(
89 (&self.list, self.list.len()),
90 (self.from, [new.start, new.end]),
91 (self.from, self.shift, 0, std::ops::Add::add),
92 (|r| r.start, |r| r.end),
93 );
94
95 if self.from <= m_range.end {
97 for range in self.list.range_mut(self.from..m_range.end).iter_mut() {
98 range.start += self.shift;
99 range.end += self.shift;
100 }
101 }
102
103 let added_range = {
104 let slice = self.list.range(m_range.clone());
105 let mut iter = slice.iter();
106
107 let first = iter.next().cloned().unwrap_or(new.clone());
108 let last = iter.next_back().cloned().unwrap_or(first.clone());
109
110 first.start.min(new.start)..last.end.max(new.end)
111 };
112
113 let new_from = self.from.saturating_sub(m_range.len()).max(m_range.start) + 1;
114 if new_from < self.list.len() + 1 - m_range.len() {
115 self.from = new_from;
116 } else {
117 self.from = 0;
118 self.shift = 0;
119 }
120
121 self.list.splice(m_range.clone(), [added_range]);
122 }
123
124 #[track_caller]
127 pub fn remove(
128 &mut self,
129 within: Range<usize>,
130 ) -> impl ExactSizeIterator<Item = Range<usize>> + '_ {
131 assert_range(&within);
132 let within = within.start as i32..within.end as i32;
133
134 let m_range = merging_range_by_guess_and_lazy_shift(
135 (&self.list, self.list.len()),
136 (self.from, [within.start, within.end]),
137 (self.from, self.shift, 0, std::ops::Add::add),
138 (|r| r.start, |r| r.end),
139 );
140
141 if self.from <= m_range.end {
143 for range in self.list.range_mut(self.from..m_range.end).iter_mut() {
144 range.start += self.shift;
145 range.end += self.shift;
146 }
147 }
148
149 let split_off = {
150 let slice = self.list.range(m_range.clone());
151
152 let first = slice.iter().next().cloned();
153 let last = slice.iter().next_back().cloned().or(first.clone());
154
155 let split_start = first.filter(|f| f.start < within.start).map(|first| {
156 self.list[m_range.start].start = within.start;
157 first.start..within.start
158 });
159 let split_end = last.filter(|l| l.end > within.end).map(|last| {
160 self.list[m_range.end - 1].end = within.end;
161 within.end..last.end
162 });
163
164 let min_len = |range: &Range<i32>| range.len() >= self.min_len;
165
166 [split_start.filter(min_len), split_end.filter(min_len)]
167 };
168
169 let added = split_off.iter().flatten().count();
170
171 let new_from = self.from.saturating_sub(m_range.len()).max(m_range.start) + added;
172 if new_from < self.list.len() + added - m_range.len() {
173 self.from = new_from;
174 } else {
175 self.from = 0;
176 self.shift = 0;
177 }
178
179 self.list
180 .splice(m_range, split_off.into_iter().flatten())
181 .map(|r| r.start as usize..r.end as usize)
182 }
183
184 #[track_caller]
188 pub fn merge(&mut self, other: Self) {
189 for range in other.list {
190 self.add(range.start as usize..range.end as usize)
191 }
192 }
193
194 pub fn shift_by(&mut self, from: usize, shift: i32) {
202 let from = from as i32;
203
204 let m_range = merging_range_by_guess_and_lazy_shift(
206 (&self.list, self.list.len()),
207 (self.from, [from, from - shift.min(0)]),
208 (self.from, self.shift, 0, std::ops::Add::add),
209 (|r| r.start, |r| r.end),
210 );
211
212 if self.from < m_range.end && self.shift != 0 {
216 for range in self.list.range_mut(self.from..m_range.end).iter_mut() {
217 range.start += self.shift;
218 range.end += self.shift;
219 }
220 } else if self.from > m_range.end && self.shift != 0 {
225 for range in &mut self.list.range_mut(m_range.end..self.from) {
226 range.start -= self.shift;
227 range.end -= self.shift;
228 }
229 }
230
231 let range_left = {
232 let slice = self.list.range(m_range.clone());
233 let mut iter = slice.iter();
234
235 iter.next().and_then(|first| {
236 let last = iter.next_back().unwrap_or(first);
237 let range = first.start.min(from)..(last.end + shift).max(from);
238
239 (range.len() >= self.min_len).then_some(range)
240 })
241 };
242
243 let new_from = m_range.start + range_left.is_some() as usize;
244
245 self.list.splice(m_range.clone(), range_left);
246
247 if new_from < self.list.len() {
248 self.from = new_from;
249 self.shift += shift;
250 } else {
251 self.from = 0;
252 self.shift = 0;
253 }
254 }
255
256 pub fn len(&self) -> usize {
258 self.list.len()
259 }
260
261 pub fn is_empty(&self) -> bool {
263 self.list.is_empty()
264 }
265
266 pub fn iter(&self) -> impl Iterator<Item = Range<usize>> {
268 self.list.iter().enumerate().map(move |(i, range)| {
269 if i >= self.from {
270 (range.start + self.shift) as usize..(range.end + self.shift) as usize
271 } else {
272 range.start as usize..range.end as usize
273 }
274 })
275 }
276
277 #[track_caller]
280 pub fn iter_over(&self, within: Range<usize>) -> impl Iterator<Item = Range<usize>> {
281 assert_range(&within);
282 let within = within.start as i32..within.end as i32;
283
284 let m_range = merging_range_by_guess_and_lazy_shift(
285 (&self.list, self.list.len()),
286 (self.from, [within.start, within.end]),
287 (self.from, self.shift, 0, std::ops::Add::add),
288 (|r| r.start, |r| r.end),
289 );
290
291 let (s0, s1) = self.list.range(m_range.clone()).as_slices();
292 s0.iter().chain(s1).enumerate().map(move |(i, range)| {
293 let mut range = if i + m_range.start > self.from {
294 range.start + self.shift..range.end + self.shift
295 } else {
296 range.clone()
297 };
298
299 if i == 0 {
300 range.start = range.start.max(within.start);
301 }
302 if i == m_range.len() - 1 {
303 range.end = range.end.min(within.end);
304 }
305
306 range.start as usize..range.end as usize
307 })
308 }
309}
310
311impl IntoIterator for Ranges {
312 type IntoIter = IntoIter;
313 type Item = Range<usize>;
314
315 fn into_iter(self) -> Self::IntoIter {
316 IntoIter {
317 iter: self.list.into_iter().enumerate(),
318 from: self.from,
319 shift: self.shift,
320 }
321 }
322}
323
324pub struct IntoIter {
325 iter: std::iter::Enumerate<gapbuf::IntoIter<Range<i32>>>,
326 from: usize,
327 shift: i32,
328}
329
330impl Iterator for IntoIter {
331 type Item = Range<usize>;
332
333 fn next(&mut self) -> Option<Self::Item> {
334 self.iter.next().map(|(i, range)| {
335 if i >= self.from {
336 (range.start + self.shift) as usize..(range.end + self.shift) as usize
337 } else {
338 range.start as usize..range.end as usize
339 }
340 })
341 }
342}
343
344impl ExactSizeIterator for IntoIter {}
345
346#[track_caller]
347fn assert_range(range: &Range<usize>) {
348 assert!(
349 range.start <= range.end,
350 "range starts at {} but ends at {}",
351 range.start,
352 range.end
353 );
354}