From 90112530ffb5fe26796a84c1bccb6d2ce9c268f6 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 3 Apr 2014 22:28:45 +1100 Subject: [PATCH] std: override clone_from for Vec. A vector can reuse its allocation (and the allocations/resources of any contained values) when cloning into an already-instantiated vector, so we might as well do so. --- src/libstd/lib.rs | 1 + src/libstd/vec.rs | 56 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fb6c1b4c8a3a8..7971c332b273d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -232,4 +232,5 @@ mod std { pub use to_str; pub use ty; pub use unstable; + pub use vec; } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 69c3a85b2f160..e414ff25d4335 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -310,11 +310,24 @@ impl Vec { impl Clone for Vec { fn clone(&self) -> Vec { - let mut vector = Vec::with_capacity(self.len()); - for element in self.iter() { - vector.push((*element).clone()) + self.iter().map(|x| x.clone()).collect() + } + + fn clone_from(&mut self, other: &Vec) { + // drop anything in self that will not be overwritten + if self.len() > other.len() { + self.truncate(other.len()) } - vector + + // reuse the contained values' allocations/resources. + for (place, thing) in self.mut_iter().zip(other.iter()) { + place.clone_from(thing) + } + + // self.len <= other.len due to the truncate above, so the + // slice here is always in-bounds. + let len = self.len(); + self.extend(other.slice_from(len).iter().map(|x| x.clone())); } } @@ -1475,4 +1488,39 @@ mod tests { assert!(values == Vec::from_slice([2u8, 3, 5, 6, 7])); } + + #[test] + fn test_clone() { + let v: Vec = vec!(); + let w = vec!(1, 2, 3); + + assert_eq!(v, v.clone()); + + let z = w.clone(); + assert_eq!(w, z); + // they should be disjoint in memory. + assert!(w.as_ptr() != z.as_ptr()) + } + + #[test] + fn test_clone_from() { + let mut v = vec!(); + let three = vec!(~1, ~2, ~3); + let two = vec!(~4, ~5); + // zero, long + v.clone_from(&three); + assert_eq!(v, three); + + // equal + v.clone_from(&three); + assert_eq!(v, three); + + // long, short + v.clone_from(&two); + assert_eq!(v, two); + + // short, long + v.clone_from(&three); + assert_eq!(v, three) + } }