1use std::{
2 cell::{RefCell, RefMut},
3 marker::PhantomData,
4 rc::Rc,
5};
6
7use crate::{id::Id, signal::NotThreadSafe};
8
9#[derive(Clone)]
10pub struct WriteSignalValue<T> {
11 pub(crate) id: Id,
12 pub(crate) value: Rc<RefCell<T>>,
13 pub(crate) ts: PhantomData<NotThreadSafe>,
14}
15
16impl<T> Drop for WriteSignalValue<T> {
17 fn drop(&mut self) {
18 if let Some(signal) = self.id.signal() {
19 signal.run_effects();
20 }
21 }
22}
23
24impl<T> WriteSignalValue<T> {
25 pub fn borrow_mut(&self) -> RefMut<'_, T> {
27 self.value.borrow_mut()
28 }
29}
30
31pub trait SignalUpdate<T> {
32 fn id(&self) -> Id;
34
35 fn set(&self, new_value: T)
37 where
38 T: 'static,
39 {
40 if let Some(signal) = self.id().signal() {
41 signal.update_value(|v| *v = new_value);
42 }
43 }
44
45 fn update(&self, f: impl FnOnce(&mut T))
47 where
48 T: 'static,
49 {
50 if let Some(signal) = self.id().signal() {
51 signal.update_value(f);
52 }
53 }
54
55 fn try_update<O>(&self, f: impl FnOnce(&mut T) -> O) -> Option<O>
58 where
59 T: 'static,
60 {
61 self.id().signal().map(|signal| signal.update_value(f))
62 }
63}
64
65pub trait SignalWrite<T> {
66 fn id(&self) -> Id;
68 fn write(&self) -> WriteSignalValue<T>
73 where
74 T: 'static,
75 {
76 self.try_write().unwrap()
77 }
78
79 fn try_write(&self) -> Option<WriteSignalValue<T>>
85 where
86 T: 'static,
87 {
88 if let Some(signal) = self.id().signal() {
89 Some(WriteSignalValue {
90 id: signal.id,
91 value: signal
92 .value
93 .clone()
94 .downcast::<RefCell<T>>()
95 .expect("to downcast signal type"),
96 ts: PhantomData,
97 })
98 } else {
99 None
100 }
101 }
102}