• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::size_hint;
2 use std::iter::{Fuse, FusedIterator};
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 impl<I, F> std::fmt::Debug for PadUsing<I, F>
20 where
21     I: std::fmt::Debug,
22 {
23     debug_fmt_fields!(PadUsing, iter, min, pos);
24 }
25 
26 /// 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::Item,27 pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F>
28 where
29     I: Iterator,
30     F: FnMut(usize) -> I::Item,
31 {
32     PadUsing {
33         iter: iter.fuse(),
34         min,
35         pos: 0,
36         filler,
37     }
38 }
39 
40 impl<I, F> Iterator for PadUsing<I, F>
41 where
42     I: Iterator,
43     F: FnMut(usize) -> I::Item,
44 {
45     type Item = I::Item;
46 
47     #[inline]
next(&mut self) -> Option<Self::Item>48     fn next(&mut self) -> Option<Self::Item> {
49         match self.iter.next() {
50             None => {
51                 if self.pos < self.min {
52                     let e = Some((self.filler)(self.pos));
53                     self.pos += 1;
54                     e
55                 } else {
56                     None
57                 }
58             }
59             e => {
60                 self.pos += 1;
61                 e
62             }
63         }
64     }
65 
size_hint(&self) -> (usize, Option<usize>)66     fn size_hint(&self) -> (usize, Option<usize>) {
67         let tail = self.min.saturating_sub(self.pos);
68         size_hint::max(self.iter.size_hint(), (tail, Some(tail)))
69     }
70 
fold<B, G>(self, mut init: B, mut f: G) -> B where G: FnMut(B, Self::Item) -> B,71     fn fold<B, G>(self, mut init: B, mut f: G) -> B
72     where
73         G: FnMut(B, Self::Item) -> B,
74     {
75         let mut pos = self.pos;
76         init = self.iter.fold(init, |acc, item| {
77             pos += 1;
78             f(acc, item)
79         });
80         (pos..self.min).map(self.filler).fold(init, f)
81     }
82 }
83 
84 impl<I, F> DoubleEndedIterator for PadUsing<I, F>
85 where
86     I: DoubleEndedIterator + ExactSizeIterator,
87     F: FnMut(usize) -> I::Item,
88 {
next_back(&mut self) -> Option<Self::Item>89     fn next_back(&mut self) -> Option<Self::Item> {
90         if self.min == 0 {
91             self.iter.next_back()
92         } else if self.iter.len() >= self.min {
93             self.min -= 1;
94             self.iter.next_back()
95         } else {
96             self.min -= 1;
97             Some((self.filler)(self.min))
98         }
99     }
100 
rfold<B, G>(self, mut init: B, mut f: G) -> B where G: FnMut(B, Self::Item) -> B,101     fn rfold<B, G>(self, mut init: B, mut f: G) -> B
102     where
103         G: FnMut(B, Self::Item) -> B,
104     {
105         init = (self.iter.len()..self.min)
106             .map(self.filler)
107             .rfold(init, &mut f);
108         self.iter.rfold(init, f)
109     }
110 }
111 
112 impl<I, F> ExactSizeIterator for PadUsing<I, F>
113 where
114     I: ExactSizeIterator,
115     F: FnMut(usize) -> I::Item,
116 {
117 }
118 
119 impl<I, F> FusedIterator for PadUsing<I, F>
120 where
121     I: FusedIterator,
122     F: FnMut(usize) -> I::Item,
123 {
124 }
125