1 use std::iter::{Fuse, FusedIterator};
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()`](crate::Itertools::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<Self::Item>39 fn next(&mut self) -> Option<Self::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<Self::Item>67 fn next_back(&mut self) -> Option<Self::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
85
86 impl<I, F> FusedIterator for PadUsing<I, F>
87 where I: FusedIterator,
88 F: FnMut(usize) -> I::Item
89 {}
90