-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Implement clone_from for BTreeMap and BTreeSet #66648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
293cdf7
f547978
8651aa0
3caa17b
60a7c94
81b6f8c
6c3e477
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -207,6 +207,60 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> { | |
clone_subtree(self.root.as_ref()) | ||
} | ||
} | ||
|
||
fn clone_from(&mut self, other: &Self) { | ||
BTreeClone::clone_from(self, other); | ||
} | ||
} | ||
|
||
trait BTreeClone { | ||
fn clone_from(&mut self, other: &Self); | ||
} | ||
|
||
impl<K: Clone, V: Clone> BTreeClone for BTreeMap<K, V> { | ||
default fn clone_from(&mut self, other: &Self) { | ||
Centril marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*self = other.clone(); | ||
} | ||
} | ||
|
||
impl<K: Clone + Ord, V: Clone> BTreeClone for BTreeMap<K, V> { | ||
fn clone_from(&mut self, other: &Self) { | ||
// This truncates `self` to `other.len()` by calling `split_off` on | ||
// the first key after `other.len()` elements if it exists | ||
let split_off_key = if self.len() > other.len() { | ||
let diff = self.len() - other.len(); | ||
if diff <= other.len() { | ||
self.iter().nth_back(diff - 1).map(|pair| (*pair.0).clone()) | ||
} else { | ||
self.iter().nth(other.len()).map(|pair| (*pair.0).clone()) | ||
} | ||
} else { | ||
None | ||
}; | ||
if let Some(key) = split_off_key { | ||
self.split_off(&key); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel that a lot of duplicate work being done here. We first find the nth key, the pass it to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that I can see, unfortunately! However, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My point is that you are traversing the tree twice: once in the |
||
} | ||
|
||
let mut siter = self.range_mut(..); | ||
let mut oiter = other.iter(); | ||
// After truncation, `self` is at most as long as `other` so this loop | ||
// replaces every key-value pair in `self`. Since `oiter` is in sorted | ||
// order and the structure of the `BTreeMap` stays the same, | ||
// the BTree invariants are maintained at the end of the loop | ||
while !siter.is_empty() { | ||
if let Some((ok, ov)) = oiter.next() { | ||
// SAFETY: This is safe because the `siter.front != siter.back` check | ||
// ensures that `siter` is nonempty | ||
let (sk, sv) = unsafe { siter.next_unchecked() }; | ||
Centril marked this conversation as resolved.
Show resolved
Hide resolved
|
||
sk.clone_from(ok); | ||
sv.clone_from(ov); | ||
} else { | ||
break; | ||
} | ||
} | ||
// If `other` is longer than `self`, the remaining elements are inserted | ||
self.extend(oiter.map(|(k, v)| ((*k).clone(), (*v).clone()))); | ||
} | ||
} | ||
|
||
impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()> | ||
|
@@ -1328,7 +1382,10 @@ impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> { | |
None | ||
} else { | ||
self.length -= 1; | ||
unsafe { Some(self.range.next_unchecked()) } | ||
unsafe { | ||
let (k, v) = self.range.next_unchecked(); | ||
Some((k, v)) // coerce k from `&mut K` to `&K` | ||
} | ||
} | ||
} | ||
|
||
|
@@ -1707,7 +1764,14 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { | |
type Item = (&'a K, &'a mut V); | ||
|
||
fn next(&mut self) -> Option<(&'a K, &'a mut V)> { | ||
if self.front == self.back { None } else { unsafe { Some(self.next_unchecked()) } } | ||
if self.is_empty() { | ||
None | ||
} else { | ||
unsafe { | ||
let (k, v) = self.next_unchecked(); | ||
Some((k, v)) // coerce k from `&mut K` to `&K` | ||
} | ||
} | ||
} | ||
|
||
fn last(mut self) -> Option<(&'a K, &'a mut V)> { | ||
|
@@ -1716,16 +1780,19 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { | |
} | ||
|
||
impl<'a, K, V> RangeMut<'a, K, V> { | ||
unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { | ||
fn is_empty(&self) -> bool { | ||
self.front == self.back | ||
} | ||
|
||
unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) { | ||
KodrAus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let handle = ptr::read(&self.front); | ||
|
||
let mut cur_handle = match handle.right_kv() { | ||
Ok(kv) => { | ||
self.front = ptr::read(&kv).right_edge(); | ||
// Doing the descend invalidates the references returned by `into_kv_mut`, | ||
// so we have to do this last. | ||
let (k, v) = kv.into_kv_mut(); | ||
return (k, v); // coerce k from `&mut K` to `&K` | ||
return kv.into_kv_mut(); | ||
} | ||
Err(last_edge) => { | ||
let next_level = last_edge.into_node().ascend().ok(); | ||
|
@@ -1739,8 +1806,7 @@ impl<'a, K, V> RangeMut<'a, K, V> { | |
self.front = first_leaf_edge(ptr::read(&kv).right_edge().descend()); | ||
// Doing the descend invalidates the references returned by `into_kv_mut`, | ||
// so we have to do this last. | ||
let (k, v) = kv.into_kv_mut(); | ||
return (k, v); // coerce k from `&mut K` to `&K` | ||
return kv.into_kv_mut(); | ||
} | ||
Err(last_edge) => { | ||
let next_level = last_edge.into_node().ascend().ok(); | ||
|
@@ -1754,7 +1820,7 @@ impl<'a, K, V> RangeMut<'a, K, V> { | |
#[stable(feature = "btree_range", since = "1.17.0")] | ||
impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { | ||
fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { | ||
if self.front == self.back { None } else { unsafe { Some(self.next_back_unchecked()) } } | ||
if self.is_empty() { None } else { unsafe { Some(self.next_back_unchecked()) } } | ||
} | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.