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