1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::MiniVec;
extern crate alloc;
pub struct Drain<'a, T: 'a> {
vec_: core::ptr::NonNull<MiniVec<T>>,
drain_pos_: core::ptr::NonNull<T>,
drain_end_: core::ptr::NonNull<T>,
remaining_pos_: core::ptr::NonNull<T>,
remaining_: usize,
marker_: core::marker::PhantomData<&'a T>,
}
pub fn make_drain_iterator<'a, T>(
vec: &mut MiniVec<T>,
data: *mut T,
remaining: usize,
start_idx: usize,
end_idx: usize,
) -> Drain<'a, T> {
if data.is_null() {
Drain {
vec_: core::ptr::NonNull::from(vec),
drain_pos_: core::ptr::NonNull::dangling(),
drain_end_: core::ptr::NonNull::dangling(),
remaining_pos_: core::ptr::NonNull::dangling(),
remaining_: remaining,
marker_: core::marker::PhantomData,
}
} else {
Drain {
vec_: core::ptr::NonNull::from(vec),
drain_pos_: unsafe { core::ptr::NonNull::new_unchecked(data.add(start_idx)) },
drain_end_: unsafe { core::ptr::NonNull::new_unchecked(data.add(end_idx)) },
remaining_pos_: unsafe { core::ptr::NonNull::new_unchecked(data.add(end_idx)) },
remaining_: remaining,
marker_: core::marker::PhantomData,
}
}
}
impl<T> Iterator for Drain<'_, T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.drain_pos_ >= self.drain_end_ {
return None;
}
let p = self.drain_pos_.as_ptr();
let tmp = unsafe { core::ptr::read(p) };
self.drain_pos_ = unsafe { core::ptr::NonNull::new_unchecked(p.add(1)) };
Some(tmp)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = (self.drain_end_.as_ptr() as *const _ as usize
- self.drain_pos_.as_ptr() as *const _ as usize)
/ core::mem::size_of::<T>();
(len, Some(len))
}
}
impl<T> ExactSizeIterator for Drain<'_, T> {}
impl<T> DoubleEndedIterator for Drain<'_, T> {
fn next_back(&mut self) -> Option<Self::Item> {
let pos = unsafe { self.drain_end_.as_ptr().sub(1) };
if pos < self.drain_pos_.as_ptr() {
return None;
}
let tmp = unsafe { core::ptr::read(pos) };
self.drain_end_ = unsafe { core::ptr::NonNull::new_unchecked(pos) };
Some(tmp)
}
}
impl<T> Drop for Drain<'_, T> {
fn drop(&mut self) {
struct DropGuard<'b, 'a, T> {
drain: &'b mut Drain<'a, T>,
}
impl<'b, 'a, T> Drop for DropGuard<'b, 'a, T> {
fn drop(&mut self) {
for x in &mut self.drain {
core::mem::drop(x);
}
if self.drain.remaining_ > 0 {
let v = unsafe { self.drain.vec_.as_mut() };
let v_len = v.len();
let src = self.drain.remaining_pos_.as_ptr();
let dst = unsafe { v.as_mut_ptr().add(v_len) };
unsafe {
core::ptr::copy(src, dst, self.drain.remaining_);
v.set_len(v_len + self.drain.remaining_);
};
}
}
}
while let Some(item) = self.next() {
let guard = DropGuard { drain: self };
drop(item);
core::mem::forget(guard);
}
DropGuard { drain: self };
}
}