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