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
10pub 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 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
142impl<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);