slice_group_by/exponential_group/
exponential_group_by_key.rs1use crate::{exponential_search_by, offset_from};
2use std::cmp::Ordering::{Greater, Less};
3use std::slice::{from_raw_parts, from_raw_parts_mut};
4use std::{fmt, marker};
5
6macro_rules! exponential_group_by_key {
7 (struct $name:ident, $elem:ty, $mkslice:ident) => {
8 impl<'a, T: 'a, F> $name<'a, T, F> {
9 #[inline]
10 pub fn is_empty(&self) -> bool {
11 self.ptr == self.end
12 }
13
14 #[inline]
15 pub fn remainder_len(&self) -> usize {
16 unsafe { offset_from(self.end, self.ptr) }
17 }
18 }
19
20 impl<'a, T: 'a, F, K> std::iter::Iterator for $name<'a, T, F>
21 where
22 F: FnMut(&T) -> K,
23 K: PartialEq,
24 {
25 type Item = $elem;
26
27 fn next(&mut self) -> Option<Self::Item> {
28 if self.is_empty() {
29 return None;
30 }
31
32 let first = unsafe { &*self.ptr };
33
34 let len = self.remainder_len();
35 let tail = unsafe { $mkslice(self.ptr.add(1), len - 1) };
36
37 let predicate = |x: &T| {
38 if (self.func)(first) == (self.func)(x) {
39 Less
40 } else {
41 Greater
42 }
43 };
44 let index = exponential_search_by(tail, predicate).unwrap_err();
45
46 let left = unsafe { $mkslice(self.ptr, index + 1) };
47 self.ptr = unsafe { self.ptr.add(index + 1) };
48
49 Some(left)
50 }
51
52 fn size_hint(&self) -> (usize, Option<usize>) {
53 if self.is_empty() {
54 return (0, Some(0));
55 }
56
57 let len = self.remainder_len();
58 (1, Some(len))
59 }
60
61 fn last(mut self) -> Option<Self::Item> {
62 self.next_back()
63 }
64 }
65
66 impl<'a, T: 'a, F, K> std::iter::DoubleEndedIterator for $name<'a, T, F>
67 where
68 F: FnMut(&T) -> K,
69 K: PartialEq,
70 {
71 fn next_back(&mut self) -> Option<Self::Item> {
72 if self.is_empty() {
73 return None;
74 }
75
76 let last = unsafe { &*self.end.sub(1) };
77
78 let len = self.remainder_len();
79 let head = unsafe { $mkslice(self.ptr, len - 1) };
80
81 let predicate = |x: &T| {
82 if (self.func)(last) == (self.func)(x) {
83 Greater
84 } else {
85 Less
86 }
87 };
88 let index = exponential_search_by(head, predicate).unwrap_err();
89
90 let right = unsafe { $mkslice(self.ptr.add(index), len - index) };
91 self.end = unsafe { self.end.sub(len - index) };
92
93 Some(right)
94 }
95 }
96
97 impl<'a, T: 'a, F, K> std::iter::FusedIterator for $name<'a, T, F>
98 where
99 F: FnMut(&T) -> K,
100 K: PartialEq,
101 {
102 }
103 };
104}
105
106pub struct ExponentialGroupByKey<'a, T, F> {
111 ptr: *const T,
112 end: *const T,
113 func: F,
114 _phantom: marker::PhantomData<&'a T>,
115}
116
117impl<'a, T: 'a, F> ExponentialGroupByKey<'a, T, F> {
118 pub fn new(slice: &'a [T], func: F) -> Self {
119 ExponentialGroupByKey {
120 ptr: slice.as_ptr(),
121 end: unsafe { slice.as_ptr().add(slice.len()) },
122 func,
123 _phantom: marker::PhantomData,
124 }
125 }
126}
127
128impl<'a, T: 'a, F> ExponentialGroupByKey<'a, T, F> {
129 pub fn remainder(&self) -> &[T] {
132 let len = self.remainder_len();
133 unsafe { from_raw_parts(self.ptr, len) }
134 }
135}
136
137impl<'a, T: 'a + fmt::Debug, F> fmt::Debug for ExponentialGroupByKey<'a, T, F> {
138 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
139 f.debug_struct("ExponentialGroupByKey")
140 .field("remainder", &self.remainder())
141 .finish()
142 }
143}
144
145exponential_group_by_key! { struct ExponentialGroupByKey, &'a [T], from_raw_parts }
146
147pub struct ExponentialGroupByKeyMut<'a, T, F> {
153 ptr: *mut T,
154 end: *mut T,
155 func: F,
156 _phantom: marker::PhantomData<&'a mut T>,
157}
158
159impl<'a, T: 'a, F> ExponentialGroupByKeyMut<'a, T, F> {
160 pub fn new(slice: &'a mut [T], func: F) -> Self {
161 let ptr = slice.as_mut_ptr();
162 let end = unsafe { ptr.add(slice.len()) };
163 ExponentialGroupByKeyMut {
164 ptr,
165 end,
166 func,
167 _phantom: marker::PhantomData,
168 }
169 }
170}
171
172impl<'a, T: 'a, F> ExponentialGroupByKeyMut<'a, T, F> {
173 pub fn into_remainder(self) -> &'a mut [T] {
176 let len = self.remainder_len();
177 unsafe { from_raw_parts_mut(self.ptr, len) }
178 }
179}
180
181impl<'a, T: 'a + fmt::Debug, F> fmt::Debug for ExponentialGroupByKeyMut<'a, T, F> {
182 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183 let len = self.remainder_len();
184 let remainder = unsafe { from_raw_parts(self.ptr, len) };
185
186 f.debug_struct("ExponentialGroupByKeyMut")
187 .field("remaining", &remainder)
188 .finish()
189 }
190}
191
192exponential_group_by_key! { struct ExponentialGroupByKeyMut, &'a mut [T], from_raw_parts_mut }