use core::fmt;
use core::fmt::Debug;
use core::iter::{Cycle, FusedIterator};
use crate::{ArrayWindows, IterArrayWindows};
pub trait IterCircularArrayWindows: Iterator {
#[inline]
fn circular_array_windows<const N: usize>(self) -> CircularArrayWindows<Self, N>
where
Self: Sized + Clone + ExactSizeIterator,
Self::Item: Clone,
{
CircularArrayWindows::new(self)
}
}
impl<I: ?Sized> IterCircularArrayWindows for I where I: Iterator {}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct CircularArrayWindows<I, const N: usize>
where
I: Iterator + Clone,
{
iter: ArrayWindows<Cycle<I>, N>,
len: usize,
}
impl<I, const N: usize> CircularArrayWindows<I, N>
where
I: ExactSizeIterator + Clone,
I::Item: Clone,
{
fn new(iter: I) -> Self {
let len = iter.len();
let iter = iter.cycle().array_windows();
Self { iter, len }
}
}
impl<I, const N: usize> Debug for CircularArrayWindows<I, N>
where
I: Iterator + Clone + Debug,
I::Item: Clone + Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CircularArrayWindows")
.field("iter", &self.iter)
.field("len", &self.len)
.finish()
}
}
impl<I, const N: usize> Clone for CircularArrayWindows<I, N>
where
I: Iterator + Clone,
I::Item: Clone,
{
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
len: self.len,
}
}
}
impl<I, const N: usize> Iterator for CircularArrayWindows<I, N>
where
I: Iterator + Clone,
I::Item: Clone,
{
type Item = [I::Item; N];
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.len != 0 {
self.len -= 1;
self.iter.next()
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
#[inline]
fn count(self) -> usize {
self.len
}
}
impl<I, const N: usize> ExactSizeIterator for CircularArrayWindows<I, N>
where
I: ExactSizeIterator + Clone,
I::Item: Clone,
{
}
impl<I, const N: usize> FusedIterator for CircularArrayWindows<I, N>
where
I: ExactSizeIterator + Clone,
I::Item: Clone,
{
}