slice_group_by/binary_group/
binary_group_by_key.rs1use crate::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! binary_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 #[inline]
28 fn next(&mut self) -> Option<Self::Item> {
29 if self.is_empty() {
30 return None;
31 }
32
33 let first = unsafe { &*self.ptr };
34
35 let len = self.remainder_len();
36 let tail = unsafe { $mkslice(self.ptr.add(1), len - 1) };
37
38 let predicate = |x: &T| {
39 if (self.func)(first) == (self.func)(x) {
40 Less
41 } else {
42 Greater
43 }
44 };
45 let index = tail.binary_search_by(predicate).unwrap_err();
46
47 let left = unsafe { $mkslice(self.ptr, index + 1) };
48 self.ptr = unsafe { self.ptr.add(index + 1) };
49
50 Some(left)
51 }
52
53 fn size_hint(&self) -> (usize, Option<usize>) {
54 if self.is_empty() {
55 return (0, Some(0));
56 }
57
58 let len = self.remainder_len();
59 (1, Some(len))
60 }
61
62 fn last(mut self) -> Option<Self::Item> {
63 self.next_back()
64 }
65 }
66
67 impl<'a, T: 'a, F, K> std::iter::DoubleEndedIterator for $name<'a, T, F>
68 where
69 F: FnMut(&T) -> K,
70 K: PartialEq,
71 {
72 #[inline]
73 fn next_back(&mut self) -> Option<Self::Item> {
74 if self.is_empty() {
75 return None;
76 }
77
78 let last = unsafe { &*self.end.sub(1) };
79
80 let len = self.remainder_len();
81 let head = unsafe { $mkslice(self.ptr, len - 1) };
82
83 let predicate = |x: &T| {
84 if (self.func)(last) == (self.func)(x) {
85 Greater
86 } else {
87 Less
88 }
89 };
90 let index = head.binary_search_by(predicate).unwrap_err();
91
92 let right = unsafe { $mkslice(self.ptr.add(index), len - index) };
93 self.end = unsafe { self.end.sub(len - index) };
94
95 Some(right)
96 }
97 }
98
99 impl<'a, T: 'a, F, K> std::iter::FusedIterator for $name<'a, T, F>
100 where
101 F: FnMut(&T) -> K,
102 K: PartialEq,
103 {
104 }
105 };
106}
107
108pub struct BinaryGroupByKey<'a, T, F> {
113 ptr: *const T,
114 end: *const T,
115 func: F,
116 _phantom: marker::PhantomData<&'a T>,
117}
118
119impl<'a, T: 'a, F> BinaryGroupByKey<'a, T, F> {
120 pub fn new(slice: &'a [T], func: F) -> Self {
121 BinaryGroupByKey {
122 ptr: slice.as_ptr(),
123 end: unsafe { slice.as_ptr().add(slice.len()) },
124 func,
125 _phantom: marker::PhantomData,
126 }
127 }
128}
129
130impl<'a, T, F> BinaryGroupByKey<'a, T, F> {
131 pub fn remainder(&self) -> &[T] {
134 let len = self.remainder_len();
135 unsafe { from_raw_parts(self.ptr, len) }
136 }
137}
138
139impl<'a, T: 'a + fmt::Debug, F> fmt::Debug for BinaryGroupByKey<'a, T, F> {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 f.debug_struct("BinaryGroupByKey")
142 .field("remainder", &self.remainder())
143 .finish()
144 }
145}
146
147binary_group_by_key! { struct BinaryGroupByKey, &'a [T], from_raw_parts }
148
149pub struct BinaryGroupByKeyMut<'a, T, F> {
155 ptr: *mut T,
156 end: *mut T,
157 func: F,
158 _phantom: marker::PhantomData<&'a mut T>,
159}
160
161impl<'a, T: 'a, F> BinaryGroupByKeyMut<'a, T, F> {
162 pub fn new(slice: &'a mut [T], func: F) -> Self {
163 let ptr = slice.as_mut_ptr();
164 let end = unsafe { ptr.add(slice.len()) };
165 BinaryGroupByKeyMut {
166 ptr,
167 end,
168 func,
169 _phantom: marker::PhantomData,
170 }
171 }
172}
173
174impl<'a, T, F> BinaryGroupByKeyMut<'a, T, F> {
175 pub fn remainder(&self) -> &[T] {
178 let len = self.remainder_len();
179 unsafe { from_raw_parts(self.ptr, len) }
180 }
181}
182
183impl<'a, T: 'a + fmt::Debug, F> fmt::Debug for BinaryGroupByKeyMut<'a, T, F> {
184 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185 f.debug_struct("BinaryGroupByKeyMut")
186 .field("remainder", &self.remainder())
187 .finish()
188 }
189}
190
191binary_group_by_key! { struct BinaryGroupByKeyMut, &'a mut [T], from_raw_parts_mut }