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}