1 use std::iter::Fuse;
2 use crate::size_hint;
3 
4 /// An iterator adaptor that pads a sequence to a minimum length by filling
5 /// missing elements using a closure.
6 ///
7 /// Iterator element type is `I::Item`.
8 ///
9 /// See [`.pad_using()`](../trait.Itertools.html#method.pad_using) for more information.
10 #[derive(Clone)]
11 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
12 pub struct PadUsing<I, F> {
13     iter: Fuse<I>,
14     min: usize,
15     pos: usize,
16     filler: F,
17 }
18 
19 /// Create a new **PadUsing** iterator.
pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F> where I: Iterator, F: FnMut(usize) -> I::Item20 pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F>
21     where I: Iterator,
22           F: FnMut(usize) -> I::Item
23 {
24     PadUsing {
25         iter: iter.fuse(),
26         min,
27         pos: 0,
28         filler,
29     }
30 }
31 
32 impl<I, F> Iterator for PadUsing<I, F>
33     where I: Iterator,
34           F: FnMut(usize) -> I::Item
35 {
36     type Item = I::Item;
37 
38     #[inline]
next(&mut self) -> Option<I::Item>39     fn next(&mut self) -> Option<I::Item> {
40         match self.iter.next() {
41             None => {
42                 if self.pos < self.min {
43                     let e = Some((self.filler)(self.pos));
44                     self.pos += 1;
45                     e
46                 } else {
47                     None
48                 }
49             },
50             e => {
51                 self.pos += 1;
52                 e
53             }
54         }
55     }
56 
size_hint(&self) -> (usize, Option<usize>)57     fn size_hint(&self) -> (usize, Option<usize>) {
58         let tail = self.min.saturating_sub(self.pos);
59         size_hint::max(self.iter.size_hint(), (tail, Some(tail)))
60     }
61 }
62 
63 impl<I, F> DoubleEndedIterator for PadUsing<I, F>
64     where I: DoubleEndedIterator + ExactSizeIterator,
65           F: FnMut(usize) -> I::Item
66 {
next_back(&mut self) -> Option<I::Item>67     fn next_back(&mut self) -> Option<I::Item> {
68         if self.min == 0 {
69             self.iter.next_back()
70         } else if self.iter.len() >= self.min {
71             self.min -= 1;
72             self.iter.next_back()
73         } else {
74             self.min -= 1;
75             Some((self.filler)(self.min))
76         }
77     }
78 }
79 
80 impl<I, F> ExactSizeIterator for PadUsing<I, F>
81     where I: ExactSizeIterator,
82           F: FnMut(usize) -> I::Item
83 {}
84