Skip to content

Commit

Permalink
Unrolled build for rust-lang#135890
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#135890 - GrigorenkoPV:deque-pop-if, r=thomcc

Implement `VecDeque::pop_front_if` & `VecDeque::pop_back_if`

Tracking issue: rust-lang#135889
  • Loading branch information
rust-timer authored Jan 24, 2025
2 parents 48ef38d + ed7cc34 commit 0b27748
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
46 changes: 46 additions & 0 deletions library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,52 @@ impl<T, A: Allocator> VecDeque<T, A> {
}
}

/// Removes and returns the first element from the deque if the predicate
/// returns `true`, or [`None`] if the predicate returns false or the deque
/// is empty (the predicate will not be called in that case).
///
/// # Examples
///
/// ```
/// #![feature(vec_deque_pop_if)]
/// use std::collections::VecDeque;
///
/// let mut deque: VecDeque<i32> = vec![0, 1, 2, 3, 4].into();
/// let pred = |x: &mut i32| *x % 2 == 0;
///
/// assert_eq!(deque.pop_front_if(pred), Some(0));
/// assert_eq!(deque, [1, 2, 3, 4]);
/// assert_eq!(deque.pop_front_if(pred), None);
/// ```
#[unstable(feature = "vec_deque_pop_if", issue = "135889")]
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
let first = self.front_mut()?;
if predicate(first) { self.pop_front() } else { None }
}

/// Removes and returns the last element from the deque if the predicate
/// returns `true`, or [`None`] if the predicate returns false or the deque
/// is empty (the predicate will not be called in that case).
///
/// # Examples
///
/// ```
/// #![feature(vec_deque_pop_if)]
/// use std::collections::VecDeque;
///
/// let mut deque: VecDeque<i32> = vec![0, 1, 2, 3, 4].into();
/// let pred = |x: &mut i32| *x % 2 == 0;
///
/// assert_eq!(deque.pop_back_if(pred), Some(4));
/// assert_eq!(deque, [0, 1, 2, 3]);
/// assert_eq!(deque.pop_back_if(pred), None);
/// ```
#[unstable(feature = "vec_deque_pop_if", issue = "135889")]
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
let first = self.back_mut()?;
if predicate(first) { self.pop_back() } else { None }
}

/// Prepends an element to the deque.
///
/// # Examples
Expand Down
1 change: 1 addition & 0 deletions library/alloc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#![feature(str_as_str)]
#![feature(strict_provenance_lints)]
#![feature(vec_pop_if)]
#![feature(vec_deque_pop_if)]
#![feature(unique_rc_arc)]
#![feature(macro_metavar_expr_concat)]
#![allow(internal_features)]
Expand Down
39 changes: 39 additions & 0 deletions library/alloc/tests/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,45 @@ fn test_parameterized<T: Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) {
assert_eq!(deq[3].clone(), d.clone());
}

#[test]
fn test_pop_if() {
let mut deq: VecDeque<_> = vec![0, 1, 2, 3, 4].into();
let pred = |x: &mut i32| *x % 2 == 0;

assert_eq!(deq.pop_front_if(pred), Some(0));
assert_eq!(deq, [1, 2, 3, 4]);

assert_eq!(deq.pop_front_if(pred), None);
assert_eq!(deq, [1, 2, 3, 4]);

assert_eq!(deq.pop_back_if(pred), Some(4));
assert_eq!(deq, [1, 2, 3]);

assert_eq!(deq.pop_back_if(pred), None);
assert_eq!(deq, [1, 2, 3]);
}

#[test]
fn test_pop_if_empty() {
let mut deq = VecDeque::<i32>::new();
assert_eq!(deq.pop_front_if(|_| true), None);
assert_eq!(deq.pop_back_if(|_| true), None);
assert!(deq.is_empty());
}

#[test]
fn test_pop_if_mutates() {
let mut v: VecDeque<_> = vec![-1, 1].into();
let pred = |x: &mut i32| {
*x *= 2;
false
};
assert_eq!(v.pop_front_if(pred), None);
assert_eq!(v, [-2, 1]);
assert_eq!(v.pop_back_if(pred), None);
assert_eq!(v, [-2, 2]);
}

#[test]
fn test_push_front_grow() {
let mut deq = VecDeque::new();
Expand Down

0 comments on commit 0b27748

Please sign in to comment.