use core::{
mem::{size_of, MaybeUninit},
ptr,
};
use std::alloc::{alloc_zeroed, handle_alloc_error, Layout};
pub const fn zero<T>() -> T {
unsafe { MaybeUninit::zeroed().assume_init() }
}
pub const fn ones<T>() -> T {
unsafe {
let mut x = MaybeUninit::uninit();
ptr::write_bytes(x.as_mut_ptr(), 0xFF, 1);
x.assume_init()
}
}
pub const fn make_zero<T: ?Sized>(v: &mut T) {
unsafe { ptr::write_bytes(v as *mut _ as *mut u8, 0, core::mem::size_of_val(v)) }
}
pub fn zeroed_box<T>() -> Box<T> {
unsafe {
let layout = Layout::new::<T>();
let ptr = alloc_zeroed(layout);
if ptr.is_null() {
handle_alloc_error(layout);
}
Box::from_raw(ptr.cast())
}
}
pub const fn read<D, T: Copy>(data: *const D, offset: usize) -> T {
unsafe { *data.cast::<u8>().add(offset).cast() }
}
pub const fn write<D, T: Copy>(data: *mut D, offset: usize, val: T) {
unsafe { data.cast::<u8>().add(offset).cast::<T>().write(val) }
}
pub trait MemValue: Sized + Copy {
fn from_le_bytes(bytes: [u8; size_of::<Self>()]) -> Self;
fn from_be_bytes(bytes: [u8; size_of::<Self>()]) -> Self;
fn from_ne_bytes(bytes: [u8; size_of::<Self>()]) -> Self;
fn to_le_bytes(self) -> [u8; size_of::<Self>()];
fn to_be_bytes(self) -> [u8; size_of::<Self>()];
fn to_ne_bytes(self) -> [u8; size_of::<Self>()];
unsafe fn read_le(ptr: *const Self) -> Self;
unsafe fn read_le_aligned(ptr: *const Self) -> Self;
unsafe fn read_be(ptr: *const Self) -> Self;
unsafe fn read_be_aligned(ptr: *const Self) -> Self;
unsafe fn read_ne(ptr: *const Self) -> Self;
unsafe fn read_ne_aligned(ptr: *const Self) -> Self;
unsafe fn write_le(self, ptr: *mut Self);
unsafe fn write_le_aligned(self, ptr: *mut Self);
unsafe fn write_be(self, ptr: *mut Self);
unsafe fn write_be_aligned(self, ptr: *mut Self);
unsafe fn write_ne(self, ptr: *mut Self);
unsafe fn write_ne_aligned(self, ptr: *mut Self);
}
macro_rules! impl_mem_value {
($($ty: ty),*) => {
$(
#[allow(unused_mut)]
impl MemValue for $ty {
#[inline]
fn from_le_bytes(bytes: [u8; size_of::<Self>()]) -> Self {
<$ty>::from_le_bytes(bytes)
}
#[inline]
fn from_be_bytes(bytes: [u8; size_of::<Self>()]) -> Self {
<$ty>::from_be_bytes(bytes)
}
#[inline]
fn from_ne_bytes(bytes: [u8; size_of::<Self>()]) -> Self {
<$ty>::from_ne_bytes(bytes)
}
#[inline]
fn to_le_bytes(self) -> [u8; size_of::<Self>()] {
<$ty>::to_le_bytes(self)
}
#[inline]
fn to_be_bytes(self) -> [u8; size_of::<Self>()] {
<$ty>::to_be_bytes(self)
}
#[inline]
fn to_ne_bytes(self) -> [u8; size_of::<Self>()] {
<$ty>::to_ne_bytes(self)
}
#[inline]
unsafe fn read_le(ptr: *const Self) -> Self {
let mut res = ptr.read_unaligned();
#[cfg(not(target_endian = "little"))]
{
res = res.swap_bytes();
}
res
}
#[inline]
unsafe fn read_le_aligned(ptr: *const Self) -> Self {
let mut res = ptr.read();
#[cfg(not(target_endian = "little"))]
{
res = res.swap_bytes();
}
res
}
#[inline]
unsafe fn read_be(ptr: *const Self) -> Self {
let mut res = ptr.read_unaligned();
#[cfg(not(target_endian = "big"))]
{
res = res.swap_bytes();
}
res
}
#[inline]
unsafe fn read_be_aligned(ptr: *const Self) -> Self {
let mut res = ptr.read();
#[cfg(not(target_endian = "big"))]
{
res = res.swap_bytes();
}
res
}
#[inline]
unsafe fn read_ne(ptr: *const Self) -> Self {
ptr.read_unaligned()
}
#[inline]
unsafe fn read_ne_aligned(ptr: *const Self) -> Self {
ptr.read()
}
#[inline]
unsafe fn write_le(mut self, ptr: *mut Self) {
#[cfg(not(target_endian = "little"))]
{
self = self.swap_bytes();
}
ptr.write_unaligned(self);
}
#[inline]
unsafe fn write_le_aligned(mut self, ptr: *mut Self) {
#[cfg(not(target_endian = "little"))]
{
self = self.swap_bytes();
}
ptr.write(self);
}
#[inline]
unsafe fn write_be(mut self, ptr: *mut Self) {
#[cfg(not(target_endian = "big"))]
{
self = self.swap_bytes();
}
ptr.write_unaligned(self);
}
#[inline]
unsafe fn write_be_aligned(mut self, ptr: *mut Self) {
#[cfg(not(target_endian = "big"))]
{
self = self.swap_bytes();
}
ptr.write(self);
}
#[inline]
unsafe fn write_ne(self, ptr: *mut Self) {
ptr.write_unaligned(self);
}
#[inline]
unsafe fn write_ne_aligned(self, ptr: *mut Self) {
ptr.write(self);
}
}
)*
};
}
impl_mem_value!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);