-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve performance characteristics of Vector iterators to better match Vec iterators #104
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1881,8 +1881,21 @@ impl<'a, A: Clone> Iterator for Iter<'a, A> { | |||||
} | ||||||
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) { | ||||||
let remaining = self.back_index - self.front_index; | ||||||
(remaining, Some(remaining)) | ||||||
let len = self.len(); | ||||||
(len, Some(len)) | ||||||
} | ||||||
|
||||||
fn count(self) -> usize { | ||||||
self.len() | ||||||
} | ||||||
|
||||||
fn nth(&mut self, n: usize) -> Option<Self::Item> { | ||||||
if n >= self.len() { | ||||||
None | ||||||
} else { | ||||||
self.front_index += n; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if this overflows? |
||||||
self.next() | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -1899,9 +1912,22 @@ impl<'a, A: Clone> DoubleEndedIterator for Iter<'a, A> { | |||||
let focus: &'a mut Focus<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; | ||||||
focus.get(self.back_index) | ||||||
} | ||||||
|
||||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> { | ||||||
if n >= self.len() { | ||||||
None | ||||||
} else { | ||||||
self.back_index -= n; | ||||||
self.next_back() | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> ExactSizeIterator for Iter<'a, A> {} | ||||||
impl<'a, A: Clone> ExactSizeIterator for Iter<'a, A> { | ||||||
fn len(&self) -> usize { | ||||||
self.back_index - self.front_index | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if this underflows?
Suggested change
|
||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> FusedIterator for Iter<'a, A> {} | ||||||
|
||||||
|
@@ -1963,8 +1989,21 @@ where | |||||
} | ||||||
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) { | ||||||
let remaining = self.back_index - self.front_index; | ||||||
(remaining, Some(remaining)) | ||||||
let len = self.len(); | ||||||
(len, Some(len)) | ||||||
} | ||||||
|
||||||
fn count(self) -> usize { | ||||||
self.len() | ||||||
} | ||||||
|
||||||
fn nth(&mut self, n: usize) -> Option<Self::Item> { | ||||||
if n >= self.len() { | ||||||
None | ||||||
} else { | ||||||
self.front_index += n; | ||||||
self.next() | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -1984,9 +2023,22 @@ where | |||||
let focus: &'a mut FocusMut<'a, A> = unsafe { &mut *(&mut self.focus as *mut _) }; | ||||||
focus.get_mut(self.back_index) | ||||||
} | ||||||
|
||||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> { | ||||||
if n >= self.len() { | ||||||
None | ||||||
} else { | ||||||
self.back_index -= n; | ||||||
self.next_back() | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> ExactSizeIterator for IterMut<'a, A> {} | ||||||
impl<'a, A: Clone> ExactSizeIterator for IterMut<'a, A> { | ||||||
fn len(&self) -> usize { | ||||||
self.back_index - self.front_index | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> FusedIterator for IterMut<'a, A> {} | ||||||
|
||||||
|
@@ -2089,6 +2141,24 @@ impl<'a, A: Clone> Iterator for Chunks<'a, A> { | |||||
self.front_index = range.end; | ||||||
Some(value) | ||||||
} | ||||||
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) { | ||||||
let len = self.len(); | ||||||
(len, Some(len)) | ||||||
} | ||||||
|
||||||
fn count(self) -> usize { | ||||||
self.len() | ||||||
} | ||||||
|
||||||
fn nth(&mut self, n: usize) -> Option<Self::Item> { | ||||||
if n >= self.len() { | ||||||
None | ||||||
} else { | ||||||
self.front_index += n; | ||||||
self.next() | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> DoubleEndedIterator for Chunks<'a, A> { | ||||||
|
@@ -2106,6 +2176,21 @@ impl<'a, A: Clone> DoubleEndedIterator for Chunks<'a, A> { | |||||
self.back_index = range.start; | ||||||
Some(value) | ||||||
} | ||||||
|
||||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> { | ||||||
if n >= self.len() { | ||||||
None | ||||||
} else { | ||||||
self.back_index -= n; | ||||||
self.next_back() | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> ExactSizeIterator for Chunks<'a, A> { | ||||||
fn len(&self) -> usize { | ||||||
self.back_index - self.front_index | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> FusedIterator for Chunks<'a, A> {} | ||||||
|
@@ -2148,6 +2233,24 @@ impl<'a, A: Clone> Iterator for ChunksMut<'a, A> { | |||||
self.front_index = range.end; | ||||||
Some(value) | ||||||
} | ||||||
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) { | ||||||
let len = self.len(); | ||||||
(len, Some(len)) | ||||||
} | ||||||
|
||||||
fn count(self) -> usize { | ||||||
self.len() | ||||||
} | ||||||
|
||||||
fn nth(&mut self, n: usize) -> Option<Self::Item> { | ||||||
if n >= self.len() { | ||||||
None | ||||||
} else { | ||||||
self.front_index += n; | ||||||
self.next() | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> DoubleEndedIterator for ChunksMut<'a, A> { | ||||||
|
@@ -2165,6 +2268,21 @@ impl<'a, A: Clone> DoubleEndedIterator for ChunksMut<'a, A> { | |||||
self.back_index = range.start; | ||||||
Some(value) | ||||||
} | ||||||
|
||||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> { | ||||||
if n >= self.len() { | ||||||
None | ||||||
} else { | ||||||
self.back_index -= n; | ||||||
self.next_back() | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> ExactSizeIterator for ChunksMut<'a, A> { | ||||||
fn len(&self) -> usize { | ||||||
self.back_index - self.front_index | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
} | ||||||
|
||||||
impl<'a, A: Clone> FusedIterator for ChunksMut<'a, A> {} | ||||||
|
@@ -2635,6 +2753,31 @@ mod test { | |||||
assert_eq!(&vec[index], item); | ||||||
} | ||||||
assert_eq!(vec.len(), seq.len()); | ||||||
assert_eq!(vec.iter().count(), seq.iter().count()); | ||||||
} | ||||||
|
||||||
#[test] | ||||||
#[allow(clippy::iter_nth)] | ||||||
fn iter_nth(ref vec in vec(i32::ANY, 0..1000)) { | ||||||
let seq: Vector<i32> = Vector::from_iter(vec.iter().cloned()); | ||||||
assert_eq!(vec.iter().nth(0), seq.iter().nth(0)); | ||||||
assert_eq!(vec.iter().nth(1), seq.iter().nth(1)); | ||||||
let last_index = seq.len().checked_sub(1).unwrap_or(0); | ||||||
assert_eq!(vec.iter().nth(last_index), seq.iter().nth(last_index)); | ||||||
let last_index_plus_one = seq.len(); | ||||||
assert_eq!(vec.iter().nth(last_index_plus_one), seq.iter().nth(last_index_plus_one)); | ||||||
} | ||||||
|
||||||
#[test] | ||||||
#[allow(clippy::iter_nth)] | ||||||
fn iter_nth_back(ref vec in vec(i32::ANY, 0..1000)) { | ||||||
let seq: Vector<i32> = Vector::from_iter(vec.iter().cloned()); | ||||||
assert_eq!(vec.iter().nth_back(0), seq.iter().nth_back(0)); | ||||||
assert_eq!(vec.iter().nth_back(1), seq.iter().nth_back(1)); | ||||||
let last_index = seq.len().checked_sub(1).unwrap_or(0); | ||||||
assert_eq!(vec.iter().nth_back(last_index), seq.iter().nth_back(last_index)); | ||||||
let last_index_plus_one = seq.len(); | ||||||
assert_eq!(vec.iter().nth_back(last_index_plus_one), seq.iter().nth_back(last_index_plus_one)); | ||||||
} | ||||||
|
||||||
#[test] | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this shortcut is correct. It introduces a bug.
Before this change, this works:
Afterwards, it panics because the call to
next()
returnsSome(1)
.Since the implementation of
next()
already has a check for exhaustion, I would remove thisif
altogether and replace it with itselse
case.