From ae205a9c68c39578bb2b55e3ea13770fb79b9af0 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 23 Feb 2014 10:56:38 +1100 Subject: [PATCH 1/2] std: make .swap_remove return Option. This is one of the last raw "indexing" method on vectors that returns `T` instead of the Option. --- src/libgreen/stack.rs | 2 +- src/libstd/vec.rs | 50 ++++++++++++++++++++++++++----------------- src/libstd/vec_ng.rs | 10 ++++----- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/libgreen/stack.rs b/src/libgreen/stack.rs index 8a5e6be17c87d..053d73c010e39 100644 --- a/src/libgreen/stack.rs +++ b/src/libgreen/stack.rs @@ -139,7 +139,7 @@ impl StackPool { pub fn take_stack(&mut self, min_size: uint) -> Stack { // Ideally this would be a binary search match self.stacks.iter().position(|s| min_size <= s.min_size) { - Some(idx) => self.stacks.swap_remove(idx), + Some(idx) => self.stacks.swap_remove(idx).unwrap(), None => Stack::new(min_size) } } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 0adc6083f6b81..499891507ae90 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -1368,13 +1368,24 @@ pub trait OwnedVector { /// ``` fn remove(&mut self, i: uint) -> Option; - /** - * Remove an element from anywhere in the vector and return it, replacing it - * with the last element. This does not preserve ordering, but is O(1). - * - * Fails if index >= length. - */ - fn swap_remove(&mut self, index: uint) -> T; + /// Remove an element from anywhere in the vector and return it, replacing it + /// with the last element. This does not preserve ordering, but is O(1). + /// + /// Returns `None` if `index` is out of bounds. + /// + /// # Example + /// ```rust + /// let mut v = ~[~"foo", ~"bar", ~"baz", ~"qux"]; + /// + /// assert_eq!(v.swap_remove(1), Some(~"bar")); + /// assert_eq!(v, ~[~"foo", ~"qux", ~"baz"]); + /// + /// assert_eq!(v.swap_remove(0), Some(~"foo")); + /// assert_eq!(v, ~[~"baz", ~"qux"]); + /// + /// assert_eq!(v.swap_remove(2), None); + /// ``` + fn swap_remove(&mut self, index: uint) -> Option; /// Shorten a vector, dropping excess elements. fn truncate(&mut self, newlen: uint); @@ -1580,15 +1591,14 @@ impl OwnedVector for ~[T] { None } } - fn swap_remove(&mut self, index: uint) -> T { + fn swap_remove(&mut self, index: uint) -> Option { let ln = self.len(); - if index >= ln { - fail!("vec::swap_remove - index {} >= length {}", index, ln); - } if index < ln - 1 { self.swap(index, ln - 1); + } else if index >= ln { + return None } - self.pop().unwrap() + self.pop() } fn truncate(&mut self, newlen: uint) { let oldlen = self.len(); @@ -3194,15 +3204,15 @@ mod tests { fn test_swap_remove() { let mut v = ~[1, 2, 3, 4, 5]; let mut e = v.swap_remove(0); - assert_eq!(v.len(), 4); - assert_eq!(e, 1); - assert_eq!(v[0], 5); + assert_eq!(e, Some(1)); + assert_eq!(v, ~[5, 2, 3, 4]); e = v.swap_remove(3); - assert_eq!(v.len(), 3); - assert_eq!(e, 4); - assert_eq!(v[0], 5); - assert_eq!(v[1], 2); - assert_eq!(v[2], 3); + assert_eq!(e, Some(4)); + assert_eq!(v, ~[5, 2, 3]); + + e = v.swap_remove(3); + assert_eq!(e, None); + assert_eq!(v, ~[5, 2, 3]); } #[test] diff --git a/src/libstd/vec_ng.rs b/src/libstd/vec_ng.rs index 114f34963e2c7..adaa0a32527e8 100644 --- a/src/libstd/vec_ng.rs +++ b/src/libstd/vec_ng.rs @@ -277,15 +277,14 @@ impl Vec { } #[inline] - pub fn swap_remove(&mut self, index: uint) -> T { + pub fn swap_remove(&mut self, index: uint) -> Option { let length = self.len(); - if index >= length { - fail!("Vec::swap_remove - index {} >= length {}", index, length); - } if index < length - 1 { self.as_mut_slice().swap(index, length - 1); + } else if index >= length { + return None } - self.pop().unwrap() + self.pop() } #[inline] @@ -392,4 +391,3 @@ impl Drop for MoveItems { } } } - From 479d9e6b7692b39ccbe2782d0a3a231c9cb9fab6 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Sun, 23 Feb 2014 10:59:23 +1100 Subject: [PATCH 2/2] std: Add Vec.reserve for rounding-up reservation. `.reserve_exact` can cause pathological O(n^2) behaviour, so providing a `.reserve` that ensures that capacity doubles (if you step 1, 2, ..., n) is more efficient. cc #11949 --- src/libstd/vec_ng.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libstd/vec_ng.rs b/src/libstd/vec_ng.rs index adaa0a32527e8..0008f43673ee5 100644 --- a/src/libstd/vec_ng.rs +++ b/src/libstd/vec_ng.rs @@ -18,6 +18,7 @@ use container::Container; use iter::{DoubleEndedIterator, FromIterator, Iterator}; use libc::{free, c_void}; use mem::{size_of, move_val_init}; +use num; use num::CheckedMul; use ops::Drop; use option::{None, Option, Some}; @@ -136,6 +137,12 @@ impl Vec { self.cap } + pub fn reserve(&mut self, capacity: uint) { + if capacity >= self.len { + self.reserve_exact(num::next_power_of_two(capacity)) + } + } + pub fn reserve_exact(&mut self, capacity: uint) { if capacity >= self.len { let size = capacity.checked_mul(&size_of::()).expect("capacity overflow"); @@ -296,7 +303,7 @@ impl Vec { let len = self.len(); assert!(index <= len); // space for the new element - self.reserve_exact(len + 1); + self.reserve(len + 1); unsafe { // infallible // The spot to put the new value