1use core::mem::MaybeUninit;
2
3use ::bytemuck::Zeroable;
4
5use crate::{
6 BaseAllocator, Bump, BumpBox, BumpScope, ErrorBehavior, MinimumAlignment, SupportedMinimumAlignment, alloc::AllocError,
7};
8
9#[cfg(feature = "panic-on-alloc")]
10use crate::panic_on_error;
11
12mod vec_ext;
13
14pub use vec_ext::VecExt;
15
16mod init_zeroed {
17 use super::*;
18
19 pub trait Sealed {}
20
21 impl<T: Zeroable> Sealed for BumpBox<'_, MaybeUninit<T>> {}
22 impl<T: Zeroable> Sealed for BumpBox<'_, [MaybeUninit<T>]> {}
23}
24
25pub trait InitZeroed<'a>: init_zeroed::Sealed {
27 type Output: ?Sized;
29
30 #[must_use]
49 fn init_zeroed(self) -> BumpBox<'a, Self::Output>;
50}
51
52impl<'a, T: Zeroable> InitZeroed<'a> for BumpBox<'a, MaybeUninit<T>> {
53 type Output = T;
54
55 #[inline]
56 fn init_zeroed(mut self) -> BumpBox<'a, T> {
57 unsafe {
58 self.as_mut_ptr().write_bytes(0, 1);
59 self.assume_init()
60 }
61 }
62}
63
64impl<'a, T: Zeroable> InitZeroed<'a> for BumpBox<'a, [MaybeUninit<T>]> {
65 type Output = [T];
66
67 #[inline]
68 fn init_zeroed(mut self) -> BumpBox<'a, [T]> {
69 unsafe {
70 let len = self.len();
71 self.as_mut_ptr().write_bytes(0, len);
72 self.assume_init()
73 }
74 }
75}
76
77mod bump_ext {
78 use super::*;
79
80 pub trait Sealed {}
81
82 impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Sealed
83 for Bump<A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
84 where
85 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
86 A: BaseAllocator<GUARANTEED_ALLOCATED>,
87 {
88 }
89}
90
91mod bump_scope_ext {
92 use super::*;
93
94 pub trait Sealed {}
95
96 impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> Sealed
97 for BumpScope<'_, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
98 where
99 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
100 A: BaseAllocator<GUARANTEED_ALLOCATED>,
101 {
102 }
103}
104
105pub trait BumpExt: bump_ext::Sealed {
107 #[cfg(feature = "panic-on-alloc")]
121 fn alloc_zeroed<T>(&self) -> BumpBox<'_, T>
122 where
123 T: Zeroable;
124
125 fn try_alloc_zeroed<T>(&self) -> Result<BumpBox<'_, T>, AllocError>
140 where
141 T: Zeroable;
142
143 #[cfg(feature = "panic-on-alloc")]
157 fn alloc_zeroed_slice<T>(&self, len: usize) -> BumpBox<'_, [T]>
158 where
159 T: Zeroable;
160
161 fn try_alloc_zeroed_slice<T>(&self, len: usize) -> Result<BumpBox<'_, [T]>, AllocError>
176 where
177 T: Zeroable;
178}
179
180pub trait BumpScopeExt<'a>: bump_scope_ext::Sealed {
182 #[cfg(feature = "panic-on-alloc")]
198 fn alloc_zeroed<T>(&self) -> BumpBox<'a, T>
199 where
200 T: Zeroable;
201
202 fn try_alloc_zeroed<T>(&self) -> Result<BumpBox<'a, T>, AllocError>
220 where
221 T: Zeroable;
222
223 #[cfg(feature = "panic-on-alloc")]
239 fn alloc_zeroed_slice<T>(&self, len: usize) -> BumpBox<'a, [T]>
240 where
241 T: Zeroable;
242
243 fn try_alloc_zeroed_slice<T>(&self, len: usize) -> Result<BumpBox<'a, [T]>, AllocError>
261 where
262 T: Zeroable;
263}
264
265impl<A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool> BumpExt
266 for Bump<A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
267where
268 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
269 A: BaseAllocator<GUARANTEED_ALLOCATED>,
270{
271 #[inline(always)]
272 #[cfg(feature = "panic-on-alloc")]
273 fn alloc_zeroed<T>(&self) -> BumpBox<'_, T>
274 where
275 T: Zeroable,
276 {
277 self.as_scope().alloc_zeroed()
278 }
279
280 #[inline(always)]
281 fn try_alloc_zeroed<T>(&self) -> Result<BumpBox<'_, T>, AllocError>
282 where
283 T: Zeroable,
284 {
285 self.as_scope().try_alloc_zeroed()
286 }
287
288 #[inline(always)]
289 #[cfg(feature = "panic-on-alloc")]
290 fn alloc_zeroed_slice<T>(&self, len: usize) -> BumpBox<'_, [T]>
291 where
292 T: Zeroable,
293 {
294 self.as_scope().alloc_zeroed_slice(len)
295 }
296
297 #[inline(always)]
298 fn try_alloc_zeroed_slice<T>(&self, len: usize) -> Result<BumpBox<'_, [T]>, AllocError>
299 where
300 T: Zeroable,
301 {
302 self.as_scope().try_alloc_zeroed_slice(len)
303 }
304}
305
306impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
307 BumpScopeExt<'a> for BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
308where
309 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
310 A: BaseAllocator<GUARANTEED_ALLOCATED>,
311{
312 #[inline(always)]
313 #[cfg(feature = "panic-on-alloc")]
314 fn alloc_zeroed<T>(&self) -> BumpBox<'a, T>
315 where
316 T: Zeroable,
317 {
318 panic_on_error(self.generic_alloc_zeroed())
319 }
320
321 #[inline(always)]
322 fn try_alloc_zeroed<T>(&self) -> Result<BumpBox<'a, T>, AllocError>
323 where
324 T: Zeroable,
325 {
326 self.generic_alloc_zeroed()
327 }
328
329 #[inline(always)]
330 #[cfg(feature = "panic-on-alloc")]
331 fn alloc_zeroed_slice<T>(&self, len: usize) -> BumpBox<'a, [T]>
332 where
333 T: Zeroable,
334 {
335 panic_on_error(self.generic_alloc_zeroed_slice(len))
336 }
337
338 #[inline(always)]
339 fn try_alloc_zeroed_slice<T>(&self, len: usize) -> Result<BumpBox<'a, [T]>, AllocError>
340 where
341 T: Zeroable,
342 {
343 self.generic_alloc_zeroed_slice(len)
344 }
345}
346
347trait PrivateBumpScopeExt<'a> {
348 fn generic_alloc_zeroed<B: ErrorBehavior, T>(&self) -> Result<BumpBox<'a, T>, B>
349 where
350 T: Zeroable;
351
352 fn generic_alloc_zeroed_slice<B: ErrorBehavior, T>(&self, len: usize) -> Result<BumpBox<'a, [T]>, B>
353 where
354 T: Zeroable;
355}
356
357impl<'a, A, const MIN_ALIGN: usize, const UP: bool, const GUARANTEED_ALLOCATED: bool, const DEALLOCATES: bool>
358 PrivateBumpScopeExt<'a> for BumpScope<'a, A, MIN_ALIGN, UP, GUARANTEED_ALLOCATED, DEALLOCATES>
359where
360 MinimumAlignment<MIN_ALIGN>: SupportedMinimumAlignment,
361 A: BaseAllocator<GUARANTEED_ALLOCATED>,
362{
363 #[inline(always)]
364 fn generic_alloc_zeroed<B: ErrorBehavior, T>(&self) -> Result<BumpBox<'a, T>, B>
365 where
366 T: Zeroable,
367 {
368 Ok(self.generic_alloc_uninit::<B, T>()?.init_zeroed())
369 }
370
371 #[inline(always)]
372 fn generic_alloc_zeroed_slice<B: ErrorBehavior, T>(&self, len: usize) -> Result<BumpBox<'a, [T]>, B>
373 where
374 T: Zeroable,
375 {
376 Ok(self.generic_alloc_uninit_slice::<B, T>(len)?.init_zeroed())
377 }
378}