itertools/
pad_tail.rs

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{}