use std::{alloc::Layout, num, ptr};
use crate::{alloc, buffer::storage::regions};
#[repr(C)]
#[derive(Debug)]
pub(in crate::buffer) struct Header<P: crate::buffer::raw::Policy> {
pub(super) prefix: regions::Prefix<num::NonZero<u32>>,
pub(super) policy: P,
}
unsafe impl<P: crate::buffer::raw::Policy> crate::mem::raw::Edge for Header<P> {
fn count(&self) -> &crate::mem::raw::Count {
crate::mem::raw::Edge::count(&self.prefix)
}
}
unsafe impl<P: crate::buffer::raw::Policy> crate::mem::raw::Target for Header<P> {
unsafe fn destroy(pointer: ptr::NonNull<Self>) {
unsafe { Self::destroy(pointer) };
}
}
impl<P: crate::buffer::raw::Policy> Header<P> {
pub(in crate::buffer) const DATA_OFFSET: usize = size_of::<Self>();
const ALIGN: usize = align_of::<Self>();
const VALID: () = assert!(alloc::raw::Layout::<u8>::fits_after(
Layout::new::<Self>(),
u32::MAX as usize
));
pub(in crate::buffer) fn layout(capacity: num::NonZero<u32>) -> Layout {
let () = Self::VALID;
unsafe {
alloc::raw::Layout::<u8>::at(
Self::DATA_OFFSET,
capacity.get() as usize,
num::NonZero::<usize>::MIN.saturating_add(Self::ALIGN - 1),
)
}
}
pub(in crate::buffer) unsafe fn destroy(pointer: ptr::NonNull<Self>) {
let header = unsafe { pointer.as_ref() };
let capacity = header.capacity();
unsafe { ptr::drop_in_place(pointer.as_ptr()) };
unsafe { Self::free(pointer, capacity) };
}
pub(super) unsafe fn free(pointer: ptr::NonNull<Self>, capacity: num::NonZero<u32>) {
unsafe { crate::alloc::raw::dealloc(Self::layout(capacity), pointer) };
}
pub(in crate::buffer) fn capacity(&self) -> num::NonZero<u32> {
self.prefix.word()
}
pub(in crate::buffer) unsafe fn set_capacity(&mut self, capacity: num::NonZero<u32>) {
unsafe { self.prefix.write(capacity) };
}
pub(super) fn data(pointer: ptr::NonNull<Self>) -> ptr::NonNull<u8> {
unsafe { pointer.cast::<u8>().add(Self::DATA_OFFSET) }
}
pub(in crate::buffer) unsafe fn slice(pointer: ptr::NonNull<Self>) -> ptr::NonNull<[u8]> {
let capacity = unsafe { pointer.as_ref() }.capacity().get() as usize;
ptr::NonNull::slice_from_raw_parts(Self::data(pointer), capacity)
}
}
const _: () = {
assert!(size_of::<Header<()>>() == size_of::<regions::Prefix>());
assert!(size_of::<regions::Prefix<num::NonZero<u32>>>() == size_of::<regions::Prefix>());
assert!(align_of::<regions::Prefix<num::NonZero<u32>>>() == align_of::<regions::Prefix>());
};
const _: () = assert!(align_of::<Header<()>>() >= 8);