slice_ext/
lib.rs

1
2
3#![no_std]
4
5/// SplitBefore trait returns an iterator splitting a slice before a predicate
6/// and including the matched item at the start of the next set (if found).
7/// For example:
8/// 
9/// ```
10/// use slice_ext::*;
11/// 
12/// let a: &[u8] = &[0, 1, 2]; 
13/// let mut s = (&a[..]).split_before(|v| *v == 1 );
14/// 
15/// assert_eq!(s.next().unwrap(), &[0]);
16/// assert_eq!(s.next().unwrap(), &[1, 2]);
17/// assert_eq!(s.next().is_none(), true);
18/// 
19/// ```
20pub trait SplitBefore<'a, T: 'a, P> {
21    fn split_before(&self, predicate: P) -> SplitInc<'a, T, P>;
22}
23
24impl <'a, T: 'a, P> SplitBefore<'a, T, P> for &'a [T] 
25where
26    P: FnMut(&T) -> bool,
27    T: core::fmt::Debug,
28{
29    fn split_before(&self, predicate: P) -> SplitInc<'a, T, P> {
30        SplitInc::split_before(&self, predicate)
31    }
32}
33
34/// SplitAfter trait returns an iterator splitting a slice after a predicate
35/// and including the matched item at the end of each set (if existing).
36/// For example: 
37/// 
38/// ```
39/// use slice_ext::*;
40/// 
41/// let a: &[u8] = &[0, 1, 2]; 
42/// let mut s = (&a[..]).split_after(|v| *v == 1 );
43/// 
44/// assert_eq!(s.next().unwrap(), &[0, 1]);
45/// assert_eq!(s.next().unwrap(), &[2]);
46/// assert_eq!(s.next().is_none(), true);
47/// 
48/// ```
49pub trait SplitAfter<'a, T: 'a, P> {
50    fn split_after(&self, predicate: P) -> SplitInc<'a, T, P>;
51}
52
53impl <'a, T: 'a, P> SplitAfter<'a, T, P> for &'a [T] 
54where
55    P: FnMut(&T) -> bool,
56    T: core::fmt::Debug,
57{
58    fn split_after(&self, predicate: P) -> SplitInc<'a, T, P> {
59        SplitInc::split_after(&self, predicate)
60    }
61}
62
63pub struct SplitInc<'a, T: 'a, F> {
64    index: usize,
65    data: &'a [T],
66    matcher: F,
67    mode: Mode,
68}
69
70enum Mode {
71    Before,
72    After,
73}
74
75impl <'a, T, F> SplitInc<'a, T, F> 
76where 
77    F: FnMut(&T) -> bool,
78    T: core::fmt::Debug,
79{
80    pub fn split_before(data: &'a [T], matcher: F) -> Self {
81        SplitInc{ index: 0, data, matcher, mode: Mode::Before }
82    }
83
84    pub fn split_after(data: &'a [T], matcher: F) -> Self {
85        SplitInc{ index: 0, data, matcher, mode: Mode::After }
86    }
87
88    fn iter_before(&mut self) -> Option<&'a [T]> {
89        // Short circuit on completion
90        if self.index == self.data.len() {
91            return None
92        }
93
94        // Select search range
95        let index = self.index;
96
97        for i in index..self.data.len() {
98
99            if (self.matcher)(&self.data[i]) {
100                // If our match is in the first position, and we're not at the end,
101                // continue searching
102                if i == index && i < self.data.len() - 1 {
103                    continue
104                // If our match is in the first position, and we are at the end,
105                // return the last entry
106                } else if i == index {
107                    self.index = self.data.len();
108                    return Some(&self.data[index..])
109                }
110
111                // When a match is found, update the count and return preceding data
112                self.index = i;
113                return Some(&self.data[index..i])
114            }
115
116             // When we're out of data, return anything left
117            if i == (self.data.len() - 1) {
118                self.index = self.data.len();
119                return Some(&self.data[index..])
120            }
121        }
122
123        None
124    }
125
126    fn iter_after(&mut self) -> Option<&'a [T]> {
127        // Short circuit on completion
128        if self.index == self.data.len() {
129            return None
130        }
131
132        // Select search range
133        let index = self.index;
134
135        for i in index..self.data.len() {
136
137            // When a match is found, update the count and return preceding data
138            if (self.matcher)(&self.data[i]) {
139                self.index = i+1;
140                return Some(&self.data[index..i+1])
141            }
142
143            // When we're out of data, return anything left
144            if i == (self.data.len() - 1) {
145                self.index = self.data.len();
146                return Some(&self.data[index..])
147            }
148        }
149
150        None
151    }
152}
153
154impl <'a, T, F> Iterator for SplitInc<'a, T, F> 
155where 
156    F: FnMut(&T) -> bool,
157    T: core::fmt::Debug,
158{
159    type Item = &'a [T];
160    
161    fn next(&mut self) -> Option<Self::Item> {
162    
163        match self.mode {
164            Mode::Before => self.iter_before(),
165            Mode::After => self.iter_after(),
166        }
167    }
168}
169
170#[cfg(test)]
171mod tests {
172    use super::*;
173
174    #[test]
175    fn test_split_before() {
176        let a: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
177        
178        let mut s = (&a[..]).split_before(|v| *v == 2 || *v == 5);
179        
180        assert_eq!(s.next().unwrap(), &[0, 1]);
181        assert_eq!(s.next().unwrap(), &[2, 3, 4]);
182        assert_eq!(s.next().unwrap(), &[5, 6, 7, 8]);
183        assert_eq!(s.next().is_none(), true);
184    }
185    
186    #[test]
187    fn test_split_before_no_match() {
188        let a: &[u8] = &[0, 1, 2];
189        
190        let mut s = SplitInc::split_before(&a, |v| *v == 12);
191        
192        assert_eq!(s.next().unwrap(), &[0, 1, 2]);
193        assert_eq!(s.next().is_none(), true);
194    }
195    
196    #[test]
197    fn test_split_before_start() {
198        let a: &[u8] = &[0, 1, 2];
199        
200        let mut s = SplitInc::split_before(&a, |v| *v == 0 );
201        
202        assert_eq!(s.next().unwrap(), &[0, 1, 2]);
203        assert_eq!(s.next().is_none(), true);
204    }
205    
206    #[test]
207    fn test_split_before_end() {
208        let a: &[u8] = &[0, 1, 2];
209        
210        let mut s = SplitInc::split_before(&a, |v| *v == 2 );
211        
212        assert_eq!(s.next().unwrap(), &[0, 1]);
213        assert_eq!(s.next().unwrap(), &[2]);
214        assert_eq!(s.next().is_none(), true);
215    }
216
217    #[test]
218    fn test_split_after() {
219        let a: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
220        
221        let mut s = SplitInc::split_after(&a, |v| *v == 2 || *v == 5);
222        
223        assert_eq!(s.next().unwrap(), &[0, 1, 2]);
224        assert_eq!(s.next().unwrap(), &[3, 4, 5]);
225        assert_eq!(s.next().unwrap(), &[6, 7, 8]);
226        assert_eq!(s.next().is_none(), true);
227    }
228    
229    #[test]
230    fn test_split_after_no_match() {
231        let a: &[u8] = &[0, 1, 2];
232        
233        let mut s = SplitInc::split_after(&a, |v| *v == 12);
234        
235        assert_eq!(s.next().unwrap(), &[0, 1, 2]);
236        assert_eq!(s.next().is_none(), true);
237    }
238    
239    #[test]
240    fn test_split_after_start() {
241        let a: &[u8] = &[0, 1, 2];
242        
243        let mut s = SplitInc::split_after(&a, |v| *v == 0 );
244        
245        assert_eq!(s.next().unwrap(), &[0]);
246        assert_eq!(s.next().unwrap(), &[1, 2]);
247        assert_eq!(s.next().is_none(), true);
248    }
249    
250    #[test]
251    fn test_split_after_end() {
252        let a: &[u8] = &[0, 1, 2];
253        
254        let mut s = SplitInc::split_after(&a, |v| *v == 2 );
255        
256        assert_eq!(s.next().unwrap(), &[0, 1, 2]);
257        assert_eq!(s.next().is_none(), true);
258    }
259}
260