use {
super::super::{
SmallVec,
allocator::{
Allocator,
global::Global
}
},
core::{
fmt::{
Debug,
Formatter,
Result as Format
},
ptr::copy_nonoverlapping
}
};
pub struct ExtractIf<'valid, Item, const INLINE: usize, F, Heap: Allocator = Global>
where F: FnMut(&mut Item) -> bool
{
pub(crate) vec: &'valid mut SmallVec<Item, INLINE, Heap>,
pub(crate) idx: usize,
pub(crate) end: usize,
pub(crate) del: usize,
pub(crate) old_len: usize,
pub(crate) pred: F
}
impl<Item, const INLINE: usize, Heap: Allocator, F> Debug for ExtractIf<'_, Item, INLINE, F, Heap>
where
F: FnMut(&mut Item) -> bool,
Item: Debug
{
fn fmt(&self, f: &mut Formatter<'_>) -> Format {
f.debug_tuple("ExtractIf")
.field(&self.vec.as_ref())
.finish()
}
}
impl<Item, F, const INLINE: usize, Heap: Allocator> Iterator
for ExtractIf<'_, Item, INLINE, F, Heap>
where F: FnMut(&mut Item) -> bool
{
type Item = Item;
fn next(&mut self) -> Option<Item> {
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(cur.read());
} else if self.del > 0 {
copy_nonoverlapping(cur, cur.sub(self.del), 1);
}
}
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.end - self.idx))
}
}
impl<Item, F, const INLINE: usize, Heap: Allocator> Drop for ExtractIf<'_, Item, INLINE, F, Heap>
where F: FnMut(&mut Item) -> 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);
}
}
}