Skip to content

Commit f547978

Browse files
committed
Implement clone_from for BTree collections
1 parent 293cdf7 commit f547978

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

src/liballoc/collections/btree/map.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,60 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
207207
clone_subtree(self.root.as_ref())
208208
}
209209
}
210+
211+
fn clone_from(&mut self, other: &Self) {
212+
BTreeClone::clone_from(self, other);
213+
}
214+
}
215+
216+
trait BTreeClone {
217+
fn clone_from(&mut self, other: &Self);
218+
}
219+
220+
impl<K: Clone, V: Clone> BTreeClone for BTreeMap<K, V> {
221+
default fn clone_from(&mut self, other: &Self) {
222+
*self = other.clone();
223+
}
224+
}
225+
226+
impl<K: Clone + Ord, V: Clone> BTreeClone for BTreeMap<K, V> {
227+
fn clone_from(&mut self, other: &Self) {
228+
// This truncates `self` to `other.len()` by calling `split_off` on
229+
// the first key after `other.len()` elements if it exists
230+
if let Some(key) = {
231+
if self.len() > other.len() {
232+
let diff = self.len() - other.len();
233+
if diff <= other.len() {
234+
self.iter().nth_back(diff - 1).map(|pair| (*pair.0).clone())
235+
} else {
236+
self.iter().nth(other.len()).map(|pair| (*pair.0).clone())
237+
}
238+
} else {
239+
None
240+
}
241+
} {
242+
self.split_off(&key);
243+
}
244+
let mut siter = self.range_mut(..);
245+
let mut oiter = other.iter();
246+
// After truncation, `self` is at most as long as `other` so this loop
247+
// replaces every key-value pair in `self`. Since `oiter` is in sorted
248+
// order and the structure of the `BTreeMap` stays the same,
249+
// the BTree invariants are maintained at the end of the loop
250+
while siter.front != siter.back {
251+
if let Some((ok, ov)) = oiter.next() {
252+
// This is safe because the `siter.front != siter.back` check
253+
// ensures that `siter` is nonempty
254+
let (sk, sv) = unsafe { siter.next_unchecked() };
255+
sk.clone_from(ok);
256+
sv.clone_from(ov);
257+
} else {
258+
break;
259+
}
260+
}
261+
// If `other` is longer than `self`, the remaining elements are inserted
262+
self.extend(oiter.map(|(k, v)| ((*k).clone(), (*v).clone())));
263+
}
210264
}
211265

212266
impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()>

src/liballoc/collections/btree/set.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,23 @@ use crate::collections::btree_map::{self, BTreeMap, Keys};
5656
/// println!("{}", book);
5757
/// }
5858
/// ```
59-
#[derive(Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
59+
#[derive(Hash, PartialEq, Eq, Ord, PartialOrd)]
6060
#[stable(feature = "rust1", since = "1.0.0")]
6161
pub struct BTreeSet<T> {
6262
map: BTreeMap<T, ()>,
6363
}
6464

65+
#[stable(feature = "rust1", since = "1.0.0")]
66+
impl<T: Clone> Clone for BTreeSet<T> {
67+
fn clone(&self) -> Self {
68+
BTreeSet { map: self.map.clone() }
69+
}
70+
71+
fn clone_from(&mut self, other: &Self) {
72+
self.map.clone_from(&other.map);
73+
}
74+
}
75+
6576
/// An iterator over the items of a `BTreeSet`.
6677
///
6778
/// This `struct` is created by the [`iter`] method on [`BTreeSet`].

0 commit comments

Comments
 (0)