use core::marker::PhantomData;
use core::mem;
use core::ptr::NonNull;
use allocator_api2::alloc::Allocator;
use super::chunk::Chunk;
use super::shared_chunk::SharedChunk;
pub(crate) struct ChunkRef<A: Allocator + Clone> {
chunk: NonNull<SharedChunk<A>>,
_phantom: PhantomData<*const SharedChunk<A>>,
}
impl<A: Allocator + Clone> ChunkRef<A> {
#[inline]
pub(crate) unsafe fn adopt(chunk: NonNull<SharedChunk<A>>) -> Self {
Self {
chunk,
_phantom: PhantomData,
}
}
#[inline]
pub(crate) unsafe fn from_value_ptr<T: ?Sized>(value: NonNull<T>) -> Self {
unsafe {
let header = SharedChunk::<A>::header_from_value_ptr(value.cast::<u8>());
let chunk_fat = SharedChunk::<A>::header_to_fat(header.as_ptr());
Self {
chunk: NonNull::new_unchecked(chunk_fat),
_phantom: PhantomData,
}
}
}
#[inline]
pub(crate) unsafe fn clone_from_value_ptr<T: ?Sized>(value: NonNull<T>) -> Self {
unsafe {
let header = SharedChunk::<A>::header_from_value_ptr(value.cast::<u8>());
let chunk_fat = SharedChunk::<A>::header_to_fat(header.as_ptr());
let chunk = NonNull::new_unchecked(chunk_fat);
chunk.as_ref().inc_ref();
Self {
chunk,
_phantom: PhantomData,
}
}
}
#[inline]
pub(crate) fn forget(self) -> NonNull<SharedChunk<A>> {
let chunk = self.chunk;
mem::forget(self);
chunk
}
}
impl<A: Allocator + Clone> Drop for ChunkRef<A> {
#[inline]
fn drop(&mut self) {
unsafe {
SharedChunk::<A>::release_one_ref(self.chunk);
}
}
}