1 //! An iterator that skips values equal to a provided value. 2 //! 3 //! SkipValueIterator iterates over a slice, returning all values 4 //! except for those matching the provided skip value. 5 //! 6 //! Example 7 //! ------- 8 //! 9 //! ```text 10 //! let iter = SkipValueIterator(&[1, 2, 5, 2, 6, 7], 2); 11 //! assert!(iter.eq([1, 5, 6, 7].iter())); 12 //! ``` 13 14 use crate::lib::slice; 15 use super::iterator::*; 16 17 /// Slice iterator that skips characters matching a given value. 18 pub(crate) struct SkipValueIterator<'a, T: 'a + PartialEq> { 19 /// Slice iterator to wrap. 20 iter: slice::Iter<'a, T>, 21 /// Value to skip. 22 skip: T 23 } 24 25 impl<'a, T: 'a + PartialEq> SkipValueIterator<'a, T> { 26 #[inline] new(slc: &'a [T], skip: T) -> Self27 pub(crate) fn new(slc: &'a [T], skip: T) -> Self { 28 SkipValueIterator { 29 iter: slc.iter(), 30 skip: skip 31 } 32 } 33 } 34 35 impl<'a, T: 'a + PartialEq + Clone> Clone for SkipValueIterator<'a, T> { 36 #[inline] clone(&self) -> Self37 fn clone(&self) -> Self { 38 SkipValueIterator { 39 iter: self.iter.clone(), 40 skip: self.skip.clone() 41 } 42 } 43 } 44 45 impl<'a, T: 'a + PartialEq> Iterator for SkipValueIterator<'a, T> { 46 type Item = &'a T; 47 48 #[inline] next(&mut self) -> Option<Self::Item>49 fn next(&mut self) -> Option<Self::Item> { 50 loop { 51 let value = self.iter.next()?; 52 if *value != self.skip { 53 return Some(value); 54 } 55 } 56 } 57 } 58 59 impl<'a, T: 'a + PartialEq> ConsumedIterator for SkipValueIterator<'a, T> { 60 // Preconditions: The iterator cannot end with `skip` characters. 61 // Use debug_assert to enforce this is removed successfully in test scenarios. 62 #[inline] consumed(&self) -> bool63 fn consumed(&self) -> bool { 64 // This implementation is essentially a hack. 65 // We rely on callers to ensure this is only ever called without 66 // any trailing digit separators, otherwise, it will incorrectly 67 // report if the iterator itself is consumed. 68 debug_assert!(self.iter.as_slice().last() != Some(&self.skip)); 69 self.iter.len() == 0 70 } 71 } 72 73 impl<'a, T: 'a + PartialEq> AsPtrIterator<'a, T> for SkipValueIterator<'a, T> { 74 #[inline] as_ptr(&self) -> *const T75 fn as_ptr(&self) -> *const T { 76 self.iter.as_slice().as_ptr() 77 } 78 } 79 80 // TESTS 81 // ----- 82 83 #[cfg(test)] 84 mod tests { 85 use super::*; 86 87 #[test] skip_value_test()88 fn skip_value_test() { 89 let slc = &[1, 2, 5, 2, 6, 7]; 90 let iter = SkipValueIterator::new(slc, 2); 91 assert!(iter.eq([1, 5, 6, 7].iter())); 92 93 let iter = SkipValueIterator::new(slc, 5); 94 assert!(iter.eq([1, 2, 2, 6, 7].iter())); 95 96 let iter = SkipValueIterator::new(slc, 1); 97 assert!(iter.eq([2, 5, 2, 6, 7].iter())); 98 } 99 } 100