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