slice_group_by/linear_group/
linear_group_by_key.rs1use crate::offset_from;
2use std::slice::{from_raw_parts, from_raw_parts_mut};
3use std::{fmt, marker};
4
5macro_rules! group_by_key {
6 (struct $name:ident, $elem:ty, $mkslice:ident) => {
7 impl<'a, T: 'a, P> $name<'a, T, P> {
8 #[inline]
9 pub fn is_empty(&self) -> bool {
10 self.ptr == self.end
11 }
12
13 #[inline]
14 pub fn remainder_len(&self) -> usize {
15 unsafe { offset_from(self.end, self.ptr) }
16 }
17 }
18
19 impl<'a, T: 'a, F, K> std::iter::Iterator for $name<'a, T, F>
20 where
21 F: FnMut(&T) -> K,
22 K: PartialEq,
23 {
24 type Item = $elem;
25
26 fn next(&mut self) -> Option<Self::Item> {
27 if self.is_empty() {
28 return None;
29 }
30
31 let mut i = 0;
32 let mut ptr = self.ptr;
33
34 unsafe {
43 while ptr != self.end.sub(1) {
44 let a = &*ptr;
45 ptr = ptr.add(1);
46 let b = &*ptr;
47
48 i += 1;
49
50 if (self.func)(a) != (self.func)(b) {
51 let slice = $mkslice(self.ptr, i);
52 self.ptr = ptr;
53 return Some(slice);
54 }
55 }
56 }
57
58 let slice = unsafe { $mkslice(self.ptr, i + 1) };
64 self.ptr = self.end;
65 Some(slice)
66 }
67
68 fn size_hint(&self) -> (usize, Option<usize>) {
69 if self.is_empty() {
70 return (0, Some(0));
71 }
72
73 let len = self.remainder_len();
74 (1, Some(len))
75 }
76
77 fn last(mut self) -> Option<Self::Item> {
78 self.next_back()
79 }
80 }
81
82 impl<'a, T: 'a, F, K> std::iter::DoubleEndedIterator for $name<'a, T, F>
83 where
84 F: FnMut(&T) -> K,
85 K: PartialEq,
86 {
87 fn next_back(&mut self) -> Option<Self::Item> {
88 if self.is_empty() {
90 return None;
91 }
92
93 let mut i = 0;
94
95 unsafe {
96 let mut ptr = self.end.sub(1);
99
100 while ptr != self.ptr {
101 let a = &*ptr.sub(1);
104 let b = &*ptr;
105
106 i += 1;
107
108 if (self.func)(a) != (self.func)(b) {
109 let slice = $mkslice(ptr, i);
112
113 self.end = ptr;
116 return Some(slice);
117 }
118
119 ptr = ptr.sub(1);
120 }
121 }
122
123 let slice = unsafe { $mkslice(self.ptr, i + 1) };
124 self.ptr = self.end;
125 Some(slice)
126 }
127 }
128
129 impl<'a, T: 'a, F, K> std::iter::FusedIterator for $name<'a, T, F>
130 where
131 F: FnMut(&T) -> K,
132 K: PartialEq,
133 {
134 }
135 };
136}
137
138pub struct LinearGroupByKey<'a, T: 'a, F> {
144 ptr: *const T,
145 end: *const T,
146 func: F,
147 _phantom: marker::PhantomData<&'a T>,
148}
149
150impl<'a, T, F> LinearGroupByKey<'a, T, F> {
151 pub fn new(slice: &'a [T], func: F) -> Self {
152 LinearGroupByKey {
153 ptr: slice.as_ptr(),
154 end: unsafe { slice.as_ptr().add(slice.len()) },
155 func,
156 _phantom: marker::PhantomData,
157 }
158 }
159}
160
161impl<'a, T: 'a, F> LinearGroupByKey<'a, T, F> {
162 pub fn remainder(&self) -> &[T] {
165 let len = self.remainder_len();
166 unsafe { from_raw_parts(self.ptr, len) }
167 }
168}
169
170impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for LinearGroupByKey<'a, T, P> {
171 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172 f.debug_struct("LinearGroupByKey")
173 .field("remainder", &self.remainder())
174 .finish()
175 }
176}
177
178group_by_key! { struct LinearGroupByKey, &'a [T], from_raw_parts }
179
180pub struct LinearGroupByKeyMut<'a, T: 'a, F> {
186 ptr: *mut T,
187 end: *mut T,
188 func: F,
189 _phantom: marker::PhantomData<&'a mut T>,
190}
191
192impl<'a, T, F> LinearGroupByKeyMut<'a, T, F> {
193 pub fn new(slice: &'a mut [T], func: F) -> Self {
194 let ptr = slice.as_mut_ptr();
195 let end = unsafe { ptr.add(slice.len()) };
196 LinearGroupByKeyMut {
197 ptr,
198 end,
199 func,
200 _phantom: marker::PhantomData,
201 }
202 }
203}
204
205impl<'a, T: 'a, F> LinearGroupByKeyMut<'a, T, F> {
206 pub fn into_remainder(self) -> &'a mut [T] {
209 let len = self.remainder_len();
210 unsafe { from_raw_parts_mut(self.ptr, len) }
211 }
212}
213
214impl<'a, T: 'a + fmt::Debug, F> fmt::Debug for LinearGroupByKeyMut<'a, T, F> {
215 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
216 let len = self.remainder_len();
217 let remainder = unsafe { from_raw_parts(self.ptr, len) };
218
219 f.debug_struct("LinearGroupByKeyMut")
220 .field("remainder", &remainder)
221 .finish()
222 }
223}
224
225group_by_key! { struct LinearGroupByKeyMut, &'a mut [T], from_raw_parts_mut }