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.