1use std::{
2 any::Any,
3 cell::{Ref, RefCell},
4 collections::HashMap,
5 fmt,
6 marker::PhantomData,
7 rc::Rc,
8};
9
10use crate::{
11 effect::{run_effect, EffectTrait},
12 id::Id,
13 read::{SignalRead, SignalTrack, SignalWith},
14 runtime::RUNTIME,
15 write::SignalWrite,
16 SignalGet, SignalUpdate,
17};
18
19#[allow(dead_code)]
22pub struct NotThreadSafe(*const ());
23
24pub struct RwSignal<T> {
26 pub(crate) id: Id,
27 pub(crate) ty: PhantomData<T>,
28 pub(crate) ts: PhantomData<NotThreadSafe>,
29}
30
31impl<T> Copy for RwSignal<T> {}
32
33impl<T> Clone for RwSignal<T> {
34 fn clone(&self) -> Self {
35 *self
36 }
37}
38
39impl<T> Eq for RwSignal<T> {}
40
41impl<T> PartialEq for RwSignal<T> {
42 fn eq(&self, other: &Self) -> bool {
43 self.id == other.id
44 }
45}
46
47impl<T> fmt::Debug for RwSignal<T> {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 let mut s = f.debug_struct("RwSignal");
50 s.field("id", &self.id);
51 s.field("ty", &self.ty);
52 s.finish()
53 }
54}
55
56impl<T: Default + 'static> Default for RwSignal<T> {
57 fn default() -> Self {
58 RwSignal::new(T::default())
59 }
60}
61
62impl<T> RwSignal<T> {
63 pub fn read_only(&self) -> ReadSignal<T> {
65 ReadSignal {
66 id: self.id,
67 ty: PhantomData,
68 ts: PhantomData,
69 }
70 }
71
72 pub fn write_only(&self) -> WriteSignal<T> {
74 WriteSignal {
75 id: self.id,
76 ty: PhantomData,
77 ts: PhantomData,
78 }
79 }
80}
81
82impl<T: 'static> RwSignal<T> {
83 pub fn new(value: T) -> Self {
84 create_rw_signal(value)
85 }
86 pub fn new_split(value: T) -> (ReadSignal<T>, WriteSignal<T>) {
87 let sig = Self::new(value);
88 (sig.read_only(), sig.write_only())
89 }
90}
91
92pub fn create_rw_signal<T>(value: T) -> RwSignal<T>
98where
99 T: Any + 'static,
100{
101 let id = Signal::create(value);
102 id.set_scope();
103 RwSignal {
104 id,
105 ty: PhantomData,
106 ts: PhantomData,
107 }
108}
109
110pub struct ReadSignal<T> {
112 pub(crate) id: Id,
113 pub(crate) ty: PhantomData<T>,
114 pub(crate) ts: PhantomData<NotThreadSafe>,
115}
116
117impl<T> Copy for ReadSignal<T> {}
118
119impl<T> Clone for ReadSignal<T> {
120 fn clone(&self) -> Self {
121 *self
122 }
123}
124
125impl<T> Eq for ReadSignal<T> {}
126
127impl<T> PartialEq for ReadSignal<T> {
128 fn eq(&self, other: &Self) -> bool {
129 self.id == other.id
130 }
131}
132
133pub struct WriteSignal<T> {
135 pub(crate) id: Id,
136 pub(crate) ty: PhantomData<T>,
137 pub(crate) ts: PhantomData<NotThreadSafe>,
138}
139
140impl<T> Copy for WriteSignal<T> {}
141
142impl<T> Clone for WriteSignal<T> {
143 fn clone(&self) -> Self {
144 *self
145 }
146}
147
148impl<T> Eq for WriteSignal<T> {}
149
150impl<T> PartialEq for WriteSignal<T> {
151 fn eq(&self, other: &Self) -> bool {
152 self.id == other.id
153 }
154}
155
156pub fn create_signal<T>(value: T) -> (ReadSignal<T>, WriteSignal<T>)
162where
163 T: Any + 'static,
164{
165 let s = create_rw_signal(value);
166 (s.read_only(), s.write_only())
167}
168
169#[derive(Clone)]
171pub(crate) struct Signal {
172 pub(crate) id: Id,
173 pub(crate) value: Rc<dyn Any>,
174 pub(crate) subscribers: Rc<RefCell<HashMap<Id, Rc<dyn EffectTrait>>>>,
175 pub(crate) ts: PhantomData<NotThreadSafe>,
176}
177
178impl Signal {
179 pub fn create<T>(value: T) -> Id
180 where
181 T: Any + 'static,
182 {
183 let id = Id::next();
184 let value = RefCell::new(value);
185 let signal = Signal {
186 id,
187 subscribers: Rc::new(RefCell::new(HashMap::new())),
188 value: Rc::new(value),
189 ts: PhantomData,
190 };
191 id.add_signal(signal);
192 id
193 }
194
195 pub fn borrow<T: 'static>(&self) -> Ref<'_, T> {
196 let value = self
197 .value
198 .downcast_ref::<RefCell<T>>()
199 .expect("to downcast signal type");
200 value.borrow()
201 }
202
203 pub(crate) fn get_untracked<T: Clone + 'static>(&self) -> T {
204 let value = self.borrow::<T>();
205 value.clone()
206 }
207
208 pub(crate) fn get<T: Clone + 'static>(&self) -> T {
209 self.subscribe();
210 self.get_untracked()
211 }
212
213 pub(crate) fn with_untracked<O, T: 'static>(&self, f: impl FnOnce(&T) -> O) -> O {
214 let value = self.borrow::<T>();
215 f(&value)
216 }
217
218 pub(crate) fn with<O, T: 'static>(&self, f: impl FnOnce(&T) -> O) -> O {
219 self.subscribe();
220 self.with_untracked(f)
221 }
222
223 pub(crate) fn update_value<U, T: 'static>(&self, f: impl FnOnce(&mut T) -> U) -> U {
224 let result = self
225 .value
226 .downcast_ref::<RefCell<T>>()
227 .expect("to downcast signal type");
228 let result = f(&mut result.borrow_mut());
229 self.run_effects();
230 result
231 }
232
233 pub(crate) fn subscribers(&self) -> HashMap<Id, Rc<dyn EffectTrait>> {
234 self.subscribers.borrow().clone()
235 }
236
237 pub(crate) fn run_effects(&self) {
238 if RUNTIME.with(|r| r.batching.get()) {
240 RUNTIME.with(|r| {
241 for (_, subscriber) in self.subscribers() {
242 r.add_pending_effect(subscriber);
243 }
244 });
245 return;
246 }
247
248 for (_, subscriber) in self.subscribers() {
249 run_effect(subscriber);
250 }
251 }
252
253 pub(crate) fn subscribe(&self) {
254 RUNTIME.with(|runtime| {
255 if let Some(effect) = runtime.current_effect.borrow().as_ref() {
256 self.subscribers
257 .borrow_mut()
258 .insert(effect.id(), effect.clone());
259 effect.add_observer(self.id);
260 }
261 });
262 }
263}
264
265impl<T: Clone> SignalGet<T> for RwSignal<T> {
266 fn id(&self) -> Id {
267 self.id
268 }
269}
270
271impl<T> SignalWith<T> for RwSignal<T> {
272 fn id(&self) -> Id {
273 self.id
274 }
275}
276
277impl<T> SignalTrack<T> for RwSignal<T> {
278 fn id(&self) -> Id {
279 self.id
280 }
281}
282
283impl<T> SignalRead<T> for RwSignal<T> {
284 fn id(&self) -> Id {
285 self.id
286 }
287}
288
289impl<T> SignalUpdate<T> for RwSignal<T> {
290 fn id(&self) -> Id {
291 self.id
292 }
293}
294
295impl<T> SignalWrite<T> for RwSignal<T> {
296 fn id(&self) -> Id {
297 self.id
298 }
299}
300
301impl<T: Clone> SignalGet<T> for ReadSignal<T> {
302 fn id(&self) -> Id {
303 self.id
304 }
305}
306
307impl<T> SignalWith<T> for ReadSignal<T> {
308 fn id(&self) -> Id {
309 self.id
310 }
311}
312
313impl<T> SignalTrack<T> for ReadSignal<T> {
314 fn id(&self) -> Id {
315 self.id
316 }
317}
318
319impl<T> SignalRead<T> for ReadSignal<T> {
320 fn id(&self) -> Id {
321 self.id
322 }
323}
324
325impl<T> SignalUpdate<T> for WriteSignal<T> {
326 fn id(&self) -> Id {
327 self.id
328 }
329}
330
331impl<T> SignalWrite<T> for WriteSignal<T> {
332 fn id(&self) -> Id {
333 self.id
334 }
335}