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