use crate::bound::Bound;
use crate::normalize::Finite;
use crate::normalize::Normalize;
use crate::raw_interval::RawInterval;
use crate::raw_interval::IntervalParseError;
#[cfg(feature="serde")] use serde::Deserialize;
#[cfg(feature="serde")] use serde::Serialize;
use std::iter::FusedIterator;
use std::ops::Range;
use std::ops::RangeFrom;
use std::ops::RangeFull;
use std::ops::RangeTo;
use std::ops::RangeToInclusive;
use std::ops::Sub;
use std::str::FromStr;
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature="serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature="serde", serde(transparent))]
pub struct Interval<T>(pub (crate) RawInterval<T>);
impl<T> Default for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn default() -> Self {
Self::empty()
}
}
impl<T> Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
pub fn write_fmt_with<F>(&self,
f: &mut std::fmt::Formatter<'_>,
write_fn: F)
-> Result<(), std::fmt::Error>
where F: Fn(&T, &mut std::fmt::Formatter<'_>)
-> Result<(), std::fmt::Error>
{
self.0.write_fmt_with(f, write_fn)
}
pub fn from_str_with<F, E>(s: &str, read_fn: F)
-> Result<Self, IntervalParseError<E>>
where F: Fn(&str) -> Result<T, E>
{
Ok(Self(RawInterval::<T>::from_str_with(s, read_fn)?.normalized()))
}
}
impl<T> Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
#[inline]
#[must_use]
pub fn new(left: Bound<T>, right: Bound<T>) -> Self {
Self(RawInterval::new(left, right).normalized())
}
#[inline]
#[must_use]
pub fn empty() -> Self {
Self(RawInterval::Empty)
}
#[inline]
#[must_use]
pub fn point(point: T) -> Self {
Self(RawInterval::Point(point))
}
#[inline]
#[must_use]
pub fn open(left: T, right: T) -> Self {
Self(RawInterval::open(left, right).normalized())
}
#[inline]
#[must_use]
pub fn left_open(left: T, right: T) -> Self {
Self(RawInterval::left_open(left, right).normalized())
}
#[inline]
#[must_use]
pub fn right_open(left: T, right: T) -> Self {
Self(RawInterval::right_open(left, right).normalized())
}
#[inline]
#[must_use]
pub fn closed(left: T, right: T) -> Self {
Self(RawInterval::closed(left, right).normalized())
}
#[inline]
#[must_use]
pub fn left_closed(left: T, right: T) -> Self {
Self::right_open(left, right)
}
#[inline]
#[must_use]
pub fn right_closed(left: T, right: T) -> Self {
Self::left_open(left, right)
}
#[inline]
#[must_use]
pub fn unbounded_from(point: T) -> Self {
Self(RawInterval::From(point).normalized())
}
#[inline]
#[must_use]
pub fn unbounded_to(point: T) -> Self {
Self(RawInterval::To(point).normalized())
}
#[inline]
#[must_use]
pub fn unbounded_up_from(point: T) -> Self {
Self(RawInterval::UpFrom(point).normalized())
}
#[inline]
#[must_use]
pub fn unbounded_up_to(point: T) -> Self {
Self(RawInterval::UpTo(point).normalized())
}
#[inline]
#[must_use]
pub fn full() -> Self {
Self(RawInterval::Full.normalized())
}
#[must_use]
pub fn into_non_empty(self) -> Option<Self> {
if self.is_empty() {
None
} else {
Some(self)
}
}
#[inline]
#[must_use]
pub fn bounds(&self) -> Option<(Bound<T>, Bound<T>)> {
self.0.bounds()
}
#[inline]
#[must_use]
pub fn lower_bound(&self) -> Option<Bound<T>> {
self.0.lower_bound()
}
#[inline]
#[must_use]
pub fn upper_bound(&self) -> Option<Bound<T>> {
self.0.upper_bound()
}
#[inline]
#[must_use]
pub fn infimum(&self) -> Option<T> {
self.0.infimum()
}
#[inline]
#[must_use]
pub fn supremum(&self) -> Option<T> {
self.0.supremum()
}
#[inline]
#[must_use]
pub fn extrema(&self) -> Option<(T, T)> {
self.0.extrema()
}
pub fn size(&self) -> Option<T> where T: Sub<Output=T> {
match (self.infimum(), self.supremum()) {
(Some(l), Some(u)) => Some(u - l),
_ => None,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
matches!(self.0, RawInterval::Empty)
}
#[inline]
pub fn is_degenerate(&self) -> bool {
matches!(self.0, RawInterval::Point(_))
}
#[inline]
pub fn is_proper(&self) -> bool {
!matches!(self.0,
RawInterval::Empty |
RawInterval::Point(_) )
}
#[inline]
pub fn is_open(&self) -> bool {
!matches!(self.0,
RawInterval::Point(_) |
RawInterval::Closed(_, _) )
}
#[inline]
pub fn is_left_open(&self) -> bool {
matches!(self.0,
RawInterval::LeftOpen(_, _) |
RawInterval::UpTo(_) |
RawInterval::To(_) |
RawInterval::Full )
}
#[inline]
pub fn is_right_open(&self) -> bool {
matches!(self.0,
RawInterval::RightOpen(_, _) |
RawInterval::UpFrom(_) |
RawInterval::From(_) |
RawInterval::Full )
}
#[inline]
pub fn is_half_open(&self) -> bool {
!matches!(self.0,
RawInterval::Empty |
RawInterval::Point(_) |
RawInterval::Closed(_, _) )
}
#[inline]
pub fn is_closed(&self) -> bool {
matches!(self.0,
RawInterval::Empty |
RawInterval::Point(_) |
RawInterval::Closed(_, _) |
RawInterval::Full )
}
#[inline]
pub fn is_left_closed(&self) -> bool {
matches!(self.0,
RawInterval::Point(_) |
RawInterval::RightOpen(_, _) |
RawInterval::Closed(_, _) |
RawInterval::From(_) )
}
#[inline]
pub fn is_right_closed(&self) -> bool {
matches!(self.0,
RawInterval::Point(_) |
RawInterval::LeftOpen(_, _) |
RawInterval::Closed(_, _) |
RawInterval::To(_) )
}
#[inline]
pub fn is_half_closed(&self) -> bool {
matches!(self.0,
RawInterval::LeftOpen(_, _) |
RawInterval::RightOpen(_, _) |
RawInterval::To(_) |
RawInterval::From(_) )
}
#[inline]
pub fn is_bounded(&self) -> bool {
!matches!(self.0,
RawInterval::UpTo(_) |
RawInterval::UpFrom(_) |
RawInterval::To(_) |
RawInterval::From(_) |
RawInterval::Full )
}
#[inline]
pub fn is_left_bounded(&self) -> bool {
!matches!(self.0,
RawInterval::UpTo(_) |
RawInterval::To(_) |
RawInterval::Full )
}
#[inline]
pub fn is_right_bounded(&self) -> bool {
!matches!(self.0,
RawInterval::UpFrom(_) |
RawInterval::From(_) |
RawInterval::Full )
}
#[inline]
pub fn is_half_bounded(&self) -> bool {
matches!(self.0,
RawInterval::UpTo(_) |
RawInterval::UpFrom(_) |
RawInterval::To(_) |
RawInterval::From(_) )
}
#[inline]
pub fn contains(&self, point: &T) -> bool {
self.0.contains(point)
}
pub fn intersects(&self, other: &Self) -> bool {
self.0.intersects(&other.0)
}
pub fn is_adjacent_to(&self, other: &Self) -> bool {
self.0 .is_adjacent_to(&other.0)
}
pub fn complement(&self) -> impl Iterator<Item=Self> {
self.0
.complement()
.map(Normalize::normalized)
.map(Interval)
}
#[must_use]
pub fn intersect(&self, other: &Self) -> Self {
self.0.intersect(&other.0).normalized().into()
}
pub fn union(&self, other: &Self) -> impl Iterator<Item=Self> {
self.0
.union(&other.0)
.map(Normalize::normalized)
.map(Interval)
}
pub fn minus(&self, other: &Self) -> impl Iterator<Item=Self> {
self.0
.minus(&other.0)
.map(Normalize::normalized)
.map(Interval)
}
#[must_use]
pub fn enclose(&self, other: &Self) -> Self {
self.0.enclose(&other.0).normalized().into()
}
#[must_use]
pub fn closure(&self) -> Self {
self.0.closure().normalized().into()
}
}
impl<T> Interval<T>
where
T: Ord + Clone + Sub<T>,
RawInterval<T>: Normalize,
{
#[inline]
#[must_use]
pub fn width(&self) -> Option<T::Output> {
self.0.width()
}
}
impl<T> From<RawInterval<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(raw_interval: RawInterval<T>) -> Self {
Self(raw_interval.normalized())
}
}
impl<T> From<T> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(point: T) -> Self {
Self(RawInterval::Point(point).normalized())
}
}
impl<T> From<Range<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(r: Range<T>) -> Self {
Self(RawInterval::right_open(r.start, r.end).normalized())
}
}
impl<T> From<RangeFrom<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(r: RangeFrom<T>) -> Self {
Self(RawInterval::From(r.start).normalized())
}
}
impl<T> From<RangeTo<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(r: RangeTo<T>) -> Self {
Self(RawInterval::UpTo(r.end).normalized())
}
}
impl<T> From<RangeToInclusive<T>> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(r: RangeToInclusive<T>) -> Self {
Self(RawInterval::To(r.end).normalized())
}
}
impl<T> From<RangeFull> for Interval<T>
where
T: Ord + Clone,
RawInterval<T>: Normalize,
{
fn from(_r: RangeFull) -> Self {
Self(RawInterval::Full.normalized())
}
}
impl<T> Interval<T> where T: Ord + Clone + Finite {
pub fn iter(&self) -> Iter<T> {
Iter {
inner: self.clone(),
}
}
}
impl<T> IntoIterator for Interval<T>
where T: Ord + Clone + Finite,
{
type Item = T;
type IntoIter = Iter<T>;
fn into_iter(self) -> Self::IntoIter {
Iter { inner: self }
}
}
impl<'a, T> IntoIterator for &'a Interval<T>
where T: Ord + Clone + Finite,
{
type Item = T;
type IntoIter = Iter<T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug)]
pub struct Iter<T> where T: Ord + Clone {
inner: Interval<T>,
}
impl<T> Iterator for Iter<T>
where T: Ord + Clone + Finite
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match self.inner.lower_bound() {
Some(Bound::Include(lb)) => {
self.inner = self.inner
.minus(&lb.clone().into())
.next()
.unwrap_or_else(Interval::empty);
Some(lb)
},
None => None,
_ => unreachable!("iter for Finite interval with open lower bound"),
}
}
}
impl<T> DoubleEndedIterator for Iter<T>
where T: Ord + Clone + Finite
{
fn next_back(&mut self) -> Option<Self::Item> {
match self.inner.upper_bound() {
Some(Bound::Include(ub)) => {
self.inner = self.inner
.minus(&ub.clone().into())
.next()
.unwrap_or_else(Interval::empty);
Some(ub)
},
None => None,
_ => unreachable!("iter for Finite interval with open upper bound"),
}
}
}
impl<T> FusedIterator for Iter<T>
where
T: Ord + Clone + Finite
{}
impl<T> std::fmt::Display for Interval<T> where T: std::fmt::Display {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl<T> FromStr for Interval<T> where T: Ord + FromStr + Finite {
type Err = IntervalParseError<T::Err>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(RawInterval::<T>::from_str(s)?.normalized()))
}
}
impl<T> std::fmt::Binary for Interval<T>
where T: std::fmt::Binary
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> Result<(), std::fmt::Error>
{
self.0.write_fmt_with(f, |p, f| std::fmt::Binary::fmt(p, f))
}
}
impl<T> std::fmt::Octal for Interval<T>
where T: std::fmt::Octal
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> Result<(), std::fmt::Error>
{
self.0.write_fmt_with(f, |p, f| std::fmt::Octal::fmt(p, f))
}
}
impl<T> std::fmt::LowerHex for Interval<T>
where T: std::fmt::LowerHex
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> Result<(), std::fmt::Error>
{
self.0.write_fmt_with(f, |p, f| std::fmt::LowerHex::fmt(p, f))
}
}
impl<T> std::fmt::UpperHex for Interval<T>
where T: std::fmt::UpperHex
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> Result<(), std::fmt::Error>
{
self.0.write_fmt_with(f, |p, f| std::fmt::UpperHex::fmt(p, f))
}
}
impl<T> std::fmt::LowerExp for Interval<T>
where T: std::fmt::LowerExp
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> Result<(), std::fmt::Error>
{
self.0.write_fmt_with(f, |p, f| std::fmt::LowerExp::fmt(p, f))
}
}
impl<T> std::fmt::UpperExp for Interval<T>
where T: std::fmt::UpperExp
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> Result<(), std::fmt::Error>
{
self.0.write_fmt_with(f, |p, f| std::fmt::UpperExp::fmt(p, f))
}
}
impl<T> std::fmt::Pointer for Interval<T>
where T: std::fmt::Pointer
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> Result<(), std::fmt::Error>
{
self.0.write_fmt_with(f, |p, f| std::fmt::Pointer::fmt(p, f))
}
}