s2n_quic_core/interval_set/
interval.rs1use super::IntervalSetError;
5use core::{
6 cmp::Ordering,
7 fmt,
8 ops::{Bound, Range, RangeBounds, RangeInclusive},
9};
10
11#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct Interval<T> {
13 pub(super) start: T,
14 pub(super) end: T,
15}
16
17impl<T: IntervalBound> Interval<T> {
18 pub fn from_range_bounds<B: RangeBounds<T>>(bounds: B) -> Result<Self, IntervalSetError> {
19 let start = match bounds.start_bound() {
20 Bound::Included(start) => *start,
21 Bound::Excluded(start) => start.step_down().ok_or(IntervalSetError::InvalidInterval)?,
22 _ => return Err(IntervalSetError::InvalidInterval),
23 };
24
25 let end = match bounds.end_bound() {
26 Bound::Included(end) => *end,
27 Bound::Excluded(end) => end.step_down().ok_or(IntervalSetError::InvalidInterval)?,
28 _ => return Err(IntervalSetError::InvalidInterval),
29 };
30
31 let interval = Self { start, end };
32
33 if interval.is_valid() {
34 Ok(interval)
35 } else {
36 Err(IntervalSetError::InvalidInterval)
37 }
38 }
39
40 #[inline]
41 pub fn start_inclusive(&self) -> T {
42 self.start
43 }
44
45 #[inline]
46 pub fn start_exclusive(&self) -> T {
47 self.start.step_down_saturating()
48 }
49
50 #[inline]
51 pub fn end_inclusive(&self) -> T {
52 self.end
53 }
54
55 #[inline]
56 pub fn end_exclusive(&self) -> T {
57 self.end.step_up_saturating()
58 }
59
60 #[inline]
61 pub fn len(&self) -> usize {
62 let interval_base_len = 1;
64 interval_base_len + self.start.steps_between(&self.end)
65 }
66
67 #[inline]
68 pub fn set_len(&mut self, len: usize) {
69 debug_assert_ne!(len, 0, "Intervals cannot be 0 length");
70 self.end = self.start.steps_between_len(len);
71 }
72
73 #[inline]
74 pub fn is_empty(&self) -> bool {
75 false
77 }
78
79 #[inline]
80 pub fn is_valid(&self) -> bool {
81 self.end >= self.start
82 }
83
84 #[inline]
85 pub(crate) fn should_coalesce(&self, other: &Self) -> bool {
86 self.start <= other.end_exclusive()
87 }
88}
89
90impl<T: IntervalBound> IntoIterator for &Interval<T> {
91 type IntoIter = Interval<T>;
92 type Item = T;
93
94 #[inline]
95 fn into_iter(self) -> Self::IntoIter {
96 *self
97 }
98}
99
100impl<T> RangeBounds<T> for Interval<T> {
101 #[inline]
102 fn start_bound(&self) -> Bound<&T> {
103 Bound::Included(&self.start)
104 }
105
106 #[inline]
107 fn end_bound(&self) -> Bound<&T> {
108 Bound::Included(&self.end)
109 }
110}
111
112impl<T> RangeBounds<T> for &Interval<T> {
113 #[inline]
114 fn start_bound(&self) -> Bound<&T> {
115 Bound::Included(&self.start)
116 }
117
118 #[inline]
119 fn end_bound(&self) -> Bound<&T> {
120 Bound::Included(&self.end)
121 }
122}
123
124impl<T: Ord> PartialEq<T> for Interval<T> {
125 #[inline]
126 fn eq(&self, value: &T) -> bool {
127 self.partial_cmp(value) == Some(Ordering::Equal)
128 }
129}
130
131impl<T: Ord> PartialOrd<T> for Interval<T> {
132 #[inline]
133 fn partial_cmp(&self, value: &T) -> Option<Ordering> {
134 use Ordering::*;
135 Some(match (self.start.cmp(value), self.end.cmp(value)) {
136 (Equal, _) => Equal,
137 (_, Equal) => Equal,
138 (Greater, Less) => Equal,
139 (Less, Greater) => Equal,
140 (Less, Less) => Less,
141 (Greater, Greater) => Greater,
142 })
143 }
144}
145
146impl<T: IntervalBound> From<&Interval<T>> for Interval<T> {
147 #[inline]
148 fn from(interval: &Interval<T>) -> Self {
149 *interval
150 }
151}
152
153macro_rules! range_impls {
154 ($range_ty:ident, $into:expr, $from:expr) => {
155 impl<T: IntervalBound> From<Interval<T>> for $range_ty<T> {
156 #[inline]
157 fn from(range: Interval<T>) -> Self {
158 #[allow(clippy::redundant_closure_call)]
159 ($into)(range)
160 }
161 }
162
163 impl<T: IntervalBound> From<&Interval<T>> for $range_ty<T> {
164 #[inline]
165 fn from(range: &Interval<T>) -> Self {
166 #[allow(clippy::redundant_closure_call)]
167 ($into)(*range)
168 }
169 }
170
171 impl<T: IntervalBound> From<$range_ty<T>> for Interval<T> {
172 #[inline]
173 fn from(range: $range_ty<T>) -> Self {
174 #[allow(clippy::redundant_closure_call)]
175 ($from)(range)
176 }
177 }
178
179 impl<'a, T: IntervalBound> From<&'a $range_ty<T>> for Interval<T> {
180 #[inline]
181 fn from(range: &'a $range_ty<T>) -> Self {
182 #[allow(clippy::redundant_closure_call)]
183 ($from)(range.clone())
184 }
185 }
186
187 impl<T: IntervalBound> PartialEq<$range_ty<T>> for Interval<T> {
188 #[inline]
189 fn eq(&self, other: &$range_ty<T>) -> bool {
190 self.partial_cmp(other) == Some(Ordering::Equal)
191 }
192 }
193
194 impl<T: IntervalBound> PartialEq<$range_ty<T>> for &Interval<T> {
195 #[inline]
196 fn eq(&self, other: &$range_ty<T>) -> bool {
197 self.partial_cmp(other) == Some(Ordering::Equal)
198 }
199 }
200
201 impl<T: IntervalBound> PartialOrd<$range_ty<T>> for Interval<T> {
202 #[inline]
203 fn partial_cmp(&self, other: &$range_ty<T>) -> Option<Ordering> {
204 let other: Self = other.into();
205 self.partial_cmp(&other)
206 }
207 }
208
209 impl<T: IntervalBound> PartialOrd<$range_ty<T>> for &Interval<T> {
210 #[inline]
211 fn partial_cmp(&self, other: &$range_ty<T>) -> Option<Ordering> {
212 let other: Interval<_> = other.into();
213 (*self).partial_cmp(&other)
214 }
215 }
216 };
217}
218
219range_impls!(
220 Range,
221 |interval: Interval<_>| interval.start..interval.end_exclusive(),
222 |range: Range<_>| Self {
223 start: range.start,
224 end: range.end.step_down_saturating(),
225 }
226);
227
228range_impls!(
229 RangeInclusive,
230 |interval: Interval<_>| interval.start..=interval.end,
231 |range: RangeInclusive<_>| {
232 let (start, end) = range.into_inner();
233 Self { start, end }
234 }
235);
236
237impl<T: IntervalBound> Iterator for Interval<T> {
238 type Item = T;
239
240 #[inline]
241 fn next(&mut self) -> Option<T> {
242 let current = self.start;
243 if current > self.end {
244 return None;
245 }
246 if let Some(next) = current.step_up() {
247 self.start = next;
248 } else {
249 self.end = current.step_down()?;
250 }
251 Some(current)
252 }
253}
254
255impl<T: IntervalBound> DoubleEndedIterator for Interval<T> {
256 #[inline]
257 fn next_back(&mut self) -> Option<T> {
258 let current = self.end;
259 if current < self.start {
260 return None;
261 }
262 if let Some(next) = current.step_down() {
263 self.end = next;
264 } else {
265 self.start = current.step_up()?;
266 }
267 Some(current)
268 }
269}
270
271impl<T: fmt::Debug> fmt::Debug for Interval<T> {
272 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
273 ((&self.start)..=(&self.end)).fmt(f)
274 }
275}
276
277pub trait IntervalBound: Copy + Ord + Sized {
278 fn step_up(self) -> Option<Self>;
279 fn step_down(self) -> Option<Self>;
280 fn steps_between(&self, upper: &Self) -> usize;
281 fn steps_between_len(&self, len: usize) -> Self;
282
283 fn step_up_saturating(self) -> Self {
284 self.step_up().unwrap_or(self)
285 }
286
287 fn step_down_saturating(self) -> Self {
288 self.step_down().unwrap_or(self)
289 }
290}
291
292macro_rules! integer_bounds {
293 ($type:ident) => {
294 impl IntervalBound for $type {
295 #[inline]
296 fn step_up(self) -> Option<Self> {
297 self.checked_add(1)
298 }
299
300 #[inline]
301 fn step_down(self) -> Option<Self> {
302 self.checked_sub(1)
303 }
304
305 #[inline]
306 fn steps_between(&self, upper: &Self) -> usize {
307 use core::convert::TryInto;
308 (upper - self).try_into().unwrap_or(usize::MAX)
309 }
310
311 #[inline]
312 fn steps_between_len(&self, len: usize) -> Self {
313 use core::convert::TryInto;
314 let len: Self = (len - 1).try_into().unwrap();
315 *self + len
316 }
317 }
318 };
319}
320
321integer_bounds!(u8);
322integer_bounds!(i8);
323integer_bounds!(u16);
324integer_bounds!(i16);
325integer_bounds!(u32);
326integer_bounds!(i32);
327integer_bounds!(u64);
328integer_bounds!(i64);
329integer_bounds!(u128);
330integer_bounds!(i128);
331integer_bounds!(usize);
332integer_bounds!(isize);
333
334use crate::{packet::number::PacketNumber, varint::VarInt};
335
336impl IntervalBound for VarInt {
337 #[inline]
338 fn step_up(self) -> Option<Self> {
339 self.checked_add(Self::from_u8(1))
340 }
341
342 #[inline]
343 fn step_down(self) -> Option<Self> {
344 self.checked_sub(Self::from_u8(1))
345 }
346
347 #[inline]
348 fn steps_between(&self, upper: &Self) -> usize {
349 <u64 as IntervalBound>::steps_between(self, upper)
350 }
351
352 #[inline]
353 fn steps_between_len(&self, len: usize) -> Self {
354 *self + (len - 1)
355 }
356}
357
358impl IntervalBound for PacketNumber {
359 #[inline]
360 fn step_up(self) -> Option<Self> {
361 self.next()
362 }
363
364 #[inline]
365 fn step_down(self) -> Option<Self> {
366 let space = self.space();
367 let value = PacketNumber::as_varint(self);
368 Some(space.new_packet_number(value.step_down()?))
369 }
370
371 #[inline]
372 fn steps_between(&self, upper: &Self) -> usize {
373 let lower = PacketNumber::as_varint(*self);
374 let upper = PacketNumber::as_varint(*upper);
375 lower.steps_between(&upper)
376 }
377
378 #[inline]
379 fn steps_between_len(&self, len: usize) -> Self {
380 let start = PacketNumber::as_varint(*self);
381 let end = start.steps_between_len(len);
382 self.space().new_packet_number(end)
383 }
384}