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 LayeredAbsBoundsUnion<I> {
iter: I,
exhausted: bool,
}
impl<I> LayeredAbsBoundsUnion<I>
where
I: Iterator<Item = LayeredBoundsStateChangeAtAbsBound>,
{
pub fn new(iter: I) -> LayeredAbsBoundsUnion<I> {
LayeredAbsBoundsUnion {
iter,
exhausted: false,
}
}
}
impl<I> Iterator for LayeredAbsBoundsUnion<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) {
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!(
"Since the input requirements state that the state changes need to be continuous, and since \
we already stopped at a state that is not `NoLayers`, we can expect the next elements to \
exist until a state change that transitions to `NoLayers` is returned"
);
};
if !matches!(next.new_state(), LayeredBoundsState::NoLayers) {
continue;
}
let Some(end) = next.old_state_end() else {
unreachable!(
"Since the input requirements state that the state changes need to be continuous, we can \
expect the next state change which transitions to `NoLayers` to contain the change's old \
state's end"
);
};
return Some(AbsBoundPair::new(start, end));
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let inner_size_hint = self.iter.size_hint();
(
inner_size_hint.0.min(1),
inner_size_hint.1.map(|upper_bound| upper_bound.div_ceil(2)),
)
}
}
impl<I> FusedIterator for LayeredAbsBoundsUnion<I> where I: Iterator<Item = LayeredBoundsStateChangeAtAbsBound> {}
pub trait LayeredAbsBoundsUnionIteratorDispatcher
where
Self: IntoIterator<Item = LayeredBoundsStateChangeAtAbsBound> + Sized,
{
fn abs_unite_layered(self) -> LayeredAbsBoundsUnion<Self::IntoIter> {
LayeredAbsBoundsUnion::new(self.into_iter())
}
}
impl<I> LayeredAbsBoundsUnionIteratorDispatcher for I where
I: IntoIterator<Item = LayeredBoundsStateChangeAtAbsBound> + Sized
{
}
#[derive(Debug, Clone, Hash)]
pub struct LayeredRelBoundsUnion<I> {
iter: I,
exhausted: bool,
}
impl<I> LayeredRelBoundsUnion<I>
where
I: Iterator<Item = LayeredBoundsStateChangeAtRelBound>,
{
pub fn new(iter: I) -> LayeredRelBoundsUnion<I> {
LayeredRelBoundsUnion {
iter,
exhausted: false,
}
}
}
impl<I> Iterator for LayeredRelBoundsUnion<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) {
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!(
"Since the input requirements state that the state changes need to be continuous, and since \
we already stopped at a state that is not `NoLayers`, we can expect the next elements to \
exist until a state change that transitions to `NoLayers` is returned"
);
};
if !matches!(next.new_state(), LayeredBoundsState::NoLayers) {
continue;
}
let Some(end) = next.old_state_end() else {
unreachable!(
"Since the input requirements state that the state changes need to be continuous, we can \
expect the next state change which transitions to `NoLayers` to contain the change's old \
state's end"
);
};
return Some(RelBoundPair::new(start, end));
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let inner_size_hint = self.iter.size_hint();
(
inner_size_hint.0.min(1),
inner_size_hint.1.map(|upper_bound| upper_bound.div_ceil(2)),
)
}
}
impl<I> FusedIterator for LayeredRelBoundsUnion<I> where I: Iterator<Item = LayeredBoundsStateChangeAtRelBound> {}
pub trait LayeredRelBoundsUnionIteratorDispatcher
where
Self: IntoIterator<Item = LayeredBoundsStateChangeAtRelBound> + Sized,
{
fn rel_unite_layered(self) -> LayeredRelBoundsUnion<Self::IntoIter> {
LayeredRelBoundsUnion::new(self.into_iter())
}
}
impl<I> LayeredRelBoundsUnionIteratorDispatcher for I where
I: IntoIterator<Item = LayeredBoundsStateChangeAtRelBound> + Sized
{
}