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 LayeredAbsBoundsSymmetricDifference<I> {
iter: I,
exhausted: bool,
}
impl<I> LayeredAbsBoundsSymmetricDifference<I>
where
I: Iterator<Item = LayeredBoundsStateChangeAtAbsBound>,
{
pub fn new(iter: I) -> LayeredAbsBoundsSymmetricDifference<I> {
LayeredAbsBoundsSymmetricDifference {
iter,
exhausted: false,
}
}
}
impl<I> Iterator for LayeredAbsBoundsSymmetricDifference<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::NoLayers | LayeredBoundsState::BothLayers
) {
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");
};
loop {
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` or `SecondLayer`"
);
};
if matches!(
next.new_state(),
LayeredBoundsState::FirstLayer | LayeredBoundsState::SecondLayer
) {
continue;
}
let Some(end) = next.old_state_end() else {
unreachable!(
"We can infer the guarantee that the state change following one that transitions to \
`FirstLayer` or `SecondLayer` 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` or `SecondLayer`"
);
};
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 LayeredAbsBoundsSymmetricDifference<I> where
I: Iterator<Item = LayeredBoundsStateChangeAtAbsBound>
{
}
pub trait LayeredAbsBoundsSymmetricDifferenceIteratorDispatcher
where
Self: IntoIterator<Item = LayeredBoundsStateChangeAtAbsBound> + Sized,
{
fn abs_symmetric_difference_layered(self) -> LayeredAbsBoundsSymmetricDifference<Self::IntoIter> {
LayeredAbsBoundsSymmetricDifference::new(self.into_iter())
}
}
impl<I> LayeredAbsBoundsSymmetricDifferenceIteratorDispatcher for I where
I: IntoIterator<Item = LayeredBoundsStateChangeAtAbsBound> + Sized
{
}
#[derive(Debug, Clone, Hash)]
pub struct LayeredRelBoundsSymmetricDifference<I> {
iter: I,
exhausted: bool,
}
impl<I> LayeredRelBoundsSymmetricDifference<I>
where
I: Iterator<Item = LayeredBoundsStateChangeAtRelBound>,
{
pub fn new(iter: I) -> LayeredRelBoundsSymmetricDifference<I> {
LayeredRelBoundsSymmetricDifference {
iter,
exhausted: false,
}
}
}
impl<I> Iterator for LayeredRelBoundsSymmetricDifference<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::NoLayers | LayeredBoundsState::BothLayers
) {
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");
};
loop {
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` or `SecondLayer`"
);
};
if matches!(
next.new_state(),
LayeredBoundsState::FirstLayer | LayeredBoundsState::SecondLayer
) {
continue;
}
let Some(end) = next.old_state_end() else {
unreachable!(
"We can infer the guarantee that the state change following one that transitions to \
`FirstLayer` or `SecondLayer` 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` or `SecondLayer`"
);
};
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 LayeredRelBoundsSymmetricDifference<I> where
I: Iterator<Item = LayeredBoundsStateChangeAtRelBound>
{
}
pub trait LayeredRelBoundsSymmetricDifferenceIteratorDispatcher
where
Self: IntoIterator<Item = LayeredBoundsStateChangeAtRelBound> + Sized,
{
fn rel_symmetric_difference_layered(self) -> LayeredRelBoundsSymmetricDifference<Self::IntoIter> {
LayeredRelBoundsSymmetricDifference::new(self.into_iter())
}
}
impl<I> LayeredRelBoundsSymmetricDifferenceIteratorDispatcher for I where
I: IntoIterator<Item = LayeredBoundsStateChangeAtRelBound> + Sized
{
}