reactive_graph/owner/
arena_item.rsuse super::{
arena::{Arena, NodeId},
LocalStorage, Storage, SyncStorage, OWNER,
};
use crate::traits::{Dispose, IntoInner, IsDisposed};
use send_wrapper::SendWrapper;
use std::{any::Any, hash::Hash, marker::PhantomData};
#[derive(Debug)]
pub struct ArenaItem<T, S = SyncStorage> {
node: NodeId,
#[allow(clippy::type_complexity)]
ty: PhantomData<fn() -> (SendWrapper<T>, S)>,
}
impl<T, S> Copy for ArenaItem<T, S> {}
impl<T, S> Clone for ArenaItem<T, S> {
fn clone(&self) -> Self {
*self
}
}
impl<T, S> PartialEq for ArenaItem<T, S> {
fn eq(&self, other: &Self) -> bool {
self.node == other.node
}
}
impl<T, S> Eq for ArenaItem<T, S> {}
impl<T, S> Hash for ArenaItem<T, S> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.node.hash(state);
}
}
impl<T, S> ArenaItem<T, S>
where
T: 'static,
S: Storage<T>,
{
#[track_caller]
pub fn new_with_storage(value: T) -> Self {
let node = {
Arena::with_mut(|arena| {
arena.insert(
Box::new(S::wrap(value)) as Box<dyn Any + Send + Sync>
)
})
};
OWNER.with(|o| {
if let Some(owner) = &*o.borrow() {
owner.register(node);
}
});
Self {
node,
ty: PhantomData,
}
}
}
impl<T, S> Default for ArenaItem<T, S>
where
T: Default + 'static,
S: Storage<T>,
{
#[track_caller] fn default() -> Self {
Self::new_with_storage(Default::default())
}
}
impl<T> ArenaItem<T>
where
T: Send + Sync + 'static,
{
#[track_caller]
pub fn new(value: T) -> Self {
ArenaItem::new_with_storage(value)
}
}
impl<T> ArenaItem<T, LocalStorage>
where
T: 'static,
{
#[track_caller]
pub fn new_local(value: T) -> Self {
ArenaItem::new_with_storage(value)
}
}
impl<T, S: Storage<T>> ArenaItem<T, S> {
#[track_caller]
pub fn try_with_value<U>(&self, fun: impl FnOnce(&T) -> U) -> Option<U> {
S::try_with(self.node, fun)
}
#[track_caller]
pub fn try_update_value<U>(
&self,
fun: impl FnOnce(&mut T) -> U,
) -> Option<U> {
S::try_with_mut(self.node, fun)
}
}
impl<T: Clone, S: Storage<T>> ArenaItem<T, S> {
#[track_caller]
pub fn try_get_value(&self) -> Option<T> {
S::try_with(self.node, Clone::clone)
}
}
impl<T, S> IsDisposed for ArenaItem<T, S> {
fn is_disposed(&self) -> bool {
Arena::with(|arena| !arena.contains_key(self.node))
}
}
impl<T, S> Dispose for ArenaItem<T, S> {
fn dispose(self) {
Arena::with_mut(|arena| arena.remove(self.node));
}
}
impl<T, S: Storage<T>> IntoInner for ArenaItem<T, S> {
type Value = T;
#[inline(always)]
fn into_inner(self) -> Option<Self::Value> {
S::take(self.node)
}
}