use crate::layout::*;
use alloc::alloc::{alloc, dealloc};
use core::fmt;
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::ptr::{NonNull, drop_in_place};
#[repr(transparent)]
pub struct PageRef<H, T> {
inner: NonNull<u8>,
_phantom: PhantomData<(H,T)>,
}
impl<H, T> Eq for PageRef<H, T> {}
impl<H, T> PartialEq for PageRef<H, T> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool { self.inner == other.inner }
}
impl<H, T> Clone for PageRef<H, T> {
#[inline(always)]
fn clone(&self) -> Self { PageRef { inner: self.inner, _phantom: self._phantom } }
}
impl<H, T> Copy for PageRef<H, T> {}
impl<H, T> PageRef<H, T> {
#[inline(always)]
pub fn new(header: H, items: u32) -> Self {
let layout = PageLayout::<H, T>::with_capacity(items);
let ptr = unsafe { alloc(layout.layout()) }; unsafe { Self::from_uninit(ptr, header, layout) } }
#[inline(always)]
pub unsafe fn capacity(self) -> u32 { self.desc().items }
#[inline(always)]
pub unsafe fn header(&self) -> &H { &(*self.page_header()).header }
#[inline(always)]
pub unsafe fn header_mut(&mut self) -> &mut H { &mut (*self.page_header()).header }
#[inline(always)]
pub unsafe fn data(self) -> *mut MaybeUninit<T> {
let raw = self.inner.as_ptr();
let offset = (*raw.cast::<PageHeader<H>>()).desc.data;
raw.add(offset as usize).cast()
}
#[inline(always)]
pub unsafe fn layout(self) -> PageLayout<H, T> { PageLayout::with_capacity(self.desc().items) }
pub unsafe fn drop(page: Self) {
let raw = page.inner.as_ptr();
drop_in_place(raw.cast::<PageHeader<H>>());
let layout = PageLayout::<H, T>::with_capacity(page.desc().items);
dealloc(raw, layout.layout());
}
#[inline(always)]
pub unsafe fn from_uninit(raw_ptr: *mut u8, header: H, layout: PageLayout<H, T>) -> Self {
let header_ptr = raw_ptr.cast::<PageHeader<H>>();
let header = PageHeader { header, desc: PageDesc::from(layout) };
header_ptr.write(header);
let inner = NonNull::new_unchecked(header_ptr.cast());
PageRef { inner, _phantom: PhantomData }
}
#[inline(always)]
pub(crate) fn desc(self) -> PageDesc { unsafe { &*self.page_header() }.desc }
#[inline(always)]
pub(crate) fn page_header(self) -> *mut PageHeader<H> { self.inner.as_ptr().cast::<PageHeader<H>>() }
}
impl<H, T> fmt::Debug for PageRef<H, T> {
#[inline(always)]
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "PageRef {{}}") }
}