reactive_graph/owner/
arena_item.rs1use super::{
2 arena::{Arena, NodeId},
3 LocalStorage, Storage, SyncStorage, OWNER,
4};
5use crate::traits::{Dispose, IntoInner, IsDisposed};
6use send_wrapper::SendWrapper;
7use std::{any::Any, hash::Hash, marker::PhantomData};
8
9#[derive(Debug)]
12pub struct ArenaItem<T, S = SyncStorage> {
13 node: NodeId,
14 #[allow(clippy::type_complexity)]
15 ty: PhantomData<fn() -> (SendWrapper<T>, S)>,
16}
17
18impl<T, S> Copy for ArenaItem<T, S> {}
19
20impl<T, S> Clone for ArenaItem<T, S> {
21 fn clone(&self) -> Self {
22 *self
23 }
24}
25
26impl<T, S> PartialEq for ArenaItem<T, S> {
27 fn eq(&self, other: &Self) -> bool {
28 self.node == other.node
29 }
30}
31
32impl<T, S> Eq for ArenaItem<T, S> {}
33
34impl<T, S> Hash for ArenaItem<T, S> {
35 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
36 self.node.hash(state);
37 }
38}
39
40impl<T, S> ArenaItem<T, S>
41where
42 T: 'static,
43 S: Storage<T>,
44{
45 #[track_caller]
47 pub fn new_with_storage(value: T) -> Self {
48 let node = {
49 Arena::with_mut(|arena| {
50 arena.insert(
51 Box::new(S::wrap(value)) as Box<dyn Any + Send + Sync>
52 )
53 })
54 };
55 OWNER.with(|o| {
56 if let Some(owner) = o.borrow().as_ref().and_then(|o| o.upgrade()) {
57 owner.register(node);
58 }
59 });
60
61 Self {
62 node,
63 ty: PhantomData,
64 }
65 }
66}
67
68impl<T, S> Default for ArenaItem<T, S>
69where
70 T: Default + 'static,
71 S: Storage<T>,
72{
73 #[track_caller] fn default() -> Self {
75 Self::new_with_storage(Default::default())
76 }
77}
78
79impl<T> ArenaItem<T>
80where
81 T: Send + Sync + 'static,
82{
83 #[track_caller]
85 pub fn new(value: T) -> Self {
86 ArenaItem::new_with_storage(value)
87 }
88}
89
90impl<T> ArenaItem<T, LocalStorage>
91where
92 T: 'static,
93{
94 #[track_caller]
96 pub fn new_local(value: T) -> Self {
97 ArenaItem::new_with_storage(value)
98 }
99}
100
101impl<T, S: Storage<T>> ArenaItem<T, S> {
102 #[track_caller]
104 pub fn try_with_value<U>(&self, fun: impl FnOnce(&T) -> U) -> Option<U> {
105 S::try_with(self.node, fun)
106 }
107
108 #[track_caller]
110 pub fn try_update_value<U>(
111 &self,
112 fun: impl FnOnce(&mut T) -> U,
113 ) -> Option<U> {
114 S::try_with_mut(self.node, fun)
115 }
116}
117
118impl<T: Clone, S: Storage<T>> ArenaItem<T, S> {
119 #[track_caller]
121 pub fn try_get_value(&self) -> Option<T> {
122 S::try_with(self.node, Clone::clone)
123 }
124}
125
126impl<T, S> IsDisposed for ArenaItem<T, S> {
127 fn is_disposed(&self) -> bool {
128 Arena::with(|arena| !arena.contains_key(self.node))
129 }
130}
131
132impl<T, S> Dispose for ArenaItem<T, S> {
133 fn dispose(self) {
134 Arena::with_mut(|arena| arena.remove(self.node));
135 }
136}
137
138impl<T, S: Storage<T>> IntoInner for ArenaItem<T, S> {
139 type Value = T;
140
141 #[inline(always)]
142 fn into_inner(self) -> Option<Self::Value> {
143 S::take(self.node)
144 }
145}