reactive_stores/
arc_field.rs

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