1use crate::{
2 arc_field::{StoreFieldReader, StoreFieldWriter},
3 path::{StorePath, StorePathSegment},
4 ArcField, ArcStore, AtIndex, AtKeyed, DerefedField, KeyMap, KeyedSubfield,
5 Store, StoreField, StoreFieldTrigger, Subfield,
6};
7use reactive_graph::{
8 owner::{ArenaItem, Storage, SyncStorage},
9 traits::{
10 DefinedAt, IsDisposed, Notify, ReadUntracked, Track, UntrackableGuard,
11 Write,
12 },
13};
14use std::{
15 fmt::Debug,
16 hash::Hash,
17 ops::{Deref, DerefMut, IndexMut},
18 panic::Location,
19};
20
21pub struct Field<T, S = SyncStorage>
26where
27 T: 'static,
28{
29 #[cfg(any(debug_assertions, leptos_debuginfo))]
30 defined_at: &'static Location<'static>,
31 inner: ArenaItem<ArcField<T>, S>,
32}
33
34impl<T, S> Debug for Field<T, S>
35where
36 T: 'static,
37 S: Debug,
38{
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 let mut f = f.debug_struct("Field");
41 #[cfg(any(debug_assertions, leptos_debuginfo))]
42 let f = f.field("defined_at", &self.defined_at);
43 f.field("inner", &self.inner).finish()
44 }
45}
46
47impl<T, S> StoreField for Field<T, S>
48where
49 S: Storage<ArcField<T>>,
50{
51 type Value = T;
52 type Reader = StoreFieldReader<T>;
53 type Writer = StoreFieldWriter<T>;
54
55 fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
56 self.inner
57 .try_get_value()
58 .map(|inner| inner.get_trigger(path))
59 .unwrap_or_default()
60 }
61
62 fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
63 self.inner
64 .try_get_value()
65 .map(|inner| inner.path().into_iter().collect::<Vec<_>>())
66 .unwrap_or_default()
67 }
68
69 fn reader(&self) -> Option<Self::Reader> {
70 self.inner.try_get_value().and_then(|inner| inner.reader())
71 }
72
73 fn writer(&self) -> Option<Self::Writer> {
74 self.inner.try_get_value().and_then(|inner| inner.writer())
75 }
76
77 fn keys(&self) -> Option<KeyMap> {
78 self.inner.try_get_value().and_then(|n| n.keys())
79 }
80}
81
82impl<T, S> From<Store<T, S>> for Field<T, S>
83where
84 T: 'static,
85 S: Storage<ArcStore<T>> + Storage<ArcField<T>>,
86{
87 #[track_caller]
88 fn from(value: Store<T, S>) -> Self {
89 Field {
90 #[cfg(any(debug_assertions, leptos_debuginfo))]
91 defined_at: Location::caller(),
92 inner: ArenaItem::new_with_storage(value.into()),
93 }
94 }
95}
96
97impl<T, S> From<ArcField<T>> for Field<T, S>
98where
99 T: 'static,
100 S: Storage<ArcField<T>>,
101{
102 #[track_caller]
103 fn from(value: ArcField<T>) -> Self {
104 Field {
105 #[cfg(any(debug_assertions, leptos_debuginfo))]
106 defined_at: Location::caller(),
107 inner: ArenaItem::new_with_storage(value),
108 }
109 }
110}
111
112impl<T, S> From<ArcStore<T>> for Field<T, S>
113where
114 T: Send + Sync + 'static,
115 S: Storage<ArcStore<T>> + Storage<ArcField<T>>,
116{
117 #[track_caller]
118 fn from(value: ArcStore<T>) -> Self {
119 Field {
120 #[cfg(any(debug_assertions, leptos_debuginfo))]
121 defined_at: Location::caller(),
122 inner: ArenaItem::new_with_storage(value.into()),
123 }
124 }
125}
126
127impl<Inner, Prev, T, S> From<Subfield<Inner, Prev, T>> for Field<T, S>
128where
129 T: Send + Sync,
130 S: Storage<ArcField<T>>,
131 Subfield<Inner, Prev, T>: Clone,
132 Inner: StoreField<Value = Prev> + Send + Sync + 'static,
133 Prev: 'static,
134{
135 #[track_caller]
136 fn from(value: Subfield<Inner, Prev, T>) -> Self {
137 Field {
138 #[cfg(any(debug_assertions, leptos_debuginfo))]
139 defined_at: Location::caller(),
140 inner: ArenaItem::new_with_storage(value.into()),
141 }
142 }
143}
144
145impl<Inner, T> From<DerefedField<Inner>> for Field<T>
146where
147 Inner: Clone + StoreField + Send + Sync + 'static,
148 Inner::Value: Deref<Target = T> + DerefMut,
149 T: Sized + 'static,
150{
151 #[track_caller]
152 fn from(value: DerefedField<Inner>) -> Self {
153 Field {
154 #[cfg(any(debug_assertions, leptos_debuginfo))]
155 defined_at: Location::caller(),
156 inner: ArenaItem::new_with_storage(value.into()),
157 }
158 }
159}
160
161impl<Inner, Prev, S> From<AtIndex<Inner, Prev>> for Field<Prev::Output, S>
162where
163 AtIndex<Inner, Prev>: Clone,
164 S: Storage<ArcField<Prev::Output>>,
165 Inner: StoreField<Value = Prev> + Send + Sync + 'static,
166 Prev: IndexMut<usize> + Send + Sync + 'static,
167 Prev::Output: Sized + Send + Sync,
168{
169 #[track_caller]
170 fn from(value: AtIndex<Inner, Prev>) -> Self {
171 Field {
172 #[cfg(any(debug_assertions, leptos_debuginfo))]
173 defined_at: Location::caller(),
174 inner: ArenaItem::new_with_storage(value.into()),
175 }
176 }
177}
178
179impl<Inner, Prev, K, T, S> From<AtKeyed<Inner, Prev, K, T>>
180 for Field<T::Output, S>
181where
182 S: Storage<ArcField<T::Output>>,
183 AtKeyed<Inner, Prev, K, T>: Clone,
184 K: Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
185 KeyedSubfield<Inner, Prev, K, T>: Clone,
186 for<'a> &'a T: IntoIterator,
187 Inner: StoreField<Value = Prev> + Send + Sync + 'static,
188 Prev: 'static,
189 T: IndexMut<usize> + 'static,
190 T::Output: Sized,
191{
192 #[track_caller]
193 fn from(value: AtKeyed<Inner, Prev, K, T>) -> Self {
194 Field {
195 #[cfg(any(debug_assertions, leptos_debuginfo))]
196 defined_at: Location::caller(),
197 inner: ArenaItem::new_with_storage(value.into()),
198 }
199 }
200}
201
202impl<T, S> Clone for Field<T, S> {
203 fn clone(&self) -> Self {
204 *self
205 }
206}
207
208impl<T, S> Copy for Field<T, S> {}
209
210impl<T, S> DefinedAt for Field<T, S> {
211 fn defined_at(&self) -> Option<&'static Location<'static>> {
212 #[cfg(any(debug_assertions, leptos_debuginfo))]
213 {
214 Some(self.defined_at)
215 }
216 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
217 {
218 None
219 }
220 }
221}
222
223impl<T, S> Notify for Field<T, S>
224where
225 S: Storage<ArcField<T>>,
226{
227 fn notify(&self) {
228 if let Some(inner) = self.inner.try_get_value() {
229 inner.notify();
230 }
231 }
232}
233
234impl<T, S> Track for Field<T, S>
235where
236 S: Storage<ArcField<T>>,
237{
238 fn track(&self) {
239 if let Some(inner) = self.inner.try_get_value() {
240 inner.track();
241 }
242 }
243}
244
245impl<T, S> ReadUntracked for Field<T, S>
246where
247 S: Storage<ArcField<T>>,
248{
249 type Value = StoreFieldReader<T>;
250
251 fn try_read_untracked(&self) -> Option<Self::Value> {
252 self.inner
253 .try_get_value()
254 .and_then(|inner| inner.try_read_untracked())
255 }
256}
257
258impl<T> Write for Field<T> {
259 type Value = T;
260
261 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
262 self.inner.try_get_value().and_then(|inner| (inner.write)())
263 }
264
265 fn try_write_untracked(
266 &self,
267 ) -> Option<impl DerefMut<Target = Self::Value>> {
268 self.inner.try_get_value().and_then(|inner| {
269 let mut guard = (inner.write)()?;
270 guard.untrack();
271 Some(guard)
272 })
273 }
274}
275
276impl<T, S> IsDisposed for Field<T, S> {
277 fn is_disposed(&self) -> bool {
278 self.inner.is_disposed()
279 }
280}