]>
Commit | Line | Data |
---|---|---|
532ac7d7 XL |
1 | use std::iter::Fuse; |
2 | use 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. | |
20 | 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: min, | |
27 | pos: 0, | |
28 | filler: 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] | |
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 | ||
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 | { | |
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 | {} |