Skip to content

Commit 6cbfbe2

Browse files
author
bors-servo
authored
Auto merge of #59 - Xaeroxe:retain, r=emilio,jdm
Add retain function <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/59) <!-- Reviewable:end -->
2 parents a39aaea + 5879b5e commit 6cbfbe2

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

lib.rs

+57
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,24 @@ impl<A: Array> SmallVec<A> {
605605
}
606606
}
607607
}
608+
609+
/// Retains only the elements specified by the predicate.
610+
///
611+
/// In other words, remove all elements `e` such that `f(&e)` returns `false`.
612+
/// This method operates in place and preserves the order of the retained
613+
/// elements.
614+
pub fn retain<F: FnMut(&A::Item) -> bool>(&mut self, mut f: F) {
615+
let mut del = 0;
616+
let len = self.len;
617+
for i in 0..len {
618+
if !f(&self[i]) {
619+
del += 1;
620+
} else if del > 0 {
621+
self.swap(i - del, i);
622+
}
623+
}
624+
self.truncate(len - del);
625+
}
608626
}
609627

610628
impl<A: Array> SmallVec<A> where A::Item: Copy {
@@ -1059,6 +1077,10 @@ pub mod tests {
10591077
use std::borrow::ToOwned;
10601078
#[cfg(not(feature = "std"))]
10611079
use alloc::borrow::ToOwned;
1080+
#[cfg(feature = "std")]
1081+
use std::rc::Rc;
1082+
#[cfg(not(feature = "std"))]
1083+
use alloc::rc::Rc;
10621084
#[cfg(not(feature = "std"))]
10631085
use alloc::boxed::Box;
10641086
#[cfg(not(feature = "std"))]
@@ -1589,6 +1611,41 @@ pub mod tests {
15891611
drop(small_vec);
15901612
}
15911613

1614+
#[test]
1615+
fn test_retain() {
1616+
// Test inline data storate
1617+
let mut sv: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]);
1618+
sv.retain(|&i| i != 3);
1619+
assert_eq!(sv.pop(), Some(4));
1620+
assert_eq!(sv.pop(), Some(2));
1621+
assert_eq!(sv.pop(), Some(1));
1622+
assert_eq!(sv.pop(), None);
1623+
1624+
// Test spilled data storage
1625+
let mut sv: SmallVec<[i32; 3]> = SmallVec::from_slice(&[1, 2, 3, 3, 4]);
1626+
sv.retain(|&i| i != 3);
1627+
assert_eq!(sv.pop(), Some(4));
1628+
assert_eq!(sv.pop(), Some(2));
1629+
assert_eq!(sv.pop(), Some(1));
1630+
assert_eq!(sv.pop(), None);
1631+
1632+
// Test that drop implementations are called for inline.
1633+
let one = Rc::new(1);
1634+
let mut sv: SmallVec<[Rc<i32>; 3]> = SmallVec::new();
1635+
sv.push(Rc::clone(&one));
1636+
assert_eq!(Rc::strong_count(&one), 2);
1637+
sv.retain(|_| false);
1638+
assert_eq!(Rc::strong_count(&one), 1);
1639+
1640+
// Test that drop implementations are called for spilled data.
1641+
let mut sv: SmallVec<[Rc<i32>; 1]> = SmallVec::new();
1642+
sv.push(Rc::clone(&one));
1643+
sv.push(Rc::new(2));
1644+
assert_eq!(Rc::strong_count(&one), 2);
1645+
sv.retain(|_| false);
1646+
assert_eq!(Rc::strong_count(&one), 1);
1647+
}
1648+
15921649
#[cfg(feature = "std")]
15931650
#[test]
15941651
fn test_write() {

0 commit comments

Comments
 (0)