use std::iter::FusedIterator;
use crate::intervals::absolute::AbsBoundPair;
use crate::intervals::relative::RelBoundPair;
use crate::iter::intervals::layered_bounds::{
LayeredBoundsState,
LayeredBoundsStateChangeAtAbsBound,
LayeredBoundsStateChangeAtRelBound,
};
#[derive(Debug, Clone, Hash)]
pub struct LayeredAbsBoundsDifference<I> {
iter: I,
exhausted: bool,
}
impl<I> LayeredAbsBoundsDifference<I>
where
I: Iterator<Item = LayeredBoundsStateChangeAtAbsBound>,
{
pub fn new(iter: I) -> LayeredAbsBoundsDifference<I> {
LayeredAbsBoundsDifference {
iter,
exhausted: false,
}
}
}
impl<I> Iterator for LayeredAbsBoundsDifference<I>
where
I: Iterator<Item = LayeredBoundsStateChangeAtAbsBound>,
{
type Item = AbsBoundPair;
fn next(&mut self) -> Option<Self::Item> {
if self.exhausted {
return None;
}
loop {
let Some(current) = self.iter.next() else {
self.exhausted = true;
return None;
};
if !matches!(current.new_state(), LayeredBoundsState::FirstLayer) {
continue;
}
let Some(start) = current.new_state_start() else {
unreachable!("When the state is not `NoLayers`, the new state's start is guaranteed to exist");
};
let Some(next) = self.iter.next() else {
unreachable!(
"The input requirements guarantee that the given iterator cannot end on an active state such as \
`FirstLayer`"
);
};
let Some(end) = next.old_state_end() else {
unreachable!(
"We can infer the guarantee that the state change following one that transitions to `FirstLayer` \
must contain an end to the old state, given that the input requirements guarantee that the given \
iterator cannot end on an active state such as `FirstLayer`"
);
};
return Some(AbsBoundPair::new(start, end));
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1.map(|upper_bound| upper_bound.div_ceil(2)))
}
}
impl<I> FusedIterator for LayeredAbsBoundsDifference<I> where I: Iterator<Item = LayeredBoundsStateChangeAtAbsBound> {}
pub trait LayeredAbsBoundsDifferenceIteratorDispatcher
where
Self: IntoIterator<Item = LayeredBoundsStateChangeAtAbsBound> + Sized,
{
fn abs_difference_layered(self) -> LayeredAbsBoundsDifference<Self::IntoIter> {
LayeredAbsBoundsDifference::new(self.into_iter())
}
}
impl<I> LayeredAbsBoundsDifferenceIteratorDispatcher for I where
I: IntoIterator<Item = LayeredBoundsStateChangeAtAbsBound> + Sized
{
}
#[derive(Debug, Clone, Hash)]
pub struct LayeredRelBoundsDifference<I> {
iter: I,
exhausted: bool,
}
impl<I> LayeredRelBoundsDifference<I>
where
I: Iterator<Item = LayeredBoundsStateChangeAtRelBound>,
{
pub fn new(iter: I) -> LayeredRelBoundsDifference<I> {
LayeredRelBoundsDifference {
iter,
exhausted: false,
}
}
}
impl<I> Iterator for LayeredRelBoundsDifference<I>
where
I: Iterator<Item = LayeredBoundsStateChangeAtRelBound>,
{
type Item = RelBoundPair;
fn next(&mut self) -> Option<Self::Item> {
if self.exhausted {
return None;
}
loop {
let Some(current) = self.iter.next() else {
self.exhausted = true;
return None;
};
if !matches!(current.new_state(), LayeredBoundsState::FirstLayer) {
continue;
}
let Some(start) = current.new_state_start() else {
unreachable!("When the state is not `NoLayers`, the new state's start is guaranteed to exist");
};
let Some(next) = self.iter.next() else {
unreachable!(
"The input requirements guarantee that the given iterator cannot end on an active state such as \
`FirstLayer`"
);
};
let Some(end) = next.old_state_end() else {
unreachable!(
"We can infer the guarantee that the state change following one that transitions to `FirstLayer` \
must contain an end to the old state, given that the input requirements guarantee that the given \
iterator cannot end on an active state such as `FirstLayer`"
);
};
return Some(RelBoundPair::new(start, end));
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, self.iter.size_hint().1.map(|upper_bound| upper_bound.div_ceil(2)))
}
}
impl<I> FusedIterator for LayeredRelBoundsDifference<I> where I: Iterator<Item = LayeredBoundsStateChangeAtRelBound> {}
pub trait LayeredRelBoundsDifferenceIteratorDispatcher
where
Self: IntoIterator<Item = LayeredBoundsStateChangeAtRelBound> + Sized,
{
fn rel_difference_layered(self) -> LayeredRelBoundsDifference<Self::IntoIter> {
LayeredRelBoundsDifference::new(self.into_iter())
}
}
impl<I> LayeredRelBoundsDifferenceIteratorDispatcher for I where
I: IntoIterator<Item = LayeredBoundsStateChangeAtRelBound> + Sized
{
}