1use std::iter::{Fuse, FusedIterator};
2use 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"]
12pub struct PadUsing<I, F> {
13 iter: Fuse<I>,
14 min: usize,
15 pos: usize,
16 filler: F,
17}
18
19impl<I, F> std::fmt::Debug for PadUsing<I, F>
20where
21 I: std::fmt::Debug,
22{
23 debug_fmt_fields!(PadUsing, iter, min, pos);
24}
25
26/// Create a new `PadUsing` iterator.
27pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F>
28 where I: Iterator,
29 F: FnMut(usize) -> I::Item
30{
31 PadUsing {
32 iter: iter.fuse(),
33 min,
34 pos: 0,
35 filler,
36 }
37}
38
39impl<I, F> Iterator for PadUsing<I, F>
40 where I: Iterator,
41 F: FnMut(usize) -> I::Item
42{
43 type Item = I::Item;
44
45 #[inline]
46 fn next(&mut self) -> Option<Self::Item> {
47 match self.iter.next() {
48 None => {
49 if self.pos < self.min {
50 let e = Some((self.filler)(self.pos));
51 self.pos += 1;
52 e
53 } else {
54 None
55 }
56 },
57 e => {
58 self.pos += 1;
59 e
60 }
61 }
62 }
63
64 fn size_hint(&self) -> (usize, Option<usize>) {
65 let tail = self.min.saturating_sub(self.pos);
66 size_hint::max(self.iter.size_hint(), (tail, Some(tail)))
67 }
68}
69
70impl<I, F> DoubleEndedIterator for PadUsing<I, F>
71 where I: DoubleEndedIterator + ExactSizeIterator,
72 F: FnMut(usize) -> I::Item
73{
74 fn next_back(&mut self) -> Option<Self::Item> {
75 if self.min == 0 {
76 self.iter.next_back()
77 } else if self.iter.len() >= self.min {
78 self.min -= 1;
79 self.iter.next_back()
80 } else {
81 self.min -= 1;
82 Some((self.filler)(self.min))
83 }
84 }
85}
86
87impl<I, F> ExactSizeIterator for PadUsing<I, F>
88 where I: ExactSizeIterator,
89 F: FnMut(usize) -> I::Item
90{}
91
92
93impl<I, F> FusedIterator for PadUsing<I, F>
94 where I: FusedIterator,
95 F: FnMut(usize) -> I::Item
96{}
97