Skip to content

Commit 6adcad8

Browse files
committed
Use array::IntoIter for the ArrayChunks remainder
1 parent c115d5a commit 6adcad8

File tree

4 files changed

+33
-105
lines changed

4 files changed

+33
-105
lines changed

library/core/src/array/iter.rs

+10
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ impl<T, const N: usize> IntoIter<T, N> {
8484
IntoIterator::into_iter(array)
8585
}
8686

87+
/// Creates a new iterator from a partially initalized array.
88+
///
89+
/// # Safety
90+
///
91+
/// The caller must guarantee that all and only the `alive` elements of
92+
/// `data` are initialized.
93+
pub(crate) unsafe fn with_partial(data: [MaybeUninit<T>; N], alive: Range<usize>) -> Self {
94+
Self { data, alive }
95+
}
96+
8797
/// Creates an iterator over the elements in a partially-initialized buffer.
8898
///
8999
/// If you have a fully-initialized array, then use [`IntoIterator`].

library/core/src/iter/adapters/array_chunks.rs

+14-79
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,10 @@
1+
use crate::array;
12
use crate::iter::{Fuse, FusedIterator, Iterator, TrustedLen};
23
use crate::mem;
34
use crate::mem::MaybeUninit;
45
use crate::ops::{ControlFlow, Try};
56
use crate::ptr;
67

7-
#[derive(Debug)]
8-
struct Remainder<T, const N: usize> {
9-
array: [MaybeUninit<T>; N],
10-
init: usize,
11-
}
12-
13-
impl<T, const N: usize> Remainder<T, N> {
14-
fn new() -> Self {
15-
Self { array: MaybeUninit::uninit_array(), init: 0 }
16-
}
17-
18-
unsafe fn with_init(array: [MaybeUninit<T>; N], init: usize) -> Self {
19-
Self { array, init }
20-
}
21-
22-
fn as_slice(&self) -> &[T] {
23-
debug_assert!(self.init <= N);
24-
// SAFETY: This raw slice will only contain the initialized objects
25-
// within the buffer.
26-
unsafe {
27-
let slice = self.array.get_unchecked(..self.init);
28-
MaybeUninit::slice_assume_init_ref(slice)
29-
}
30-
}
31-
32-
fn as_mut_slice(&mut self) -> &mut [T] {
33-
debug_assert!(self.init <= N);
34-
// SAFETY: This raw slice will only contain the initialized objects
35-
// within the buffer.
36-
unsafe {
37-
let slice = self.array.get_unchecked_mut(..self.init);
38-
MaybeUninit::slice_assume_init_mut(slice)
39-
}
40-
}
41-
}
42-
43-
impl<T, const N: usize> Clone for Remainder<T, N>
44-
where
45-
T: Clone,
46-
{
47-
fn clone(&self) -> Self {
48-
let mut new = Self::new();
49-
// SAFETY: The new array is the same size and `init` is always less than
50-
// or equal to `N`.
51-
let this = unsafe { new.array.get_unchecked_mut(..self.init) };
52-
MaybeUninit::write_slice_cloned(this, self.as_slice());
53-
new.init = self.init;
54-
new
55-
}
56-
}
57-
58-
impl<T, const N: usize> Drop for Remainder<T, N> {
59-
fn drop(&mut self) {
60-
// SAFETY: This raw slice will only contain the initialized objects
61-
// within the buffer.
62-
unsafe { ptr::drop_in_place(self.as_mut_slice()) }
63-
}
64-
}
65-
668
/// An iterator over `N` elements of the iterator at a time.
679
///
6810
/// The chunks do not overlap. If `N` does not divide the length of the
@@ -75,7 +17,7 @@ impl<T, const N: usize> Drop for Remainder<T, N> {
7517
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "none")]
7618
pub struct ArrayChunks<I: Iterator, const N: usize> {
7719
iter: Fuse<I>,
78-
remainder: Remainder<I::Item, N>,
20+
remainder: Option<array::IntoIter<I::Item, N>>,
7921
}
8022

8123
impl<I, const N: usize> ArrayChunks<I, N>
@@ -84,25 +26,16 @@ where
8426
{
8527
pub(in crate::iter) fn new(iter: I) -> Self {
8628
assert!(N != 0, "chunk size must be non-zero");
87-
Self { iter: iter.fuse(), remainder: Remainder::new() }
88-
}
89-
90-
/// Returns a reference to the remaining elements of the original iterator
91-
/// that are not going to be returned by this iterator. The returned slice
92-
/// has at most `N-1` elements.
93-
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "none")]
94-
#[inline]
95-
pub fn remainder(&self) -> &[I::Item] {
96-
self.remainder.as_slice()
29+
Self { iter: iter.fuse(), remainder: None }
9730
}
9831

99-
/// Returns a mutable reference to the remaining elements of the original
100-
/// iterator that are not going to be returned by this iterator. The
101-
/// returned slice has at most `N-1` elements.
32+
/// Returns an iterator over the remaining elements of the original iterator
33+
/// that are not going to be returned by this iterator. The returned
34+
/// iterator will yield at most `N-1` elements.
10235
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "none")]
10336
#[inline]
104-
pub fn remainder_mut(&mut self) -> &mut [I::Item] {
105-
self.remainder.as_mut_slice()
37+
pub fn into_remainder(self) -> Option<array::IntoIter<I::Item, N>> {
38+
self.remainder
10639
}
10740
}
10841

@@ -129,8 +62,10 @@ where
12962
if guard.init > 0 {
13063
let init = guard.init;
13164
mem::forget(guard);
132-
// SAFETY: `array` was initialized with `init` elements.
133-
self.remainder = unsafe { Remainder::with_init(array, init) };
65+
self.remainder = {
66+
// SAFETY: `array` was initialized with `init` elements.
67+
Some(unsafe { array::IntoIter::with_partial(array, 0..init) })
68+
};
13469
}
13570
return None;
13671
}
@@ -189,7 +124,7 @@ where
189124
let init = guard.init;
190125
mem::forget(guard);
191126
// SAFETY: `array` was initialized with `init` elements.
192-
self.remainder = unsafe { Remainder::with_init(array, init) };
127+
self.remainder = Some(unsafe { array::IntoIter::with_partial(array, 0..init) });
193128
}
194129
R::from_output(o)
195130
}
@@ -370,7 +305,7 @@ where
370305
// SAFETY: `array` was initialized with exactly `init` elements.
371306
self.remainder = unsafe {
372307
array.get_unchecked_mut(..init).reverse();
373-
Remainder::with_init(array, init)
308+
Some(array::IntoIter::with_partial(array, 0..init))
374309
};
375310
Some(())
376311
}

library/core/src/iter/traits/iterator.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -3092,7 +3092,9 @@ pub trait Iterator {
30923092
/// Returns an iterator over `N` elements of the iterator at a time.
30933093
///
30943094
/// The chunks do not overlap. If `N` does not divide the length of the
3095-
/// iterator, then the last up to `N-1` elements will be omitted.
3095+
/// iterator, then the last up to `N-1` elements will be omitted and can be
3096+
/// retrieved from the [`.into_remainder()`][ArrayChunks::into_remainder]
3097+
/// function of the iterator.
30963098
///
30973099
/// # Panics
30983100
///
@@ -3109,7 +3111,7 @@ pub trait Iterator {
31093111
/// assert_eq!(iter.next(), Some(['l', 'o']));
31103112
/// assert_eq!(iter.next(), Some(['r', 'e']));
31113113
/// assert_eq!(iter.next(), None);
3112-
/// assert_eq!(iter.remainder(), &['m']);
3114+
/// assert_eq!(iter.into_remainder().unwrap().as_slice(), &['m']);
31133115
/// ```
31143116
///
31153117
/// ```

library/core/tests/iter/adapters/array_chunks.rs

+5-24
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,24 @@ fn test_iterator_array_chunks_infer() {
1515
fn test_iterator_array_chunks_clone_and_drop() {
1616
let count = Cell::new(0);
1717
let mut it = (0..5).map(|_| CountDrop::new(&count)).array_chunks::<3>();
18-
1918
assert_eq!(it.by_ref().count(), 1);
2019
assert_eq!(count.get(), 3);
21-
assert_eq!(it.remainder().len(), 2);
22-
2320
let mut it2 = it.clone();
2421
assert_eq!(count.get(), 3);
25-
assert_eq!(it2.remainder().len(), 2);
26-
27-
drop(it);
22+
assert_eq!(it.into_remainder().unwrap().len(), 2);
2823
assert_eq!(count.get(), 5);
29-
assert_eq!(it2.remainder().len(), 2);
3024
assert!(it2.next().is_none());
31-
32-
drop(it2);
25+
assert_eq!(it2.into_remainder().unwrap().len(), 2);
3326
assert_eq!(count.get(), 7);
3427
}
3528

3629
#[test]
3730
fn test_iterator_array_chunks_remainder() {
3831
let mut it = (0..11).array_chunks::<4>();
39-
assert_eq!(it.remainder(), &[]);
40-
assert_eq!(it.remainder_mut(), &[]);
4132
assert_eq!(it.next(), Some([0, 1, 2, 3]));
42-
assert_eq!(it.remainder(), &[]);
43-
assert_eq!(it.remainder_mut(), &[]);
4433
assert_eq!(it.next(), Some([4, 5, 6, 7]));
45-
assert_eq!(it.remainder(), &[]);
46-
assert_eq!(it.remainder_mut(), &[]);
47-
assert_eq!(it.next(), None);
4834
assert_eq!(it.next(), None);
49-
assert_eq!(it.remainder(), &[8, 9, 10]);
50-
assert_eq!(it.remainder_mut(), &[8, 9, 10]);
35+
assert_eq!(it.into_remainder().unwrap().as_slice(), &[8, 9, 10]);
5136
}
5237

5338
#[test]
@@ -105,8 +90,7 @@ fn test_iterator_array_chunks_next_and_next_back() {
10590
assert_eq!(it.next(), None);
10691
assert_eq!(it.next_back(), None);
10792
assert_eq!(it.next(), None);
108-
assert_eq!(it.remainder(), &[9, 10]);
109-
assert_eq!(it.remainder_mut(), &[9, 10]);
93+
assert_eq!(it.into_remainder().unwrap().as_slice(), &[9, 10]);
11094
}
11195

11296
#[test]
@@ -119,7 +103,7 @@ fn test_iterator_array_chunks_rev_remainder() {
119103
assert_eq!(it.next(), None);
120104
assert_eq!(it.next(), None);
121105
}
122-
assert_eq!(it.remainder(), &[8, 9, 10]);
106+
assert_eq!(it.into_remainder().unwrap().as_slice(), &[8, 9, 10]);
123107
}
124108

125109
#[test]
@@ -128,7 +112,6 @@ fn test_iterator_array_chunks_try_fold() {
128112
let mut it = (0..10).map(|_| CountDrop::new(&count)).array_chunks::<3>();
129113
let result: Result<_, ()> = it.by_ref().try_fold(0, |acc, _item| Ok(acc + 1));
130114
assert_eq!(result, Ok(3));
131-
assert_eq!(it.remainder().len(), 1);
132115
assert_eq!(count.get(), 9);
133116
drop(it);
134117
assert_eq!(count.get(), 10);
@@ -137,7 +120,6 @@ fn test_iterator_array_chunks_try_fold() {
137120
let mut it = (0..10).map(|_| CountDrop::new(&count)).array_chunks::<3>();
138121
let result = it.by_ref().try_fold(0, |acc, _item| if acc < 2 { Ok(acc + 1) } else { Err(acc) });
139122
assert_eq!(result, Err(2));
140-
assert_eq!(it.remainder().len(), 0);
141123
assert_eq!(count.get(), 9);
142124
drop(it);
143125
assert_eq!(count.get(), 9);
@@ -166,7 +148,6 @@ fn test_iterator_array_chunks_try_rfold() {
166148
let mut it = (0..10).map(|_| CountDrop::new(&count)).array_chunks::<3>();
167149
let result: Result<_, ()> = it.try_rfold(0, |acc, _item| Ok(acc + 1));
168150
assert_eq!(result, Ok(3));
169-
assert_eq!(it.remainder().len(), 1);
170151
assert_eq!(count.get(), 9);
171152
drop(it);
172153
assert_eq!(count.get(), 10);

0 commit comments

Comments
 (0)