hash_roll/
range.rs

1use std::ops::Bound::{self, *};
2
3pub trait RangeExt<T> {
4    fn exceeds_max(&self, other: &T) -> bool
5    where
6        T: PartialOrd<T>;
7
8    fn under_min(&self, item: &T) -> bool
9    where
10        T: PartialOrd<T>;
11
12    fn contains(&self, item: &T) -> bool
13    where
14        T: PartialOrd<T>;
15
16    fn into_tuple(self) -> (std::ops::Bound<T>, std::ops::Bound<T>)
17    where
18        T: Copy + std::marker::Sized;
19}
20
21impl<T, R: std::ops::RangeBounds<T>> RangeExt<T> for R {
22    fn exceeds_max(&self, item: &T) -> bool
23    where
24        T: PartialOrd<T>,
25    {
26        match self.end_bound() {
27            Included(ref i) => {
28                if item > i {
29                    return true;
30                }
31            }
32            Excluded(ref i) => {
33                if item >= i {
34                    return true;
35                }
36            }
37            Unbounded => {}
38        }
39
40        false
41    }
42
43    fn under_min(&self, item: &T) -> bool
44    where
45        T: PartialOrd<T>,
46    {
47        match self.start_bound() {
48            Included(ref i) => {
49                if item < i {
50                    return true;
51                }
52            }
53            Excluded(ref i) => {
54                if item <= i {
55                    return true;
56                }
57            }
58            Unbounded => {}
59        }
60
61        false
62    }
63
64    fn contains(&self, item: &T) -> bool
65    where
66        T: PartialOrd<T>,
67    {
68        /* not excluded by lower */
69        if self.under_min(item) {
70            return false;
71        }
72
73        if self.exceeds_max(item) {
74            return false;
75        }
76
77        true
78    }
79
80    fn into_tuple(self) -> (std::ops::Bound<T>, std::ops::Bound<T>)
81    where
82        T: Copy + std::marker::Sized,
83    {
84        (
85            bound_cloned(self.start_bound()),
86            bound_cloned(self.end_bound()),
87        )
88    }
89}
90
91/// Map a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound.
92///
93/// # Examples
94///
95/// ```
96/// use std::ops::Bound::*;
97/// use std::ops::RangeBounds;
98/// use hash_roll::range::bound_cloned;
99///
100/// assert_eq!((1..12).start_bound(), Included(&1));
101/// assert_eq!(bound_cloned((1..12).start_bound()), Included(1));
102/// ```
103pub fn bound_cloned<T: Clone>(src: std::ops::Bound<&T>) -> std::ops::Bound<T> {
104    match src {
105        Bound::Unbounded => Bound::Unbounded,
106        Bound::Included(x) => Bound::Included(x.clone()),
107        Bound::Excluded(x) => Bound::Excluded(x.clone()),
108    }
109}