use core::fmt::{Debug, Error, Formatter};
use core::hash::{Hash, Hasher};
use core::mem::transmute;
use crate::OnceCellCompatible;
pub type VoidPtr = *mut u8;
pub type DependentInner = VoidPtr;
pub struct UnsafeOnceSelfCell<Owner: 'static, DependentCell: OnceCellCompatible<DependentInner>> {
owner_ptr: *mut Owner,
dependent_cell: DependentCell,
}
impl<Owner, DependentCell> UnsafeOnceSelfCell<Owner, DependentCell>
where
DependentCell: OnceCellCompatible<DependentInner>,
{
pub unsafe fn new(owner: Owner) -> Self {
UnsafeOnceSelfCell {
owner_ptr: Box::into_raw(Box::new(owner)),
dependent_cell: DependentCell::new(),
}
}
pub unsafe fn get_owner<'a>(&'a self) -> &'a Owner {
&*self.owner_ptr
}
pub unsafe fn get_or_init_dependent<'a, Dependent>(
&'a self,
make_dependent: fn(&'a Owner) -> Dependent,
) -> &'a Dependent {
let dependent_void_ptr = self.dependent_cell.get_or_init(|| {
let owner = transmute::<*mut Owner, &'a Owner>(self.owner_ptr);
let dependent_ptr = Box::into_raw(Box::new(make_dependent(owner)));
transmute::<*mut Dependent, VoidPtr>(dependent_ptr)
});
let dependent_ptr = transmute::<VoidPtr, *mut Dependent>(*dependent_void_ptr);
&*dependent_ptr
}
pub unsafe fn drop_dependent<Dependent>(&mut self) {
if let Some(dependent_void_ptr) = self.dependent_cell.take() {
let dependent_ptr = transmute::<VoidPtr, *mut Dependent>(dependent_void_ptr);
let dependent_box = Box::from_raw(dependent_ptr);
drop(dependent_box);
}
}
pub fn dependent_is_none(&self) -> bool {
self.dependent_cell.get().is_none()
}
}
impl<Owner, DependentCell> Drop for UnsafeOnceSelfCell<Owner, DependentCell>
where
DependentCell: OnceCellCompatible<DependentInner>,
{
fn drop(&mut self) {
unsafe {
drop(Box::from_raw(self.owner_ptr));
}
}
}
unsafe impl<Owner, DependentCell> Send for UnsafeOnceSelfCell<Owner, DependentCell>
where
Owner: Send,
DependentCell: OnceCellCompatible<DependentInner> + Send,
{
}
unsafe impl<Owner, DependentCell> Sync for UnsafeOnceSelfCell<Owner, DependentCell>
where
Owner: Sync,
DependentCell: OnceCellCompatible<DependentInner> + Sync,
{
}
impl<Owner, DependentCell> Clone for UnsafeOnceSelfCell<Owner, DependentCell>
where
Owner: Clone,
DependentCell: OnceCellCompatible<DependentInner>,
{
fn clone(&self) -> Self {
UnsafeOnceSelfCell {
owner_ptr: Box::into_raw(Box::new(unsafe { self.get_owner() }.clone())),
dependent_cell: DependentCell::new(),
}
}
}
impl<Owner, DependentCell> PartialEq for UnsafeOnceSelfCell<Owner, DependentCell>
where
Owner: PartialEq,
DependentCell: OnceCellCompatible<DependentInner>,
{
fn eq(&self, other: &Self) -> bool {
unsafe { *self.get_owner() == *other.get_owner() }
}
}
impl<Owner, DependentCell> Eq for UnsafeOnceSelfCell<Owner, DependentCell>
where
Owner: Eq,
DependentCell: OnceCellCompatible<DependentInner>,
{
}
impl<Owner, DependentCell> Hash for UnsafeOnceSelfCell<Owner, DependentCell>
where
Owner: Hash,
DependentCell: OnceCellCompatible<DependentInner>,
{
fn hash<H: Hasher>(&self, state: &mut H) {
unsafe { self.get_owner() }.hash(state);
}
}
impl<Owner, DependentCell> Debug for UnsafeOnceSelfCell<Owner, DependentCell>
where
Owner: Debug,
DependentCell: Debug + OnceCellCompatible<DependentInner>,
{
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
write!(
fmt,
"UnsafeOnceSelfCell {{ owner: {:?}, dependent_cell: {:?} }}",
unsafe { self.get_owner() },
self.dependent_cell
)
}
}