Skip to content

Commit e75ffb0

Browse files
committed
use Iter<'_, [T; N]> in array_chunks
1 parent a410ebc commit e75ffb0

File tree

1 file changed

+20
-58
lines changed

1 file changed

+20
-58
lines changed

library/core/src/slice/mod.rs

+20-58
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,8 @@ impl<T> [T] {
852852
///
853853
/// # Panics
854854
///
855-
/// Panics if `N` is 0.
855+
/// Panics if `N` is 0. This check will most probably get changed to a compile time
856+
/// error before this method gets stabilized.
856857
///
857858
/// # Examples
858859
///
@@ -871,10 +872,12 @@ impl<T> [T] {
871872
#[inline]
872873
pub fn array_chunks<const N: usize>(&self) -> ArrayChunks<'_, T, N> {
873874
assert_ne!(N, 0);
874-
let rem = self.len() % N;
875-
let len = self.len() - rem;
876-
let (fst, snd) = self.split_at(len);
877-
ArrayChunks { v: fst, rem: snd }
875+
let len = self.len() / N;
876+
let (fst, snd) = self.split_at(len * N);
877+
// SAFETY: We cast a slice of `len * N` elements into
878+
// a slice of `len` many `N` elements chunks.
879+
let array_slice: &[[T; N]] = unsafe { from_raw_parts(fst.as_ptr().cast(), len) };
880+
ArrayChunks { iter: array_slice.iter(), rem: snd }
878881
}
879882

880883
/// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
@@ -5483,7 +5486,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
54835486
#[derive(Debug)]
54845487
#[unstable(feature = "array_chunks", issue = "none")]
54855488
pub struct ArrayChunks<'a, T: 'a, const N: usize> {
5486-
v: &'a [T],
5489+
iter: Iter<'a, [T; N]>,
54875490
rem: &'a [T],
54885491
}
54895492

@@ -5501,7 +5504,7 @@ impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
55015504
#[unstable(feature = "array_chunks", issue = "none")]
55025505
impl<T, const N: usize> Clone for ArrayChunks<'_, T, N> {
55035506
fn clone(&self) -> Self {
5504-
ArrayChunks { v: self.v, rem: self.rem }
5507+
ArrayChunks { iter: self.iter.clone(), rem: self.rem }
55055508
}
55065509
}
55075510

@@ -5511,84 +5514,47 @@ impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> {
55115514

55125515
#[inline]
55135516
fn next(&mut self) -> Option<&'a [T; N]> {
5514-
if self.v.len() < N {
5515-
None
5516-
} else {
5517-
let (fst, snd) = self.v.split_at(N);
5518-
self.v = snd;
5519-
// SAFETY: This is safe as fst is exactly N elements long.
5520-
let ptr = fst.as_ptr() as *const [T; N];
5521-
unsafe { Some(&*ptr) }
5522-
}
5517+
self.iter.next()
55235518
}
55245519

55255520
#[inline]
55265521
fn size_hint(&self) -> (usize, Option<usize>) {
5527-
let n = self.v.len() / N;
5528-
(n, Some(n))
5522+
self.iter.size_hint()
55295523
}
55305524

55315525
#[inline]
55325526
fn count(self) -> usize {
5533-
self.len()
5527+
self.iter.count()
55345528
}
55355529

55365530
#[inline]
55375531
fn nth(&mut self, n: usize) -> Option<Self::Item> {
5538-
let (start, overflow) = n.overflowing_mul(N);
5539-
if start >= self.v.len() || overflow {
5540-
self.v = &[];
5541-
None
5542-
} else {
5543-
let (_, snd) = self.v.split_at(start);
5544-
self.v = snd;
5545-
self.next()
5546-
}
5532+
self.iter.nth(n)
55475533
}
55485534

55495535
#[inline]
5550-
fn last(mut self) -> Option<Self::Item> {
5551-
self.next_back()
5536+
fn last(self) -> Option<Self::Item> {
5537+
self.iter.last()
55525538
}
55535539
}
55545540

55555541
#[unstable(feature = "array_chunks", issue = "none")]
55565542
impl<'a, T, const N: usize> DoubleEndedIterator for ArrayChunks<'a, T, N> {
55575543
#[inline]
55585544
fn next_back(&mut self) -> Option<&'a [T; N]> {
5559-
if self.v.len() < N {
5560-
None
5561-
} else {
5562-
let (fst, snd) = self.v.split_at(self.v.len() - N);
5563-
self.v = fst;
5564-
// SAFETY: This is safe as snd is exactly N elements long.
5565-
let ptr = snd.as_ptr() as *const [T; N];
5566-
unsafe { Some(&*ptr) }
5567-
}
5545+
self.iter.next_back()
55685546
}
55695547

55705548
#[inline]
55715549
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
5572-
let len = self.len();
5573-
if n >= len {
5574-
self.v = &[];
5575-
None
5576-
} else {
5577-
let start = (len - 1 - n) * N;
5578-
let end = start + N;
5579-
let nth_back = &self.v[start..end];
5580-
self.v = &self.v[..start];
5581-
// SAFETY: This is safe as snd is exactly N elements long.
5582-
let ptr = nth_back.as_ptr() as *const [T; N];
5583-
unsafe { Some(&*ptr) }
5584-
}
5550+
self.iter.nth_back(n)
55855551
}
55865552
}
55875553

55885554
#[unstable(feature = "array_chunks", issue = "none")]
55895555
impl<T, const N: usize> ExactSizeIterator for ArrayChunks<'_, T, N> {
55905556
fn is_empty(&self) -> bool {
5591-
self.v.is_empty()
5557+
self.iter.is_empty()
55925558
}
55935559
}
55945560

@@ -5602,11 +5568,7 @@ impl<T, const N: usize> FusedIterator for ArrayChunks<'_, T, N> {}
56025568
#[unstable(feature = "array_chunks", issue = "none")]
56035569
unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N> {
56045570
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T; N] {
5605-
let start = i * N;
5606-
// SAFETY: This is safe as `i` must be less than `self.size_hint`.
5607-
let segment = unsafe { from_raw_parts(self.v.as_ptr().add(start), N) };
5608-
// SAFETY: This is safe as segment is exactly `N` elements long.
5609-
unsafe { &*(segment.as_ptr() as *const [T; N]) }
5571+
unsafe { self.iter.get_unchecked(i) }
56105572
}
56115573
fn may_have_side_effect() -> bool {
56125574
false

0 commit comments

Comments
 (0)