flex_alloc/storage/
bytes.rs

1use 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/// A reusable storage buffer consisting of an array of bytes.
12#[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    /// Access the buffer contents as a mutable slice.
20    pub fn as_uninit_slice(&mut self) -> &mut [MaybeUninit<u8>] {
21        // SAFETY: `self.data` is always safe to access.
22        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        // SAFETY: this is the accepted method to construct a `MaybeUninit` slice.
40        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}