1use alloc::vec::Vec;
2use codec::{Compact, CompactLen, Decode, Encode, Input, MaxEncodedLen};
3
4#[derive(Clone, PartialEq, Eq, Encode, Default)]
6pub struct RangeSet {
7 ranges: Vec<Range>,
8}
9
10impl RangeSet {
11 pub const fn new() -> Self {
12 Self { ranges: Vec::new() }
13 }
14
15 pub fn with_capacity(capacity: usize) -> Self {
16 Self { ranges: Vec::with_capacity(capacity) }
17 }
18
19 pub fn insert(&mut self, mut new_range: Range) {
20 if new_range.is_empty() {
21 return;
22 }
23 if self.ranges.is_empty() {
24 self.ranges.push(new_range);
25 return;
26 }
27 let (at, from) =
28 match self.ranges.binary_search_by(|range| range.start.cmp(&new_range.start)) {
29 Ok(i) => (i, i),
30 Err(i) => (i, i.saturating_sub(1)),
31 };
32 let mut splice_range = at..at;
33 for i in from..self.ranges.len() {
34 let r = &mut self.ranges[i];
35 let contains_start = (r.start..=r.end).contains(&new_range.start);
36 let contains_end = (r.start..=r.end).contains(&new_range.end);
37 if contains_start && contains_end {
38 return;
39 }
40 if contains_start {
41 new_range.start = r.start;
42 splice_range = i..i + 1;
43 continue;
44 }
45 if contains_end {
46 new_range.end = r.end;
47 splice_range.end = i + 1;
48 break;
49 }
50 }
51 self.ranges.splice(splice_range, [new_range]);
52 }
53
54 pub fn remove(&mut self, range: &Range) {
55 if range.is_empty() {
56 return;
57 }
58 let from = match self.ranges.binary_search_by(|r| r.start.cmp(&range.start)) {
59 Ok(i) => i,
60 Err(i) => i.saturating_sub(1),
61 };
62 #[allow(clippy::reversed_empty_ranges)]
63 let mut drain_range = usize::MAX..0;
64 for i in from..self.ranges.len() {
65 let r = &mut self.ranges[i];
66 let contains_start = (r.start..r.end).contains(&range.start);
67 let contains_end = (r.start..=r.end).contains(&range.end);
68 if contains_start && contains_end {
69 let old_end = r.end;
70 r.end = range.start;
71 let new_range = Range::new(range.end, old_end);
72 if r.is_empty() && new_range.is_empty() {
73 drain_range = i..i + 1;
74 break;
75 }
76 if r.is_empty() {
77 self.ranges[i] = new_range;
78 break;
79 }
80 if !new_range.is_empty() {
81 self.ranges.insert(i + 1, new_range);
82 }
83 break;
84 }
85 if range.contains_range(r) {
86 if i < drain_range.start {
87 drain_range.start = i;
88 }
89 if i + 1 > drain_range.end {
90 drain_range.end = i + 1;
91 }
92 } else if contains_start {
93 r.end = range.start;
94 drain_range.start = if r.is_empty() { i } else { i + 1 };
95 }
96 if contains_end {
97 r.start = range.end;
98 drain_range.end = if r.is_empty() { i + 1 } else { i };
99 break;
100 }
101 }
102 if !drain_range.is_empty() {
103 self.ranges.drain(drain_range);
104 }
105 }
106
107 pub fn overlap(&self, range: &Range) -> bool {
108 if range.is_empty() {
109 return false;
110 }
111 for r in &self.ranges {
112 if r.start < range.end && range.start < r.end {
113 return true;
114 }
115 }
116 false
117 }
118
119 pub fn clear(&mut self) {
120 self.ranges.clear();
121 }
122
123 pub fn enclosing_range(&self) -> Option<Range> {
124 if self.ranges.is_empty() {
125 return None;
126 }
127 let start = self.ranges[0].start;
128 let end = self.ranges[self.ranges.len() - 1].end;
129 Some(Range::new(start, end))
130 }
131
132 pub fn count(&self) -> u64 {
133 self.ranges.iter().map(|range| range.end - range.start).sum()
134 }
135
136 pub fn contains_index(&self, index: u64) -> bool {
137 let i = match self.ranges.binary_search_by(|range| range.start.cmp(&index)) {
138 Ok(i) => i,
139 Err(i) => i.saturating_sub(1),
140 };
141 self.ranges.get(i).map(|range| range.contains(index)).unwrap_or(false)
142 }
143
144 pub fn as_slice(&self) -> &[Range] {
145 self.ranges.as_slice()
146 }
147
148 pub fn encoded_len(&self) -> usize {
149 let len = self.ranges.len();
150 Compact::<u64>::compact_len(&(len as u64)) +
151 self.ranges.iter().map(|range| range.encoded_len()).sum::<usize>()
152 }
153}
154
155impl AsRef<[Range]> for RangeSet {
156 fn as_ref(&self) -> &[Range] {
157 &self.ranges[..]
158 }
159}
160
161impl core::fmt::Debug for RangeSet {
162 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
163 f.debug_list().entries(self.ranges.iter()).finish()
164 }
165}
166
167impl FromIterator<Range> for RangeSet {
168 fn from_iter<I: IntoIterator<Item = Range>>(items: I) -> Self {
169 let iter = items.into_iter();
170 let (min_size, max_size) = iter.size_hint();
171 let mut set = RangeSet::with_capacity(max_size.unwrap_or(min_size));
172 set.extend(iter);
173 set
174 }
175}
176
177impl Extend<Range> for RangeSet {
178 fn extend<I: IntoIterator<Item = Range>>(&mut self, iter: I) {
179 for range in iter.into_iter() {
180 self.insert(range);
181 }
182 }
183}
184
185impl Decode for RangeSet {
186 fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
187 let ranges = Vec::<Range>::decode(input)?;
188 if !validate_ranges(&ranges) {
189 return Err("RangeSet: out-of-order/overlapping/empty ranges".into());
190 }
191 Ok(Self { ranges })
192 }
193}
194
195fn validate_ranges(ranges: &[Range]) -> bool {
196 if ranges.iter().any(|r| r.is_empty()) {
197 return false;
198 }
199 for window in ranges.windows(2) {
200 let a = &window[0];
201 let b = &window[1];
202 if b.start <= a.start || b.start <= a.end {
203 return false;
204 }
205 }
206 true
207}
208
209#[derive(Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
210pub struct Range {
211 #[codec(compact)]
213 pub start: u64,
214 #[codec(compact)]
216 pub end: u64,
217}
218
219impl Range {
220 pub const fn new(start: u64, end: u64) -> Self {
221 Self { start, end }
222 }
223
224 pub const fn is_empty(&self) -> bool {
225 self.start >= self.end
226 }
227
228 pub fn contains_range(&self, other: &Range) -> bool {
232 !other.is_empty() &&
233 (self.start..self.end).contains(&other.start) &&
234 (self.start..=self.end).contains(&other.end)
235 }
236
237 pub const fn contains(&self, i: u64) -> bool {
238 self.start <= i && i < self.end
239 }
240
241 pub fn encoded_len(&self) -> usize {
242 Compact::<u64>::compact_len(&self.start) + Compact::<u64>::compact_len(&self.end)
243 }
244}
245
246impl core::fmt::Display for Range {
247 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
248 if self.start.saturating_add(1) == self.end {
249 write!(f, "{}", self.start)
250 } else {
251 write!(f, "{}..{}", self.start, self.end)
252 }
253 }
254}
255
256impl core::fmt::Debug for Range {
257 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
258 core::fmt::Display::fmt(self, f)
259 }
260}
261
262#[cfg(test)]
263mod tests {
264 use super::*;
265 use rand::{seq::SliceRandom, Rng};
266
267 #[test]
268 fn insert_works() {
269 let mut ranges = RangeSet::new();
270 assert_eq!(0, ranges.as_ref().len());
271 ranges.insert(Range::new(0, 0));
272 assert_eq!(0, ranges.as_ref().len());
273 ranges.insert(Range::new(0, 1));
274 assert_eq!(1, ranges.as_ref().len());
275 ranges.insert(Range::new(0, 1));
276 assert_eq!(1, ranges.as_ref().len());
277 ranges.insert(Range::new(2, 3));
278 assert_eq!([Range::new(0, 1), Range::new(2, 3)].as_slice(), ranges.as_ref());
279 ranges.insert(Range::new(1, 2));
280 assert_eq!([Range::new(0, 3)].as_slice(), ranges.as_ref());
281 ranges.insert(Range::new(3, 10));
282 assert_eq!([Range::new(0, 10)].as_slice(), ranges.as_ref());
283 }
284
285 #[test]
286 fn remove_works() {
287 let mut ranges = RangeSet::new();
288 assert_eq!(0, ranges.as_ref().len());
289 ranges.insert(Range::new(0, 1));
291 assert_eq!(1, ranges.as_ref().len());
292 ranges.remove(&Range::new(0, 1));
293 assert_eq!(0, ranges.as_ref().len());
294 ranges.insert(Range::new(0, 4));
296 ranges.remove(&Range::new(1, 3));
297 assert_eq!([Range::new(0, 1), Range::new(3, 4)].as_slice(), ranges.as_ref());
298 ranges.clear();
300 ranges.insert(Range::new(0, 4));
301 ranges.remove(&Range::new(0, 1));
302 assert_eq!([Range::new(1, 4)].as_slice(), ranges.as_ref());
303 ranges.clear();
305 ranges.insert(Range::new(0, 4));
306 ranges.remove(&Range::new(3, 4));
307 assert_eq!([Range::new(0, 3)].as_slice(), ranges.as_ref());
308 ranges.clear();
310 ranges.insert(Range::new(1, 4));
311 ranges.remove(&Range::new(0, 5));
312 assert_eq!(([] as [Range; 0]).as_slice(), ranges.as_ref());
313 ranges.clear();
315 ranges.insert(Range::new(1, 4));
316 ranges.remove(&Range::new(0, 2));
317 assert_eq!([Range::new(2, 4)].as_slice(), ranges.as_ref());
318 ranges.clear();
320 ranges.insert(Range::new(1, 4));
321 ranges.remove(&Range::new(3, 5));
322 assert_eq!([Range::new(1, 3)].as_slice(), ranges.as_ref());
323 }
324
325 #[test]
326 fn insert_remove_random() {
327 let mut rng = rand::rng();
328 for _ in 0..1000 {
329 let mut ranges = Vec::new();
330 let mut offset = 0;
331 for _ in 0..10 {
332 let start = offset;
333 let end = rng.random_range(start..=start + 20);
334 offset = end;
335 ranges.push(Range::new(start, end));
336 }
337 ranges.shuffle(&mut rng);
339 let mut set = RangeSet::new();
340 for range in ranges.iter() {
341 set.insert(range.clone());
342 }
343 assert_eq!(1, set.as_ref().len());
344 assert_eq!(&[Range::new(0, offset)], set.as_ref());
345 ranges.shuffle(&mut rng);
347 for range in ranges.iter() {
348 set.remove(range);
349 }
350 assert_eq!(0, set.as_ref().len());
351 }
352 }
353
354 #[test]
355 fn remove_reverts_insert() {
356 let mut rng = rand::rng();
357 for _ in 0..1000 {
358 let mut ranges = RangeSet::new();
359 {
360 let mut offset = 0;
361 for _ in 0..10 {
362 let start = rng.random_range(offset..=20);
363 let end = rng.random_range(start..=20);
364 offset = end;
365 ranges.insert(Range::new(start, end));
366 }
367 }
368 let range = {
369 let start = rng.random_range(0..=20);
370 Range::new(start, rng.random_range(start..=20))
371 };
372 if ranges.overlap(&range) {
373 continue;
375 }
376 let expected = ranges.clone();
377 ranges.insert(range.clone());
378 let middle = ranges.clone();
379 ranges.remove(&range);
380 assert_eq!(expected, ranges,
381 "ranges = {expected:?}, insert/remove {range:?}, after insert = {middle:?}, after remove = {ranges:?}");
382 }
383 }
384
385 #[test]
386 fn insert_reverts_remove() {
387 let mut rng = rand::rng();
388 for _ in 0..1000 {
389 let mut ranges = RangeSet::new();
390 {
391 let mut offset = 0;
392 for _ in 0..10 {
393 let start = rng.random_range(offset..=20);
394 let end = rng.random_range(start..=20);
395 offset = end;
396 ranges.insert(Range::new(start, end));
397 }
398 }
399 let range = {
400 let start = rng.random_range(0..=20);
401 Range::new(start, rng.random_range(start..=20))
402 };
403 if !ranges.as_ref().iter().any(|r| r.contains_range(&range)) {
404 continue;
407 }
408 let expected = ranges.clone();
409 ranges.remove(&range);
410 let middle = ranges.clone();
411 ranges.insert(range.clone());
412 assert_eq!(expected, ranges,
413 "ranges = {expected:?}, remove/insert {range:?}, after remove = {middle:?}, after insert = {ranges:?}");
414 }
415 }
416
417 #[test]
418 fn validate_works() {
419 assert!(!validate_ranges(&[Range::new(0, 0)]));
420 assert!(!validate_ranges(&[Range::new(0, 1), Range::new(0, 2)]));
421 assert!(!validate_ranges(&[Range::new(0, 2), Range::new(1, 3)]));
422 assert!(!validate_ranges(&[Range::new(0, 1), Range::new(1, 2)]));
423 assert!(!validate_ranges(&[Range::new(2, 3), Range::new(0, 1)]));
424 assert!(validate_ranges(&[Range::new(0, 1), Range::new(2, 3)]));
425 }
426
427 #[test]
428 fn encoded_len_works() {
429 let mut rng = rand::rng();
430 for _ in 0..1000 {
431 let mut ranges = RangeSet::new();
432 {
433 let mut offset = 0;
434 for _ in 0..10 {
435 let start = rng.random_range(offset..=20);
436 let end = rng.random_range(start..=20);
437 offset = end;
438 ranges.insert(Range::new(start, end));
439 }
440 }
441 let actual = ranges.encoded_len();
442 let expected = ranges.encode().len();
443 assert_eq!(expected, actual);
444 }
445 }
446}