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