bump_scope/features/
zerocopy_08.rs

1use core::mem::MaybeUninit;
2
3use zerocopy_08::FromZeros;
4
5use crate::{
6    BaseAllocator, Bump, BumpBox, BumpScope, MinimumAlignment, SupportedMinimumAlignment, alloc::AllocError,
7    error_behavior::ErrorBehavior,
8};
9
10#[cfg(feature = "panic-on-alloc")]
11use crate::panic_on_error;
12
13mod vec_ext;
14
15pub use vec_ext::VecExt;
16
17mod init_zeroed {
18    use super::*;
19
20    pub trait Sealed {}
21
22    impl<T: FromZeros> Sealed for BumpBox<'_, MaybeUninit<T>> {}
23    impl<T: FromZeros> Sealed for BumpBox<'_, [MaybeUninit<T>]> {}
24}
25
26/// Extension trait for [`BumpBox`] that adds the `init_zeroed` method.
27pub trait InitZeroed<'a>: init_zeroed::Sealed {
28    /// The initialized type.
29    type Output: ?Sized;
30
31    /// Initializes `self` by filling it with zero.
32    ///
33    /// # Examples
34    ///
35    /// ```
36    /// use bump_scope::{Bump, zerocopy_08::InitZeroed};
37    /// let bump: Bump = Bump::new();
38    ///
39    /// // single value
40    /// let uninit = bump.alloc_uninit::<i32>();
41    /// let init = uninit.init_zeroed();
42    /// assert_eq!(*init, 0);
43    ///
44    /// // slice
45    /// let uninit = bump.alloc_uninit_slice::<i32>(10);
46    /// let init = uninit.init_zeroed();
47    /// assert_eq!(*init, [0; 10]);
48    /// ```
49    #[must_use]
50    fn init_zeroed(self) -> BumpBox<'a, Self::Output>;
51}
52
53impl<'a, T: FromZeros> InitZeroed<'a> for BumpBox<'a, MaybeUninit<T>> {
54    type Output = T;
55
56    #[inline]
57    fn init_zeroed(mut self) -> BumpBox<'a, T> {
58        unsafe {
59            self.as_mut_ptr().write_bytes(0, 1);
60            self.assume_init()
61        }
62    }
63}
64
65impl<'a, T: FromZeros> InitZeroed<'a> for BumpBox<'a, [MaybeUninit<T>]> {
66    type Output = [T];
67
68    #[inline]
69    fn init_zeroed(mut self) -> BumpBox<'a, [T]> {
70        unsafe {
71            let len = self.len();
72            self.as_mut_ptr().write_bytes(0, len);
73            self.assume_init()
74        }
75    }
76}
77
78mod bump_ext {
79    use super::*;
80
81    pub trait Sealed {}
82
83    impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Sealed
84        for Bump<A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
85    where
86        MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
87        A: BaseAllocator<GUARANTEED_ALLOCATED>,
88    {
89    }
90}
91
92mod bump_scope_ext {
93    use super::*;
94
95    pub trait Sealed {}
96
97    impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Sealed
98        for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
99    where
100        MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
101        A: BaseAllocator<GUARANTEED_ALLOCATED>,
102    {
103    }
104}
105
106/// Extension trait for [`Bump`] that adds the `(try_)alloc_zeroed(_slice)` methods.
107pub trait BumpExt: bump_ext::Sealed {
108    /// Allocate a zeroed object.
109    ///
110    /// # Panics
111    /// Panics if the allocation fails.
112    ///
113    /// # Examples
114    /// ```
115    /// use bump_scope::{Bump, zerocopy_08::BumpExt};
116    /// let bump: Bump = Bump::new();
117    ///
118    /// let zero = bump.alloc_zeroed::<i32>();
119    /// assert_eq!(*zero, 0);
120    /// ```
121    #[cfg(feature = "panic-on-alloc")]
122    fn alloc_zeroed<T>(&self) -> BumpBox<'_, T>
123    where
124        T: FromZeros;
125
126    /// Allocate a zeroed object.
127    ///
128    /// # Errors
129    /// Errors if the allocation fails.
130    ///
131    /// # Examples
132    /// ```
133    /// use bump_scope::{Bump, zerocopy_08::BumpExt};
134    /// let bump: Bump = Bump::try_new()?;
135    ///
136    /// let zero = bump.try_alloc_zeroed::<i32>()?;
137    /// assert_eq!(*zero, 0);
138    /// # Ok::<(), bump_scope::alloc::AllocError>(())
139    /// ```
140    fn try_alloc_zeroed<T>(&self) -> Result<BumpBox<'_, T>, AllocError>
141    where
142        T: FromZeros;
143
144    /// Allocate a zeroed object slice.
145    ///
146    /// # Panics
147    /// Panics if the allocation fails.
148    ///
149    /// # Examples
150    /// ```
151    /// use bump_scope::{Bump, zerocopy_08::BumpExt};
152    /// let bump: Bump = Bump::new();
153    ///
154    /// let zeroes = bump.alloc_zeroed_slice::<i32>(3);
155    /// assert_eq!(*zeroes, [0; 3]);
156    /// ```
157    #[cfg(feature = "panic-on-alloc")]
158    fn alloc_zeroed_slice<T>(&self, len: usize) -> BumpBox<'_, [T]>
159    where
160        T: FromZeros;
161
162    /// Allocate a zeroed object slice.
163    ///
164    /// # Errors
165    /// Errors if the allocation fails.
166    ///
167    /// # Examples
168    /// ```
169    /// use bump_scope::{Bump, zerocopy_08::BumpExt};
170    /// let bump: Bump = Bump::try_new()?;
171    ///
172    /// let zeroes = bump.try_alloc_zeroed_slice::<i32>(3)?;
173    /// assert_eq!(*zeroes, [0; 3]);
174    /// # Ok::<(), bump_scope::alloc::AllocError>(())
175    /// ```
176    fn try_alloc_zeroed_slice<T>(&self, len: usize) -> Result<BumpBox<'_, [T]>, AllocError>
177    where
178        T: FromZeros;
179}
180
181/// Extension trait for [`BumpScope`] that adds the `(try_)alloc_zeroed(_slice)` methods.
182pub trait BumpScopeExt<'a>: bump_scope_ext::Sealed {
183    /// Allocate a zeroed object.
184    ///
185    /// # Panics
186    /// Panics if the allocation fails.
187    ///
188    /// # Examples
189    /// ```
190    /// use bump_scope::{Bump, zerocopy_08::BumpScopeExt};
191    /// let mut bump: Bump = Bump::new();
192    ///
193    /// bump.scoped(|bump| {
194    ///     let zero = bump.alloc_zeroed::<i32>();
195    ///     assert_eq!(*zero, 0);
196    /// });
197    /// ```
198    #[cfg(feature = "panic-on-alloc")]
199    fn alloc_zeroed<T>(&self) -> BumpBox<'a, T>
200    where
201        T: FromZeros;
202
203    /// Allocate a zeroed object.
204    ///
205    /// # Errors
206    /// Errors if the allocation fails.
207    ///
208    /// # Examples
209    /// ```
210    /// use bump_scope::{Bump, alloc::AllocError, zerocopy_08::BumpScopeExt};
211    /// let mut bump: Bump = Bump::try_new()?;
212    ///
213    /// bump.scoped(|bump| -> Result<(), AllocError> {
214    ///     let zero = bump.try_alloc_zeroed::<i32>()?;
215    ///     assert_eq!(*zero, 0);
216    ///     Ok(())
217    /// })?;
218    /// # Ok::<(), bump_scope::alloc::AllocError>(())
219    /// ```
220    fn try_alloc_zeroed<T>(&self) -> Result<BumpBox<'a, T>, AllocError>
221    where
222        T: FromZeros;
223
224    /// Allocate a zeroed object slice.
225    ///
226    /// # Panics
227    /// Panics if the allocation fails.
228    ///
229    /// # Examples
230    /// ```
231    /// use bump_scope::{Bump, zerocopy_08::BumpScopeExt};
232    /// let mut bump: Bump = Bump::new();
233    ///
234    /// bump.scoped(|bump| {
235    ///     let zeroes = bump.alloc_zeroed_slice::<i32>(3);
236    ///     assert_eq!(*zeroes, [0; 3]);
237    /// });
238    /// ```
239    #[cfg(feature = "panic-on-alloc")]
240    fn alloc_zeroed_slice<T>(&self, len: usize) -> BumpBox<'a, [T]>
241    where
242        T: FromZeros;
243
244    /// Allocate a zeroed object slice.
245    ///
246    /// # Errors
247    /// Errors if the allocation fails.
248    ///
249    /// # Examples
250    /// ```
251    /// use bump_scope::{Bump, alloc::AllocError, zerocopy_08::BumpScopeExt};
252    /// let mut bump: Bump = Bump::try_new()?;
253    ///
254    /// bump.scoped(|bump| -> Result<(), AllocError>  {
255    ///     let zeroes = bump.try_alloc_zeroed_slice::<i32>(3)?;
256    ///     assert_eq!(*zeroes, [0; 3]);
257    ///     Ok(())
258    /// })?;
259    /// # Ok::<(), bump_scope::alloc::AllocError>(())
260    /// ```
261    fn try_alloc_zeroed_slice<T>(&self, len: usize) -> Result<BumpBox<'a, [T]>, AllocError>
262    where
263        T: FromZeros;
264}
265
266impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> BumpExt
267    for Bump<A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
268where
269    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
270    A: BaseAllocator<GUARANTEED_ALLOCATED>,
271{
272    #[inline(always)]
273    #[cfg(feature = "panic-on-alloc")]
274    fn alloc_zeroed<T>(&self) -> BumpBox<'_, T>
275    where
276        T: FromZeros,
277    {
278        self.as_scope().alloc_zeroed()
279    }
280
281    #[inline(always)]
282    fn try_alloc_zeroed<T>(&self) -> Result<BumpBox<'_, T>, AllocError>
283    where
284        T: FromZeros,
285    {
286        self.as_scope().try_alloc_zeroed()
287    }
288
289    #[inline(always)]
290    #[cfg(feature = "panic-on-alloc")]
291    fn alloc_zeroed_slice<T>(&self, len: usize) -> BumpBox<'_, [T]>
292    where
293        T: FromZeros,
294    {
295        self.as_scope().alloc_zeroed_slice(len)
296    }
297
298    #[inline(always)]
299    fn try_alloc_zeroed_slice<T>(&self, len: usize) -> Result<BumpBox<'_, [T]>, AllocError>
300    where
301        T: FromZeros,
302    {
303        self.as_scope().try_alloc_zeroed_slice(len)
304    }
305}
306
307impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
308    BumpScopeExt<'a> for BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
309where
310    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
311    A: BaseAllocator<GUARANTEED_ALLOCATED>,
312{
313    #[inline(always)]
314    #[cfg(feature = "panic-on-alloc")]
315    fn alloc_zeroed<T>(&self) -> BumpBox<'a, T>
316    where
317        T: FromZeros,
318    {
319        panic_on_error(self.generic_alloc_zeroed())
320    }
321
322    #[inline(always)]
323    fn try_alloc_zeroed<T>(&self) -> Result<BumpBox<'a, T>, AllocError>
324    where
325        T: FromZeros,
326    {
327        self.generic_alloc_zeroed()
328    }
329
330    #[inline(always)]
331    #[cfg(feature = "panic-on-alloc")]
332    fn alloc_zeroed_slice<T>(&self, len: usize) -> BumpBox<'a, [T]>
333    where
334        T: FromZeros,
335    {
336        panic_on_error(self.generic_alloc_zeroed_slice(len))
337    }
338
339    #[inline(always)]
340    fn try_alloc_zeroed_slice<T>(&self, len: usize) -> Result<BumpBox<'a, [T]>, AllocError>
341    where
342        T: FromZeros,
343    {
344        self.generic_alloc_zeroed_slice(len)
345    }
346}
347
348trait PrivateBumpScopeExt<'a> {
349    fn generic_alloc_zeroed<B: ErrorBehavior, T>(&self) -> Result<BumpBox<'a, T>, B>
350    where
351        T: FromZeros;
352
353    fn generic_alloc_zeroed_slice<B: ErrorBehavior, T>(&self, len: usize) -> Result<BumpBox<'a, [T]>, B>
354    where
355        T: FromZeros;
356}
357
358impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
359    PrivateBumpScopeExt<'a> for BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
360where
361    MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
362    A: BaseAllocator<GUARANTEED_ALLOCATED>,
363{
364    #[inline(always)]
365    fn generic_alloc_zeroed<B: ErrorBehavior, T>(&self) -> Result<BumpBox<'a, T>, B>
366    where
367        T: FromZeros,
368    {
369        Ok(self.generic_alloc_uninit::<B, T>()?.init_zeroed())
370    }
371
372    #[inline(always)]
373    fn generic_alloc_zeroed_slice<B: ErrorBehavior, T>(&self, len: usize) -> Result<BumpBox<'a, [T]>, B>
374    where
375        T: FromZeros,
376    {
377        Ok(self.generic_alloc_uninit_slice::<B, T>(len)?.init_zeroed())
378    }
379}