Skip to main content

range_tree_rs/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![cfg_attr(docsrs, allow(unused_attributes))]
3
4//! This crate provides a range-tree implementation, intended to manage range section with btree.
5
6use core::{
7    cmp::Ordering,
8    fmt,
9    ops::{AddAssign, Bound, RangeBounds, SubAssign},
10};
11use embed_collections::btree::{BTreeMap, Cursor, Entry};
12use num_traits::*;
13
14/// consuming iterator of RangeTree
15pub use embed_collections::btree::IntoIter;
16/// Iterator of RangeTree (without bound)
17pub use embed_collections::btree::Iter;
18
19pub trait RangeTreeKey:
20    Unsigned + AddAssign + SubAssign + Ord + Copy + fmt::Debug + fmt::Display + Default + 'static
21{
22}
23
24impl<T> RangeTreeKey for T where
25    T: Unsigned
26        + AddAssign
27        + SubAssign
28        + Ord
29        + Copy
30        + fmt::Debug
31        + fmt::Display
32        + Default
33        + 'static
34{
35}
36
37/// A b+tree stores range segment of [start, start+size)
38pub struct RangeTree<T: RangeTreeKey> {
39    tree: BTreeMap<T, T>,
40    space: T,
41}
42
43/// Trait for allocator
44///
45/// when range tree merge/split, need to mirror the adding and removal range from size_tree
46pub trait RangeTreeOps<T: RangeTreeKey> {
47    /// Callback for manage size tree
48    fn op_add(&mut self, start: T, size: T);
49    /// Callback for manage size tree
50    fn op_remove(&mut self, start: T, size: T);
51}
52
53struct DummyOps();
54
55impl<T: RangeTreeKey> RangeTreeOps<T> for DummyOps {
56    #[inline]
57    fn op_add(&mut self, _start: T, _size: T) {}
58
59    #[inline]
60    fn op_remove(&mut self, _start: T, _size: T) {}
61}
62
63impl<T: RangeTreeKey> RangeTree<T> {
64    pub fn new() -> Self {
65        Self { tree: BTreeMap::new(), space: T::zero() }
66    }
67
68    #[inline]
69    pub fn is_empty(&self) -> bool {
70        self.tree.is_empty()
71    }
72
73    #[inline(always)]
74    pub fn get_space(&self) -> T {
75        self.space
76    }
77
78    #[inline(always)]
79    pub fn len(&self) -> usize {
80        self.tree.len()
81    }
82
83    /// Add range segment, merge with adjacent ranges, assuming no intersections.
84    ///
85    /// Returns `Ok(())` if there are no intersection;
86    /// otherwise returns the overlapping range as `Err((existing_start, existing_size))`.
87    ///
88    /// This equals to add + add_find_overlap in v0.1
89    #[inline]
90    pub fn add(&mut self, start: T, size: T) -> Result<(), (T, T)> {
91        self.add_with(start, size, &mut DummyOps {})
92    }
93
94    #[inline]
95    pub fn add_with<O>(&mut self, start: T, size: T, ops: &mut O) -> Result<(), (T, T)>
96    where
97        O: RangeTreeOps<T>,
98    {
99        assert!(size > T::zero(), "range tree add size={} error", size);
100        let end = start + size;
101        let mut prev = None;
102        let mut next = None;
103        match self.tree.entry(start) {
104            Entry::Occupied(ent) => Err((*ent.key(), *ent.get())),
105            Entry::Vacant(ent) => {
106                if let Some((_start, _size)) = ent.peek_backward() {
107                    let _end = *_start + *_size;
108                    match _end.cmp(&start) {
109                        Ordering::Equal => {
110                            prev = Some((*_start, *_size));
111                        }
112                        Ordering::Greater => return Err((*_start, *_size)),
113                        _ => {}
114                    }
115                }
116                if let Some((_start, _size)) = ent.peek_forward() {
117                    match end.cmp(_start) {
118                        Ordering::Equal => {
119                            next = Some((*_start, *_size));
120                        }
121                        Ordering::Greater => return Err((*_start, *_size)),
122                        _ => {}
123                    }
124                }
125                match (prev, next) {
126                    (None, None) => {
127                        ops.op_add(start, size);
128                        ent.insert(size);
129                    }
130                    (None, Some((next_start, mut next_size))) => {
131                        let mut ent_next = ent.move_forward().expect("merge next");
132                        ops.op_remove(next_start, next_size);
133                        next_size += size;
134                        *ent_next.get_mut() = next_size;
135                        ent_next.alter_key(start).expect("merge next alter_key");
136                        ops.op_add(start, next_size);
137                    }
138                    (Some((prev_start, mut prev_size)), None) => {
139                        ops.op_remove(prev_start, prev_size);
140                        let mut ent_prev = ent.move_backward().expect("merge prev");
141                        prev_size += size;
142                        *ent_prev.get_mut() = prev_size;
143                        ops.op_add(prev_start, prev_size);
144                    }
145                    (Some((prev_start, prev_size)), Some((next_start, next_size))) => {
146                        ops.op_remove(prev_start, prev_size);
147                        ops.op_remove(next_start, next_size);
148                        let mut ent_prev = ent.move_backward().expect("merge prev");
149                        let final_size = prev_size + size + next_size;
150                        *ent_prev.get_mut() = final_size;
151                        ops.op_add(prev_start, final_size);
152                        let ent_next = ent_prev.move_forward().expect("merge next");
153                        ent_next.remove();
154                    }
155                }
156                self.space += size;
157                Ok(())
158            }
159        }
160    }
161
162    /// Add to the tree with [start, end)
163    ///
164    /// Returns `Ok(())` if there are no intersection;
165    /// otherwise returns the overlapping range as `Err((existing_start, existing_size))`.
166    ///
167    /// This equals to add_abs in v0.1
168    #[inline(always)]
169    pub fn add_abs(&mut self, start: T, end: T) -> Result<(), (T, T)> {
170        assert!(start < end, "range tree add start={} end={}", start, end);
171        self.add(start, end - start)
172    }
173
174    /// Add range which may have multiple intersections with existing range, ensuring union result
175    /// stores in the tree
176    #[inline]
177    pub fn add_loosely(&mut self, start: T, size: T) {
178        assert!(size > T::zero(), "range tree add size error");
179        let new_end = start + size;
180        let base_ent = match self.tree.entry(start) {
181            Entry::Occupied(oe) => {
182                if start + *oe.get() >= new_end {
183                    return;
184                }
185                Entry::Occupied(oe)
186            }
187            Entry::Vacant(ve) => {
188                if let Some((pre_start, pre_size)) = ve.peek_backward() {
189                    let cur_end = *pre_start + *pre_size;
190                    if cur_end >= new_end {
191                        return;
192                    }
193                    if cur_end >= start {
194                        Entry::Occupied(ve.move_backward().expect("move back to merge"))
195                    } else {
196                        Entry::Vacant(ve)
197                    }
198                } else {
199                    Entry::Vacant(ve)
200                }
201            }
202        };
203
204        macro_rules! remove_intersect {
205            ($next_start: expr, $new_end: expr) => {
206                if let Some((last_start, last_size)) = self.tree.remove_range_with(
207                    $next_start..=$new_end,
208                    |_removed_start, removed_size| {
209                        self.space -= *removed_size;
210                    },
211                ) {
212                    let last_end = last_start + last_size;
213                    if last_end > new_end {
214                        let _size = last_end - new_end;
215                        // add back and join with previous range
216                        self.add(new_end, _size)
217                            .expect("add {new_end:?}:{_size:?} should not fail");
218                    }
219                }
220            };
221        }
222        match base_ent {
223            Entry::Occupied(mut oe) => {
224                let base_start = *oe.key();
225                let old_size = *oe.get();
226
227                // extend the size to final size
228                let final_size = new_end - base_start;
229                self.space += final_size - old_size;
230                *oe.get_mut() = final_size;
231
232                if let Some((_next_start, _next_size)) = oe.peek_forward() {
233                    let next_start = *_next_start;
234                    let next_size = *_next_size;
235                    if next_start < new_end {
236                        _ = oe;
237                        remove_intersect!(next_start, new_end);
238                    } else if next_start == new_end {
239                        // space is neutral (moving between segments)
240                        *oe.get_mut() += next_size;
241                        self.tree.remove(&next_start);
242                    }
243                }
244            }
245            Entry::Vacant(ve) => {
246                let base_start = start;
247                self.space += size;
248
249                if let Some((_next_start, _next_size)) = ve.peek_forward() {
250                    let next_start = *_next_start;
251                    let next_size = *_next_size;
252                    if next_start < new_end {
253                        ve.insert(size);
254                        remove_intersect!(next_start, new_end);
255                    } else if next_start == new_end {
256                        let final_size = new_end - base_start + next_size;
257                        ve.insert(final_size);
258                        self.tree.remove(&next_start);
259                    } else {
260                        ve.insert(size);
261                    }
262                } else {
263                    ve.insert(size);
264                }
265            }
266        }
267    }
268
269    /// Valid and remove specify range start:size
270    ///
271    /// # Return value
272    /// - Only return Ok(()) when there's existing range equal to or contain the removal range in the tree,
273    /// - return Err(None) when not found,
274    /// - return Err(Some(start, size)) when a range intersect with the removal range, or when the
275    ///   removal range larger than existing range.
276    #[inline]
277    pub fn remove(&mut self, start: T, size: T) -> Result<(), Option<(T, T)>> {
278        self.remove_with(start, size, &mut DummyOps {})
279    }
280
281    /// Valid and remove specify range start:size
282    ///
283    /// # Return value
284    ///
285    /// - Only return Ok(()) when there's existing range equal to or contain the removal range in the tree,
286    /// - return Err(None) when not found,
287    /// - return Err(Some(start, size)) when a range intersect with the removal range, or when the
288    ///   removal range larger than existing range.
289    pub fn remove_with<O>(&mut self, start: T, size: T, ops: &mut O) -> Result<(), Option<(T, T)>>
290    where
291        O: RangeTreeOps<T>,
292    {
293        let end = start + size;
294        let ent = self.tree.entry(start);
295        match ent {
296            Entry::Occupied(mut oent) => {
297                let rs_size = *oent.get();
298                ops.op_remove(start, rs_size);
299                if rs_size == size {
300                    // Exact match or subset removed
301                    oent.remove();
302                    self.space -= rs_size;
303                    Ok(())
304                } else if rs_size > size {
305                    // Shrink from front
306                    let new_start = start + size;
307                    let new_size = rs_size - size;
308                    oent.alter_key(new_start).expect("shrink alter_key");
309                    *oent.get_mut() = new_size;
310                    ops.op_add(new_start, new_size);
311                    self.space -= size;
312                    Ok(())
313                } else {
314                    // existing range smaller than what need to remove
315                    Err(Some((start, rs_size)))
316                }
317            }
318            Entry::Vacant(vent) => {
319                if let Some((&rs_start, &rs_size)) = vent.peek_backward() {
320                    let rs_end = rs_start + rs_size;
321                    if rs_end > start {
322                        ops.op_remove(rs_start, rs_size);
323                        let mut oent = vent.move_backward().expect("move back to overlapping");
324                        if rs_end > end {
325                            let new_size = start - rs_start;
326                            // punch a hold in the middle
327                            *oent.get_mut() = new_size;
328                            ops.op_add(rs_start, new_size);
329                            let new_size2 = rs_end - end;
330                            // TODO optimize add insert after entry for btree
331                            self.tree.insert(end, new_size2);
332                            ops.op_add(end, new_size2);
333                            self.space -= size;
334                            Ok(())
335                        } else if rs_end == end {
336                            // Shrink from back
337                            let new_size = start - rs_start;
338                            *oent.get_mut() = new_size;
339                            ops.op_add(rs_start, new_size);
340                            self.space -= rs_end - start;
341                            Ok(())
342                        } else {
343                            Err(Some((rs_start, rs_size)))
344                        }
345                    } else {
346                        Err(None)
347                    }
348                } else {
349                    Err(None)
350                }
351            }
352        }
353    }
354
355    /// Remove all the intersection ranges in the tree
356    ///
357    /// Unlike the strict behavior of [RangeTree::remove()],
358    /// this function allows the removal range start:size to to be larger than the existing range.
359    ///
360    /// Equals to remove_and_split in v0.1
361    ///
362    /// return true if overlapping range found and removed.
363    /// return false if overlapping range not found.
364    ///
365    /// #[inline]
366    pub fn remove_loosely(&mut self, mut start: T, mut size: T) -> bool {
367        let end = start + size;
368        let mut ent = self.tree.entry(start);
369        let mut removed = false;
370        loop {
371            match ent {
372                Entry::Occupied(mut oent) => {
373                    let rs_size = *oent.get();
374                    if rs_size == size {
375                        // Exact match or subset removed
376                        oent.remove();
377                        self.space -= rs_size;
378                        return true;
379                    } else if rs_size > size {
380                        // Shrink from front
381                        let new_start = start + size;
382                        let new_size = rs_size - size;
383                        oent.alter_key(new_start).expect("shrink alter_key");
384                        *oent.get_mut() = new_size;
385                        self.space -= size;
386                        return true;
387                    } else {
388                        if let Some((_next_start, _next_size)) = oent.peek_forward()
389                            && *_next_start < end
390                        {
391                            start = *_next_start;
392                            size = end - start;
393                            self.space -= *oent.get();
394                            oent.remove();
395                            ent = self.tree.entry(start);
396                            removed = true;
397                            continue;
398                        }
399                        self.space -= rs_size;
400                        oent.remove();
401                        return true;
402                    }
403                }
404                Entry::Vacant(vent) => {
405                    if let Some((&rs_start, &rs_size)) = vent.peek_backward() {
406                        let rs_end = rs_start + rs_size;
407                        if rs_end > start {
408                            let mut oent = vent.move_backward().expect("move back to overlapping");
409                            if rs_end > end {
410                                let new_size = start - rs_start;
411                                // punch a hold in the middle
412                                *oent.get_mut() = new_size;
413                                let new_size2 = rs_end - end;
414                                // TODO optimize add insert after entry for btree
415                                self.tree.insert(end, new_size2);
416                                self.space -= size;
417                                return true;
418                            } else {
419                                // Shrink from back
420                                let new_size = start - rs_start;
421                                *oent.get_mut() = new_size;
422                                self.space -= rs_end - start;
423                                if rs_end == end {
424                                    return true;
425                                }
426                                if let Some((next_start, _)) = oent.peek_forward()
427                                    && *next_start < end
428                                {
429                                    start = *next_start;
430                                    size = end - *next_start;
431                                    ent = Entry::Occupied(
432                                        oent.move_forward().expect("move forward to overlapping"),
433                                    );
434                                    continue;
435                                }
436                                return true;
437                            }
438                        }
439                    }
440                    // Handle the case where range starts before the first overlapping segment
441                    if let Some((next_start, _)) = vent.peek_forward()
442                        && *next_start < end
443                    {
444                        start = *next_start;
445                        size = end - *next_start;
446                        ent = Entry::Occupied(
447                            vent.move_forward().expect("move forward to overlapping"),
448                        );
449                        continue;
450                    }
451                    return removed;
452                }
453            }
454        }
455    }
456
457    /// return only when segment overlaps with [start, start+size)
458    #[inline]
459    pub fn range<'a, R: RangeBounds<T>>(&'a self, r: R) -> RangeIter<'a, T> {
460        let start = match r.start_bound() {
461            Bound::Included(start) => Some(*start),
462            Bound::Excluded(start) => Some(*start),
463            _ => None,
464        };
465        let cursor = if let Some(_start) = start {
466            let mut _cursor = self.tree.cursor(&_start);
467            if let Some((pre_start, pre_size)) = _cursor.peek_backward() {
468                let pre_end = *pre_start + *pre_size;
469                if pre_end > _start {
470                    _cursor.previous();
471                }
472                // TODO what if we find pre_start < start but pre_start + size >= start
473            }
474            _cursor
475        } else {
476            self.tree.first_cursor()
477        };
478        RangeIter { cursor, end: r.end_bound().cloned(), not_empty: true }
479    }
480
481    pub fn collect(&self) -> Vec<(T, T)> {
482        let mut v = Vec::with_capacity(self.len());
483        for (start, size) in &self.tree {
484            v.push((*start, *size))
485        }
486        v
487    }
488
489    #[inline]
490    pub fn iter(&self) -> Iter<'_, T, T> {
491        self.tree.iter()
492    }
493
494    pub fn validate(&self) {
495        self.tree.validate();
496    }
497
498    #[inline]
499    pub fn memory_used(&self) -> usize {
500        self.tree.memory_used()
501    }
502}
503
504impl<'a, T: RangeTreeKey> IntoIterator for &'a RangeTree<T> {
505    type Item = (&'a T, &'a T);
506    type IntoIter = Iter<'a, T, T>;
507
508    #[inline]
509    fn into_iter(self) -> Self::IntoIter {
510        self.iter()
511    }
512}
513
514impl<T: RangeTreeKey> IntoIterator for RangeTree<T> {
515    type Item = (T, T);
516    type IntoIter = IntoIter<T, T>;
517
518    #[inline]
519    fn into_iter(self) -> Self::IntoIter {
520        self.tree.into_iter()
521    }
522}
523
524/// An iterator with bound, acquire from [RangeTree::range()]
525pub struct RangeIter<'a, T: RangeTreeKey> {
526    cursor: Cursor<'a, T, T>,
527    end: Bound<T>,
528    not_empty: bool,
529}
530
531impl<'a, T: RangeTreeKey> Iterator for RangeIter<'a, T> {
532    type Item = (T, T);
533
534    #[inline]
535    fn next(&mut self) -> Option<Self::Item> {
536        if self.not_empty {
537            if let Some((start, size)) = self.cursor.next() {
538                match self.end {
539                    Bound::Unbounded => return Some((*start, *size)),
540                    Bound::Excluded(end) => {
541                        if *start < end {
542                            return Some((*start, *size));
543                        }
544                        self.not_empty = false;
545                        return None;
546                    }
547                    Bound::Included(end) => {
548                        if *start <= end {
549                            return Some((*start, *size));
550                        }
551                        self.not_empty = false;
552                        return None;
553                    }
554                }
555            }
556            self.not_empty = false;
557        }
558        None
559    }
560}