slice_group_by/linear_str_group/
mod.rs1macro_rules! str_group_by_wrapped {
2 (struct $name:ident, $elem:ty) => {
3 impl<'a> $name<'a> {
4 #[inline]
5 pub fn as_str(&self) -> &str {
6 self.0.as_str()
7 }
8
9 #[inline]
10 pub fn is_empty(&self) -> bool {
11 self.0.is_empty()
12 }
13
14 #[inline]
15 pub fn remainder_len(&self) -> usize {
16 self.0.remainder_len()
17 }
18 }
19
20 impl<'a> std::iter::Iterator for $name<'a> {
21 type Item = $elem;
22
23 #[inline]
24 fn next(&mut self) -> Option<Self::Item> {
25 self.0.next()
26 }
27
28 fn last(self) -> Option<Self::Item> {
29 self.0.last()
30 }
31 }
32
33 impl<'a> DoubleEndedIterator for $name<'a> {
34 #[inline]
35 fn next_back(&mut self) -> Option<Self::Item> {
36 self.0.next_back()
37 }
38 }
39
40 impl<'a> std::iter::FusedIterator for $name<'a> { }
41 }
42}
43
44mod linear_str_group;
45mod linear_str_group_by;
46mod linear_str_group_by_key;
47
48pub use self::linear_str_group::{LinearStrGroup, LinearStrGroupMut};
49pub use self::linear_str_group_by::{LinearStrGroupBy, LinearStrGroupByMut};
50pub use self::linear_str_group_by_key::{LinearStrGroupByKey, LinearStrGroupByKeyMut};
51
52fn str_as_ptr(string: &str) -> *const u8 {
53 string.as_bytes().as_ptr()
54}
55
56fn str_as_mut_ptr(string: &mut str) -> *mut u8 {
57 unsafe { string.as_bytes_mut().as_mut_ptr() }
58}
59
60unsafe fn str_from_raw_parts<'a>(data: *const u8, len: usize) -> &'a str {
61 let slice = std::slice::from_raw_parts(data, len);
62 std::str::from_utf8_unchecked(slice)
63}
64
65unsafe fn str_from_raw_parts_mut<'a>(data: *mut u8, len: usize) -> &'a mut str {
66 let slice = std::slice::from_raw_parts_mut(data, len);
67 std::str::from_utf8_unchecked_mut(slice)
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn str_easy() {
76 let string = "aaaabbbbbaacccc";
77
78 let mut iter = LinearStrGroup::new(string);
79
80 assert_eq!(iter.next(), Some("aaaa"));
81 assert_eq!(iter.next(), Some("bbbbb"));
82 assert_eq!(iter.next(), Some("aa"));
83 assert_eq!(iter.next(), Some("cccc"));
84 assert_eq!(iter.next(), None);
85 }
86
87 #[test]
88 fn str_mut_easy() {
89 let mut string = String::from("aaaabbbbbaacccc");
90
91 let mut iter = LinearStrGroupMut::new(&mut string);
92
93 assert_eq!(iter.next().map(|s| &*s), Some("aaaa"));
94 assert_eq!(iter.next().map(|s| &*s), Some("bbbbb"));
95 assert_eq!(iter.next().map(|s| &*s), Some("aa"));
96 assert_eq!(iter.next().map(|s| &*s), Some("cccc"));
97 assert_eq!(iter.next(), None);
98 }
99
100 #[test]
101 fn str_kanji() {
102 let string = "包包饰饰与与钥钥匙匙扣扣";
103
104 let mut iter = LinearStrGroup::new(string);
105
106 assert_eq!(iter.next(), Some("包包"));
107 assert_eq!(iter.next(), Some("饰饰"));
108 assert_eq!(iter.next(), Some("与与"));
109 assert_eq!(iter.next(), Some("钥钥"));
110 assert_eq!(iter.next(), Some("匙匙"));
111 assert_eq!(iter.next(), Some("扣扣"));
112 assert_eq!(iter.next(), None);
113 }
114
115 fn is_cjk(c: char) -> bool {
116 (c >= '\u{2e80}' && c <= '\u{2eff}') ||
117 (c >= '\u{2f00}' && c <= '\u{2fdf}') ||
118 (c >= '\u{3040}' && c <= '\u{309f}') ||
119 (c >= '\u{30a0}' && c <= '\u{30ff}') ||
120 (c >= '\u{3100}' && c <= '\u{312f}') ||
121 (c >= '\u{3200}' && c <= '\u{32ff}') ||
122 (c >= '\u{3400}' && c <= '\u{4dbf}') ||
123 (c >= '\u{4e00}' && c <= '\u{9fff}') ||
124 (c >= '\u{f900}' && c <= '\u{faff}')
125 }
126
127 #[test]
128 fn str_ascii_cjk() {
129 let string = "abc包包bbccdd饰饰";
130
131 let mut iter = LinearStrGroupBy::new(string, |a, b| is_cjk(a) == is_cjk(b));
132
133 assert_eq!(iter.next(), Some("abc"));
134 assert_eq!(iter.next(), Some("包包"));
135 assert_eq!(iter.next(), Some("bbccdd"));
136 assert_eq!(iter.next(), Some("饰饰"));
137 assert_eq!(iter.next(), None);
138 }
139
140 #[test]
141 fn str_rev_easy() {
142 let string = "aaaabbbbbaacccc";
143
144 let mut iter = LinearStrGroup::new(string).rev();
145
146 assert_eq!(iter.next(), Some("cccc"));
147 assert_eq!(iter.next(), Some("aa"));
148 assert_eq!(iter.next(), Some("bbbbb"));
149 assert_eq!(iter.next(), Some("aaaa"));
150 assert_eq!(iter.next(), None);
151 }
152
153 #[test]
154 fn str_mut_rev_easy() {
155 let mut string = String::from("aaaabbbbbaacccc");
156
157 let mut iter = LinearStrGroupMut::new(&mut string).rev();
158
159 assert_eq!(iter.next().map(|s| &*s), Some("cccc"));
160 assert_eq!(iter.next().map(|s| &*s), Some("aa"));
161 assert_eq!(iter.next().map(|s| &*s), Some("bbbbb"));
162 assert_eq!(iter.next().map(|s| &*s), Some("aaaa"));
163 assert_eq!(iter.next(), None);
164 }
165
166 #[test]
167 fn str_rev_ascii_cjk() {
168 let string = "abc包包bbccdd饰饰";
169
170 let mut iter = LinearStrGroupBy::new(string, |a, b| is_cjk(a) == is_cjk(b)).rev();
171
172 assert_eq!(iter.next(), Some("饰饰"));
173 assert_eq!(iter.next(), Some("bbccdd"));
174 assert_eq!(iter.next(), Some("包包"));
175 assert_eq!(iter.next(), Some("abc"));
176 assert_eq!(iter.next(), None);
177 }
178}