use core::{mem::MaybeUninit, num::*};
#[cfg(all(not(feature = "safe_mem"), feature = "unsafe_layout"))]
pub unsafe trait MemPod: Copy + 'static {
#[must_use]
fn zeroed() -> Self {
unsafe { core::mem::zeroed() }
}
#[must_use]
fn from_bytes(bytes: &[u8]) -> Self {
let size = size_of::<Self>();
let bytes_to_copy = core::cmp::min(bytes.len(), size);
let mut new_self = MaybeUninit::<Self>::uninit();
unsafe {
core::ptr::copy_nonoverlapping(
bytes.as_ptr(),
new_self.as_mut_ptr() as *mut u8,
bytes_to_copy,
);
if bytes_to_copy < size {
core::ptr::write_bytes(
(new_self.as_mut_ptr() as *mut u8).add(bytes_to_copy),
0,
size - bytes_to_copy,
);
}
new_self.assume_init()
}
}
#[must_use]
fn as_bytes(&self) -> &[u8] {
let ptr = self as *const Self as *const u8;
let len = size_of::<Self>();
unsafe { core::slice::from_raw_parts(ptr, len) }
}
#[must_use]
fn as_bytes_mut(&mut self) -> &mut [u8] {
let ptr = self as *mut Self as *mut u8;
let len = size_of::<Self>();
unsafe { core::slice::from_raw_parts_mut(ptr, len) }
}
}
#[rustfmt::skip]
macro_rules! mem_pod {
($($t:ty),+) => { $( mem_pod![@$t]; )+ };
(@$t:ty) => { unsafe impl MemPod for $t {} };
(option: $($t:ty),+) => { $( mem_pod![@option: $t]; )+ };
(@option: $t:ty) => { unsafe impl MemPod for Option<$t> {} };
}
pub(crate) use mem_pod;
#[rustfmt::skip]
mem_pod![(), u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64];
unsafe impl<T: MemPod, const N: usize> MemPod for [T; N] {}
unsafe impl<T: MemPod> MemPod for MaybeUninit<T> {}
unsafe impl<T: MemPod> MemPod for core::mem::ManuallyDrop<T> {}
unsafe impl<T: MemPod> MemPod for core::num::Wrapping<T> {}
unsafe impl<T: ?Sized + 'static> MemPod for core::marker::PhantomData<T> {}
unsafe impl<T: MemPod> MemPod for Option<T> {}
mem_pod![option:
NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize
];