use std::{num, ops, ptr};
use crate::{
buffer,
buffer::{resident, storage, storage::backing},
mem::rc,
};
pub(in crate::buffer) type Rc<P = ()> = crate::mem::raw::Owner<crate::buffer::raw::Header<P>>;
#[repr(transparent)]
pub(in crate::buffer) struct Unique<'a, P: crate::buffer::raw::Policy = ()>(&'a mut Rc<P>);
impl<P: crate::buffer::raw::Policy> Rc<P> {
pub(in crate::buffer) fn capacity(&self) -> num::NonZero<u32> {
self.get().capacity()
}
pub(in crate::buffer) fn seed(&self) -> P::Seed {
self.get().policy.seed()
}
pub(in crate::buffer) fn data(&self) -> *const u8 {
crate::buffer::raw::Header::data(self.as_ptr()).as_ptr()
}
pub(in crate::buffer) fn is_unique(&self) -> bool {
use crate::mem::raw::Edge as _;
self.get().prefix.is_unique()
}
}
impl Rc<resident::Lease<'_>> {
pub(in crate::buffer) fn try_own(self) -> Result<Rc, Self> {
use crate::buffer::{raw::Header, resident::Lease};
const EXTRA: u32 = {
assert!(size_of::<Header<Lease<'_>>>() >= size_of::<Header<()>>());
let extra = size_of::<Header<Lease<'_>>>() - size_of::<Header<()>>();
assert!(extra <= u32::MAX as usize);
extra as u32
};
let original = self.capacity();
let Some(capacity) = original.checked_add(EXTRA) else {
return Err(self);
};
if !self.is_unique() || align_of::<Header<Lease<'_>>>() != align_of::<Header<()>>() {
return Err(self);
}
let pointer = self.into_raw();
unsafe { ptr::drop_in_place(&raw mut (*pointer.as_ptr()).policy) };
let mut pointer = pointer.cast::<Header<()>>();
unsafe {
pointer.as_mut().set_capacity(capacity);
Ok(Rc::from_raw(pointer))
}
}
}
impl<'a, P: crate::buffer::raw::Policy> Unique<'a, P> {
pub(in crate::buffer) fn capacity(&self) -> num::NonZero<u32> {
self.0.capacity()
}
pub(in crate::buffer) fn policy(&self) -> &P {
&self.0.get().policy
}
pub(in crate::buffer) fn data(&self) -> *const u8 {
self.0.data()
}
pub(in crate::buffer) fn slot(self) -> &'a mut Rc<P> {
self.0
}
pub(in crate::buffer) fn try_resize(
&mut self,
target: num::NonZero<u32>,
debit: P::Charge,
) -> Result<(), crate::alloc::Exhausted> {
let pointer = self.0.as_ptr();
let pointer = unsafe { crate::buffer::raw::Growth::try_resize(pointer, target, debit)? };
unsafe {
ptr::write(self.0, Rc::from_raw(pointer));
}
Ok(())
}
pub(in crate::buffer) fn replace<I: crate::buffer::raw::SliceExt>(
self,
pointer: ptr::NonNull<crate::buffer::raw::Header<P>>,
target: num::NonZero<u32>,
debit: P::Charge,
range: ops::Range<u32>,
tail: I,
) {
use crate::buffer::raw::SliceExt as _;
let len = (range.end - range.start) as usize;
let dst = crate::buffer::raw::Header::data(pointer);
unsafe {
let source = buffer::raw::range(self.data(), range.start as usize, len);
(source, tail).copy_to(dst.as_ptr());
}
let current = self.capacity();
let slot = self.slot();
let old = unsafe { ptr::read(slot) }.into_raw();
unsafe {
crate::buffer::raw::Growth::write(old, pointer, target, debit);
ptr::write(slot, crate::buffer::raw::Rc::from_raw(pointer));
crate::buffer::raw::Header::free(old, current);
}
}
}
unsafe impl<P: crate::buffer::raw::Policy> buffer::raw::Retain for Rc<P> {
fn try_retain(&self) -> Result<Self, rc::Error> {
self.try_clone()
}
}
const _: () = assert!(size_of::<Rc<()>>() == size_of::<ptr::NonNull<()>>());
const _: () = assert!(size_of::<Option<Rc<()>>>() == size_of::<ptr::NonNull<()>>());
const _: () = assert!(size_of::<Unique<'static, ()>>() == size_of::<ptr::NonNull<()>>());
impl<P: crate::buffer::raw::Policy> Rc<P> {
pub(in crate::buffer) fn access(&mut self) -> Option<Unique<'_, P>> {
if self.is_unique() {
Some(Unique(self))
} else {
None
}
}
}
impl<P: buffer::raw::Policy> Rc<P> {
pub(in crate::buffer) unsafe fn into_range(
self,
start: u32,
len: u32,
) -> storage::Shared<Self> {
let pointer = crate::buffer::raw::Header::data(self.as_ptr());
let pointer = unsafe { pointer.add(start as usize) };
unsafe { storage::Shared::from_raw(pointer, len as usize, self) }
}
}
impl<'d> backing::Owner<'d> for Rc<resident::Lease<'d>> {
fn root<'a>(&'a self) -> Option<backing::Root<'a, 'd>>
where
'd: 'a,
{
Some(backing::Root::Resident(self.get()))
}
}