bump_scope/owned_slice/drain.rs
1use 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
16/// A draining iterator for owned slices.
17///
18/// This struct is created by the `drain` method on
19/// [`BumpBox`](BumpBox::drain),
20/// [`FixedBumpVec`](crate::FixedBumpVec::drain),
21/// [`BumpVec`](crate::BumpVec::drain) and
22/// [`MutBumpVec`](crate::MutBumpVec::drain).
23///
24/// See their documentation for more.
25///
26/// # Example
27///
28/// ```
29/// use bump_scope::{Bump, owned_slice::Drain};
30/// let bump: Bump = Bump::new();
31///
32/// let mut v = bump.alloc_slice_copy(&[0, 1, 2]);
33/// let iter: Drain<'_, _> = v.drain(..);
34/// # _ = iter;
35/// ```
36pub struct Drain<'a, T: 'a> {
37 /// Index of tail to preserve
38 tail_start: usize,
39 /// Length of tail
40 tail_len: usize,
41 /// Current remaining range to remove
42 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 // Memory safety
55 //
56 // When the Drain is first created, it shortens the length of
57 // the source slice to make sure no uninitialized or moved-from elements
58 // are accessible at all if the Drain's destructor never gets to run.
59 //
60 // Drain will copy out the values to remove.
61 // When finished, remaining tail of the vec is copied back to cover
62 // the hole, and the vector length is restored to the new length.
63
64 let len = boxed.len();
65 let range = slice::range(range, ..len);
66
67 unsafe {
68 // set self.vec length's to start, to be safe in case Drain is leaked
69 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 /// Returns the remaining items of this iterator as a slice.
81 ///
82 /// # Examples
83 ///
84 /// ```
85 /// # use bump_scope::{Bump, bump_vec};
86 /// # let bump: Bump = Bump::new();
87 /// let mut vec = bump_vec![in ≎ 'a', 'b', 'c'];
88 /// let mut drain = vec.drain(..);
89 /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
90 /// let _ = drain.next().unwrap();
91 /// assert_eq!(drain.as_slice(), &['b', 'c']);
92 /// ```
93 #[must_use]
94 pub fn as_slice(&self) -> &[T] {
95 self.iter.as_slice()
96 }
97
98 /// Keep unyielded elements in the source slice.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// # use bump_scope::{Bump, bump_vec};
104 /// # let bump: Bump = Bump::new();
105 /// let mut vec = bump_vec![in ≎ 'a', 'b', 'c'];
106 /// let mut drain = vec.drain(..);
107 ///
108 /// assert_eq!(drain.next().unwrap(), 'a');
109 ///
110 /// // This call keeps 'b' and 'c' in the vec.
111 /// drain.keep_rest();
112 ///
113 /// // If we wouldn't call `keep_rest()`,
114 /// // `vec` would be empty.
115 /// assert_eq!(vec, ['b', 'c']);
116 /// ```
117 pub fn keep_rest(self) {
118 // At this moment layout looks like this:
119 //
120 // [head] [yielded by next] [unyielded] [yielded by next_back] [tail]
121 // ^-- start \_________/-- unyielded_len \____/-- self.tail_len
122 // ^-- unyielded_ptr ^-- tail
123 //
124 // Normally `Drop` impl would drop [unyielded] and then move [tail] to the `start`.
125 // Here we want to
126 // 1. Move [unyielded] to `start`
127 // 2. Move [tail] to a new start at `start + len(unyielded)`
128 // 3. Update length of the original vec to `len(head) + len(unyielded) + len(tail)`
129 // a. In case of ZST, this is the only thing we want to do
130 // 4. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do
131 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 // ZSTs have no identity, so we don't need to move them around.
143 if !T::IS_ZST {
144 let start_ptr = slice_ptr.add(start);
145
146 // memmove back unyielded elements
147 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 // memmove back untouched tail
155 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 /// Moves back the un-`Drain`ed elements to restore the original slice.
201 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 // memmove back untouched tail, update to new length
208 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 // ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount.
229 // this can be achieved by manipulating the slice length instead of moving values out from `iter`.
230 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 // Ensure elements are moved back into their appropriate places, even when dropping `iter` panics.
240 let _guard = DropGuard(self);
241
242 // Drops the remaining drained elements.
243 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}