use std::alloc::{GlobalAlloc, Layout, System};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
pub(crate) struct SysBox<T> {
ptr: NonNull<T>,
_marker: PhantomData<T>,
}
impl<T> SysBox<T> {
pub fn new(val: T) -> Self {
let layout = Layout::new::<T>();
let raw = unsafe { System.alloc(layout) } as *mut T;
let Some(ptr) = NonNull::new(raw) else {
std::alloc::handle_alloc_error(layout);
};
unsafe {
ptr.as_ptr().write(val);
}
Self {
ptr,
_marker: PhantomData,
}
}
pub unsafe fn new_zeroed() -> Self {
let layout = Layout::new::<T>();
let raw = unsafe { System.alloc_zeroed(layout) } as *mut T;
let Some(ptr) = NonNull::new(raw) else {
std::alloc::handle_alloc_error(layout);
};
Self {
ptr,
_marker: PhantomData,
}
}
#[inline]
pub fn as_non_null(&self) -> NonNull<T> {
self.ptr
}
}
impl<T> Deref for SysBox<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { self.ptr.as_ref() }
}
}
impl<T> DerefMut for SysBox<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.ptr.as_mut() }
}
}
impl<T> Drop for SysBox<T> {
fn drop(&mut self) {
unsafe {
std::ptr::drop_in_place(self.ptr.as_ptr());
System.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::<T>());
}
}
}
unsafe impl<T: Send> Send for SysBox<T> {}
unsafe impl<T: Sync> Sync for SysBox<T> {}