floem_reactive/
base.rs

1use std::marker::PhantomData;
2
3use crate::{
4    id::Id, signal::SignalState, storage::SyncStorage, ReadSignal, RwSignal, SignalGet,
5    SignalUpdate, SignalWith, WriteSignal,
6};
7
8/// BaseSignal gives you another way to control the lifetime of a Signal apart
9/// from Scope. This unsync variant stores its value on the UI thread.
10///
11/// When BaseSignal is dropped, it will dispose the underlying Signal as well.
12/// The signal isn't put in any Scope when a BaseSignal is created, so that the
13/// lifetime of the signal can only be determined by BaseSignal rather than
14/// Scope dependencies.
15pub struct BaseSignal<T: 'static> {
16    id: Id,
17    ty: PhantomData<T>,
18}
19
20impl<T: 'static> Eq for BaseSignal<T> {}
21
22impl<T: 'static> PartialEq for BaseSignal<T> {
23    fn eq(&self, other: &Self) -> bool {
24        self.id == other.id
25    }
26}
27
28impl<T: 'static> Drop for BaseSignal<T> {
29    fn drop(&mut self) {
30        self.id.dispose();
31    }
32}
33
34#[deprecated(
35    since = "0.2.0",
36    note = "Use BaseSignal::new instead; this will be removed in a future release"
37)]
38pub fn create_base_signal<T: 'static>(value: T) -> BaseSignal<T> {
39    BaseSignal::new(value)
40}
41
42impl<T: 'static> BaseSignal<T> {
43    pub fn new(value: T) -> Self {
44        let id = SignalState::new(value);
45        BaseSignal {
46            id,
47            ty: PhantomData,
48        }
49    }
50
51    /// Create a RwSignal of this Signal
52    pub fn rw(&self) -> RwSignal<T> {
53        RwSignal {
54            id: self.id,
55            ty: PhantomData,
56            st: PhantomData,
57        }
58    }
59
60    /// Create a Getter of this Signal
61    pub fn read_only(&self) -> ReadSignal<T> {
62        ReadSignal {
63            id: self.id,
64            ty: PhantomData,
65            st: PhantomData,
66        }
67    }
68
69    /// Create a Setter of this Signal
70    pub fn write_only(&self) -> WriteSignal<T> {
71        WriteSignal {
72            id: self.id,
73            ty: PhantomData,
74            st: PhantomData,
75        }
76    }
77}
78
79impl<T: Clone + 'static> SignalGet<T> for BaseSignal<T> {
80    fn id(&self) -> Id {
81        self.id
82    }
83}
84
85impl<T: Clone + 'static> SignalWith<T> for BaseSignal<T> {
86    fn id(&self) -> Id {
87        self.id
88    }
89}
90
91impl<T: 'static> SignalUpdate<T> for BaseSignal<T> {
92    fn id(&self) -> Id {
93        self.id
94    }
95
96    fn set(&self, new_value: T)
97    where
98        T: 'static,
99    {
100        self.write_only().set(new_value)
101    }
102
103    fn update(&self, f: impl FnOnce(&mut T))
104    where
105        T: 'static,
106    {
107        self.write_only().update(f)
108    }
109
110    fn try_update<O>(&self, f: impl FnOnce(&mut T) -> O) -> Option<O>
111    where
112        T: 'static,
113    {
114        self.write_only().try_update(f)
115    }
116}
117
118/// Thread-safe variant that stores the signal in the sync runtime.
119pub struct SyncBaseSignal<T: Send + Sync + 'static> {
120    id: Id,
121    ty: PhantomData<T>,
122}
123
124impl<T: Send + Sync + 'static> Eq for SyncBaseSignal<T> {}
125
126impl<T: Send + Sync + 'static> PartialEq for SyncBaseSignal<T> {
127    fn eq(&self, other: &Self) -> bool {
128        self.id == other.id
129    }
130}
131
132impl<T: Send + Sync + 'static> Drop for SyncBaseSignal<T> {
133    fn drop(&mut self) {
134        self.id.dispose();
135    }
136}
137
138impl<T: Send + Sync + 'static> SyncBaseSignal<T> {
139    pub fn new(value: T) -> Self {
140        let id = SignalState::new_sync(value);
141        SyncBaseSignal {
142            id,
143            ty: PhantomData,
144        }
145    }
146
147    /// Create a RwSignal of this Signal
148    pub fn rw(&self) -> RwSignal<T, SyncStorage> {
149        RwSignal {
150            id: self.id,
151            ty: PhantomData,
152            st: PhantomData,
153        }
154    }
155
156    /// Create a Getter of this Signal
157    pub fn read_only(&self) -> ReadSignal<T, SyncStorage> {
158        ReadSignal {
159            id: self.id,
160            ty: PhantomData,
161            st: PhantomData,
162        }
163    }
164
165    /// Create a Setter of this Signal
166    pub fn write_only(&self) -> WriteSignal<T, SyncStorage> {
167        WriteSignal {
168            id: self.id,
169            ty: PhantomData,
170            st: PhantomData,
171        }
172    }
173}
174
175impl<T: Clone + Send + Sync + 'static> SignalGet<T> for SyncBaseSignal<T> {
176    fn id(&self) -> Id {
177        self.id
178    }
179}
180
181impl<T: Clone + Send + Sync + 'static> SignalWith<T> for SyncBaseSignal<T> {
182    fn id(&self) -> Id {
183        self.id
184    }
185}
186
187impl<T: Send + Sync + 'static> SignalUpdate<T> for SyncBaseSignal<T> {
188    fn id(&self) -> Id {
189        self.id
190    }
191
192    fn set(&self, new_value: T)
193    where
194        T: 'static,
195    {
196        self.write_only().set(new_value)
197    }
198
199    fn update(&self, f: impl FnOnce(&mut T))
200    where
201        T: 'static,
202    {
203        self.write_only().update(f)
204    }
205
206    fn try_update<O>(&self, f: impl FnOnce(&mut T) -> O) -> Option<O>
207    where
208        T: 'static,
209    {
210        self.write_only().try_update(f)
211    }
212}