Skip to content

Commit 949a1e2

Browse files
committed
Implement Vec::pop_if
1 parent 536606b commit 949a1e2

File tree

4 files changed

+57
-0
lines changed

4 files changed

+57
-0
lines changed

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@
169169
#![feature(unicode_internals)]
170170
#![feature(unsize)]
171171
#![feature(utf8_chunks)]
172+
#![feature(vec_pop_if)]
172173
// tidy-alphabetical-end
173174
//
174175
// Language features:

library/alloc/src/vec/mod.rs

+36
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,42 @@ impl<T, A: Allocator> Vec<T, A> {
20582058
}
20592059
}
20602060

2061+
/// Removes and returns the last element in a vector if the predicate
2062+
/// returns `true`, or [`None`] if the predicate returns false or the vector
2063+
/// is empty.
2064+
///
2065+
/// # Examples
2066+
///
2067+
/// ```
2068+
/// #![feature(vec_pop_if)]
2069+
///
2070+
/// let mut vec = vec![1, 2, 3, 4];
2071+
/// let pred = |x: &mut i32| *x % 2 == 0;
2072+
///
2073+
/// assert_eq!(vec.pop_if(pred), Some(4));
2074+
/// assert_eq!(vec, [1, 2, 3]);
2075+
/// assert_eq!(vec.pop_if(pred), None);
2076+
/// ```
2077+
#[unstable(feature = "vec_pop_if", issue = "122741")]
2078+
pub fn pop_if<F>(&mut self, f: F) -> Option<T>
2079+
where
2080+
F: FnOnce(&mut T) -> bool,
2081+
{
2082+
if self.len == 0 {
2083+
return None;
2084+
}
2085+
2086+
// SAFETY: the vector is not empty
2087+
let mut last = unsafe { ptr::read(self.as_ptr().add(self.len() - 1)) };
2088+
2089+
if f(&mut last) {
2090+
self.len -= 1;
2091+
Some(last)
2092+
} else {
2093+
None
2094+
}
2095+
}
2096+
20612097
/// Moves all the elements of `other` into `self`, leaving `other` empty.
20622098
///
20632099
/// # Panics

library/alloc/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#![feature(strict_provenance)]
4444
#![feature(drain_keep_rest)]
4545
#![feature(local_waker)]
46+
#![feature(vec_pop_if)]
4647
#![allow(internal_features)]
4748
#![deny(fuzzy_provenance_casts)]
4849
#![deny(unsafe_op_in_unsafe_fn)]

library/alloc/tests/vec.rs

+19
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,25 @@ impl Drop for DropCounter<'_> {
2828
}
2929
}
3030

31+
#[test]
32+
fn test_pop_if() {
33+
let mut v = vec![1, 2, 3, 4];
34+
let pred = |x: &mut i32| *x % 2 == 0;
35+
36+
assert_eq!(v.pop_if(pred), Some(4));
37+
assert_eq!(v, [1, 2, 3]);
38+
39+
assert_eq!(v.pop_if(pred), None);
40+
assert_eq!(v, [1, 2, 3]);
41+
}
42+
43+
#[test]
44+
fn test_pop_if_empty() {
45+
let mut v = Vec::<i32>::new();
46+
assert_eq!(v.pop_if(|_| true), None);
47+
assert!(v.is_empty());
48+
}
49+
3150
#[test]
3251
fn test_small_vec_struct() {
3352
assert_eq!(size_of::<Vec<u8>>(), size_of::<usize>() * 3);

0 commit comments

Comments
 (0)