dioxus_signals/
map_mut.rs

1use std::ops::Deref;
2
3use crate::{
4    read_impls, write_impls, Readable, ReadableExt, ReadableRef, Writable, WritableExt,
5    WritableRef, WriteLock,
6};
7use dioxus_core::{IntoAttributeValue, Subscribers};
8use generational_box::{AnyStorage, BorrowResult};
9
10/// A read only signal that has been mapped to a new type.
11pub struct MappedMutSignal<
12    O: ?Sized,
13    V,
14    F = fn(&<V as Readable>::Target) -> &O,
15    FMut = fn(&mut <V as Readable>::Target) -> &mut O,
16> {
17    value: V,
18    map_fn: F,
19    map_fn_mut: FMut,
20    _marker: std::marker::PhantomData<O>,
21}
22
23impl<V, O, F, FMut> Clone for MappedMutSignal<O, V, F, FMut>
24where
25    V: Clone,
26    F: Clone,
27    FMut: Clone,
28{
29    fn clone(&self) -> Self {
30        MappedMutSignal {
31            value: self.value.clone(),
32            map_fn: self.map_fn.clone(),
33            map_fn_mut: self.map_fn_mut.clone(),
34            _marker: std::marker::PhantomData,
35        }
36    }
37}
38
39impl<V, O, F, FMut> Copy for MappedMutSignal<O, V, F, FMut>
40where
41    V: Copy,
42    F: Copy,
43    FMut: Copy,
44{
45}
46
47impl<V, O, F, FMut> MappedMutSignal<O, V, F, FMut>
48where
49    O: ?Sized,
50{
51    /// Create a new mapped signal.
52    pub fn new(value: V, map_fn: F, map_fn_mut: FMut) -> Self {
53        MappedMutSignal {
54            value,
55            map_fn,
56            map_fn_mut,
57            _marker: std::marker::PhantomData,
58        }
59    }
60}
61
62impl<V, O, F, FMut> Readable for MappedMutSignal<O, V, F, FMut>
63where
64    O: ?Sized,
65    V: Readable,
66    V::Target: 'static,
67    F: Fn(&V::Target) -> &O,
68{
69    type Target = O;
70    type Storage = V::Storage;
71
72    fn try_read_unchecked(
73        &self,
74    ) -> Result<ReadableRef<'static, Self>, generational_box::BorrowError>
75    where
76        O: 'static,
77    {
78        let value = self.value.try_read_unchecked()?;
79        Ok(V::Storage::map(value, |v| (self.map_fn)(v)))
80    }
81
82    fn try_peek_unchecked(&self) -> BorrowResult<ReadableRef<'static, Self>>
83    where
84        O: 'static,
85    {
86        let value = self.value.try_peek_unchecked()?;
87        Ok(V::Storage::map(value, |v| (self.map_fn)(v)))
88    }
89
90    fn subscribers(&self) -> Subscribers
91    where
92        O: 'static,
93    {
94        self.value.subscribers()
95    }
96}
97
98impl<V, O, F, FMut> Writable for MappedMutSignal<O, V, F, FMut>
99where
100    O: ?Sized,
101    V: Writable,
102    V::Target: 'static,
103    F: Fn(&V::Target) -> &O,
104    FMut: Fn(&mut V::Target) -> &mut O,
105{
106    type WriteMetadata = V::WriteMetadata;
107
108    fn try_write_unchecked(
109        &self,
110    ) -> Result<WritableRef<'static, Self>, generational_box::BorrowMutError> {
111        let value = self.value.try_write_unchecked()?;
112        Ok(WriteLock::map(value, |v| (self.map_fn_mut)(v)))
113    }
114}
115
116impl<V, O, F, FMut> IntoAttributeValue for MappedMutSignal<O, V, F, FMut>
117where
118    O: Clone + IntoAttributeValue + 'static,
119    V: Readable,
120    V::Target: 'static,
121    F: Fn(&V::Target) -> &O,
122{
123    fn into_value(self) -> dioxus_core::AttributeValue {
124        self.with(|f| f.clone().into_value())
125    }
126}
127
128impl<V, O, F, FMut> PartialEq for MappedMutSignal<O, V, F, FMut>
129where
130    O: ?Sized,
131    V: Readable + PartialEq,
132    F: PartialEq,
133    FMut: PartialEq,
134{
135    fn eq(&self, other: &Self) -> bool {
136        self.value == other.value
137            && self.map_fn == other.map_fn
138            && self.map_fn_mut == other.map_fn_mut
139    }
140}
141
142/// Allow calling a signal with signal() syntax
143///
144/// Currently only limited to clone types, though could probably specialize for string/arc/rc
145impl<V, O, F, FMut> Deref for MappedMutSignal<O, V, F, FMut>
146where
147    O: Clone + 'static,
148    V: Readable + 'static,
149    V::Target: 'static,
150    F: Fn(&V::Target) -> &O + 'static,
151    FMut: 'static,
152{
153    type Target = dyn Fn() -> O;
154
155    fn deref(&self) -> &Self::Target {
156        unsafe { ReadableExt::deref_impl(self) }
157    }
158}
159
160read_impls!(MappedMutSignal<T, V, F, FMut> where V: Readable<Target: 'static>, F: Fn(&V::Target) -> &T);
161write_impls!(MappedMutSignal<T, V, F, FMut> where V: Writable<Target: 'static>, F: Fn(&V::Target) -> &T, FMut: Fn(&mut V::Target) -> &mut T);