use std::iter::{FusedIterator, Peekable};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::intervals::absolute::{AbsBound, AbsBoundPair};
use crate::intervals::bound_position::BoundPosition;
use crate::intervals::ops::{BoundOrd, BoundOverlapDisambiguationRuleSet};
use crate::intervals::relative::{RelBound, RelBoundPair};
use crate::iter::intervals::layered_bounds::{LayeredAbsBounds, LayeredRelBounds};
use crate::iter::intervals::united_bounds::{AbsUnitedBoundsIter, RelUnitedBoundsIter};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct AbsBoundsIter {
bounds: Vec<AbsBoundPair>,
position: BoundPosition,
initd: bool, exhausted: bool,
}
impl AbsBoundsIter {
#[must_use]
pub fn new<I>(iter: I) -> Self
where
I: Iterator<Item = AbsBoundPair>,
{
AbsBoundsIter {
bounds: iter.collect::<Vec<_>>(),
position: BoundPosition::default(),
initd: true,
exhausted: false,
}
}
#[must_use]
pub fn unite_bounds(self) -> AbsUnitedBoundsIter<Peekable<impl Iterator<Item = AbsBound>>> {
let mut bounds = self.collect::<Vec<_>>();
bounds.sort_by(|a, b| a.bound_cmp(b).disambiguate(BoundOverlapDisambiguationRuleSet::Strict));
AbsUnitedBoundsIter::new(bounds.into_iter())
}
#[must_use]
pub fn unchecked_layer(
self,
second_layer: AbsBoundsIter,
) -> LayeredAbsBounds<Peekable<Self>, Peekable<AbsBoundsIter>> {
LayeredAbsBounds::new(self, second_layer)
}
}
impl Iterator for AbsBoundsIter {
type Item = AbsBound;
fn next(&mut self) -> Option<Self::Item> {
if self.exhausted {
return None;
}
if !self.initd && self.position.next_bound() {
self.exhausted = true;
return None;
}
if self.initd {
self.initd = false;
}
self.position.get_abs_bound(&self.bounds)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let bounds_amount = self.bounds.len().checked_mul(2);
(bounds_amount.unwrap_or(usize::MAX), bounds_amount)
}
}
impl FusedIterator for AbsBoundsIter {}
impl ExactSizeIterator for AbsBoundsIter {}
impl FromIterator<AbsBoundPair> for AbsBoundsIter {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = AbsBoundPair>,
{
AbsBoundsIter::new(iter.into_iter())
}
}
impl Extend<AbsBoundPair> for AbsBoundsIter {
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = AbsBoundPair>,
{
self.bounds.extend(iter);
}
}
pub trait AbsBoundsIteratorDispatcher: IntoIterator<Item = AbsBoundPair> + Sized {
fn abs_bounds_iter(self) -> AbsBoundsIter {
AbsBoundsIter::new(self.into_iter())
}
}
impl<I> AbsBoundsIteratorDispatcher for I where I: IntoIterator<Item = AbsBoundPair> + Sized {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct RelBoundsIter {
bounds: Vec<RelBoundPair>,
position: BoundPosition,
initd: bool, exhausted: bool,
}
impl RelBoundsIter {
#[must_use]
pub fn new<I>(iter: I) -> Self
where
I: Iterator<Item = RelBoundPair>,
{
RelBoundsIter {
bounds: iter.collect::<Vec<_>>(),
position: BoundPosition::default(),
initd: true,
exhausted: false,
}
}
#[must_use]
pub fn unite_bounds(self) -> RelUnitedBoundsIter<Peekable<impl Iterator<Item = RelBound>>> {
let mut bounds = self.collect::<Vec<_>>();
bounds.sort_by(|a, b| a.bound_cmp(b).disambiguate(BoundOverlapDisambiguationRuleSet::Strict));
RelUnitedBoundsIter::new(bounds.into_iter())
}
#[must_use]
pub fn unchecked_layer(
self,
second_layer: RelBoundsIter,
) -> LayeredRelBounds<Peekable<Self>, Peekable<RelBoundsIter>> {
LayeredRelBounds::new(self, second_layer)
}
}
impl Iterator for RelBoundsIter {
type Item = RelBound;
fn next(&mut self) -> Option<Self::Item> {
if self.exhausted {
return None;
}
if !self.initd && self.position.next_bound() {
self.exhausted = true;
return None;
}
if self.initd {
self.initd = false;
}
self.position.get_rel_bound(&self.bounds)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let bounds_amount = self.bounds.len().checked_mul(2);
(bounds_amount.unwrap_or(usize::MAX), bounds_amount)
}
}
impl FusedIterator for RelBoundsIter {}
impl ExactSizeIterator for RelBoundsIter {}
impl FromIterator<RelBoundPair> for RelBoundsIter {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = RelBoundPair>,
{
RelBoundsIter::new(iter.into_iter())
}
}
impl Extend<RelBoundPair> for RelBoundsIter {
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = RelBoundPair>,
{
self.bounds.extend(iter);
}
}
pub trait RelBoundsIteratorDispatcher: IntoIterator<Item = RelBoundPair> + Sized {
fn rel_bounds_iter(self) -> RelBoundsIter {
RelBoundsIter::new(self.into_iter())
}
}
impl<I> RelBoundsIteratorDispatcher for I where I: IntoIterator<Item = RelBoundPair> + Sized {}