1use leptos::prelude::*;
2use std::fmt::Debug;
3
4pub enum MaybeRwSignal<T, S = SyncStorage>
5where
6 T: 'static,
7 S: Storage<T>,
8{
9 Static(T),
10 DynamicRw(Signal<T, S>, WriteSignal<T, S>),
11 DynamicRead(Signal<T, S>),
12}
13
14impl<T: Clone, S> Clone for MaybeRwSignal<T, S>
15where
16 S: Storage<T>,
17{
18 fn clone(&self) -> Self {
19 match self {
20 Self::Static(t) => Self::Static(t.clone()),
21 Self::DynamicRw(r, w) => Self::DynamicRw(*r, *w),
22 Self::DynamicRead(s) => Self::DynamicRead(*s),
23 }
24 }
25}
26
27impl<T: Copy, S> Copy for MaybeRwSignal<T, S> where S: Storage<T> {}
28
29impl<T: Default, S> Default for MaybeRwSignal<T, S>
30where
31 S: Storage<T>,
32{
33 fn default() -> Self {
34 Self::Static(T::default())
35 }
36}
37
38impl<T: Debug, S> Debug for MaybeRwSignal<T, S>
39where
40 S: Storage<T> + Debug,
41{
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 match self {
44 Self::Static(t) => f.debug_tuple("Static").field(t).finish(),
45 Self::DynamicRw(r, w) => f.debug_tuple("DynamicRw").field(r).field(w).finish(),
46 Self::DynamicRead(s) => f.debug_tuple("DynamicRead").field(s).finish(),
47 }
48 }
49}
50
51impl<T> From<T> for MaybeRwSignal<T, SyncStorage>
52where
53 SyncStorage: Storage<T>,
54{
55 fn from(t: T) -> Self {
56 Self::Static(t)
57 }
58}
59
60impl<T> FromLocal<T> for MaybeRwSignal<T, LocalStorage>
61where
62 LocalStorage: Storage<T>,
63{
64 fn from_local(value: T) -> Self {
65 Self::Static(value)
66 }
67}
68
69impl<T> From<Signal<T>> for MaybeRwSignal<T>
70where
71 SyncStorage: Storage<T>,
72{
73 fn from(s: Signal<T>) -> Self {
74 Self::DynamicRead(s)
75 }
76}
77
78impl<T> FromLocal<Signal<T, LocalStorage>> for MaybeRwSignal<T, LocalStorage>
79where
80 LocalStorage: Storage<T>,
81{
82 fn from_local(s: Signal<T, LocalStorage>) -> Self {
83 Self::DynamicRead(s)
84 }
85}
86
87impl<T> From<ReadSignal<T>> for MaybeRwSignal<T>
88where
89 T: Send + Sync,
90{
91 fn from(s: ReadSignal<T>) -> Self {
92 Self::DynamicRead(s.into())
93 }
94}
95
96impl<T> FromLocal<ReadSignal<T, LocalStorage>> for MaybeRwSignal<T, LocalStorage>
97where
98 LocalStorage: Storage<T>,
99{
100 fn from_local(s: ReadSignal<T, LocalStorage>) -> Self {
101 Self::DynamicRead(s.into())
102 }
103}
104
105impl<T> From<Memo<T>> for MaybeRwSignal<T>
106where
107 T: Send + Sync,
108{
109 fn from(s: Memo<T>) -> Self {
110 Self::DynamicRead(s.into())
111 }
112}
113
114impl<T> FromLocal<Memo<T, LocalStorage>> for MaybeRwSignal<T, LocalStorage>
115where
116 LocalStorage: Storage<T>,
117{
118 fn from_local(s: Memo<T, LocalStorage>) -> Self {
119 Self::DynamicRead(s.into())
120 }
121}
122
123impl<T> From<RwSignal<T>> for MaybeRwSignal<T>
124where
125 T: Send + Sync,
126{
127 fn from(s: RwSignal<T>) -> Self {
128 let (r, w) = s.split();
129 Self::DynamicRw(r.into(), w)
130 }
131}
132
133impl<T> FromLocal<RwSignal<T, LocalStorage>> for MaybeRwSignal<T, LocalStorage>
134where
135 LocalStorage: Storage<T>,
136{
137 fn from_local(s: RwSignal<T, LocalStorage>) -> Self {
138 let (r, w) = s.split();
139 Self::DynamicRw(r.into(), w)
140 }
141}
142
143impl<T> From<(ReadSignal<T>, WriteSignal<T>)> for MaybeRwSignal<T>
144where
145 T: Send + Sync,
146{
147 fn from(s: (ReadSignal<T>, WriteSignal<T>)) -> Self {
148 Self::DynamicRw(s.0.into(), s.1)
149 }
150}
151
152impl<T> FromLocal<(ReadSignal<T, LocalStorage>, WriteSignal<T, LocalStorage>)>
153 for MaybeRwSignal<T, LocalStorage>
154where
155 LocalStorage: Storage<T>,
156{
157 fn from_local(s: (ReadSignal<T, LocalStorage>, WriteSignal<T, LocalStorage>)) -> Self {
158 Self::DynamicRw(s.0.into(), s.1)
159 }
160}
161
162impl<T> From<(Signal<T>, WriteSignal<T>)> for MaybeRwSignal<T>
163where
164 T: Send + Sync,
165{
166 fn from(s: (Signal<T>, WriteSignal<T>)) -> Self {
167 Self::DynamicRw(s.0, s.1)
168 }
169}
170
171impl<T> FromLocal<(Signal<T, LocalStorage>, WriteSignal<T, LocalStorage>)>
172 for MaybeRwSignal<T, LocalStorage>
173where
174 LocalStorage: Storage<T>,
175{
176 fn from_local(s: (Signal<T, LocalStorage>, WriteSignal<T, LocalStorage>)) -> Self {
177 Self::DynamicRw(s.0, s.1)
178 }
179}
180
181impl<S> From<&str> for MaybeRwSignal<String, S>
182where
183 S: Storage<String>,
184{
185 fn from(s: &str) -> Self {
186 Self::Static(s.to_string())
187 }
188}
189
190impl<T: Clone> MaybeRwSignal<T, LocalStorage> {
191 pub fn into_signal(self) -> (Signal<T, LocalStorage>, WriteSignal<T, LocalStorage>) {
192 match self {
193 Self::DynamicRead(s) => {
194 let (r, w) = signal_local(s.get_untracked());
195
196 Effect::<LocalStorage>::new(move |_| {
197 w.update(move |w| {
198 *w = s.get();
199 });
200 });
201
202 (r.into(), w)
203 }
204 Self::DynamicRw(r, w) => (r, w),
205 Self::Static(v) => {
206 let (r, w) = signal_local(v.clone());
207 (Signal::from(r), w)
208 }
209 }
210 }
211}
212
213impl<T: Clone> MaybeRwSignal<T>
214where
215 T: Send + Sync,
216{
217 pub fn into_signal(self) -> (Signal<T>, WriteSignal<T>) {
218 match self {
219 Self::DynamicRead(s) => {
220 let (r, w) = signal(s.get_untracked());
221
222 Effect::new(move |_| {
223 w.update(move |w| {
224 *w = s.get();
225 });
226 });
227
228 (r.into(), w)
229 }
230 Self::DynamicRw(r, w) => (r, w),
231 Self::Static(v) => {
232 let (r, w) = signal(v.clone());
233 (Signal::from(r), w)
234 }
235 }
236 }
237}