bump_scope/owned_slice/
drain.rs1use core::{
2 fmt,
3 iter::FusedIterator,
4 mem::{self, ManuallyDrop},
5 ops::RangeBounds,
6 ptr::{self, NonNull},
7};
8
9use crate::{
10 BumpBox, SizedTypeProperties, owned_slice,
11 polyfill::{non_null, slice},
12};
13
14use super::TakeOwnedSlice;
15
16pub struct Drain<'a, T: 'a> {
37 tail_start: usize,
39 tail_len: usize,
41 iter: owned_slice::IntoIter<'a, T>,
43 slice: &'a mut NonNull<[T]>,
44}
45
46impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
49 }
50}
51
52impl<'a, T> Drain<'a, T> {
53 pub(crate) fn new(boxed: &'a mut BumpBox<[T]>, range: impl RangeBounds<usize>) -> Drain<'a, T> {
54 let len = boxed.len();
65 let range = slice::range(range, ..len);
66
67 unsafe {
68 boxed.set_len(range.start);
70
71 Drain {
72 tail_start: range.end,
73 tail_len: len - range.end,
74 iter: owned_slice::IntoIter::new_ranged(boxed.ptr(), range),
75 slice: boxed.mut_ptr(),
76 }
77 }
78 }
79
80 #[must_use]
94 pub fn as_slice(&self) -> &[T] {
95 self.iter.as_slice()
96 }
97
98 pub fn keep_rest(self) {
118 let mut this = ManuallyDrop::new(self);
132
133 unsafe {
134 let slice_ptr = non_null::as_non_null_ptr(*this.slice).as_ptr();
135
136 let start = this.slice.len();
137 let tail = this.tail_start;
138
139 let unyielded_len = this.iter.len();
140 let unyielded_ptr = this.iter.as_slice().as_ptr();
141
142 if !T::IS_ZST {
144 let start_ptr = slice_ptr.add(start);
145
146 if unyielded_ptr != start_ptr {
148 let src = unyielded_ptr;
149 let dst = start_ptr;
150
151 ptr::copy(src, dst, unyielded_len);
152 }
153
154 if tail != (start + unyielded_len) {
156 let src = slice_ptr.add(tail);
157 let dst = start_ptr.add(unyielded_len);
158 ptr::copy(src, dst, this.tail_len);
159 }
160 }
161
162 let new_len = start + unyielded_len + this.tail_len;
163 non_null::set_len(this.slice, new_len);
164 }
165 }
166}
167
168impl<T> AsRef<[T]> for Drain<'_, T> {
169 fn as_ref(&self) -> &[T] {
170 self.as_slice()
171 }
172}
173
174unsafe impl<T: Sync> Sync for Drain<'_, T> {}
175unsafe impl<T: Send> Send for Drain<'_, T> {}
176
177impl<T> Iterator for Drain<'_, T> {
178 type Item = T;
179
180 #[inline]
181 fn next(&mut self) -> Option<T> {
182 self.iter.next()
183 }
184
185 #[inline]
186 fn size_hint(&self) -> (usize, Option<usize>) {
187 self.iter.size_hint()
188 }
189}
190
191impl<T> DoubleEndedIterator for Drain<'_, T> {
192 #[inline]
193 fn next_back(&mut self) -> Option<T> {
194 self.iter.next_back()
195 }
196}
197
198impl<T> Drop for Drain<'_, T> {
199 fn drop(&mut self) {
200 struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>);
202
203 impl<T> Drop for DropGuard<'_, '_, T> {
204 fn drop(&mut self) {
205 if self.0.tail_len > 0 {
206 unsafe {
207 let slice_ptr = non_null::as_non_null_ptr(*self.0.slice).as_ptr();
209
210 let start = self.0.slice.len();
211 let tail = self.0.tail_start;
212
213 if tail != start {
214 let src = slice_ptr.add(tail);
215 let dst = slice_ptr.add(start);
216 ptr::copy(src, dst, self.0.tail_len);
217 }
218
219 non_null::set_len(self.0.slice, start + self.0.tail_len);
220 }
221 }
222 }
223 }
224
225 let iter = mem::take(&mut self.iter);
226
227 if T::IS_ZST {
228 unsafe {
231 let old_len = self.slice.len();
232 non_null::set_len(self.slice, old_len + iter.len() + self.tail_len);
233 non_null::truncate(self.slice, old_len + self.tail_len);
234 }
235
236 return;
237 }
238
239 let _guard = DropGuard(self);
241
242 drop(iter);
244 }
245}
246
247impl<T> ExactSizeIterator for Drain<'_, T> {
248 #[cfg(feature = "nightly-exact-size-is-empty")]
249 fn is_empty(&self) -> bool {
250 self.iter.is_empty()
251 }
252}
253
254#[cfg(feature = "nightly-trusted-len")]
255unsafe impl<T> core::iter::TrustedLen for Drain<'_, T> {}
256
257impl<T> FusedIterator for Drain<'_, T> {}
258
259unsafe impl<T> TakeOwnedSlice for Drain<'_, T> {
260 type Item = T;
261
262 #[inline]
263 fn owned_slice_ref(&self) -> &[Self::Item] {
264 self.iter.owned_slice_ref()
265 }
266
267 #[inline]
268 fn take_owned_slice(&mut self) {
269 self.iter.take_owned_slice();
270 }
271}
272
273#[cfg(all(test, feature = "std"))]
274mod tests {
275 use std::{string::ToString, vec::Vec};
276
277 use crate::{
278 FixedBumpVec,
279 tests::{Bump, TestWrap},
280 };
281
282 #[test]
283 fn owned_slice() {
284 let bump: Bump = Bump::new();
285 let slice = bump.alloc_iter((0..5).map(|v| v.to_string()).map(TestWrap));
286 assert_eq!(
287 slice.iter().map(|v| v.0.clone()).collect::<Vec<_>>(),
288 &["0", "1", "2", "3", "4"]
289 );
290
291 for start in 0..slice.len() {
292 for end in start..slice.len() {
293 TestWrap::expect().drops(5).clones(5).run(|| {
294 let mut slice_clone = bump.alloc_slice_clone(&slice);
295
296 let mut vec = FixedBumpVec::with_capacity_in(10, &bump);
297 vec.append(slice_clone.drain(start..end));
298
299 assert_eq!(vec, slice[start..end]);
300
301 assert_eq!(
302 TestWrap::peel_slice(slice_clone.as_slice()),
303 TestWrap::peel_slice(&slice[..start])
304 .iter()
305 .chain(TestWrap::peel_slice(&slice[end..]))
306 .cloned()
307 .collect::<Vec<_>>()
308 );
309 });
310 }
311 }
312 }
313
314 #[test]
315 fn owned_slice_zst() {
316 let bump: Bump = Bump::new();
317 let slice = bump.alloc_iter((0..5).map(|v| v.to_string()).map(TestWrap));
318
319 for start in 0..slice.len() {
320 for end in start..slice.len() {
321 TestWrap::expect().drops(5).clones(5).run(|| {
322 let mut slice_clone = bump.alloc_slice_clone(&slice);
323 let mut vec = FixedBumpVec::with_capacity_in(10, &bump);
324 vec.append(slice_clone.drain(start..end));
325
326 assert_eq!(vec.len(), end - start);
327 assert_eq!(slice_clone.len(), slice[..start].len() + slice[end..].len());
328 });
329 }
330 }
331 }
332}