use std::iter::{Fuse, FusedIterator}; use crate::size_hint; /// An iterator adaptor that pads a sequence to a minimum length by filling /// missing elements using a closure. /// /// Iterator element type is `I::Item`. /// /// See [`.pad_using()`](crate::Itertools::pad_using) for more information. #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] pub struct PadUsing { iter: Fuse, min: usize, pos: usize, filler: F, } impl std::fmt::Debug for PadUsing where I: std::fmt::Debug, { debug_fmt_fields!(PadUsing, iter, min, pos); } /// Create a new `PadUsing` iterator. pub fn pad_using(iter: I, min: usize, filler: F) -> PadUsing where I: Iterator, F: FnMut(usize) -> I::Item { PadUsing { iter: iter.fuse(), min, pos: 0, filler, } } impl Iterator for PadUsing where I: Iterator, F: FnMut(usize) -> I::Item { type Item = I::Item; #[inline] fn next(&mut self) -> Option { 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) { let tail = self.min.saturating_sub(self.pos); size_hint::max(self.iter.size_hint(), (tail, Some(tail))) } } impl DoubleEndedIterator for PadUsing where I: DoubleEndedIterator + ExactSizeIterator, F: FnMut(usize) -> I::Item { fn next_back(&mut self) -> Option { 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 ExactSizeIterator for PadUsing where I: ExactSizeIterator, F: FnMut(usize) -> I::Item {} impl FusedIterator for PadUsing where I: FusedIterator, F: FnMut(usize) -> I::Item {}