use core::iter::Peekable; /// An iterator that skips all leading zeros. /// /// When the wrapped iterator is all zeros, then the last item is retained. pub struct LeadingZerosStripped where I: Iterator, { inner: Peekable, } impl Clone for LeadingZerosStripped where I: Iterator, Peekable: Clone, { fn clone(&self) -> Self { Self { inner: self.inner.clone(), } } } impl LeadingZerosStripped where I: ExactSizeIterator, { pub fn new(inner: I) -> Self { let mut len = inner.len(); let mut inner = inner.peekable(); // Strip all leading zeroes, but don't strip the last byte if all bytes // were zero. while len > 1 && inner.next_if_eq(&0).is_some() { len -= 1; } Self { inner } } } impl Iterator for LeadingZerosStripped where I: Iterator, { type Item = I::Item; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl ExactSizeIterator for LeadingZerosStripped where I: ExactSizeIterator {} #[cfg(test)] mod tests { use super::*; #[test] fn test_leading_zeroes_stripped() { static TEST_CASES: &[(&[u8], &[u8])] = &[ (&[], &[]), (&[0], &[0]), (&[0, 1], &[1]), (&[0, 0, 1], &[1]), (&[0, 0, 0, 1], &[1]), (&[1, 0], &[1, 0]), (&[0, 1, 0], &[1, 0]), ]; TEST_CASES.iter().copied().for_each(|(input, expected)| { let stripped = LeadingZerosStripped::new(input.iter().copied()); super::super::test::assert_iterator(stripped, expected); }); } }