]> git.lizzy.rs Git - rust.git/commitdiff
vec: Add .pop_opt() -> Option<T>
authorblake2-ppc <blake2-ppc>
Fri, 5 Jul 2013 18:32:25 +0000 (20:32 +0200)
committerblake2-ppc <blake2-ppc>
Fri, 5 Jul 2013 18:32:25 +0000 (20:32 +0200)
Add a function to safely retrieve the last element of a ~[T], as
Option<T>. Implement pop() using pop_opt(); it benches the same as the
old implementation when tested with optimization level 2.

src/libstd/vec.rs

index 1014ff48b1d2386c26723b9727d831ee9835f72a..7ae4e8a1d2fb3b847886bb40f7e39f8cc3428226 100644 (file)
@@ -1091,6 +1091,7 @@ pub trait OwnedVector<T> {
 
     fn push_all_move(&mut self, rhs: ~[T]);
     fn pop(&mut self) -> T;
+    fn pop_opt(&mut self) -> Option<T>;
     fn shift(&mut self) -> T;
     fn unshift(&mut self, x: T);
     fn insert(&mut self, i: uint, x:T);
@@ -1281,20 +1282,28 @@ fn push_all_move(&mut self, mut rhs: ~[T]) {
         }
     }
 
-    /// Remove the last element from a vector and return it
-    fn pop(&mut self) -> T {
-        let ln = self.len();
-        if ln == 0 {
-            fail!("sorry, cannot pop an empty vector")
-        }
-        let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]);
-        unsafe {
-            let val = ptr::replace_ptr(valptr, intrinsics::init());
-            raw::set_len(self, ln - 1u);
-            val
+    /// Remove the last element from a vector and return it, or `None` if it is empty
+    fn pop_opt(&mut self) -> Option<T> {
+        match self.len() {
+            0  => None,
+            ln => {
+                let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]);
+                unsafe {
+                    let val = ptr::replace_ptr(valptr, intrinsics::init());
+                    raw::set_len(self, ln - 1u);
+                    Some(val)
+                }
+            }
         }
     }
 
+
+    /// Remove the last element from a vector and return it, failing if it is empty
+    #[inline]
+    fn pop(&mut self) -> T {
+        self.pop_opt().expect("pop: empty vector")
+    }
+
     /// Removes the first element from a vector and return it
     fn shift(&mut self) -> T {
         unsafe {
@@ -2089,18 +2098,13 @@ fn next(&mut self) -> Option<T> {
         //
         // [1,2,3,4,5] => 1, [5,2,3,4] => 2, [5,4,3] => 3, [5,4] => 4,
         // [5] -> 5, []
-
-        if self.v.is_empty() {
-            None
-        } else {
-            let l = self.v.len();
-            if self.idx < l {
-                self.v.swap(self.idx, l - 1);
-                self.idx += 1;
-            }
-
-            Some(self.v.pop())
+        let l = self.v.len();
+        if self.idx < l {
+            self.v.swap(self.idx, l - 1);
+            self.idx += 1;
         }
+
+        self.v.pop_opt()
     }
 }
 
@@ -2111,8 +2115,7 @@ pub struct VecConsumeRevIterator<T> {
 
 impl<T> Iterator<T> for VecConsumeRevIterator<T> {
     fn next(&mut self) -> Option<T> {
-        if self.v.is_empty() { None }
-        else { Some(self.v.pop()) }
+        self.v.pop_opt()
     }
 }
 
@@ -2415,6 +2418,17 @@ fn test_pop() {
     }
 
     #[test]
+    fn test_pop_opt() {
+        let mut v = ~[5];
+        let e = v.pop_opt();
+        assert_eq!(v.len(), 0);
+        assert_eq!(e, Some(5));
+        let f = v.pop_opt();
+        assert_eq!(f, None);
+        let g = v.pop_opt();
+        assert_eq!(g, None);
+    }
+
     fn test_swap_remove() {
         let mut v = ~[1, 2, 3, 4, 5];
         let mut e = v.swap_remove(0);