sequoia_async/
signal_ext.rs1#![forbid(unsafe_code)]
2
3use futures_core::Future;
4
5use sequoia_reactive::Signal;
6
7pub trait SignalAsyncExt<T: Clone + PartialEq + Send + 'static> {
8 fn async_setter(&self) -> impl Fn(T) + Clone + 'static
9 where
10 Self: Clone;
11}
12
13impl<T: Clone + PartialEq + Send + 'static> SignalAsyncExt<T> for Signal<T> {
14 fn async_setter(&self) -> impl Fn(T) + Clone + 'static
15 where
16 Self: Clone,
17 {
18 let signal = self.clone();
19 move |value: T| signal.set(value)
20 }
21}
22
23pub fn pipe_to_signal<T>(signal: &Signal<T>) -> impl FnOnce(T) + 'static
24where
25 T: Clone + PartialEq + Send + 'static,
26{
27 let signal = signal.clone();
28 move |value: T| signal.set(value)
29}
30
31pub fn pipe_result_to_signal<T, E>(
32 signal: &Signal<T>,
33 on_error: impl FnOnce(E) + 'static,
34) -> impl FnOnce(Result<T, E>) + 'static
35where
36 T: Clone + PartialEq + Send + 'static,
37 E: Send + 'static,
38{
39 let signal = signal.clone();
40 move |result: Result<T, E>| match result {
41 Ok(v) => signal.set(v),
42 Err(e) => on_error(e),
43 }
44}
45
46#[allow(dead_code)]
47pub(crate) fn assert_ui_future<T: Send, F: Future<Output = T>>(_: &F) {}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn pipe_writes_to_signal() {
55 let s = Signal::new(0u32);
56 let apply = pipe_to_signal(&s);
57 apply(5);
58 assert_eq!(s.get_untracked(), 5);
59 }
60
61 #[test]
62 fn pipe_result_routes_ok_and_err() {
63 let s = Signal::new(0u32);
64 let apply = pipe_result_to_signal(&s, |e: String| assert_eq!(e, "boom"));
65 apply(Ok(3));
66 assert_eq!(s.get_untracked(), 3);
67 let s2 = Signal::new(0u32);
68 let apply2 = pipe_result_to_signal(&s2, |e: String| assert_eq!(e, "boom"));
69 apply2(Err("boom".to_string()));
70 assert_eq!(s2.get_untracked(), 0);
71 }
72}