about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/vec.rs24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index db564fc4a6f..33199576c11 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -42,6 +42,7 @@ export push, push_all, push_all_move;
 export grow;
 export grow_fn;
 export grow_set;
+export truncate;
 export map;
 export mapi;
 export map2;
@@ -611,6 +612,20 @@ fn push_all_move<T>(&v: ~[const T], -rhs: ~[const T]) {
     }
 }
 
+/// Shorten a vector, dropping excess elements.
+fn truncate<T>(&v: ~[const T], newlen: uint) {
+    do as_buf(v) |p, oldlen| {
+        assert(newlen <= oldlen);
+        unsafe {
+            // This loop is optimized out for non-drop types.
+            for uint::range(newlen, oldlen) |i| {
+                let _dropped <- *ptr::offset(p, i);
+            }
+            unsafe::set_len(v, newlen);
+        }
+    }
+}
+
 // Appending
 #[inline(always)]
 pure fn append<T: copy>(+lhs: ~[T], rhs: &[const T]) -> ~[T] {
@@ -2167,6 +2182,15 @@ mod tests {
     }
 
     #[test]
+    fn test_truncate() {
+        let mut v = ~[@6,@5,@4];
+        truncate(v, 1);
+        assert(v.len() == 1);
+        assert(*(v[0]) == 6);
+        // If the unsafe block didn't drop things properly, we blow up here.
+    }
+
+    #[test]
     fn test_map() {
         // Test on-stack map.
         let mut v = ~[1u, 2u, 3u];