slice_group_by/linear_str_group/
linear_str_group_by_key.rs

1use std::mem;
2use super::{str_as_ptr, str_as_mut_ptr, str_from_raw_parts, str_from_raw_parts_mut};
3
4macro_rules! str_group_by_key {
5    (struct $name:ident, $elem:ty, $as_ptr:ident, $as_str:ident) => {
6        impl<'a, F> $name<'a, F> {
7            #[inline]
8            pub fn as_str(&self) -> &str {
9                self.inner
10            }
11
12            #[inline]
13            pub fn is_empty(&self) -> bool {
14                self.inner.is_empty()
15            }
16
17            #[inline]
18            pub fn remainder_len(&self) -> usize {
19                self.inner.len()
20            }
21        }
22
23        impl<'a, F, K> std::iter::Iterator for $name<'a, F>
24        where F: FnMut(char) -> K,
25              K: PartialEq,
26        {
27            type Item = $elem;
28
29            #[inline]
30            fn next(&mut self) -> Option<Self::Item> {
31                if self.inner.is_empty() { return None }
32
33                let mut iter = self.inner.char_indices().peekable();
34                while let (Some((_, ac)), Some((bi, bc))) = (iter.next(), iter.peek().cloned())
35                {
36                    if (self.func)(ac) != (self.func)(bc) {
37                        let len = self.inner.len();
38                        let ptr = $as_ptr(self.inner);
39
40                        let left = unsafe { $as_str(ptr, bi) };
41                        let right = unsafe { $as_str(ptr.add(bi), len - bi) };
42
43                        self.inner = right;
44                        return Some(left);
45                    }
46                }
47
48                let output = mem::replace(&mut self.inner, Default::default());
49                return Some(output);
50            }
51
52            fn last(mut self) -> Option<Self::Item> {
53                self.next_back()
54            }
55        }
56
57        impl<'a, F, K> std::iter::DoubleEndedIterator for $name<'a, F>
58        where F: FnMut(char) -> K,
59              K: PartialEq,
60        {
61            #[inline]
62            fn next_back(&mut self) -> Option<Self::Item> {
63                if self.inner.is_empty() { return None }
64
65                let mut iter = self.inner.char_indices().rev().peekable();
66                while let (Some((ai, ac)), Some((_, bc))) = (iter.next(), iter.peek().cloned())
67                {
68                    if (self.func)(ac) != (self.func)(bc) {
69                        let len = self.inner.len();
70                        let ptr = $as_ptr(self.inner);
71
72                        let left = unsafe { $as_str(ptr, ai) };
73                        let right = unsafe { $as_str(ptr.add(ai), len - ai) };
74
75                        self.inner = left;
76                        return Some(right);
77                    }
78                }
79
80                let output = mem::replace(&mut self.inner, Default::default());
81                return Some(output);
82            }
83        }
84
85        impl<'a, F, K> std::iter::FusedIterator for $name<'a, F>
86        where F: FnMut(char) -> K,
87              K: PartialEq,
88        { }
89    }
90}
91
92/// An iterator that will return non-overlapping groups in the `str`
93/// using *linear/sequential search*.
94///
95/// It will give an element to the given function, producing a key and comparing
96/// the keys to determine groups.
97pub struct LinearStrGroupByKey<'a, F> {
98    inner: &'a str,
99    func: F,
100}
101
102impl<'a, F> LinearStrGroupByKey<'a, F> {
103    pub fn new(string: &'a str, func: F) -> Self {
104        Self { inner: string, func }
105    }
106}
107
108str_group_by_key!{ struct LinearStrGroupByKey, &'a str, str_as_ptr, str_from_raw_parts }
109
110/// An iterator that will return non-overlapping *mutable* groups in the `str`
111/// using *linear/sequential search*.
112///
113/// It will give an element to the given function, producing a key and comparing
114/// the keys to determine groups.
115pub struct LinearStrGroupByKeyMut<'a, F> {
116    inner: &'a mut str,
117    func: F,
118}
119
120impl<'a, F> LinearStrGroupByKeyMut<'a, F> {
121    pub fn new(string: &'a mut str, func: F) -> Self {
122        Self { inner: string, func }
123    }
124
125    #[inline]
126    pub fn as_str_mut(&mut self) -> &mut str {
127        &mut self.inner
128    }
129}
130
131str_group_by_key!{ struct LinearStrGroupByKeyMut, &'a mut str, str_as_mut_ptr, str_from_raw_parts_mut }