#![no_std]
#![doc = include_str!("../README.md")]
extern crate alloc;
use alloc::{
alloc::{alloc, alloc_zeroed, handle_alloc_error},
boxed::Box,
};
use core::{
alloc::Layout,
marker::PhantomData,
mem::{size_of, transmute, MaybeUninit},
ptr::NonNull,
};
pub use boxify_macro::boxify;
#[doc(hidden)]
pub unsafe fn clone<T>(t: &T) -> T {
let mut dest = MaybeUninit::uninit();
(t as *const T).copy_to(dest.as_mut_ptr(), 1);
dest.assume_init()
}
pub struct TypeInferer<T>(PhantomData<T>);
impl<T> TypeInferer<T> {
pub fn new(_: impl FnOnce() -> T) -> Self {
Self(PhantomData)
}
}
#[doc(hidden)]
pub fn new_box_uninit_typed<T>(_: TypeInferer<T>) -> Box<MaybeUninit<T>> {
new_box_uninit::<T>()
}
#[doc(hidden)]
pub unsafe fn new_box_zeroed_typed<T>(_: TypeInferer<T>) -> Box<T> {
new_box_zeroed()
}
#[doc(hidden)]
pub fn new_box_uninit<T>() -> Box<MaybeUninit<T>> {
let ptr = if size_of::<T>() == 0 {
NonNull::dangling()
} else {
let layout = Layout::new::<MaybeUninit<T>>();
let ptr = unsafe { alloc(layout) } as *mut MaybeUninit<T>;
if ptr.is_null() {
handle_alloc_error(layout);
}
unsafe { NonNull::new_unchecked(ptr) }
};
unsafe { Box::from_raw(ptr.as_ptr()) }
}
#[doc(hidden)]
pub unsafe fn new_box_zeroed<T>() -> Box<T> {
let ptr = if size_of::<T>() == 0 {
NonNull::dangling()
} else {
let layout = Layout::new::<MaybeUninit<T>>();
let ptr = unsafe { alloc_zeroed(layout) as *mut MaybeUninit<T> };
if ptr.is_null() {
handle_alloc_error(layout);
}
unsafe { NonNull::new_unchecked(ptr) }
};
unsafe { Box::from_raw(ptr.as_ptr() as *mut T) }
}
#[inline(always)]
#[doc(hidden)]
pub unsafe fn fill_array<T: Copy, const SIZE: usize>(array: *mut [T; SIZE], value: T) {
let array = array as *mut T;
if size_of::<T>() == 1 {
let value_byte: *const u8 = core::ptr::addr_of!(value) as *const u8;
core::ptr::write_bytes(array as *mut u8, *value_byte, SIZE);
} else {
for i in 0..SIZE {
array.add(i).write_unaligned(value);
}
}
}
#[doc(hidden)]
pub unsafe fn assume_init<T>(b: Box<MaybeUninit<T>>) -> Box<T> {
transmute(b)
}