use std::{mem, ptr, slice};
use crate::alloc::{self, tail};
#[repr(transparent)]
pub struct Block<H, T, N: alloc::raw::TailExtent = usize> {
pub(in crate::alloc::tail) pointer: ptr::NonNull<tail::Prefix<H, T, N>>,
}
impl<H, T, N: alloc::raw::TailExtent> Block<H, mem::MaybeUninit<T>, N> {
pub(crate) unsafe fn assume_init(self) -> Block<H, T, N> {
let block = mem::ManuallyDrop::new(self);
Block {
pointer: block.pointer.cast(),
}
}
}
impl<H, T, N: alloc::raw::TailExtent> Block<H, T, N> {
pub(crate) fn extent(&self) -> N {
tail::View::new(self).len_proof().extent()
}
pub fn header_mut(&mut self) -> &mut H {
unsafe { &mut self.pointer.as_mut().header }
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.parts_mut().1
}
pub fn parts_mut(&mut self) -> (&mut H, &mut [T]) {
let len = tail::View::new(self).len_proof();
let header = unsafe { &mut self.pointer.as_mut().header };
let values = unsafe { slice::from_raw_parts_mut(self.data(), len.len()) };
(header, values)
}
pub(crate) fn into_header(self) -> H {
let owner = mem::ManuallyDrop::new(self);
let len = tail::View::new(&owner).len_proof();
let values = ptr::slice_from_raw_parts_mut(owner.data(), len.len());
unsafe { ptr::drop_in_place(values) };
let header = unsafe { ptr::read(&owner.pointer.as_ref().header) };
unsafe { alloc::raw::LayoutExt::deallocate(len.layout(), owner.pointer) };
header
}
pub(in crate::alloc::tail) fn data(&self) -> *mut T {
tail::View::new(self).data().as_ptr()
}
}
impl<H, T, N: alloc::raw::TailExtent> Drop for Block<H, T, N> {
fn drop(&mut self) {
let len = tail::View::new(self).len_proof();
let values = ptr::slice_from_raw_parts_mut(self.data(), len.len());
unsafe { ptr::drop_in_place(values) };
unsafe { ptr::drop_in_place(self.pointer.as_ptr()) };
unsafe { alloc::raw::LayoutExt::deallocate(len.layout(), self.pointer) };
}
}