use core::fmt::Debug;
use core::iter::FusedIterator;
use core::marker::PhantomData;
use alloc::boxed::Box;
use alloc::vec::Vec;
use crate::curve::curve_types::CurveType;
use crate::iterators::curve::IterCurveWrapper;
use crate::iterators::peek::Peeker;
use crate::iterators::{CurveIterator, CurveIteratorIterator};
use crate::time::TimeUnit;
use crate::window::window_types::WindowType;
use crate::window::WindowEnd;
use crate::window::{Overlap, Window, WindowDeltaResult};
#[derive(Debug)]
pub enum Delta<S, D, SI, DI> {
RemainingSupply(Window<S>),
EndSupply(Box<SI>),
Overlap(Window<Overlap<S, D>>),
RemainingDemand(Window<D>),
EndDemand(Peeker<CurveIteratorIterator<Box<DI>>, Window<D>>),
}
impl<S, D, SI, DI> Delta<S, D, SI, DI> {
#[must_use]
pub fn overlap(self) -> Option<Window<Overlap<S, D>>> {
#![allow(clippy::missing_const_for_fn)] match self {
Delta::RemainingSupply(_)
| Delta::EndSupply(_)
| Delta::RemainingDemand(_)
| Delta::EndDemand(_) => None,
Delta::Overlap(overlap) => Some(overlap),
}
}
}
#[derive(Debug)]
pub struct RemainingSupplyIterator<S, D, SI, DI> {
delta: Option<CurveDeltaIterator<D, S, DI, SI>>,
end_supply: Option<Box<SI>>,
}
impl<S, D, SI: Clone, DI: Clone> Clone for RemainingSupplyIterator<S, D, SI, DI> {
fn clone(&self) -> Self {
RemainingSupplyIterator {
delta: self.delta.clone(),
end_supply: self.end_supply.clone(),
}
}
}
impl<SI, DI> CurveIterator
for RemainingSupplyIterator<
<SI::CurveKind as CurveType>::WindowKind,
<DI::CurveKind as CurveType>::WindowKind,
SI,
DI,
>
where
Self: Debug,
SI: CurveIterator,
DI: CurveIterator,
{
type CurveKind = SI::CurveKind;
fn next_window(&mut self) -> Option<Window<<SI::CurveKind as CurveType>::WindowKind>> {
'outer: loop {
if let Some(end_supply) = self.end_supply.as_mut() {
if let Some(supply) = end_supply.next_window() {
return Some(supply);
} else {
self.end_supply = None;
}
}
if let Some(delta_iter) = self.delta.as_mut() {
loop {
if let Some(delta) = delta_iter.next() {
match delta {
Delta::Overlap(_) | Delta::EndDemand(_) | Delta::RemainingDemand(_) => {
continue
}
Delta::RemainingSupply(supply) => return Some(supply),
Delta::EndSupply(supply) => {
self.end_supply = Some(supply);
continue 'outer;
}
}
} else {
self.delta = None;
break;
}
}
}
return None;
}
}
}
#[derive(Debug)]
pub struct InverseCurveIterator<I, C> {
iter: I,
previous_end: WindowEnd,
curve_type: PhantomData<C>,
}
impl<I, C> InverseCurveIterator<I, C> {
#[must_use]
pub const fn new(iter: I) -> Self {
InverseCurveIterator {
iter,
previous_end: WindowEnd::Finite(TimeUnit::ZERO),
curve_type: PhantomData,
}
}
}
impl<I: Clone, C> Clone for InverseCurveIterator<I, C> {
fn clone(&self) -> Self {
InverseCurveIterator {
iter: self.iter.clone(),
previous_end: self.previous_end,
curve_type: PhantomData,
}
}
}
impl<I: CurveIterator, C: CurveType> CurveIterator for InverseCurveIterator<I, C> {
type CurveKind = C;
fn next_window(&mut self) -> Option<Window<C::WindowKind>> {
if let WindowEnd::Finite(mut previous_end) = self.previous_end {
while let Some(window) = self.iter.next_window() {
if self.previous_end < window.start {
let result = Window::new(previous_end, window.start);
self.previous_end = window.end;
return Some(result);
} else if self.previous_end == window.start {
self.previous_end = window.end;
match self.previous_end {
WindowEnd::Finite(end) => previous_end = end,
WindowEnd::Infinite => return None,
}
} else {
panic!("Overlapping Windows in CurveIterator 'self.iter'")
}
}
let result = Window::new(previous_end, WindowEnd::Infinite);
self.previous_end = WindowEnd::Infinite;
Some(result)
} else {
None
}
}
}
#[derive(Debug)]
pub struct CurveDeltaIterator<DW, SW, DI, SI> {
demand: Option<Peeker<CurveIteratorIterator<Box<DI>>, Window<DW>>>,
supply: Option<Box<SI>>,
remaining_supply: Vec<Window<SW>>,
}
impl<DW, SW, DI: Clone, SI: Clone> Clone for CurveDeltaIterator<DW, SW, DI, SI> {
fn clone(&self) -> Self {
CurveDeltaIterator {
demand: self.demand.clone(),
supply: self.supply.clone(),
remaining_supply: self.remaining_supply.clone(),
}
}
}
impl<S, D, SI, DI> CurveDeltaIterator<D, S, DI, SI> {
#[must_use]
pub const fn remaining_supply(self) -> RemainingSupplyIterator<S, D, SI, DI> {
RemainingSupplyIterator {
delta: Some(self),
end_supply: None,
}
}
}
impl<DI: CurveIterator, SI: CurveIterator>
CurveDeltaIterator<
<DI::CurveKind as CurveType>::WindowKind,
<SI::CurveKind as CurveType>::WindowKind,
DI,
SI,
>
{
pub fn new(supply: SI, demand: DI) -> Self {
CurveDeltaIterator {
demand: Some(Peeker::new(Box::new(demand).into_iterator())),
supply: Some(Box::new(supply)),
remaining_supply: Vec::with_capacity(2), }
}
pub fn overlap<
C: CurveType<
WindowKind = Overlap<
<SI::CurveKind as CurveType>::WindowKind,
<DI::CurveKind as CurveType>::WindowKind,
>,
>,
>(
self,
) -> impl CurveIterator<CurveKind = C> + Clone
where
Self: Clone + Debug,
{
let inner = self.filter_map(Delta::overlap);
unsafe {
IterCurveWrapper::new(inner)
}
}
}
impl<DC, SC, DI, SI> FusedIterator for CurveDeltaIterator<DC, SC, DI, SI>
where
Self: Iterator,
DI: FusedIterator,
SI: FusedIterator,
{
}
impl<DW, SW, DI, SI> Iterator for CurveDeltaIterator<DW, SW, DI, SI>
where
DW: WindowType,
SW: WindowType,
DI: CurveIterator,
DI::CurveKind: CurveType<WindowKind = DW>,
SI: CurveIterator,
SI::CurveKind: CurveType<WindowKind = SW>,
{
type Item = Delta<SW, DW, SI, DI>;
fn next(&mut self) -> Option<Self::Item> {
#![allow(clippy::option_if_let_else)]
if let (Some(supply_iter), Some(demand_iter)) = (self.supply.as_mut(), self.demand.as_mut())
{
let demand = demand_iter.peek_ref();
if let Some(demand_window) = demand {
let supply = self
.remaining_supply
.pop()
.or_else(|| supply_iter.next_window());
if let Some(supply_window) = supply {
if demand_window.start < supply_window.end {
let WindowDeltaResult {
remaining_supply_head,
remaining_supply_tail,
overlap,
remaining_demand,
} = Window::delta(&supply_window, &demand_window.take());
let remaining_supply = &mut self.remaining_supply;
IntoIterator::into_iter([remaining_supply_head, remaining_supply_tail])
.filter(|window| !window.is_empty())
.rev()
.for_each(|window| remaining_supply.push(window));
if !remaining_demand.is_empty() {
demand_iter.restore_peek(remaining_demand);
}
Some(Delta::Overlap(overlap))
} else {
Some(Delta::RemainingSupply(supply_window))
}
} else {
self.supply = None;
Some(Delta::RemainingDemand(demand_window.take()))
}
} else {
self.demand = None;
let remaining_supply = self.remaining_supply.pop().map(Delta::RemainingSupply);
let lazy_supply_iter = || self.supply.take().map(Delta::EndSupply);
remaining_supply.or_else(lazy_supply_iter)
}
} else {
let remaining_supply = self.remaining_supply.pop().map(Delta::RemainingSupply);
let s = &mut self.supply;
let d = &mut self.demand;
let lazy_supply_iter = || s.take().map(Delta::EndSupply);
let lazy_demand_iter = || d.take().map(Delta::EndDemand);
remaining_supply
.or_else(lazy_supply_iter)
.or_else(lazy_demand_iter)
}
}
}