bump_scope/
owned_slice.rs

1use core::{array, mem};
2
3#[cfg(feature = "alloc")]
4use core::mem::ManuallyDrop;
5
6#[cfg(feature = "alloc")]
7use alloc_crate::{
8    boxed::Box,
9    vec::{self, Vec},
10};
11
12use crate::{BumpAllocatorExt, BumpBox, BumpVec, FixedBumpVec, MutBumpVec, MutBumpVecRev, unsize_bump_box};
13
14mod drain;
15mod extract_if;
16mod into_iter;
17
18pub use drain::Drain;
19pub use extract_if::ExtractIf;
20pub use into_iter::IntoIter;
21
22/// A trait for objects that own a slice of elements.
23///
24/// For example `[T; N]`, `Vec<T>`, `Box<[T]>` and `vec::Drain<T>`.
25///
26/// This trait is used for the parameter of [`alloc_slice_move`], [`append`] and [`from_owned_slice_in`].
27///
28/// Any implementor of `TakeOwnedSlice` automatically implements this trait.
29///
30/// [`append`]: crate::BumpVec::append
31/// [`alloc_slice_move`]: crate::Bump::alloc_slice_move
32/// [`from_owned_slice_in`]: crate::BumpVec::from_owned_slice_in
33pub trait OwnedSlice {
34    /// The type of an element of this owned slice.
35    type Item;
36
37    /// A type that `Self` can convert into that implements `TakeOwnedSlice`.
38    type Take: TakeOwnedSlice<Item = Self::Item>;
39
40    /// Converts this type into one that implements `TakeOwnedSlice`.
41    fn into_take_owned_slice(self) -> Self::Take;
42}
43
44// every `TakeOwnedSlice` automatically implements `OwnedSlice`
45impl<T: TakeOwnedSlice> OwnedSlice for T {
46    type Item = <Self as TakeOwnedSlice>::Item;
47
48    type Take = Self;
49
50    fn into_take_owned_slice(self) -> Self::Take {
51        self
52    }
53}
54
55impl<T, const N: usize> OwnedSlice for [T; N] {
56    type Item = T;
57
58    type Take = array::IntoIter<T, N>;
59
60    fn into_take_owned_slice(self) -> Self::Take {
61        self.into_iter()
62    }
63}
64
65impl<'a, T, const N: usize> OwnedSlice for BumpBox<'a, [T; N]> {
66    type Item = T;
67
68    type Take = BumpBox<'a, [T]>;
69
70    fn into_take_owned_slice(self) -> Self::Take {
71        unsize_bump_box!(self)
72    }
73}
74
75#[cfg(feature = "alloc")]
76impl<T, const N: usize> OwnedSlice for Box<[T; N]> {
77    type Item = T;
78
79    type Take = Box<[T]>;
80
81    fn into_take_owned_slice(self) -> Self::Take {
82        self
83    }
84}
85
86/// A trait for objects which own a slice and can relinquish their ownership of all its elements at once.
87///
88/// Implementors of this trait must behave like a `Vec<T>` in the sense that they manage a slice they own.
89/// When the slice is "taken" using `take_owned_slice`, the implementor
90/// must relinquish ownership of its elements entirely, leaving behind an empty slice.
91///
92/// The goal of the safety conditions are so that a function like this is sound:
93/// ```
94/// # extern crate alloc;
95/// # use core::ptr::NonNull;
96/// # use alloc::vec::Vec;
97/// # use bump_scope::owned_slice::TakeOwnedSlice;
98/// fn append<T>(vec: &mut Vec<T>, mut to_append: impl TakeOwnedSlice<Item = T>) {
99///     let slice = NonNull::from(to_append.owned_slice_ref());
100///     vec.reserve(slice.len());
101///     
102///     unsafe {
103///         let src = slice.cast::<T>().as_ptr();
104///         let dst = vec.as_mut_ptr().add(vec.len());
105///         src.copy_to_nonoverlapping(dst, slice.len());
106///
107///         to_append.take_owned_slice();
108///         vec.set_len(vec.len() + slice.len());
109///     }
110/// }
111///
112/// # use alloc::string::ToString;
113/// # let mut vec = (0..3).map(|i| i.to_string()).collect::<Vec<_>>();
114/// # let mut to_append = (3..10).map(|i| i.to_string()).collect::<Vec<_>>();
115/// # append(&mut vec, &mut to_append);
116/// # assert_eq!(to_append.len(), 0);
117/// # assert_eq!(vec.len(), 10);
118/// # assert_eq!(vec, ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])
119/// ```
120///
121/// # Safety
122///
123/// The implementor must own a slice, that both of the methods operate on.
124/// Let's call it *the slice*.
125///
126/// - `owned_slice_ref` returns *the slice*.
127/// - `take_owned_slice` relinquishes the ownership of the slice.
128///   The elements of *the slice* **must not be dropped**.
129///   Once called, *the slice* becomes an empty slice.
130/// - Between calls to `owned_slice_ref` and `take_owned_slice`,
131///   the caller can assume that *the slice* won't change as long as the caller itself does not interact with the type.
132///   As such this trait must not be implemented for a type whose *slice* could change from a different thread for instance.
133///
134/// [set_len]: alloc_crate::vec::Vec::set_len
135/// [`owned_slice_ref`]: TakeOwnedSlice::owned_slice_ref
136/// [`take_owned_slice`]: TakeOwnedSlice::take_owned_slice
137pub unsafe trait TakeOwnedSlice {
138    /// The element type of the slice.
139    type Item;
140
141    /// Returns a slice of its elements.
142    fn owned_slice_ref(&self) -> &[Self::Item];
143
144    /// This will make the slice forget all of its elements.
145    ///
146    /// *Its elements* are the same elements referred to by [`owned_slice_ref`].
147    /// The caller is now responsible for dropping those elements.
148    ///
149    /// After calling this, `owned_slice_ref` will return a slice with a length of `0`.
150    ///
151    /// [`owned_slice_ref`]: Self::owned_slice_ref
152    fn take_owned_slice(&mut self);
153}
154
155unsafe impl<T: TakeOwnedSlice + ?Sized> TakeOwnedSlice for &mut T {
156    type Item = T::Item;
157
158    #[inline]
159    fn owned_slice_ref(&self) -> &[Self::Item] {
160        T::owned_slice_ref(self)
161    }
162
163    #[inline]
164    fn take_owned_slice(&mut self) {
165        T::take_owned_slice(self);
166    }
167}
168
169unsafe impl<T, const N: usize> TakeOwnedSlice for array::IntoIter<T, N> {
170    type Item = T;
171
172    #[inline]
173    fn owned_slice_ref(&self) -> &[Self::Item] {
174        self.as_slice()
175    }
176
177    #[inline]
178    fn take_owned_slice(&mut self) {
179        self.for_each(mem::forget);
180    }
181}
182
183unsafe impl<T> TakeOwnedSlice for BumpBox<'_, [T]> {
184    type Item = T;
185
186    #[inline]
187    fn owned_slice_ref(&self) -> &[Self::Item] {
188        self
189    }
190
191    #[inline]
192    fn take_owned_slice(&mut self) {
193        unsafe { self.set_len(0) }
194    }
195}
196
197unsafe impl<T> TakeOwnedSlice for FixedBumpVec<'_, T> {
198    type Item = T;
199
200    #[inline]
201    fn owned_slice_ref(&self) -> &[Self::Item] {
202        self
203    }
204
205    #[inline]
206    fn take_owned_slice(&mut self) {
207        unsafe { self.set_len(0) }
208    }
209}
210
211unsafe impl<T, A: BumpAllocatorExt> TakeOwnedSlice for BumpVec<T, A> {
212    type Item = T;
213
214    #[inline]
215    fn owned_slice_ref(&self) -> &[Self::Item] {
216        self
217    }
218
219    #[inline]
220    fn take_owned_slice(&mut self) {
221        unsafe { self.set_len(0) }
222    }
223}
224
225unsafe impl<T, A> TakeOwnedSlice for MutBumpVec<T, A> {
226    type Item = T;
227
228    #[inline]
229    fn owned_slice_ref(&self) -> &[Self::Item] {
230        self
231    }
232
233    #[inline]
234    fn take_owned_slice(&mut self) {
235        unsafe { self.set_len(0) }
236    }
237}
238
239unsafe impl<T, A> TakeOwnedSlice for MutBumpVecRev<T, A> {
240    type Item = T;
241
242    #[inline]
243    fn owned_slice_ref(&self) -> &[Self::Item] {
244        self
245    }
246
247    #[inline]
248    fn take_owned_slice(&mut self) {
249        unsafe { self.set_len(0) }
250    }
251}
252
253#[cfg(feature = "alloc")]
254unsafe impl<T> TakeOwnedSlice for Box<[T]> {
255    type Item = T;
256
257    #[inline]
258    fn owned_slice_ref(&self) -> &[Self::Item] {
259        self
260    }
261
262    #[inline]
263    fn take_owned_slice(&mut self) {
264        // We must not drop the elements but we must deallocate the slice itself.
265        let ptr = Box::into_raw(mem::take(self));
266        let forget_elements_box = unsafe { Box::<[ManuallyDrop<T>]>::from_raw(ptr as *mut [ManuallyDrop<T>]) };
267        drop(forget_elements_box);
268    }
269}
270
271#[cfg(feature = "alloc")]
272unsafe impl<T> TakeOwnedSlice for Vec<T> {
273    type Item = T;
274
275    #[inline]
276    fn owned_slice_ref(&self) -> &[Self::Item] {
277        self
278    }
279
280    #[inline]
281    fn take_owned_slice(&mut self) {
282        unsafe { self.set_len(0) }
283    }
284}
285
286#[cfg(feature = "alloc")]
287unsafe impl<T> TakeOwnedSlice for vec::IntoIter<T> {
288    type Item = T;
289
290    #[inline]
291    fn owned_slice_ref(&self) -> &[Self::Item] {
292        self.as_slice()
293    }
294
295    #[inline]
296    fn take_owned_slice(&mut self) {
297        self.for_each(mem::forget);
298    }
299}
300
301#[cfg(feature = "alloc")]
302unsafe impl<T> TakeOwnedSlice for vec::Drain<'_, T> {
303    type Item = T;
304
305    #[inline]
306    fn owned_slice_ref(&self) -> &[Self::Item] {
307        self.as_slice()
308    }
309
310    #[inline]
311    fn take_owned_slice(&mut self) {
312        self.for_each(mem::forget);
313    }
314}
315
316#[cfg(all(test, feature = "alloc"))]
317mod tests {
318    use crate::tests::Bump;
319
320    use super::*;
321
322    const _: () = {
323        const fn is_dyn_compatible<T: TakeOwnedSlice + ?Sized>() {}
324        is_dyn_compatible::<dyn TakeOwnedSlice<Item = i32>>();
325        is_dyn_compatible::<&mut dyn TakeOwnedSlice<Item = i32>>();
326    };
327
328    macro_rules! assert_implements {
329        ($($ty:ty)*) => {
330            const _: () = {
331                type T = i32;
332                const fn implements<S: OwnedSlice + ?Sized>() {}
333                $(implements::<$ty>();)*
334            };
335        };
336    }
337
338    assert_implements! {
339        &mut dyn TakeOwnedSlice<Item = T>
340
341        [T; 3]
342        BumpBox<[T; 3]>
343
344        BumpBox<[T]>
345        &mut BumpBox<[T]>
346        FixedBumpVec<T>
347        &mut FixedBumpVec<T>
348        BumpVec<T, &Bump>
349        &mut BumpVec<T, &Bump>
350        MutBumpVec<T, &mut Bump>
351        &mut MutBumpVec<T, &mut Bump>
352        MutBumpVecRev<T, &mut Bump>
353        &mut MutBumpVecRev<T, &mut Bump>
354        BumpVec<T, Bump>
355        &mut BumpVec<T, Bump>
356        MutBumpVec<T, Bump>
357        &mut MutBumpVec<T, Bump>
358        MutBumpVecRev<T, Bump>
359        &mut MutBumpVecRev<T, Bump>
360    }
361
362    #[cfg(feature = "alloc")]
363    assert_implements! {
364        Box<[T; 3]>
365
366        Box<[T]>
367        &mut Box<[T]>
368        Vec<T>
369        &mut Vec<T>
370    }
371}