Skip to content

Commit 11e488b

Browse files
committed
Optimize VecDeque::append
1 parent 6ce76ac commit 11e488b

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

src/liballoc/collections/vec_deque.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,22 @@ impl<T> VecDeque<T> {
202202
len);
203203
}
204204

205+
/// Copies all values from `src` to `self`, wrapping around if needed.
206+
/// Assumes capacity is sufficient.
207+
#[inline]
208+
unsafe fn copy_slice(&mut self, src: &[T]) {
209+
let dst_high_ptr = self.ptr().add(self.head);
210+
let dst_high_len = self.cap() - self.head;
211+
212+
let split = cmp::min(src.len(), dst_high_len);
213+
let (src_high, src_low) = src.split_at(split);
214+
215+
ptr::copy_nonoverlapping(src_high.as_ptr(), dst_high_ptr, src_high.len());
216+
ptr::copy_nonoverlapping(src_low.as_ptr(), self.ptr(), src_low.len());
217+
218+
self.head = self.wrap_add(self.head, src.len());
219+
}
220+
205221
/// Copies a potentially wrapping block of memory len long from src to dest.
206222
/// (abs(dst - src) + len) must be no larger than cap() (There must be at
207223
/// most one continuous overlapping region between src and dest).
@@ -1834,8 +1850,17 @@ impl<T> VecDeque<T> {
18341850
#[inline]
18351851
#[stable(feature = "append", since = "1.4.0")]
18361852
pub fn append(&mut self, other: &mut Self) {
1837-
// naive impl
1838-
self.extend(other.drain(..));
1853+
// Guarantees there is space in `self` for `other
1854+
self.reserve(other.len());
1855+
1856+
unsafe {
1857+
let (src_high, src_low) = other.as_slices();
1858+
self.copy_slice(src_low);
1859+
self.copy_slice(src_high);
1860+
}
1861+
1862+
// Some values now exist in both `other` and `self` but are made inaccessible in `other`.
1863+
other.tail = other.head;
18391864
}
18401865

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

0 commit comments

Comments
 (0)