Rollup merge of #92284 - the8472:simplify-advance-by, r=scottmcm
Change advance(_back)_by to return the remainder instead of the number of processed elements When advance_by can't advance the iterator by the number of requested elements it now returns the amount by which it couldn't be advanced instead of the amount by which it did. This simplifies adapters like chain, flatten or cycle because the remainder doesn't have to be calculated as the difference between requested steps and completed steps anymore. Additionally switching from `Result<(), usize>` to `Result<(), NonZeroUsize>` reduces the size of the result and makes converting from/to a usize representing the number of remaining steps cheap.
This commit is contained in:
commit
0883848882
32 changed files with 381 additions and 324 deletions
|
@ -1,4 +1,5 @@
|
|||
use core::iter::{FusedIterator, TrustedLen};
|
||||
use core::num::NonZeroUsize;
|
||||
use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr};
|
||||
|
||||
use crate::alloc::{Allocator, Global};
|
||||
|
@ -54,15 +55,16 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
if self.inner.len < n {
|
||||
let len = self.inner.len;
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let len = self.inner.len;
|
||||
let rem = if len < n {
|
||||
self.inner.clear();
|
||||
Err(len)
|
||||
n - len
|
||||
} else {
|
||||
self.inner.drain(..n);
|
||||
Ok(())
|
||||
}
|
||||
0
|
||||
};
|
||||
NonZeroUsize::new(rem).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -182,15 +184,16 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let len = self.inner.len;
|
||||
if len >= n {
|
||||
self.inner.truncate(len - n);
|
||||
Ok(())
|
||||
} else {
|
||||
let rem = if len < n {
|
||||
self.inner.clear();
|
||||
Err(len)
|
||||
}
|
||||
n - len
|
||||
} else {
|
||||
self.inner.truncate(len - n);
|
||||
0
|
||||
};
|
||||
NonZeroUsize::new(rem).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> R
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
|
||||
use core::num::NonZeroUsize;
|
||||
use core::ops::Try;
|
||||
use core::{fmt, mem, slice};
|
||||
|
||||
|
@ -55,13 +56,15 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let m = match self.i1.advance_by(n) {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(m) => m,
|
||||
};
|
||||
mem::swap(&mut self.i1, &mut self.i2);
|
||||
self.i1.advance_by(n - m).map_err(|o| o + m)
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let remaining = self.i1.advance_by(n);
|
||||
match remaining {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(n) => {
|
||||
mem::swap(&mut self.i1, &mut self.i2);
|
||||
self.i1.advance_by(n.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -125,14 +128,14 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let m = match self.i2.advance_back_by(n) {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(m) => m,
|
||||
};
|
||||
|
||||
mem::swap(&mut self.i1, &mut self.i2);
|
||||
self.i2.advance_back_by(n - m).map_err(|o| m + o)
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
match self.i2.advance_back_by(n) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(n) => {
|
||||
mem::swap(&mut self.i1, &mut self.i2);
|
||||
self.i2.advance_back_by(n.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
|
||||
use core::num::NonZeroUsize;
|
||||
use core::ops::Try;
|
||||
use core::{fmt, mem, slice};
|
||||
|
||||
|
@ -47,13 +48,14 @@ impl<'a, T> Iterator for IterMut<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let m = match self.i1.advance_by(n) {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(m) => m,
|
||||
};
|
||||
mem::swap(&mut self.i1, &mut self.i2);
|
||||
self.i1.advance_by(n - m).map_err(|o| o + m)
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
match self.i1.advance_by(n) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(remaining) => {
|
||||
mem::swap(&mut self.i1, &mut self.i2);
|
||||
self.i1.advance_by(remaining.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -117,14 +119,14 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let m = match self.i2.advance_back_by(n) {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(m) => m,
|
||||
};
|
||||
|
||||
mem::swap(&mut self.i1, &mut self.i2);
|
||||
self.i2.advance_back_by(n - m).map_err(|o| m + o)
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
match self.i2.advance_back_by(n) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(remaining) => {
|
||||
mem::swap(&mut self.i1, &mut self.i2);
|
||||
self.i2.advance_back_by(remaining.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rfold<Acc, F>(self, accum: Acc, mut f: F) -> Acc
|
||||
|
|
|
@ -11,6 +11,7 @@ use core::iter::{
|
|||
};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
|
||||
use core::num::NonZeroUsize;
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
use core::ops::Deref;
|
||||
use core::ptr::{self, NonNull};
|
||||
|
@ -213,7 +214,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let step_size = self.len().min(n);
|
||||
let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size);
|
||||
if T::IS_ZST {
|
||||
|
@ -227,10 +228,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
|
|||
unsafe {
|
||||
ptr::drop_in_place(to_drop);
|
||||
}
|
||||
if step_size < n {
|
||||
return Err(step_size);
|
||||
}
|
||||
Ok(())
|
||||
NonZeroUsize::new(n - step_size).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -313,7 +311,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let step_size = self.len().min(n);
|
||||
if T::IS_ZST {
|
||||
// SAFETY: same as for advance_by()
|
||||
|
@ -327,10 +325,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
|
|||
unsafe {
|
||||
ptr::drop_in_place(to_drop);
|
||||
}
|
||||
if step_size < n {
|
||||
return Err(step_size);
|
||||
}
|
||||
Ok(())
|
||||
NonZeroUsize::new(n - step_size).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use core::alloc::{Allocator, Layout};
|
||||
use core::assert_eq;
|
||||
use core::iter::IntoIterator;
|
||||
use core::num::NonZeroUsize;
|
||||
use core::ptr::NonNull;
|
||||
use std::alloc::System;
|
||||
use std::assert_matches::assert_matches;
|
||||
|
@ -1062,21 +1064,21 @@ fn test_into_iter_leak() {
|
|||
|
||||
#[test]
|
||||
fn test_into_iter_advance_by() {
|
||||
let mut i = [1, 2, 3, 4, 5].into_iter();
|
||||
i.advance_by(0).unwrap();
|
||||
i.advance_back_by(0).unwrap();
|
||||
let mut i = vec![1, 2, 3, 4, 5].into_iter();
|
||||
assert_eq!(i.advance_by(0), Ok(()));
|
||||
assert_eq!(i.advance_back_by(0), Ok(()));
|
||||
assert_eq!(i.as_slice(), [1, 2, 3, 4, 5]);
|
||||
|
||||
i.advance_by(1).unwrap();
|
||||
i.advance_back_by(1).unwrap();
|
||||
assert_eq!(i.advance_by(1), Ok(()));
|
||||
assert_eq!(i.advance_back_by(1), Ok(()));
|
||||
assert_eq!(i.as_slice(), [2, 3, 4]);
|
||||
|
||||
assert_eq!(i.advance_back_by(usize::MAX), Err(3));
|
||||
assert_eq!(i.advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 3).unwrap()));
|
||||
|
||||
assert_eq!(i.advance_by(usize::MAX), Err(0));
|
||||
assert_eq!(i.advance_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX).unwrap()));
|
||||
|
||||
i.advance_by(0).unwrap();
|
||||
i.advance_back_by(0).unwrap();
|
||||
assert_eq!(i.advance_by(0), Ok(()));
|
||||
assert_eq!(i.advance_back_by(0), Ok(()));
|
||||
|
||||
assert_eq!(i.len(), 0);
|
||||
}
|
||||
|
@ -1124,7 +1126,7 @@ fn test_into_iter_zst() {
|
|||
for _ in vec![C; 5].into_iter().rev() {}
|
||||
|
||||
let mut it = vec![C, C].into_iter();
|
||||
it.advance_by(1).unwrap();
|
||||
assert_eq!(it.advance_by(1), Ok(()));
|
||||
drop(it);
|
||||
|
||||
let mut it = vec![C, C].into_iter();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use core::num::NonZeroUsize;
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::collections::TryReserveErrorKind::*;
|
||||
use std::collections::{vec_deque::Drain, VecDeque};
|
||||
|
@ -426,6 +427,28 @@ fn test_into_iter() {
|
|||
assert_eq!(it.next(), Some(7));
|
||||
assert_eq!(it.size_hint(), (5, Some(5)));
|
||||
}
|
||||
|
||||
// advance_by
|
||||
{
|
||||
let mut d = VecDeque::new();
|
||||
for i in 0..=4 {
|
||||
d.push_back(i);
|
||||
}
|
||||
for i in 6..=8 {
|
||||
d.push_front(i);
|
||||
}
|
||||
|
||||
let mut it = d.into_iter();
|
||||
assert_eq!(it.advance_by(1), Ok(()));
|
||||
assert_eq!(it.next(), Some(7));
|
||||
assert_eq!(it.advance_back_by(1), Ok(()));
|
||||
assert_eq!(it.next_back(), Some(3));
|
||||
|
||||
let mut it = VecDeque::from(vec![1, 2, 3, 4, 5]).into_iter();
|
||||
assert_eq!(it.advance_by(10), Err(NonZeroUsize::new(5).unwrap()));
|
||||
let mut it = VecDeque::from(vec![1, 2, 3, 4, 5]).into_iter();
|
||||
assert_eq!(it.advance_back_by(10), Err(NonZeroUsize::new(5).unwrap()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Defines the `IntoIter` owned iterator for arrays.
|
||||
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::{
|
||||
fmt,
|
||||
iter::{self, ExactSizeIterator, FusedIterator, TrustedLen},
|
||||
|
@ -284,12 +285,11 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
|||
self.next_back()
|
||||
}
|
||||
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let original_len = self.len();
|
||||
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
// This also moves the start, which marks them as conceptually "dropped",
|
||||
// so if anything goes bad then our drop impl won't double-free them.
|
||||
let range_to_drop = self.alive.take_prefix(n);
|
||||
let remaining = n - range_to_drop.len();
|
||||
|
||||
// SAFETY: These elements are currently initialized, so it's fine to drop them.
|
||||
unsafe {
|
||||
|
@ -297,7 +297,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
|||
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
|
||||
}
|
||||
|
||||
if n > original_len { Err(original_len) } else { Ok(()) }
|
||||
NonZeroUsize::new(remaining).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,12 +334,11 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
|
|||
})
|
||||
}
|
||||
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let original_len = self.len();
|
||||
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
// This also moves the end, which marks them as conceptually "dropped",
|
||||
// so if anything goes bad then our drop impl won't double-free them.
|
||||
let range_to_drop = self.alive.take_suffix(n);
|
||||
let remaining = n - range_to_drop.len();
|
||||
|
||||
// SAFETY: These elements are currently initialized, so it's fine to drop them.
|
||||
unsafe {
|
||||
|
@ -347,7 +346,7 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
|
|||
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
|
||||
}
|
||||
|
||||
if n > original_len { Err(original_len) } else { Ok(()) }
|
||||
NonZeroUsize::new(remaining).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::{NeverShortCircuit, Try};
|
||||
|
||||
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
|
||||
|
@ -26,7 +27,7 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
I::advance_by(self.0, n)
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,7 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
I::advance_back_by(self.0, n)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that links two iterators together, in a chain.
|
||||
|
@ -95,38 +96,33 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let mut rem = n;
|
||||
|
||||
fn advance_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> {
|
||||
if let Some(ref mut a) = self.a {
|
||||
match a.advance_by(rem) {
|
||||
n = match a.advance_by(n) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(k) => rem -= k,
|
||||
}
|
||||
Err(k) => k.get(),
|
||||
};
|
||||
self.a = None;
|
||||
}
|
||||
|
||||
if let Some(ref mut b) = self.b {
|
||||
match b.advance_by(rem) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(k) => rem -= k,
|
||||
}
|
||||
return b.advance_by(n);
|
||||
// we don't fuse the second iterator
|
||||
}
|
||||
|
||||
if rem == 0 { Ok(()) } else { Err(n - rem) }
|
||||
NonZeroUsize::new(n).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
|
||||
if let Some(ref mut a) = self.a {
|
||||
match a.advance_by(n) {
|
||||
n = match a.advance_by(n) {
|
||||
Ok(()) => match a.next() {
|
||||
None => n = 0,
|
||||
None => 0,
|
||||
x => return x,
|
||||
},
|
||||
Err(k) => n -= k,
|
||||
}
|
||||
Err(k) => k.get(),
|
||||
};
|
||||
|
||||
self.a = None;
|
||||
}
|
||||
|
@ -186,38 +182,33 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let mut rem = n;
|
||||
|
||||
fn advance_back_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> {
|
||||
if let Some(ref mut b) = self.b {
|
||||
match b.advance_back_by(rem) {
|
||||
n = match b.advance_back_by(n) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(k) => rem -= k,
|
||||
}
|
||||
Err(k) => k.get(),
|
||||
};
|
||||
self.b = None;
|
||||
}
|
||||
|
||||
if let Some(ref mut a) = self.a {
|
||||
match a.advance_back_by(rem) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(k) => rem -= k,
|
||||
}
|
||||
return a.advance_back_by(n);
|
||||
// we don't fuse the second iterator
|
||||
}
|
||||
|
||||
if rem == 0 { Ok(()) } else { Err(n - rem) }
|
||||
NonZeroUsize::new(n).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
|
||||
if let Some(ref mut b) = self.b {
|
||||
match b.advance_back_by(n) {
|
||||
n = match b.advance_back_by(n) {
|
||||
Ok(()) => match b.next_back() {
|
||||
None => n = 0,
|
||||
None => 0,
|
||||
x => return x,
|
||||
},
|
||||
Err(k) => n -= k,
|
||||
}
|
||||
Err(k) => k.get(),
|
||||
};
|
||||
|
||||
self.b = None;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::iter::adapters::{
|
|||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::mem::SizedTypeProperties;
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::Try;
|
||||
use crate::{array, ptr};
|
||||
|
||||
|
@ -89,7 +90,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.it.advance_by(n)
|
||||
}
|
||||
|
||||
|
@ -130,7 +131,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.it.advance_back_by(n)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::num::NonZeroUsize;
|
||||
use crate::{iter::FusedIterator, ops::Try};
|
||||
|
||||
/// An iterator that repeats endlessly.
|
||||
|
@ -81,23 +82,22 @@ where
|
|||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let mut rem = n;
|
||||
match self.iter.advance_by(rem) {
|
||||
ret @ Ok(_) => return ret,
|
||||
Err(advanced) => rem -= advanced,
|
||||
}
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let mut n = match self.iter.advance_by(n) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(rem) => rem.get(),
|
||||
};
|
||||
|
||||
while rem > 0 {
|
||||
while n > 0 {
|
||||
self.iter = self.orig.clone();
|
||||
match self.iter.advance_by(rem) {
|
||||
ret @ Ok(_) => return ret,
|
||||
Err(0) => return Err(n - rem),
|
||||
Err(advanced) => rem -= advanced,
|
||||
}
|
||||
n = match self.iter.advance_by(n) {
|
||||
Ok(()) => return Ok(()),
|
||||
e @ Err(rem) if rem.get() == n => return e,
|
||||
Err(rem) => rem.get(),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
NonZeroUsize::new(n).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
// No `fold` override, because `fold` doesn't make much sense for `Cycle`,
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::iter::adapters::{
|
|||
zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
|
||||
};
|
||||
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that yields the current count and the element during iteration.
|
||||
|
@ -114,17 +115,14 @@ where
|
|||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
match self.iter.advance_by(n) {
|
||||
ret @ Ok(_) => {
|
||||
self.count += n;
|
||||
ret
|
||||
}
|
||||
ret @ Err(advanced) => {
|
||||
self.count += advanced;
|
||||
ret
|
||||
}
|
||||
}
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let remaining = self.iter.advance_by(n);
|
||||
let advanced = match remaining {
|
||||
Ok(()) => n,
|
||||
Err(rem) => n - rem.get(),
|
||||
};
|
||||
self.count += advanced;
|
||||
remaining
|
||||
}
|
||||
|
||||
#[rustc_inherit_overflow_checks]
|
||||
|
@ -208,7 +206,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
// we do not need to update the count since that only tallies the number of items
|
||||
// consumed from the front. consuming items from the back can never reduce that.
|
||||
self.iter.advance_back_by(n)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::fmt;
|
||||
use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen};
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator that maps each element to an iterator, and yields the elements
|
||||
|
@ -75,7 +76,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.inner.advance_by(n)
|
||||
}
|
||||
|
||||
|
@ -120,7 +121,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.inner.advance_back_by(n)
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +237,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.inner.advance_by(n)
|
||||
}
|
||||
|
||||
|
@ -281,7 +282,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.inner.advance_back_by(n)
|
||||
}
|
||||
}
|
||||
|
@ -552,18 +553,18 @@ where
|
|||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
|
||||
match iter.advance_by(n) {
|
||||
Ok(()) => ControlFlow::Break(()),
|
||||
Err(advanced) => ControlFlow::Continue(n - advanced),
|
||||
Err(remaining) => ControlFlow::Continue(remaining.get()),
|
||||
}
|
||||
}
|
||||
|
||||
match self.iter_try_fold(n, advance) {
|
||||
ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining),
|
||||
ControlFlow::Continue(remaining) => NonZeroUsize::new(remaining).map_or(Ok(()), Err),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
@ -642,18 +643,18 @@ where
|
|||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
|
||||
match iter.advance_back_by(n) {
|
||||
Ok(()) => ControlFlow::Break(()),
|
||||
Err(advanced) => ControlFlow::Continue(n - advanced),
|
||||
Err(remaining) => ControlFlow::Continue(remaining.get()),
|
||||
}
|
||||
}
|
||||
|
||||
match self.iter_try_rfold(n, advance) {
|
||||
ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining),
|
||||
ControlFlow::Continue(remaining) => NonZeroUsize::new(remaining).map_or(Ok(()), Err),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::Try;
|
||||
|
||||
/// A double-ended iterator with the direction inverted.
|
||||
|
@ -38,7 +39,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.iter.advance_back_by(n)
|
||||
}
|
||||
|
||||
|
@ -83,7 +84,7 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.iter.advance_by(n)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::intrinsics::unlikely;
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator that skips over `n` elements of `iter`.
|
||||
|
@ -128,34 +129,27 @@ where
|
|||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let mut rem = n;
|
||||
let step_one = self.n.saturating_add(rem);
|
||||
fn advance_by(&mut self, mut n: usize) -> Result<(), NonZeroUsize> {
|
||||
let skip_inner = self.n;
|
||||
let skip_and_advance = skip_inner.saturating_add(n);
|
||||
|
||||
match self.iter.advance_by(step_one) {
|
||||
Ok(_) => {
|
||||
rem -= step_one - self.n;
|
||||
self.n = 0;
|
||||
}
|
||||
Err(advanced) => {
|
||||
let advanced_without_skip = advanced.saturating_sub(self.n);
|
||||
self.n = self.n.saturating_sub(advanced);
|
||||
return if n == 0 { Ok(()) } else { Err(advanced_without_skip) };
|
||||
let remainder = match self.iter.advance_by(skip_and_advance) {
|
||||
Ok(()) => 0,
|
||||
Err(n) => n.get(),
|
||||
};
|
||||
let advanced_inner = skip_and_advance - remainder;
|
||||
n -= advanced_inner.saturating_sub(skip_inner);
|
||||
self.n = self.n.saturating_sub(advanced_inner);
|
||||
|
||||
// skip_and_advance may have saturated
|
||||
if unlikely(remainder == 0 && n > 0) {
|
||||
n = match self.iter.advance_by(n) {
|
||||
Ok(()) => 0,
|
||||
Err(n) => n.get(),
|
||||
}
|
||||
}
|
||||
|
||||
// step_one calculation may have saturated
|
||||
if unlikely(rem > 0) {
|
||||
return match self.iter.advance_by(rem) {
|
||||
ret @ Ok(_) => ret,
|
||||
Err(advanced) => {
|
||||
rem -= advanced;
|
||||
Err(n - rem)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
NonZeroUsize::new(n).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,13 +203,11 @@ where
|
|||
impl_fold_via_try_fold! { rfold -> try_rfold }
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let min = crate::cmp::min(self.len(), n);
|
||||
return match self.iter.advance_back_by(min) {
|
||||
ret @ Ok(_) if n <= min => ret,
|
||||
Ok(_) => Err(min),
|
||||
_ => panic!("ExactSizeIterator contract violation"),
|
||||
};
|
||||
let rem = self.iter.advance_back_by(min);
|
||||
assert!(rem.is_ok(), "ExactSizeIterator contract violation");
|
||||
NonZeroUsize::new(n - min).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::cmp;
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator that only iterates over the first `n` iterations of `iter`.
|
||||
|
@ -121,18 +122,15 @@ where
|
|||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let min = self.n.min(n);
|
||||
match self.iter.advance_by(min) {
|
||||
Ok(_) => {
|
||||
self.n -= min;
|
||||
if min < n { Err(min) } else { Ok(()) }
|
||||
}
|
||||
ret @ Err(advanced) => {
|
||||
self.n -= advanced;
|
||||
ret
|
||||
}
|
||||
}
|
||||
let rem = match self.iter.advance_by(min) {
|
||||
Ok(()) => 0,
|
||||
Err(rem) => rem.get(),
|
||||
};
|
||||
let advanced = min - rem;
|
||||
self.n -= advanced;
|
||||
NonZeroUsize::new(n - advanced).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +221,7 @@ where
|
|||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
// The amount by which the inner iterator needs to be shortened for it to be
|
||||
// at most as long as the take() amount.
|
||||
let trim_inner = self.iter.len().saturating_sub(self.n);
|
||||
|
@ -232,12 +230,14 @@ where
|
|||
// about having to advance more than usize::MAX here.
|
||||
let advance_by = trim_inner.saturating_add(n);
|
||||
|
||||
let advanced = match self.iter.advance_back_by(advance_by) {
|
||||
Ok(_) => advance_by - trim_inner,
|
||||
Err(advanced) => advanced - trim_inner,
|
||||
let remainder = match self.iter.advance_back_by(advance_by) {
|
||||
Ok(()) => 0,
|
||||
Err(rem) => rem.get(),
|
||||
};
|
||||
self.n -= advanced;
|
||||
return if advanced < n { Err(advanced) } else { Ok(()) };
|
||||
let advanced_by_inner = advance_by - remainder;
|
||||
let advanced_by = advanced_by_inner - trim_inner;
|
||||
self.n -= advanced_by;
|
||||
NonZeroUsize::new(n - advanced_by).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::convert::TryFrom;
|
||||
use crate::marker::Destruct;
|
||||
use crate::mem;
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::{self, Try};
|
||||
|
||||
use super::{
|
||||
|
@ -530,12 +531,12 @@ trait RangeIteratorImpl {
|
|||
// Iterator
|
||||
fn spec_next(&mut self) -> Option<Self::Item>;
|
||||
fn spec_nth(&mut self, n: usize) -> Option<Self::Item>;
|
||||
fn spec_advance_by(&mut self, n: usize) -> Result<(), usize>;
|
||||
fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize>;
|
||||
|
||||
// DoubleEndedIterator
|
||||
fn spec_next_back(&mut self) -> Option<Self::Item>;
|
||||
fn spec_nth_back(&mut self, n: usize) -> Option<Self::Item>;
|
||||
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>;
|
||||
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>;
|
||||
}
|
||||
|
||||
impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A> {
|
||||
|
@ -567,7 +568,7 @@ impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A>
|
|||
}
|
||||
|
||||
#[inline]
|
||||
default fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
default fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let available = if self.start <= self.end {
|
||||
Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX)
|
||||
} else {
|
||||
|
@ -579,7 +580,7 @@ impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A>
|
|||
self.start =
|
||||
Step::forward_checked(self.start.clone(), taken).expect("`Step` invariants not upheld");
|
||||
|
||||
if taken < n { Err(taken) } else { Ok(()) }
|
||||
NonZeroUsize::new(n - taken).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -608,7 +609,7 @@ impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A>
|
|||
}
|
||||
|
||||
#[inline]
|
||||
default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let available = if self.start <= self.end {
|
||||
Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX)
|
||||
} else {
|
||||
|
@ -620,7 +621,7 @@ impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A>
|
|||
self.end =
|
||||
Step::backward_checked(self.end.clone(), taken).expect("`Step` invariants not upheld");
|
||||
|
||||
if taken < n { Err(taken) } else { Ok(()) }
|
||||
NonZeroUsize::new(n - taken).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -651,7 +652,7 @@ impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::R
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let available = if self.start <= self.end {
|
||||
Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX)
|
||||
} else {
|
||||
|
@ -666,7 +667,7 @@ impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::R
|
|||
// Otherwise 0 is returned which always safe to use.
|
||||
self.start = unsafe { Step::forward_unchecked(self.start.clone(), taken) };
|
||||
|
||||
if taken < n { Err(taken) } else { Ok(()) }
|
||||
NonZeroUsize::new(n - taken).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -695,7 +696,7 @@ impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::R
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let available = if self.start <= self.end {
|
||||
Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX)
|
||||
} else {
|
||||
|
@ -707,7 +708,7 @@ impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::R
|
|||
// SAFETY: same as the spec_advance_by() implementation
|
||||
self.end = unsafe { Step::backward_unchecked(self.end.clone(), taken) };
|
||||
|
||||
if taken < n { Err(taken) } else { Ok(()) }
|
||||
NonZeroUsize::new(n - taken).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -757,7 +758,7 @@ impl<A: ~const Step + ~const Destruct> const Iterator for ops::Range<A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.spec_advance_by(n)
|
||||
}
|
||||
|
||||
|
@ -836,7 +837,7 @@ impl<A: ~const Step + ~const Destruct> const DoubleEndedIterator for ops::Range<
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.spec_advance_back_by(n)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::num::NonZeroUsize;
|
||||
|
||||
/// Creates a new iterator that endlessly repeats a single element.
|
||||
///
|
||||
|
@ -80,7 +81,7 @@ impl<A: Clone> Iterator for Repeat<A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
// Advancing an infinite iterator of a single element is a no-op.
|
||||
let _ = n;
|
||||
Ok(())
|
||||
|
@ -109,7 +110,7 @@ impl<A: Clone> DoubleEndedIterator for Repeat<A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
// Advancing an infinite iterator of a single element is a no-op.
|
||||
let _ = n;
|
||||
Ok(())
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::num::NonZeroUsize;
|
||||
|
||||
/// Creates a new iterator that repeats a single element a given number of times.
|
||||
///
|
||||
|
@ -137,7 +138,7 @@ impl<A: Clone> Iterator for RepeatN<A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, skip: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, skip: usize) -> Result<(), NonZeroUsize> {
|
||||
let len = self.count;
|
||||
|
||||
if skip >= len {
|
||||
|
@ -145,7 +146,8 @@ impl<A: Clone> Iterator for RepeatN<A> {
|
|||
}
|
||||
|
||||
if skip > len {
|
||||
Err(len)
|
||||
// SAFETY: we just checked that the difference is positive
|
||||
Err(unsafe { NonZeroUsize::new_unchecked(skip - len) })
|
||||
} else {
|
||||
self.count = len - skip;
|
||||
Ok(())
|
||||
|
@ -178,7 +180,7 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
self.advance_by(n)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::marker::Destruct;
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator able to yield elements from both ends.
|
||||
|
@ -100,10 +101,11 @@ pub trait DoubleEndedIterator: Iterator {
|
|||
/// eagerly skip `n` elements starting from the back by calling [`next_back`] up
|
||||
/// to `n` times until [`None`] is encountered.
|
||||
///
|
||||
/// `advance_back_by(n)` will return [`Ok(())`] if the iterator successfully advances by
|
||||
/// `n` elements, or [`Err(k)`] if [`None`] is encountered, where `k` is the number of
|
||||
/// elements the iterator is advanced by before running out of elements (i.e. the length
|
||||
/// of the iterator). Note that `k` is always less than `n`.
|
||||
/// `advance_back_by(n)` will return `Ok(())` if the iterator successfully advances by
|
||||
/// `n` elements, or a `Err(NonZeroUsize)` with value `k` if [`None`] is encountered, where `k`
|
||||
/// is remaining number of steps that could not be advanced because the iterator ran out.
|
||||
/// If `self` is empty and `n` is non-zero, then this returns `Err(n)`.
|
||||
/// Otherwise, `k` is always less than `n`.
|
||||
///
|
||||
/// Calling `advance_back_by(0)` can do meaningful work, for example [`Flatten`] can advance its
|
||||
/// outer iterator until it finds an inner iterator that is not empty, which then often
|
||||
|
@ -120,25 +122,29 @@ pub trait DoubleEndedIterator: Iterator {
|
|||
/// ```
|
||||
/// #![feature(iter_advance_by)]
|
||||
///
|
||||
/// use std::num::NonZeroUsize;
|
||||
/// let a = [3, 4, 5, 6];
|
||||
/// let mut iter = a.iter();
|
||||
///
|
||||
/// assert_eq!(iter.advance_back_by(2), Ok(()));
|
||||
/// assert_eq!(iter.next_back(), Some(&4));
|
||||
/// assert_eq!(iter.advance_back_by(0), Ok(()));
|
||||
/// assert_eq!(iter.advance_back_by(100), Err(1)); // only `&3` was skipped
|
||||
/// assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&3` was skipped
|
||||
/// ```
|
||||
///
|
||||
/// [`Ok(())`]: Ok
|
||||
/// [`Err(k)`]: Err
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize>
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize>
|
||||
where
|
||||
Self::Item: ~const Destruct,
|
||||
{
|
||||
for i in 0..n {
|
||||
self.next_back().ok_or(i)?;
|
||||
if self.next_back().is_none() {
|
||||
// SAFETY: `i` is always less than `n`.
|
||||
return Err(unsafe { NonZeroUsize::new_unchecked(n - i) });
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -188,7 +194,9 @@ pub trait DoubleEndedIterator: Iterator {
|
|||
#[stable(feature = "iter_nth_back", since = "1.37.0")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
self.advance_back_by(n).ok()?;
|
||||
if self.advance_back_by(n).is_err() {
|
||||
return None;
|
||||
}
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
|
@ -374,7 +382,7 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
|
|||
fn next_back(&mut self) -> Option<I::Item> {
|
||||
(**self).next_back()
|
||||
}
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
(**self).advance_back_by(n)
|
||||
}
|
||||
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::array;
|
||||
use crate::cmp::{self, Ordering};
|
||||
use crate::marker::Destruct;
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
|
||||
|
||||
use super::super::try_process;
|
||||
|
@ -308,10 +309,11 @@ pub trait Iterator {
|
|||
/// This method will eagerly skip `n` elements by calling [`next`] up to `n`
|
||||
/// times until [`None`] is encountered.
|
||||
///
|
||||
/// `advance_by(n)` will return [`Ok(())`][Ok] if the iterator successfully advances by
|
||||
/// `n` elements, or [`Err(k)`][Err] if [`None`] is encountered, where `k` is the number
|
||||
/// of elements the iterator is advanced by before running out of elements (i.e. the
|
||||
/// length of the iterator). Note that `k` is always less than `n`.
|
||||
/// `advance_by(n)` will return `Ok(())` if the iterator successfully advances by
|
||||
/// `n` elements, or a `Err(NonZeroUsize)` with value `k` if [`None`] is encountered,
|
||||
/// where `k` is remaining number of steps that could not be advanced because the iterator ran out.
|
||||
/// If `self` is empty and `n` is non-zero, then this returns `Err(n)`.
|
||||
/// Otherwise, `k` is always less than `n`.
|
||||
///
|
||||
/// Calling `advance_by(0)` can do meaningful work, for example [`Flatten`]
|
||||
/// can advance its outer iterator until it finds an inner iterator that is not empty, which
|
||||
|
@ -327,22 +329,26 @@ pub trait Iterator {
|
|||
/// ```
|
||||
/// #![feature(iter_advance_by)]
|
||||
///
|
||||
/// use std::num::NonZeroUsize;
|
||||
/// let a = [1, 2, 3, 4];
|
||||
/// let mut iter = a.iter();
|
||||
///
|
||||
/// assert_eq!(iter.advance_by(2), Ok(()));
|
||||
/// assert_eq!(iter.next(), Some(&3));
|
||||
/// assert_eq!(iter.advance_by(0), Ok(()));
|
||||
/// assert_eq!(iter.advance_by(100), Err(1)); // only `&4` was skipped
|
||||
/// assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&4` was skipped
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize>
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize>
|
||||
where
|
||||
Self::Item: ~const Destruct,
|
||||
{
|
||||
for i in 0..n {
|
||||
self.next().ok_or(i)?;
|
||||
if self.next().is_none() {
|
||||
// SAFETY: `i` is always less than `n`.
|
||||
return Err(unsafe { NonZeroUsize::new_unchecked(n - i) });
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -4013,7 +4019,7 @@ impl<I: Iterator + ?Sized> Iterator for &mut I {
|
|||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(**self).size_hint()
|
||||
}
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
(**self).advance_by(n)
|
||||
}
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::intrinsics::{assert_unsafe_precondition, unchecked_add, unchecked_sub};
|
||||
use crate::iter::{FusedIterator, TrustedLen};
|
||||
use crate::num::NonZeroUsize;
|
||||
|
||||
/// Like a `Range<usize>`, but with a safety invariant that `start <= end`.
|
||||
///
|
||||
|
@ -132,10 +133,9 @@ impl Iterator for IndexRange {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let original_len = self.len();
|
||||
self.take_prefix(n);
|
||||
if n > original_len { Err(original_len) } else { Ok(()) }
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let taken = self.take_prefix(n);
|
||||
NonZeroUsize::new(n - taken.len()).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,10 +151,9 @@ impl DoubleEndedIterator for IndexRange {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let original_len = self.len();
|
||||
self.take_suffix(n);
|
||||
if n > original_len { Err(original_len) } else { Ok(()) }
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let taken = self.take_suffix(n);
|
||||
NonZeroUsize::new(n - taken.len()).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -176,11 +176,11 @@ macro_rules! iterator {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let advance = cmp::min(len!(self), n);
|
||||
// SAFETY: By construction, `advance` does not exceed `self.len()`.
|
||||
unsafe { self.post_inc_start(advance) };
|
||||
if advance == n { Ok(()) } else { Err(advance) }
|
||||
NonZeroUsize::new(n - advance).map_or(Ok(()), Err)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -371,11 +371,11 @@ macro_rules! iterator {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
|
||||
let advance = cmp::min(len!(self), n);
|
||||
// SAFETY: By construction, `advance` does not exceed `self.len()`.
|
||||
unsafe { self.pre_dec_end(advance) };
|
||||
if advance == n { Ok(()) } else { Err(advance) }
|
||||
NonZeroUsize::new(n - advance).map_or(Ok(()), Err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use core::array;
|
||||
use core::{array, assert_eq};
|
||||
use core::convert::TryFrom;
|
||||
use core::num::NonZeroUsize;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
#[test]
|
||||
|
@ -557,7 +558,7 @@ fn array_intoiter_advance_by() {
|
|||
assert_eq!(counter.get(), 13);
|
||||
|
||||
let r = it.advance_by(123456);
|
||||
assert_eq!(r, Err(87));
|
||||
assert_eq!(r, Err(NonZeroUsize::new(123456 - 87).unwrap()));
|
||||
assert_eq!(it.len(), 0);
|
||||
assert_eq!(counter.get(), 100);
|
||||
|
||||
|
@ -567,7 +568,7 @@ fn array_intoiter_advance_by() {
|
|||
assert_eq!(counter.get(), 100);
|
||||
|
||||
let r = it.advance_by(10);
|
||||
assert_eq!(r, Err(0));
|
||||
assert_eq!(r, Err(NonZeroUsize::new(10).unwrap()));
|
||||
assert_eq!(it.len(), 0);
|
||||
assert_eq!(counter.get(), 100);
|
||||
}
|
||||
|
@ -610,7 +611,7 @@ fn array_intoiter_advance_back_by() {
|
|||
assert_eq!(counter.get(), 13);
|
||||
|
||||
let r = it.advance_back_by(123456);
|
||||
assert_eq!(r, Err(87));
|
||||
assert_eq!(r, Err(NonZeroUsize::new(123456 - 87).unwrap()));
|
||||
assert_eq!(it.len(), 0);
|
||||
assert_eq!(counter.get(), 100);
|
||||
|
||||
|
@ -620,7 +621,7 @@ fn array_intoiter_advance_back_by() {
|
|||
assert_eq!(counter.get(), 100);
|
||||
|
||||
let r = it.advance_back_by(10);
|
||||
assert_eq!(r, Err(0));
|
||||
assert_eq!(r, Err(NonZeroUsize::new(10).unwrap()));
|
||||
assert_eq!(it.len(), 0);
|
||||
assert_eq!(counter.get(), 100);
|
||||
}
|
||||
|
@ -679,8 +680,8 @@ fn array_into_iter_fold() {
|
|||
|
||||
let a = [1, 2, 3, 4, 5, 6];
|
||||
let mut it = a.into_iter();
|
||||
it.advance_by(1).unwrap();
|
||||
it.advance_back_by(2).unwrap();
|
||||
assert_eq!(it.advance_by(1), Ok(()));
|
||||
assert_eq!(it.advance_back_by(2), Ok(()));
|
||||
let s = it.fold(10, |a, b| 10 * a + b);
|
||||
assert_eq!(s, 10234);
|
||||
}
|
||||
|
@ -695,8 +696,8 @@ fn array_into_iter_rfold() {
|
|||
|
||||
let a = [1, 2, 3, 4, 5, 6];
|
||||
let mut it = a.into_iter();
|
||||
it.advance_by(1).unwrap();
|
||||
it.advance_back_by(2).unwrap();
|
||||
assert_eq!(it.advance_by(1), Ok(()));
|
||||
assert_eq!(it.advance_back_by(2), Ok(()));
|
||||
let s = it.rfold(10, |a, b| 10 * a + b);
|
||||
assert_eq!(s, 10432);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::*;
|
||||
use core::iter::*;
|
||||
use core::num::NonZeroUsize;
|
||||
|
||||
#[test]
|
||||
fn test_iterator_chain() {
|
||||
|
@ -31,28 +32,28 @@ fn test_iterator_chain_advance_by() {
|
|||
|
||||
for i in 0..xs.len() {
|
||||
let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
|
||||
iter.advance_by(i).unwrap();
|
||||
assert_eq!(iter.advance_by(i), Ok(()));
|
||||
assert_eq!(iter.next(), Some(&xs[i]));
|
||||
assert_eq!(iter.advance_by(100), Err(len - i - 1));
|
||||
iter.advance_by(0).unwrap();
|
||||
assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (len - i - 1)).unwrap()));
|
||||
assert_eq!(iter.advance_by(0), Ok(()));
|
||||
}
|
||||
|
||||
for i in 0..ys.len() {
|
||||
let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
|
||||
iter.advance_by(xs.len() + i).unwrap();
|
||||
assert_eq!(iter.advance_by(xs.len() + i), Ok(()));
|
||||
assert_eq!(iter.next(), Some(&ys[i]));
|
||||
assert_eq!(iter.advance_by(100), Err(ys.len() - i - 1));
|
||||
iter.advance_by(0).unwrap();
|
||||
assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (ys.len() - i - 1)).unwrap()));
|
||||
assert_eq!(iter.advance_by(0), Ok(()));
|
||||
}
|
||||
|
||||
let mut iter = xs.iter().chain(ys);
|
||||
iter.advance_by(len).unwrap();
|
||||
assert_eq!(iter.advance_by(len), Ok(()));
|
||||
assert_eq!(iter.next(), None);
|
||||
iter.advance_by(0).unwrap();
|
||||
assert_eq!(iter.advance_by(0), Ok(()));
|
||||
|
||||
let mut iter = xs.iter().chain(ys);
|
||||
assert_eq!(iter.advance_by(len + 1), Err(len));
|
||||
iter.advance_by(0).unwrap();
|
||||
assert_eq!(iter.advance_by(len + 1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
assert_eq!(iter.advance_by(0), Ok(()));
|
||||
}
|
||||
|
||||
test_chain(&[], &[]);
|
||||
|
@ -68,28 +69,28 @@ fn test_iterator_chain_advance_back_by() {
|
|||
|
||||
for i in 0..ys.len() {
|
||||
let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
|
||||
iter.advance_back_by(i).unwrap();
|
||||
assert_eq!(iter.advance_back_by(i), Ok(()));
|
||||
assert_eq!(iter.next_back(), Some(&ys[ys.len() - i - 1]));
|
||||
assert_eq!(iter.advance_back_by(100), Err(len - i - 1));
|
||||
iter.advance_back_by(0).unwrap();
|
||||
assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (len - i - 1)).unwrap()));
|
||||
assert_eq!(iter.advance_back_by(0), Ok(()));
|
||||
}
|
||||
|
||||
for i in 0..xs.len() {
|
||||
let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
|
||||
iter.advance_back_by(ys.len() + i).unwrap();
|
||||
assert_eq!(iter.advance_back_by(ys.len() + i), Ok(()));
|
||||
assert_eq!(iter.next_back(), Some(&xs[xs.len() - i - 1]));
|
||||
assert_eq!(iter.advance_back_by(100), Err(xs.len() - i - 1));
|
||||
iter.advance_back_by(0).unwrap();
|
||||
assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (xs.len() - i - 1)).unwrap()));
|
||||
assert_eq!(iter.advance_back_by(0), Ok(()));
|
||||
}
|
||||
|
||||
let mut iter = xs.iter().chain(ys);
|
||||
iter.advance_back_by(len).unwrap();
|
||||
assert_eq!(iter.advance_back_by(len), Ok(()));
|
||||
assert_eq!(iter.next_back(), None);
|
||||
iter.advance_back_by(0).unwrap();
|
||||
assert_eq!(iter.advance_back_by(0), Ok(()));
|
||||
|
||||
let mut iter = xs.iter().chain(ys);
|
||||
assert_eq!(iter.advance_back_by(len + 1), Err(len));
|
||||
iter.advance_back_by(0).unwrap();
|
||||
assert_eq!(iter.advance_back_by(len + 1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
assert_eq!(iter.advance_back_by(0), Ok(()));
|
||||
}
|
||||
|
||||
test_chain(&[], &[]);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::iter::*;
|
||||
use core::num::NonZeroUsize;
|
||||
|
||||
#[test]
|
||||
fn test_iterator_enumerate() {
|
||||
|
@ -55,6 +56,20 @@ fn test_iterator_enumerate_count() {
|
|||
assert_eq!(xs.iter().enumerate().count(), 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_enumerate_advance_by() {
|
||||
let xs = [0, 1, 2, 3, 4, 5];
|
||||
let mut it = xs.iter().enumerate();
|
||||
assert_eq!(it.advance_by(0), Ok(()));
|
||||
assert_eq!(it.next(), Some((0, &0)));
|
||||
assert_eq!(it.advance_by(1), Ok(()));
|
||||
assert_eq!(it.next(), Some((2, &2)));
|
||||
assert_eq!(it.advance_by(2), Ok(()));
|
||||
assert_eq!(it.next(), Some((5, &5)));
|
||||
assert_eq!(it.advance_by(1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
assert_eq!(it.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_enumerate_fold() {
|
||||
let xs = [0, 1, 2, 3, 4, 5];
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use core::assert_eq;
|
||||
use super::*;
|
||||
use core::iter::*;
|
||||
use core::num::NonZeroUsize;
|
||||
|
||||
#[test]
|
||||
fn test_iterator_flatten() {
|
||||
|
@ -61,19 +63,19 @@ fn test_flatten_try_folds() {
|
|||
fn test_flatten_advance_by() {
|
||||
let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten();
|
||||
|
||||
it.advance_by(5).unwrap();
|
||||
assert_eq!(it.advance_by(5), Ok(()));
|
||||
assert_eq!(it.next(), Some(5));
|
||||
it.advance_by(9).unwrap();
|
||||
assert_eq!(it.advance_by(9), Ok(()));
|
||||
assert_eq!(it.next(), Some(15));
|
||||
it.advance_back_by(4).unwrap();
|
||||
assert_eq!(it.advance_back_by(4), Ok(()));
|
||||
assert_eq!(it.next_back(), Some(35));
|
||||
it.advance_back_by(9).unwrap();
|
||||
assert_eq!(it.advance_back_by(9), Ok(()));
|
||||
assert_eq!(it.next_back(), Some(25));
|
||||
|
||||
assert_eq!(it.advance_by(usize::MAX), Err(9));
|
||||
assert_eq!(it.advance_back_by(usize::MAX), Err(0));
|
||||
it.advance_by(0).unwrap();
|
||||
it.advance_back_by(0).unwrap();
|
||||
assert_eq!(it.advance_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 9).unwrap()));
|
||||
assert_eq!(it.advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX).unwrap()));
|
||||
assert_eq!(it.advance_by(0), Ok(()));
|
||||
assert_eq!(it.advance_back_by(0), Ok(()));
|
||||
assert_eq!(it.size_hint(), (0, Some(0)));
|
||||
}
|
||||
|
||||
|
@ -174,19 +176,19 @@ fn test_flatten_count() {
|
|||
let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten();
|
||||
|
||||
assert_eq!(it.clone().count(), 40);
|
||||
it.advance_by(5).unwrap();
|
||||
assert_eq!(it.advance_by(5), Ok(()));
|
||||
assert_eq!(it.clone().count(), 35);
|
||||
it.advance_back_by(5).unwrap();
|
||||
assert_eq!(it.advance_back_by(5), Ok(()));
|
||||
assert_eq!(it.clone().count(), 30);
|
||||
it.advance_by(10).unwrap();
|
||||
assert_eq!(it.advance_by(10), Ok(()));
|
||||
assert_eq!(it.clone().count(), 20);
|
||||
it.advance_back_by(8).unwrap();
|
||||
assert_eq!(it.advance_back_by(8), Ok(()));
|
||||
assert_eq!(it.clone().count(), 12);
|
||||
it.advance_by(4).unwrap();
|
||||
assert_eq!(it.advance_by(4), Ok(()));
|
||||
assert_eq!(it.clone().count(), 8);
|
||||
it.advance_back_by(5).unwrap();
|
||||
assert_eq!(it.advance_back_by(5), Ok(()));
|
||||
assert_eq!(it.clone().count(), 3);
|
||||
it.advance_by(3).unwrap();
|
||||
assert_eq!(it.advance_by(3), Ok(()));
|
||||
assert_eq!(it.clone().count(), 0);
|
||||
}
|
||||
|
||||
|
@ -195,18 +197,18 @@ fn test_flatten_last() {
|
|||
let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten();
|
||||
|
||||
assert_eq!(it.clone().last(), Some(39));
|
||||
it.advance_by(5).unwrap(); // 5..40
|
||||
assert_eq!(it.advance_by(5), Ok(())); // 5..40
|
||||
assert_eq!(it.clone().last(), Some(39));
|
||||
it.advance_back_by(5).unwrap(); // 5..35
|
||||
assert_eq!(it.advance_back_by(5), Ok(())); // 5..35
|
||||
assert_eq!(it.clone().last(), Some(34));
|
||||
it.advance_by(10).unwrap(); // 15..35
|
||||
assert_eq!(it.advance_by(10), Ok(())); // 15..35
|
||||
assert_eq!(it.clone().last(), Some(34));
|
||||
it.advance_back_by(8).unwrap(); // 15..27
|
||||
assert_eq!(it.advance_back_by(8), Ok(())); // 15..27
|
||||
assert_eq!(it.clone().last(), Some(26));
|
||||
it.advance_by(4).unwrap(); // 19..27
|
||||
assert_eq!(it.advance_by(4), Ok(())); // 19..27
|
||||
assert_eq!(it.clone().last(), Some(26));
|
||||
it.advance_back_by(5).unwrap(); // 19..22
|
||||
assert_eq!(it.advance_back_by(5), Ok(())); // 19..22
|
||||
assert_eq!(it.clone().last(), Some(21));
|
||||
it.advance_by(3).unwrap(); // 22..22
|
||||
assert_eq!(it.advance_by(3), Ok(())); // 22..22
|
||||
assert_eq!(it.clone().last(), None);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::iter::*;
|
||||
use core::num::NonZeroUsize;
|
||||
|
||||
use super::Unfuse;
|
||||
|
||||
|
@ -74,11 +75,14 @@ fn test_iterator_skip_nth() {
|
|||
#[test]
|
||||
fn test_skip_advance_by() {
|
||||
assert_eq!((0..0).skip(10).advance_by(0), Ok(()));
|
||||
assert_eq!((0..0).skip(10).advance_by(1), Err(0));
|
||||
assert_eq!((0u128..(usize::MAX as u128) + 1).skip(usize::MAX).advance_by(usize::MAX), Err(1));
|
||||
assert_eq!((0u128..u128::MAX).skip(usize::MAX).advance_by(1), Ok(()));
|
||||
assert_eq!((0..0).skip(10).advance_by(1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
assert_eq!(
|
||||
(0u128..(usize::MAX as u128) + 1).skip(usize::MAX - 10).advance_by(usize::MAX - 5),
|
||||
Err(NonZeroUsize::new(usize::MAX - 16).unwrap())
|
||||
);
|
||||
assert_eq!((0u128..u128::MAX).skip(usize::MAX - 10).advance_by(20), Ok(()));
|
||||
|
||||
assert_eq!((0..2).skip(1).advance_back_by(10), Err(1));
|
||||
assert_eq!((0..2).skip(1).advance_back_by(10), Err(NonZeroUsize::new(9).unwrap()));
|
||||
assert_eq!((0..0).skip(1).advance_back_by(0), Ok(()));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::iter::*;
|
||||
use core::num::NonZeroUsize;
|
||||
|
||||
#[test]
|
||||
fn test_iterator_take() {
|
||||
|
@ -78,21 +79,21 @@ fn test_take_advance_by() {
|
|||
let mut take = (0..10).take(3);
|
||||
assert_eq!(take.advance_by(2), Ok(()));
|
||||
assert_eq!(take.next(), Some(2));
|
||||
assert_eq!(take.advance_by(1), Err(0));
|
||||
assert_eq!(take.advance_by(1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
|
||||
assert_eq!((0..0).take(10).advance_by(0), Ok(()));
|
||||
assert_eq!((0..0).take(10).advance_by(1), Err(0));
|
||||
assert_eq!((0..10).take(4).advance_by(5), Err(4));
|
||||
assert_eq!((0..0).take(10).advance_by(1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
assert_eq!((0..10).take(4).advance_by(5), Err(NonZeroUsize::new(1).unwrap()));
|
||||
|
||||
let mut take = (0..10).take(3);
|
||||
assert_eq!(take.advance_back_by(2), Ok(()));
|
||||
assert_eq!(take.next(), Some(0));
|
||||
assert_eq!(take.advance_back_by(1), Err(0));
|
||||
assert_eq!(take.advance_back_by(1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
|
||||
assert_eq!((0..2).take(1).advance_back_by(10), Err(1));
|
||||
assert_eq!((0..0).take(1).advance_back_by(1), Err(0));
|
||||
assert_eq!((0..2).take(1).advance_back_by(10), Err(NonZeroUsize::new(9).unwrap()));
|
||||
assert_eq!((0..0).take(1).advance_back_by(1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
assert_eq!((0..0).take(1).advance_back_by(0), Ok(()));
|
||||
assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(100));
|
||||
assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 100).unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use core::num::NonZeroUsize;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -287,25 +288,25 @@ fn test_range_step() {
|
|||
#[test]
|
||||
fn test_range_advance_by() {
|
||||
let mut r = 0..usize::MAX;
|
||||
r.advance_by(0).unwrap();
|
||||
r.advance_back_by(0).unwrap();
|
||||
assert_eq!(Ok(()), r.advance_by(0));
|
||||
assert_eq!(Ok(()), r.advance_back_by(0));
|
||||
|
||||
assert_eq!(r.len(), usize::MAX);
|
||||
|
||||
r.advance_by(1).unwrap();
|
||||
r.advance_back_by(1).unwrap();
|
||||
assert_eq!(Ok(()), r.advance_by(1));
|
||||
assert_eq!(Ok(()), r.advance_back_by(1));
|
||||
|
||||
assert_eq!((r.start, r.end), (1, usize::MAX - 1));
|
||||
|
||||
assert_eq!(r.advance_by(usize::MAX), Err(usize::MAX - 2));
|
||||
assert_eq!(Err(NonZeroUsize::new(2).unwrap()), r.advance_by(usize::MAX));
|
||||
|
||||
r.advance_by(0).unwrap();
|
||||
r.advance_back_by(0).unwrap();
|
||||
assert_eq!(Ok(()), r.advance_by(0));
|
||||
assert_eq!(Ok(()), r.advance_back_by(0));
|
||||
|
||||
let mut r = 0u128..u128::MAX;
|
||||
|
||||
r.advance_by(usize::MAX).unwrap();
|
||||
r.advance_back_by(usize::MAX).unwrap();
|
||||
assert_eq!(Ok(()), r.advance_by(usize::MAX));
|
||||
assert_eq!(Ok(()), r.advance_back_by(usize::MAX));
|
||||
|
||||
assert_eq!((r.start, r.end), (0u128 + usize::MAX as u128, u128::MAX - usize::MAX as u128));
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use core::num::NonZeroUsize;
|
||||
|
||||
/// A wrapper struct that implements `Eq` and `Ord` based on the wrapped
|
||||
/// integer modulo 3. Used to test that `Iterator::max` and `Iterator::min`
|
||||
/// return the correct element if some of them are equal.
|
||||
|
@ -150,11 +152,11 @@ fn test_iterator_advance_by() {
|
|||
let mut iter = v.iter();
|
||||
assert_eq!(iter.advance_by(i), Ok(()));
|
||||
assert_eq!(iter.next().unwrap(), &v[i]);
|
||||
assert_eq!(iter.advance_by(100), Err(v.len() - 1 - i));
|
||||
assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap()));
|
||||
}
|
||||
|
||||
assert_eq!(v.iter().advance_by(v.len()), Ok(()));
|
||||
assert_eq!(v.iter().advance_by(100), Err(v.len()));
|
||||
assert_eq!(v.iter().advance_by(100), Err(NonZeroUsize::new(100 - v.len()).unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -165,11 +167,11 @@ fn test_iterator_advance_back_by() {
|
|||
let mut iter = v.iter();
|
||||
assert_eq!(iter.advance_back_by(i), Ok(()));
|
||||
assert_eq!(iter.next_back().unwrap(), &v[v.len() - 1 - i]);
|
||||
assert_eq!(iter.advance_back_by(100), Err(v.len() - 1 - i));
|
||||
assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap()));
|
||||
}
|
||||
|
||||
assert_eq!(v.iter().advance_back_by(v.len()), Ok(()));
|
||||
assert_eq!(v.iter().advance_back_by(100), Err(v.len()));
|
||||
assert_eq!(v.iter().advance_back_by(100), Err(NonZeroUsize::new(100 - v.len()).unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -180,11 +182,11 @@ fn test_iterator_rev_advance_back_by() {
|
|||
let mut iter = v.iter().rev();
|
||||
assert_eq!(iter.advance_back_by(i), Ok(()));
|
||||
assert_eq!(iter.next_back().unwrap(), &v[i]);
|
||||
assert_eq!(iter.advance_back_by(100), Err(v.len() - 1 - i));
|
||||
assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap()));
|
||||
}
|
||||
|
||||
assert_eq!(v.iter().rev().advance_back_by(v.len()), Ok(()));
|
||||
assert_eq!(v.iter().rev().advance_back_by(100), Err(v.len()));
|
||||
assert_eq!(v.iter().rev().advance_back_by(100), Err(NonZeroUsize::new(100 - v.len()).unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -424,11 +426,11 @@ fn test_iterator_rev_advance_by() {
|
|||
let mut iter = v.iter().rev();
|
||||
assert_eq!(iter.advance_by(i), Ok(()));
|
||||
assert_eq!(iter.next().unwrap(), &v[v.len() - 1 - i]);
|
||||
assert_eq!(iter.advance_by(100), Err(v.len() - 1 - i));
|
||||
assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap()));
|
||||
}
|
||||
|
||||
assert_eq!(v.iter().rev().advance_by(v.len()), Ok(()));
|
||||
assert_eq!(v.iter().rev().advance_by(100), Err(v.len()));
|
||||
assert_eq!(v.iter().rev().advance_by(100), Err(NonZeroUsize::new(100 - v.len()).unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use core::cell::Cell;
|
||||
use core::cmp::Ordering;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::num::NonZeroUsize;
|
||||
use core::result::Result::{Err, Ok};
|
||||
use core::slice;
|
||||
|
||||
|
@ -142,20 +143,20 @@ fn test_iterator_advance_by() {
|
|||
|
||||
for i in 0..=v.len() {
|
||||
let mut iter = v.iter();
|
||||
iter.advance_by(i).unwrap();
|
||||
assert_eq!(iter.advance_by(i), Ok(()));
|
||||
assert_eq!(iter.as_slice(), &v[i..]);
|
||||
}
|
||||
|
||||
let mut iter = v.iter();
|
||||
assert_eq!(iter.advance_by(v.len() + 1), Err(v.len()));
|
||||
assert_eq!(iter.advance_by(v.len() + 1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
assert_eq!(iter.as_slice(), &[]);
|
||||
|
||||
let mut iter = v.iter();
|
||||
iter.advance_by(3).unwrap();
|
||||
assert_eq!(iter.advance_by(3), Ok(()));
|
||||
assert_eq!(iter.as_slice(), &v[3..]);
|
||||
iter.advance_by(2).unwrap();
|
||||
assert_eq!(iter.advance_by(2), Ok(()));
|
||||
assert_eq!(iter.as_slice(), &[]);
|
||||
iter.advance_by(0).unwrap();
|
||||
assert_eq!(iter.advance_by(0), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -164,20 +165,20 @@ fn test_iterator_advance_back_by() {
|
|||
|
||||
for i in 0..=v.len() {
|
||||
let mut iter = v.iter();
|
||||
iter.advance_back_by(i).unwrap();
|
||||
assert_eq!(iter.advance_back_by(i), Ok(()));
|
||||
assert_eq!(iter.as_slice(), &v[..v.len() - i]);
|
||||
}
|
||||
|
||||
let mut iter = v.iter();
|
||||
assert_eq!(iter.advance_back_by(v.len() + 1), Err(v.len()));
|
||||
assert_eq!(iter.advance_back_by(v.len() + 1), Err(NonZeroUsize::new(1).unwrap()));
|
||||
assert_eq!(iter.as_slice(), &[]);
|
||||
|
||||
let mut iter = v.iter();
|
||||
iter.advance_back_by(3).unwrap();
|
||||
assert_eq!(iter.advance_back_by(3), Ok(()));
|
||||
assert_eq!(iter.as_slice(), &v[..v.len() - 3]);
|
||||
iter.advance_back_by(2).unwrap();
|
||||
assert_eq!(iter.advance_back_by(2), Ok(()));
|
||||
assert_eq!(iter.as_slice(), &[]);
|
||||
iter.advance_back_by(0).unwrap();
|
||||
assert_eq!(iter.advance_back_by(0), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Reference in a new issue