use core::alloc::{Layout, LayoutError};
use core::fmt;
use core::mem::{ManuallyDrop, MaybeUninit, size_of};
use core::ptr::NonNull;
use core::slice;
use crate::buf;
use crate::error::CoerceError;
use crate::pointer::{Pointee, Size};
use crate::traits::ZeroCopy;
#[repr(C, packed)]
pub union PackedMaybeUninit<T> {
uninit: (),
value: ManuallyDrop<T>,
}
impl<T> PackedMaybeUninit<T> {
pub const fn uninit() -> Self {
PackedMaybeUninit { uninit: () }
}
#[inline]
pub fn write(&mut self, value: &T) -> &mut [u8]
where
T: ZeroCopy,
{
unsafe {
let ptr = NonNull::new_unchecked(self as *mut Self as *mut MaybeUninit<u8>);
buf::store_unaligned(ptr, value);
slice::from_raw_parts_mut(ptr.as_ptr().cast(), size_of::<T>())
}
}
}
impl<T> fmt::Debug for PackedMaybeUninit<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MaybeUninit").finish_non_exhaustive()
}
}
impl<T> Pointee for PackedMaybeUninit<T>
where
T: Pointee,
{
type Metadata = T::Metadata;
type Stored<O>
= T::Stored<O>
where
O: Size;
#[inline(always)]
fn try_from_metadata<O>(metadata: Self::Metadata) -> Result<Self::Stored<O>, CoerceError>
where
O: Size,
{
T::try_from_metadata(metadata)
}
#[inline(always)]
fn to_metadata<O>(stored: Self::Stored<O>) -> Self::Metadata
where
O: Size,
{
T::to_metadata(stored)
}
#[inline(always)]
fn size(metadata: Self::Metadata) -> Option<usize> {
T::size(metadata)
}
#[inline(always)]
fn align(metadata: Self::Metadata) -> usize {
T::align(metadata)
}
#[inline(always)]
fn pointee_layout(metadata: Self::Metadata) -> Result<Layout, LayoutError> {
T::pointee_layout(metadata)
}
}