Skip to main content

reactive_stores/
arc_field.rs

1use crate::{
2    path::{StorePath, StorePathSegment},
3    ArcStore, AtIndex, AtKeyed, DerefedField, KeyMap, KeyedAccess,
4    KeyedSubfield, Store, StoreField, StoreFieldTrigger, Subfield,
5};
6use reactive_graph::{
7    owner::Storage,
8    traits::{
9        DefinedAt, IsDisposed, Notify, ReadUntracked, Track, UntrackableGuard,
10        Write,
11    },
12};
13use std::{
14    fmt::Debug,
15    hash::Hash,
16    ops::{Deref, DerefMut, IndexMut},
17    panic::Location,
18    sync::Arc,
19};
20
21/// Reference-counted access to a single field of type `T`.
22///
23/// This can be used to erase the chain of field-accessors, to make it easier to pass this into
24/// another component or function without needing to specify the full type signature.
25pub struct ArcField<T>
26where
27    T: 'static,
28{
29    #[cfg(any(debug_assertions, leptos_debuginfo))]
30    defined_at: &'static Location<'static>,
31    path: Arc<dyn Fn() -> StorePath + Send + Sync>,
32    path_unkeyed: Arc<dyn Fn() -> StorePath + Send + Sync>,
33    get_trigger: Arc<dyn Fn(StorePath) -> StoreFieldTrigger + Send + Sync>,
34    get_trigger_unkeyed:
35        Arc<dyn Fn(StorePath) -> StoreFieldTrigger + Send + Sync>,
36    read: Arc<dyn Fn() -> Option<StoreFieldReader<T>> + Send + Sync>,
37    pub(crate) write:
38        Arc<dyn Fn() -> Option<StoreFieldWriter<T>> + Send + Sync>,
39    keys: Arc<dyn Fn() -> Option<KeyMap> + Send + Sync>,
40    track_field: Arc<dyn Fn() + Send + Sync>,
41    notify: Arc<dyn Fn() + Send + Sync>,
42}
43
44impl<T> Debug for ArcField<T>
45where
46    T: 'static,
47{
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        let mut f = f.debug_struct("ArcField");
50        #[cfg(any(debug_assertions, leptos_debuginfo))]
51        let f = f.field("defined_at", &self.defined_at);
52        f.finish_non_exhaustive()
53    }
54}
55
56pub struct StoreFieldReader<T>(Box<dyn Deref<Target = T>>);
57
58impl<T> StoreFieldReader<T> {
59    pub fn new(inner: impl Deref<Target = T> + 'static) -> Self {
60        Self(Box::new(inner))
61    }
62}
63
64impl<T> Deref for StoreFieldReader<T> {
65    type Target = T;
66
67    fn deref(&self) -> &Self::Target {
68        self.0.deref()
69    }
70}
71
72pub struct StoreFieldWriter<T>(Box<dyn UntrackableGuard<Target = T>>);
73
74impl<T> StoreFieldWriter<T> {
75    pub fn new(inner: impl UntrackableGuard<Target = T> + 'static) -> Self {
76        Self(Box::new(inner))
77    }
78}
79
80impl<T> Deref for StoreFieldWriter<T> {
81    type Target = T;
82
83    fn deref(&self) -> &Self::Target {
84        self.0.deref()
85    }
86}
87
88impl<T> DerefMut for StoreFieldWriter<T> {
89    fn deref_mut(&mut self) -> &mut Self::Target {
90        self.0.deref_mut()
91    }
92}
93
94impl<T> UntrackableGuard for StoreFieldWriter<T> {
95    fn untrack(&mut self) {
96        self.0.untrack();
97    }
98}
99
100impl<T> StoreField for ArcField<T> {
101    type Value = T;
102    type Reader = StoreFieldReader<T>;
103    type Writer = StoreFieldWriter<T>;
104
105    fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
106        (self.get_trigger)(path)
107    }
108
109    fn get_trigger_unkeyed(&self, path: StorePath) -> StoreFieldTrigger {
110        (self.get_trigger_unkeyed)(path)
111    }
112
113    fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
114        (self.path)()
115    }
116
117    fn path_unkeyed(&self) -> impl IntoIterator<Item = StorePathSegment> {
118        (self.path_unkeyed)()
119    }
120
121    fn reader(&self) -> Option<Self::Reader> {
122        (self.read)().map(StoreFieldReader::new)
123    }
124
125    fn writer(&self) -> Option<Self::Writer> {
126        (self.write)().map(StoreFieldWriter::new)
127    }
128
129    fn keys(&self) -> Option<KeyMap> {
130        (self.keys)()
131    }
132}
133
134impl<T, S> From<Store<T, S>> for ArcField<T>
135where
136    T: 'static,
137    S: Storage<ArcStore<T>>,
138{
139    #[track_caller]
140    fn from(value: Store<T, S>) -> Self {
141        ArcField {
142            #[cfg(any(debug_assertions, leptos_debuginfo))]
143            defined_at: Location::caller(),
144            path: Arc::new(move || value.path().into_iter().collect()),
145            path_unkeyed: Arc::new(move || {
146                value.path_unkeyed().into_iter().collect()
147            }),
148            get_trigger: Arc::new(move |path| value.get_trigger(path)),
149            get_trigger_unkeyed: Arc::new(move |path| {
150                value.get_trigger_unkeyed(path)
151            }),
152            read: Arc::new(move || value.reader().map(StoreFieldReader::new)),
153            write: Arc::new(move || value.writer().map(StoreFieldWriter::new)),
154            keys: Arc::new(move || value.keys()),
155            track_field: Arc::new(move || value.track_field()),
156            notify: Arc::new(move || value.notify()),
157        }
158    }
159}
160
161impl<T> From<ArcStore<T>> for ArcField<T>
162where
163    T: Send + Sync + 'static,
164{
165    #[track_caller]
166    fn from(value: ArcStore<T>) -> Self {
167        ArcField {
168            #[cfg(any(debug_assertions, leptos_debuginfo))]
169            defined_at: Location::caller(),
170            path: Arc::new({
171                let value = value.clone();
172                move || value.path().into_iter().collect()
173            }),
174            path_unkeyed: Arc::new({
175                let value = value.clone();
176                move || value.path_unkeyed().into_iter().collect()
177            }),
178            get_trigger: Arc::new({
179                let value = value.clone();
180                move |path| value.get_trigger(path)
181            }),
182            get_trigger_unkeyed: Arc::new({
183                let value = value.clone();
184                move |path| value.get_trigger_unkeyed(path)
185            }),
186            read: Arc::new({
187                let value = value.clone();
188                move || value.reader().map(StoreFieldReader::new)
189            }),
190            write: Arc::new({
191                let value = value.clone();
192                move || value.writer().map(StoreFieldWriter::new)
193            }),
194            keys: Arc::new({
195                let value = value.clone();
196                move || value.keys()
197            }),
198            track_field: Arc::new({
199                let value = value.clone();
200                move || value.track_field()
201            }),
202            notify: Arc::new({
203                let value = value.clone();
204                move || value.notify()
205            }),
206        }
207    }
208}
209
210impl<Inner, Prev, T> From<Subfield<Inner, Prev, T>> for ArcField<T>
211where
212    T: Send + Sync,
213    Subfield<Inner, Prev, T>: Clone,
214    Inner: StoreField<Value = Prev> + Send + Sync + 'static,
215    Prev: 'static,
216{
217    #[track_caller]
218    fn from(value: Subfield<Inner, Prev, T>) -> Self {
219        ArcField {
220            #[cfg(any(debug_assertions, leptos_debuginfo))]
221            defined_at: Location::caller(),
222            path: Arc::new({
223                let value = value.clone();
224                move || value.path().into_iter().collect()
225            }),
226            path_unkeyed: Arc::new({
227                let value = value.clone();
228                move || value.path_unkeyed().into_iter().collect()
229            }),
230            get_trigger: Arc::new({
231                let value = value.clone();
232                move |path| value.get_trigger(path)
233            }),
234            get_trigger_unkeyed: Arc::new({
235                let value = value.clone();
236                move |path| value.get_trigger_unkeyed(path)
237            }),
238            read: Arc::new({
239                let value = value.clone();
240                move || value.reader().map(StoreFieldReader::new)
241            }),
242            write: Arc::new({
243                let value = value.clone();
244                move || value.writer().map(StoreFieldWriter::new)
245            }),
246            keys: Arc::new({
247                let value = value.clone();
248                move || value.keys()
249            }),
250            track_field: Arc::new({
251                let value = value.clone();
252                move || value.track_field()
253            }),
254            notify: Arc::new({
255                let value = value.clone();
256                move || value.notify()
257            }),
258        }
259    }
260}
261
262impl<Inner, T> From<DerefedField<Inner>> for ArcField<T>
263where
264    Inner: Clone + StoreField + Send + Sync + 'static,
265    Inner::Value: Deref<Target = T> + DerefMut,
266    T: Sized + 'static,
267{
268    #[track_caller]
269    fn from(value: DerefedField<Inner>) -> Self {
270        ArcField {
271            #[cfg(any(debug_assertions, leptos_debuginfo))]
272            defined_at: Location::caller(),
273            path: Arc::new({
274                let value = value.clone();
275                move || value.path().into_iter().collect()
276            }),
277            path_unkeyed: Arc::new({
278                let value = value.clone();
279                move || value.path_unkeyed().into_iter().collect()
280            }),
281            get_trigger: Arc::new({
282                let value = value.clone();
283                move |path| value.get_trigger(path)
284            }),
285            get_trigger_unkeyed: Arc::new({
286                let value = value.clone();
287                move |path| value.get_trigger_unkeyed(path)
288            }),
289            read: Arc::new({
290                let value = value.clone();
291                move || value.reader().map(StoreFieldReader::new)
292            }),
293            write: Arc::new({
294                let value = value.clone();
295                move || value.writer().map(StoreFieldWriter::new)
296            }),
297            keys: Arc::new({
298                let value = value.clone();
299                move || value.keys()
300            }),
301            track_field: Arc::new({
302                let value = value.clone();
303                move || value.track_field()
304            }),
305            notify: Arc::new({
306                let value = value.clone();
307                move || value.notify()
308            }),
309        }
310    }
311}
312
313impl<Inner, Prev> From<AtIndex<Inner, Prev>> for ArcField<Prev::Output>
314where
315    AtIndex<Inner, Prev>: Clone,
316    Inner: StoreField<Value = Prev> + Send + Sync + 'static,
317    Prev: IndexMut<usize> + Send + Sync + 'static,
318    Prev::Output: Sized + Send + Sync,
319{
320    #[track_caller]
321    fn from(value: AtIndex<Inner, Prev>) -> Self {
322        ArcField {
323            #[cfg(any(debug_assertions, leptos_debuginfo))]
324            defined_at: Location::caller(),
325            path: Arc::new({
326                let value = value.clone();
327                move || value.path().into_iter().collect()
328            }),
329            path_unkeyed: Arc::new({
330                let value = value.clone();
331                move || value.path_unkeyed().into_iter().collect()
332            }),
333            get_trigger: Arc::new({
334                let value = value.clone();
335                move |path| value.get_trigger(path)
336            }),
337            get_trigger_unkeyed: Arc::new({
338                let value = value.clone();
339                move |path| value.get_trigger_unkeyed(path)
340            }),
341            read: Arc::new({
342                let value = value.clone();
343                move || value.reader().map(StoreFieldReader::new)
344            }),
345            write: Arc::new({
346                let value = value.clone();
347                move || value.writer().map(StoreFieldWriter::new)
348            }),
349            keys: Arc::new({
350                let value = value.clone();
351                move || value.keys()
352            }),
353            track_field: Arc::new({
354                let value = value.clone();
355                move || value.track_field()
356            }),
357            notify: Arc::new({
358                let value = value.clone();
359                move || value.notify()
360            }),
361        }
362    }
363}
364
365impl<Inner, Prev, K, T> From<AtKeyed<Inner, Prev, K, T>> for ArcField<T::Value>
366where
367    AtKeyed<Inner, Prev, K, T>: Clone,
368    K: Clone + Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
369    KeyedSubfield<Inner, Prev, K, T>: Clone,
370    for<'a> &'a T: IntoIterator,
371    Inner: StoreField<Value = Prev> + Send + Sync + 'static,
372    Prev: 'static,
373    T: KeyedAccess<K> + 'static,
374    T::Value: Sized,
375{
376    #[track_caller]
377    fn from(value: AtKeyed<Inner, Prev, K, T>) -> Self {
378        ArcField {
379            #[cfg(any(debug_assertions, leptos_debuginfo))]
380            defined_at: Location::caller(),
381            path: Arc::new({
382                let value = value.clone();
383                move || value.path().into_iter().collect()
384            }),
385            path_unkeyed: Arc::new({
386                let value = value.clone();
387                move || value.path_unkeyed().into_iter().collect()
388            }),
389            get_trigger: Arc::new({
390                let value = value.clone();
391                move |path| value.get_trigger(path)
392            }),
393            get_trigger_unkeyed: Arc::new({
394                let value = value.clone();
395                move |path| value.get_trigger_unkeyed(path)
396            }),
397            read: Arc::new({
398                let value = value.clone();
399                move || value.reader().map(StoreFieldReader::new)
400            }),
401            write: Arc::new({
402                let value = value.clone();
403                move || value.writer().map(StoreFieldWriter::new)
404            }),
405            keys: Arc::new({
406                let value = value.clone();
407                move || value.keys()
408            }),
409            track_field: Arc::new({
410                let value = value.clone();
411                move || value.track_field()
412            }),
413            notify: Arc::new({
414                let value = value.clone();
415                move || value.notify()
416            }),
417        }
418    }
419}
420
421impl<T> Clone for ArcField<T> {
422    fn clone(&self) -> Self {
423        Self {
424            #[cfg(any(debug_assertions, leptos_debuginfo))]
425            defined_at: self.defined_at,
426            path: self.path.clone(),
427            path_unkeyed: self.path_unkeyed.clone(),
428            get_trigger: Arc::clone(&self.get_trigger),
429            get_trigger_unkeyed: Arc::clone(&self.get_trigger_unkeyed),
430            read: Arc::clone(&self.read),
431            write: Arc::clone(&self.write),
432            keys: Arc::clone(&self.keys),
433            track_field: Arc::clone(&self.track_field),
434            notify: Arc::clone(&self.notify),
435        }
436    }
437}
438
439impl<T> DefinedAt for ArcField<T> {
440    fn defined_at(&self) -> Option<&'static Location<'static>> {
441        #[cfg(any(debug_assertions, leptos_debuginfo))]
442        {
443            Some(self.defined_at)
444        }
445        #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
446        {
447            None
448        }
449    }
450}
451
452impl<T> Notify for ArcField<T> {
453    fn notify(&self) {
454        (self.notify)()
455    }
456}
457
458impl<T> Track for ArcField<T> {
459    fn track(&self) {
460        (self.track_field)();
461    }
462}
463
464impl<T> ReadUntracked for ArcField<T> {
465    type Value = StoreFieldReader<T>;
466
467    fn try_read_untracked(&self) -> Option<Self::Value> {
468        (self.read)()
469    }
470}
471
472impl<T> Write for ArcField<T> {
473    type Value = T;
474
475    fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
476        (self.write)()
477    }
478
479    fn try_write_untracked(
480        &self,
481    ) -> Option<impl DerefMut<Target = Self::Value>> {
482        let mut guard = (self.write)()?;
483        guard.untrack();
484        Some(guard)
485    }
486}
487
488impl<T> IsDisposed for ArcField<T> {
489    fn is_disposed(&self) -> bool {
490        false
491    }
492}