vec_utils/vec/
general_zip.rs1use std::alloc::Layout;
2
3use super::{r#try, Input, Output, Try};
4
5use seal::Seal;
6mod seal {
7 use super::*;
8
9 pub unsafe trait Seal {
10 const LEN: u64;
11
12 type Item;
13 type Data;
14 type Iter: Iterator<Item = Self::Item>;
15
16 fn into_data(self) -> Self::Data;
17
18 fn remaining_len(&self) -> usize;
19
20 fn into_iterator(self) -> Self::Iter;
21
22 fn check_layout<V>() -> bool;
23
24 fn max_cap<V>(data: &Self::Data, depth: &mut u64) -> Option<usize>;
25
26 unsafe fn take_output<V>(data: &mut Self::Data) -> Output<V>;
27
28 unsafe fn take_output_impl<V>(_: &mut Self::Data, min_cap: u64) -> Output<V>;
29
30 unsafe fn next_unchecked(data: &mut Self::Data) -> Self::Item;
31
32 unsafe fn drop_rest(data: &mut Self::Data, len: usize);
33 }
34}
35
36pub trait Tuple: Seal {}
43
44#[allow(clippy::len_without_is_empty)]
53pub unsafe trait TupleElem {
54 type Item;
56
57 type Data;
60
61 type Iter: Iterator<Item = Self::Item>;
63
64 fn capacity(data: &Self::Data) -> usize;
66
67 fn len(&self) -> usize;
71
72 fn into_data(self) -> Self::Data;
74
75 fn into_iterator(self) -> Self::Iter;
77
78 fn check_layout<V>() -> bool;
81
82 unsafe fn take_output<V>(data: &mut Self::Data) -> Output<V>;
90
91 unsafe fn next_unchecked(data: &mut Self::Data) -> Self::Item;
97
98 unsafe fn drop_rest(data: &mut Self::Data, len: usize);
106}
107
108unsafe impl<A: TupleElem> TupleElem for (A,) {
109 type Item = A::Item;
110 type Data = A::Data;
111 type Iter = A::Iter;
112
113 #[inline(always)]
114 fn capacity(data: &Self::Data) -> usize {
115 A::capacity(data)
116 }
117
118 #[inline(always)]
119 fn len(&self) -> usize {
120 A::len(&self.0)
121 }
122
123 #[inline]
124 fn into_data(self) -> Self::Data {
125 self.0.into_data()
126 }
127
128 #[inline]
129 fn into_iterator(self) -> Self::Iter {
130 self.0.into_iterator()
131 }
132
133 #[inline]
134 fn check_layout<V>() -> bool {
135 A::check_layout::<V>()
136 }
137
138 #[inline]
139 unsafe fn take_output<V>(data: &mut Self::Data) -> Output<V> {
140 A::take_output(data)
141 }
142
143 #[inline]
144 unsafe fn next_unchecked(data: &mut Self::Data) -> Self::Item {
145 A::next_unchecked(data)
146 }
147
148 #[inline]
149 unsafe fn drop_rest(data: &mut Self::Data, len: usize) {
150 A::drop_rest(data, len)
151 }
152}
153
154unsafe impl<A> TupleElem for Vec<A> {
155 type Item = A;
156 type Data = Input<A>;
157 type Iter = std::vec::IntoIter<A>;
158
159 #[inline(always)]
160 fn capacity(data: &Self::Data) -> usize {
161 data.cap
162 }
163
164 #[inline(always)]
165 fn len(&self) -> usize {
166 self.len()
167 }
168
169 #[inline]
170 fn into_data(self) -> Self::Data {
171 Input::from(self)
172 }
173
174 #[inline]
175 fn into_iterator(self) -> Self::Iter {
176 self.into_iter()
177 }
178
179 #[inline]
180 fn check_layout<V>() -> bool {
181 Layout::new::<A>() == Layout::new::<V>()
182 }
183
184 #[inline]
185 unsafe fn take_output<V>(data: &mut Self::Data) -> Output<V> {
186 debug_assert!(Layout::new::<A>() == Layout::new::<V>());
187
188 data.drop_alloc = false;
189 Output::new(data.start as *mut V, data.cap)
190 }
191
192 #[inline]
193 unsafe fn next_unchecked(data: &mut Self::Data) -> Self::Item {
194 let ptr = data.ptr;
195 data.ptr = data.ptr.add(1);
196 ptr.read()
197 }
198
199 #[inline]
200 unsafe fn drop_rest(data: &mut Self::Data, len: usize) {
201 defer! {
202 if data.drop_alloc {
203 Vec::from_raw_parts(data.start, 0, data.cap);
204 }
205 }
206
207 std::ptr::drop_in_place(std::slice::from_raw_parts_mut(data.ptr, data.len - len));
208 }
209}
210
211impl<A: TupleElem> Tuple for (A,) {}
212unsafe impl<A: TupleElem> Seal for (A,) {
213 const LEN: u64 = 0;
214
215 type Item = A::Item;
216 type Data = A::Data;
217 type Iter = A::Iter;
218
219 #[inline]
220 fn into_data(self) -> Self::Data {
221 self.0.into_data()
222 }
223
224 #[inline]
225 fn into_iterator(self) -> Self::Iter {
226 self.0.into_iterator()
227 }
228
229 #[inline]
230 fn remaining_len(&self) -> usize {
231 self.0.len()
232 }
233
234 #[inline]
235 fn check_layout<V>() -> bool {
236 A::check_layout::<V>()
237 }
238
239 #[inline]
240 fn max_cap<V>(data: &Self::Data, depth: &mut u64) -> Option<usize> {
241 if A::check_layout::<V>() {
242 *depth = Self::LEN;
243 Some(A::capacity(data))
244 } else {
245 None
246 }
247 }
248
249 #[inline]
250 unsafe fn take_output<V>(data: &mut Self::Data) -> Output<V> {
251 A::take_output::<V>(data)
252 }
253
254 #[inline]
255 unsafe fn take_output_impl<V>(data: &mut Self::Data, depth: u64) -> Output<V> {
256 debug_assert_eq!(Self::LEN, depth);
257 A::take_output(data)
258 }
259
260 #[inline]
261 unsafe fn next_unchecked(data: &mut Self::Data) -> Self::Item {
262 A::next_unchecked(data)
263 }
264
265 #[inline]
266 unsafe fn drop_rest(data: &mut Self::Data, len: usize) {
267 A::drop_rest(data, len)
268 }
269}
270
271impl<A: TupleElem, T: Tuple> Tuple for (A, T) {}
272unsafe impl<A: TupleElem, T: Seal> Seal for (A, T) {
273 const LEN: u64 = T::LEN + 1;
274
275 type Item = (A::Item, T::Item);
276 type Data = (A::Data, T::Data);
277 type Iter = std::iter::Zip<A::Iter, T::Iter>;
278
279 #[inline]
280 fn into_data(self) -> Self::Data {
281 (self.0.into_data(), self.1.into_data())
282 }
283
284 #[inline]
285 fn into_iterator(self) -> Self::Iter {
286 self.0.into_iterator().zip(self.1.into_iterator())
287 }
288
289 #[inline]
290 fn remaining_len(&self) -> usize {
291 self.0.len().min(self.1.remaining_len())
292 }
293
294 #[inline]
295 fn check_layout<V>() -> bool {
296 A::check_layout::<V>() || T::check_layout::<V>()
297 }
298
299 #[inline]
300 fn max_cap<V>((a, rest): &Self::Data, depth: &mut u64) -> Option<usize> {
301 let cap_rest = T::max_cap::<V>(rest, depth);
302
303 if A::check_layout::<V>() {
304 let cap = A::capacity(a);
305
306 if let Some(cap_rest) = cap_rest {
307 if cap_rest > cap {
308 return Some(cap_rest);
309 }
310 }
311
312 *depth = Self::LEN;
313 Some(cap)
314 } else {
315 cap_rest
316 }
317 }
318
319 #[inline]
320 unsafe fn take_output<V>(data: &mut Self::Data) -> Output<V> {
321 let mut depth = 0;
322 let val = Self::max_cap::<V>(data, &mut depth);
323 debug_assert!(val.is_some());
324 Self::take_output_impl(data, depth)
325 }
326
327 #[inline]
328 unsafe fn take_output_impl<V>((a, rest): &mut Self::Data, depth: u64) -> Output<V> {
329 if Self::LEN == depth {
330 A::take_output(a)
331 } else {
332 T::take_output_impl(rest, depth)
333 }
334 }
335
336 #[inline]
337 unsafe fn next_unchecked((vec, rest): &mut Self::Data) -> Self::Item {
338 (A::next_unchecked(vec), T::next_unchecked(rest))
339 }
340
341 #[inline]
342 unsafe fn drop_rest((vec, rest): &mut Self::Data, len: usize) {
343 defer! {
344 T::drop_rest(rest, len);
345 }
346
347 A::drop_rest(vec, len)
348 }
349}
350
351struct ZipWithIter<V, In: Tuple> {
352 output: Output<V>,
355
356 input: In::Data,
358
359 initial_len: usize,
361
362 remaining_len: usize,
364
365 should_free_output: bool,
366}
367
368pub fn try_zip_with_impl<R: Try, In: Tuple>(
370 input: In,
371 f: impl FnMut(In::Item) -> R,
372) -> Result<Vec<R::Ok>, R::Error> {
373 if In::check_layout::<R::Ok>() {
374 let len = input.remaining_len();
375 let mut input = input.into_data();
376
377 ZipWithIter::<_, In> {
378 output: unsafe { In::take_output::<R::Ok>(&mut input) },
379 input,
380 initial_len: len,
381 remaining_len: len,
382 should_free_output: true,
383 }
384 .try_into_vec(f)
385 } else {
386 input.into_iterator().map(f).map(R::into_result).collect()
387 }
388}
389
390impl<V, In: Tuple> ZipWithIter<V, In> {
391 pub fn try_into_vec<R: Try<Ok = V>, F: FnMut(In::Item) -> R>(
392 mut self,
393 mut f: F,
394 ) -> Result<Vec<V>, R::Error> {
395 unsafe {
398 while let Some(remaining_len) = self.remaining_len.checked_sub(1) {
399 self.remaining_len = remaining_len;
400
401 let input = In::next_unchecked(&mut self.input);
402
403 self.output.ptr.write(r#try!(f(input)));
404 self.output.ptr = self.output.ptr.add(1);
405 }
406
407 self.should_free_output = false;
410
411 let (ptr, len, cap) = (
412 self.output.start,
413 self.initial_len,
414 self.output.cap,
415 );
416
417 drop(self);
418
419 Ok(Vec::from_raw_parts(ptr, len, cap))
421 }
422 }
423}
424
425impl<V, In: Tuple> Drop for ZipWithIter<V, In> {
426 fn drop(&mut self) {
427 let &mut ZipWithIter {
428 ref mut output,
429 ref mut input,
430 should_free_output,
431 initial_len,
432 remaining_len,
433 ..
434 } = self;
435
436 let initialized_len = initial_len - remaining_len;
437
438 defer! {
439 if should_free_output {
440 unsafe {
441 Vec::from_raw_parts(output.start, initialized_len - 1, output.cap);
442 }
443 }
444 }
445
446 unsafe {
447 In::drop_rest(input, initialized_len);
448 }
449 }
450}