use crate::size_hint;
use std::iter::{Fuse, FusedIterator};
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct PadUsing<I, F> {
iter: Fuse<I>,
min: usize,
pos: usize,
filler: F,
}
impl<I, F> std::fmt::Debug for PadUsing<I, F>
where
I: std::fmt::Debug,
{
debug_fmt_fields!(PadUsing, iter, min, pos);
}
pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F>
where
I: Iterator,
F: FnMut(usize) -> I::Item,
{
PadUsing {
iter: iter.fuse(),
min,
pos: 0,
filler,
}
}
impl<I, F> Iterator for PadUsing<I, F>
where
I: Iterator,
F: FnMut(usize) -> I::Item,
{
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => {
if self.pos < self.min {
let e = Some((self.filler)(self.pos));
self.pos += 1;
e
} else {
None
}
}
e => {
self.pos += 1;
e
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let tail = self.min.saturating_sub(self.pos);
size_hint::max(self.iter.size_hint(), (tail, Some(tail)))
}
}
impl<I, F> DoubleEndedIterator for PadUsing<I, F>
where
I: DoubleEndedIterator + ExactSizeIterator,
F: FnMut(usize) -> I::Item,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.min == 0 {
self.iter.next_back()
} else if self.iter.len() >= self.min {
self.min -= 1;
self.iter.next_back()
} else {
self.min -= 1;
Some((self.filler)(self.min))
}
}
}
impl<I, F> ExactSizeIterator for PadUsing<I, F>
where
I: ExactSizeIterator,
F: FnMut(usize) -> I::Item,
{
}
impl<I, F> FusedIterator for PadUsing<I, F>
where
I: FusedIterator,
F: FnMut(usize) -> I::Item,
{
}