1use alloc::vec::Vec;
2use codec::{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
149impl AsRef<[Range]> for RangeSet {
150 fn as_ref(&self) -> &[Range] {
151 &self.ranges[..]
152 }
153}
154
155impl core::fmt::Debug for RangeSet {
156 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
157 f.debug_list().entries(self.ranges.iter()).finish()
158 }
159}
160
161impl FromIterator<Range> for RangeSet {
162 fn from_iter<I: IntoIterator<Item = Range>>(items: I) -> Self {
163 let iter = items.into_iter();
164 let (min_size, max_size) = iter.size_hint();
165 let mut set = RangeSet::with_capacity(max_size.unwrap_or(min_size));
166 set.extend(iter);
167 set
168 }
169}
170
171impl Extend<Range> for RangeSet {
172 fn extend<I: IntoIterator<Item = Range>>(&mut self, iter: I) {
173 for range in iter.into_iter() {
174 self.insert(range);
175 }
176 }
177}
178
179impl Decode for RangeSet {
180 fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
181 let ranges = Vec::<Range>::decode(input)?;
182 if !validate_ranges(&ranges) {
183 return Err("RangeSet: out-of-order/overlapping/empty ranges".into());
184 }
185 Ok(Self { ranges })
186 }
187}
188
189fn validate_ranges(ranges: &[Range]) -> bool {
190 if ranges.iter().any(|r| r.is_empty()) {
191 return false;
192 }
193 for window in ranges.windows(2) {
194 let a = &window[0];
195 let b = &window[1];
196 if b.start <= a.start || b.start <= a.end {
197 return false;
198 }
199 }
200 true
201}
202
203#[derive(Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen)]
204pub struct Range {
205 #[codec(compact)]
207 pub start: u64,
208 #[codec(compact)]
210 pub end: u64,
211}
212
213impl Range {
214 pub const fn new(start: u64, end: u64) -> Self {
215 Self { start, end }
216 }
217
218 pub const fn is_empty(&self) -> bool {
219 self.start >= self.end
220 }
221
222 pub fn contains_range(&self, other: &Range) -> bool {
226 !other.is_empty() &&
227 (self.start..self.end).contains(&other.start) &&
228 (self.start..=self.end).contains(&other.end)
229 }
230
231 pub const fn contains(&self, i: u64) -> bool {
232 self.start <= i && i < self.end
233 }
234}
235
236impl core::fmt::Display for Range {
237 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
238 if self.start.saturating_add(1) == self.end {
239 write!(f, "{}", self.start)
240 } else {
241 write!(f, "{}..{}", self.start, self.end)
242 }
243 }
244}
245
246impl core::fmt::Debug for Range {
247 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
248 core::fmt::Display::fmt(self, f)
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255 use rand::{seq::SliceRandom, Rng};
256
257 #[test]
258 fn insert_works() {
259 let mut ranges = RangeSet::new();
260 assert_eq!(0, ranges.as_ref().len());
261 ranges.insert(Range::new(0, 0));
262 assert_eq!(0, ranges.as_ref().len());
263 ranges.insert(Range::new(0, 1));
264 assert_eq!(1, ranges.as_ref().len());
265 ranges.insert(Range::new(0, 1));
266 assert_eq!(1, ranges.as_ref().len());
267 ranges.insert(Range::new(2, 3));
268 assert_eq!([Range::new(0, 1), Range::new(2, 3)].as_slice(), ranges.as_ref());
269 ranges.insert(Range::new(1, 2));
270 assert_eq!([Range::new(0, 3)].as_slice(), ranges.as_ref());
271 ranges.insert(Range::new(3, 10));
272 assert_eq!([Range::new(0, 10)].as_slice(), ranges.as_ref());
273 }
274
275 #[test]
276 fn remove_works() {
277 let mut ranges = RangeSet::new();
278 assert_eq!(0, ranges.as_ref().len());
279 ranges.insert(Range::new(0, 1));
281 assert_eq!(1, ranges.as_ref().len());
282 ranges.remove(&Range::new(0, 1));
283 assert_eq!(0, ranges.as_ref().len());
284 ranges.insert(Range::new(0, 4));
286 ranges.remove(&Range::new(1, 3));
287 assert_eq!([Range::new(0, 1), Range::new(3, 4)].as_slice(), ranges.as_ref());
288 ranges.clear();
290 ranges.insert(Range::new(0, 4));
291 ranges.remove(&Range::new(0, 1));
292 assert_eq!([Range::new(1, 4)].as_slice(), ranges.as_ref());
293 ranges.clear();
295 ranges.insert(Range::new(0, 4));
296 ranges.remove(&Range::new(3, 4));
297 assert_eq!([Range::new(0, 3)].as_slice(), ranges.as_ref());
298 ranges.clear();
300 ranges.insert(Range::new(1, 4));
301 ranges.remove(&Range::new(0, 5));
302 assert_eq!(([] as [Range; 0]).as_slice(), ranges.as_ref());
303 ranges.clear();
305 ranges.insert(Range::new(1, 4));
306 ranges.remove(&Range::new(0, 2));
307 assert_eq!([Range::new(2, 4)].as_slice(), ranges.as_ref());
308 ranges.clear();
310 ranges.insert(Range::new(1, 4));
311 ranges.remove(&Range::new(3, 5));
312 assert_eq!([Range::new(1, 3)].as_slice(), ranges.as_ref());
313 }
314
315 #[test]
316 fn insert_remove_random() {
317 let mut rng = rand::rng();
318 for _ in 0..1000 {
319 let mut ranges = Vec::new();
320 let mut offset = 0;
321 for _ in 0..10 {
322 let start = offset;
323 let end = rng.random_range(start..=start + 20);
324 offset = end;
325 ranges.push(Range::new(start, end));
326 }
327 ranges.shuffle(&mut rng);
329 let mut set = RangeSet::new();
330 for range in ranges.iter() {
331 set.insert(range.clone());
332 }
333 assert_eq!(1, set.as_ref().len());
334 assert_eq!(&[Range::new(0, offset)], set.as_ref());
335 ranges.shuffle(&mut rng);
337 for range in ranges.iter() {
338 set.remove(range);
339 }
340 assert_eq!(0, set.as_ref().len());
341 }
342 }
343
344 #[test]
345 fn remove_reverts_insert() {
346 let mut rng = rand::rng();
347 for _ in 0..1000 {
348 let mut ranges = RangeSet::new();
349 {
350 let mut offset = 0;
351 for _ in 0..10 {
352 let start = rng.random_range(offset..=20);
353 let end = rng.random_range(start..=20);
354 offset = end;
355 ranges.insert(Range::new(start, end));
356 }
357 }
358 let range = {
359 let start = rng.random_range(0..=20);
360 Range::new(start, rng.random_range(start..=20))
361 };
362 if ranges.overlap(&range) {
363 continue;
365 }
366 let expected = ranges.clone();
367 ranges.insert(range.clone());
368 let middle = ranges.clone();
369 ranges.remove(&range);
370 assert_eq!(expected, ranges,
371 "ranges = {expected:?}, insert/remove {range:?}, after insert = {middle:?}, after remove = {ranges:?}");
372 assert_eq!(expected.encoded_size(), ranges.encoded_size());
373 }
374 }
375
376 #[test]
377 fn insert_reverts_remove() {
378 let mut rng = rand::rng();
379 for _ in 0..1000 {
380 let mut ranges = RangeSet::new();
381 {
382 let mut offset = 0;
383 for _ in 0..10 {
384 let start = rng.random_range(offset..=20);
385 let end = rng.random_range(start..=20);
386 offset = end;
387 ranges.insert(Range::new(start, end));
388 }
389 }
390 let range = {
391 let start = rng.random_range(0..=20);
392 Range::new(start, rng.random_range(start..=20))
393 };
394 if !ranges.as_ref().iter().any(|r| r.contains_range(&range)) {
395 continue;
398 }
399 let expected = ranges.clone();
400 ranges.remove(&range);
401 let middle = ranges.clone();
402 ranges.insert(range.clone());
403 assert_eq!(expected, ranges,
404 "ranges = {expected:?}, remove/insert {range:?}, after remove = {middle:?}, after insert = {ranges:?}");
405 }
406 }
407
408 #[test]
409 fn validate_works() {
410 assert!(!validate_ranges(&[Range::new(0, 0)]));
411 assert!(!validate_ranges(&[Range::new(0, 1), Range::new(0, 2)]));
412 assert!(!validate_ranges(&[Range::new(0, 2), Range::new(1, 3)]));
413 assert!(!validate_ranges(&[Range::new(0, 1), Range::new(1, 2)]));
414 assert!(!validate_ranges(&[Range::new(2, 3), Range::new(0, 1)]));
415 assert!(validate_ranges(&[Range::new(0, 1), Range::new(2, 3)]));
416 }
417}