]> git.lizzy.rs Git - rust.git/commitdiff
std: override clone_from for Vec.
authorHuon Wilson <dbau.pp+github@gmail.com>
Thu, 3 Apr 2014 11:28:45 +0000 (22:28 +1100)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 3 Apr 2014 20:42:32 +0000 (13:42 -0700)
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
src/libstd/vec.rs

index fb6c1b4c8a3a8776f990d93e21e8b8cc4157b5e2..7971c332b273dae5af2efc89a859fe76f03c9c6f 100644 (file)
@@ -232,4 +232,5 @@ mod std {
     pub use to_str;
     pub use ty;
     pub use unstable;
+    pub use vec;
 }
index 69c3a85b2f16057b3f03746ad7cf735b6a9433c3..e414ff25d433539eb419d3e556883f17d3e3c71e 100644 (file)
@@ -310,11 +310,24 @@ pub fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, 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 @@ fn test_mut_split_at() {
 
         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)
+    }
 }