maycoon_core/signal/map.rs
1use crate::signal::{ArcSignal, Listener, Ref, Signal};
2
3/// A signal wrapping another signal and applying a mapping function, when the inner value is requested.
4/// The mapping function will be called every time the inner value is requested via [Signal::get].
5/// This signal cannot be directly mutated. Use [MapSignal::signal] to get the inner signal.
6///
7/// Calling [Signal::set], [Signal::set_value], [Signal::listen] or [Signal::notify] has no effect.
8pub struct MapSignal<T, U> {
9 signal: ArcSignal<T>,
10 map: Box<dyn Fn(Ref<T>) -> Ref<U>>,
11}
12
13impl<T: 'static, U> MapSignal<T, U> {
14 /// Create a new map signal using the given inner signal and mapping function.
15 pub fn new(signal: ArcSignal<T>, map: impl Fn(Ref<T>) -> Ref<U> + 'static) -> Self {
16 Self {
17 signal,
18 map: Box::new(map),
19 }
20 }
21
22 /// Get the inner signal.
23 ///
24 /// Can be used to mutate the inner value.
25 pub fn signal(&self) -> ArcSignal<T> {
26 self.signal.clone()
27 }
28
29 /// Get the inner signal's value, without applying the mapping function.
30 pub fn get_unmapped(&self) -> Ref<T> {
31 self.signal.get()
32 }
33}
34
35impl<T: 'static, U: 'static> Signal<U> for MapSignal<T, U> {
36 fn get(&self) -> Ref<U> {
37 (self.map)(self.get_unmapped())
38 }
39
40 fn set_value(&self, _: U) {}
41
42 fn listen(&mut self, _: Listener<U>) {}
43
44 fn notify(&self) {
45 self.signal.notify();
46 }
47}