Skip to main content

bevy_platform/collections/
aligned_vec.rs

1//! Provides [`AlignedVec`] based on [rkyv::util::AlignedVec](https://github.com/rkyv/rkyv/blob/main/rkyv/src/util/alloc/aligned_vec.rs)'s implementation but the alignment can be set at runtime.
2//!
3//! The original source code, adapted here, is copyright 2021 David Koloski, used here under the MIT License.
4#![expect(unsafe_code, reason = "This struct needs to interact with raw memory")]
5
6use alloc::alloc::{alloc, dealloc, handle_alloc_error, realloc};
7#[cfg(feature = "bytemuck")]
8use alloc::vec::Vec;
9use core::{
10    alloc::Layout,
11    borrow::{Borrow, BorrowMut},
12    fmt,
13    mem::ManuallyDrop,
14    ops::{Deref, DerefMut, Index, IndexMut},
15    ptr::NonNull,
16    slice,
17};
18
19/// A vector of bytes that dynamically aligns its memory to the specified alignment.
20///
21/// ```
22/// # use bevy_platform::collections::AlignedVec;
23/// let bytes = AlignedVec::with_capacity(4096, 1);
24/// assert_eq!(bytes.as_ptr().align_offset(4096), 0);
25/// ```
26pub struct AlignedVec {
27    ptr: NonNull<u8>,
28    align: usize,
29    cap: usize,
30    len: usize,
31}
32
33impl Drop for AlignedVec {
34    fn drop(&mut self) {
35        if self.cap != 0 {
36            // SAFETY: both `ptr` and `layout` are valid
37            unsafe {
38                dealloc(self.ptr.as_ptr(), self.layout());
39            }
40        }
41    }
42}
43
44impl AlignedVec {
45    /// The alignment of the vector
46    #[inline]
47    pub fn alignment(&self) -> usize {
48        self.align
49    }
50
51    /// Maximum valid size of [`Layout`].
52    ///
53    /// Dictated by the requirements of [`Layout::from_size_align`]:
54    /// `size`, when rounded up to the nearest multiple of `align`, must not overflow `isize`.
55    #[inline]
56    const fn max_size_for_alignment(align: usize) -> usize {
57        isize::MAX as usize + 1 - align
58    }
59
60    /// Maximum valid capacity of the vector with `self.align`.
61    #[inline]
62    fn max_capacity(&self) -> usize {
63        Self::max_size_for_alignment(self.alignment())
64    }
65
66    /// Constructs a new, empty `AlignedVec`.
67    ///
68    /// The vector will not allocate until elements are pushed into it.
69    ///
70    /// # Examples
71    /// ```
72    /// # use bevy_platform::collections::AlignedVec;
73    /// let mut vec = AlignedVec::new(16);
74    /// ```
75    #[inline]
76    pub fn new(align: usize) -> Self {
77        Self::with_capacity(align, 0)
78    }
79
80    /// Constructs a new, empty `AlignedVec` with the specified alignment and capacity.
81    ///
82    /// The vector will be able to hold exactly `capacity` bytes without
83    /// reallocating. If `capacity` is 0, the vector will not allocate.
84    ///
85    /// # Examples
86    /// ```
87    /// # use bevy_platform::collections::AlignedVec;
88    /// let mut vec = AlignedVec::with_capacity(16, 10);
89    ///
90    /// // The vector contains no items, even though it has capacity for more
91    /// assert_eq!(vec.len(), 0);
92    /// assert_eq!(vec.capacity(), 10);
93    ///
94    /// // These are all done without reallocating...
95    /// for i in 0..10 {
96    ///     vec.push(i);
97    /// }
98    /// assert_eq!(vec.len(), 10);
99    /// assert_eq!(vec.capacity(), 10);
100    ///
101    /// // ...but this may make the vector reallocate
102    /// vec.push(11);
103    /// assert_eq!(vec.len(), 11);
104    /// assert!(vec.capacity() >= 11);
105    /// ```
106    #[inline]
107    pub fn with_capacity(align: usize, capacity: usize) -> Self {
108        assert!(align > 0, "align must be 1 or more");
109        assert!(align.is_power_of_two(), "align must be a power of 2");
110        // As `align` has to be a power of 2, this caps `align` at a max
111        // of `(isize::MAX + 1) / 2` (1 GiB on 32-bit systems).
112        assert!(
113            align < isize::MAX as usize,
114            "align must be less than isize::MAX"
115        );
116
117        if capacity == 0 {
118            Self {
119                ptr: NonNull::without_provenance(
120                    // SAFETY: `align` is checked to be non-zero.
121                    unsafe { core::num::NonZero::<usize>::new_unchecked(align) },
122                ),
123                align,
124                cap: 0,
125                len: 0,
126            }
127        } else {
128            assert!(
129                capacity <= Self::max_size_for_alignment(align),
130                "`capacity` when rounded up to the nearest multiple of align overflows `isize`"
131            );
132
133            let ptr = {
134                // SAFETY: align > 0, align is power of two and capacity <= max size for alignment.
135                let layout = unsafe { Layout::from_size_align_unchecked(capacity, align) };
136                // SAFETY: capacity is not zero.
137                let ptr = unsafe { alloc(layout) };
138                if ptr.is_null() {
139                    handle_alloc_error(layout);
140                }
141                // SAFETY: ptr is not null
142                unsafe { NonNull::new_unchecked(ptr) }
143            };
144
145            Self {
146                ptr,
147                align,
148                cap: capacity,
149                len: 0,
150            }
151        }
152    }
153
154    #[inline]
155    fn layout(&self) -> Layout {
156        // SAFETY: `cap` and `align` are valid for layout
157        unsafe { Layout::from_size_align_unchecked(self.cap, self.alignment()) }
158    }
159
160    /// Clears the vector, removing all values.
161    ///
162    /// Note that this method has no effect on the allocated capacity of the
163    /// vector.
164    ///
165    /// # Examples
166    /// ```
167    /// # use bevy_platform::collections::AlignedVec;
168    /// let mut v = AlignedVec::new(16);
169    /// v.extend_from_slice(&[1, 2, 3, 4]);
170    ///
171    /// v.clear();
172    ///
173    /// assert!(v.is_empty());
174    /// ```
175    #[inline]
176    pub fn clear(&mut self) {
177        self.len = 0;
178    }
179
180    /// Change capacity of vector.
181    ///
182    /// Will set capacity to exactly `new_cap`.
183    /// Can be used to either grow or shrink capacity.
184    /// Backing memory will be reallocated.
185    ///
186    /// Usually the safe methods `reserve` or `reserve_exact` are a better
187    /// choice. This method only exists as a micro-optimization for very
188    /// performance-sensitive code where the calculation of capacity
189    /// required has already been performed, and you want to avoid doing it
190    /// again, or if you want to implement a different growth strategy.
191    ///
192    /// # Safety
193    ///
194    /// - `new_cap` when rounded up to the nearest multiple of align must not overflow `isize`
195    /// - `new_cap` must be greater than or equal to [`len()`](AlignedVec::len)
196    pub unsafe fn change_capacity(&mut self, new_cap: usize) {
197        debug_assert!(new_cap <= self.max_capacity());
198        debug_assert!(new_cap >= self.len);
199
200        if new_cap > 0 {
201            let new_ptr = if self.cap > 0 {
202                // SAFETY:
203                // - `self.ptr` is currently allocated because `self.cap` is
204                //   greater than zero.
205                // - `self.layout()` always matches the layout used to allocate
206                //   the current block of memory.
207                // - We checked that `new_cap` is greater than zero.
208                let new_ptr = unsafe { realloc(self.ptr.as_ptr(), self.layout(), new_cap) };
209                if new_ptr.is_null() {
210                    // SAFETY:
211                    // - `self.align` is always guaranteed to be a nonzero power
212                    //   of two.
213                    // - We checked that `new_cap` doesn't overflow `isize` when
214                    //   rounded up to the nearest power of two.
215                    let layout =
216                        unsafe { Layout::from_size_align_unchecked(new_cap, self.alignment()) };
217                    handle_alloc_error(layout);
218                }
219                new_ptr
220            } else {
221                // SAFETY:
222                // - `self.align` is always guaranteed to be a nonzero power of
223                //   two.
224                // - We checked that `new_cap` doesn't overflow `isize` when
225                //   rounded up to the nearest power of two.
226                let layout =
227                    unsafe { Layout::from_size_align_unchecked(new_cap, self.alignment()) };
228                // SAFETY: We checked that `new_cap` has non-zero size.
229                let new_ptr = unsafe { alloc(layout) };
230                if new_ptr.is_null() {
231                    handle_alloc_error(layout);
232                }
233                new_ptr
234            };
235            // SAFETY: We checked that `new_ptr` is non-null in each of the
236            // branches.
237            self.ptr = unsafe { NonNull::new_unchecked(new_ptr) };
238            self.cap = new_cap;
239        } else if self.cap > 0 {
240            // SAFETY: Because the capacity is nonzero, `self.ptr` points to a
241            // currently-allocated memory block. All memory blocks are allocated
242            // with a layout of `self.layout()`.
243            unsafe {
244                dealloc(self.ptr.as_ptr(), self.layout());
245            }
246            self.ptr = NonNull::without_provenance(
247                // SAFETY: `align` is checked to be non-zero.
248                unsafe { core::num::NonZero::<usize>::new_unchecked(self.alignment()) },
249            );
250            self.cap = 0;
251        }
252    }
253
254    /// Shrinks the capacity of the vector as much as possible.
255    ///
256    /// It will drop down as close as possible to the length but the allocator
257    /// may still inform the vector that there is space for a few more
258    /// elements.
259    ///
260    /// # Examples
261    /// ```
262    /// # use bevy_platform::collections::AlignedVec;
263    /// let mut vec = AlignedVec::with_capacity(16, 10);
264    /// vec.extend_from_slice(&[1, 2, 3]);
265    /// assert_eq!(vec.capacity(), 10);
266    /// vec.shrink_to_fit();
267    /// assert!(vec.capacity() >= 3);
268    ///
269    /// vec.clear();
270    /// vec.shrink_to_fit();
271    /// assert!(vec.capacity() == 0);
272    /// ```
273    #[inline]
274    pub fn shrink_to_fit(&mut self) {
275        if self.cap != self.len {
276            // SAFETY: New capacity is equal to length, and cannot exceed max as it's shrinking
277            unsafe { self.change_capacity(self.len) };
278        }
279    }
280
281    /// Returns an unsafe mutable pointer to the vector's buffer.
282    ///
283    /// The caller must ensure that the vector outlives the pointer this
284    /// function returns, or else it will end up pointing to garbage.
285    /// Modifying the vector may cause its buffer to be reallocated, which
286    /// would also make any pointers to it invalid.
287    ///
288    /// # Examples
289    /// ```
290    /// # use bevy_platform::collections::AlignedVec;
291    /// // Allocate 1-aligned vector big enough for 4 bytes.
292    /// let size = 4;
293    /// let mut x = AlignedVec::with_capacity(1, size);
294    /// let x_ptr = x.as_mut_ptr();
295    ///
296    /// // Initialize elements via raw pointer writes, then set length.
297    /// unsafe {
298    ///     for i in 0..size {
299    ///         *x_ptr.add(i) = i as u8;
300    ///     }
301    ///     x.set_len(size);
302    /// }
303    /// assert_eq!(&*x, &[0, 1, 2, 3]);
304    /// ```
305    #[inline]
306    pub fn as_mut_ptr(&mut self) -> *mut u8 {
307        self.ptr.as_ptr()
308    }
309
310    /// Extracts a mutable slice of the entire vector.
311    ///
312    /// Equivalent to `&mut s[..]`.
313    ///
314    /// # Examples
315    /// ```
316    /// # use bevy_platform::collections::AlignedVec;
317    /// let mut vec = AlignedVec::new(16);
318    /// vec.extend_from_slice(&[1, 2, 3, 4, 5]);
319    /// assert_eq!(vec.as_mut_slice().len(), 5);
320    /// for i in 0..5 {
321    ///     assert_eq!(vec.as_mut_slice()[i], i as u8 + 1);
322    ///     vec.as_mut_slice()[i] = i as u8;
323    ///     assert_eq!(vec.as_mut_slice()[i], i as u8);
324    /// }
325    /// ```
326    #[inline]
327    pub fn as_mut_slice(&mut self) -> &mut [u8] {
328        // SAFETY: `ptr` and `len` are valid to construct slice
329        unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
330    }
331
332    /// Returns a raw pointer to the vector's buffer.
333    ///
334    /// The caller must ensure that the vector outlives the pointer this
335    /// function returns, or else it will end up pointing to garbage.
336    /// Modifying the vector may cause its buffer to be reallocated, which
337    /// would also make any pointers to it invalid.
338    ///
339    /// The caller must also ensure that the memory the pointer
340    /// (non-transitively) points to is never written to (except inside an
341    /// `UnsafeCell`) using this pointer or any pointer derived from it. If
342    /// you need to mutate the contents of the slice, use
343    /// [`as_mut_ptr`](AlignedVec::as_mut_ptr).
344    ///
345    /// # Examples
346    /// ```
347    /// # use bevy_platform::collections::AlignedVec;
348    /// let mut x = AlignedVec::new(16);
349    /// x.extend_from_slice(&[1, 2, 4]);
350    /// let x_ptr = x.as_ptr();
351    ///
352    /// unsafe {
353    ///     for i in 0..x.len() {
354    ///         assert_eq!(*x_ptr.add(i), 1 << i);
355    ///     }
356    /// }
357    /// ```
358    #[inline]
359    pub fn as_ptr(&self) -> *const u8 {
360        self.ptr.as_ptr()
361    }
362
363    /// Extracts a slice containing the entire vector.
364    ///
365    /// Equivalent to `&s[..]`.
366    ///
367    /// # Examples
368    /// ```
369    /// # use bevy_platform::collections::AlignedVec;
370    /// let mut vec = AlignedVec::new(16);
371    /// vec.extend_from_slice(&[1, 2, 3, 4, 5]);
372    /// assert_eq!(vec.as_slice().len(), 5);
373    /// for i in 0..5 {
374    ///     assert_eq!(vec.as_slice()[i], i as u8 + 1);
375    /// }
376    /// ```
377    #[inline]
378    pub fn as_slice(&self) -> &[u8] {
379        // SAFETY: `ptr` and `len` are valid to construct slice
380        unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
381    }
382
383    /// Returns the number of elements the vector can hold without reallocating.
384    ///
385    /// # Examples
386    /// ```
387    /// # use bevy_platform::collections::AlignedVec;
388    /// let vec = AlignedVec::with_capacity(16, 10);
389    /// assert_eq!(vec.capacity(), 10);
390    /// ```
391    #[inline]
392    pub fn capacity(&self) -> usize {
393        self.cap
394    }
395
396    /// Reserves capacity for at least `additional` more bytes to be inserted
397    /// into the given `AlignedVec`. The collection may reserve more space
398    /// to avoid frequent reallocations. After calling `reserve`, capacity
399    /// will be greater than or equal to `self.len() + additional`. Does
400    /// nothing if capacity is already sufficient.
401    ///
402    /// # Panics
403    ///
404    /// Panics if the new capacity when rounded up to the nearest multiple of align overflow `isize`.
405    ///
406    /// # Examples
407    /// ```
408    /// # use bevy_platform::collections::AlignedVec;
409    ///
410    /// let mut vec = AlignedVec::new(16);
411    /// vec.push(1);
412    /// vec.reserve(10);
413    /// assert!(vec.capacity() >= 11);
414    /// ```
415    pub fn reserve(&mut self, additional: usize) {
416        // Cannot wrap because capacity always exceeds len,
417        // but avoids having to handle potential overflow here
418        let remaining = self.cap.wrapping_sub(self.len);
419        if additional > remaining {
420            self.do_reserve(additional);
421        }
422    }
423
424    /// Extend capacity after `reserve` has found it's necessary.
425    ///
426    /// Actually performing the extension is in this separate function marked
427    /// `#[cold]` to hint to compiler that this branch is not often taken.
428    /// This keeps the path for common case where capacity is already sufficient
429    /// as fast as possible, and makes `reserve` more likely to be inlined.
430    /// This is the same trick that Rust's `Vec::reserve` uses.
431    #[cold]
432    fn do_reserve(&mut self, additional: usize) {
433        let new_cap = self
434            .len
435            .checked_add(additional)
436            .expect("cannot reserve a larger AlignedVec");
437        // SAFETY: `do_reserve` is only called when capacity grows
438        unsafe { self.grow_capacity_to(new_cap) };
439    }
440
441    /// Grows total capacity of vector to `new_cap` or more.
442    ///
443    /// Capacity after this call will be `new_cap` rounded up to next power of
444    /// 2, unless that would exceed maximum capacity, in which case capacity
445    /// is capped at the maximum.
446    ///
447    /// This is same growth strategy used by `reserve`, `push` and
448    /// `extend_from_slice`.
449    ///
450    /// Usually the safe methods `reserve` or `reserve_exact` are a better
451    /// choice. This method only exists as a micro-optimization for very
452    /// performance-sensitive code where the calculation of capacity
453    /// required has already been performed, and you want to avoid doing it
454    /// again.
455    ///
456    /// Maximum capacity is `isize::MAX + 1 - self.align` bytes.
457    ///
458    /// # Panics
459    ///
460    /// Panics if the new capacity when rounded up to the nearest multiple of align overflow `isize`.
461    ///
462    /// # Safety
463    ///
464    /// - `new_cap` must be greater than current
465    ///   [`capacity()`](AlignedVec::capacity)
466    ///
467    /// # Examples
468    /// ```
469    /// # use bevy_platform::collections::AlignedVec;
470    ///
471    /// let mut vec = AlignedVec::new(16);
472    /// vec.push(1);
473    /// unsafe { vec.grow_capacity_to(50) };
474    /// assert_eq!(vec.len(), 1);
475    /// assert_eq!(vec.capacity(), 64);
476    /// ```
477    pub unsafe fn grow_capacity_to(&mut self, new_cap: usize) {
478        debug_assert!(new_cap > self.cap);
479
480        let new_cap = if new_cap > (isize::MAX as usize + 1) >> 1 {
481            // Rounding up to next power of 2 would result in `isize::MAX + 1`
482            // or higher, which exceeds max capacity. So cap at max
483            // instead.
484            assert!(
485                new_cap <= self.max_capacity(),
486                "cannot reserve a larger AlignedVec"
487            );
488            self.max_capacity()
489        } else {
490            // Cannot overflow due to check above
491            new_cap.next_power_of_two()
492        };
493        let min_non_zero_cap = 8;
494        let new_cap = core::cmp::max(new_cap, min_non_zero_cap);
495        // SAFETY: We just checked that `new_cap` is greater than or equal to
496        // `len` and less than or equal to `max_capacity`.
497        unsafe {
498            self.change_capacity(new_cap);
499        }
500    }
501
502    /// Resizes the Vec in-place so that len is equal to `new_len`.
503    ///
504    /// If `new_len` is greater than len, the Vec is extended by the difference,
505    /// with each additional slot filled with value. If `new_len` is less than
506    /// len, the Vec is simply truncated.
507    ///
508    /// # Panics
509    ///
510    /// Panics if the new length when rounded up to the nearest multiple of align overflow `isize`.
511    ///
512    /// # Examples
513    /// ```
514    /// # use bevy_platform::collections::AlignedVec;
515    ///
516    /// let mut vec = AlignedVec::new(16);
517    /// vec.push(3);
518    /// vec.resize(3, 2);
519    /// assert_eq!(vec.as_slice(), &[3, 2, 2]);
520    ///
521    /// let mut vec = AlignedVec::new(16);
522    /// vec.extend_from_slice(&[1, 2, 3, 4]);
523    /// vec.resize(2, 0);
524    /// assert_eq!(vec.as_slice(), &[1, 2]);
525    /// ```
526    pub fn resize(&mut self, new_len: usize, value: u8) {
527        if new_len > self.len {
528            let additional = new_len - self.len;
529            self.reserve(additional);
530            // SAFETY: ptr is valid to write after `reserve`
531            unsafe {
532                core::ptr::write_bytes(self.ptr.as_ptr().add(self.len), value, additional);
533            }
534        }
535        // SAFETY: required elements are initialized for `new_len`
536        unsafe {
537            self.set_len(new_len);
538        }
539    }
540
541    /// Returns `true` if the vector contains no elements.
542    ///
543    /// # Examples
544    /// ```
545    /// # use bevy_platform::collections::AlignedVec;
546    ///
547    /// let mut v = Vec::new();
548    /// assert!(v.is_empty());
549    ///
550    /// v.push(1);
551    /// assert!(!v.is_empty());
552    /// ```
553    #[inline]
554    pub fn is_empty(&self) -> bool {
555        self.len == 0
556    }
557
558    /// Returns the number of elements in the vector, also referred to as its
559    /// 'length'.
560    ///
561    /// # Examples
562    /// ```
563    /// # use bevy_platform::collections::AlignedVec;
564    ///
565    /// let mut a = AlignedVec::new(16);
566    /// a.extend_from_slice(&[1, 2, 3]);
567    /// assert_eq!(a.len(), 3);
568    /// ```
569    #[inline]
570    pub fn len(&self) -> usize {
571        self.len
572    }
573
574    /// Consumes and leaks the `AlignedVec`, returning a mutable reference to
575    /// the contents, `&'static mut [u8]`.
576    ///
577    /// This method does not reallocate or shrink the `AlignedVec`, so the
578    /// leaked allocation may include unused capacity that is not part of the
579    /// returned slice.
580    ///
581    /// This function is mainly useful for data that lives for the remainder of
582    /// the program's life. Dropping the returned reference will cause a memory
583    /// leak.
584    ///
585    /// # Examples
586    ///
587    /// Simple usage:
588    ///
589    /// ```
590    /// # use std::alloc::{Layout, dealloc};
591    /// # use bevy_platform::collections::AlignedVec;
592    ///
593    /// let mut x = AlignedVec::new(16);
594    /// x.extend_from_slice(&[1, 2, 3]);
595    /// # let layout = Layout::from_size_align(x.capacity(), 16).unwrap();
596    /// let static_ref: &'static mut [u8] = x.leak();
597    /// static_ref[0] += 1;
598    /// assert_eq!(static_ref, &[2, 2, 3]);
599    /// # // Need to manually dealloc to avoid triggering Miri's leak check
600    /// # unsafe {
601    /// #     dealloc(static_ref.as_mut_ptr(), layout);
602    /// # }
603    /// ```
604    pub fn leak(self) -> &'static mut [u8] {
605        let mut me = ManuallyDrop::new(self);
606        // SAFETY: `ptr` and `len` are valid to construct slice
607        unsafe { slice::from_raw_parts_mut(me.as_mut_ptr(), me.len) }
608    }
609
610    /// Copies and appends all bytes in a slice to the `AlignedVec`.
611    ///
612    /// The elements of the slice are appended in-order.
613    ///
614    /// # Examples
615    /// ```
616    /// # use bevy_platform::collections::AlignedVec;
617    ///
618    /// let mut vec = AlignedVec::new(16);
619    /// vec.push(1);
620    /// vec.extend_from_slice(&[2, 3, 4]);
621    /// assert_eq!(vec.as_slice(), &[1, 2, 3, 4]);
622    /// ```
623    pub fn extend_from_slice(&mut self, other: &[u8]) {
624        self.reserve(other.len());
625        // SAFETY: memory is reserved for copy
626        unsafe {
627            core::ptr::copy_nonoverlapping(
628                other.as_ptr(),
629                self.as_mut_ptr().add(self.len()),
630                other.len(),
631            );
632        }
633        self.len += other.len();
634    }
635
636    /// Removes the last element from a vector and returns it, or `None` if it
637    /// is empty.
638    ///
639    /// # Examples
640    /// ```
641    /// # use bevy_platform::collections::AlignedVec;
642    ///
643    /// let mut vec = AlignedVec::new(16);
644    /// vec.extend_from_slice(&[1, 2, 3]);
645    /// assert_eq!(vec.pop(), Some(3));
646    /// assert_eq!(vec.as_slice(), &[1, 2]);
647    /// ```
648    #[inline]
649    pub fn pop(&mut self) -> Option<u8> {
650        if self.len == 0 {
651            None
652        } else {
653            let result = self[self.len - 1];
654            self.len -= 1;
655            Some(result)
656        }
657    }
658
659    /// Appends an element to the back of a collection.
660    ///
661    /// # Panics
662    ///
663    /// Panics if the new capacity when rounded up to the nearest multiple of align overflow `isize`.
664    ///
665    /// # Examples
666    /// ```
667    /// # use bevy_platform::collections::AlignedVec;
668    ///
669    /// let mut vec = AlignedVec::new(16);
670    /// vec.extend_from_slice(&[1, 2]);
671    /// vec.push(3);
672    /// assert_eq!(vec.as_slice(), &[1, 2, 3]);
673    /// ```
674    #[inline]
675    pub fn push(&mut self, value: u8) {
676        if self.len == self.cap {
677            self.reserve_for_push();
678        }
679
680        // SAFETY: memory is reserved for writing.
681        unsafe {
682            self.as_mut_ptr().add(self.len).write(value);
683            self.len += 1;
684        }
685    }
686
687    /// Extend capacity by at least 1 byte after `push` has found it's
688    /// necessary.
689    ///
690    /// Actually performing the extension is in this separate function marked
691    /// `#[cold]` to hint to compiler that this branch is not often taken.
692    /// This keeps the path for common case where capacity is already sufficient
693    /// as fast as possible, and makes `push` more likely to be inlined.
694    /// This is the same trick that Rust's `Vec::push` uses.
695    #[cold]
696    fn reserve_for_push(&mut self) {
697        // `len` is always less than `isize::MAX`, so no possibility of overflow
698        // here
699        let new_cap = self.len + 1;
700        // SAFETY: `reserve_for_push` is only called when capacity grows
701        unsafe { self.grow_capacity_to(new_cap) };
702    }
703
704    /// Reserves the minimum capacity for exactly `additional` more elements to
705    /// be inserted in the given `AlignedVec`. After calling
706    /// `reserve_exact`, capacity will be greater than or equal
707    /// to `self.len() + additional`. Does nothing if the capacity is already
708    /// sufficient.
709    ///
710    /// Note that the allocator may give the collection more space than it
711    /// requests. Therefore, capacity can not be relied upon to be precisely
712    /// minimal. Prefer reserve if future insertions are expected.
713    ///
714    /// # Panics
715    ///
716    /// Panics if the new capacity when rounded up to the nearest multiple of align overflow `isize`.
717    ///
718    /// # Examples
719    /// ```
720    /// # use bevy_platform::collections::AlignedVec;
721    ///
722    /// let mut vec = AlignedVec::new(16);
723    /// vec.push(1);
724    /// vec.reserve_exact(10);
725    /// assert!(vec.capacity() >= 11);
726    /// ```
727    pub fn reserve_exact(&mut self, additional: usize) {
728        // This function does not use the hot/cold paths trick that `reserve`
729        // and `push` do, on assumption that user probably knows this will
730        // require an increase in capacity. Otherwise, they'd likely use
731        // `reserve`.
732        let new_cap = self
733            .len
734            .checked_add(additional)
735            .expect("cannot reserve a larger AlignedVec");
736        if new_cap > self.cap {
737            assert!(
738                new_cap <= self.max_capacity(),
739                "cannot reserve a larger AlignedVec"
740            );
741            // SAFETY: `new_cap` is `self.len + additional` thus it is >= `self.len`
742            unsafe { self.change_capacity(new_cap) };
743        }
744    }
745
746    /// Forces the length of the vector to `new_len`.
747    ///
748    /// This is a low-level operation that maintains none of the normal
749    /// invariants of the type.
750    ///
751    /// # Safety
752    ///
753    /// - `new_len` must be less than or equal to
754    ///   [`capacity()`](AlignedVec::capacity)
755    /// - The elements at `old_len..new_len` must be initialized
756    ///
757    /// # Examples
758    /// ```
759    /// # use bevy_platform::collections::AlignedVec;
760    /// let mut vec = AlignedVec::with_capacity(16, 3);
761    /// vec.extend_from_slice(&[1, 2, 3]);
762    ///
763    /// // SAFETY:
764    /// // 1. `old_len..0` is empty to no elements need to be initialized.
765    /// // 2. `0 <= capacity` always holds whatever capacity is.
766    /// unsafe {
767    ///     vec.set_len(0);
768    /// }
769    /// ```
770    pub unsafe fn set_len(&mut self, new_len: usize) {
771        debug_assert!(new_len <= self.capacity());
772
773        self.len = new_len;
774    }
775
776    /// Converts the vector into `Vec<T>`.
777    ///
778    /// Panics if any of the following assertions fail:
779    /// ```rust,ignore
780    /// assert!(align_of::<T>() == self.alignment());
781    /// assert!(self.len().is_multiple_of(size_of::<T>()));
782    /// assert!(self.capacity().is_multiple_of(size_of::<T>()));
783    /// ```
784    ///
785    /// # Examples
786    /// ```
787    /// # use bevy_platform::collections::AlignedVec;
788    /// let mut v = AlignedVec::new(2);
789    /// v.extend_from_slice(&[1, 2, 3, 4]);
790    ///
791    /// let vec: Vec<u16> = v.into_vec();
792    /// assert_eq!(vec.len(), 2);
793    /// assert_eq!(vec.as_slice(), &[513, 1027]);
794    /// ```
795    #[cfg(feature = "bytemuck")]
796    pub fn into_vec<T: bytemuck::AnyBitPattern>(self) -> Vec<T> {
797        const {
798            assert!(size_of::<T>() != 0);
799        }
800        assert!(align_of::<T>() == self.alignment());
801        assert!(self.len().is_multiple_of(size_of::<T>()));
802        assert!(self.capacity().is_multiple_of(size_of::<T>()));
803        let (ptr, _align, len, cap) = self.into_raw_parts();
804        // SAFETY: the raw parts from `self` are valid to be used as `Vec`
805        unsafe {
806            Vec::from_raw_parts(
807                ptr.cast::<T>().as_ptr(),
808                len / size_of::<T>(),
809                cap / size_of::<T>(),
810            )
811        }
812    }
813
814    /// Casts the vector to a slice of `T`.
815    ///
816    /// Panics:
817    /// * If `T` has a greater alignment requirement than the `AlignedVec`.
818    /// * If the size of `AlignedVec` is not a multiple of `size_of::<T>()`
819    #[cfg(feature = "bytemuck")]
820    pub fn cast_slice<T: bytemuck::AnyBitPattern>(&self) -> &[T] {
821        assert!(align_of::<T>() <= self.alignment());
822        bytemuck::cast_slice(self.as_slice())
823    }
824
825    /// Casts the vector to a mutable slice of `T`.
826    ///
827    /// Panics:
828    /// * If `T` has a greater alignment requirement than the `AlignedVec`.
829    /// * If the size of `AlignedVec` is not a multiple of `size_of::<T>()`
830    #[cfg(feature = "bytemuck")]
831    pub fn cast_slice_mut<T: bytemuck::AnyBitPattern + bytemuck::NoUninit>(&mut self) -> &mut [T] {
832        assert!(align_of::<T>() <= self.alignment());
833        bytemuck::cast_slice_mut(self.as_mut_slice())
834    }
835
836    /// Decompose an [`AlignedVec`] into its raw components: `(NonNull pointer, align,
837    /// length, capacity)`.
838    ///
839    /// The returned parts can be used to re-assemble the [`AlignedVec`] using
840    /// the [`from_raw_parts`](AlignedVec::from_raw_parts) function.
841    ///
842    /// After calling this function, the caller is responsible for the memory
843    /// previously managed by the [`AlignedVec`]. The only way to do this is
844    /// to convert the [`NonNull`] pointer, the length and the capacity back
845    /// into an [`AlignedVec`] using the [`from_raw_parts`](AlignedVec::from_raw_parts)
846    /// function, allowing the destructor to perform the cleanup.
847    ///
848    /// # Example
849    ///
850    /// ```
851    /// use bevy_platform::collections::AlignedVec;
852    ///
853    /// let mut v: AlignedVec = AlignedVec::new(16);
854    /// for i in 1..=5 {
855    ///     v.push(i);
856    /// }
857    ///
858    /// let (ptr, align, len, cap) = v.into_raw_parts();
859    ///
860    /// let rebuilt: AlignedVec =
861    ///     unsafe { AlignedVec::from_raw_parts(ptr, align, len, cap) };
862    /// assert_eq!(rebuilt.as_slice(), &[1, 2, 3, 4, 5]);
863    /// ```
864    #[must_use = "losing the pointer will leak memory"]
865    pub fn into_raw_parts(self) -> (NonNull<u8>, usize, usize, usize) {
866        let this = ManuallyDrop::new(self);
867        (this.ptr, this.align, this.len, this.cap)
868    }
869
870    /// Create an [`AlignedVec`] directly from a [`NonNull`] pointer, a length
871    /// and a capacity.
872    ///
873    /// # Safety
874    ///
875    /// This is highly unsafe, due to the number of invariants that aren't
876    /// checked:
877    ///
878    /// * `align` must be a non-zero power of two, and must be less than
879    ///   `isize::MAX`.
880    /// * `capacity`, when rounded up to the nearest multiple of `align`, must
881    ///   not overflow `isize`.
882    /// * If the capacity is nonzero, `ptr` must have been allocated using
883    ///   the global allocator, such as via the [`alloc::alloc`] function,
884    ///   with a [`Layout`] using this exact `align` and a `size` of `capacity`.
885    ///   (Because similar to alignment, [`dealloc`] must be called with the
886    ///   same layout `size`.)
887    /// * If the capacity is zero, `ptr` need not point to allocated memory,
888    ///   but it must still be aligned to `align` bytes (i.e.
889    ///   `ptr.as_ptr() as usize % align == 0`).
890    /// * `length` needs to be less than or equal to `capacity`.
891    ///
892    /// # Example
893    ///
894    /// ```
895    /// use bevy_platform::collections::AlignedVec;
896    ///
897    /// let mut v: AlignedVec = AlignedVec::new(16);
898    /// for i in 1..=5 {
899    ///     v.push(i);
900    /// }
901    ///
902    /// let (ptr, align, len, cap) = v.into_raw_parts();
903    ///
904    /// let rebuilt: AlignedVec =
905    ///     unsafe { AlignedVec::from_raw_parts(ptr, align, len, cap) };
906    /// assert_eq!(rebuilt.as_slice(), &[1, 2, 3, 4, 5]);
907    /// ```
908    pub unsafe fn from_raw_parts(ptr: NonNull<u8>, align: usize, len: usize, cap: usize) -> Self {
909        Self {
910            ptr,
911            align,
912            len,
913            cap,
914        }
915    }
916}
917
918impl AsMut<[u8]> for AlignedVec {
919    fn as_mut(&mut self) -> &mut [u8] {
920        self.as_mut_slice()
921    }
922}
923
924impl AsRef<[u8]> for AlignedVec {
925    fn as_ref(&self) -> &[u8] {
926        self.as_slice()
927    }
928}
929
930impl Borrow<[u8]> for AlignedVec {
931    fn borrow(&self) -> &[u8] {
932        self.as_slice()
933    }
934}
935
936impl BorrowMut<[u8]> for AlignedVec {
937    fn borrow_mut(&mut self) -> &mut [u8] {
938        self.as_mut_slice()
939    }
940}
941
942impl Clone for AlignedVec {
943    fn clone(&self) -> Self {
944        let mut result = Self::with_capacity(self.align, self.len);
945        result.len = self.len;
946        // SAFETY: Both pointers are valid to do full copy and not overlap
947        unsafe { core::ptr::copy_nonoverlapping(self.as_ptr(), result.as_mut_ptr(), self.len) };
948        result
949    }
950}
951
952impl fmt::Debug for AlignedVec {
953    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
954        self.as_slice().fmt(f)
955    }
956}
957
958impl Deref for AlignedVec {
959    type Target = [u8];
960
961    fn deref(&self) -> &Self::Target {
962        self.as_slice()
963    }
964}
965
966impl DerefMut for AlignedVec {
967    fn deref_mut(&mut self) -> &mut Self::Target {
968        self.as_mut_slice()
969    }
970}
971
972impl<I: slice::SliceIndex<[u8]>> Index<I> for AlignedVec {
973    type Output = <I as slice::SliceIndex<[u8]>>::Output;
974
975    fn index(&self, index: I) -> &Self::Output {
976        &self.as_slice()[index]
977    }
978}
979
980impl<I: slice::SliceIndex<[u8]>> IndexMut<I> for AlignedVec {
981    fn index_mut(&mut self, index: I) -> &mut Self::Output {
982        &mut self.as_mut_slice()[index]
983    }
984}
985
986#[cfg(feature = "bytemuck")]
987impl<T: bytemuck::NoUninit> From<Vec<T>> for AlignedVec {
988    fn from(value: Vec<T>) -> Self {
989        let (ptr, len, cap) = value.into_raw_parts();
990        // SAFETY: `ptr` from `Vec` is non-null
991        let ptr = unsafe { NonNull::new_unchecked(ptr.cast::<u8>()) };
992        // SAFETY: the raw parts from `Vec` are valid to be used as `AlignedVec`
993        unsafe {
994            AlignedVec::from_raw_parts(
995                ptr,
996                align_of::<T>(),
997                len * size_of::<T>(),
998                cap * size_of::<T>(),
999            )
1000        }
1001    }
1002}
1003
1004// SAFETY: `AlignedVec`, like `Vec<u8>`, is safe to send to another thread
1005unsafe impl Send for AlignedVec {}
1006
1007// SAFETY: `AlignedVec`, like `Vec<u8>`, is safe to share between threads
1008unsafe impl Sync for AlignedVec {}
1009
1010impl Unpin for AlignedVec {}