use crate::interval::LeftT::*;
use crate::interval::RightT::*;
use crate::interval::*;
use core::cmp::Ordering;
#[derive(Debug, Clone, PartialEq)]
pub struct EndpointSymmetric<T>(pub T);
impl<T> EndpointToggle for EndpointSymmetric<T> {
fn toggle(self) -> Self {
self
}
}
impl<E> EndpointMap for EndpointSymmetric<E> {
type EndpointValue = E;
fn map_endpoint(self, f: impl Fn(Self::EndpointValue) -> Self::EndpointValue) -> Self {
EndpointSymmetric(f(self.0))
}
}
impl<T, U> EndpointMapInto<U> for EndpointSymmetric<T> {
type EndpointValue = T;
type Output = EndpointSymmetric<U>;
fn map_endpoint_into(self, f: impl Fn(T) -> U) -> EndpointSymmetric<U> {
EndpointSymmetric(f(self.0))
}
}
impl<T> EndpointSymmetric<T> {
pub fn value(&self) -> &T {
&self.0
}
pub fn into_value(self) -> T {
self.0
}
}
pub fn endpoint_symmetric<T>(value: T) -> EndpointSymmetric<T> {
EndpointSymmetric(value)
}
impl<T> PartialOrd<LeftT<EndpointSymmetric<T>>> for LeftT<EndpointSymmetric<T>>
where
T: Ord,
{
fn partial_cmp(&self, other: &LeftT<EndpointSymmetric<T>>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T> PartialOrd<RightT<EndpointSymmetric<T>>> for RightT<EndpointSymmetric<T>>
where
T: Ord,
{
fn partial_cmp(&self, other: &RightT<EndpointSymmetric<T>>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T> Eq for LeftT<EndpointSymmetric<T>> where T: Eq {}
impl<T> Eq for RightT<EndpointSymmetric<T>> where T: Eq {}
impl<T> Ord for LeftT<EndpointSymmetric<T>>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
let Left(ref a) = self;
let Left(ref b) = other;
a.0.cmp(&b.0)
}
}
impl<T> Ord for RightT<EndpointSymmetric<T>>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
let Right(ref a) = self;
let Right(ref b) = other;
a.0.cmp(&b.0)
}
}
#[cfg(test)]
mod tests {
use core::cmp::Ordering;
use crate::EndpointSymmetric;
use crate::LeftT;
use crate::RightT;
#[test]
fn toggle_is_identity() {
use crate::EndpointToggle;
let e = EndpointSymmetric(5);
let toggled = e.toggle();
assert_eq!(toggled, EndpointSymmetric(5));
}
#[test]
fn map_endpoint() {
use crate::EndpointMap;
let e = EndpointSymmetric(3);
let mapped = e.map_endpoint(|x| x * 2);
assert_eq!(mapped, EndpointSymmetric(6));
}
#[test]
fn left_left_cmp() {
let a = LeftT::Left(EndpointSymmetric(2));
let b = LeftT::Left(EndpointSymmetric(2));
assert_eq!(a.partial_cmp(&b), Some(Ordering::Equal));
let a = LeftT::Left(EndpointSymmetric(1));
let b = LeftT::Left(EndpointSymmetric(3));
assert_eq!(a.partial_cmp(&b), Some(Ordering::Less));
assert_eq!(b.partial_cmp(&a), Some(Ordering::Greater));
}
#[test]
fn right_right_cmp() {
let a = RightT::Right(EndpointSymmetric(2));
let b = RightT::Right(EndpointSymmetric(2));
assert_eq!(a.partial_cmp(&b), Some(Ordering::Equal));
let a = RightT::Right(EndpointSymmetric(1));
let b = RightT::Right(EndpointSymmetric(3));
assert_eq!(a.partial_cmp(&b), Some(Ordering::Less));
assert_eq!(b.partial_cmp(&a), Some(Ordering::Greater));
}
#[test]
fn interval_with_symmetric_endpoints() {
use crate::Interval;
let iv = Interval::new(EndpointSymmetric(2), EndpointSymmetric(5), "A");
assert_eq!(iv.left().endpoint().0, 2);
assert_eq!(iv.right().endpoint().0, 5);
assert_eq!(iv.value(), "A");
}
}