rkyv/util/
scratch_vec.rs

1use crate::ser::ScratchSpace;
2use core::{
3    alloc::Layout,
4    borrow::{Borrow, BorrowMut},
5    fmt,
6    mem::MaybeUninit,
7    ops,
8    ptr::NonNull,
9    slice,
10};
11
12/// A vector view into serializer scratch space.
13pub struct ScratchVec<T> {
14    ptr: NonNull<T>,
15    cap: usize,
16    len: usize,
17}
18
19impl<T> Drop for ScratchVec<T> {
20    fn drop(&mut self) {
21        for i in 0..self.len {
22            unsafe {
23                core::ptr::drop_in_place(self.ptr.as_ptr().add(i));
24            }
25        }
26    }
27}
28
29// SAFETY: ScratchVec is safe to send to another thread is T is safe to send to another thread
30unsafe impl<T: Send> Send for ScratchVec<T> {}
31
32// SAFETY: ScratchVec is safe to share between threads if T is safe to share between threads
33unsafe impl<T: Sync> Sync for ScratchVec<T> {}
34
35impl<T> ScratchVec<T> {
36    /// Constructs a new, empty `ScratchVec` with the specified capacity.
37    ///
38    /// The vector will be able to hold exactly `capacity` elements. If `capacity` is 0, the vector
39    /// will not allocate.
40    ///
41    /// # Safety
42    ///
43    /// - The vector must not outlive the given scratch space.
44    /// - Vectors must be dropped in the reverse order they are allocated.
45    #[inline]
46    pub unsafe fn new<S: ScratchSpace + ?Sized>(
47        scratch_space: &mut S,
48        capacity: usize,
49    ) -> Result<Self, S::Error> {
50        let layout = Layout::array::<T>(capacity).unwrap();
51        if layout.size() == 0 {
52            Ok(Self {
53                ptr: NonNull::dangling(),
54                cap: capacity,
55                len: 0,
56            })
57        } else {
58            let ptr = scratch_space.push_scratch(layout)?;
59            Ok(Self {
60                ptr: ptr.cast(),
61                cap: capacity,
62                len: 0,
63            })
64        }
65    }
66
67    /// Frees the memory associated with the scratch vec and releases it back to the scratch space.
68    ///
69    /// This must be called when serialization succeeds, but may be omitted when serialization
70    /// fails. In that case, the elements of the scratch vec will be dropped but the memory will not
71    /// be popped. It is the duty of the scratch space in that case to ensure that memory resources
72    /// are properly cleaned up.
73    ///
74    /// # Safety
75    ///
76    /// The given scratch space must be the same one used to allocate the scratch vec.
77    #[inline]
78    pub unsafe fn free<S: ScratchSpace + ?Sized>(
79        self,
80        scratch_space: &mut S,
81    ) -> Result<(), S::Error> {
82        let layout = self.layout();
83        if layout.size() != 0 {
84            let ptr = self.ptr.cast();
85            core::mem::drop(self);
86            scratch_space.pop_scratch(ptr, layout)?;
87        }
88        Ok(())
89    }
90
91    #[inline]
92    fn layout(&self) -> Layout {
93        Layout::array::<T>(self.cap).unwrap()
94    }
95
96    /// Clears the vector, removing all values.
97    ///
98    /// Note that this method has no effect on the allocated capacity of the vector.
99    #[inline]
100    pub fn clear(&mut self) {
101        self.len = 0;
102    }
103
104    /// Returns an unsafe mutable pointer to the vector's buffer.
105    ///
106    /// The caller must ensure that the vector outlives the pointer this function returns, or else
107    /// it will end up pointing to garbage.
108    #[inline]
109    pub fn as_mut_ptr(&mut self) -> *mut T {
110        self.ptr.as_ptr()
111    }
112
113    /// Extracts a mutable slice of the entire vector.
114    ///
115    /// Equivalent to `&mut s[..]`.
116    #[inline]
117    pub fn as_mut_slice(&mut self) -> &mut [T] {
118        unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
119    }
120
121    /// Returns a raw pointer to the vector's buffer.
122    ///
123    /// The caller must ensure that the vector outlives the pointer this functions returns, or else
124    /// it will end up pointing to garbage.
125    ///
126    /// The caller must also ensure that the memory the pointer (non-transitively) points to is
127    /// never written to (except inside an `UnsafeCell`) using this pointer or any pointer derived
128    /// from it. If you need to mutate the contents of the slice, use
129    /// [`as_mut_ptr`](ScratchVec::as_mut_ptr).
130    #[inline]
131    pub fn as_ptr(&self) -> *const T {
132        self.ptr.as_ptr()
133    }
134
135    /// Extracts a slice containing the entire vector.
136    ///
137    /// Equivalent to `&s[..]`.
138    #[inline]
139    pub fn as_slice(&self) -> &[T] {
140        unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
141    }
142
143    /// Returns the number of elements the vector can hole without reallocating.
144    #[inline]
145    pub fn capacity(&self) -> usize {
146        self.cap
147    }
148
149    /// Ensures that there is capacity for at least `additional` more elements to be inserted into
150    /// the `ScratchVec`.
151    ///
152    /// # Panics
153    ///
154    /// Panics if the required capacity exceeds the available capacity.
155    #[inline]
156    pub fn reserve(&mut self, additional: usize) {
157        if self.len + additional > self.cap {
158            panic!("reserve requested more capacity than the scratch vec has available");
159        }
160    }
161
162    /// Returns `true` if the vector contains no elements.
163    #[inline]
164    pub fn is_empty(&self) -> bool {
165        self.len == 0
166    }
167
168    /// Returns the number of elements in the vector, also referred to as its `length`.
169    #[inline]
170    pub fn len(&self) -> usize {
171        self.len
172    }
173
174    /// Copies and appends all elements in a slice to the `ScratchVec`.
175    ///
176    /// The elements of the slice are appended in-order.
177    #[inline]
178    pub fn extend_from_slice(&mut self, other: &[T]) {
179        if !other.is_empty() {
180            self.reserve(other.len());
181            unsafe {
182                core::ptr::copy_nonoverlapping(
183                    other.as_ptr(),
184                    self.as_mut_ptr().add(self.len()),
185                    other.len(),
186                );
187            }
188            self.len += other.len();
189        }
190    }
191
192    /// Removes the last element from a vector and returns it, or `None` if it is empty.
193    #[inline]
194    pub fn pop(&mut self) -> Option<T> {
195        if self.len == 0 {
196            None
197        } else {
198            unsafe {
199                self.len -= 1;
200                Some(self.as_ptr().add(self.len()).read())
201            }
202        }
203    }
204
205    /// Appends an element to the back of a collection.
206    #[inline]
207    pub fn push(&mut self, value: T) {
208        unsafe {
209            self.reserve(1);
210            self.as_mut_ptr().add(self.len).write(value);
211            self.len += 1;
212        }
213    }
214
215    /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
216    /// given `AlignedVec`. After calling `reserve_exact`, capacity will be greater than or equal
217    /// to `self.len() + additional`. Does nothing if the capacity is already sufficient.
218    ///
219    /// # Panics
220    ///
221    /// Panics if the required capacity exceeds the available capacity.
222    #[inline]
223    pub fn reserve_exact(&mut self, additional: usize) {
224        self.reserve(additional);
225    }
226
227    /// Forces the length of the vector to `new_len`.
228    ///
229    /// This is a low-level operation that maintains none of the normal invariants of the type.
230    ///
231    /// # Safety
232    ///
233    /// - `new_len` must be less than or equal to [`capacity()`](ScratchVec::capacity)
234    /// - The elements at `old_len..new_len` must be initialized
235    #[inline]
236    pub unsafe fn set_len(&mut self, new_len: usize) {
237        debug_assert!(new_len <= self.capacity());
238
239        self.len = new_len;
240    }
241
242    // This is taken from `slice::range`, which is not yet stable.
243    #[inline]
244    fn drain_range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
245    where
246        R: ops::RangeBounds<usize>,
247    {
248        let len = bounds.end;
249
250        let start: ops::Bound<&usize> = range.start_bound();
251        let start = match start {
252            ops::Bound::Included(&start) => start,
253            ops::Bound::Excluded(start) => start
254                .checked_add(1)
255                .unwrap_or_else(|| panic!("attempted to index slice from after maximum usize")),
256            ops::Bound::Unbounded => 0,
257        };
258
259        let end: ops::Bound<&usize> = range.end_bound();
260        let end = match end {
261            ops::Bound::Included(end) => end
262                .checked_add(1)
263                .unwrap_or_else(|| panic!("attempted to index slice up to maximum usize")),
264            ops::Bound::Excluded(&end) => end,
265            ops::Bound::Unbounded => len,
266        };
267
268        if start > end {
269            panic!("slice index starts at {} but ends at {}", start, end);
270        }
271        if end > len {
272            panic!(
273                "range start index {} out of range for slice of length {}",
274                end, len
275            );
276        }
277
278        ops::Range { start, end }
279    }
280
281    /// Creates a draining iterator that removes the specified range in the vector and yields the
282    /// removed items.
283    ///
284    /// When the iterator **is** dropped, all elements in the range are removed from the vector,
285    /// even if the iterator was not fully consumed. If the iterator **is not** dropped (with
286    /// `mem::forget` for example), it is unspecified how many elements are removed.
287    ///
288    /// # Panics
289    ///
290    /// Panics if the starting point is greater than the end point or if the end point is greater
291    /// than the length of the vector.
292    #[inline]
293    pub fn drain<R: ops::RangeBounds<usize>>(&mut self, range: R) -> Drain<'_, T> {
294        let len = self.len();
295        let ops::Range { start, end } = Self::drain_range(range, ..len);
296
297        unsafe {
298            self.set_len(start);
299            let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start);
300            Drain {
301                tail_start: end,
302                tail_len: len - end,
303                iter: range_slice.iter(),
304                vec: NonNull::from(self),
305            }
306        }
307    }
308}
309
310impl<T> ScratchVec<MaybeUninit<T>> {
311    /// Assuming that all the elements are initialized, removes the `MaybeUninit` wrapper from the
312    /// vector.
313    ///
314    /// # Safety
315    ///
316    /// It is up to the caller to guarantee that the `MaybeUninit<T>` elements really are in an
317    /// initialized state. Calling this when the content is not yet fully initialized causes
318    /// undefined behavior.
319    #[inline]
320    pub fn assume_init(self) -> ScratchVec<T> {
321        ScratchVec {
322            ptr: self.ptr.cast(),
323            cap: self.cap,
324            len: self.len,
325        }
326    }
327}
328
329impl<T> AsMut<[T]> for ScratchVec<T> {
330    #[inline]
331    fn as_mut(&mut self) -> &mut [T] {
332        self.as_mut_slice()
333    }
334}
335
336impl<T> AsRef<[T]> for ScratchVec<T> {
337    #[inline]
338    fn as_ref(&self) -> &[T] {
339        self.as_slice()
340    }
341}
342
343impl<T> Borrow<[T]> for ScratchVec<T> {
344    #[inline]
345    fn borrow(&self) -> &[T] {
346        self.as_slice()
347    }
348}
349
350impl<T> BorrowMut<[T]> for ScratchVec<T> {
351    #[inline]
352    fn borrow_mut(&mut self) -> &mut [T] {
353        self.as_mut_slice()
354    }
355}
356
357impl<T: fmt::Debug> fmt::Debug for ScratchVec<T> {
358    #[inline]
359    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360        self.as_slice().fmt(f)
361    }
362}
363
364impl<T> ops::Deref for ScratchVec<T> {
365    type Target = [T];
366
367    #[inline]
368    fn deref(&self) -> &Self::Target {
369        self.as_slice()
370    }
371}
372
373impl<T> ops::DerefMut for ScratchVec<T> {
374    #[inline]
375    fn deref_mut(&mut self) -> &mut Self::Target {
376        self.as_mut_slice()
377    }
378}
379
380impl<T, I: slice::SliceIndex<[T]>> ops::Index<I> for ScratchVec<T> {
381    type Output = <I as slice::SliceIndex<[T]>>::Output;
382
383    #[inline]
384    fn index(&self, index: I) -> &Self::Output {
385        &self.as_slice()[index]
386    }
387}
388
389impl<T, I: slice::SliceIndex<[T]>> ops::IndexMut<I> for ScratchVec<T> {
390    #[inline]
391    fn index_mut(&mut self, index: I) -> &mut Self::Output {
392        &mut self.as_mut_slice()[index]
393    }
394}
395
396/// A draining iterator for `ScratchVec<T>`.
397///
398/// This `struct` is created by [`ScratchVec::drain`]. See its documentation for more.
399pub struct Drain<'a, T: 'a> {
400    tail_start: usize,
401    tail_len: usize,
402    iter: slice::Iter<'a, T>,
403    vec: NonNull<ScratchVec<T>>,
404}
405
406impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
407    #[inline]
408    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409        f.debug_tuple("Drain").field(&self.iter.as_slice()).finish()
410    }
411}
412
413impl<T> Drain<'_, T> {
414    /// Returns the remaining items of this iterator as a slice.
415    #[inline]
416    pub fn as_slice(&self) -> &[T] {
417        self.iter.as_slice()
418    }
419}
420
421impl<T> AsRef<[T]> for Drain<'_, T> {
422    fn as_ref(&self) -> &[T] {
423        self.as_slice()
424    }
425}
426
427impl<T> Iterator for Drain<'_, T> {
428    type Item = T;
429
430    #[inline]
431    fn next(&mut self) -> Option<T> {
432        self.iter
433            .next()
434            .map(|elt| unsafe { core::ptr::read(elt as *const _) })
435    }
436
437    #[inline]
438    fn size_hint(&self) -> (usize, Option<usize>) {
439        self.iter.size_hint()
440    }
441}
442
443impl<T> DoubleEndedIterator for Drain<'_, T> {
444    #[inline]
445    fn next_back(&mut self) -> Option<T> {
446        self.iter
447            .next_back()
448            .map(|elt| unsafe { core::ptr::read(elt as *const _) })
449    }
450}
451
452impl<T> Drop for Drain<'_, T> {
453    fn drop(&mut self) {
454        /// Continues dropping the remaining elements in the `Drain`, then moves back the
455        /// un-`Drain`ed elements to restore the original `Vec`.
456        struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>);
457
458        impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> {
459            fn drop(&mut self) {
460                // Continue the same loop we have below. If the loop already finished, this does
461                // nothing.
462                self.0.for_each(drop);
463
464                if self.0.tail_len > 0 {
465                    unsafe {
466                        let source_vec = self.0.vec.as_mut();
467                        // memmove back untouched tail, update to new length
468                        let start = source_vec.len();
469                        let tail = self.0.tail_start;
470                        if tail != start {
471                            let src = source_vec.as_ptr().add(tail);
472                            let dst = source_vec.as_mut_ptr().add(start);
473                            core::ptr::copy(src, dst, self.0.tail_len);
474                        }
475                        source_vec.set_len(start + self.0.tail_len);
476                    }
477                }
478            }
479        }
480
481        // exhaust self first
482        while let Some(item) = self.next() {
483            let guard = DropGuard(self);
484            drop(item);
485            core::mem::forget(guard);
486        }
487
488        // Drop a `DropGuard` to move back the non-drained tail of `self`.
489        DropGuard(self);
490    }
491}
492
493impl<T> ExactSizeIterator for Drain<'_, T> {}
494
495impl<T> core::iter::FusedIterator for Drain<'_, T> {}