Added more efficient implementation for ArrayVecDrain, changed a few internal members of the struct, tests passed

This commit is contained in:
mgostIH
2020-01-26 13:51:25 +01:00
parent 554903f05f
commit fbcc24e988
+15 -7
View File
@@ -235,8 +235,9 @@ impl<A: Array> ArrayVec<A> {
);
ArrayVecDrain {
parent: self,
target_start: start,
target_index: start,
target_count: end - start,
target_end: end,
}
}
@@ -718,18 +719,19 @@ impl<A: Array> ArrayVec<A> {
/// See [`ArrayVecDrain::drain`](ArrayVecDrain::<A>::drain)
pub struct ArrayVecDrain<'p, A: Array> {
parent: &'p mut ArrayVec<A>,
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<Self::Item> {
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;
}
}