1use std::borrow::Borrow;
21use std::ops::{Bound, RangeBounds};
22
23#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
25pub enum RangeOrdering {
26 Below,
28 Inside,
30 Above,
32}
33
34pub trait BorrowRange<T: ?Sized, R>: Borrow<R> {}
85impl<T, R: RangeBounds<T>> BorrowRange<T, R> for R {}
86impl<T, R: RangeBounds<T>> BorrowRange<T, R> for &R {}
87
88pub trait RangeComparable {
92 fn range_cmp<R: RangeBounds<Self>, B: BorrowRange<Self, R>>(&self, range: B) -> RangeOrdering;
102}
103
104impl<T: Ord> RangeComparable for T {
105 fn range_cmp<R: RangeBounds<Self>, B: BorrowRange<Self, R>>(&self, range: B) -> RangeOrdering {
106 let range = range.borrow();
107
108 if range.contains(self) {
109 return RangeOrdering::Inside;
110 }
111
112 if match range.start_bound() {
113 Bound::Included(key) => self < key,
114 Bound::Excluded(key) => self <= key,
115 _ => false,
116 } {
117 return RangeOrdering::Below;
118 }
119
120 if match range.end_bound() {
121 Bound::Included(key) => self > key,
122 Bound::Excluded(key) => self >= key,
123 _ => false,
124 } {
125 return RangeOrdering::Above;
126 }
127
128 unreachable!()
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn range_full() {
138 assert_eq!(1.range_cmp(..), RangeOrdering::Inside);
140 }
141
142 #[test]
143 fn range_from() {
144 assert_eq!(1.range_cmp(1..), RangeOrdering::Inside);
146 assert_eq!(1.range_cmp(&1..), RangeOrdering::Inside);
147
148 assert_eq!(1.range_cmp(2..), RangeOrdering::Below);
150 assert_eq!(1.range_cmp(&2..), RangeOrdering::Below);
151 }
152
153 #[test]
154 fn range_to() {
155 assert_eq!(1.range_cmp(..1), RangeOrdering::Above);
157 assert_eq!(1.range_cmp(..&1), RangeOrdering::Above);
158
159 assert_eq!(1.range_cmp(..2), RangeOrdering::Inside);
161 assert_eq!(1.range_cmp(..&2), RangeOrdering::Inside);
162 }
163
164 #[test]
165 fn range() {
166 assert_eq!(1.range_cmp(0..1), RangeOrdering::Above);
168 assert_eq!(1.range_cmp(&0..&1), RangeOrdering::Above);
169
170 assert_eq!(1.range_cmp(1..2), RangeOrdering::Inside);
172 assert_eq!(1.range_cmp(&1..&2), RangeOrdering::Inside);
173
174 assert_eq!(1.range_cmp(2..3), RangeOrdering::Below);
176 assert_eq!(1.range_cmp(&2..&3), RangeOrdering::Below);
177 }
178
179 #[test]
180 fn range_inclusive() {
181 assert_eq!(1.range_cmp(0..=0), RangeOrdering::Above);
183 assert_eq!(1.range_cmp(&0..=&0), RangeOrdering::Above);
184
185 assert_eq!(1.range_cmp(1..=1), RangeOrdering::Inside);
187 assert_eq!(1.range_cmp(&1..=&1), RangeOrdering::Inside);
188
189 assert_eq!(1.range_cmp(2..=2), RangeOrdering::Below);
191 assert_eq!(1.range_cmp(&2..=&2), RangeOrdering::Below);
192 }
193
194 #[test]
195 fn range_to_inclusive() {
196 assert_eq!(1.range_cmp(..=0), RangeOrdering::Above);
198 assert_eq!(1.range_cmp(..=&0), RangeOrdering::Above);
199
200 assert_eq!(1.range_cmp(..=1), RangeOrdering::Inside);
202 assert_eq!(1.range_cmp(..=&1), RangeOrdering::Inside);
203 }
204
205 #[test]
206 fn bounds_full() {
207 let bounds: (Bound<i32>, Bound<i32>) = (Bound::Unbounded, Bound::Unbounded);
209 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
210 }
211
212 #[test]
213 fn bounds_from() {
214 let bounds = (Bound::Included(1), Bound::Unbounded);
216 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
217
218 let bounds = (Bound::Included(&1), Bound::Unbounded);
219 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
220
221 let bounds = (Bound::Included(2), Bound::Unbounded);
223 assert_eq!(1.range_cmp(bounds), RangeOrdering::Below);
224
225 let bounds = (Bound::Included(&2), Bound::Unbounded);
226 assert_eq!(1.range_cmp(bounds), RangeOrdering::Below);
227 }
228
229 #[test]
230 fn bounds_to() {
231 let bounds = (Bound::Unbounded, Bound::Excluded(1));
233 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
234
235 let bounds = (Bound::Unbounded, Bound::Excluded(&1));
236 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
237
238 let bounds = (Bound::Unbounded, Bound::Excluded(2));
240 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
241
242 let bounds = (Bound::Unbounded, Bound::Excluded(&2));
243 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
244 }
245
246 #[test]
247 fn bounds() {
248 let bounds = (Bound::Included(0), Bound::Excluded(1));
250 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
251
252 let bounds = (Bound::Included(&0), Bound::Excluded(&1));
253 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
254
255 let bounds = (Bound::Included(1), Bound::Excluded(2));
257 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
258
259 let bounds = (Bound::Included(&1), Bound::Excluded(&2));
260 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
261
262 let bounds = (Bound::Included(2), Bound::Excluded(3));
264 assert_eq!(1.range_cmp(bounds), RangeOrdering::Below);
265
266 let bounds = (Bound::Included(&2), Bound::Excluded(&3));
267 assert_eq!(1.range_cmp(bounds), RangeOrdering::Below);
268 }
269
270 #[test]
271 fn bounds_inclusive() {
272 let bounds = (Bound::Included(0), Bound::Included(0));
274 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
275
276 let bounds = (Bound::Included(&0), Bound::Included(&0));
277 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
278
279 let bounds = (Bound::Included(1), Bound::Included(1));
281 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
282
283 let bounds = (Bound::Included(&1), Bound::Included(&1));
284 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
285
286 let bounds = (Bound::Included(2), Bound::Included(2));
288 assert_eq!(1.range_cmp(bounds), RangeOrdering::Below);
289
290 let bounds = (Bound::Included(&2), Bound::Included(&2));
291 assert_eq!(1.range_cmp(bounds), RangeOrdering::Below);
292 }
293
294 #[test]
295 fn bounds_to_inclusive() {
296 let bounds = (Bound::Unbounded, Bound::Included(0));
298 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
299
300 let bounds = (Bound::Unbounded, Bound::Included(&0));
301 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
302
303 let bounds = (Bound::Unbounded, Bound::Included(1));
305 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
306
307 let bounds = (Bound::Unbounded, Bound::Included(&1));
308 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
309 }
310
311 #[test]
312 fn bounds_exclusive_inclusive() {
313 let bounds: (Bound<i32>, Bound<i32>) = (Bound::Excluded(-1), Bound::Included(0));
315 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
316
317 let bounds: (Bound<&i32>, Bound<&i32>) = (Bound::Excluded(&-1), Bound::Included(&0));
318 assert_eq!(1.range_cmp(bounds), RangeOrdering::Above);
319
320 let bounds: (Bound<i32>, Bound<i32>) = (Bound::Excluded(0), Bound::Included(1));
322 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
323
324 let bounds: (Bound<&i32>, Bound<&i32>) = (Bound::Excluded(&0), Bound::Included(&1));
325 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
326
327 let bounds: (Bound<i32>, Bound<i32>) = (Bound::Excluded(1), Bound::Included(2));
329 assert_eq!(1.range_cmp(bounds), RangeOrdering::Below);
330
331 let bounds: (Bound<&i32>, Bound<&i32>) = (Bound::Excluded(&1), Bound::Included(&2));
332 assert_eq!(1.range_cmp(bounds), RangeOrdering::Below);
333 }
334
335 #[test]
336 fn bounds_as_reference() {
337 let bounds = 0..2;
338 assert_eq!(1.range_cmp(&bounds), RangeOrdering::Inside);
339 assert_eq!(1.range_cmp(bounds), RangeOrdering::Inside);
340 }
341
342 #[test]
343 fn empty_ranges() {
344 assert_eq!(0.range_cmp(0..0), RangeOrdering::Above);
346 assert_eq!(0.range_cmp(&0..&0), RangeOrdering::Above);
347
348 assert_eq!(0.range_cmp(..0u32), RangeOrdering::Above);
350 assert_eq!(0.range_cmp(..&0u32), RangeOrdering::Above);
351
352 assert_eq!(30.range_cmp(45..35), RangeOrdering::Below);
354 assert_eq!(30.range_cmp(&45..&35), RangeOrdering::Below);
355
356 assert_eq!(30.range_cmp(25..15), RangeOrdering::Above);
358 assert_eq!(30.range_cmp(&25..&15), RangeOrdering::Above);
359 }
360}