maycoon_core/signal/
map.rs1use crate::signal::{BoxedSignal, Ref, Signal};
2use std::rc::Rc;
3
4pub struct MapSignal<T: 'static, U: 'static> {
10 signal: BoxedSignal<T>,
11 map: Rc<dyn Fn(Ref<T>) -> Ref<U>>,
12}
13
14impl<T: 'static, U: 'static> MapSignal<T, U> {
15 #[inline(always)]
17 pub fn new(signal: BoxedSignal<T>, map: impl Fn(Ref<T>) -> Ref<U> + 'static) -> Self {
18 Self {
19 signal,
20 map: Rc::new(map),
21 }
22 }
23
24 #[inline(always)]
28 pub fn signal(&self) -> BoxedSignal<T> {
29 self.signal.dyn_clone()
30 }
31
32 #[inline(always)]
34 pub fn get_unmapped(&self) -> Ref<'_, T> {
35 self.signal.get()
36 }
37}
38
39impl<T: 'static, U: 'static> Signal<U> for MapSignal<T, U> {
40 #[inline(always)]
41 fn get(&self) -> Ref<'_, U> {
42 (self.map)(self.get_unmapped())
43 }
44
45 #[inline(always)]
46 fn set_value(&self, _: U) {}
47
48 #[inline(always)]
49 fn listen(self, _: Box<dyn Fn(Ref<'_, U>)>) -> Self
50 where
51 Self: Sized,
52 {
53 self
54 }
55
56 #[inline(always)]
57 fn notify(&self) {
58 self.signal.notify();
59 }
60
61 #[inline(always)]
62 fn dyn_clone(&self) -> Box<dyn Signal<U>> {
63 Box::new(self.clone())
64 }
65}
66
67impl<T: 'static, U: 'static> Clone for MapSignal<T, U> {
68 #[inline(always)]
69 fn clone(&self) -> Self {
70 Self {
71 signal: self.signal.dyn_clone(),
72 map: self.map.clone(),
73 }
74 }
75}
76
77#[cfg(all(test, feature = "test"))]
78mod tests {
79 use crate::reference::Ref;
80 use crate::signal::Signal;
81 use crate::signal::fixed::FixedSignal;
82
83 #[test]
85 fn test_map_signal() {
86 let signal = FixedSignal::new(0)
87 .map(|i| Ref::Owned(i.to_string()))
88 .map(|s| Ref::Owned(s.len()))
89 .map(|len| Ref::Owned(len.to_string()));
90
91 assert_eq!(*signal.get(), "1".to_string());
92 }
93}