about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2014-04-03 22:28:45 +1100
committerAlex Crichton <alex@alexcrichton.com>2014-04-03 13:42:32 -0700
commitf5a4837df0885368352d118e1e71f4853bf55bf8 (patch)
tree782fff3828b54a74c2ec885379414b350e951c8b /src/libstd
parent0bd6f2ce0b650ebcb1d2b05dc501a9ed4907b6d2 (diff)
downloadrust-f5a4837df0885368352d118e1e71f4853bf55bf8.tar.gz
rust-f5a4837df0885368352d118e1e71f4853bf55bf8.zip
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.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/vec.rs56
2 files changed, 53 insertions, 4 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index fb6c1b4c8a3..7971c332b27 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 69c3a85b2f1..e414ff25d43 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -310,11 +310,24 @@ impl<T: Clone> Vec<T> {
 
 impl<T:Clone> Clone for Vec<T> {
     fn clone(&self) -> Vec<T> {
-        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<T>) {
+        // 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<int> = 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)
+    }
 }