1use std::{cell::RefCell, iter, rc::Rc};
2
3use crate::api::Liftable;
4
5pub(crate) trait SignalExt<'a> {
6 fn react(&self);
7 fn guard(&self) -> SignalGuard<'a>;
8 fn decrease_dirty(&self);
9 fn get_dirty(&self) -> isize;
10 fn clone_box(&self) -> Box<dyn SignalExt<'a> + 'a>;
11 fn collect_guards_recursive(&self, result: &mut Vec<SignalGuardInner<'a>>);
12 fn collect_predecessors_recursive(&self, result: &mut Vec<SignalGuardInner<'a>>);
13 fn reset_explicitly_modified(&self);
14}
15
16pub(crate) trait RefStrategy<'a> {
17 type Ref<T: 'a>: 'a;
18 fn new_ref<T: 'a>(inner: &Rc<SignalInner<'a, T>>) -> Self::Ref<T>;
19 fn upgrade<T: 'a>(ref_: &Self::Ref<T>) -> Option<Rc<SignalInner<'a, T>>>;
20}
21
22pub(crate) struct WeakRefStrategy;
23
24impl<'a> RefStrategy<'a> for WeakRefStrategy {
25 type Ref<T: 'a> = std::rc::Weak<SignalInner<'a, T>>;
26
27 fn new_ref<T: 'a>(inner: &Rc<SignalInner<'a, T>>) -> Self::Ref<T> {
28 Rc::downgrade(inner)
29 }
30
31 fn upgrade<T: 'a>(ref_: &Self::Ref<T>) -> Option<Rc<SignalInner<'a, T>>> {
32 ref_.upgrade()
33 }
34}
35
36pub(crate) struct StrongRefStrategy;
37
38impl<'a> RefStrategy<'a> for StrongRefStrategy {
39 type Ref<T: 'a> = Rc<SignalInner<'a, T>>;
40
41 fn new_ref<T: 'a>(inner: &Rc<SignalInner<'a, T>>) -> Self::Ref<T> {
42 inner.clone()
43 }
44
45 fn upgrade<T: 'a>(ref_: &Self::Ref<T>) -> Option<Rc<SignalInner<'a, T>>> {
46 Some(ref_.clone())
47 }
48}
49
50pub(crate) struct WeakSignalRef<'a> {
51 upgrade: Box<dyn Fn() -> Option<Box<dyn SignalExt<'a> + 'a>> + 'a>,
52}
53
54impl<'a> WeakSignalRef<'a> {
55 pub fn new<T: 'a>(signal: &Signal<'a, T>) -> Self {
56 let weak = Rc::downgrade(&signal.0);
57 WeakSignalRef {
58 upgrade: Box::new(move || {
59 weak.upgrade()
60 .map(|rc| Box::new(Signal(rc)) as Box<dyn SignalExt<'a> + 'a>)
61 }),
62 }
63 }
64
65 pub fn upgrade(&self) -> Option<Box<dyn SignalExt<'a> + 'a>> {
66 (self.upgrade)()
67 }
68
69 pub fn is_alive(&self) -> bool {
70 self.upgrade().is_some()
71 }
72}
73
74pub struct SignalGuardInner<'a>(Box<dyn SignalExt<'a> + 'a>);
76
77#[allow(dead_code)]
79#[allow(unused_must_use)]
80pub struct SignalGuard<'a>(Vec<SignalGuardInner<'a>>);
81
82impl<'a> SignalGuard<'a> {
83 pub fn and(mut self, mut other: SignalGuard<'a>) -> SignalGuard<'a> {
85 self.0.append(&mut other.0);
86 self
87 }
88}
89
90impl<'a> Drop for SignalGuardInner<'a> {
91 fn drop(&mut self) {
92 self.0.decrease_dirty();
93 if self.0.get_dirty() == 0 {
94 self.0.react();
95 self.0.reset_explicitly_modified();
96 }
97 }
98}
99
100impl<'a> Drop for SignalGuard<'a> {
101 fn drop(&mut self) {
102 drop(std::mem::take(&mut self.0));
104 }
105}
106
107pub struct SignalInner<'a, T> {
109 pub(crate) value: RefCell<T>,
110 pub(crate) react_fns: RefCell<Vec<Box<dyn Fn() + 'a>>>,
111 pub(crate) successors: RefCell<Vec<WeakSignalRef<'a>>>,
112 pub(crate) predecessors: RefCell<Vec<WeakSignalRef<'a>>>,
113 pub(crate) dirty: RefCell<isize>,
114 pub(crate) explicitly_modified: RefCell<bool>,
115}
116
117pub struct Signal<'a, T>(pub(crate) Rc<SignalInner<'a, T>>);
119
120impl<'a, T: 'a> Signal<'a, T> {
121 pub fn new(initial: T) -> Self {
123 let inner = Rc::new(SignalInner {
124 value: RefCell::new(initial),
125 react_fns: RefCell::new(Vec::new()),
126 successors: RefCell::new(Vec::new()),
127 predecessors: RefCell::new(Vec::new()),
128 dirty: RefCell::new(0),
129 explicitly_modified: RefCell::new(false),
130 });
131 Signal(inner)
132 }
133
134 #[inline]
136 fn take_value<U>(cell: &RefCell<U>) -> U {
137 let mut temp = unsafe { std::mem::MaybeUninit::<U>::uninit().assume_init() };
138 std::mem::swap(&mut *cell.borrow_mut(), &mut temp);
139 temp
140 }
141
142 pub fn send(&self, new_value: T) -> SignalGuard<'a> {
159 self.modify(|v| *v = new_value);
160 *self.0.explicitly_modified.borrow_mut() = true;
161 self.guard()
162 }
163
164 pub fn send_with<F>(&self, f: F) -> SignalGuard<'a>
172 where
173 F: FnOnce(&mut T),
174 {
175 self.modify(f);
176 self.guard()
177 }
178
179 pub fn set(&mut self, signal: Signal<'a, T>) {
180 self.0 = signal.0;
181 }
182
183 pub fn map<U: 'a, F>(&self, f: F) -> Signal<'a, U>
196 where
197 F: Fn(&T) -> U + 'a,
198 {
199 self.map_ref::<U, F, WeakRefStrategy>(f)
200 }
201
202 pub fn with<U: 'a, F>(&self, f: F) -> Signal<'a, U>
216 where
217 F: Fn(&T) -> U + 'a,
218 {
219 self.map_ref::<U, F, StrongRefStrategy>(f)
220 }
221
222 fn map_ref<U: 'a, F, S: RefStrategy<'a>>(&self, f: F) -> Signal<'a, U>
223 where
224 F: Fn(&T) -> U + 'a,
225 {
226 let new_signal = Signal::new(f(&self.0.value.borrow()));
227 let result_new_signal = new_signal.clone();
228
229 let new_signal_ref = S::new_ref(&new_signal.0);
230 let source_ref = S::new_ref(&self.0);
231
232 let react_fn = Box::new(move || {
233 if let Some(new_sig_inner) = S::upgrade(&new_signal_ref) {
234 if !*new_sig_inner.explicitly_modified.borrow() {
235 if let Some(src_inner) = S::upgrade(&source_ref) {
236 let new_value = f(&src_inner.value.borrow());
237 *new_sig_inner.value.borrow_mut() = new_value;
238 }
239 }
240 }
241 });
242
243 self.0.react_fns.borrow_mut().push(react_fn);
244 self.0
245 .successors
246 .borrow_mut()
247 .push(WeakSignalRef::new(&new_signal));
248
249 result_new_signal
250 }
251
252 pub fn contramap<F, U>(&self, f: F) -> Signal<'a, U>
268 where
269 F: Fn(&U) -> T + 'a,
270 U: Default + 'a,
271 {
272 let new_signal = Signal::new(U::default());
273 let result_new_signal = new_signal.clone();
274 let source_inner = Rc::downgrade(&self.0);
275 let new_signal_rc = Rc::downgrade(&new_signal.0);
276
277 let react_fn = Box::new(move || {
278 if let Some(new_sig) = new_signal_rc.upgrade() {
279 if *new_sig.explicitly_modified.borrow() {
280 let u_value_ref = new_sig.value.borrow();
281 let t_value = f(&u_value_ref);
282 drop(u_value_ref);
283
284 if let Some(source) = source_inner.upgrade() {
285 *source.value.borrow_mut() = t_value;
286 *source.explicitly_modified.borrow_mut() = true;
287 }
288 }
289 }
290 });
291 new_signal.0.react_fns.borrow_mut().push(react_fn);
292
293 new_signal
294 .0
295 .predecessors
296 .borrow_mut()
297 .push(WeakSignalRef::new(self));
298
299 result_new_signal
300 }
301
302 pub fn promap<F, G, U>(&self, f: F, g: G) -> Signal<'a, U>
319 where
320 F: Fn(&T) -> U + 'a,
321 G: Fn(&U) -> T + 'a,
322 U: Default + 'a,
323 {
324 let new_signal = Signal::new(U::default());
325 let result_new_signal = new_signal.clone();
326 let source_weak = Rc::downgrade(&self.0);
327 let new_signal_weak = Rc::downgrade(&new_signal.0);
328
329 let source_inner = source_weak.clone();
331 let new_signal_rc = new_signal_weak.clone();
332 let forward_react_fn = Box::new(move || {
333 if let Some(new_sig) = new_signal_rc.upgrade() {
334 if !*new_sig.explicitly_modified.borrow() {
335 if let Some(source) = source_inner.upgrade() {
336 let t_value = source.value.borrow();
337 let u_value = f(&t_value);
338 drop(t_value);
339 *new_sig.value.borrow_mut() = u_value;
340 }
341 }
342 }
343 });
344
345 self.0.react_fns.borrow_mut().push(forward_react_fn);
346 self.0
347 .successors
348 .borrow_mut()
349 .push(WeakSignalRef::new(&new_signal));
350
351 let new_signal_rc_back = new_signal_weak.clone();
353 let source_inner_back = source_weak.clone();
354
355 let backward_react_fn = Box::new(move || {
356 if let Some(new_sig) = new_signal_rc_back.upgrade() {
357 if *new_sig.explicitly_modified.borrow() {
358 let u_value_ref = new_sig.value.borrow();
359 let t_value = g(&u_value_ref);
360 drop(u_value_ref);
361
362 if let Some(source) = source_inner_back.upgrade() {
363 *source.value.borrow_mut() = t_value;
364 *source.explicitly_modified.borrow_mut() = true;
365 }
366 }
367 }
368 });
369 new_signal.0.react_fns.borrow_mut().push(backward_react_fn);
370
371 new_signal
374 .0
375 .predecessors
376 .borrow_mut()
377 .push(WeakSignalRef::new(self));
378
379 result_new_signal
380 }
381
382 pub fn combine<S>(&self, another: S) -> Signal<'a, (T, S::Inner)>
396 where
397 S: Liftable<'a>,
398 S::Inner: 'a,
399 T: 'a,
400 {
401 self.combine_ref::<S, WeakRefStrategy>(another)
402 }
403
404 pub fn and<S>(&self, another: S) -> Signal<'a, (T, S::Inner)>
418 where
419 S: Liftable<'a>,
420 S::Inner: 'a,
421 T: 'a,
422 {
423 self.combine_ref::<S, StrongRefStrategy>(another)
424 }
425
426 fn combine_ref<S: Liftable<'a>, Strat: RefStrategy<'a>>(
427 &self,
428 another: S,
429 ) -> Signal<'a, (T, S::Inner)>
430 where
431 S::Inner: 'a,
432 T: 'a,
433 {
434 let another = another.as_ref();
435
436 let temp_val_0 = Self::take_value(&self.0.value);
438 let temp_val_1 = Self::take_value(&another.0.value);
439 let new_signal = Signal::new((temp_val_0, temp_val_1));
440 std::mem::swap(
441 &mut *self.0.value.borrow_mut(),
442 &mut new_signal.0.value.borrow_mut().0,
443 );
444 std::mem::swap(
445 &mut *another.0.value.borrow_mut(),
446 &mut new_signal.0.value.borrow_mut().1,
447 );
448
449 let result_new_signal = new_signal.clone();
450
451 let new_signal_ref = Strat::new_ref(&new_signal.0);
453 let self_ref = Strat::new_ref(&self.0);
454 let react_fn_self = Box::new(move || {
455 if let (Some(new_sig), Some(src)) =
456 (Strat::upgrade(&new_signal_ref), Strat::upgrade(&self_ref))
457 {
458 if !*new_sig.explicitly_modified.borrow() {
459 std::mem::swap(
460 &mut *src.value.borrow_mut(),
461 &mut new_sig.value.borrow_mut().0,
462 );
463 }
464 }
465 });
466 self.0.react_fns.borrow_mut().push(react_fn_self);
467 self.0
468 .successors
469 .borrow_mut()
470 .push(WeakSignalRef::new(&result_new_signal));
471
472 let new_signal_ref_2 = Strat::new_ref(&new_signal.0);
474 let another_ref = Strat::new_ref(&another.0);
475 let react_fn_another = Box::new(move || {
476 if let (Some(new_sig), Some(src)) = (
477 Strat::upgrade(&new_signal_ref_2),
478 Strat::upgrade(&another_ref),
479 ) {
480 if !*new_sig.explicitly_modified.borrow() {
481 std::mem::swap(
482 &mut *src.value.borrow_mut(),
483 &mut new_sig.value.borrow_mut().1,
484 );
485 }
486 }
487 });
488 another.0.react_fns.borrow_mut().push(react_fn_another);
489 another
490 .0
491 .successors
492 .borrow_mut()
493 .push(WeakSignalRef::new(&result_new_signal));
494
495 result_new_signal
496 }
497
498 pub fn extend<S>(&self, others: impl IntoIterator<Item = S>) -> Signal<'a, Vec<T>>
514 where
515 S: Liftable<'a, Inner = T>,
516 T: 'a,
517 {
518 self.extend_ref::<S, WeakRefStrategy>(others)
519 }
520
521 pub fn follow<S>(&self, others: impl IntoIterator<Item = S>) -> Signal<'a, Vec<T>>
537 where
538 S: Liftable<'a, Inner = T>,
539 T: 'a,
540 {
541 self.extend_ref::<S, StrongRefStrategy>(others)
542 }
543
544 fn extend_ref<S, Strat: RefStrategy<'a>>(
545 &self,
546 others: impl IntoIterator<Item = S>,
547 ) -> Signal<'a, Vec<T>>
548 where
549 S: Liftable<'a, Inner = T>,
550 T: 'a,
551 {
552 let others_signals: Vec<Signal<'a, T>> =
553 others.into_iter().map(|s| s.as_ref().clone()).collect();
554
555 let all_signals: Vec<&Signal<'a, T>> =
557 iter::once(self).chain(others_signals.iter()).collect();
558
559 let temp_values: Vec<T> = all_signals
560 .iter()
561 .map(|s| Self::take_value(&s.0.value))
562 .collect();
563 let new_signal: Signal<'a, Vec<T>> = Signal::new(temp_values);
564
565 for (index, signal) in all_signals.iter().enumerate() {
567 std::mem::swap(
568 &mut *signal.0.value.borrow_mut(),
569 &mut new_signal.0.value.borrow_mut()[index],
570 );
571 }
572
573 let result_new_signal = new_signal.clone();
574
575 iter::once(self)
576 .chain(others_signals.iter())
577 .enumerate()
578 .for_each(|(index, signal)| {
579 let new_signal_ref = Strat::new_ref(&new_signal.0);
580 let source_ref = Strat::new_ref(&signal.0);
581
582 let react_fn = Box::new(move || {
583 if let Some(new_sig) = Strat::upgrade(&new_signal_ref) {
584 if !*new_sig.explicitly_modified.borrow() {
585 if let Some(src) = Strat::upgrade(&source_ref) {
586 std::mem::swap(
588 &mut new_sig.value.borrow_mut()[index],
589 &mut *src.value.borrow_mut(),
590 );
591 }
592 }
593 }
594 });
595
596 signal.0.react_fns.borrow_mut().push(react_fn);
597 signal
598 .0
599 .successors
600 .borrow_mut()
601 .push(WeakSignalRef::new(&new_signal));
602 });
603
604 result_new_signal
605 }
606
607 pub fn depend(&self, dependency: Signal<'a, T>) -> Signal<'a, T>
632 where
633 T: Clone,
634 {
635 let self_weak = Rc::downgrade(&self.0);
636 let dependency_weak = Rc::downgrade(&dependency.0);
637
638 let react_fn = Box::new(move || {
639 if let Some(dep) = dependency_weak.upgrade() {
640 if let Some(target) = self_weak.upgrade() {
641 if !*target.explicitly_modified.borrow() {
642 std::mem::swap(
644 &mut *target.value.borrow_mut(),
645 &mut *dep.value.borrow_mut(),
646 );
647 }
648 }
649 }
650 });
651
652 dependency.0.react_fns.borrow_mut().push(react_fn);
653 dependency
654 .0
655 .successors
656 .borrow_mut()
657 .push(WeakSignalRef::new(self));
658 dependency
659 }
660
661 pub(crate) fn modify(&self, f: impl FnOnce(&mut T)) {
662 let mut value = self.0.value.borrow_mut();
663 f(&mut value);
664 }
665
666 fn mark_dirty(&self) {
667 *self.0.dirty.borrow_mut() += 1;
668 }
669
670 fn collect_and_iterate<F>(&self, refs: &RefCell<Vec<WeakSignalRef<'a>>>, mut callback: F)
671 where
672 F: FnMut(&dyn SignalExt<'a>),
673 {
674 refs.borrow_mut().retain(|s| s.is_alive());
675 for s in refs.borrow().iter() {
676 if let Some(signal) = s.upgrade() {
677 callback(&*signal);
678 }
679 }
680 }
681
682 fn collect_guards(&self, result: &mut Vec<SignalGuardInner<'a>>) {
683 self.mark_dirty();
684 result.push(SignalGuardInner(self.clone_box()));
685 self.collect_and_iterate(&self.0.successors, |signal| {
686 signal.collect_guards_recursive(result);
687 });
688 self.collect_and_iterate(&self.0.predecessors, |signal| {
689 signal.collect_predecessors_recursive(result);
690 });
691 }
692
693 pub fn lift_from_array<S, const N: usize>(items: [S; N]) -> Signal<'a, [S::Inner; N]>
708 where
709 S: Liftable<'a>,
710 S::Inner: 'a,
711 {
712 let signals: [Signal<'a, S::Inner>; N] = std::array::from_fn(|i| items[i].as_ref().clone());
713
714 let initial: [S::Inner; N] = std::array::from_fn(|i| Self::take_value(&signals[i].0.value));
716 let new_signal: Signal<'a, [S::Inner; N]> = Signal::new(initial);
717
718 for (index, signal) in signals.iter().enumerate() {
720 std::mem::swap(
721 &mut *signal.0.value.borrow_mut(),
722 &mut new_signal.0.value.borrow_mut()[index],
723 );
724 }
725
726 let result_new_signal = new_signal.clone();
727
728 for (index, signal) in signals.iter().enumerate() {
729 let new_signal_weak = Rc::downgrade(&new_signal.0);
730 let source_for_closure = Rc::downgrade(&signal.0);
731
732 let react_fn = Box::new(move || {
733 if let Some(new_sig) = new_signal_weak.upgrade() {
734 if !*new_sig.explicitly_modified.borrow() {
735 if let Some(source) = source_for_closure.upgrade() {
736 std::mem::swap(
738 &mut new_sig.value.borrow_mut()[index],
739 &mut *source.value.borrow_mut(),
740 );
741 }
742 }
743 }
744 });
745
746 signal.0.react_fns.borrow_mut().push(react_fn);
747 signal
748 .0
749 .successors
750 .borrow_mut()
751 .push(WeakSignalRef::new(&new_signal));
752 }
753
754 result_new_signal
755 }
756}
757
758impl<'a, T: 'a> SignalExt<'a> for Signal<'a, T> {
759 fn react(&self) {
760 self.0.react_fns.borrow().iter().for_each(|react_fn| {
761 react_fn();
762 });
763 }
764 fn guard(&self) -> SignalGuard<'a> {
765 let mut result = vec![];
766 self.collect_guards(&mut result);
767 SignalGuard(result)
768 }
769 fn clone_box(&self) -> Box<dyn SignalExt<'a> + 'a> {
770 Box::new(Signal(Rc::clone(&self.0)))
771 }
772 fn decrease_dirty(&self) {
773 *self.0.dirty.borrow_mut() -= 1;
774 }
775 fn get_dirty(&self) -> isize {
776 *self.0.dirty.borrow()
777 }
778 fn reset_explicitly_modified(&self) {
779 *self.0.explicitly_modified.borrow_mut() = false;
780 }
781 fn collect_guards_recursive(&self, result: &mut Vec<SignalGuardInner<'a>>) {
782 self.mark_dirty();
783 result.push(SignalGuardInner(self.clone_box()));
784 self.collect_and_iterate(&self.0.successors, |signal| {
785 signal.collect_guards_recursive(result);
786 });
787 }
788 fn collect_predecessors_recursive(&self, result: &mut Vec<SignalGuardInner<'a>>) {
789 self.mark_dirty();
790 result.push(SignalGuardInner(self.clone_box()));
791 self.collect_and_iterate(&self.0.predecessors, |signal| {
793 signal.collect_predecessors_recursive(result);
794 });
795 }
796}
797
798impl<T> Clone for Signal<'_, T> {
799 fn clone(&self) -> Self {
800 Self(self.0.clone())
801 }
802}
803
804impl<'a, T> AsRef<Signal<'a, T>> for Signal<'a, T> {
805 fn as_ref(&self) -> &Signal<'a, T> {
806 self
807 }
808}
809
810#[cfg(test)]
811mod tests {
812
813 use crate::api::LiftInto;
814
815 use super::*;
816
817 #[test]
818 fn test_signal() {
819 let a = Signal::new(0);
820 let _a = a.map(|x| println!("a changed: {}", x));
821 (a.send(100), a.send(5));
822 }
823
824 #[test]
825 fn test_signal1() {
826 let a = Signal::new(0);
827 let b = a.map(|x| x * 2);
828 let _b = b.map(|x| println!("b changed: {}", x));
829 drop(b);
830 a.send(100);
831 }
832
833 #[test]
834 fn test_signal2() {
835 let a = Signal::new(0);
836 let b = a.map(|x| x * 2);
837 let ab = a.combine(&b);
838 let _ab = ab.map(|(x, y)| println!("c changed: {} + {} = {}", x, y, x + y));
839 (a.send(5), a.send(100));
840 }
841
842 #[test]
843 fn test_signal3() {
844 let a = Signal::new(0);
845 let b = a.map(|x| x * 2);
846 let ab = (&a, &b).lift();
847 let _ab = ab.map(|(x, y)| println!("c changed: {} + {} = {}", x, y, x + y));
848 (a.send(5), b.send(100));
849 }
850
851 #[test]
852 fn test_signal4() {
853 let a = Signal::new(0);
854 let b = Signal::new(10);
855 let c = Signal::new(20);
856 let abc = [&a, &b, &c].lift();
857 let _abc =
858 abc.map(|[x, y, z]| println!("d changed: {} + {} + {} = {}", x, y, z, x + y + z));
859 let d = Signal::new(0);
860 let abcd = abc.combine(&d);
861 let _abcd = abcd.map(|numbers| {
862 println!(
863 "e changed: {} + {} + {} + {} = {}",
864 numbers.0[0],
865 numbers.0[1],
866 numbers.0[2],
867 numbers.1,
868 numbers.0.iter().sum::<i32>() + numbers.1
869 )
870 });
871 (a.send(5), b.send(15), c.send(25), abc.send([2, 3, 4]));
872 }
873
874 #[test]
875 fn test_signal5() {
876 let result = Signal::new(42);
877 let source1 = result.contramap(|x| x + 1);
878 let source2 = source1.contramap(|x| x * 2);
879
880 let _observer_1 = result.map(|x| println!("result changed: {}", x));
881 let _observer_2 = source1.map(|x| println!("source1 changed: {}", x));
882 let _observer_3 = source2.map(|x| println!("source2 changed: {}", x));
883
884 println!("--- Sending to source1 ---");
885 source1.send(100);
886 println!("--- Sending to source2 ---");
887 source2.send(200);
888 println!("--- Sending to source1 and source2 ---");
889 (source1.send(300), source2.send(400));
890 }
891
892 #[test]
893 fn test_promap_forward() {
894 let source = Signal::new(10);
895 let derived = source.promap(|x| x * 2, |y| y / 2);
896
897 let _ = derived.map(|x| println!("derived changed: {}", x));
898 source.send(5);
899 }
900
901 #[test]
902 fn test_promap_backward() {
903 let source = Signal::new(10);
904 let derived = source.promap(|x| x * 2, |y| y / 2);
905
906 let _ = source.map(|x| println!("source changed: {}", x));
907 let _ = derived.map(|x| println!("derived changed: {}", x));
908 derived.send(50);
909 }
910
911 #[test]
912 fn test_promap_bidirectional() {
913 let a = Signal::new(10);
914 let b = a.promap(|x| x * 2, |y| y / 2);
915 let c = b.promap(|x| x + 3, |y| y - 3);
916
917 let _observer_a = a.map(|x| println!("a changed: {}", x));
918 let _observer_b = b.map(|x| println!("b changed: {}", x));
919 let _observer_c = c.map(|x| println!("c changed: {}", x));
920
921 println!("--- Sending to a ---");
922 a.send(5);
923 println!("--- Sending to c ---");
924 c.send(13);
925 println!("--- Sending to b ---");
926 b.send(10);
927 println!("--- Sending to a and c ---");
928 a.send(20).and(c.send(50));
929 println!("--- Sending to b and c ---");
930 (b.send(30), c.send(60));
931 }
932
933 #[test]
934 fn test_high_order_signal() {
935 let source = Signal::new(0);
936 let derived = source.map(|x| Signal::new(x + 1));
937 let _ = derived.map(|s| s.send(233));
938 let _ = derived.map(|s| s.map(|x| println!("derived changed: {}", x)));
939 source.send(5);
940 }
941
942 #[test]
943 fn test_depend() {
944 let a = Signal::new(10);
945 let b = Signal::new(10);
946 let c = Signal::new(10);
947
948 let _observer_a = a.map(|x| println!("a changed: {}", x));
949 let _observer_b = b.map(|x| println!("b changed: {}", x));
950 let _observer_c = c.map(|x| println!("c changed: {}", x));
951
952 c.depend(b.with(|x| x * 2));
953 b.depend(a.clone());
954
955 a.send(42);
956 }
957
958 #[test]
959 fn test_depend2() {
960 let a = Signal::new(10);
961 let b = a.map(|x| *x);
962 let c = b.map(|x| *x);
963
964 let _observer_a = a.map(|x| println!("a changed: {}", x));
965 let _observer_b = b.map(|x| println!("b changed: {}", x));
966 let _observer_c = c.map(|x| println!("c changed: {}", x));
967
968 (a.send(42), b.send(88));
969 }
970}