reactive_graph/signal/
guards.rs

1//! Guards that integrate with the reactive system, wrapping references to the values of signals.
2
3use crate::{
4    computed::BlockingLock,
5    traits::{Notify, UntrackableGuard},
6};
7use core::fmt::Debug;
8use guardian::{ArcRwLockReadGuardian, ArcRwLockWriteGuardian};
9use std::{
10    borrow::Borrow,
11    fmt::Display,
12    marker::PhantomData,
13    ops::{Deref, DerefMut},
14    sync::{Arc, RwLock},
15};
16
17/// A wrapper type for any kind of guard returned by [`Read`](crate::traits::Read).
18///
19/// If `Inner` implements `Deref`, so does `ReadGuard<_, Inner>`.
20#[derive(Debug)]
21pub struct ReadGuard<T, Inner> {
22    ty: PhantomData<T>,
23    inner: Inner,
24}
25
26impl<T, Inner> ReadGuard<T, Inner> {
27    /// Creates a new wrapper around another guard type.
28    pub fn new(inner: Inner) -> Self {
29        Self {
30            inner,
31            ty: PhantomData,
32        }
33    }
34
35    /// Returns the inner guard type.
36    pub fn into_inner(self) -> Inner {
37        self.inner
38    }
39}
40
41impl<T, Inner> Clone for ReadGuard<T, Inner>
42where
43    Inner: Clone,
44{
45    fn clone(&self) -> Self {
46        Self {
47            ty: self.ty,
48            inner: self.inner.clone(),
49        }
50    }
51}
52
53impl<T, Inner> Deref for ReadGuard<T, Inner>
54where
55    Inner: Deref<Target = T>,
56{
57    type Target = T;
58
59    fn deref(&self) -> &Self::Target {
60        self.inner.deref()
61    }
62}
63
64impl<T, Inner> Borrow<T> for ReadGuard<T, Inner>
65where
66    Inner: Deref<Target = T>,
67{
68    fn borrow(&self) -> &T {
69        self.deref()
70    }
71}
72
73impl<T, Inner> PartialEq<T> for ReadGuard<T, Inner>
74where
75    Inner: Deref<Target = T>,
76    T: PartialEq,
77{
78    fn eq(&self, other: &Inner::Target) -> bool {
79        self.deref() == other
80    }
81}
82
83impl<T, Inner> Display for ReadGuard<T, Inner>
84where
85    Inner: Deref<Target = T>,
86    T: Display,
87{
88    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89        Display::fmt(&**self, f)
90    }
91}
92
93/// A guard that provides access to a signal's inner value.
94pub struct Plain<T: 'static> {
95    guard: ArcRwLockReadGuardian<T>,
96}
97
98impl<T: 'static> Debug for Plain<T> {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        f.debug_struct("Plain").finish()
101    }
102}
103
104impl<T: 'static> Plain<T> {
105    /// Takes a reference-counted read guard on the given lock.
106    pub fn try_new(inner: Arc<RwLock<T>>) -> Option<Self> {
107        ArcRwLockReadGuardian::try_take(inner)?
108            .ok()
109            .map(|guard| Plain { guard })
110    }
111}
112
113impl<T> Deref for Plain<T> {
114    type Target = T;
115
116    fn deref(&self) -> &Self::Target {
117        self.guard.deref()
118    }
119}
120
121impl<T: PartialEq> PartialEq for Plain<T> {
122    fn eq(&self, other: &Self) -> bool {
123        **self == **other
124    }
125}
126
127impl<T: PartialEq> PartialEq<T> for Plain<T> {
128    fn eq(&self, other: &T) -> bool {
129        **self == *other
130    }
131}
132
133impl<T: Display> Display for Plain<T> {
134    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135        Display::fmt(&**self, f)
136    }
137}
138
139/// A guard that provides access to an async signal's value.
140pub struct AsyncPlain<T: 'static> {
141    pub(crate) guard: async_lock::RwLockReadGuardArc<T>,
142}
143
144impl<T: 'static> Debug for AsyncPlain<T> {
145    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146        f.debug_struct("AsyncPlain").finish()
147    }
148}
149
150impl<T: 'static> AsyncPlain<T> {
151    /// Takes a reference-counted async read guard on the given lock.
152    pub fn try_new(inner: &Arc<async_lock::RwLock<T>>) -> Option<Self> {
153        Some(Self {
154            guard: inner.blocking_read_arc(),
155        })
156    }
157}
158
159impl<T> Deref for AsyncPlain<T> {
160    type Target = T;
161
162    fn deref(&self) -> &Self::Target {
163        self.guard.deref()
164    }
165}
166
167impl<T: PartialEq> PartialEq for AsyncPlain<T> {
168    fn eq(&self, other: &Self) -> bool {
169        **self == **other
170    }
171}
172
173impl<T: PartialEq> PartialEq<T> for AsyncPlain<T> {
174    fn eq(&self, other: &T) -> bool {
175        **self == *other
176    }
177}
178
179impl<T: Display> Display for AsyncPlain<T> {
180    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181        Display::fmt(&**self, f)
182    }
183}
184
185/// A guard that maps over another guard.
186#[derive(Debug)]
187pub struct Mapped<Inner, U>
188where
189    Inner: Deref,
190{
191    inner: Inner,
192    map_fn: fn(&Inner::Target) -> &U,
193}
194
195impl<T: 'static, U> Mapped<Plain<T>, U> {
196    /// Creates a mapped read guard from the inner lock.
197    pub fn try_new(
198        inner: Arc<RwLock<T>>,
199        map_fn: fn(&T) -> &U,
200    ) -> Option<Self> {
201        let inner = Plain::try_new(inner)?;
202        Some(Self { inner, map_fn })
203    }
204}
205
206impl<Inner, U> Mapped<Inner, U>
207where
208    Inner: Deref,
209{
210    /// Creates a mapped read guard from the inner guard.
211    pub fn new_with_guard(
212        inner: Inner,
213        map_fn: fn(&Inner::Target) -> &U,
214    ) -> Self {
215        Self { inner, map_fn }
216    }
217}
218
219impl<Inner, U> Deref for Mapped<Inner, U>
220where
221    Inner: Deref,
222{
223    type Target = U;
224
225    fn deref(&self) -> &Self::Target {
226        (self.map_fn)(self.inner.deref())
227    }
228}
229
230impl<Inner, U: PartialEq> PartialEq for Mapped<Inner, U>
231where
232    Inner: Deref,
233{
234    fn eq(&self, other: &Self) -> bool {
235        **self == **other
236    }
237}
238
239impl<Inner, U: PartialEq> PartialEq<U> for Mapped<Inner, U>
240where
241    Inner: Deref,
242{
243    fn eq(&self, other: &U) -> bool {
244        **self == *other
245    }
246}
247
248impl<Inner, U: Display> Display for Mapped<Inner, U>
249where
250    Inner: Deref,
251{
252    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253        Display::fmt(&**self, f)
254    }
255}
256
257/// A guard that provides mutable access to a signal's value, triggering some reactive change
258/// when it is dropped.
259#[derive(Debug)]
260pub struct WriteGuard<S, G>
261where
262    S: Notify,
263{
264    pub(crate) triggerable: Option<S>,
265    pub(crate) guard: Option<G>,
266}
267
268impl<S, G> WriteGuard<S, G>
269where
270    S: Notify,
271{
272    /// Creates a new guard from the inner mutable guard type, and the signal that should be
273    /// triggered on drop.
274    pub fn new(triggerable: S, guard: G) -> Self {
275        Self {
276            triggerable: Some(triggerable),
277            guard: Some(guard),
278        }
279    }
280}
281
282impl<S, G> UntrackableGuard for WriteGuard<S, G>
283where
284    S: Notify,
285    G: DerefMut,
286{
287    /// Removes the triggerable type, so that it is no longer notifies when dropped.
288    fn untrack(&mut self) {
289        self.triggerable.take();
290    }
291}
292
293impl<S, G> Deref for WriteGuard<S, G>
294where
295    S: Notify,
296    G: Deref,
297{
298    type Target = G::Target;
299
300    fn deref(&self) -> &Self::Target {
301        self.guard
302            .as_ref()
303            .expect(
304                "the guard should always be in place until the Drop \
305                 implementation",
306            )
307            .deref()
308    }
309}
310
311impl<S, G> DerefMut for WriteGuard<S, G>
312where
313    S: Notify,
314    G: DerefMut,
315{
316    fn deref_mut(&mut self) -> &mut Self::Target {
317        self.guard
318            .as_mut()
319            .expect(
320                "the guard should always be in place until the Drop \
321                 implementation",
322            )
323            .deref_mut()
324    }
325}
326
327/// A guard that provides mutable access to a signal's inner value, but does not notify of any
328/// changes.
329pub struct UntrackedWriteGuard<T: 'static>(ArcRwLockWriteGuardian<T>);
330
331impl<T: 'static> UntrackedWriteGuard<T> {
332    /// Creates a write guard from the given lock.
333    pub fn try_new(inner: Arc<RwLock<T>>) -> Option<Self> {
334        ArcRwLockWriteGuardian::try_take(inner)?
335            .ok()
336            .map(UntrackedWriteGuard)
337    }
338}
339
340impl<T> Deref for UntrackedWriteGuard<T> {
341    type Target = T;
342
343    fn deref(&self) -> &Self::Target {
344        self.0.deref()
345    }
346}
347
348impl<T> DerefMut for UntrackedWriteGuard<T> {
349    fn deref_mut(&mut self) -> &mut Self::Target {
350        self.0.deref_mut()
351    }
352}
353
354// Dropping the write guard will notify dependencies.
355impl<S, T> Drop for WriteGuard<S, T>
356where
357    S: Notify,
358{
359    fn drop(&mut self) {
360        // first, drop the inner guard
361        drop(self.guard.take());
362
363        // then, notify about a change
364        if let Some(triggerable) = self.triggerable.as_ref() {
365            triggerable.notify();
366        }
367    }
368}
369
370/// A mutable guard that maps over an inner mutable guard.
371#[derive(Debug)]
372pub struct MappedMut<Inner, U>
373where
374    Inner: Deref,
375{
376    inner: Inner,
377    map_fn: fn(&Inner::Target) -> &U,
378    map_fn_mut: fn(&mut Inner::Target) -> &mut U,
379}
380
381impl<Inner, U> UntrackableGuard for MappedMut<Inner, U>
382where
383    Inner: UntrackableGuard,
384{
385    fn untrack(&mut self) {
386        self.inner.untrack();
387    }
388}
389
390impl<Inner, U> MappedMut<Inner, U>
391where
392    Inner: DerefMut,
393{
394    /// Creates a new writable guard from the inner guard.
395    pub fn new(
396        inner: Inner,
397        map_fn: fn(&Inner::Target) -> &U,
398        map_fn_mut: fn(&mut Inner::Target) -> &mut U,
399    ) -> Self {
400        Self {
401            inner,
402            map_fn,
403            map_fn_mut,
404        }
405    }
406}
407
408impl<Inner, U> Deref for MappedMut<Inner, U>
409where
410    Inner: Deref,
411{
412    type Target = U;
413
414    fn deref(&self) -> &Self::Target {
415        (self.map_fn)(self.inner.deref())
416    }
417}
418
419impl<Inner, U> DerefMut for MappedMut<Inner, U>
420where
421    Inner: DerefMut,
422{
423    fn deref_mut(&mut self) -> &mut Self::Target {
424        (self.map_fn_mut)(self.inner.deref_mut())
425    }
426}
427
428impl<Inner, U: PartialEq> PartialEq for MappedMut<Inner, U>
429where
430    Inner: Deref,
431{
432    fn eq(&self, other: &Self) -> bool {
433        **self == **other
434    }
435}
436
437impl<Inner, U: Display> Display for MappedMut<Inner, U>
438where
439    Inner: Deref,
440{
441    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
442        Display::fmt(&**self, f)
443    }
444}
445
446/// A mapped read guard in which the mapping function is a closure. If the mapping function is a
447/// function pointer, use [`Mapped`].
448pub struct MappedArc<Inner, U>
449where
450    Inner: Deref,
451{
452    inner: Inner,
453    #[allow(clippy::type_complexity)]
454    map_fn: Arc<dyn Fn(&Inner::Target) -> &U>,
455}
456
457impl<Inner, U> Clone for MappedArc<Inner, U>
458where
459    Inner: Clone + Deref,
460{
461    fn clone(&self) -> Self {
462        Self {
463            inner: self.inner.clone(),
464            map_fn: self.map_fn.clone(),
465        }
466    }
467}
468
469impl<Inner, U> Debug for MappedArc<Inner, U>
470where
471    Inner: Debug + Deref,
472{
473    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
474        f.debug_struct("MappedArc")
475            .field("inner", &self.inner)
476            .finish_non_exhaustive()
477    }
478}
479
480impl<Inner, U> MappedArc<Inner, U>
481where
482    Inner: Deref,
483{
484    /// Creates a new mapped guard from the inner guard and the map function.
485    pub fn new(
486        inner: Inner,
487        map_fn: impl Fn(&Inner::Target) -> &U + 'static,
488    ) -> Self {
489        Self {
490            inner,
491            map_fn: Arc::new(map_fn),
492        }
493    }
494}
495
496impl<Inner, U> Deref for MappedArc<Inner, U>
497where
498    Inner: Deref,
499{
500    type Target = U;
501
502    fn deref(&self) -> &Self::Target {
503        (self.map_fn)(self.inner.deref())
504    }
505}
506
507impl<Inner, U: PartialEq> PartialEq for MappedArc<Inner, U>
508where
509    Inner: Deref,
510{
511    fn eq(&self, other: &Self) -> bool {
512        **self == **other
513    }
514}
515
516impl<Inner, U: Display> Display for MappedArc<Inner, U>
517where
518    Inner: Deref,
519{
520    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
521        Display::fmt(&**self, f)
522    }
523}
524
525/// A mapped write guard in which the mapping function is a closure. If the mapping function is a
526/// function pointer, use [`MappedMut`].
527pub struct MappedMutArc<Inner, U>
528where
529    Inner: Deref,
530{
531    inner: Inner,
532    #[allow(clippy::type_complexity)]
533    map_fn: Arc<dyn Fn(&Inner::Target) -> &U>,
534    #[allow(clippy::type_complexity)]
535    map_fn_mut: Arc<dyn Fn(&mut Inner::Target) -> &mut U>,
536}
537
538impl<Inner, U> Clone for MappedMutArc<Inner, U>
539where
540    Inner: Clone + Deref,
541{
542    fn clone(&self) -> Self {
543        Self {
544            inner: self.inner.clone(),
545            map_fn: self.map_fn.clone(),
546            map_fn_mut: self.map_fn_mut.clone(),
547        }
548    }
549}
550
551impl<Inner, U> Debug for MappedMutArc<Inner, U>
552where
553    Inner: Debug + Deref,
554{
555    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
556        f.debug_struct("MappedMutArc")
557            .field("inner", &self.inner)
558            .finish_non_exhaustive()
559    }
560}
561
562impl<Inner, U> UntrackableGuard for MappedMutArc<Inner, U>
563where
564    Inner: UntrackableGuard,
565{
566    fn untrack(&mut self) {
567        self.inner.untrack();
568    }
569}
570
571impl<Inner, U> MappedMutArc<Inner, U>
572where
573    Inner: Deref,
574{
575    /// Creates the new mapped mutable guard from the inner guard and mapping functions.
576    pub fn new(
577        inner: Inner,
578        map_fn: impl Fn(&Inner::Target) -> &U + 'static,
579        map_fn_mut: impl Fn(&mut Inner::Target) -> &mut U + 'static,
580    ) -> Self {
581        Self {
582            inner,
583            map_fn: Arc::new(map_fn),
584            map_fn_mut: Arc::new(map_fn_mut),
585        }
586    }
587}
588
589impl<Inner, U> Deref for MappedMutArc<Inner, U>
590where
591    Inner: Deref,
592{
593    type Target = U;
594
595    fn deref(&self) -> &Self::Target {
596        (self.map_fn)(self.inner.deref())
597    }
598}
599
600impl<Inner, U> DerefMut for MappedMutArc<Inner, U>
601where
602    Inner: DerefMut,
603{
604    fn deref_mut(&mut self) -> &mut Self::Target {
605        (self.map_fn_mut)(self.inner.deref_mut())
606    }
607}
608
609impl<Inner, U: PartialEq> PartialEq for MappedMutArc<Inner, U>
610where
611    Inner: Deref,
612{
613    fn eq(&self, other: &Self) -> bool {
614        **self == **other
615    }
616}
617
618impl<Inner, U: Display> Display for MappedMutArc<Inner, U>
619where
620    Inner: Deref,
621{
622    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
623        Display::fmt(&**self, f)
624    }
625}
626
627/// A wrapper that implements [`Deref`] and [`Borrow`] for itself.
628pub struct Derefable<T>(pub T);
629
630impl<T> Clone for Derefable<T>
631where
632    T: Clone,
633{
634    fn clone(&self) -> Self {
635        Derefable(self.0.clone())
636    }
637}
638
639impl<T> std::ops::Deref for Derefable<T> {
640    type Target = T;
641    fn deref(&self) -> &Self::Target {
642        &self.0
643    }
644}
645
646impl<T> Borrow<T> for Derefable<T> {
647    fn borrow(&self) -> &T {
648        self.deref()
649    }
650}
651
652impl<T> PartialEq<T> for Derefable<T>
653where
654    T: PartialEq,
655{
656    fn eq(&self, other: &T) -> bool {
657        self.deref() == other
658    }
659}
660
661impl<T> Display for Derefable<T>
662where
663    T: Display,
664{
665    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
666        Display::fmt(&**self, f)
667    }
668}