use core::fmt::Debug;
use core::iter::{FromIterator, FusedIterator};
use core::marker::PhantomData;
use alloc::vec::Vec;
pub use aggregate::AggregationIterator;
pub use delta::{
CurveDeltaIterator,
Delta::{self, *},
InverseCurveIterator,
};
pub use split::CurveSplitIterator;
use crate::curve::curve_types::CurveType;
use crate::curve::Curve;
use crate::iterators::join::JoinAdjacentIterator;
use crate::iterators::CurveIterator;
use crate::time::{TimeUnit, UnitNumber};
use crate::window::window_types::WindowType;
use crate::window::Window;
use crate::window::WindowEnd;
mod aggregate;
mod delta;
mod split;
pub trait FromCurveIterator<C: CurveType> {
fn from_curve_iter<CI: CurveIterator<CurveKind = C>>(iter: CI) -> Self;
}
impl<C: CurveType, T: FromIterator<Window<C::WindowKind>>> FromCurveIterator<C> for T {
fn from_curve_iter<CI: CurveIterator<CurveKind = C>>(iter: CI) -> Self {
iter.into_iterator().collect()
}
}
impl<C: CurveType> FromCurveIterator<C> for Curve<C> {
fn from_curve_iter<CI: CurveIterator<CurveKind = C>>(iter: CI) -> Self {
let windows = iter.normalize().into_iterator().collect();
unsafe {
Curve::from_windows_unchecked(windows)
}
}
}
#[derive(Debug)]
pub struct CurveIter<C: CurveType> {
curve: Vec<Window<C::WindowKind>>,
}
impl<C: CurveType> Clone for CurveIter<C> {
fn clone(&self) -> Self {
CurveIter {
curve: self.curve.clone(),
}
}
}
impl<C: CurveType> IntoIterator for Curve<C> {
type Item = Window<C::WindowKind>;
type IntoIter = CurveIter<C>;
fn into_iter(self) -> Self::IntoIter {
let mut windows = self.into_windows();
windows.reverse();
CurveIter { curve: windows }
}
}
impl<C: CurveType> CurveIterator for CurveIter<C> {
type CurveKind = C;
fn next_window(&mut self) -> Option<Window<C::WindowKind>> {
self.curve.pop()
}
}
impl<C: CurveType> FusedIterator for CurveIter<C> {}
impl<C: CurveType> Iterator for CurveIter<C> {
type Item = Window<C::WindowKind>;
fn next(&mut self) -> Option<Self::Item> {
self.next_window()
}
}
#[derive(Debug)]
pub struct IterCurveWrapper<I, C> {
iter: I,
curve_kind: PhantomData<C>,
}
impl<I: Clone, C> Clone for IterCurveWrapper<I, C> {
fn clone(&self) -> Self {
IterCurveWrapper {
iter: self.iter.clone(),
curve_kind: PhantomData,
}
}
}
impl<I, C> IterCurveWrapper<I, C> {
pub const unsafe fn new(iter: I) -> Self {
IterCurveWrapper {
iter,
curve_kind: PhantomData,
}
}
}
impl<C, I> CurveIterator for IterCurveWrapper<I, C>
where
Self: Debug,
C: CurveType,
I: Iterator<Item = Window<C::WindowKind>>,
{
type CurveKind = C;
fn next_window(&mut self) -> Option<Window<C::WindowKind>> {
self.iter.next()
}
}
#[derive(Debug, Clone)]
pub struct CapacityCheckIterator<W, I, C> {
iter: JoinAdjacentIterator<InnerCapacityCheckIterator<W, I>, W, C>,
}
impl<W, I, C> CapacityCheckIterator<W, I, C>
where
W: WindowType,
I: CurveIterator,
I::CurveKind: CurveType<WindowKind = W>,
{
pub fn new(to_be_checked: I, capacity: TimeUnit, interval: TimeUnit) -> Self {
let inner = InnerCapacityCheckIterator {
iter: CurveSplitIterator::new(to_be_checked, interval),
capacity,
interval,
current_group: 0,
accounted: WindowEnd::Finite(TimeUnit::ZERO),
};
let outer = unsafe { JoinAdjacentIterator::new(inner) };
CapacityCheckIterator { iter: outer }
}
}
impl<W, I, C> CurveIterator for CapacityCheckIterator<W, I, C>
where
I: CurveIterator<CurveKind = C>,
C: CurveType<WindowKind = W> + Debug,
W: WindowType,
{
type CurveKind = C;
fn next_window(&mut self) -> Option<Window<C::WindowKind>> {
self.iter.next_window()
}
}
#[derive(Debug, Clone)]
struct InnerCapacityCheckIterator<W, I> {
iter: CurveSplitIterator<W, I>,
capacity: TimeUnit,
interval: TimeUnit,
current_group: UnitNumber,
accounted: WindowEnd,
}
impl<W, I> Iterator for InnerCapacityCheckIterator<W, I>
where
W: WindowType,
I: CurveIterator,
I::CurveKind: CurveType<WindowKind = W>,
{
type Item = Window<W>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(next) = self.iter.next() {
let next_group = next.budget_group(self.interval);
if next_group == self.current_group {
self.accounted += next.length();
} else if next_group == self.current_group + 1 {
if self.accounted < self.capacity {
panic!(
"Not enough capacity in group {}, expected at least {:?} capacity , got {:?}, next group {:?}!",
self.current_group, self.capacity, self.accounted, next_group
);
}
self.current_group = next_group;
self.accounted = next.length();
} else {
panic!(
"No capacity for group {}, expected {:?} capacity, next group {}!",
self.current_group + 1,
self.capacity,
next_group
);
};
Some(next)
} else {
None
}
}
}