1use super::{
2 guards::{Mapped, MappedMutArc},
3 ArcRwSignal, RwSignal,
4};
5use crate::{
6 owner::{StoredValue, SyncStorage},
7 signal::guards::WriteGuard,
8 traits::{
9 DefinedAt, GetValue, IsDisposed, Notify, ReadUntracked, Track,
10 UntrackableGuard, Write,
11 },
12};
13use guardian::ArcRwLockWriteGuardian;
14use std::{
15 fmt::Debug,
16 ops::{Deref, DerefMut},
17 panic::Location,
18 sync::Arc,
19};
20
21pub struct ArcMappedSignal<T> {
29 #[cfg(any(debug_assertions, leptos_debuginfo))]
30 defined_at: &'static Location<'static>,
31 #[allow(clippy::type_complexity)]
32 try_read_untracked: Arc<
33 dyn Fn() -> Option<DoubleDeref<Box<dyn Deref<Target = T>>>>
34 + Send
35 + Sync,
36 >,
37 try_write: Arc<
38 dyn Fn() -> Option<Box<dyn UntrackableGuard<Target = T>>> + Send + Sync,
39 >,
40 notify: Arc<dyn Fn() + Send + Sync>,
41 track: Arc<dyn Fn() + Send + Sync>,
42}
43
44impl<T> Clone for ArcMappedSignal<T> {
45 fn clone(&self) -> Self {
46 Self {
47 #[cfg(any(debug_assertions, leptos_debuginfo))]
48 defined_at: self.defined_at,
49 try_read_untracked: self.try_read_untracked.clone(),
50 try_write: self.try_write.clone(),
51 notify: self.notify.clone(),
52 track: self.track.clone(),
53 }
54 }
55}
56
57impl<T> ArcMappedSignal<T> {
58 #[track_caller]
60 pub fn new<U>(
61 inner: ArcRwSignal<U>,
62 map: fn(&U) -> &T,
63 map_mut: fn(&mut U) -> &mut T,
64 ) -> Self
65 where
66 T: 'static,
67 U: Send + Sync + 'static,
68 {
69 Self {
70 #[cfg(any(debug_assertions, leptos_debuginfo))]
71 defined_at: Location::caller(),
72 try_read_untracked: {
73 let this = inner.clone();
74 Arc::new(move || {
75 this.try_read_untracked().map(|guard| DoubleDeref {
76 inner: Box::new(Mapped::new_with_guard(guard, map))
77 as Box<dyn Deref<Target = T>>,
78 })
79 })
80 },
81 try_write: {
82 let this = inner.clone();
83 Arc::new(move || {
84 let guard = ArcRwLockWriteGuardian::try_take(Arc::clone(
85 &this.value,
86 ))?
87 .ok()?;
88 let mapped = WriteGuard::new(
89 this.clone(),
90 MappedMutArc::new(guard, map, map_mut),
91 );
92 Some(Box::new(mapped))
93 })
94 },
95 notify: {
96 let this = inner.clone();
97 Arc::new(move || {
98 this.notify();
99 })
100 },
101 track: {
102 Arc::new(move || {
103 inner.track();
104 })
105 },
106 }
107 }
108}
109
110impl<T> Debug for ArcMappedSignal<T> {
111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112 let mut partial = f.debug_struct("ArcMappedSignal");
113 #[cfg(any(debug_assertions, leptos_debuginfo))]
114 partial.field("defined_at", &self.defined_at);
115 partial.finish()
116 }
117}
118
119impl<T> DefinedAt for ArcMappedSignal<T> {
120 fn defined_at(&self) -> Option<&'static Location<'static>> {
121 #[cfg(any(debug_assertions, leptos_debuginfo))]
122 {
123 Some(self.defined_at)
124 }
125 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
126 {
127 None
128 }
129 }
130}
131
132impl<T> Notify for ArcMappedSignal<T> {
133 fn notify(&self) {
134 (self.notify)()
135 }
136}
137
138impl<T> Track for ArcMappedSignal<T> {
139 fn track(&self) {
140 (self.track)()
141 }
142}
143
144impl<T> ReadUntracked for ArcMappedSignal<T> {
145 type Value = DoubleDeref<Box<dyn Deref<Target = T>>>;
146
147 fn try_read_untracked(&self) -> Option<Self::Value> {
148 (self.try_read_untracked)()
149 }
150}
151
152impl<T> IsDisposed for ArcMappedSignal<T> {
153 fn is_disposed(&self) -> bool {
154 false
155 }
156}
157
158impl<T> Write for ArcMappedSignal<T>
159where
160 T: 'static,
161{
162 type Value = T;
163
164 fn try_write_untracked(
165 &self,
166 ) -> Option<impl DerefMut<Target = Self::Value>> {
167 let mut guard = self.try_write()?;
168 guard.untrack();
169 Some(guard)
170 }
171
172 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
173 let inner = (self.try_write)()?;
174 let inner = DoubleDeref { inner };
175 Some(inner)
176 }
177}
178
179pub struct DoubleDeref<T> {
188 inner: T,
189}
190
191impl<T> Deref for DoubleDeref<T>
192where
193 T: Deref,
194 T::Target: Deref,
195{
196 type Target = <T::Target as Deref>::Target;
197
198 fn deref(&self) -> &Self::Target {
199 self.inner.deref().deref()
200 }
201}
202
203impl<T> DerefMut for DoubleDeref<T>
204where
205 T: DerefMut,
206 T::Target: DerefMut,
207{
208 fn deref_mut(&mut self) -> &mut Self::Target {
209 self.inner.deref_mut().deref_mut()
210 }
211}
212
213impl<T> UntrackableGuard for DoubleDeref<T>
214where
215 T: UntrackableGuard,
216 T::Target: DerefMut,
217{
218 fn untrack(&mut self) {
219 self.inner.untrack();
220 }
221}
222
223pub struct MappedSignal<T, S = SyncStorage> {
231 #[cfg(any(debug_assertions, leptos_debuginfo))]
232 defined_at: &'static Location<'static>,
233 inner: StoredValue<ArcMappedSignal<T>, S>,
234}
235
236impl<T> MappedSignal<T> {
237 #[track_caller]
239 pub fn new<U>(
240 inner: RwSignal<U>,
241 map: fn(&U) -> &T,
242 map_mut: fn(&mut U) -> &mut T,
243 ) -> Self
244 where
245 T: Send + Sync + 'static,
246 U: Send + Sync + 'static,
247 {
248 Self {
249 #[cfg(any(debug_assertions, leptos_debuginfo))]
250 defined_at: Location::caller(),
251 inner: {
252 let this = ArcRwSignal::from(inner);
253 StoredValue::new_with_storage(ArcMappedSignal::new(
254 this, map, map_mut,
255 ))
256 },
257 }
258 }
259}
260
261impl<T> Copy for MappedSignal<T> {}
262
263impl<T> Clone for MappedSignal<T> {
264 fn clone(&self) -> Self {
265 *self
266 }
267}
268
269impl<T> Debug for MappedSignal<T> {
270 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271 let mut partial = f.debug_struct("MappedSignal");
272 #[cfg(any(debug_assertions, leptos_debuginfo))]
273 partial.field("defined_at", &self.defined_at);
274 partial.finish()
275 }
276}
277
278impl<T> DefinedAt for MappedSignal<T> {
279 fn defined_at(&self) -> Option<&'static Location<'static>> {
280 #[cfg(any(debug_assertions, leptos_debuginfo))]
281 {
282 Some(self.defined_at)
283 }
284 #[cfg(not(any(debug_assertions, leptos_debuginfo)))]
285 {
286 None
287 }
288 }
289}
290
291impl<T> Notify for MappedSignal<T>
292where
293 T: 'static,
294{
295 fn notify(&self) {
296 if let Some(inner) = self.inner.try_get_value() {
297 inner.notify();
298 }
299 }
300}
301
302impl<T> Track for MappedSignal<T>
303where
304 T: 'static,
305{
306 fn track(&self) {
307 if let Some(inner) = self.inner.try_get_value() {
308 inner.track();
309 }
310 }
311}
312
313impl<T> ReadUntracked for MappedSignal<T>
314where
315 T: 'static,
316{
317 type Value = DoubleDeref<Box<dyn Deref<Target = T>>>;
318
319 fn try_read_untracked(&self) -> Option<Self::Value> {
320 self.inner
321 .try_get_value()
322 .and_then(|inner| inner.try_read_untracked())
323 }
324}
325
326impl<T> Write for MappedSignal<T>
327where
328 T: 'static,
329{
330 type Value = T;
331
332 fn try_write_untracked(
333 &self,
334 ) -> Option<impl DerefMut<Target = Self::Value>> {
335 let mut guard = self.try_write()?;
336 guard.untrack();
337 Some(guard)
338 }
339
340 fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
341 let inner = self.inner.try_get_value()?;
342 let inner = (inner.try_write)()?;
343 let inner = DoubleDeref { inner };
344 Some(inner)
345 }
346}
347
348impl<T> From<ArcMappedSignal<T>> for MappedSignal<T>
349where
350 T: 'static,
351{
352 #[track_caller]
353 fn from(value: ArcMappedSignal<T>) -> Self {
354 MappedSignal {
355 #[cfg(any(debug_assertions, leptos_debuginfo))]
356 defined_at: Location::caller(),
357 inner: StoredValue::new(value),
358 }
359 }
360}
361
362impl<T> IsDisposed for MappedSignal<T> {
363 fn is_disposed(&self) -> bool {
364 self.inner.is_disposed()
365 }
366}