| /// Represents a set of `Size` values as a sorted list of ranges. | |
| /// | |
| /// These are (offset, length) pairs, and they are sorted and mutually disjoint, | |
| /// and never adjacent (i.e. there's always a gap between two of them). | |
| #[derive(Debug, Clone)] | |
| pub struct RangeSet<T>(pub Vec<(T, T)>); | |
| impl<T> RangeSet<T> | |
| where | |
| T: Copy + Ord + Default, | |
| T: core::ops::Add<Output = T>, | |
| T: core::ops::Sub<Output = T>, | |
| { | |
| pub fn new() -> Self { | |
| Self(Vec::new()) | |
| } | |
| pub fn add_range(&mut self, offset: T, size: T) { | |
| if size == T::default() { | |
| // No need to track empty ranges. | |
| return; | |
| } | |
| let v = &mut self.0; | |
| // We scan for a partition point where the left partition is all the elements that end | |
| // strictly before we start. Those are elements that are too "low" to merge with us. | |
| let idx = | |
| v.partition_point(|&(other_offset, other_size)| other_offset + other_size < offset); | |
| // Now we want to either merge with the first element of the second partition, or insert ourselves before that. | |
| if let Some(&(other_offset, other_size)) = v.get(idx) | |
| && offset + size >= other_offset | |
| { | |
| // Their end is >= our start (otherwise it would not be in the 2nd partition) and | |
| // our end is >= their start. This means we can merge the ranges. | |
| let new_start = other_offset.min(offset); | |
| let mut new_end = (other_offset + other_size).max(offset + size); | |
| // We grew to the right, so merge with overlapping/adjacent elements. | |
| // (We also may have grown to the left, but that can never make us adjacent with | |
| // anything there since we selected the first such candidate via `partition_point`.) | |
| let mut scan_right = 1; | |
| while let Some(&(next_offset, next_size)) = v.get(idx + scan_right) | |
| && new_end >= next_offset | |
| { | |
| // Increase our size to absorb the next element. | |
| new_end = new_end.max(next_offset + next_size); | |
| // Look at the next element. | |
| scan_right += 1; | |
| } | |
| // Update the element we grew. | |
| v[idx] = (new_start, new_end - new_start); | |
| // Remove the elements we absorbed (if any). | |
| if scan_right > 1 { | |
| drop(v.drain((idx + 1)..(idx + scan_right))); | |
| } | |
| } else { | |
| // Insert new element. | |
| v.insert(idx, (offset, size)); | |
| } | |
| } | |
| /// The ranges from `self` with any intersection with `other` removed. | |
| pub fn difference(&self, other: &Self) -> Self { | |
| let (a, b) = (self, other); | |
| let mut out = Vec::new(); | |
| let mut j = 0; | |
| for &(a_offset, a_size) in a.0.iter() { | |
| let mut cursor = a_offset; | |
| let a_end = a_offset + a_size; | |
| // Skip ranges of `b` that end before this range of `a` begins. | |
| // both sequences are sorted they cannot overlap any later range of `a` either. | |
| while let Some(&(b_offset, b_size)) = b.0.get(j) | |
| && b_offset + b_size <= cursor | |
| { | |
| j += 1; | |
| } | |
| // Carve out each range of `b` that overlaps this range of `a`. A range of `b` may extend | |
| // past `a_end` and overlap the next range of `a`, so leave `j` pointing at it. | |
| let mut k = j; | |
| while let Some(&(b_offset, b_size)) = b.0.get(k) | |
| && b_offset < a_end | |
| { | |
| if b_offset > cursor { | |
| out.push((cursor, b_offset)); | |
| } | |
| cursor = Ord::max(cursor, b_offset + b_size); | |
| k += 1; | |
| } | |
| // Keep the remainder of the `a`'s range. | |
| if cursor < a_end { | |
| out.push((cursor, a_end)); | |
| } | |
| } | |
| Self(out) | |
| } | |
| } |