1 use core::iter::Peekable;
2 
3 /// An iterator that skips all leading zeros.
4 ///
5 /// When the wrapped iterator is all zeros, then the last item is retained.
6 pub struct LeadingZerosStripped<I>
7 where
8     I: Iterator,
9 {
10     inner: Peekable<I>,
11 }
12 
13 impl<I> Clone for LeadingZerosStripped<I>
14 where
15     I: Iterator,
16     Peekable<I>: Clone,
17 {
clone(&self) -> Self18     fn clone(&self) -> Self {
19         Self {
20             inner: self.inner.clone(),
21         }
22     }
23 }
24 
25 impl<I> LeadingZerosStripped<I>
26 where
27     I: ExactSizeIterator<Item = u8>,
28 {
new(inner: I) -> Self29     pub fn new(inner: I) -> Self {
30         let mut len = inner.len();
31         let mut inner = inner.peekable();
32         // Strip all leading zeroes, but don't strip the last byte if all bytes
33         // were zero.
34         while len > 1 && inner.next_if_eq(&0).is_some() {
35             len -= 1;
36         }
37         Self { inner }
38     }
39 }
40 
41 impl<I> Iterator for LeadingZerosStripped<I>
42 where
43     I: Iterator,
44 {
45     type Item = I::Item;
46 
next(&mut self) -> Option<Self::Item>47     fn next(&mut self) -> Option<Self::Item> {
48         self.inner.next()
49     }
50 
size_hint(&self) -> (usize, Option<usize>)51     fn size_hint(&self) -> (usize, Option<usize>) {
52         self.inner.size_hint()
53     }
54 }
55 
56 impl<I> ExactSizeIterator for LeadingZerosStripped<I> where I: ExactSizeIterator {}
57 
58 #[cfg(test)]
59 mod tests {
60     use super::*;
61 
62     #[test]
test_leading_zeroes_stripped()63     fn test_leading_zeroes_stripped() {
64         static TEST_CASES: &[(&[u8], &[u8])] = &[
65             (&[], &[]),
66             (&[0], &[0]),
67             (&[0, 1], &[1]),
68             (&[0, 0, 1], &[1]),
69             (&[0, 0, 0, 1], &[1]),
70             (&[1, 0], &[1, 0]),
71             (&[0, 1, 0], &[1, 0]),
72         ];
73         TEST_CASES.iter().copied().for_each(|(input, expected)| {
74             let stripped = LeadingZerosStripped::new(input.iter().copied());
75             super::super::test::assert_iterator(stripped, expected);
76         });
77     }
78 }
79