tiny_vec/
extract_if.rs

1//! [extract_if](TinyVec::extract_if) implementation for TinyVec
2
3use core::iter::FusedIterator;
4use core::ptr;
5
6use alloc::slice;
7
8use crate::TinyVec;
9
10pub struct ExtractIf<'a, T, const N: usize, F>
11where
12    T: 'a,
13    F: FnMut(&mut T) -> bool,
14{
15    pub (super) vec: &'a mut TinyVec<T, N>,
16    pub (super) next: usize,
17    pub (super) last: usize,
18    pub (super) original_len: usize,
19    pub (super) deleted: usize,
20    pub (super) pred: F,
21}
22
23impl<T, const N: usize, F> Iterator for ExtractIf<'_, T, N, F>
24where
25    F: FnMut(&mut T) -> bool,
26{
27    type Item = T;
28
29    fn next(&mut self) -> Option<Self::Item> {
30        unsafe {
31            while self.next < self.last {
32                let i = self.next;
33                let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.original_len);
34                let drained = (self.pred)(&mut v[i]);
35
36                // Update the index *after* the predicate is called. If the index
37                // is updated prior and the predicate panics, the element at this
38                // index would be leaked.
39
40                self.next += 1;
41
42                if drained {
43                    self.deleted += 1;
44                    return Some(ptr::read(&v[i]));
45                } else if self.deleted > 0 {
46                    let del = self.deleted;
47                    let src: *const T = &v[i];
48                    let dst: *mut T = &mut v[i - del];
49                    ptr::copy_nonoverlapping(src, dst, 1);
50                }
51            }
52            None
53        }
54    }
55}
56
57impl<T, const N: usize, F> FusedIterator for ExtractIf<'_, T, N, F>
58where
59    F: FnMut(&mut T) -> bool {}
60
61impl<T, const N: usize, F> Drop for ExtractIf<'_, T, N, F>
62where
63    F: FnMut(&mut T) -> bool,
64{
65    fn drop(&mut self) {
66        unsafe {
67            if self.next < self.original_len && self.deleted > 0 {
68                let ptr = self.vec.as_mut_ptr();
69                let src = ptr.add(self.next);
70                let dst = src.sub(self.deleted);
71                let tail_len = self.original_len - self.next;
72                src.copy_to(dst, tail_len);
73            }
74            self.vec.set_len(self.original_len - self.deleted);
75        }
76    }
77}