ranges_ext/
lib.rs

1#![no_std]
2
3use core::{
4    cmp::{max, min},
5    ops::Range,
6};
7
8use heapless::Vec;
9
10/// 一个「区间集合」数据结构:维护一组**有序、互不重叠**的半开区间 `[start, end)`。
11///
12/// - 插入时会把重叠/相邻的区间自动合并。
13/// - 删除一个区间时,会从集合里移除交集;必要时把已有区间拆成左右两段。
14///
15/// 约定:空区间(`start >= end`)会被忽略。
16#[derive(Clone, Debug)]
17pub struct RangeSet<T, const C: usize = 128>
18where
19    T: Ord + Copy,
20{
21    elements: Vec<Range<T>, C>,
22}
23
24impl<T, const C: usize> Default for RangeSet<T, C>
25where
26    T: Ord + Copy,
27{
28    fn default() -> Self {
29        Self {
30            elements: Vec::new(),
31        }
32    }
33}
34
35impl<T, const C: usize> RangeSet<T, C>
36where
37    T: Ord + Copy,
38{
39    /// 创建空集合。
40    pub fn new() -> Self {
41        Self::default()
42    }
43
44    /// 返回内部区间的切片(已排序、已合并、互不重叠)。
45    #[inline]
46    pub fn as_slice(&self) -> &[Range<T>] {
47        &self.elements
48    }
49
50    /// 返回区间迭代器(零拷贝)。
51    #[inline]
52    pub fn iter(&self) -> impl Iterator<Item = &Range<T>> {
53        self.elements.iter()
54    }
55
56    #[inline]
57    pub fn is_empty(&self) -> bool {
58        self.elements.is_empty()
59    }
60
61    #[inline]
62    pub fn len(&self) -> usize {
63        self.elements.len()
64    }
65
66    pub fn clear(&mut self) {
67        self.elements.clear();
68    }
69
70    /// 添加一个区间;会把与其重叠或相邻的区间合并。
71    pub fn add(&mut self, range: Range<T>) {
72        if range.start >= range.end {
73            return;
74        }
75
76        if self.elements.is_empty() {
77            let _ = self.elements.push(range);
78            return;
79        }
80
81        // 二分查找插入位置:第一个 start >= range.start 的位置
82        let insert_at = self
83            .elements
84            .binary_search_by(|e| {
85                if e.start < range.start {
86                    core::cmp::Ordering::Less
87                } else {
88                    core::cmp::Ordering::Greater
89                }
90            })
91            .unwrap_or_else(|pos| pos);
92
93        let mut merged_range = range;
94
95        // 向左合并:若左侧区间与 range 重叠/相邻(end >= start)
96        let mut insert_at = insert_at;
97        while insert_at > 0 {
98            let left = &self.elements[insert_at - 1];
99            if left.end < merged_range.start {
100                break;
101            }
102            merged_range.start = min(merged_range.start, left.start);
103            merged_range.end = max(merged_range.end, left.end);
104            self.elements.remove(insert_at - 1);
105            insert_at -= 1;
106        }
107
108        // 向右合并:若右侧区间与 range 重叠/相邻(start <= end)
109        while insert_at < self.elements.len() {
110            let right = &self.elements[insert_at];
111            if right.start > merged_range.end {
112                break;
113            }
114            merged_range.start = min(merged_range.start, right.start);
115            merged_range.end = max(merged_range.end, right.end);
116            self.elements.remove(insert_at);
117        }
118
119        let _ = self.elements.insert(insert_at, merged_range);
120    }
121
122    /// 查询某个值是否落在任意一个区间中。
123    #[inline]
124    pub fn contains(&self, value: T) -> bool {
125        // 二分查找:找到可能包含 value 的区间
126        self.elements
127            .binary_search_by(|e| {
128                if e.end <= value {
129                    core::cmp::Ordering::Less
130                } else if e.start > value {
131                    core::cmp::Ordering::Greater
132                } else {
133                    core::cmp::Ordering::Equal
134                }
135            })
136            .is_ok()
137    }
138
139    /// 删除一个区间:从集合中移除与其相交的部分。
140    ///
141    /// 若被删除区间位于某个已有区间内部,会导致该已有区间被拆分为两段。
142    pub fn remove(&mut self, range: Range<T>) {
143        if range.start >= range.end || self.elements.is_empty() {
144            return;
145        }
146
147        let mut out: Vec<Range<T>, C> = Vec::new();
148        for elem in self.elements.drain(..) {
149            // 无交集
150            if elem.end <= range.start || elem.start >= range.end {
151                let _ = out.push(elem);
152                continue;
153            }
154
155            let has_left = elem.start < range.start;
156            let has_right = elem.end > range.end;
157
158            match (has_left, has_right) {
159                (true, true) => {
160                    // 需要分裂成两段
161                    let left = elem.start..min(elem.end, range.start);
162                    if left.start < left.end {
163                        let _ = out.push(left);
164                    }
165                    let right = max(elem.start, range.end)..elem.end;
166                    if right.start < right.end {
167                        let _ = out.push(right);
168                    }
169                }
170                (true, false) => {
171                    // 只有左半段
172                    let left = elem.start..min(elem.end, range.start);
173                    if left.start < left.end {
174                        let _ = out.push(left);
175                    }
176                }
177                (false, true) => {
178                    // 只有右半段
179                    let right = max(elem.start, range.end)..elem.end;
180                    if right.start < right.end {
181                        let _ = out.push(right);
182                    }
183                }
184                (false, false) => {
185                    // 完全被删除,不添加任何内容
186                }
187            }
188        }
189        self.elements = out;
190    }
191
192    /// 批量添加多个区间。
193    pub fn extend<I>(&mut self, ranges: I)
194    where
195        I: IntoIterator<Item = Range<T>>,
196    {
197        for r in ranges {
198            self.add(r);
199        }
200    }
201}