From fbcc24e98839321f0da40b72d4ee14bf3fe0f4a6 Mon Sep 17 00:00:00 2001 From: mgostIH Date: Sun, 26 Jan 2020 13:51:25 +0100 Subject: [PATCH] Added more efficient implementation for ArrayVecDrain, changed a few internal members of the struct, tests passed --- src/arrayvec.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index 5c75b14..278b211 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -235,8 +235,9 @@ impl ArrayVec { ); ArrayVecDrain { parent: self, + target_start: start, target_index: start, - target_count: end - start, + target_end: end, } } @@ -718,18 +719,19 @@ impl ArrayVec { /// See [`ArrayVecDrain::drain`](ArrayVecDrain::::drain) pub struct ArrayVecDrain<'p, A: Array> { parent: &'p mut ArrayVec, + target_start: usize, target_index: usize, - target_count: usize, + target_end: usize, } -// GoodFirstIssue: this entire type is correct but slow. + // NIGHTLY: vec_drain_as_slice, https://github.com/rust-lang/rust/issues/58957 impl<'p, A: Array> Iterator for ArrayVecDrain<'p, A> { type Item = A::Item; #[inline] fn next(&mut self) -> Option { - if self.target_count > 0 { - let out = self.parent.remove(self.target_index); - self.target_count -= 1; + if self.target_index != self.target_end { + let out = take(&mut self.parent[self.target_index]); + self.target_index += 1; Some(out) } else { None @@ -739,7 +741,13 @@ impl<'p, A: Array> Iterator for ArrayVecDrain<'p, A> { impl<'p, A: Array> Drop for ArrayVecDrain<'p, A> { #[inline] fn drop(&mut self) { - for _ in self {} + // Changed because it was moving `self`, it's also more clear and the std does the same + self.for_each(drop); + // Implementation very similar to [`ArrayVec::remove`](ArrayVec::remove) + let count = self.target_end - self.target_start; + let targets: &mut [A::Item] = &mut self.parent.deref_mut()[self.target_start..]; + targets.rotate_left(count); + self.parent.len -= count; } }