slice_group_by/linear_str_group/
linear_str_group_by_key.rs1use 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
92pub 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
110pub 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 }