1#![no_std]
2
3use core::{
4 cmp::{max, min},
5 ops::Range,
6};
7
8use heapless::Vec;
9
10#[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 pub fn new() -> Self {
41 Self::default()
42 }
43
44 #[inline]
46 pub fn as_slice(&self) -> &[Range<T>] {
47 &self.elements
48 }
49
50 #[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 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 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 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 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 #[inline]
124 pub fn contains(&self, value: T) -> bool {
125 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 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 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 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 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 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 }
187 }
188 }
189 self.elements = out;
190 }
191
192 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}