use std::ops::Deref;
use stable_deref_trait::StableDeref;
use super::*;
pub(crate) struct OwnedCellInner<O, D> {
dep: D,
owner: O,
}
impl<O, D> Deref for OwnedCellInner<O, D> {
type Target = D;
fn deref(&self) -> &Self::Target {
&self.dep
}
}
impl<O, D> DerefMut for OwnedCellInner<O, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.dep
}
}
pub(crate) struct OwnedCell<O, D> {
inner: OwnedCellInner<O, D>,
}
impl<O, D> OwnedCell<O, D> {
pub fn owner(&self) -> &O {
&self.inner.owner
}
}
pub(crate) struct MutOwnedCell<O, D> {
inner: OwnedCellInner<O, D>,
}
impl<O, D> MutOwnedCell<O, D>
where
O: StableDeref + DerefMut,
{
pub(crate) fn try_make<'a, E>(
mut owner: O,
make_dependent: impl FnOnce(&'a mut O::Target) -> Result<D, E>,
) -> Result<Self, E>
where
O::Target: 'a,
{
let stable_deref: *mut O::Target = owner.deref_mut();
Ok(Self {
inner: OwnedCellInner {
owner,
dep: make_dependent(unsafe { &mut *stable_deref })?,
},
})
}
}
impl<O, D> OwnedCell<O, D>
where
O: StableDeref,
{
pub(crate) fn try_make<'a, E>(
owner: O,
make_dependent: impl FnOnce(&'a O::Target) -> Result<D, E>,
) -> Result<Self, E>
where
O::Target: 'a,
{
let stable_deref: *const O::Target = owner.deref();
Ok(Self {
inner: OwnedCellInner {
owner,
dep: make_dependent(unsafe { &*stable_deref })?,
},
})
}
}
pub(crate) trait MoveDependent<D> {
fn move_dependent<R>(self, f: impl FnOnce(D) -> R) -> R;
}
impl<O, D> MoveDependent<D> for MutOwnedCell<O, D> {
fn move_dependent<R>(self, f: impl FnOnce(D) -> R) -> R {
f(self.inner.dep)
}
}
impl<O, D> MoveDependent<D> for OwnedCell<O, D> {
fn move_dependent<R>(self, f: impl FnOnce(D) -> R) -> R {
f(self.inner.dep)
}
}
#[allow(dead_code)]
impl<O, D> OwnedCellInner<O, D> {
fn move_dependent<R>(self, f: impl FnOnce(D) -> R) -> R {
f(self.dep)
}
}
impl<O, D> DerefMut for OwnedCell<O, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<O, D> Deref for OwnedCell<O, D> {
type Target = OwnedCellInner<O, D>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<O, D> Deref for MutOwnedCell<O, D> {
type Target = OwnedCellInner<O, D>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<O, D> DerefMut for MutOwnedCell<O, D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}