specialize slice_iter.copied().next_chunk()
This commit is contained in:
parent
963d6f757c
commit
873a18e221
@ -2,7 +2,10 @@
|
|||||||
zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
|
zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
|
||||||
};
|
};
|
||||||
use crate::iter::{FusedIterator, TrustedLen};
|
use crate::iter::{FusedIterator, TrustedLen};
|
||||||
|
use crate::mem::MaybeUninit;
|
||||||
|
use crate::mem::SizedTypeProperties;
|
||||||
use crate::ops::Try;
|
use crate::ops::Try;
|
||||||
|
use crate::{array, ptr};
|
||||||
|
|
||||||
/// An iterator that copies the elements of an underlying iterator.
|
/// An iterator that copies the elements of an underlying iterator.
|
||||||
///
|
///
|
||||||
@ -44,6 +47,15 @@ fn next(&mut self) -> Option<T> {
|
|||||||
self.it.next().copied()
|
self.it.next().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn next_chunk<const N: usize>(
|
||||||
|
&mut self,
|
||||||
|
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
<I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
|
||||||
|
}
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
self.it.size_hint()
|
self.it.size_hint()
|
||||||
}
|
}
|
||||||
@ -166,3 +178,65 @@ unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
|
|||||||
T: Copy,
|
T: Copy,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
|
||||||
|
where
|
||||||
|
T: Copy,
|
||||||
|
{
|
||||||
|
fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
|
||||||
|
where
|
||||||
|
I: Iterator<Item = &'a T>,
|
||||||
|
T: Copy,
|
||||||
|
{
|
||||||
|
default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
|
||||||
|
array::iter_next_chunk(&mut self.map(|e| *e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T>
|
||||||
|
where
|
||||||
|
T: Copy,
|
||||||
|
{
|
||||||
|
fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
|
||||||
|
let mut raw_array = MaybeUninit::uninit_array();
|
||||||
|
|
||||||
|
let len = self.len();
|
||||||
|
|
||||||
|
if T::IS_ZST {
|
||||||
|
if len < N {
|
||||||
|
let _ = self.advance_by(len);
|
||||||
|
// SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct
|
||||||
|
return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = self.advance_by(N);
|
||||||
|
// SAFETY: ditto
|
||||||
|
return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
|
||||||
|
}
|
||||||
|
|
||||||
|
if len < N {
|
||||||
|
// SAFETY: `len` indicates that this many elements are available and we just checked that
|
||||||
|
// it fits into the array.
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(
|
||||||
|
self.as_ref().as_ptr(),
|
||||||
|
raw_array.as_mut_ptr() as *mut T,
|
||||||
|
len,
|
||||||
|
);
|
||||||
|
let _ = self.advance_by(len);
|
||||||
|
return Err(array::IntoIter::new_unchecked(raw_array, 0..len));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize
|
||||||
|
// the array.
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
|
||||||
|
let _ = self.advance_by(N);
|
||||||
|
Ok(MaybeUninit::array_assume_init(raw_array))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user