Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ jobs:
- uses: taiki-e/install-action@v2
with:
tool: cargo-nextest
if: github.event_name == 'merge_group'
- run: cargo miri nextest run
if: github.event_name == 'merge_group'
- run: cargo miri test --doc

minimal-versions:
Expand Down
60 changes: 60 additions & 0 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,66 @@ impl<K, V, S> RingMap<K, V, S> {
self.core.pop_front()
}

/// Removes and returns the last key-value pair from a map if the predicate
/// returns `true`, or [`None`] if the predicate returns false or the map
/// is empty (the predicate will not be called in that case).
///
/// This preserves the order of the remaining elements.
///
/// Computes in **O(1)** time (average).
///
/// # Examples
///
/// ```
/// use ringmap::RingMap;
///
/// let init = [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')];
/// let mut map = RingMap::from(init);
/// let pred = |key: &i32, _value: &mut char| *key % 2 == 0;
///
/// assert_eq!(map.pop_back_if(pred), Some((4, 'd')));
/// assert_eq!(map.as_slices().0, &init[..3]);
/// assert_eq!(map.pop_back_if(pred), None);
/// ```
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)> {
let (last_key, last_value) = self.back_mut()?;
if predicate(last_key, last_value) {
self.core.pop_back()
} else {
None
}
}

/// Removes and returns the first key-value pair from a map if the predicate
/// returns `true`, or [`None`] if the predicate returns false or the map
/// is empty (the predicate will not be called in that case).
///
/// This preserves the order of the remaining elements.
///
/// Computes in **O(1)** time (average).
///
/// # Examples
///
/// ```
/// use ringmap::RingMap;
///
/// let init = [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')];
/// let mut map = RingMap::from(init);
/// let pred = |key: &i32, _value: &mut char| *key % 2 == 1;
///
/// assert_eq!(map.pop_front_if(pred), Some((1, 'a')));
/// assert_eq!(map.as_slices().0, &init[1..]);
/// assert_eq!(map.pop_front_if(pred), None);
/// ```
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&K, &mut V) -> bool) -> Option<(K, V)> {
let (first_key, first_value) = self.front_mut()?;
if predicate(first_key, first_value) {
self.core.pop_front()
} else {
None
}
}

/// Scan through each key-value pair in the map and keep those where the
/// closure `keep` returns `true`.
///
Expand Down
58 changes: 58 additions & 0 deletions src/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,64 @@ impl<T, S> RingSet<T, S> {
self.map.pop_front().map(|(x, ())| x)
}

/// Removes and returns the last value from a set if the predicate
/// returns `true`, or [`None`] if the predicate returns false or the set
/// is empty (the predicate will not be called in that case).
///
/// This preserves the order of the remaining elements.
///
/// Computes in **O(1)** time (average).
///
/// # Examples
///
/// ```
/// use ringmap::RingSet;
///
/// let mut set = RingSet::from([1, 2, 3, 4]);
/// let pred = |x: &i32| *x % 2 == 0;
///
/// assert_eq!(set.pop_back_if(pred), Some(4));
/// assert_eq!(set.as_slices().0, &[1, 2, 3]);
/// assert_eq!(set.pop_back_if(pred), None);
/// ```
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
let last = self.back()?;
if predicate(last) {
self.pop_back()
} else {
None
}
}

/// Removes and returns the first value from a set if the predicate
/// returns `true`, or [`None`] if the predicate returns false or the set
/// is empty (the predicate will not be called in that case).
///
/// This preserves the order of the remaining elements.
///
/// Computes in **O(1)** time (average).
///
/// # Examples
///
/// ```
/// use ringmap::RingSet;
///
/// let mut set = RingSet::from([1, 2, 3, 4]);
/// let pred = |x: &i32| *x % 2 == 1;
///
/// assert_eq!(set.pop_front_if(pred), Some(1));
/// assert_eq!(set.as_slices().0, &[2, 3, 4]);
/// assert_eq!(set.pop_front_if(pred), None);
/// ```
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
let first = self.front()?;
if predicate(first) {
self.pop_front()
} else {
None
}
}

/// Scan through each value in the set and keep those where the
/// closure `keep` returns `true`.
///
Expand Down