1use crate::nothing_between::NothingBetween;
2use crate::step::Step;
3use ::core::cmp::{Ordering, PartialOrd};
4
5pub(crate) enum Bound<T> {
11 LeftUnbounded,
12 LeftOf(T),
13 RightOf(T),
14 RightUnbounded,
15}
16
17impl<T> Bound<T> {
18 pub(crate) fn left_of(&self, value: &T) -> bool
20 where
21 T: PartialOrd,
22 {
23 match self {
24 Bound::LeftUnbounded => true,
25 Bound::LeftOf(point) => *point <= *value,
26 Bound::RightOf(point) => *point < *value,
27 Bound::RightUnbounded => false,
28 }
29 }
30
31 pub(crate) fn right_of(&self, value: &T) -> bool
33 where
34 T: PartialOrd,
35 {
36 match self {
37 Bound::LeftUnbounded => false,
38 Bound::LeftOf(point) => *value < *point,
39 Bound::RightOf(point) => *value <= *point,
40 Bound::RightUnbounded => true,
41 }
42 }
43
44 pub(crate) fn value(&self) -> Option<&T> {
47 match self {
48 Bound::LeftUnbounded | Bound::RightUnbounded => None,
49 Bound::LeftOf(p) | Bound::RightOf(p) => Some(p),
50 }
51 }
52
53 pub(crate) fn as_ref(&self) -> Bound<&T> {
55 match self {
56 Bound::LeftUnbounded => Bound::LeftUnbounded,
57 Bound::LeftOf(point) => Bound::LeftOf(point),
58 Bound::RightOf(point) => Bound::RightOf(point),
59 Bound::RightUnbounded => Bound::RightUnbounded,
60 }
61 }
62}
63
64impl<T> ::core::fmt::Debug for Bound<T>
65where
66 T: ::core::fmt::Debug,
67{
68 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
69 match self {
70 Bound::LeftUnbounded => write!(f, "-infinity")?,
71 Bound::LeftOf(point) => write!(f, "LeftOf({point:?})")?,
72 Bound::RightOf(point) => write!(f, "RightOf({point:?})")?,
73 Bound::RightUnbounded => write!(f, "+infinity")?,
74 }
75 Ok(())
76 }
77}
78
79impl<T> ::core::hash::Hash for Bound<T>
80where
81 T: ::core::hash::Hash + Step,
82{
83 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
84 match self {
93 Bound::LeftUnbounded | Bound::RightUnbounded => {
94 core::mem::discriminant(self).hash(state);
95 }
96 Bound::LeftOf(point) => {
97 core::mem::discriminant(self).hash(state);
98 point.hash(state);
99 }
100 Bound::RightOf(point) => {
101 let next = point.forward(1);
102 if let Some(next) = next {
103 Bound::LeftOf(next).hash(state);
104 return;
105 }
106 core::mem::discriminant(self).hash(state);
107 point.hash(state);
108 }
109 }
110 }
111}
112
113impl<T> PartialEq<Bound<&T>> for Bound<T>
114where
115 T: PartialOrd + NothingBetween,
116{
117 fn eq(&self, other: &Bound<&T>) -> bool {
120 match (self, other) {
121 (Bound::LeftUnbounded, Bound::LeftUnbounded)
122 | (Bound::RightUnbounded, Bound::RightUnbounded) => true,
123 (Bound::LeftOf(s), Bound::LeftOf(o))
124 | (Bound::RightOf(s), Bound::RightOf(o)) => *s == **o,
125 (Bound::LeftOf(s), Bound::RightOf(o)) => match s.partial_cmp(o) {
126 None | Some(Ordering::Less | Ordering::Equal) => false,
127 Some(Ordering::Greater) => (*o).nothing_between(s),
128 },
129 (Bound::RightOf(s), Bound::LeftOf(o)) => match s.partial_cmp(o) {
130 None | Some(Ordering::Equal | Ordering::Greater) => false,
131 Some(Ordering::Less) => s.nothing_between(o),
132 },
133 (Bound::LeftUnbounded, _)
134 | (_, Bound::LeftUnbounded)
135 | (_, Bound::RightUnbounded)
136 | (Bound::RightUnbounded, _) => false,
137 }
138 }
139}
140
141impl<T> PartialEq for Bound<T>
142where
143 T: PartialOrd + NothingBetween,
144{
145 fn eq(&self, other: &Bound<T>) -> bool {
148 self.eq(&other.as_ref())
149 }
150}
151
152impl<T> Eq for Bound<T> where T: PartialOrd + NothingBetween {}
153
154impl<T> PartialOrd for Bound<T>
155where
156 T: PartialOrd + NothingBetween,
157{
158 fn partial_cmp(&self, other: &Bound<T>) -> Option<Ordering> {
159 self.partial_cmp(&other.as_ref())
160 }
161}
162
163impl<T> PartialOrd<Bound<&T>> for Bound<T>
164where
165 T: PartialOrd + NothingBetween,
166{
167 fn partial_cmp(&self, other: &Bound<&T>) -> Option<Ordering> {
178 match (self, other) {
179 (Bound::LeftUnbounded, Bound::LeftUnbounded)
180 | (Bound::RightUnbounded, Bound::RightUnbounded) => {
181 Some(Ordering::Equal)
182 }
183 (Bound::LeftOf(s), Bound::LeftOf(o))
184 | (Bound::RightOf(s), Bound::RightOf(o)) => s.partial_cmp(*o),
185 (Bound::LeftOf(s), Bound::RightOf(o)) => match s.partial_cmp(o) {
186 None => None,
187 Some(Ordering::Less | Ordering::Equal) => Some(Ordering::Less),
188 Some(Ordering::Greater) => Some(if (*o).nothing_between(s) {
189 Ordering::Equal
190 } else {
191 Ordering::Greater
192 }),
193 },
194 (Bound::RightOf(s), Bound::LeftOf(o)) => match s.partial_cmp(*o) {
195 None => None,
196 Some(Ordering::Less) => Some(if s.nothing_between(*o) {
197 Ordering::Equal
198 } else {
199 Ordering::Less
200 }),
201 Some(Ordering::Equal | Ordering::Greater) => {
202 Some(Ordering::Greater)
203 }
204 },
205 (Bound::LeftUnbounded, _) => Some(Ordering::Less),
206 (_, Bound::LeftUnbounded) => Some(Ordering::Greater),
207 (_, Bound::RightUnbounded) => Some(Ordering::Less),
208 (Bound::RightUnbounded, _) => Some(Ordering::Greater),
209 }
210 }
211}
212
213impl<T> ::core::clone::Clone for Bound<T>
214where
215 T: Clone,
216{
217 fn clone(&self) -> Self {
218 match self {
219 Bound::LeftUnbounded => Bound::LeftUnbounded,
220 Bound::RightUnbounded => Bound::RightUnbounded,
221 Bound::LeftOf(point) => Bound::LeftOf(point.clone()),
222 Bound::RightOf(point) => Bound::RightOf(point.clone()),
223 }
224 }
225}
226
227impl<T> Copy for Bound<T> where T: Copy {}