Skip to content

Commit 903624f

Browse files
committed
Add ExactChunks::remainder and ExactChunks::into_remainder
These allow to get the leftover items of the slice that are not being iterated as part of the iterator due to not filling a complete chunk. The mutable version consumes the slice because otherwise we would either a) have to borrow the iterator instead of taking the lifetime of the underlying slice, which is not what *any* of the other iterator functions is doing, or b) would allow returning multiple mutable references to the same data The current behaviour of consuming the iterator is consistent with IterMut::into_slice for the normal iterator.
1 parent 6eafab0 commit 903624f

File tree

2 files changed

+54
-8
lines changed

2 files changed

+54
-8
lines changed

src/libcore/slice/mod.rs

+40-8
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,8 @@ impl<T> [T] {
729729
/// Returns an iterator over `chunk_size` elements of the slice at a
730730
/// time. The chunks are slices and do not overlap. If `chunk_size` does
731731
/// not divide the length of the slice, then the last up to `chunk_size-1`
732-
/// elements will be omitted.
732+
/// elements will be omitted and can be retrieved from the `remainder`
733+
/// function of the iterator.
733734
///
734735
/// Due to each chunk having exactly `chunk_size` elements, the compiler
735736
/// can often optimize the resulting code better than in the case of
@@ -758,14 +759,15 @@ impl<T> [T] {
758759
assert!(chunk_size != 0);
759760
let rem = self.len() % chunk_size;
760761
let len = self.len() - rem;
761-
ExactChunks { v: &self[..len], chunk_size: chunk_size}
762+
let (fst, snd) = self.split_at(len);
763+
ExactChunks { v: fst, rem: snd, chunk_size: chunk_size}
762764
}
763765

764766
/// Returns an iterator over `chunk_size` elements of the slice at a time.
765767
/// The chunks are mutable slices, and do not overlap. If `chunk_size` does
766768
/// not divide the length of the slice, then the last up to `chunk_size-1`
767-
/// elements will be omitted.
768-
///
769+
/// elements will be omitted and can be retrieved from the `into_remainder`
770+
/// function of the iterator.
769771
///
770772
/// Due to each chunk having exactly `chunk_size` elements, the compiler
771773
/// can often optimize the resulting code better than in the case of
@@ -799,7 +801,8 @@ impl<T> [T] {
799801
assert!(chunk_size != 0);
800802
let rem = self.len() % chunk_size;
801803
let len = self.len() - rem;
802-
ExactChunksMut { v: &mut self[..len], chunk_size: chunk_size}
804+
let (fst, snd) = self.split_at_mut(len);
805+
ExactChunksMut { v: fst, rem: snd, chunk_size: chunk_size}
803806
}
804807

805808
/// Divides one slice into two at an index.
@@ -3654,25 +3657,39 @@ unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
36543657
/// time).
36553658
///
36563659
/// When the slice len is not evenly divided by the chunk size, the last
3657-
/// up to `chunk_size-1` elements will be omitted.
3660+
/// up to `chunk_size-1` elements will be omitted but can be retrieved from
3661+
/// the [`remainder`] function from the iterator.
36583662
///
36593663
/// This struct is created by the [`exact_chunks`] method on [slices].
36603664
///
36613665
/// [`exact_chunks`]: ../../std/primitive.slice.html#method.exact_chunks
3666+
/// [`remainder`]: ../../std/slice/struct.ExactChunks.html#method.remainder
36623667
/// [slices]: ../../std/primitive.slice.html
36633668
#[derive(Debug)]
36643669
#[unstable(feature = "exact_chunks", issue = "47115")]
36653670
pub struct ExactChunks<'a, T:'a> {
36663671
v: &'a [T],
3672+
rem: &'a [T],
36673673
chunk_size: usize
36683674
}
36693675

3676+
#[unstable(feature = "exact_chunks", issue = "47115")]
3677+
impl<'a, T> ExactChunks<'a, T> {
3678+
/// Return the remainder of the original slice that is not going to be
3679+
/// returned by the iterator. The returned slice has at most `chunk_size-1`
3680+
/// elements.
3681+
pub fn remainder(&self) -> &'a [T] {
3682+
self.rem
3683+
}
3684+
}
3685+
36703686
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
36713687
#[unstable(feature = "exact_chunks", issue = "47115")]
36723688
impl<'a, T> Clone for ExactChunks<'a, T> {
36733689
fn clone(&self) -> ExactChunks<'a, T> {
36743690
ExactChunks {
36753691
v: self.v,
3692+
rem: self.rem,
36763693
chunk_size: self.chunk_size,
36773694
}
36783695
}
@@ -3760,20 +3777,35 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunks<'a, T> {
37603777
}
37613778

37623779
/// An iterator over a slice in (non-overlapping) mutable chunks (`chunk_size`
3763-
/// elements at a time). When the slice len is not evenly divided by the chunk
3764-
/// size, the last up to `chunk_size-1` elements will be omitted.
3780+
/// elements at a time).
3781+
///
3782+
/// When the slice len is not evenly divided by the chunk size, the last up to
3783+
/// `chunk_size-1` elements will be omitted but can be retrieved from the
3784+
/// [`into_remainder`] function from the iterator.
37653785
///
37663786
/// This struct is created by the [`exact_chunks_mut`] method on [slices].
37673787
///
37683788
/// [`exact_chunks_mut`]: ../../std/primitive.slice.html#method.exact_chunks_mut
3789+
/// [`into_remainder`]: ../../std/slice/struct.ExactChunksMut.html#method.into_remainder
37693790
/// [slices]: ../../std/primitive.slice.html
37703791
#[derive(Debug)]
37713792
#[unstable(feature = "exact_chunks", issue = "47115")]
37723793
pub struct ExactChunksMut<'a, T:'a> {
37733794
v: &'a mut [T],
3795+
rem: &'a mut [T],
37743796
chunk_size: usize
37753797
}
37763798

3799+
#[unstable(feature = "exact_chunks", issue = "47115")]
3800+
impl<'a, T> ExactChunksMut<'a, T> {
3801+
/// Return the remainder of the original slice that is not going to be
3802+
/// returned by the iterator. The returned slice has at most `chunk_size-1`
3803+
/// elements.
3804+
pub fn into_remainder(self) -> &'a mut [T] {
3805+
self.rem
3806+
}
3807+
}
3808+
37773809
#[unstable(feature = "exact_chunks", issue = "47115")]
37783810
impl<'a, T> Iterator for ExactChunksMut<'a, T> {
37793811
type Item = &'a mut [T];

src/libcore/tests/slice.rs

+14
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ fn test_exact_chunks_last() {
259259
assert_eq!(c2.last().unwrap(), &[2, 3]);
260260
}
261261

262+
#[test]
263+
fn test_exact_chunks_remainder() {
264+
let v: &[i32] = &[0, 1, 2, 3, 4];
265+
let c = v.exact_chunks(2);
266+
assert_eq!(c.remainder(), &[4]);
267+
}
268+
262269
#[test]
263270
fn test_exact_chunks_zip() {
264271
let v1: &[i32] = &[0, 1, 2, 3, 4];
@@ -310,6 +317,13 @@ fn test_exact_chunks_mut_last() {
310317
assert_eq!(c2.last().unwrap(), &[2, 3]);
311318
}
312319

320+
#[test]
321+
fn test_exact_chunks_mut_remainder() {
322+
let v: &mut [i32] = &mut [0, 1, 2, 3, 4];
323+
let c = v.exact_chunks_mut(2);
324+
assert_eq!(c.into_remainder(), &[4]);
325+
}
326+
313327
#[test]
314328
fn test_exact_chunks_mut_zip() {
315329
let v1: &mut [i32] = &mut [0, 1, 2, 3, 4];

0 commit comments

Comments
 (0)