use core::{
alloc::Layout,
marker::PhantomData,
mem::{self},
ops::CoerceUnsized,
};
use alloc::alloc::{handle_alloc_error, Global};
use crate::buffer::{AllocatedBuffer, Buffer, UnmanagedBuffer};
pub struct RawBox<T, B = AllocatedBuffer<T>>
where
T: ?Sized,
B: Buffer<T> + ?Sized,
{
_marker: PhantomData<fn() -> *const T>,
buffer: B,
}
#[allow(clippy::use_self)]
impl<T> RawBox<T> {
fn global_allocator_storage() -> AllocatedBuffer<T> {
AllocatedBuffer::new().unwrap_or_else(|_| handle_alloc_error(Layout::new::<T>()))
}
#[inline]
pub fn new(value: T) -> Self {
Self::new_in(value, Self::global_allocator_storage(), &Global)
}
#[inline]
pub fn new_uninit() -> RawBox<mem::MaybeUninit<T>, AllocatedBuffer<T>> {
Self::new_uninit_in(Self::global_allocator_storage())
}
#[inline]
pub fn new_zeroed() -> RawBox<mem::MaybeUninit<T>, AllocatedBuffer<T>> {
Self::new_uninit_in(
AllocatedBuffer::new_zeroed()
.unwrap_or_else(|_| handle_alloc_error(Layout::new::<T>())),
)
}
}
#[allow(clippy::use_self)]
impl<T> RawBox<[T]> {
#[inline]
pub fn new_uninit_slice(len: usize) -> RawBox<[mem::MaybeUninit<T>], AllocatedBuffer<[T]>> {
RawBox {
buffer: AllocatedBuffer::new_slice(&Global, len)
.unwrap_or_else(|_| handle_alloc_error(Layout::array::<T>(len).unwrap())),
_marker: PhantomData,
}
}
#[inline]
pub fn new_zeroed_slice(len: usize) -> RawBox<[mem::MaybeUninit<T>], AllocatedBuffer<[T]>> {
RawBox {
buffer: AllocatedBuffer::new_slice_zeroed(&Global, len)
.unwrap_or_else(|_| handle_alloc_error(Layout::array::<T>(len).unwrap())),
_marker: PhantomData,
}
}
}
#[allow(clippy::use_self)]
impl<T, B> RawBox<T, B>
where
B: Buffer<T>,
{
#[inline]
pub fn new_in(value: T, mut buffer: B, data: &B::ExternalData) -> Self {
unsafe { buffer.as_mut_ptr(data).write(value) };
Self {
buffer,
_marker: PhantomData,
}
}
#[inline]
pub fn new_uninit_in(buffer: B) -> RawBox<mem::MaybeUninit<T>, B>
where
B: Buffer<mem::MaybeUninit<T>>,
{
RawBox {
buffer,
_marker: PhantomData,
}
}
}
#[allow(clippy::use_self)]
impl<T, B> RawBox<[T], B>
where
B: Buffer<[T]>,
{
#[inline]
pub fn new_uninit_slice_in(buffer: B) -> RawBox<[mem::MaybeUninit<T>], B>
where
B: Buffer<[mem::MaybeUninit<T>]>,
{
RawBox {
buffer,
_marker: PhantomData,
}
}
}
impl<T: ?Sized, B> RawBox<T, B>
where
B: Buffer<T>,
{
pub unsafe fn from_buffer(buffer: B) -> Self {
Self {
buffer,
_marker: PhantomData,
}
}
}
#[allow(clippy::use_self)]
impl<T, B> RawBox<mem::MaybeUninit<T>, B>
where
B: Buffer<T> + Buffer<mem::MaybeUninit<T>>,
{
#[inline]
pub unsafe fn assume_init(self) -> RawBox<T, B> {
RawBox {
buffer: self.buffer,
_marker: PhantomData,
}
}
}
#[allow(clippy::use_self)]
impl<T, B> RawBox<[mem::MaybeUninit<T>], B>
where
B: Buffer<[T]> + Buffer<[mem::MaybeUninit<T>]>,
{
#[inline]
pub unsafe fn assume_init(self) -> RawBox<[T], B> {
RawBox {
buffer: self.buffer,
_marker: PhantomData,
}
}
}
impl<T, B> RawBox<T, B>
where
T: ?Sized,
B: Buffer<T>,
{
pub fn free(self, data: &B::ExternalData)
where
B: UnmanagedBuffer<T>,
{
self.buffer.free(data)
}
pub fn buffer(&self) -> &B {
&self.buffer
}
pub fn buffer_mut(&mut self) -> &mut B {
&mut self.buffer
}
pub fn as_ref(&self, data: &B::ExternalData) -> &T {
unsafe { &*self.buffer.as_ptr(data) }
}
pub fn as_mut(&mut self, data: &B::ExternalData) -> &mut T {
unsafe { &mut *self.buffer.as_mut_ptr(data) }
}
}
impl<T, U, BT, BU> CoerceUnsized<RawBox<U, BU>> for RawBox<T, BT>
where
T: ?Sized,
U: ?Sized,
BT: Buffer<T> + CoerceUnsized<BU>,
BU: Buffer<U>,
{
}