1use std::cmp::{self, Ordering};
2use std::collections::btree_set::{self, Iter};
3use std::collections::BTreeSet;
4use std::fmt;
5
6#[derive(Debug, Clone, Default)]
7pub struct FreeRanges {
8 free_list: BTreeSet<Range>,
9}
10
11impl FreeRanges {
12 #[inline]
14 pub fn new() -> Self {
15 Default::default()
16 }
17
18 #[inline]
20 pub fn with_all_free() -> FreeRanges {
21 FreeRanges::with_initial_range(Range {
22 min: 0,
23 max: std::usize::MAX,
24 })
25 }
26
27 #[inline]
29 pub fn with_initial_range(range: Range) -> FreeRanges {
30 let mut ranges = FreeRanges::new();
31 ranges.free_list.insert(range);
32 ranges
33 }
34
35 #[inline]
37 pub fn free_ranges(&self) -> Iter<Range> {
38 self.free_list.iter()
39 }
40
41 #[inline]
45 pub fn free_ranges_after(&self, start: usize) -> btree_set::Range<Range> {
46 self.free_list.range(Range::id(start)..)
47 }
48
49 #[inline]
53 pub fn free_ranges_before(&self, end: usize) -> btree_set::Range<Range> {
54 use std::collections::Bound;
55 self.free_list
56 .range((Bound::Unbounded, Bound::Included(Range::id(end))))
57 }
58
59 #[inline]
61 pub fn set_free(&mut self, index: usize) -> bool {
62 if self.free_list.contains(&Range::id(index)) {
63 return false;
64 }
65
66 let range = Range::id(index);
67 self.do_set_free(range);
68
69 true
70 }
71
72 #[inline]
73 pub fn set_range_free(&mut self, range: Range) -> bool {
74 let front_check = self.free_list.get(&Range::id(range.min)).cloned();
75 let back_check = self.free_list.get(&Range::id(range.max)).cloned();
76
77 match (front_check, back_check) {
78 (Some(front_check), Some(back_check)) => {
79 if front_check == back_check {
80 return false;
81 }
82 }
83 _ => (),
84 }
85
86 self.do_set_free(range);
87
88 true
89 }
90
91 fn do_set_free(&mut self, range: Range) {
92 let range_front = if range.min > 0 {
93 range.push_front()
94 } else {
95 range
96 };
97 let range_back = range.push_back();
98 let combine_front = self.free_list.get(&range_front).cloned();
99 let combine_back = self.free_list.get(&range_back).cloned();
100
101 match (combine_front, combine_back) {
102 (Some(front_range), Some(back_range)) => {
103 let combined = front_range.merge(range).merge(back_range);
104
105 self.free_list.remove(&front_range);
106 self.free_list.remove(&back_range);
107 self.free_list.insert(combined);
108 }
109 (Some(front_range), None) => {
110 let combined = front_range.merge(range);
111
112 self.free_list.remove(&front_range);
113 self.free_list.insert(combined);
114 }
115 (None, Some(back_range)) => {
116 let combined = back_range.merge(range);
117
118 self.free_list.remove(&back_range);
119 self.free_list.insert(combined);
120 }
121 (None, None) => {
122 self.free_list.insert(range);
123 }
124 }
125 }
126
127 #[inline]
129 pub fn set_used(&mut self, index: usize) -> bool {
130 let range = Range::id(index);
131
132 if let Some(&intersecting) = self.free_list.get(&range) {
133 self.free_list.remove(&intersecting);
134 let (left, right) = intersecting.split(index);
135 if !left.empty() {
136 self.free_list.insert(left);
137 }
138 if !right.empty() {
139 self.free_list.insert(right);
140 }
141 true
142 } else {
143 false
144 }
145 }
146
147 #[inline]
149 pub fn first(&self) -> Option<usize> {
150 self.free_list.iter().nth(0).map(|r| r.min)
151 }
152
153 #[inline]
155 pub fn set_first_used(&mut self) -> Option<usize> {
156 if let Some(&first) = self.free_list.iter().nth(0) {
157 self.free_list.remove(&first);
158 let range = first.pop_front();
159 if !range.empty() {
160 self.free_list.insert(range);
161 }
162 return Some(first.min);
163 }
164
165 None
166 }
167
168 #[inline]
170 pub fn last(&self) -> Option<usize> {
171 self.free_list.iter().rev().nth(0).map(|r| r.max)
172 }
173
174 #[inline]
176 pub fn set_last_used(&mut self) -> Option<usize> {
177 if let Some(&last) = self.free_list.iter().rev().nth(0) {
178 self.free_list.remove(&last);
179 if last.max != 0 {
180 let range = last.pop_back();
181 if !range.empty() {
182 self.free_list.insert(range);
183 }
184 }
185 return Some(last.max);
186 }
187
188 None
189 }
190
191 #[inline]
192 pub fn remove_last_contiguous(&mut self) {
193 if let Some(last) = self.last() {
194 self.free_list.remove(&Range::id(last));
195 }
196 }
197
198 #[inline]
199 pub fn is_free(&self, index: usize) -> bool {
200 let range = Range::id(index);
201 self.free_list.get(&range).is_some()
202 }
203
204 #[inline]
205 pub fn clear(&mut self) {
206 self.free_list.clear();
207 }
208}
209
210const EMPTY_RANGE: Range = Range { min: 1, max: 0 };
211
212#[derive(Copy, Clone)]
213pub struct Range {
214 pub min: usize,
215 pub max: usize,
216}
217
218impl fmt::Debug for Range {
219 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
220 write!(fmt, "({}...{})", self.min, self.max)
221 }
222}
223
224impl Range {
225 #[inline]
226 pub fn id(id: usize) -> Self {
227 Range { min: id, max: id }
228 }
229
230 #[inline]
231 pub fn empty(self) -> bool {
232 self.min > self.max
233 }
234
235 #[inline]
236 pub fn push_front(mut self) -> Self {
237 self.min -= 1;
238 self
239 }
240
241 #[inline]
242 pub fn push_back(mut self) -> Self {
243 self.max += 1;
244 self
245 }
246
247 #[inline]
248 pub fn pop_front(mut self) -> Self {
249 self.min += 1;
250 self
251 }
252
253 #[inline]
254 pub fn pop_back(mut self) -> Self {
255 self.max -= 1;
256 self
257 }
258
259 #[inline]
260 pub fn merge(self, other: Self) -> Self {
261 Range {
262 min: cmp::min(self.min, other.min),
263 max: cmp::max(self.max, other.max),
264 }
265 }
266
267 #[inline]
268 pub fn contains(&self, value: usize) -> bool {
269 value >= self.min && value <= self.max
270 }
271
272 #[inline]
273 pub fn split(self, middle: usize) -> (Range, Range) {
274 if middle == 0 {
275 return (EMPTY_RANGE, self.pop_front());
276 }
277
278 let left = Range {
279 min: self.min,
280 max: middle - 1,
281 };
282 let right = Range {
283 min: middle + 1,
284 max: self.max,
285 };
286 (left, right)
287 }
288}
289
290impl PartialEq for Range {
291 #[inline]
292 fn eq(&self, other: &Self) -> bool {
293 self.cmp(other) == Ordering::Equal
294 }
295}
296
297impl Eq for Range {}
298
299impl PartialOrd for Range {
300 #[inline]
301 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
302 Some(self.cmp(other))
303 }
304}
305
306impl Ord for Range {
307 #[inline]
308 fn cmp(&self, other: &Self) -> Ordering {
309 if self.contains(other.min) || self.contains(other.max) || other.contains(self.min)
310 || other.contains(self.max)
311 {
312 return Ordering::Equal;
313 }
314
315 self.min.cmp(&other.min)
316 }
317}