use std::fmt::Debug;
use std::ops::{Bound, RangeBounds};
use crate::error::RangeBoundError;
use crate::lower::LowerBound;
use crate::upper::UpperBound;
#[derive(Debug, Clone, Copy, Hash)]
pub struct OrdRange<T> {
pub start: LowerBound<T>,
pub end: UpperBound<T>,
}
impl<T: Clone + Copy> OrdRange<T> {
pub fn new(range_bounds: impl RangeBounds<T>) -> Self {
let start = LowerBound(range_bounds.start_bound().cloned());
let end = UpperBound(range_bounds.end_bound().cloned());
OrdRange { start, end }
}
pub fn take(self) -> (Bound<T>, Bound<T>) {
(self.start.0, self.end.0)
}
}
impl<T> TryFrom<(LowerBound<T>, UpperBound<T>)> for OrdRange<T> {
type Error = RangeBoundError;
fn try_from(value: (LowerBound<T>, UpperBound<T>)) -> Result<Self, Self::Error> {
Ok(OrdRange {
start: value.0,
end: value.1,
})
}
}
impl<T> TryFrom<(LowerBound<T>, LowerBound<T>)> for OrdRange<T>
where
LowerBound<T>: TryInto<UpperBound<T>>,
T: Clone + Copy,
{
type Error = <LowerBound<T> as TryInto<UpperBound<T>>>::Error;
fn try_from((lower, upper): (LowerBound<T>, LowerBound<T>)) -> Result<Self, Self::Error> {
Ok(OrdRange {
start: lower,
end: upper.try_into()?,
})
}
}
impl<T> TryFrom<(UpperBound<T>, UpperBound<T>)> for OrdRange<T>
where
UpperBound<T>: TryInto<LowerBound<T>>,
T: Clone + Copy,
{
type Error = <UpperBound<T> as TryInto<LowerBound<T>>>::Error;
fn try_from((lower, upper): (UpperBound<T>, UpperBound<T>)) -> Result<Self, Self::Error> {
Ok(OrdRange {
start: lower.try_into()?,
end: upper,
})
}
}
impl<T> TryFrom<(UpperBound<T>, LowerBound<T>)> for OrdRange<T>
where
UpperBound<T>: TryInto<LowerBound<T>, Error = RangeBoundError>,
LowerBound<T>: TryInto<UpperBound<T>, Error = RangeBoundError>,
T: Clone + Copy,
{
type Error = RangeBoundError;
fn try_from((lower, upper): (UpperBound<T>, LowerBound<T>)) -> Result<Self, Self::Error> {
Ok(OrdRange {
start: lower.try_into()?,
end: upper.try_into()?,
})
}
}
impl<T> PartialEq for OrdRange<T>
where
LowerBound<T>: Ord,
UpperBound<T>: Ord,
{
fn eq(&self, other: &Self) -> bool {
self.start == other.start && self.end == other.end
}
}
impl<T> Eq for OrdRange<T>
where
LowerBound<T>: Ord,
UpperBound<T>: Ord,
{
}
impl<T> RangeBounds<T> for OrdRange<T> {
fn start_bound(&self) -> std::ops::Bound<&T> {
self.start.0.as_ref()
}
fn end_bound(&self) -> std::ops::Bound<&T> {
self.end.0.as_ref()
}
}