1use core::cmp::Ordering;
8
9#[derive(Clone, Copy, PartialEq, Eq, Debug)]
11pub struct Range {
12 pub lo: u64,
13 pub hi: u64,
14}
15
16impl Range {
17 #[inline]
18 pub fn new(lo: u64, hi: u64) -> Self {
19 debug_assert!(hi >= lo, "range {lo}..{hi} inverted");
20 Range { lo, hi }
21 }
22
23 #[inline]
24 pub fn len(&self) -> u64 {
25 self.hi.saturating_sub(self.lo)
26 }
27
28 #[inline]
29 pub fn is_empty(&self) -> bool {
30 self.hi <= self.lo
31 }
32}
33
34#[derive(Clone, Default, Debug)]
36pub struct IntervalSet {
37 iv: Vec<Range>,
38}
39
40impl IntervalSet {
41 pub fn new() -> Self {
42 IntervalSet { iv: Vec::new() }
43 }
44
45 pub fn full(size: u64) -> Self {
47 if size == 0 {
48 return Self::new();
49 }
50 IntervalSet {
51 iv: vec![Range::new(0, size)],
52 }
53 }
54
55 pub fn is_empty(&self) -> bool {
56 self.iv.is_empty()
57 }
58
59 pub fn len(&self) -> usize {
60 self.iv.len()
61 }
62
63 pub fn ranges(&self) -> &[Range] {
64 &self.iv
65 }
66
67 pub fn total(&self) -> u64 {
69 self.iv.iter().map(|r| r.len()).sum()
70 }
71
72 pub fn take_front(&mut self, n: u64) -> Option<Range> {
77 if n == 0 {
78 return None;
79 }
80 let first = *self.iv.first()?;
81 if first.len() <= n {
82 self.iv.remove(0);
83 Some(first)
84 } else {
85 let out = Range::new(first.lo, first.lo + n);
86 self.iv[0] = Range::new(first.lo + n, first.hi);
87 Some(out)
88 }
89 }
90
91 pub fn insert(&mut self, r: Range) {
95 if r.is_empty() {
96 return;
97 }
98 let pos = self
99 .iv
100 .binary_search_by(|p| {
101 if p.hi < r.lo {
102 Ordering::Less
103 } else if p.lo > r.hi {
104 Ordering::Greater
105 } else {
106 Ordering::Equal
107 }
108 })
109 .unwrap_or_else(|e| e);
110
111 let mut lo = r.lo;
113 let mut hi = r.hi;
114 let mut end = pos;
115 while end < self.iv.len() && self.iv[end].lo <= hi {
116 lo = lo.min(self.iv[end].lo);
117 hi = hi.max(self.iv[end].hi);
118 end += 1;
119 }
120 let mut start = pos;
121 while start > 0 && self.iv[start - 1].hi >= lo {
122 start -= 1;
123 lo = lo.min(self.iv[start].lo);
124 hi = hi.max(self.iv[start].hi);
125 }
126 self.iv.splice(start..end, [Range::new(lo, hi)]);
127 }
128
129 pub fn remove(&mut self, lo: u64, hi: u64) {
131 if hi <= lo {
132 return;
133 }
134 let mut out: Vec<Range> = Vec::with_capacity(self.iv.len() + 1);
135 for r in self.iv.iter().copied() {
136 if r.hi <= lo || r.lo >= hi {
137 out.push(r);
138 continue;
139 }
140 if r.lo < lo {
141 out.push(Range::new(r.lo, lo));
142 }
143 if r.hi > hi {
144 out.push(Range::new(hi, r.hi));
145 }
146 }
147 self.iv = out;
148 }
149
150 pub fn invariant_holds(&self) -> bool {
153 for w in self.iv.windows(2) {
154 if w[0].hi >= w[1].lo || w[0].is_empty() {
155 return false;
156 }
157 }
158 self.iv.last().map(|r| !r.is_empty()).unwrap_or(true)
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 fn take_front_splits_and_preserves_total() {
168 let mut s = IntervalSet::full(1000);
169 let a = s.take_front(300).unwrap();
170 assert_eq!((a.lo, a.hi), (0, 300));
171 assert_eq!(s.total(), 700);
172 let b = s.take_front(900).unwrap();
173 assert_eq!((b.lo, b.hi), (300, 1000));
174 assert!(s.is_empty());
175 assert!(s.take_front(10).is_none());
176 }
177
178 #[test]
179 fn insert_coalesces_adjacent_and_overlapping() {
180 let mut s = IntervalSet::new();
181 s.insert(Range::new(10, 20));
182 s.insert(Range::new(20, 30)); assert_eq!(s.len(), 1);
184 assert_eq!(s.total(), 20);
185 s.insert(Range::new(25, 40)); assert_eq!(s.len(), 1);
187 assert_eq!(s.ranges()[0], Range::new(10, 40));
188 s.insert(Range::new(100, 110)); assert_eq!(s.len(), 2);
190 assert!(s.invariant_holds());
191 }
192
193 #[test]
194 fn insert_bridges_two_ranges() {
195 let mut s = IntervalSet::new();
196 s.insert(Range::new(0, 10));
197 s.insert(Range::new(20, 30));
198 s.insert(Range::new(10, 20));
199 assert_eq!(s.len(), 1);
200 assert_eq!(s.ranges()[0], Range::new(0, 30));
201 }
202
203 #[test]
204 fn remove_splits() {
205 let mut s = IntervalSet::full(100);
206 s.remove(30, 40);
207 assert_eq!(s.len(), 2);
208 assert_eq!(s.total(), 90);
209 assert!(s.invariant_holds());
210 }
211
212 #[test]
213 fn empty_and_degenerate_inserts_are_noops() {
214 let mut s = IntervalSet::new();
215 s.insert(Range::new(5, 5));
216 assert!(s.is_empty());
217 assert_eq!(IntervalSet::full(0).total(), 0);
218 }
219}