flex_alloc/storage/
bytes.rs1use core::alloc::Layout;
2use core::fmt;
3use core::mem::{ManuallyDrop, MaybeUninit};
4use core::ptr::NonNull;
5
6use const_default::ConstDefault;
7
8use super::{spill::SpillStorage, utils::layout_aligned_bytes};
9use crate::alloc::{AllocError, AllocateIn, Allocator, Fixed, SpillAlloc};
10
11#[repr(C)]
13pub union ByteStorage<T, const N: usize> {
14 _align: [ManuallyDrop<T>; 0],
15 data: [MaybeUninit<u8>; N],
16}
17
18impl<T, const N: usize> ByteStorage<T, N> {
19 pub fn as_uninit_slice(&mut self) -> &mut [MaybeUninit<u8>] {
21 unsafe { &mut self.data }
23 }
24}
25
26impl<'a, T, const N: usize> AllocateIn for &'a mut ByteStorage<T, N> {
27 type Alloc = Fixed<'a>;
28
29 #[inline]
30 fn allocate_in(self, layout: Layout) -> Result<(NonNull<[u8]>, Self::Alloc), AllocError> {
31 let ptr = layout_aligned_bytes(self.as_uninit_slice(), layout).map_err(|_| AllocError)?;
32 let alloc = Fixed::default();
33 Ok((ptr, alloc))
34 }
35}
36
37impl<T, const N: usize> ConstDefault for ByteStorage<T, N> {
38 const DEFAULT: Self = Self {
39 data: unsafe { MaybeUninit::uninit().assume_init() },
41 };
42}
43
44impl<T, const N: usize> fmt::Debug for ByteStorage<T, N> {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 f.debug_struct("ByteStorage").finish_non_exhaustive()
47 }
48}
49
50impl<T, const N: usize> Default for ByteStorage<T, N> {
51 #[inline]
52 fn default() -> Self {
53 Self::DEFAULT
54 }
55}
56
57impl<'a, T: 'static, const N: usize> SpillAlloc<'a> for &'a mut ByteStorage<T, N> {
58 type NewIn<A: 'a> = SpillStorage<'a, Self, A>;
59
60 #[inline]
61 fn spill_alloc_in<A: Allocator + 'a>(self, alloc: A) -> Self::NewIn<A> {
62 SpillStorage::new_in(self, alloc)
63 }
64}
65
66#[cfg(feature = "zeroize")]
67impl<T, const N: usize> zeroize::Zeroize for ByteStorage<T, N> {
68 #[inline]
69 fn zeroize(&mut self) {
70 self.as_uninit_slice().zeroize()
71 }
72}