ori_core/reactive/
signal.rs1use std::{
2 cmp::Ordering,
3 fmt::{Debug, Formatter},
4 hash::{Hash, Hasher},
5 ops::{Deref, DerefMut},
6 panic::Location,
7};
8
9use crate::{CallbackEmitter, Lock, Lockable, Shared, Weak};
10
11pub struct ReadSignal<T: ?Sized> {
13 value: Lock<Shared<T>>,
14 emitter: CallbackEmitter,
15}
16
17impl<T> ReadSignal<T> {
18 pub fn new(value: T) -> Self {
20 Self::new_arc(Shared::new(value))
21 }
22}
23
24impl<T: ?Sized> ReadSignal<T> {
25 pub fn new_arc(value: Shared<T>) -> Self {
27 Self {
28 value: Lock::new(value),
29 emitter: CallbackEmitter::new(),
30 }
31 }
32
33 pub fn emitter(&self) -> &CallbackEmitter {
35 &self.emitter
36 }
37
38 pub fn track(&self) {
40 self.emitter.track();
41 }
42
43 pub fn get(&self) -> Shared<T> {
47 self.emitter.track();
48 self.get_untracked()
49 }
50
51 pub fn get_untracked(&self) -> Shared<T> {
53 self.value.lock_mut().clone()
54 }
55}
56
57impl<T: Clone> ReadSignal<T> {
58 pub fn cloned(&self) -> T {
62 self.get().as_ref().clone()
63 }
64
65 pub fn cloned_untracked(&self) -> T {
67 self.get_untracked().as_ref().clone()
68 }
69}
70
71impl<T: Copy> ReadSignal<T> {
72 pub fn copied(&self) -> T {
74 *self.get().as_ref()
75 }
76
77 pub fn copied_untracked(&self) -> T {
79 *self.get_untracked().as_ref()
80 }
81}
82
83pub struct Signal<T: ?Sized>(ReadSignal<T>);
113
114impl<T> Signal<T> {
115 pub fn new(value: T) -> Self {
117 Self(ReadSignal::new(value))
118 }
119
120 #[track_caller]
122 pub fn set(&self, value: T) {
123 self.set_arc(Shared::new(value));
124 }
125
126 pub fn set_silent(&self, value: T) {
128 self.set_arc_silent(Shared::new(value));
129 }
130}
131
132impl<T: ?Sized> Signal<T> {
133 pub fn new_arc(value: Shared<T>) -> Self {
135 Self(ReadSignal::new_arc(value))
136 }
137
138 #[track_caller]
140 pub fn set_arc(&self, value: Shared<T>) {
141 self.set_arc_silent(value.clone());
142 self.emit();
143 }
144
145 pub fn set_arc_silent(&self, value: Shared<T>) {
147 *self.value.lock_mut() = value;
148 }
149
150 #[track_caller]
152 pub fn emit(&self) {
153 let location = Location::caller();
154 tracing::trace!("emitting signal at {}", location);
155
156 self.emitter.emit(&());
157 }
158}
159
160impl<T: ?Sized> Deref for Signal<T> {
161 type Target = ReadSignal<T>;
162
163 fn deref(&self) -> &Self::Target {
164 &self.0
165 }
166}
167
168#[derive(Debug)]
169pub struct Modify<'a, T> {
170 value: Option<T>,
171 signal: &'a Signal<T>,
172}
173
174impl<'a, T> Deref for Modify<'a, T> {
175 type Target = T;
176
177 #[track_caller]
178 fn deref(&self) -> &Self::Target {
179 self.value.as_ref().unwrap()
180 }
181}
182
183impl<'a, T> DerefMut for Modify<'a, T> {
184 #[track_caller]
185 fn deref_mut(&mut self) -> &mut Self::Target {
186 self.value.as_mut().unwrap()
187 }
188}
189
190impl<'a, T> Drop for Modify<'a, T> {
192 fn drop(&mut self) {
193 self.signal.set(self.value.take().unwrap());
194 }
195}
196
197impl<T: Clone> Signal<T> {
198 pub fn modify(&self) -> Modify<'_, T> {
201 Modify {
202 value: Some(self.get().as_ref().clone()),
203 signal: self,
204 }
205 }
206}
207
208pub struct SharedSignal<T: ?Sized>(Shared<Signal<T>>);
210
211impl<T> SharedSignal<T> {
212 pub fn new(value: T) -> Self {
213 Self(Shared::new(Signal::new(value)))
214 }
215}
216
217impl<T: ?Sized> SharedSignal<T> {
218 pub fn new_arc(value: Shared<T>) -> Self {
219 Self(Shared::new(Signal::new_arc(value)))
220 }
221
222 pub fn downgrade(&self) -> WeakSignal<T> {
223 WeakSignal(Shared::downgrade(&self.0))
224 }
225}
226
227impl<T: ?Sized> Clone for SharedSignal<T> {
228 fn clone(&self) -> Self {
229 Self(self.0.clone())
230 }
231}
232
233impl<T: ?Sized> Deref for SharedSignal<T> {
234 type Target = Signal<T>;
235
236 fn deref(&self) -> &Self::Target {
237 &self.0
238 }
239}
240
241pub struct WeakSignal<T: ?Sized>(Weak<Signal<T>>);
243
244impl<T> WeakSignal<T> {
245 #[track_caller]
246 pub fn set(&self, value: T) {
247 if let Some(signal) = self.upgrade() {
248 signal.set(value);
249 }
250 }
251
252 pub fn set_silent(&self, value: T) {
253 if let Some(signal) = self.upgrade() {
254 signal.set_silent(value);
255 }
256 }
257}
258
259impl<T: ?Sized> WeakSignal<T> {
260 pub fn upgrade(&self) -> Option<SharedSignal<T>> {
261 self.0.upgrade().map(SharedSignal)
262 }
263
264 #[track_caller]
265 pub fn set_arc(&self, value: Shared<T>) {
266 if let Some(signal) = self.upgrade() {
267 signal.set_arc(value);
268 }
269 }
270
271 pub fn set_arc_silent(&self, value: Shared<T>) {
272 if let Some(signal) = self.upgrade() {
273 signal.set_arc_silent(value);
274 }
275 }
276
277 pub fn get(&self) -> Option<Shared<T>> {
278 Some(self.upgrade()?.get())
279 }
280
281 pub fn get_untracked(&self) -> Option<Shared<T>> {
282 Some(self.upgrade()?.get_untracked())
283 }
284}
285
286impl<T: ?Sized> Clone for WeakSignal<T> {
287 fn clone(&self) -> Self {
288 Self(self.0.clone())
289 }
290}
291
292impl<T: Debug + ?Sized> Debug for ReadSignal<T> {
293 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
294 f.debug_tuple("ReadSignal").field(&self.get()).finish()
295 }
296}
297
298impl<T: Debug + ?Sized> Debug for Signal<T> {
299 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
300 f.debug_tuple("Signal").field(&self.get()).finish()
301 }
302}
303
304impl<T: Debug + ?Sized> Debug for SharedSignal<T> {
305 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
306 f.debug_tuple("SharedSignal").field(&self.get()).finish()
307 }
308}
309
310impl<T: Debug + ?Sized> Debug for WeakSignal<T> {
311 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
312 f.debug_tuple("WeakSignal").field(&self.get()).finish()
313 }
314}
315
316impl<T: Default> Default for ReadSignal<T> {
317 fn default() -> Self {
318 Self::new(T::default())
319 }
320}
321
322impl<T: Default> Default for Signal<T> {
323 fn default() -> Self {
324 Self::new(T::default())
325 }
326}
327
328impl<T: Default> Default for SharedSignal<T> {
329 fn default() -> Self {
330 Self::new(T::default())
331 }
332}
333
334impl<T: PartialEq + ?Sized> PartialEq for ReadSignal<T> {
335 fn eq(&self, other: &Self) -> bool {
336 self.get() == other.get()
337 }
338}
339
340impl<T: PartialEq + ?Sized> PartialEq for Signal<T> {
341 fn eq(&self, other: &Self) -> bool {
342 self.get() == other.get()
343 }
344}
345
346impl<T: PartialEq + ?Sized> PartialEq for SharedSignal<T> {
347 fn eq(&self, other: &Self) -> bool {
348 self.get() == other.get()
349 }
350}
351
352impl<T: PartialEq + ?Sized> PartialEq for WeakSignal<T> {
353 fn eq(&self, other: &Self) -> bool {
354 self.get() == other.get()
355 }
356}
357
358impl<T: PartialEq + ?Sized> PartialEq<T> for ReadSignal<T> {
359 fn eq(&self, other: &T) -> bool {
360 self.get().as_ref() == other
361 }
362}
363
364impl<T: PartialEq + ?Sized> PartialEq<T> for Signal<T> {
365 fn eq(&self, other: &T) -> bool {
366 self.get().as_ref() == other
367 }
368}
369
370impl<T: PartialEq + ?Sized> PartialEq<T> for SharedSignal<T> {
371 fn eq(&self, other: &T) -> bool {
372 self.get().as_ref() == other
373 }
374}
375
376impl<T: Eq + ?Sized> Eq for ReadSignal<T> {}
377impl<T: Eq + ?Sized> Eq for Signal<T> {}
378impl<T: Eq + ?Sized> Eq for SharedSignal<T> {}
379
380impl<T: PartialOrd + ?Sized> PartialOrd for ReadSignal<T> {
381 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
382 self.get().partial_cmp(&other.get())
383 }
384}
385
386impl<T: PartialOrd + ?Sized> PartialOrd for Signal<T> {
387 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
388 self.get().partial_cmp(&other.get())
389 }
390}
391
392impl<T: PartialOrd + ?Sized> PartialOrd for SharedSignal<T> {
393 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
394 self.get().partial_cmp(&other.get())
395 }
396}
397
398impl<T: PartialOrd + ?Sized> PartialOrd<T> for ReadSignal<T> {
399 fn partial_cmp(&self, other: &T) -> Option<Ordering> {
400 self.get().as_ref().partial_cmp(other)
401 }
402}
403
404impl<T: PartialOrd + ?Sized> PartialOrd<T> for Signal<T> {
405 fn partial_cmp(&self, other: &T) -> Option<Ordering> {
406 self.get().as_ref().partial_cmp(other)
407 }
408}
409
410impl<T: PartialOrd + ?Sized> PartialOrd<T> for SharedSignal<T> {
411 fn partial_cmp(&self, other: &T) -> Option<Ordering> {
412 self.get().as_ref().partial_cmp(other)
413 }
414}
415
416impl<T: Ord + ?Sized> Ord for ReadSignal<T> {
417 fn cmp(&self, other: &Self) -> Ordering {
418 self.get().cmp(&other.get())
419 }
420}
421
422impl<T: Ord + ?Sized> Ord for Signal<T> {
423 fn cmp(&self, other: &Self) -> Ordering {
424 self.get().cmp(&other.get())
425 }
426}
427
428impl<T: Ord + ?Sized> Ord for SharedSignal<T> {
429 fn cmp(&self, other: &Self) -> Ordering {
430 self.get().cmp(&other.get())
431 }
432}
433
434impl<T: Hash + ?Sized> Hash for ReadSignal<T> {
435 fn hash<H: Hasher>(&self, state: &mut H) {
436 self.get().hash(state);
437 }
438}
439
440impl<T: Hash + ?Sized> Hash for Signal<T> {
441 fn hash<H: Hasher>(&self, state: &mut H) {
442 self.get().hash(state);
443 }
444}
445
446impl<T: Hash + ?Sized> Hash for SharedSignal<T> {
447 fn hash<H: Hasher>(&self, state: &mut H) {
448 self.get().hash(state);
449 }
450}
451
452impl<T: Hash + ?Sized> Hash for WeakSignal<T> {
453 fn hash<H: Hasher>(&self, state: &mut H) {
454 self.get().hash(state);
455 }
456}