use crate::nothing_between::NothingBetween;
use crate::step::Step;
use ::core::cmp::{Ordering, PartialOrd};
pub(crate) enum Bound<T> {
LeftUnbounded,
LeftOf(T),
RightOf(T),
RightUnbounded,
}
impl<T> Bound<T> {
pub(crate) fn left_of(&self, value: &T) -> bool
where
T: PartialOrd,
{
match self {
Bound::LeftUnbounded => true,
Bound::LeftOf(point) => *point <= *value,
Bound::RightOf(point) => *point < *value,
Bound::RightUnbounded => false,
}
}
pub(crate) fn right_of(&self, value: &T) -> bool
where
T: PartialOrd,
{
match self {
Bound::LeftUnbounded => false,
Bound::LeftOf(point) => *value < *point,
Bound::RightOf(point) => *value <= *point,
Bound::RightUnbounded => true,
}
}
pub(crate) fn value(&self) -> Option<&T> {
match self {
Bound::LeftUnbounded | Bound::RightUnbounded => None,
Bound::LeftOf(p) | Bound::RightOf(p) => Some(p),
}
}
pub(crate) fn as_ref(&self) -> Bound<&T> {
match self {
Bound::LeftUnbounded => Bound::LeftUnbounded,
Bound::LeftOf(point) => Bound::LeftOf(point),
Bound::RightOf(point) => Bound::RightOf(point),
Bound::RightUnbounded => Bound::RightUnbounded,
}
}
}
impl<T> ::core::fmt::Debug for Bound<T>
where
T: ::core::fmt::Debug,
{
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
match self {
Bound::LeftUnbounded => write!(f, "-infinity")?,
Bound::LeftOf(point) => write!(f, "LeftOf({point:?})")?,
Bound::RightOf(point) => write!(f, "RightOf({point:?})")?,
Bound::RightUnbounded => write!(f, "+infinity")?,
}
Ok(())
}
}
impl<T> ::core::hash::Hash for Bound<T>
where
T: ::core::hash::Hash + Step,
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
match self {
Bound::LeftUnbounded | Bound::RightUnbounded => {
core::mem::discriminant(self).hash(state);
}
Bound::LeftOf(point) => {
core::mem::discriminant(self).hash(state);
point.hash(state);
}
Bound::RightOf(point) => {
let next = point.forward(1);
if let Some(next) = next {
Bound::LeftOf(next).hash(state);
return;
}
core::mem::discriminant(self).hash(state);
point.hash(state);
}
}
}
}
impl<T> PartialEq<Bound<&T>> for Bound<T>
where
T: PartialOrd + NothingBetween,
{
fn eq(&self, other: &Bound<&T>) -> bool {
match (self, other) {
(Bound::LeftUnbounded, Bound::LeftUnbounded)
| (Bound::RightUnbounded, Bound::RightUnbounded) => true,
(Bound::LeftOf(s), Bound::LeftOf(o))
| (Bound::RightOf(s), Bound::RightOf(o)) => *s == **o,
(Bound::LeftOf(s), Bound::RightOf(o)) => match s.partial_cmp(o) {
None | Some(Ordering::Less | Ordering::Equal) => false,
Some(Ordering::Greater) => (*o).nothing_between(s),
},
(Bound::RightOf(s), Bound::LeftOf(o)) => match s.partial_cmp(o) {
None | Some(Ordering::Equal | Ordering::Greater) => false,
Some(Ordering::Less) => s.nothing_between(o),
},
(Bound::LeftUnbounded, _)
| (_, Bound::LeftUnbounded)
| (_, Bound::RightUnbounded)
| (Bound::RightUnbounded, _) => false,
}
}
}
impl<T> PartialEq for Bound<T>
where
T: PartialOrd + NothingBetween,
{
fn eq(&self, other: &Bound<T>) -> bool {
self.eq(&other.as_ref())
}
}
impl<T> Eq for Bound<T> where T: PartialOrd + NothingBetween {}
impl<T> PartialOrd for Bound<T>
where
T: PartialOrd + NothingBetween,
{
fn partial_cmp(&self, other: &Bound<T>) -> Option<Ordering> {
self.partial_cmp(&other.as_ref())
}
}
impl<T> PartialOrd<Bound<&T>> for Bound<T>
where
T: PartialOrd + NothingBetween,
{
fn partial_cmp(&self, other: &Bound<&T>) -> Option<Ordering> {
match (self, other) {
(Bound::LeftUnbounded, Bound::LeftUnbounded)
| (Bound::RightUnbounded, Bound::RightUnbounded) => {
Some(Ordering::Equal)
}
(Bound::LeftOf(s), Bound::LeftOf(o))
| (Bound::RightOf(s), Bound::RightOf(o)) => s.partial_cmp(*o),
(Bound::LeftOf(s), Bound::RightOf(o)) => match s.partial_cmp(o) {
None => None,
Some(Ordering::Less | Ordering::Equal) => Some(Ordering::Less),
Some(Ordering::Greater) => Some(if (*o).nothing_between(s) {
Ordering::Equal
} else {
Ordering::Greater
}),
},
(Bound::RightOf(s), Bound::LeftOf(o)) => match s.partial_cmp(*o) {
None => None,
Some(Ordering::Less) => Some(if s.nothing_between(*o) {
Ordering::Equal
} else {
Ordering::Less
}),
Some(Ordering::Equal | Ordering::Greater) => {
Some(Ordering::Greater)
}
},
(Bound::LeftUnbounded, _) => Some(Ordering::Less),
(_, Bound::LeftUnbounded) => Some(Ordering::Greater),
(_, Bound::RightUnbounded) => Some(Ordering::Less),
(Bound::RightUnbounded, _) => Some(Ordering::Greater),
}
}
}
impl<T> ::core::clone::Clone for Bound<T>
where
T: Clone,
{
fn clone(&self) -> Self {
match self {
Bound::LeftUnbounded => Bound::LeftUnbounded,
Bound::RightUnbounded => Bound::RightUnbounded,
Bound::LeftOf(point) => Bound::LeftOf(point.clone()),
Bound::RightOf(point) => Bound::RightOf(point.clone()),
}
}
}
impl<T> Copy for Bound<T> where T: Copy {}