2 use crate::iter
::{ByRefSized, FusedIterator, Iterator}
;
3 use crate::ops
::{ControlFlow, NeverShortCircuit, Try}
;
5 /// An iterator over `N` elements of the iterator at a time.
7 /// The chunks do not overlap. If `N` does not divide the length of the
8 /// iterator, then the last up to `N-1` elements will be omitted.
10 /// This `struct` is created by the [`array_chunks`][Iterator::array_chunks]
11 /// method on [`Iterator`]. See its documentation for more.
12 #[derive(Debug, Clone)]
13 #[must_use = "iterators are lazy and do nothing unless consumed"]
14 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
15 pub struct ArrayChunks
<I
: Iterator
, const N
: usize> {
17 remainder
: Option
<array
::IntoIter
<I
::Item
, N
>>,
20 impl<I
, const N
: usize> ArrayChunks
<I
, N
>
25 pub(in crate::iter
) fn new(iter
: I
) -> Self {
26 assert
!(N
!= 0, "chunk size must be non-zero");
27 Self { iter, remainder: None }
30 /// Returns an iterator over the remaining elements of the original iterator
31 /// that are not going to be returned by this iterator. The returned
32 /// iterator will yield at most `N-1` elements.
33 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
35 pub fn into_remainder(self) -> Option
<array
::IntoIter
<I
::Item
, N
>> {
40 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
41 impl<I
, const N
: usize> Iterator
for ArrayChunks
<I
, N
>
45 type Item
= [I
::Item
; N
];
48 fn next(&mut self) -> Option
<Self::Item
> {
49 self.try_for_each(ControlFlow
::Break
).break_value()
53 fn size_hint(&self) -> (usize, Option
<usize>) {
54 let (lower
, upper
) = self.iter
.size_hint();
56 (lower
/ N
, upper
.map(|n
| n
/ N
))
60 fn count(self) -> usize {
64 fn try_fold
<B
, F
, R
>(&mut self, init
: B
, mut f
: F
) -> R
67 F
: FnMut(B
, Self::Item
) -> R
,
72 match self.iter
.next_chunk() {
73 Ok(chunk
) => acc
= f(acc
, chunk
)?
,
75 // Make sure to not override `self.remainder` with an empty array
76 // when `next` is called after `ArrayChunks` exhaustion.
77 self.remainder
.get_or_insert(remainder
);
85 fn fold
<B
, F
>(mut self, init
: B
, f
: F
) -> B
88 F
: FnMut(B
, Self::Item
) -> B
,
90 self.try_fold(init
, NeverShortCircuit
::wrap_mut_2(f
)).0
94 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
95 impl<I
, const N
: usize> DoubleEndedIterator
for ArrayChunks
<I
, N
>
97 I
: DoubleEndedIterator
+ ExactSizeIterator
,
100 fn next_back(&mut self) -> Option
<Self::Item
> {
101 self.try_rfold((), |(), x
| ControlFlow
::Break(x
)).break_value()
104 fn try_rfold
<B
, F
, R
>(&mut self, init
: B
, mut f
: F
) -> R
107 F
: FnMut(B
, Self::Item
) -> R
,
110 // We are iterating from the back we need to first handle the remainder.
111 self.next_back_remainder();
114 let mut iter
= ByRefSized(&mut self.iter
).rev();
116 // NB remainder is handled by `next_back_remainder`, so
117 // `next_chunk` can't return `Err` with non-empty remainder
118 // (assuming correct `I as ExactSizeIterator` impl).
119 while let Ok(mut chunk
) = iter
.next_chunk() {
120 // FIXME: do not do double reverse
121 // (we could instead add `next_chunk_back` for example)
129 fn rfold
<B
, F
>(mut self, init
: B
, f
: F
) -> B
132 F
: FnMut(B
, Self::Item
) -> B
,
134 self.try_rfold(init
, NeverShortCircuit
::wrap_mut_2(f
)).0
138 impl<I
, const N
: usize> ArrayChunks
<I
, N
>
140 I
: DoubleEndedIterator
+ ExactSizeIterator
,
142 /// Updates `self.remainder` such that `self.iter.len` is divisible by `N`.
143 fn next_back_remainder(&mut self) {
144 // Make sure to not override `self.remainder` with an empty array
145 // when `next_back` is called after `ArrayChunks` exhaustion.
146 if self.remainder
.is_some() {
150 // We use the `ExactSizeIterator` implementation of the underlying
151 // iterator to know how many remaining elements there are.
152 let rem
= self.iter
.len() % N
;
154 // Take the last `rem` elements out of `self.iter`.
156 // SAFETY: `unwrap_err` always succeeds because x % N < N for all x.
157 unsafe { self.iter.by_ref().rev().take(rem).next_chunk().unwrap_err_unchecked() }
;
159 // We used `.rev()` above, so we need to re-reverse the reminder
160 remainder
.as_mut_slice().reverse();
161 self.remainder
= Some(remainder
);
165 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
166 impl<I
, const N
: usize> FusedIterator
for ArrayChunks
<I
, N
> where I
: FusedIterator {}
168 #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
169 impl<I
, const N
: usize> ExactSizeIterator
for ArrayChunks
<I
, N
>
171 I
: ExactSizeIterator
,
174 fn len(&self) -> usize {
179 fn is_empty(&self) -> bool
{