1use core::fmt;
2use core::iter::FusedIterator;
3use core::marker::PhantomData;
4use core::mem;
5
6use crate::alloc::{Allocator, Global, SizedTypeProperties};
7use crate::ptr::{self, NonNull};
8
9use super::VecDeque;
10
11pub struct Drain<'a, T, A = Global>
18where
19 T: 'a,
20 A: Allocator,
21{
22 deque: NonNull<VecDeque<T, A>>,
25 drain_len: usize,
27 idx: usize,
29 tail_len: usize,
31 remaining: usize,
32 _marker: PhantomData<&'a T>,
34}
35
36impl<'a, T, A> Drain<'a, T, A>
37where
38 A: Allocator,
39{
40 pub(super) unsafe fn new(
41 deque: &'a mut VecDeque<T, A>,
42 drain_start: usize,
43 drain_len: usize,
44 ) -> Self {
45 let orig_len = mem::replace(&mut deque.len, drain_start);
46 let tail_len = orig_len - drain_start - drain_len;
47 Drain {
48 deque: NonNull::from(deque),
49 drain_len,
50 idx: drain_start,
51 tail_len,
52 remaining: drain_len,
53 _marker: PhantomData,
54 }
55 }
56
57 unsafe fn as_slices(&self) -> (*mut [T], *mut [T]) {
60 unsafe {
61 let deque = self.deque.as_ref();
62
63 let logical_remaining_range = self.idx..self.idx + self.remaining;
65
66 let (a_range, b_range) =
72 deque.slice_ranges(logical_remaining_range.clone(), logical_remaining_range.end);
73 (deque.buffer_range(a_range), deque.buffer_range(b_range))
74 }
75 }
76}
77
78impl<T, A> fmt::Debug for Drain<'_, T, A>
79where
80 T: fmt::Debug,
81 A: Allocator,
82{
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.debug_tuple("Drain")
85 .field(&self.drain_len)
86 .field(&self.idx)
87 .field(&self.tail_len)
88 .field(&self.remaining)
89 .finish()
90 }
91}
92
93unsafe impl<T: Sync, A: Allocator + Sync> Sync for Drain<'_, T, A> {}
94unsafe impl<T: Send, A: Allocator + Send> Send for Drain<'_, T, A> {}
95
96impl<T, A> Drop for Drain<'_, T, A>
97where
98 A: Allocator,
99{
100 fn drop(&mut self) {
101 struct DropGuard<'r, 'a, T, A>(&'r mut Drain<'a, T, A>)
102 where
103 A: Allocator;
104
105 impl<T, A> Drop for DropGuard<'_, '_, T, A>
106 where
107 A: Allocator,
108 {
109 fn drop(&mut self) {
110 if self.0.remaining != 0 {
111 unsafe {
112 let (front, back) = self.0.as_slices();
114 ptr::drop_in_place(front);
115 ptr::drop_in_place(back);
116 }
117 }
118
119 let source_deque = unsafe { self.0.deque.as_mut() };
120
121 let drain_start = source_deque.len();
122 let drain_len = self.0.drain_len;
123 let drain_end = drain_start + drain_len;
124
125 let orig_len = self.0.tail_len + drain_end;
126
127 if T::IS_ZST {
128 source_deque.len = orig_len - drain_len;
130 return;
131 }
132
133 let head_len = drain_start;
134 let tail_len = self.0.tail_len;
135
136 match (head_len, tail_len) {
137 (0, 0) => {
138 source_deque.head = 0;
139 source_deque.len = 0;
140 }
141 (0, _) => {
142 source_deque.head = source_deque.to_physical_idx(drain_len);
143 source_deque.len = orig_len - drain_len;
144 }
145 (_, 0) => {
146 source_deque.len = orig_len - drain_len;
147 }
148 _ => unsafe {
149 if head_len <= tail_len {
150 source_deque.wrap_copy(
151 source_deque.head,
152 source_deque.to_physical_idx(drain_len),
153 head_len,
154 );
155 source_deque.head = source_deque.to_physical_idx(drain_len);
156 source_deque.len = orig_len - drain_len;
157 } else {
158 source_deque.wrap_copy(
159 source_deque.to_physical_idx(head_len + drain_len),
160 source_deque.to_physical_idx(head_len),
161 tail_len,
162 );
163 source_deque.len = orig_len - drain_len;
164 }
165 },
166 }
167 }
168 }
169
170 let guard = DropGuard(self);
171
172 if guard.0.remaining != 0 {
173 unsafe {
174 let (front, back) = guard.0.as_slices();
176 guard.0.idx += front.len();
178 guard.0.remaining -= front.len();
179 ptr::drop_in_place(front);
180 guard.0.remaining = 0;
181 ptr::drop_in_place(back);
182 }
183 }
184
185 }
187}
188
189impl<T, A> Iterator for Drain<'_, T, A>
190where
191 A: Allocator,
192{
193 type Item = T;
194
195 #[inline]
196 fn next(&mut self) -> Option<T> {
197 if self.remaining == 0 {
198 return None;
199 }
200 let wrapped_idx = unsafe { self.deque.as_ref().to_physical_idx(self.idx) };
201 self.idx += 1;
202 self.remaining -= 1;
203 Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) })
204 }
205
206 #[inline]
207 fn size_hint(&self) -> (usize, Option<usize>) {
208 let len = self.remaining;
209 (len, Some(len))
210 }
211}
212
213impl<T, A> DoubleEndedIterator for Drain<'_, T, A>
214where
215 A: Allocator,
216{
217 #[inline]
218 fn next_back(&mut self) -> Option<T> {
219 if self.remaining == 0 {
220 return None;
221 }
222 self.remaining -= 1;
223 let wrapped_idx = unsafe {
224 self.deque
225 .as_ref()
226 .to_physical_idx(self.idx + self.remaining)
227 };
228 Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) })
229 }
230}
231
232impl<T, A> ExactSizeIterator for Drain<'_, T, A> where A: Allocator {}
233
234impl<T, A> FusedIterator for Drain<'_, T, A> where A: Allocator {}