1use crate::{
2 arc_field::{StoreFieldReader, StoreFieldWriter},
3 path::{StorePath, StorePathSegment},
4 ArcField, ArcStore, AtIndex, AtKeyed, DerefedField, KeyMap, KeyedAccess,
5 KeyedSubfield, 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 get_trigger_unkeyed(&self, path: StorePath) -> StoreFieldTrigger {
63 self.inner
64 .try_get_value()
65 .map(|inner| inner.get_trigger_unkeyed(path))
66 .unwrap_or_default()
67 }
68
69 fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
70 self.inner
71 .try_get_value()
72 .map(|inner| inner.path().into_iter().collect::<Vec<_>>())
73 .unwrap_or_default()
74 }
75
76 fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
77 self.inner
78 .try_get_value()
79 .map(|inner| inner.path_unkeyed().into_iter().collect::<Vec<_>>())
80 .unwrap_or_default()
81 }
82
83 fn reader(&self) -> Option<Self::Reader> {
84 self.inner.try_get_value().and_then(|inner| inner.reader())
85 }
86
87 fn writer(&self) -> Option<Self::Writer> {
88 self.inner.try_get_value().and_then(|inner| inner.writer())
89 }
90
91 fn keys(&self) -> Option<KeyMap> {
92 self.inner.try_get_value().and_then(|n| n.keys())
93 }
94}
95
96impl<T, S> From<Store<T, S>> for Field<T, S>
97where
98 T: 'static,
99 S: Storage<ArcStore<T>> + Storage<ArcField<T>>,
100{
101 #[track_caller]
102 fn from(value: Store<T, S>) -> Self {
103 Field {
104 #[cfg(any(debug_assertions, leptos_debuginfo))]
105 defined_at: Location::caller(),
106 inner: ArenaItem::new_with_storage(value.into()),
107 }
108 }
109}
110
111impl<T, S> From<ArcField<T>> for Field<T, S>
112where
113 T: 'static,
114 S: Storage<ArcField<T>>,
115{
116 #[track_caller]
117 fn from(value: ArcField<T>) -> Self {
118 Field {
119 #[cfg(any(debug_assertions, leptos_debuginfo))]
120 defined_at: Location::caller(),
121 inner: ArenaItem::new_with_storage(value),
122 }
123 }
124}
125
126impl<T, S> From<ArcStore<T>> for Field<T, S>
127where
128 T: Send + Sync + 'static,
129 S: Storage<ArcStore<T>> + Storage<ArcField<T>>,
130{
131 #[track_caller]
132 fn from(value: ArcStore<T>) -> Self {
133 Field {
134 #[cfg(any(debug_assertions, leptos_debuginfo))]
135 defined_at: Location::caller(),
136 inner: ArenaItem::new_with_storage(value.into()),
137 }
138 }
139}
140
141impl<Inner, Prev, T, S> From<Subfield<Inner, Prev, T>> for Field<T, S>
142where
143 T: Send + Sync,
144 S: Storage<ArcField<T>>,
145 Subfield<Inner, Prev, T>: Clone,
146 Inner: StoreField<Value = Prev> + Send + Sync + 'static,
147 Prev: 'static,
148{
149 #[track_caller]
150 fn from(value: Subfield<Inner, Prev, T>) -> Self {
151 Field {
152 #[cfg(any(debug_assertions, leptos_debuginfo))]
153 defined_at: Location::caller(),
154 inner: ArenaItem::new_with_storage(value.into()),
155 }
156 }
157}
158
159impl<Inner, T> From<DerefedField<Inner>> for Field<T>
160where
161 Inner: Clone + StoreField + Send + Sync + 'static,
162 Inner::Value: Deref<Target = T> + DerefMut,
163 T: Sized + 'static,
164{
165 #[track_caller]
166 fn from(value: DerefedField<Inner>) -> Self {
167 Field {
168 #[cfg(any(debug_assertions, leptos_debuginfo))]
169 defined_at: Location::caller(),
170 inner: ArenaItem::new_with_storage(value.into()),
171 }
172 }
173}
174
175impl<Inner, Prev, S> From<AtIndex<Inner, Prev>> for Field<Prev::Output, S>
176where
177 AtIndex<Inner, Prev>: Clone,
178 S: Storage<ArcField<Prev::Output>>,
179 Inner: StoreField<Value = Prev> + Send + Sync + 'static,
180 Prev: IndexMut<usize> + Send + Sync + 'static,
181 Prev::Output: Sized + Send + Sync,
182{
183 #[track_caller]
184 fn from(value: AtIndex<Inner, Prev>) -> Self {
185 Field {
186 #[cfg(any(debug_assertions, leptos_debuginfo))]
187 defined_at: Location::caller(),
188 inner: ArenaItem::new_with_storage(value.into()),
189 }
190 }
191}
192
193impl<Inner, Prev, K, T, S> From<AtKeyed<Inner, Prev, K, T>>
194 for Field<T::Value, S>
195where
196 S: Storage<ArcField<T::Value>>,
197 AtKeyed<Inner, Prev, K, T>: Clone,
198 K: Clone + Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
199 KeyedSubfield<Inner, Prev, K, T>: Clone,
200 for<'a> &'a T: IntoIterator,
201 Inner: StoreField<Value = Prev> + Send + Sync + 'static,
202 Prev: 'static,
203 T: KeyedAccess<K> + 'static,
204 T::Value: Sized,
205{
206 #[track_caller]
207 fn from(value: AtKeyed<Inner, Prev, K, T>) -> Self {
208 Field {
209 #[cfg(any(debug_assertions, leptos_debuginfo))]
210 defined_at: Location::caller(),
211 inner: ArenaItem::new_with_storage(value.into()),
212 }
213 }
214}
215
216impl<T, S> Clone for Field<T, S> {
217 fn clone(&self) -> Self {
218 *self
219 }
220}
221
222impl<T, S> Copy for Field<T, S> {}
223
224impl<T, S> DefinedAt for Field<T, S> {
225 fn defined_at(&self) -> Option<&'static Location<'static>> {
226 #[cfg(any(debug_assertions, leptos_debuginfo))]
227 {
228 Some(self.defined_at)
229 }
230 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
231 {
232 None
233 }
234 }
235}
236
237impl<T, S> Notify for Field<T, S>
238where
239 S: Storage<ArcField<T>>,
240{
241 fn notify(&self) {
242 if let Some(inner) = self.inner.try_get_value() {
243 inner.notify();
244 }
245 }
246}
247
248impl<T, S> Track for Field<T, S>
249where
250 S: Storage<ArcField<T>>,
251{
252 fn track(&self) {
253 if let Some(inner) = self.inner.try_get_value() {
254 inner.track();
255 }
256 }
257}
258
259impl<T, S> ReadUntracked for Field<T, S>
260where
261 S: Storage<ArcField<T>>,
262{
263 type Value = StoreFieldReader<T>;
264
265 fn try_read_untracked(&self) -> Option<Self::Value> {
266 self.inner
267 .try_get_value()
268 .and_then(|inner| inner.try_read_untracked())
269 }
270}
271
272impl<T> Write for Field<T> {
273 type Value = T;
274
275 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
276 self.inner.try_get_value().and_then(|inner| (inner.write)())
277 }
278
279 fn try_write_untracked(
280 &self,
281 ) -> Option<impl DerefMut<Target = Self::Value>> {
282 self.inner.try_get_value().and_then(|inner| {
283 let mut guard = (inner.write)()?;
284 guard.untrack();
285 Some(guard)
286 })
287 }
288}
289
290impl<T, S> IsDisposed for Field<T, S> {
291 fn is_disposed(&self) -> bool {
292 self.inner.is_disposed()
293 }
294}