Skip to content

Commit 4dc0b8a

Browse files
authored
Rollup merge of rust-lang#65069 - crgl:clone-from-vec-deque, r=bluss
Implement Clone::clone_from for VecDeque See rust-lang#28481. For simple data types with the target much longer than the source, this implementation can be significantly slower than the default (probably due to the use of truncate). However, it should be substantially faster when cloning from nested data structures with similar shapes or when cloning from VecDeques with similar lengths, hopefully more common use cases for clone_from.
2 parents d0f8bd6 + d21eeb1 commit 4dc0b8a

File tree

2 files changed

+122
-2
lines changed

2 files changed

+122
-2
lines changed

src/liballoc/collections/vec_deque.rs

+99-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
use core::array::LengthAtMost32;
1111
use core::cmp::{self, Ordering};
1212
use core::fmt;
13-
use core::iter::{repeat_with, FromIterator, FusedIterator};
14-
use core::mem;
13+
use core::iter::{once, repeat_with, FromIterator, FusedIterator};
14+
use core::mem::{self, replace};
1515
use core::ops::Bound::{Excluded, Included, Unbounded};
1616
use core::ops::{Index, IndexMut, RangeBounds, Try};
1717
use core::ptr::{self, NonNull};
@@ -57,11 +57,88 @@ pub struct VecDeque<T> {
5757
buf: RawVec<T>,
5858
}
5959

60+
/// PairSlices pairs up equal length slice parts of two deques
61+
///
62+
/// For example, given deques "A" and "B" with the following division into slices:
63+
///
64+
/// A: [0 1 2] [3 4 5]
65+
/// B: [a b] [c d e]
66+
///
67+
/// It produces the following sequence of matching slices:
68+
///
69+
/// ([0 1], [a b])
70+
/// ([2], [c])
71+
/// ([3 4], [d e])
72+
///
73+
/// and the uneven remainder of either A or B is skipped.
74+
struct PairSlices<'a, 'b, T> {
75+
a0: &'a mut [T],
76+
a1: &'a mut [T],
77+
b0: &'b [T],
78+
b1: &'b [T],
79+
}
80+
81+
impl<'a, 'b, T> PairSlices<'a, 'b, T> {
82+
fn from(to: &'a mut VecDeque<T>, from: &'b VecDeque<T>) -> Self {
83+
let (a0, a1) = to.as_mut_slices();
84+
let (b0, b1) = from.as_slices();
85+
PairSlices { a0, a1, b0, b1 }
86+
}
87+
88+
fn has_remainder(&self) -> bool {
89+
!self.b0.is_empty()
90+
}
91+
92+
fn remainder(self) -> impl Iterator<Item=&'b [T]> {
93+
once(self.b0).chain(once(self.b1))
94+
}
95+
}
96+
97+
impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T>
98+
{
99+
type Item = (&'a mut [T], &'b [T]);
100+
fn next(&mut self) -> Option<Self::Item> {
101+
// Get next part length
102+
let part = cmp::min(self.a0.len(), self.b0.len());
103+
if part == 0 {
104+
return None;
105+
}
106+
let (p0, p1) = replace(&mut self.a0, &mut []).split_at_mut(part);
107+
let (q0, q1) = self.b0.split_at(part);
108+
109+
// Move a1 into a0, if it's empty (and b1, b0 the same way).
110+
self.a0 = p1;
111+
self.b0 = q1;
112+
if self.a0.is_empty() {
113+
self.a0 = replace(&mut self.a1, &mut []);
114+
}
115+
if self.b0.is_empty() {
116+
self.b0 = replace(&mut self.b1, &[]);
117+
}
118+
Some((p0, q0))
119+
}
120+
}
121+
60122
#[stable(feature = "rust1", since = "1.0.0")]
61123
impl<T: Clone> Clone for VecDeque<T> {
62124
fn clone(&self) -> VecDeque<T> {
63125
self.iter().cloned().collect()
64126
}
127+
128+
fn clone_from(&mut self, other: &Self) {
129+
self.truncate(other.len());
130+
131+
let mut iter = PairSlices::from(self, other);
132+
while let Some((dst, src)) = iter.next() {
133+
dst.clone_from_slice(&src);
134+
}
135+
136+
if iter.has_remainder() {
137+
for remainder in iter.remainder() {
138+
self.extend(remainder.iter().cloned());
139+
}
140+
}
141+
}
65142
}
66143

67144
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2209,6 +2286,16 @@ impl<'a, T> Iterator for Iter<'a, T> {
22092286
final_res
22102287
}
22112288

2289+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
2290+
if n >= count(self.tail, self.head, self.ring.len()) {
2291+
self.tail = self.head;
2292+
None
2293+
} else {
2294+
self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len());
2295+
self.next()
2296+
}
2297+
}
2298+
22122299
#[inline]
22132300
fn last(mut self) -> Option<&'a T> {
22142301
self.next_back()
@@ -2327,6 +2414,16 @@ impl<'a, T> Iterator for IterMut<'a, T> {
23272414
back.iter_mut().fold(accum, &mut f)
23282415
}
23292416

2417+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
2418+
if n >= count(self.tail, self.head, self.ring.len()) {
2419+
self.tail = self.head;
2420+
None
2421+
} else {
2422+
self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len());
2423+
self.next()
2424+
}
2425+
}
2426+
23302427
#[inline]
23312428
fn last(mut self) -> Option<&'a mut T> {
23322429
self.next_back()

src/liballoc/collections/vec_deque/tests.rs

+23
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,29 @@ fn test_vec_from_vecdeque() {
361361
}
362362
}
363363

364+
#[test]
365+
fn test_clone_from() {
366+
let m = vec![1; 8];
367+
let n = vec![2; 12];
368+
for pfv in 0..8 {
369+
for pfu in 0..8 {
370+
for longer in 0..2 {
371+
let (vr, ur) = if longer == 0 { (&m, &n) } else { (&n, &m) };
372+
let mut v = VecDeque::from(vr.clone());
373+
for _ in 0..pfv {
374+
v.push_front(1);
375+
}
376+
let mut u = VecDeque::from(ur.clone());
377+
for _ in 0..pfu {
378+
u.push_front(2);
379+
}
380+
v.clone_from(&u);
381+
assert_eq!(&v, &u);
382+
}
383+
}
384+
}
385+
}
386+
364387
#[test]
365388
fn issue_53529() {
366389
use crate::boxed::Box;

0 commit comments

Comments
 (0)