slice_group_by/linear_str_group/
mod.rs

1macro_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}