Skip to content

Commit 463dbb7

Browse files
committed
implement retain
1 parent 475e57d commit 463dbb7

File tree

1 file changed

+59
-2
lines changed

1 file changed

+59
-2
lines changed

src/lib.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,36 @@ impl<T> PacketBuf<T> {
112112
.filter_map(move |(i, slot)| slot.as_ref().map(|v| (start + i as u64, v)))
113113
}
114114

115+
pub fn retain(&mut self, f: impl FnMut(u64, &mut T) -> bool) {
116+
let mut f = f;
117+
let base = base(self.min, self.max);
118+
for i in self.min..self.max {
119+
let offset = (i - base) as usize;
120+
let Some(v) = &mut self.data[offset] else {
121+
continue;
122+
};
123+
if !f(i, v) {
124+
self.data[offset] = None;
125+
}
126+
}
127+
// Now adjust min and max
128+
let start = (self.min - base) as usize;
129+
let end = (self.max - base) as usize;
130+
let min1 = self.data[start..end]
131+
.iter()
132+
.position(|slot| slot.is_some())
133+
.map(|p| p + start)
134+
.unwrap_or(end) as u64 + base;
135+
let max1 = self.data[start..end]
136+
.iter()
137+
.rev()
138+
.position(|slot| slot.is_some())
139+
.map(|p| end - p)
140+
.unwrap_or(start + 1) as u64 + base;
141+
self.resize(min1, max1);
142+
self.check_invariants();
143+
}
144+
115145
/// Retain only the elements in the given index range.
116146
pub fn retain_range<R: std::ops::RangeBounds<u64>>(&mut self, range: R) {
117147
let (min1, max1) = self.clip_bounds(range);
@@ -281,7 +311,7 @@ impl<T> PacketBuf<T> {
281311
// nothing to do
282312
return;
283313
}
284-
if min1 == max1 {
314+
if min1 >= max1 {
285315
// resizing to empty buffer
286316
*self = Self::new();
287317
return;
@@ -471,6 +501,33 @@ mod tests {
471501
assert_eq!(pairs, (10..20).map(|i| (i, i * 10)).collect::<Vec<_>>());
472502
}
473503

504+
505+
#[test]
506+
fn test_retain() {
507+
let mut pb = PacketBuf::default();
508+
for i in 0..100 {
509+
pb.insert(i, i * 10);
510+
}
511+
512+
pb.retain(|i, _v| i % 2 == 0);
513+
514+
assert_eq!(pb.keys().next(), Some(0));
515+
assert_eq!(pb.keys().next_back(), Some(98));
516+
assert_eq!(pb.keys().count(), 50);
517+
for i in 0..100 {
518+
if i % 2 == 0 {
519+
assert_eq!(pb.get(i), Some(&(i * 10)));
520+
} else {
521+
assert_eq!(pb.get(i), None);
522+
}
523+
}
524+
pb.check_invariants_expensive();
525+
526+
pb.retain(|_,_| false);
527+
assert!(pb.is_empty());
528+
pb.check_invariants_expensive();
529+
}
530+
474531
#[test]
475532
fn test_retain_range() {
476533
let mut pb = PacketBuf::default();
@@ -531,7 +588,7 @@ mod tests {
531588
proptest! {
532589
#[test]
533590
fn test_matches_btreemap(ops in prop::collection::vec(op_strategy(), 0..1000)) {
534-
let mut pb = PacketBuffer::default();
591+
let mut pb = PacketBuf::default();
535592
let mut reference = BTreeMap::new();
536593

537594
for op in ops {

0 commit comments

Comments
 (0)