use crate::{
Allocator,
Global,
SmallVec
};
pub struct ExtractIf<'a, T, const N: usize, F, A: Allocator = Global>
where F: FnMut(&mut T) -> bool
{
pub(crate) vec: &'a mut SmallVec<T, N, A>,
pub(crate) idx: usize,
pub(crate) end: usize,
pub(crate) del: usize,
pub(crate) old_len: usize,
pub(crate) pred: F
}
impl<T, const N: usize, A: Allocator, F> core::fmt::Debug for ExtractIf<'_, T, N, F, A>
where
F: FnMut(&mut T) -> bool,
T: core::fmt::Debug
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("ExtractIf")
.field(&self.vec.as_slice())
.finish()
}
}
impl<T, F, const N: usize, A: Allocator> Iterator for ExtractIf<'_, T, N, F, A>
where F: FnMut(&mut T) -> bool
{
type Item = T;
fn next(&mut self) -> Option<T> {
unsafe {
while self.idx < self.end {
let i = self.idx;
let cur = self.vec.as_mut_ptr().add(i);
let drained = (self.pred)(&mut *cur);
self.idx += 1;
if drained {
self.del += 1;
return Some(core::ptr::read(cur));
} else if self.del > 0 {
core::ptr::copy_nonoverlapping(cur, cur.sub(self.del), 1);
}
}
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.end - self.idx))
}
}
impl<T, F, const N: usize, A: Allocator> Drop for ExtractIf<'_, T, N, F, A>
where F: FnMut(&mut T) -> bool
{
fn drop(&mut self) {
unsafe {
if self.idx < self.old_len && self.del > 0 {
let ptr = self.vec.as_mut_ptr();
let source = ptr.add(self.idx);
let destination = source.sub(self.del);
let tail_len = self.old_len - self.idx;
source.copy_to(destination, tail_len);
}
self.vec.set_len(self.old_len - self.del);
}
}
}