Skip to content

Commit

Permalink
keep_rest method for DrainFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
L0uisc authored and mbrubeck committed Jun 15, 2023
1 parent fa77030 commit 5d0c7e2
Showing 1 changed file with 42 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,48 @@ where
}
}

#[cfg(feature = "drain_filter")]
impl <T, F> DrainFilter<'_, T, F>
where
F: FnMut(T::Item) -> bool,
T: Array
{
pub fn keep_rest(self)
{
// At this moment layout looks like this:
//
// _____________________/-- old_len
// / \
// [kept] [yielded] [tail]
// \_______/ ^-- idx
// \-- del
//
// Normally `Drop` impl would drop [tail] (via .for_each(drop), ie still calling `pred`)
//
// 1. Move [tail] after [kept]
// 2. Update length of the original vec to `old_len - del`
// a. In case of ZST, this is the only thing we want to do
// 3. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do
let mut this = ManuallyDrop::new(self);

unsafe {
// ZSTs have no identity, so we don't need to move them around.
let needs_move = mem::size_of::<T>() != 0;

if needs_move && this.idx < this.old_len && this.del > 0 {
let ptr = this.vec.as_mut_ptr();
let src = ptr.add(this.idx);
let dst = src.sub(this.del);
let tail_len = this.old_len - this.idx;
src.copy_to(dst, tail_len);
}

let new_len = this.old_len - this.del;
this.vec.set_len(new_len);
}
}
}

#[cfg(feature = "union")]
union SmallVecData<A: Array> {
inline: core::mem::ManuallyDrop<MaybeUninit<A>>,
Expand Down

0 comments on commit 5d0c7e2

Please sign in to comment.