use crate::offset::Nullable;
use crate::{Offset, PointerRecomposition, SelfRef};
pub struct SelfRefCell<T: PointerRecomposition, I: Offset = isize> {
value: T,
ptr: SelfRef<T, I>,
}
impl<T: PointerRecomposition, I: Offset + Nullable> SelfRefCell<T, I> {
pub fn new(value: T) -> Result<Self, I::Error> {
let mut this = Self {
value,
ptr: SelfRef::null(),
};
this.ptr.set(&mut this.value)?;
Ok(this)
}
pub fn get(&self) -> &T {
self.try_get()
.expect("SelfRefCell accessed before initialisation")
}
#[inline]
pub fn try_get(&self) -> Option<&T> {
if !self.ptr.is_ready() {
return None;
}
let base = self as *const _ as *const u8;
Some(unsafe { self.ptr.get_ref_from_base_unchecked(base) })
}
pub fn get_mut(&mut self) -> &mut T {
self.try_get_mut()
.expect("SelfRefCell accessed before initialisation")
}
#[inline]
pub fn try_get_mut(&mut self) -> Option<&mut T> {
if !self.ptr.is_ready() {
return None;
}
let base = self as *mut _ as *mut u8;
Some(unsafe { self.ptr.get_mut_from_base_unchecked(base) })
}
pub fn into_inner(self) -> T {
self.value
}
}