Skip to content

Commit d805b83

Browse files
author
blake2-ppc
committed
vec: Add .pop_opt() -> Option<T>
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.
1 parent 58eb70a commit d805b83

File tree

1 file changed

+38
-24
lines changed

1 file changed

+38
-24
lines changed

src/libstd/vec.rs

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,7 @@ pub trait OwnedVector<T> {
10911091

10921092
fn push_all_move(&mut self, rhs: ~[T]);
10931093
fn pop(&mut self) -> T;
1094+
fn pop_opt(&mut self) -> Option<T>;
10941095
fn shift(&mut self) -> T;
10951096
fn unshift(&mut self, x: T);
10961097
fn insert(&mut self, i: uint, x:T);
@@ -1281,20 +1282,28 @@ impl<T> OwnedVector<T> for ~[T] {
12811282
}
12821283
}
12831284

1284-
/// Remove the last element from a vector and return it
1285-
fn pop(&mut self) -> T {
1286-
let ln = self.len();
1287-
if ln == 0 {
1288-
fail!("sorry, cannot pop an empty vector")
1289-
}
1290-
let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]);
1291-
unsafe {
1292-
let val = ptr::replace_ptr(valptr, intrinsics::init());
1293-
raw::set_len(self, ln - 1u);
1294-
val
1285+
/// Remove the last element from a vector and return it, or `None` if it is empty
1286+
fn pop_opt(&mut self) -> Option<T> {
1287+
match self.len() {
1288+
0 => None,
1289+
ln => {
1290+
let valptr = ptr::to_mut_unsafe_ptr(&mut self[ln - 1u]);
1291+
unsafe {
1292+
let val = ptr::replace_ptr(valptr, intrinsics::init());
1293+
raw::set_len(self, ln - 1u);
1294+
Some(val)
1295+
}
1296+
}
12951297
}
12961298
}
12971299

1300+
1301+
/// Remove the last element from a vector and return it, failing if it is empty
1302+
#[inline]
1303+
fn pop(&mut self) -> T {
1304+
self.pop_opt().expect("pop: empty vector")
1305+
}
1306+
12981307
/// Removes the first element from a vector and return it
12991308
fn shift(&mut self) -> T {
13001309
unsafe {
@@ -2089,18 +2098,13 @@ impl<T> Iterator<T> for VecConsumeIterator<T> {
20892098
//
20902099
// [1,2,3,4,5] => 1, [5,2,3,4] => 2, [5,4,3] => 3, [5,4] => 4,
20912100
// [5] -> 5, []
2092-
2093-
if self.v.is_empty() {
2094-
None
2095-
} else {
2096-
let l = self.v.len();
2097-
if self.idx < l {
2098-
self.v.swap(self.idx, l - 1);
2099-
self.idx += 1;
2100-
}
2101-
2102-
Some(self.v.pop())
2101+
let l = self.v.len();
2102+
if self.idx < l {
2103+
self.v.swap(self.idx, l - 1);
2104+
self.idx += 1;
21032105
}
2106+
2107+
self.v.pop_opt()
21042108
}
21052109
}
21062110

@@ -2111,8 +2115,7 @@ pub struct VecConsumeRevIterator<T> {
21112115

21122116
impl<T> Iterator<T> for VecConsumeRevIterator<T> {
21132117
fn next(&mut self) -> Option<T> {
2114-
if self.v.is_empty() { None }
2115-
else { Some(self.v.pop()) }
2118+
self.v.pop_opt()
21162119
}
21172120
}
21182121

@@ -2415,6 +2418,17 @@ mod tests {
24152418
}
24162419

24172420
#[test]
2421+
fn test_pop_opt() {
2422+
let mut v = ~[5];
2423+
let e = v.pop_opt();
2424+
assert_eq!(v.len(), 0);
2425+
assert_eq!(e, Some(5));
2426+
let f = v.pop_opt();
2427+
assert_eq!(f, None);
2428+
let g = v.pop_opt();
2429+
assert_eq!(g, None);
2430+
}
2431+
24182432
fn test_swap_remove() {
24192433
let mut v = ~[1, 2, 3, 4, 5];
24202434
let mut e = v.swap_remove(0);

0 commit comments

Comments
 (0)