gmsol_store/utils/
chunk_by.rs

1/// A `slice::chunk_by` implementation, copied from `std`.
2#[inline]
3pub fn chunk_by<T, F>(slice: &[T], pred: F) -> ChunkBy<'_, T, F>
4where
5    F: FnMut(&T, &T) -> bool,
6{
7    ChunkBy::new(slice, pred)
8}
9
10/// Iterator returns by [`chunk_by`].
11pub struct ChunkBy<'a, T: 'a, P> {
12    slice: &'a [T],
13    predicate: P,
14}
15
16impl<'a, T: 'a, P> ChunkBy<'a, T, P> {
17    pub(super) fn new(slice: &'a [T], predicate: P) -> Self {
18        ChunkBy { slice, predicate }
19    }
20}
21
22impl<'a, T: 'a, P> Iterator for ChunkBy<'a, T, P>
23where
24    P: FnMut(&T, &T) -> bool,
25{
26    type Item = &'a [T];
27
28    #[inline]
29    fn next(&mut self) -> Option<Self::Item> {
30        if self.slice.is_empty() {
31            None
32        } else {
33            let mut len = 1;
34            let mut iter = self.slice.windows(2);
35            while let Some([l, r]) = iter.next() {
36                if (self.predicate)(l, r) {
37                    len += 1
38                } else {
39                    break;
40                }
41            }
42            let (head, tail) = self.slice.split_at(len);
43            self.slice = tail;
44            Some(head)
45        }
46    }
47
48    #[inline]
49    fn size_hint(&self) -> (usize, Option<usize>) {
50        if self.slice.is_empty() {
51            (0, Some(0))
52        } else {
53            (1, Some(self.slice.len()))
54        }
55    }
56}