implement advance_(back_)_by on more iterators
This commit is contained in:
@@ -521,10 +521,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>;
|
||||
|
||||
// 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>;
|
||||
}
|
||||
|
||||
impl<A: Step> RangeIteratorImpl for ops::Range<A> {
|
||||
@@ -555,6 +557,22 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let available = if self.start <= self.end {
|
||||
Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let taken = available.min(n);
|
||||
|
||||
self.start =
|
||||
Step::forward_checked(self.start.clone(), taken).expect("`Step` invariants not upheld");
|
||||
|
||||
if taken < n { Err(taken) } else { Ok(()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn spec_next_back(&mut self) -> Option<A> {
|
||||
if self.start < self.end {
|
||||
@@ -579,6 +597,22 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
|
||||
self.end = self.start.clone();
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let available = if self.start <= self.end {
|
||||
Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let taken = available.min(n);
|
||||
|
||||
self.end =
|
||||
Step::backward_checked(self.end.clone(), taken).expect("`Step` invariants not upheld");
|
||||
|
||||
if taken < n { Err(taken) } else { Ok(()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
|
||||
@@ -607,6 +641,25 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn spec_advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let available = if self.start <= self.end {
|
||||
Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let taken = available.min(n);
|
||||
|
||||
// SAFETY: the conditions above ensure that the count is in bounds. If start <= end
|
||||
// then steps_between either returns a bound to which we clamp or returns None which
|
||||
// together with the initial inequality implies more than usize::MAX steps.
|
||||
// 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(()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn spec_next_back(&mut self) -> Option<T> {
|
||||
if self.start < self.end {
|
||||
@@ -631,6 +684,22 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
|
||||
self.end = self.start.clone();
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let available = if self.start <= self.end {
|
||||
Step::steps_between(&self.start, &self.end).unwrap_or(usize::MAX)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let taken = available.min(n);
|
||||
|
||||
// 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(()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@@ -677,6 +746,11 @@ impl<A: Step> Iterator for ops::Range<A> {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
self.spec_advance_by(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
|
||||
@@ -750,6 +824,11 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
|
||||
fn nth_back(&mut self, n: usize) -> Option<A> {
|
||||
self.spec_nth_back(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
self.spec_advance_back_by(n)
|
||||
}
|
||||
}
|
||||
|
||||
// Safety:
|
||||
|
||||
Reference in New Issue
Block a user