#[cfg(doc)] use crate as ialloc;
use crate::*;
use crate::meta::Stateless;
use fat::*;
use core::alloc::Layout;
use core::marker::PhantomData;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ptr::*;
pub struct ABox<T: ?Sized, A: Free> {
allocator: A,
data: NonNull<T>,
_phantom: PhantomData<T>,
}
unsafe impl<T: ?Sized + Send, A: Free + Send> Send for ABox<T, A> {}
unsafe impl<T: ?Sized + Sync, A: Free + Sync> Sync for ABox<T, A> {}
impl<T: ?Sized, A: Free> Drop for ABox<T, A> {
fn drop(&mut self) {
let layout = self.layout();
unsafe { self.data.as_ptr().drop_in_place() };
unsafe { self.allocator.free(self.data.cast(), layout) };
}
}
impl<T: ?Sized, A: Free> ABox<T, A> {
#[inline(always)] pub fn allocator(this: &Self) -> &A { &this.allocator }
#[inline(always)] pub fn as_ptr(this: &Self) -> *const T { this.data.as_ptr() }
#[inline(always)] pub fn as_mut_ptr(this: &mut Self) -> *mut T { this.data.as_ptr() }
#[inline(always)] pub(super) fn data(&self) -> NonNull<T> { self.data }
#[inline(always)] pub(super) unsafe fn set_data(&mut self, data: NonNull<T>) { self.data = data; }
#[inline(always)] pub(super) fn layout(&self) -> Layout { Layout::for_value(&**self) }
pub unsafe fn from_raw_in(data: NonNull<T>, allocator: A) -> Self {
Self { data, allocator, _phantom: PhantomData }
}
pub unsafe fn from_raw(data: NonNull<T>) -> Self where A : Stateless {
unsafe { Self::from_raw_in(data, A::default()) }
}
pub fn into_raw_with_allocator(this: Self) -> (NonNull<T>, A) {
let this = ManuallyDrop::new(this);
let data = this.data;
let allocator = unsafe { core::ptr::read(&this.allocator) };
(data, allocator)
}
pub fn into_raw(this: Self) -> NonNull<T> where A : Stateless {
Self::into_raw_with_allocator(this).0
}
pub fn leak<'a>(this: Self) -> &'a mut T where A: 'a {
let mut raw = ABox::into_raw_with_allocator(this).0;
unsafe { raw.as_mut() }
}
}
impl<T, A: Free> ABox<T, A> {
pub fn into_inner(this: Self) -> T { Self::into_inner_with_allocator(this).0 }
pub fn into_inner_with_allocator(this: Self) -> (T, A) {
let layout = this.layout();
let (ptr, allocator) = ABox::into_raw_with_allocator(this);
let data = unsafe { ptr.as_ptr().read() };
unsafe { allocator.free(ptr.cast(), layout) };
(data, allocator)
}
}
impl<T, A: Free> ABox<MaybeUninit<T>, A> {
pub(crate) unsafe fn assume_init(self) -> ABox<T, A> {
let (data, allocator) = ABox::into_raw_with_allocator(self);
unsafe { ABox::from_raw_in(data.cast(), allocator) }
}
pub(crate) fn write(boxed: Self, value: T) -> ABox<T, A> {
unsafe { boxed.data.as_ptr().write(MaybeUninit::new(value)) };
unsafe { boxed.assume_init() }
}
}
impl<T, A: Free> ABox<[MaybeUninit<T>], A> {
pub(crate) unsafe fn assume_init(self) -> ABox<[T], A> {
let (data, allocator) = ABox::into_raw_with_allocator(self);
let data = util::nn::slice_from_raw_parts(data.cast(), data.len());
unsafe { ABox::from_raw_in(data, allocator) }
}
}