diff options
| author | Daniel Micay <danielmicay@gmail.com> | 2013-11-08 23:10:09 -0500 |
|---|---|---|
| committer | Daniel Micay <danielmicay@gmail.com> | 2013-11-08 23:24:46 -0500 |
| commit | 421c63157053f72184f3548d0aa74dc1279c04f1 (patch) | |
| tree | 9e0840d8e7aded5a5f0c8b2e9e8f5f8c006d6340 | |
| parent | a594a999fbccf04710c9dfea3ef3d231c14e1bd1 (diff) | |
| download | rust-421c63157053f72184f3548d0aa74dc1279c04f1.tar.gz rust-421c63157053f72184f3548d0aa74dc1279c04f1.zip | |
add `clone_from` and `deep_clone_from`
Closes #10240
| -rw-r--r-- | src/libstd/clone.rs | 48 | ||||
| -rw-r--r-- | src/libstd/vec.rs | 24 |
2 files changed, 70 insertions, 2 deletions
diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs index 701be1b3dfa..92db250ecca 100644 --- a/src/libstd/clone.rs +++ b/src/libstd/clone.rs @@ -29,12 +29,27 @@ pub trait Clone { /// are copied to maintain uniqueness, while the contents of /// managed pointers are not copied. fn clone(&self) -> Self; + + /// Perform copy-assignment from `source`. + /// + /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality, + /// but can be overriden to reuse the resources of `a` to avoid unnecessary + /// allocations. + #[inline(always)] + fn clone_from(&mut self, source: &Self) { + *self = source.clone() + } } impl<T: Clone> Clone for ~T { - /// Return a deep copy of the owned box. + /// Return a copy of the owned box. #[inline] fn clone(&self) -> ~T { ~(**self).clone() } + + /// Perform copy-assignment from `source` by reusing the existing allocation. + fn clone_from(&mut self, source: &~T) { + **self = (**source).clone() + } } impl<T> Clone for @T { @@ -122,12 +137,27 @@ pub trait DeepClone { /// Return a deep copy of the value. Unlike `Clone`, the contents of shared pointer types /// *are* copied. fn deep_clone(&self) -> Self; + + /// Perform deep copy-assignment from `source`. + /// + /// `a.deep_clone_from(&b)` is equivalent to `a = b.deep_clone()` in + /// functionality, but can be overriden to reuse the resources of `a` to + /// avoid unnecessary allocations. + #[inline(always)] + fn deep_clone_from(&mut self, source: &Self) { + *self = source.deep_clone() + } } impl<T: DeepClone> DeepClone for ~T { /// Return a deep copy of the owned box. #[inline] fn deep_clone(&self) -> ~T { ~(**self).deep_clone() } + + /// Perform deep copy-assignment from `source` by reusing the existing allocation. + fn deep_clone_from(&mut self, source: &~T) { + **self = (**source).deep_clone() + } } // FIXME: #6525: should also be implemented for `T: Send + DeepClone` @@ -235,6 +265,22 @@ fn test_borrowed_clone() { } #[test] +fn test_clone_from() { + let a = ~5; + let mut b = ~10; + b.clone_from(&a); + assert_eq!(*b, 5); +} + +#[test] +fn test_deep_clone_from() { + let a = ~5; + let mut b = ~10; + b.deep_clone_from(&a); + assert_eq!(*b, 5); +} + +#[test] fn test_extern_fn_clone() { trait Empty {} impl Empty for int {} diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 194a72bad6f..055b0b92121 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -2029,7 +2029,7 @@ impl<'self, T:Clone> MutableCloneableVector<T> for &'self mut [T] { #[inline] fn copy_from(self, src: &[T]) -> uint { for (a, b) in self.mut_iter().zip(src.iter()) { - *a = b.clone(); + a.clone_from(b); } cmp::min(self.len(), src.len()) } @@ -2282,6 +2282,17 @@ impl<A: Clone> Clone for ~[A] { fn clone(&self) -> ~[A] { self.iter().map(|item| item.clone()).collect() } + + fn clone_from(&mut self, source: &~[A]) { + if self.len() < source.len() { + *self = source.clone() + } else { + self.truncate(source.len()); + for (x, y) in self.mut_iter().zip(source.iter()) { + x.clone_from(y); + } + } + } } impl<A: DeepClone> DeepClone for ~[A] { @@ -2289,6 +2300,17 @@ impl<A: DeepClone> DeepClone for ~[A] { fn deep_clone(&self) -> ~[A] { self.iter().map(|item| item.deep_clone()).collect() } + + fn deep_clone_from(&mut self, source: &~[A]) { + if self.len() < source.len() { + *self = source.deep_clone() + } else { + self.truncate(source.len()); + for (x, y) in self.mut_iter().zip(source.iter()) { + x.deep_clone_from(y); + } + } + } } // This works because every lifetime is a sub-lifetime of 'static |
