From 3e4b55807d9778c396ae449fe9a5680508d7d62d Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Wed, 29 Aug 2012 01:21:49 -0700 Subject: [PATCH] Add vec::truncate, for efficiently shortening a vector. --- src/libcore/vec.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) 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(&v: ~[const T], -rhs: ~[const T]) { } } +/// Shorten a vector, dropping excess elements. +fn truncate(&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(+lhs: ~[T], rhs: &[const T]) -> ~[T] { @@ -2166,6 +2181,15 @@ mod tests { assert (v[4] == 5); } + #[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.