noq_proto/range_set/
array_range_set.rs1use std::cmp::Ordering;
2use std::fmt::{self, Write};
3use std::iter::Sum;
4use std::ops::{Add, Range, Sub};
5
6use tinyvec::TinyVec;
7
8#[derive(Default, PartialEq, Eq)]
23pub(crate) struct ArrayRangeSet<const N: usize = ARRAY_RANGE_SET_INLINE_CAPACITY, T: Default = u64>(
24 TinyVec<[Range<T>; N]>,
25);
26
27impl<const N: usize, T: fmt::Debug + Default> fmt::Debug for ArrayRangeSet<N, T> {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 f.write_char('[')?;
30 let mut first = true;
31 for range in self.0.iter() {
32 if !first {
33 f.write_char(',')?;
34 }
35 write!(f, "{range:?}")?;
36 first = false;
37 }
38 f.write_char(']')?;
39 Ok(())
40 }
41}
42
43pub(crate) const ARRAY_RANGE_SET_INLINE_CAPACITY: usize = 2;
47
48impl<const N: usize> Clone for ArrayRangeSet<N> {
49 fn clone(&self) -> Self {
50 if self.0.is_inline() || self.0.len() > ARRAY_RANGE_SET_INLINE_CAPACITY {
54 return Self(self.0.clone());
55 }
56
57 let mut vec = TinyVec::new();
58 vec.extend_from_slice(self.0.as_slice());
59 Self(vec)
60 }
61}
62
63impl<const N: usize, T> ArrayRangeSet<N, T>
64where
65 T: Default
66 + Clone
67 + Copy
68 + PartialOrd
69 + Ord
70 + From<u32>
71 + Add<T, Output = T>
72 + Sub<T, Output = T>
73 + Sum,
74{
75 pub(crate) fn new() -> Self {
76 Default::default()
77 }
78
79 pub(crate) fn iter(&self) -> impl DoubleEndedIterator<Item = Range<T>> + '_ {
80 self.0.iter().cloned()
81 }
82
83 pub(crate) fn range_count(&self) -> usize {
84 self.0.len()
85 }
86
87 pub(crate) fn elts_count(&self) -> T {
88 self.0.iter().map(|r| r.end - r.start).sum()
89 }
90
91 pub(crate) fn contains(&self, x: T) -> bool {
92 self.0
93 .binary_search_by(|range| {
94 if range.end <= x {
95 Ordering::Less
96 } else if x < range.start {
97 Ordering::Greater
98 } else {
99 Ordering::Equal
101 }
102 })
103 .is_ok()
104 }
105
106 pub(crate) fn iter_range(&self, range: Range<T>) -> impl Iterator<Item = Range<T>> + '_ {
107 self.iter().filter_map(move |r| {
108 if r.end > range.start && r.start < range.end {
109 Some(r.start.max(range.start)..r.end.min(range.end))
110 } else {
111 None
112 }
113 })
114 }
115
116 pub(crate) fn insert_one(&mut self, x: T) -> bool {
117 self.insert(x..x + T::from(1u32))
118 }
119
120 pub(crate) fn insert(&mut self, x: Range<T>) -> bool {
121 let mut result = false;
122
123 if x.is_empty() {
124 return false;
126 }
127
128 let idx = self.0.partition_point(|r| r.end < x.start);
132
133 if idx == self.0.len() {
134 self.0.push(x);
135 return true;
136 }
137
138 let range = &mut self.0[idx];
139
140 if x.end < range.start {
141 self.0.insert(idx, x);
144 return true;
145 } else if range.start > x.start {
146 result = true;
152 range.start = x.start;
153 }
154
155 if x.end <= range.end {
160 return result;
162 }
163
164 range.end = x.end;
167
168 while idx != self.0.len() - 1 {
170 let curr = self.0[idx].clone();
171 let next = self.0[idx + 1].clone();
172 if curr.end >= next.start {
173 self.0[idx].end = next.end.max(curr.end);
174 self.0.remove(idx + 1);
175 } else {
176 break;
177 }
178 }
179
180 true
181 }
182
183 pub(crate) fn remove(&mut self, x: Range<T>) -> bool {
184 let mut result = false;
185
186 if x.is_empty() {
187 return false;
189 }
190
191 let mut idx = self.0.partition_point(|r| r.end <= x.start);
195
196 while idx != self.0.len() {
197 let range = self.0[idx].clone();
198
199 if x.end <= range.start {
200 break;
202 }
203
204 result = true;
206
207 let left = range.start..x.start;
208 let right = x.end..range.end;
209
210 if left.is_empty() && right.is_empty() {
211 self.0.remove(idx);
212 } else if left.is_empty() {
213 self.0[idx] = right;
214 idx += 1;
215 } else if right.is_empty() {
216 self.0[idx] = left;
217 idx += 1;
218 } else {
219 self.0[idx] = right;
220 self.0.insert(idx, left);
221 idx += 2;
222 }
223 }
224
225 result
226 }
227
228 pub(crate) fn is_empty(&self) -> bool {
229 self.0.is_empty()
230 }
231
232 pub(crate) fn pop_min(&mut self) -> Option<Range<T>> {
233 if !self.0.is_empty() {
234 Some(self.0.remove(0))
235 } else {
236 None
237 }
238 }
239
240 pub(crate) fn min(&self) -> Option<T> {
241 self.iter().next().map(|x| x.start)
242 }
243
244 pub(crate) fn max(&self) -> Option<T> {
245 self.iter().next_back().map(|x| x.end - T::from(1))
246 }
247}
248
249impl<const N: usize> ArrayRangeSet<N, u64> {
256 pub(crate) fn elts(&self) -> impl Iterator<Item = u64> + '_ {
257 self.iter().flatten()
258 }
259}
260
261#[cfg(test)]
262impl proptest::arbitrary::Arbitrary for ArrayRangeSet {
263 type Parameters = ();
264 type Strategy = proptest::strategy::BoxedStrategy<Self>;
265
266 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
267 use proptest::prelude::*;
268 prop::collection::vec((1u64..100, 1u64..50), 1..8)
271 .prop_map(|gaps_and_sizes| {
272 let mut ranges = Self::new();
273 let mut pos = 0u64;
274 for (gap, size) in gaps_and_sizes {
275 let start = pos + gap;
276 let end = start + size;
277 ranges.insert(start..end);
278 pos = end;
279 }
280 ranges
281 })
282 .boxed()
283 }
284}