padded_iterator/
lib.rs

1//! This crate provides an iterator that pads the end of the iterator with a value up to a given length.
2//!
3//! # Examples:
4//!
5//! ```
6//! use padded_iterator::PaddedIterBuilder;
7//!
8//! let mut iter = PaddedIterBuilder::new()
9//!     .iter(vec![1, 2, 3].into_iter())
10//!     .length(5)
11//!     .pad(0)
12//!     .build()
13//!     .unwrap();
14//!
15//! assert_eq!(iter.next(), Some(1));
16//! assert_eq!(iter.next(), Some(2));
17//! assert_eq!(iter.next(), Some(3));
18//! assert_eq!(iter.next(), Some(0));
19//! assert_eq!(iter.next(), Some(0));
20//! assert_eq!(iter.next(), None);
21//! ```
22//!
23//! ```
24//! use padded_iterator::PaddedIter;
25//!
26//! let mut iter = PaddedIter::from((vec![1, 2, 3].into_iter(), 5, 0));
27//!
28//! assert_eq!(iter.next(), Some(1));
29//! assert_eq!(iter.next(), Some(2));
30//! assert_eq!(iter.next(), Some(3));
31//! assert_eq!(iter.next(), Some(0));
32//! assert_eq!(iter.next(), Some(0));
33//! assert_eq!(iter.next(), None);
34//! ```
35
36mod utils;
37#[cfg(test)]
38mod tests;
39
40pub use self::utils::BuildError;
41
42/// An iterator which has been padded to a given length.
43#[derive(Debug)]
44pub struct PaddedIter<T: Iterator<Item = U>, U> {
45    iter: T,
46    n: usize,
47    length: usize,
48    pad: U,
49}
50
51impl<T, U> PaddedIter<T, U>
52where
53    T: Iterator<Item = U>,
54    U: Clone,
55{
56    pub fn next(&mut self) -> Option<U> {
57        self.n += 1;
58
59        if self.n > self.length {
60            return None;
61        }
62
63        let next_item = self.iter.next();
64        match next_item {
65            Some(item) => Some(item),
66            None => Some(self.pad.clone()),
67        }
68    }
69}
70
71impl<T, U> From<(T, usize, U)> for PaddedIter<T, U>
72where
73    T: Iterator<Item = U>,
74    U: Clone,
75{
76    /// Create a new PaddedIter from an iterator, length, and pad value.
77    ///
78    /// # Examples:
79    ///
80    /// ```
81    /// use padded_iterator::PaddedIter;
82    ///
83    /// let mut iter = PaddedIter::from((vec![1, 2, 3].into_iter(), 5, 0));
84    ///
85    /// assert_eq!(iter.next(), Some(1));
86    /// assert_eq!(iter.next(), Some(2));
87    /// assert_eq!(iter.next(), Some(3));
88    /// assert_eq!(iter.next(), Some(0));
89    /// assert_eq!(iter.next(), Some(0));
90    /// assert_eq!(iter.next(), None);
91    /// ```
92    fn from((iter, length, pad): (T, usize, U)) -> Self {
93        Self {
94            iter,
95            n: 0,
96            length,
97            pad,
98        }
99    }
100}
101
102/// A builder for PaddedIter.
103pub struct PaddedIterBuilder<T: Iterator<Item = U>, U> {
104    iter: Option<T>,
105    length: Option<usize>,
106    pad: Option<U>,
107}
108
109impl<T, U> PaddedIterBuilder<T, U>
110where
111    T: Iterator<Item = U>,
112    U: Clone,
113{
114    pub fn new() -> Self {
115        PaddedIterBuilder {
116            iter: None,
117            length: None,
118            pad: None,
119        }
120    }
121
122    /// Sets the base iterator for the PaddedIter.
123    pub fn iter(mut self, iter: T) -> Self {
124        self.iter = Some(iter);
125        self
126    }
127
128    /// Sets the length to pad the iterator to.
129    pub fn length(mut self, length: usize) -> Self {
130        self.length = Some(length);
131        self
132    }
133
134    /// Sets the value to pad the iterator with.
135    pub fn pad(mut self, pad: U) -> Self {
136        self.pad = Some(pad);
137        self
138    }
139
140    /// Consumes the builder and returns a PaddedIter.
141    pub fn build(self) -> Result<PaddedIter<T, U>, BuildError> {
142        let iter = self.iter.ok_or(BuildError::IterNotSet)?;
143        let length = self.length.ok_or(BuildError::LengthNotSet)?;
144        let pad = self.pad.ok_or(BuildError::PadNotSet)?;
145
146        Ok(PaddedIter {
147            iter,
148            n: 0,
149            length,
150            pad,
151        })
152    }
153}