use crate::{
interval::{IncorrectRangeError, Interval, NewWithLenError, TryFromRangeError},
numerated::Numerated,
};
use core::{
fmt::{self, Debug, Display, Formatter},
ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive},
};
use num_traits::bounds::{LowerBounded, UpperBounded};
#[derive(Clone, Copy, PartialEq, Eq, Debug, derive_more::From)]
pub struct IntervalIterator<T>(Option<Interval<T>>);
impl<T: Numerated> IntervalIterator<T> {
pub fn empty() -> Self {
Self(None)
}
pub fn is_empty(&self) -> bool {
self.0.is_none()
}
pub fn inner(&self) -> Option<Interval<T>> {
self.0
}
}
impl<T: Numerated> From<Interval<T>> for IntervalIterator<T> {
fn from(interval: Interval<T>) -> Self {
Self(Some(interval))
}
}
impl<T: Numerated> From<T> for IntervalIterator<T> {
fn from(point: T) -> Self {
Interval::from(point).into()
}
}
impl<T: Numerated + LowerBounded> From<RangeToInclusive<T>> for IntervalIterator<T> {
fn from(range: RangeToInclusive<T>) -> Self {
Interval::from(range).into()
}
}
impl<T: Numerated + UpperBounded, I: Into<T::Bound>> From<RangeFrom<I>> for IntervalIterator<T> {
fn from(range: RangeFrom<I>) -> Self {
Interval::try_from(range)
.map(Into::into)
.unwrap_or(Self::empty())
}
}
impl<T: Numerated + LowerBounded + UpperBounded> From<RangeFull> for IntervalIterator<T> {
fn from(range: RangeFull) -> Self {
Interval::from(range).into()
}
}
impl<T: Numerated + LowerBounded + UpperBounded, I: Into<T::Bound>> From<RangeTo<I>>
for IntervalIterator<T>
{
fn from(range: RangeTo<I>) -> Self {
Interval::try_from(range)
.map(Into::into)
.unwrap_or(Self::empty())
}
}
impl<T, S, E> TryFrom<(S, E)> for IntervalIterator<T>
where
T: Numerated + UpperBounded,
S: Into<T::Bound>,
E: Into<T::Bound>,
{
type Error = IncorrectRangeError;
fn try_from(range: (S, E)) -> Result<Self, Self::Error> {
match Interval::try_from(range) {
Ok(interval) => Ok(interval.into()),
Err(TryFromRangeError::EmptyRange) => Ok(Self::empty()),
Err(TryFromRangeError::IncorrectRange) => Err(IncorrectRangeError),
}
}
}
impl<T: Numerated + UpperBounded, I: Into<T::Bound>> TryFrom<Range<I>> for IntervalIterator<T> {
type Error = IncorrectRangeError;
fn try_from(range: Range<I>) -> Result<Self, Self::Error> {
Self::try_from((range.start, range.end))
}
}
impl<T: Numerated> TryFrom<RangeInclusive<T>> for IntervalIterator<T> {
type Error = IncorrectRangeError;
fn try_from(range: RangeInclusive<T>) -> Result<Self, Self::Error> {
Interval::try_from(range).map(Into::into)
}
}
impl<T: Numerated> Iterator for IntervalIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.0.map(|interval| {
let start = interval.start();
self.0 = interval.inc_start();
start
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OutOfBoundsError;
impl<T: Numerated + UpperBounded> IntervalIterator<T> {
pub fn with_len<S: Into<T::Bound>, L: Into<Option<T::Distance>>>(
start: S,
len: L,
) -> Result<Self, OutOfBoundsError> {
match Interval::with_len(start, len) {
Ok(interval) => Ok(interval.into()),
Err(NewWithLenError::ZeroLen) => Ok(Self::empty()),
Err(NewWithLenError::OutOfBounds) => Err(OutOfBoundsError),
}
}
}
impl<T: Display> Display for IntervalIterator<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(interval) = &self.0 {
write!(f, "{interval}")
} else {
write!(f, "∅")
}
}
}
pub struct DifferenceIterator<T: Numerated, I: Iterator<Item = Interval<T>>> {
pub(crate) iter1: I,
pub(crate) iter2: I,
pub(crate) interval1: Option<Interval<T>>,
pub(crate) interval2: Option<Interval<T>>,
}
impl<T: Numerated, I: Iterator<Item = Interval<T>>> Iterator for DifferenceIterator<T, I> {
type Item = Interval<T>;
fn next(&mut self) -> Option<Self::Item> {
loop {
self.interval1 = self.interval1.or_else(|| self.iter1.next());
let interval1 = self.interval1?;
let interval2 = self.interval2.or_else(|| self.iter2.next());
let Some(interval2) = interval2 else {
return self.interval1.take();
};
if interval2.end() < interval1.start() {
self.interval2 = None;
continue;
}
self.interval2 = Some(interval2);
if interval1.end() < interval2.start() {
self.interval1 = None;
return Some(interval1);
} else {
if let Some(new_start) = interval2.end().inc_if_lt(interval1.end()) {
self.interval1 = Interval::new(new_start, interval1.end());
debug_assert!(self.interval1.is_some(), "`T: Numerated` impl error");
} else if interval1.end() == interval2.end() {
self.interval1 = None;
self.interval2 = None;
} else {
self.interval1 = None;
}
if let Some(new_end) = interval2.start().dec_if_gt(interval1.start()) {
let res = Interval::new(interval1.start(), new_end);
debug_assert!(res.is_some(), "`T: Numerated` impl error");
return res;
} else {
continue;
}
}
}
}
}
pub struct VoidsIterator<T: Numerated, I: Iterator<Item = Interval<T>>> {
pub(crate) inner: Option<(I, Interval<T>)>,
}
impl<T: Numerated, I: Iterator<Item = Interval<T>>> Iterator for VoidsIterator<T, I> {
type Item = Interval<T>;
fn next(&mut self) -> Option<Self::Item> {
let (iter, interval) = self.inner.as_mut()?;
if let Some(next) = iter.next() {
let (start, end) = next.into_parts();
debug_assert!(interval.start() < start);
let Some(void_end) = start.dec_if_gt(interval.start()) else {
debug_assert!(false, "`T: Numerated` impl error");
return None;
};
let res = Interval::new(interval.start(), void_end);
debug_assert!(res.is_some(), "`T: Numerated` impl error");
if let Some(new_start) = end.inc_if_lt(interval.end()) {
let Some(new_interval) = Interval::new(new_start, interval.end()) else {
debug_assert!(false, "`T: Numerated` impl error");
return None;
};
*interval = new_interval;
} else {
self.inner = None;
}
res
} else {
let res = Some(*interval);
self.inner = None;
res
}
}
}
#[cfg(test)]
mod tests {
use alloc::vec;
use super::*;
#[test]
fn empty_interval() {
assert!(IntervalIterator::<u8>::empty().is_empty());
assert!(IntervalIterator::<u8>::with_len(1, 0).unwrap().is_empty());
assert!(
IntervalIterator::<u8>::with_len(None, 0)
.unwrap()
.is_empty()
);
assert!(IntervalIterator::<u8>::try_from(1..1).unwrap().is_empty());
assert!(IntervalIterator::<u8>::from(..0).is_empty());
assert!(IntervalIterator::<u8>::from(None..).is_empty());
}
#[test]
fn voids_iterator() {
let intervals = vec![1u8..3, 5..7]
.into_iter()
.map(|r| Interval::<u8>::try_from(r).unwrap());
let mut iter = VoidsIterator {
inner: Some((intervals, Interval::<u8>::from(..=10))),
};
assert_eq!(Some(0..=0), iter.next().map(Into::into));
assert_eq!(Some(3..=4), iter.next().map(Into::into));
assert_eq!(Some(7..=10), iter.next().map(Into::into));
assert_eq!(None, iter.next());
}
#[test]
fn difference_iterator() {
let intervals1 = vec![
Interval::<u8>::try_from(1..3).unwrap(),
Interval::<u8>::try_from(5..7).unwrap(),
];
let intervals2 = vec![
Interval::<u8>::try_from(2..4).unwrap(),
Interval::<u8>::try_from(6..8).unwrap(),
];
let mut iter = DifferenceIterator {
iter1: intervals1.into_iter(),
iter2: intervals2.into_iter(),
interval1: None,
interval2: None,
};
assert_eq!(Some(1..=1), iter.next().map(Into::into));
assert_eq!(Some(5..=5), iter.next().map(Into::into));
assert_eq!(None, iter.next());
}
}