corevm_host/
range_set.rs

1use alloc::vec::Vec;
2use codec::{Compact, CompactLen, Decode, Encode, Input, MaxEncodedLen};
3
4// TODO @ivan Proper B-Tree-based implementation would be useful for both CoreVM and PolkaVM.
5#[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	/// The start of the range (inclusive).
212	#[codec(compact)]
213	pub start: u64,
214	/// The end of the range (exclusive).
215	#[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	/// Returns `true` if `self` is fully contains `other`.
229	///
230	/// If `other` range is empty, returns `false`.
231	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		// Remove exact.
290		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		// Remove in the middle.
295		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		// Remove at the start.
299		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		// Remove at the end.
304		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		// Remove enclosing range.
309		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		// Remove overlaping-at-the-start range.
314		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		// Remove overlaping-at-the-end range.
319		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			// Insert all ranges in random order.
338			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			// Remove all ranges in random order.
346			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				// `remove` reverts `insert` only if there is no overlap
374				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				// `insert` reverts `remove` only if the new range is fully contained in one of the
405				// existing ranges
406				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}