Skip to content

Commit a456a55

Browse files
committed
Optimize VecDeque::append
Signed-off-by: tabokie <[email protected]>
1 parent c4f26b1 commit a456a55

File tree

1 file changed

+28
-2
lines changed
  • library/alloc/src/collections/vec_deque

1 file changed

+28
-2
lines changed

library/alloc/src/collections/vec_deque/mod.rs

+28-2
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,26 @@ impl<T, A: Allocator> VecDeque<T, A> {
417417
}
418418
}
419419

420+
/// Append all values from `src` to `self`, wrapping around if needed.
421+
/// Assumes capacity is sufficient.
422+
#[inline]
423+
unsafe fn append_slice(&mut self, src: &[T]) {
424+
debug_assert!(self.len() + src.len() + 1 <= self.cap());
425+
let head_room = self.cap() - self.head;
426+
if self.head < self.tail || src.len() <= head_room {
427+
unsafe {
428+
ptr::copy_nonoverlapping(src.as_ptr(), self.ptr().add(self.head), src.len());
429+
}
430+
} else {
431+
let (left, right) = src.split_at(head_room);
432+
unsafe {
433+
ptr::copy_nonoverlapping(left.as_ptr(), self.ptr().add(self.head), left.len());
434+
ptr::copy_nonoverlapping(right.as_ptr(), self.ptr(), right.len());
435+
}
436+
}
437+
self.head = self.wrap_add(self.head, src.len());
438+
}
439+
420440
/// Frobs the head and tail sections around to handle the fact that we
421441
/// just reallocated. Unsafe because it trusts old_capacity.
422442
#[inline]
@@ -2088,8 +2108,14 @@ impl<T, A: Allocator> VecDeque<T, A> {
20882108
#[inline]
20892109
#[stable(feature = "append", since = "1.4.0")]
20902110
pub fn append(&mut self, other: &mut Self) {
2091-
// naive impl
2092-
self.extend(other.drain(..));
2111+
self.reserve(other.len());
2112+
unsafe {
2113+
let (left, right) = other.as_slices();
2114+
self.append_slice(left);
2115+
self.append_slice(right);
2116+
}
2117+
// Silently drop values in `other`.
2118+
other.tail = other.head;
20932119
}
20942120

20952121
/// Retains only the elements specified by the predicate.

0 commit comments

Comments
 (0)