1use crate::{read::Readable, read_impls, ReadableExt, ReadableRef};
2use dioxus_core::{IntoAttributeValue, Subscribers};
3use generational_box::{AnyStorage, BorrowResult};
4use std::ops::Deref;
5
6pub struct MappedSignal<O: ?Sized, V, F = fn(&<V as Readable>::Target) -> &O> {
8 value: V,
9 map_fn: F,
10 _marker: std::marker::PhantomData<O>,
11}
12
13impl<V, O, F> Clone for MappedSignal<O, V, F>
14where
15 V: Readable + Clone,
16 F: Clone,
17{
18 fn clone(&self) -> Self {
19 MappedSignal {
20 value: self.value.clone(),
21 map_fn: self.map_fn.clone(),
22 _marker: std::marker::PhantomData,
23 }
24 }
25}
26
27impl<V, O, F> Copy for MappedSignal<O, V, F>
28where
29 V: Readable + Copy,
30 F: Copy,
31{
32}
33
34impl<V, O, F> MappedSignal<O, V, F>
35where
36 O: ?Sized,
37{
38 pub fn new(value: V, map_fn: F) -> Self {
40 MappedSignal {
41 value,
42 map_fn,
43 _marker: std::marker::PhantomData,
44 }
45 }
46}
47
48impl<V, O, F> Readable for MappedSignal<O, V, F>
49where
50 O: ?Sized,
51 V: Readable,
52 V::Target: 'static,
53 F: Fn(&V::Target) -> &O,
54{
55 type Target = O;
56 type Storage = V::Storage;
57
58 fn try_read_unchecked(
59 &self,
60 ) -> Result<ReadableRef<'static, Self>, generational_box::BorrowError> {
61 let value = self.value.try_read_unchecked()?;
62 Ok(V::Storage::map(value, |v| (self.map_fn)(v)))
63 }
64
65 fn try_peek_unchecked(&self) -> BorrowResult<ReadableRef<'static, Self>> {
66 let value = self.value.try_peek_unchecked()?;
67 Ok(V::Storage::map(value, |v| (self.map_fn)(v)))
68 }
69
70 fn subscribers(&self) -> Subscribers {
71 self.value.subscribers()
72 }
73}
74
75impl<V, O, F> IntoAttributeValue for MappedSignal<O, V, F>
76where
77 O: Clone + IntoAttributeValue + 'static,
78 V: Readable,
79 V::Target: 'static,
80 F: Fn(&V::Target) -> &O,
81{
82 fn into_value(self) -> dioxus_core::AttributeValue {
83 self.with(|f| f.clone().into_value())
84 }
85}
86
87impl<V, O, F> PartialEq for MappedSignal<O, V, F>
88where
89 O: ?Sized,
90 V: Readable + PartialEq,
91 F: PartialEq,
92{
93 fn eq(&self, other: &Self) -> bool {
94 self.value == other.value && self.map_fn == other.map_fn
95 }
96}
97
98impl<V, O, F> Deref for MappedSignal<O, V, F>
102where
103 O: Clone + 'static,
104 V: Readable + 'static,
105 F: Fn(&V::Target) -> &O + 'static,
106{
107 type Target = dyn Fn() -> O;
108
109 fn deref(&self) -> &Self::Target {
110 unsafe { ReadableExt::deref_impl(self) }
111 }
112}
113
114read_impls!(MappedSignal<T, V, F> where V: Readable<Target: 'static>, F: Fn(&V::Target) -> &T);