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