rangemap/std_ext.rs
1use core::ops::{Add, Range, RangeInclusive, Sub};
2
3pub trait RangeExt<T> {
4 fn overlaps(&self, other: &Self) -> bool;
5 fn touches(&self, other: &Self) -> bool;
6}
7
8impl<T> RangeExt<T> for Range<T>
9where
10 T: Ord,
11{
12 fn overlaps(&self, other: &Self) -> bool {
13 use core::cmp::{max, min};
14 // Strictly less than, because ends are excluded.
15 max(&self.start, &other.start) < min(&self.end, &other.end)
16 }
17
18 fn touches(&self, other: &Self) -> bool {
19 use core::cmp::{max, min};
20 // Less-than-or-equal-to because if one end is excluded, the other is included.
21 // I.e. the two could be joined into a single range, because they're overlapping
22 // or immediately adjacent.
23 max(&self.start, &other.start) <= min(&self.end, &other.end)
24 }
25}
26
27pub trait RangeInclusiveExt<T> {
28 fn overlaps(&self, other: &Self) -> bool;
29 fn touches<StepFnsT>(&self, other: &Self) -> bool
30 where
31 StepFnsT: StepFns<T>;
32}
33
34impl<T> RangeInclusiveExt<T> for RangeInclusive<T>
35where
36 T: Ord + Clone,
37{
38 fn overlaps(&self, other: &Self) -> bool {
39 use core::cmp::{max, min};
40 // Less than or equal, because ends are included.
41 max(self.start(), other.start()) <= min(self.end(), other.end())
42 }
43
44 fn touches<StepFnsT>(&self, other: &Self) -> bool
45 where
46 StepFnsT: StepFns<T>,
47 {
48 use core::cmp::{max, min};
49
50 // Touching for end-inclusive ranges is equivalent to touching of
51 // slightly longer end-inclusive ranges.
52 //
53 // We need to do a small dance to avoid arithmetic overflow
54 // at the extremes of the key space. And to do this without
55 // needing to bound our key type on something like `num::Bounded`
56 // (https://docs.rs/num/0.3.0/num/trait.Bounded.html),
57 // we'll just extend the end of the _earlier_ range iff
58 // its end is already earlier than the latter range's start.
59 let max_start = max(self.start(), other.start());
60 let min_range_end = min(self.end(), other.end());
61 let min_range_end_extended = if min_range_end < max_start {
62 StepFnsT::add_one(min_range_end)
63 } else {
64 min_range_end.clone()
65 };
66 *max_start <= min_range_end_extended
67 }
68}
69
70/// Minimal version of unstable [`Step`](core::iter::Step) trait
71/// from the Rust standard library.
72///
73/// This is needed for [`RangeInclusiveMap`](crate::RangeInclusiveMap)
74/// because ranges stored as its keys interact with each other
75/// when the start of one is _adjacent_ the end of another.
76/// I.e. we need a concept of successor values rather than just
77/// equality, and that is what `Step` will
78/// eventually provide once it is stabilized.
79///
80/// **NOTE:** This will likely be deprecated and then eventually
81/// removed once the standard library's `Step`
82/// trait is stabilised, as most crates will then likely implement `Step`
83/// for their types where appropriate.
84///
85/// See [this issue](https://github.com/rust-lang/rust/issues/42168)
86/// for details about that stabilization process.
87pub trait StepLite {
88 /// Returns the _successor_ of `self`.
89 ///
90 /// If this would overflow the range of values supported by `Self`,
91 /// this function is allowed to panic, wrap, or saturate.
92 /// The suggested behavior is to panic when debug assertions are enabled,
93 /// and to wrap or saturate otherwise.
94 fn add_one(&self) -> Self;
95
96 /// Returns the _predecessor_ of `self`.
97 ///
98 /// If this would overflow the range of values supported by `Self`,
99 /// this function is allowed to panic, wrap, or saturate.
100 /// The suggested behavior is to panic when debug assertions are enabled,
101 /// and to wrap or saturate otherwise.
102 fn sub_one(&self) -> Self;
103}
104
105// Implement for all common integer types.
106macro_rules! impl_step_lite {
107 ($($t:ty)*) => ($(
108 impl StepLite for $t {
109 #[inline]
110 fn add_one(&self) -> Self {
111 Add::add(*self, 1)
112 }
113
114 #[inline]
115 fn sub_one(&self) -> Self {
116 Sub::sub(*self, 1)
117 }
118 }
119 )*)
120}
121
122impl_step_lite!(usize u8 u16 u32 u64 u128 i8 i16 i32 i64 i128);
123
124// TODO: When on nightly, a blanket implementation for
125// all types that implement `core::iter::Step` instead
126// of the auto-impl above.
127
128/// Successor and predecessor functions defined for `T`,
129/// but as free functions rather than methods on `T` itself.
130///
131/// This is useful as a workaround for Rust's "orphan rules",
132/// which prevent you from implementing [`StepLite`](crate::StepLite) for `T` if `T`
133/// is a foreign type.
134///
135/// **NOTE:** This will likely be deprecated and then eventually
136/// removed once the standard library's [`Step`](core::iter::Step)
137/// trait is stabilised, as most crates will then likely implement `Step`
138/// for their types where appropriate.
139///
140/// See [this issue](https://github.com/rust-lang/rust/issues/42168)
141/// for details about that stabilization process.
142///
143/// There is also a blanket implementation of `StepFns` for all
144/// types implementing `StepLite`. Consumers of this crate should
145/// prefer to implement `StepLite` for their own types, and only
146/// fall back to `StepFns` when dealing with foreign types.
147pub trait StepFns<T> {
148 /// Returns the _successor_ of value `start`.
149 ///
150 /// If this would overflow the range of values supported by `Self`,
151 /// this function is allowed to panic, wrap, or saturate.
152 /// The suggested behavior is to panic when debug assertions are enabled,
153 /// and to wrap or saturate otherwise.
154 fn add_one(start: &T) -> T;
155
156 /// Returns the _predecessor_ of value `start`.
157 ///
158 /// If this would overflow the range of values supported by `Self`,
159 /// this function is allowed to panic, wrap, or saturate.
160 /// The suggested behavior is to panic when debug assertions are enabled,
161 /// and to wrap or saturate otherwise.
162 fn sub_one(start: &T) -> T;
163}
164
165impl<T> StepFns<T> for T
166where
167 T: StepLite,
168{
169 fn add_one(start: &T) -> T {
170 start.add_one()
171 }
172
173 fn sub_one(start: &T) -> T {
174 start.sub_one()
175 }
176}