1use std::{
2 fmt::Debug,
3 iter::Sum,
4 ops::{Add, AddAssign, Range, Sub},
5};
6
7#[derive(Debug)]
8pub struct RangeAllocator<T> {
9 initial_range: Range<T>,
11 free_ranges: Vec<Range<T>>,
15}
16
17#[derive(Clone, Debug, PartialEq)]
18pub struct RangeAllocationError<T> {
19 pub fragmented_free_length: T,
20}
21
22impl<T> RangeAllocator<T>
23where
24 T: Clone + Copy + Add<Output = T> + AddAssign + Sub<Output = T> + Eq + PartialOrd + Debug,
25{
26 pub fn new(range: Range<T>) -> Self {
27 RangeAllocator {
28 initial_range: range.clone(),
29 free_ranges: vec![range],
30 }
31 }
32
33 pub fn initial_range(&self) -> &Range<T> {
34 &self.initial_range
35 }
36
37 pub fn grow_to(&mut self, new_end: T) {
38 let initial_range_end = self.initial_range.end;
39 if let Some(last_range) = self
40 .free_ranges
41 .last_mut()
42 .filter(|last_range| last_range.end == initial_range_end)
43 {
44 last_range.end = new_end;
45 } else {
46 self.free_ranges.push(self.initial_range.end..new_end);
47 }
48
49 self.initial_range.end = new_end;
50 }
51
52 pub fn allocate_range(&mut self, length: T) -> Result<Range<T>, RangeAllocationError<T>> {
53 assert_ne!(length + length, length);
54 let mut best_fit: Option<(usize, Range<T>)> = None;
55
56 #[allow(clippy::eq_op)]
61 let mut fragmented_free_length = length - length;
62 for (index, range) in self.free_ranges.iter().cloned().enumerate() {
63 let range_length = range.end - range.start;
64 fragmented_free_length += range_length;
65 if range_length < length {
66 continue;
67 } else if range_length == length {
68 best_fit = Some((index, range));
70 break;
71 }
72 best_fit = Some(match best_fit {
73 Some((best_index, best_range)) => {
74 if range_length < best_range.end - best_range.start {
76 (index, range)
77 } else {
78 (best_index, best_range.clone())
79 }
80 }
81 None => (index, range),
82 });
83 }
84 match best_fit {
85 Some((index, range)) => {
86 if range.end - range.start == length {
87 self.free_ranges.remove(index);
88 } else {
89 self.free_ranges[index].start += length;
90 }
91 Ok(range.start..(range.start + length))
92 }
93 None => Err(RangeAllocationError {
94 fragmented_free_length,
95 }),
96 }
97 }
98
99 pub fn free_range(&mut self, range: Range<T>) {
100 assert!(self.initial_range.start <= range.start && range.end <= self.initial_range.end);
101 assert!(range.start < range.end);
102
103 let i = self
105 .free_ranges
106 .iter()
107 .position(|r| r.start > range.start)
108 .unwrap_or(self.free_ranges.len());
109
110 if i > 0 && range.start == self.free_ranges[i - 1].end {
113 self.free_ranges[i - 1].end =
115 if i < self.free_ranges.len() && range.end == self.free_ranges[i].start {
116 let right = self.free_ranges.remove(i);
118 right.end
119 } else {
120 range.end
121 };
122
123 return;
124 } else if i < self.free_ranges.len() && range.end == self.free_ranges[i].start {
125 self.free_ranges[i].start = if i > 0 && range.start == self.free_ranges[i - 1].end {
127 let left = self.free_ranges.remove(i - 1);
129 left.start
130 } else {
131 range.start
132 };
133
134 return;
135 }
136
137 assert!(
139 (i == 0 || self.free_ranges[i - 1].end < range.start)
140 && (i >= self.free_ranges.len() || range.end < self.free_ranges[i].start)
141 );
142
143 self.free_ranges.insert(i, range);
144 }
145
146 pub fn allocated_ranges(&self) -> impl Iterator<Item = Range<T>> + '_ {
148 let first = match self.free_ranges.first() {
149 Some(Range { ref start, .. }) if *start > self.initial_range.start => {
150 Some(self.initial_range.start..*start)
151 }
152 None => Some(self.initial_range.clone()),
153 _ => None,
154 };
155
156 let last = match self.free_ranges.last() {
157 Some(Range { end, .. }) if *end < self.initial_range.end => {
158 Some(*end..self.initial_range.end)
159 }
160 _ => None,
161 };
162
163 let mid = self
164 .free_ranges
165 .iter()
166 .zip(self.free_ranges.iter().skip(1))
167 .map(|(ra, rb)| ra.end..rb.start);
168
169 first.into_iter().chain(mid).chain(last)
170 }
171
172 pub fn reset(&mut self) {
173 self.free_ranges.clear();
174 self.free_ranges.push(self.initial_range.clone());
175 }
176
177 pub fn is_empty(&self) -> bool {
178 self.free_ranges.len() == 1 && self.free_ranges[0] == self.initial_range
179 }
180}
181
182impl<T: Copy + Sub<Output = T> + Sum> RangeAllocator<T> {
183 pub fn total_available(&self) -> T {
184 self.free_ranges
185 .iter()
186 .map(|range| range.end - range.start)
187 .sum()
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 #[test]
196 fn test_basic_allocation() {
197 let mut alloc = RangeAllocator::new(0..10);
198 assert_eq!(alloc.allocate_range(4), Ok(0..4));
200 assert!(alloc.allocated_ranges().eq(std::iter::once(0..4)));
201 alloc.free_range(0..4);
203 assert_eq!(alloc.free_ranges, vec![0..10]);
205 assert!(alloc.allocated_ranges().eq(std::iter::empty()));
206 }
207
208 #[test]
209 fn test_out_of_space() {
210 let mut alloc = RangeAllocator::new(0..10);
211 assert_eq!(alloc.allocate_range(10), Ok(0..10));
213 assert!(alloc.allocated_ranges().eq(std::iter::once(0..10)));
214 assert!(alloc.allocate_range(4).is_err());
215 alloc.free_range(0..10);
216 }
217
218 #[test]
219 fn test_grow() {
220 let mut alloc = RangeAllocator::new(0..11);
221 assert_eq!(alloc.allocate_range(10), Ok(0..10));
223 assert!(alloc.allocated_ranges().eq(std::iter::once(0..10)));
224 assert!(alloc.allocate_range(4).is_err());
225 alloc.grow_to(20);
226 assert_eq!(alloc.allocate_range(4), Ok(10..14));
227 alloc.free_range(0..14);
228 }
229
230 #[test]
231 fn test_grow_with_hole_at_start() {
232 let mut alloc = RangeAllocator::new(0..6);
233
234 assert_eq!(alloc.allocate_range(3), Ok(0..3));
235 assert_eq!(alloc.allocate_range(3), Ok(3..6));
236 alloc.free_range(0..3);
237
238 alloc.grow_to(9);
239 assert_eq!(alloc.allocated_ranges().collect::<Vec<_>>(), [3..6]);
240 }
241 #[test]
242 fn test_grow_with_hole_in_middle() {
243 let mut alloc = RangeAllocator::new(0..6);
244
245 assert_eq!(alloc.allocate_range(2), Ok(0..2));
246 assert_eq!(alloc.allocate_range(2), Ok(2..4));
247 assert_eq!(alloc.allocate_range(2), Ok(4..6));
248 alloc.free_range(2..4);
249
250 alloc.grow_to(9);
251 assert_eq!(alloc.allocated_ranges().collect::<Vec<_>>(), [0..2, 4..6]);
252 }
253
254 #[test]
255 fn test_dont_use_block_that_is_too_small() {
256 let mut alloc = RangeAllocator::new(0..10);
257 assert_eq!(alloc.allocate_range(3), Ok(0..3));
259 assert_eq!(alloc.allocate_range(3), Ok(3..6));
260 assert_eq!(alloc.allocate_range(3), Ok(6..9));
261 alloc.free_range(3..6);
262 assert_eq!(alloc.free_ranges, vec![3..6, 9..10]);
263 assert_eq!(
264 alloc.allocated_ranges().collect::<Vec<Range<i32>>>(),
265 vec![0..3, 6..9]
266 );
267 assert_eq!(alloc.allocate_range(3), Ok(3..6));
269 }
270
271 #[test]
272 fn test_free_blocks_in_middle() {
273 let mut alloc = RangeAllocator::new(0..100);
274 assert_eq!(alloc.allocate_range(10), Ok(0..10));
276 assert_eq!(alloc.allocate_range(10), Ok(10..20));
277 assert_eq!(alloc.allocate_range(10), Ok(20..30));
278 assert_eq!(alloc.allocate_range(10), Ok(30..40));
279 assert_eq!(alloc.allocate_range(10), Ok(40..50));
280 assert_eq!(alloc.allocate_range(10), Ok(50..60));
281 assert_eq!(alloc.allocate_range(10), Ok(60..70));
282 assert_eq!(alloc.allocate_range(10), Ok(70..80));
283 assert_eq!(alloc.allocate_range(10), Ok(80..90));
284 assert_eq!(alloc.allocate_range(10), Ok(90..100));
285 assert_eq!(alloc.free_ranges, vec![]);
286 assert!(alloc.allocated_ranges().eq(std::iter::once(0..100)));
287 alloc.free_range(10..20);
288 alloc.free_range(30..40);
289 alloc.free_range(50..60);
290 alloc.free_range(70..80);
291 alloc.free_range(90..100);
292 assert_eq!(
294 alloc.free_ranges,
295 vec![10..20, 30..40, 50..60, 70..80, 90..100]
296 );
297 assert_eq!(
298 alloc.allocated_ranges().collect::<Vec<Range<i32>>>(),
299 vec![0..10, 20..30, 40..50, 60..70, 80..90]
300 );
301 assert_eq!(alloc.allocate_range(6), Ok(10..16));
303 assert_eq!(alloc.allocate_range(6), Ok(30..36));
304 assert_eq!(alloc.allocate_range(6), Ok(50..56));
305 assert_eq!(alloc.allocate_range(6), Ok(70..76));
306 assert_eq!(alloc.allocate_range(6), Ok(90..96));
307 assert_eq!(
309 alloc.free_ranges,
310 vec![16..20, 36..40, 56..60, 76..80, 96..100]
311 );
312 assert_eq!(
313 alloc.allocated_ranges().collect::<Vec<Range<i32>>>(),
314 vec![0..16, 20..36, 40..56, 60..76, 80..96]
315 );
316 assert_eq!(alloc.allocate_range(4), Ok(16..20));
318 assert_eq!(alloc.allocate_range(4), Ok(36..40));
319 assert_eq!(alloc.allocate_range(4), Ok(56..60));
320 assert_eq!(alloc.allocate_range(4), Ok(76..80));
321 assert_eq!(alloc.allocate_range(4), Ok(96..100));
322 assert_eq!(alloc.free_ranges, vec![]);
324 assert!(alloc.allocated_ranges().eq(std::iter::once(0..100)));
325 }
326
327 #[test]
328 fn test_ignore_block_if_another_fits_better() {
329 let mut alloc = RangeAllocator::new(0..10);
330 assert_eq!(alloc.allocate_range(3), Ok(0..3));
333 assert_eq!(alloc.allocate_range(3), Ok(3..6));
334 assert_eq!(alloc.allocate_range(3), Ok(6..9));
335 alloc.free_range(3..6);
336 assert_eq!(alloc.free_ranges, vec![3..6, 9..10]);
337 assert_eq!(
338 alloc.allocated_ranges().collect::<Vec<Range<i32>>>(),
339 vec![0..3, 6..9]
340 );
341 assert_eq!(alloc.allocate_range(1), Ok(9..10));
344 }
345
346 #[test]
347 fn test_merge_neighbors() {
348 let mut alloc = RangeAllocator::new(0..9);
349 assert_eq!(alloc.allocate_range(3), Ok(0..3));
350 assert_eq!(alloc.allocate_range(3), Ok(3..6));
351 assert_eq!(alloc.allocate_range(3), Ok(6..9));
352 alloc.free_range(0..3);
353 alloc.free_range(6..9);
354 alloc.free_range(3..6);
355 assert_eq!(alloc.free_ranges, vec![0..9]);
356 assert!(alloc.allocated_ranges().eq(std::iter::empty()));
357 }
358}