Skip to content

Commit 45a1f11

Browse files
authored
Merge pull request #641 from sgued/deque-pop-front-if
deque: Add pop_front_if and pop_back_if
2 parents b8fa753 + 8d95d99 commit 45a1f11

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88
## [Unreleased]
99
- Added `from_bytes_truncating_at_nul` to `CString`
1010
- Added `CString::{into_bytes, into_bytes_with_nul, into_string}`
11+
- Added `pop_front_if` and `pop_back_if` to `Deque`
1112

1213
## [v0.9.2] 2025-11-12
1314

src/deque.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,56 @@ impl<T, S: VecStorage<T> + ?Sized> DequeInner<T, S> {
669669
}
670670
}
671671

672+
/// Removes and returns the first element from the deque if the predicate
673+
/// returns `true`, or [`None`] if the predicate returns false or the deque
674+
/// is empty (the predicate will not be called in that case).
675+
///
676+
/// # Examples
677+
///
678+
/// ```
679+
/// use heapless::Deque;
680+
///
681+
/// let mut deque: Deque<i32, 5> = [0, 1, 2, 3, 4].try_into().unwrap();
682+
/// let pred = |x: &mut i32| *x % 2 == 0;
683+
///
684+
/// assert_eq!(deque.pop_front_if(pred), Some(0));
685+
/// assert_eq!(deque, Deque::<i32,4>::try_from([1, 2, 3, 4]).unwrap());
686+
/// assert_eq!(deque.pop_front_if(pred), None);
687+
/// ```
688+
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
689+
let first = self.front_mut()?;
690+
if predicate(first) {
691+
self.pop_front()
692+
} else {
693+
None
694+
}
695+
}
696+
697+
/// Removes and returns the last element from the deque if the predicate
698+
/// returns `true`, or [`None`] if the predicate returns false or the deque
699+
/// is empty (the predicate will not be called in that case).
700+
///
701+
/// # Examples
702+
///
703+
/// ```
704+
/// use heapless::Deque;
705+
///
706+
/// let mut deque: Deque<i32, 5> = [0, 1, 2, 3, 4].try_into().unwrap();
707+
/// let pred = |x: &mut i32| *x % 2 == 0;
708+
///
709+
/// assert_eq!(deque.pop_back_if(pred), Some(4));
710+
/// assert_eq!(deque, Deque::<i32,4>::try_from([0, 1, 2, 3]).unwrap());
711+
/// assert_eq!(deque.pop_back_if(pred), None);
712+
/// ```
713+
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> {
714+
let last = self.back_mut()?;
715+
if predicate(last) {
716+
self.pop_back()
717+
} else {
718+
None
719+
}
720+
}
721+
672722
/// Returns a reference to the element at the given index.
673723
///
674724
/// Index 0 is the front of the `Deque`.
@@ -2199,4 +2249,30 @@ mod tests {
21992249
assert_eq!(Droppable::count(), 10);
22002250
}
22012251
}
2252+
2253+
#[test]
2254+
fn test_pop_if() {
2255+
let mut deq: Deque<i32, 5> = [0, 1, 2, 3, 4].try_into().unwrap();
2256+
let pred = |x: &mut i32| *x % 2 == 0;
2257+
2258+
assert_eq!(deq.pop_front_if(pred), Some(0));
2259+
assert_eq!(deq, Deque::<i32, 5>::try_from([1, 2, 3, 4]).unwrap());
2260+
2261+
assert_eq!(deq.pop_front_if(pred), None);
2262+
assert_eq!(deq, Deque::<i32, 5>::try_from([1, 2, 3, 4]).unwrap());
2263+
2264+
assert_eq!(deq.pop_back_if(pred), Some(4));
2265+
assert_eq!(deq, Deque::<i32, 5>::try_from([1, 2, 3]).unwrap());
2266+
2267+
assert_eq!(deq.pop_back_if(pred), None);
2268+
assert_eq!(deq, Deque::<i32, 5>::try_from([1, 2, 3]).unwrap());
2269+
}
2270+
2271+
#[test]
2272+
fn test_pop_if_empty() {
2273+
let mut deq = Deque::<i32, 5>::new();
2274+
assert_eq!(deq.pop_front_if(|_| true), None);
2275+
assert_eq!(deq.pop_back_if(|_| true), None);
2276+
assert!(deq.is_empty());
2277+
}
22022278
}

0 commit comments

Comments
 (0)