maycoon_core/signal/
eval.rs1use crate::reference::Ref;
2use crate::signal::Signal;
3use std::rc::Rc;
4
5pub struct EvalSignal<T: 'static> {
10 eval: Rc<dyn Fn() -> T>,
11}
12
13impl<T: 'static> EvalSignal<T> {
14 #[inline(always)]
16 pub fn new(eval: impl Fn() -> T + 'static) -> Self {
17 Self {
18 eval: Rc::new(eval),
19 }
20 }
21}
22
23impl<T: 'static> Signal<T> for EvalSignal<T> {
24 #[inline(always)]
25 fn get(&self) -> Ref<'_, T> {
26 Ref::Owned((self.eval)())
27 }
28
29 #[inline(always)]
30 fn set_value(&self, _: T) {}
31
32 #[inline(always)]
33 fn listen(self, _: Box<dyn Fn(Ref<'_, T>)>) -> Self
34 where
35 Self: Sized,
36 {
37 self
38 }
39
40 #[inline(always)]
41 fn notify(&self) {}
42
43 #[inline(always)]
44 fn dyn_clone(&self) -> Box<dyn Signal<T>> {
45 Box::new(self.clone())
46 }
47}
48
49impl<T: 'static> Clone for EvalSignal<T> {
50 #[inline(always)]
51 fn clone(&self) -> Self {
52 Self {
53 eval: self.eval.clone(),
54 }
55 }
56}
57
58#[cfg(all(test, feature = "test"))]
59mod tests {
60 use crate::signal::Signal;
61 use crate::signal::eval::EvalSignal;
62 use std::cell::RefCell;
63 use std::rc::Rc;
64
65 #[test]
67 fn test_eval_signal() {
68 let value = Rc::new(RefCell::new(0));
69
70 let value_clone = value.clone();
71 let signal = EvalSignal::new(move || {
72 *value_clone.borrow_mut() += 1;
73 *value_clone.borrow()
74 });
75
76 assert_eq!(*signal.get(), 1);
78 assert_eq!(*value.borrow(), 1);
79
80 assert_eq!(*signal.get(), 2);
82 assert_eq!(*value.borrow(), 2);
83
84 assert_eq!(*signal.get(), 3);
86 assert_eq!(*value.borrow(), 3);
87 }
88}