use crate::interval::LeftT::*;
use crate::interval::RightT::*;
use crate::interval::*;
use core::cmp::Ordering;
#[derive(Debug, Clone, PartialEq)]
pub enum EndpointOC<T> {
Open(T),
Closed(T),
}
impl<T> EndpointToggle for EndpointOC<T> {
fn toggle(self) -> Self {
match self {
EndpointOC::Open(a) => EndpointOC::Closed(a),
EndpointOC::Closed(a) => EndpointOC::Open(a),
}
}
}
impl<E> EndpointMap for EndpointOC<E> {
type EndpointValue = E;
fn map_endpoint(self, f: impl Fn(Self::EndpointValue) -> Self::EndpointValue) -> Self {
match self {
EndpointOC::Open(a) => EndpointOC::Open(f(a)),
EndpointOC::Closed(a) => EndpointOC::Closed(f(a)),
}
}
}
impl<T, U> EndpointMapInto<U> for EndpointOC<T> {
type EndpointValue = T;
type Output = EndpointOC<U>;
fn map_endpoint_into(self, f: impl Fn(T) -> U) -> EndpointOC<U> {
match self {
EndpointOC::Open(a) => EndpointOC::Open(f(a)),
EndpointOC::Closed(a) => EndpointOC::Closed(f(a)),
}
}
}
impl<T> EndpointOC<T> {
pub fn open(&self) -> Option<T>
where
T: Clone,
{
match self {
EndpointOC::Open(a) => Some(a.clone()),
EndpointOC::Closed(_) => None,
}
}
pub fn closed(&self) -> Option<T>
where
T: Clone,
{
match self {
EndpointOC::Open(_) => None,
EndpointOC::Closed(a) => Some(a.clone()),
}
}
}
impl<T> PartialOrd<LeftT<EndpointOC<T>>> for LeftT<EndpointOC<T>>
where
T: Ord,
{
fn partial_cmp(&self, other: &LeftT<EndpointOC<T>>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T> PartialOrd<RightT<EndpointOC<T>>> for RightT<EndpointOC<T>>
where
T: Ord,
{
fn partial_cmp(&self, other: &RightT<EndpointOC<T>>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T> Eq for LeftT<EndpointOC<T>> where T: Eq {}
impl<T> Eq for RightT<EndpointOC<T>> where T: Eq {}
impl<T> Ord for LeftT<EndpointOC<T>>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
let Left(ref a) = self;
let Left(ref b) = other;
use EndpointOC::*;
use Ordering::*;
match a {
Open(x) => match b {
Open(y) => x.cmp(y),
Closed(y) => match x.cmp(y) {
Less => Less,
Equal => Greater,
Greater => Greater,
},
},
Closed(x) => match b {
Open(y) => match x.cmp(y) {
Less => Less,
Equal => Less,
Greater => Greater,
},
Closed(y) => x.cmp(y),
},
}
}
}
impl<T> Ord for RightT<EndpointOC<T>>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
let Right(ref a) = self;
let Right(ref b) = other;
use EndpointOC::*;
use Ordering::*;
match a {
Open(x) => match b {
Open(y) => x.cmp(y),
Closed(y) => match x.cmp(y) {
Less => Less,
Equal => Less,
Greater => Greater,
},
},
Closed(x) => match b {
Open(y) => match x.cmp(y) {
Less => Less,
Equal => Greater,
Greater => Greater,
},
Closed(y) => x.cmp(y),
},
}
}
}
impl<E> EndpointOC<E> {
pub fn is_open(&self) -> bool {
match self {
EndpointOC::Open(_) => true,
EndpointOC::Closed(_) => false,
}
}
pub fn is_closed(&self) -> bool {
!self.is_open()
}
pub fn toggle(self) -> Self {
match self {
EndpointOC::Open(a) => EndpointOC::Closed(a),
EndpointOC::Closed(a) => EndpointOC::Open(a),
}
}
pub fn toggle_ref(&self) -> Self
where
E: Clone,
{
match self {
EndpointOC::Open(a) => EndpointOC::Closed(a.clone()),
EndpointOC::Closed(a) => EndpointOC::Open(a.clone()),
}
}
}
#[cfg(test)]
mod tests {
use core::cmp::Ordering;
use crate::EndpointOC;
use crate::LeftT;
use crate::RightT;
macro_rules! cmp_m {
($alr:ident, $aoc:ident, $blr:ident, $boc:ident, $e:expr) => {
let va = $alr(EndpointOC::$aoc(2));
let vb = $blr(EndpointOC::$boc(2));
let cc = va.partial_cmp(&vb);
let cx = vb.partial_cmp(&va);
assert_eq!(cc, Some($e));
match ($e) {
Ordering::Equal => assert_eq!(Some(Ordering::Equal), cx),
Ordering::Less => assert_eq!(Some(Ordering::Greater), cx),
Ordering::Greater => assert_eq!(Some(Ordering::Less), cx),
}
let va = $alr(EndpointOC::$aoc(2));
let vb = $blr(EndpointOC::$boc(3));
assert_eq!(va.partial_cmp(&vb), Some(Ordering::Less));
assert_eq!(vb.partial_cmp(&va), Some(Ordering::Greater));
};
}
#[test]
fn cmp_test() {
let left = LeftT::<EndpointOC<i32>>::Left;
let right = RightT::<EndpointOC<i32>>::Right;
cmp_m!(left, Closed, left, Closed, Ordering::Equal);
cmp_m!(right, Closed, right, Closed, Ordering::Equal);
cmp_m!(left, Closed, left, Open, Ordering::Less);
cmp_m!(right, Open, right, Closed, Ordering::Less);
cmp_m!(left, Open, left, Open, Ordering::Equal);
cmp_m!(right, Open, right, Open, Ordering::Equal);
}
}