| use crate::size_hint; | |
| use std::iter::{Fuse, FusedIterator}; | |
| /// 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<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); | |
| } | |
| /// Create a new `PadUsing` iterator. | |
| 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))) | |
| } | |
| fn fold<B, G>(self, mut init: B, mut f: G) -> B | |
| where | |
| G: FnMut(B, Self::Item) -> B, | |
| { | |
| let mut pos = self.pos; | |
| init = self.iter.fold(init, |acc, item| { | |
| pos += 1; | |
| f(acc, item) | |
| }); | |
| (pos..self.min).map(self.filler).fold(init, f) | |
| } | |
| } | |
| 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)) | |
| } | |
| } | |
| fn rfold<B, G>(self, mut init: B, mut f: G) -> B | |
| where | |
| G: FnMut(B, Self::Item) -> B, | |
| { | |
| init = (self.iter.len()..self.min) | |
| .map(self.filler) | |
| .rfold(init, &mut f); | |
| self.iter.rfold(init, f) | |
| } | |
| } | |
| 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, | |
| { | |
| } |