bump_scope/
raw_fixed_bump_vec.rs

1use core::{
2    mem::transmute,
3    ptr::{self, NonNull},
4};
5
6use crate::{
7    BumpAllocatorExt, FixedBumpVec, MutBumpAllocatorExt, SizedTypeProperties,
8    error_behavior::ErrorBehavior,
9    polyfill::{non_null, transmute_mut, transmute_ref},
10    raw_bump_box::RawBumpBox,
11    set_len_on_drop_by_ptr::SetLenOnDropByPtr,
12};
13
14/// Like [`FixedBumpVec`] but without its lifetime.
15#[repr(C)]
16pub struct RawFixedBumpVec<T> {
17    initialized: RawBumpBox<[T]>,
18    capacity: usize,
19}
20
21impl<T> RawFixedBumpVec<T> {
22    pub(crate) const EMPTY: Self = RawFixedBumpVec {
23        initialized: RawBumpBox::EMPTY,
24        capacity: if T::IS_ZST { usize::MAX } else { 0 },
25    };
26
27    pub(crate) const unsafe fn new_zst(len: usize) -> Self {
28        assert!(T::IS_ZST);
29
30        RawFixedBumpVec {
31            initialized: unsafe { RawBumpBox::from_ptr(NonNull::slice_from_raw_parts(NonNull::dangling(), len)) },
32            capacity: usize::MAX,
33        }
34    }
35
36    #[inline(always)]
37    pub(crate) const unsafe fn cook<'a>(self) -> FixedBumpVec<'a, T> {
38        unsafe { transmute(self) }
39    }
40
41    #[inline(always)]
42    pub(crate) const unsafe fn cook_ref<'a>(&self) -> &FixedBumpVec<'a, T> {
43        unsafe { transmute_ref(self) }
44    }
45
46    #[inline(always)]
47    pub(crate) unsafe fn cook_mut<'a>(&mut self) -> &mut FixedBumpVec<'a, T> {
48        unsafe { transmute_mut(self) }
49    }
50
51    #[inline(always)]
52    pub(crate) unsafe fn from_cooked(cooked: FixedBumpVec<'_, T>) -> Self {
53        unsafe {
54            let (initialized, capacity) = cooked.into_raw_parts();
55            let initialized = RawBumpBox::from_cooked(initialized);
56            Self { initialized, capacity }
57        }
58    }
59
60    #[inline(always)]
61    pub(crate) unsafe fn allocate<B: ErrorBehavior>(allocator: &impl BumpAllocatorExt, len: usize) -> Result<Self, B> {
62        let ptr = B::allocate_slice::<T>(allocator, len)?;
63
64        Ok(Self {
65            initialized: unsafe { RawBumpBox::from_ptr(NonNull::slice_from_raw_parts(ptr, 0)) },
66            capacity: len,
67        })
68    }
69
70    #[inline(always)]
71    pub(crate) unsafe fn prepare_allocation<B: ErrorBehavior>(
72        allocator: &mut impl MutBumpAllocatorExt,
73        len: usize,
74    ) -> Result<Self, B> {
75        unsafe {
76            let allocation = B::prepare_slice_allocation::<T>(allocator, len)?;
77
78            Ok(Self {
79                initialized: RawBumpBox::from_ptr(NonNull::slice_from_raw_parts(non_null::as_non_null_ptr(allocation), 0)),
80                capacity: allocation.len(),
81            })
82        }
83    }
84
85    /// `new_cap` must be greater than `self.capacity`
86    pub(crate) unsafe fn grow_prepared_allocation<B: ErrorBehavior>(
87        &mut self,
88        allocator: &mut impl MutBumpAllocatorExt,
89        minimum_new_cap: usize,
90    ) -> Result<(), B> {
91        unsafe {
92            debug_assert!(minimum_new_cap > self.capacity);
93            let allocation = B::prepare_slice_allocation::<T>(allocator, minimum_new_cap)?;
94
95            let new_ptr = allocation.cast::<T>();
96            let new_cap = allocation.len();
97
98            ptr::copy_nonoverlapping(self.as_ptr(), new_ptr.as_ptr(), self.len());
99
100            self.initialized.set_ptr(new_ptr);
101            self.capacity = new_cap;
102
103            Ok(())
104        }
105    }
106
107    #[inline(always)]
108    pub(crate) const fn len(&self) -> usize {
109        self.initialized.len()
110    }
111
112    #[inline(always)]
113    pub(crate) const fn capacity(&self) -> usize {
114        self.capacity
115    }
116
117    #[inline(always)]
118    pub(crate) fn as_ptr(&self) -> *const T {
119        self.initialized.as_ptr().cast()
120    }
121
122    #[inline(always)]
123    pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
124        self.initialized.as_mut_ptr().cast()
125    }
126
127    #[must_use]
128    #[inline(always)]
129    pub const fn as_non_null(&self) -> NonNull<T> {
130        self.initialized.as_non_null().cast()
131    }
132
133    #[doc(hidden)]
134    #[deprecated = "too niche; compute this yourself if needed"]
135    #[must_use]
136    #[inline(always)]
137    pub fn as_non_null_slice(&self) -> NonNull<[T]> {
138        self.initialized.as_non_null()
139    }
140
141    #[inline(always)]
142    pub(crate) unsafe fn set_ptr(&mut self, new_ptr: NonNull<T>) {
143        unsafe { self.initialized.set_ptr(new_ptr) };
144    }
145
146    #[inline(always)]
147    pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
148        unsafe { self.initialized.set_len(new_len) };
149    }
150
151    #[inline(always)]
152    pub(crate) unsafe fn set_cap(&mut self, new_cap: usize) {
153        self.capacity = new_cap;
154    }
155
156    #[inline(always)]
157    pub(crate) unsafe fn set_len_on_drop(&mut self) -> SetLenOnDropByPtr<'_, T> {
158        SetLenOnDropByPtr::new(&mut self.initialized.ptr)
159    }
160
161    #[inline(always)]
162    pub(crate) fn into_raw_parts(self) -> (NonNull<[T]>, usize) {
163        let Self { initialized, capacity } = self;
164        (initialized.into_ptr(), capacity)
165    }
166
167    #[inline(always)]
168    pub(crate) unsafe fn from_raw_parts(slice: NonNull<[T]>, capacity: usize) -> Self {
169        Self {
170            initialized: unsafe { RawBumpBox::from_ptr(slice) },
171            capacity,
172        }
173    }
174}