ferroui_base/reactive/
anonymous_observer.rs1use super::anonymous_observer_non_generic_helper::AnonymousObserverNonGenericHelper;
2use super::{IObserver, ObservableError};
3
4pub struct AnonymousObserver<T> {
10 on_next: Box<dyn Fn(T)>,
11 on_error: Box<dyn Fn(ObservableError)>,
12 on_completed: Box<dyn Fn()>,
13}
14
15impl<T> AnonymousObserver<T> {
16 pub fn new(on_next: impl Fn(T) + 'static) -> Self {
17 Self {
18 on_next: Box::new(on_next),
19 on_error: Box::new(AnonymousObserverNonGenericHelper::throws_on_error),
20 on_completed: Box::new(AnonymousObserverNonGenericHelper::no_op_completed),
21 }
22 }
23
24 pub fn new_with_error(on_next: impl Fn(T) + 'static, on_error: impl Fn(ObservableError) + 'static) -> Self {
25 Self::new(on_next).with_error(on_error)
26 }
27
28 pub fn new_with_completed(on_next: impl Fn(T) + 'static, on_completed: impl Fn() + 'static) -> Self {
29 Self::new(on_next).with_completed(on_completed)
30 }
31
32 pub fn new_with_error_and_completed(
33 on_next: impl Fn(T) + 'static,
34 on_error: impl Fn(ObservableError) + 'static,
35 on_completed: impl Fn() + 'static,
36 ) -> Self {
37 Self::new(on_next).with_error(on_error).with_completed(on_completed)
38 }
39
40 pub fn with_error(mut self, on_error: impl Fn(ObservableError) + 'static) -> Self {
41 self.on_error = Box::new(on_error);
42 self
43 }
44
45 pub fn with_completed(mut self, on_completed: impl Fn() + 'static) -> Self {
46 self.on_completed = Box::new(on_completed);
47 self
48 }
49}
50
51impl<T> IObserver<T> for AnonymousObserver<T> {
52 fn on_next(&self, value: T) {
53 (self.on_next)(value)
54 }
55
56 fn on_error(&self, error: ObservableError) {
57 (self.on_error)(error)
58 }
59
60 fn on_completed(&self) {
61 (self.on_completed)()
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
69 use std::cell::Cell;
70 use std::rc::Rc;
71
72 fn error() -> ObservableError {
73 Rc::new(std::fmt::Error)
74 }
75
76 #[test]
77 fn notifications_reach_the_closures() {
78 let next = Rc::new(Cell::new(0));
79 let errors = Rc::new(Cell::new(0));
80 let completed = Rc::new(Cell::new(0));
81 let (n, e, c) = (next.clone(), errors.clone(), completed.clone());
82 let observer = AnonymousObserver::new_with_error_and_completed(
83 move |value: i32| n.set(n.get() + value),
84 move |_| e.set(e.get() + 1),
85 move || c.set(c.get() + 1),
86 );
87
88 observer.on_next(2);
89 observer.on_next(3);
90 observer.on_error(error());
91 observer.on_completed();
92
93 assert_eq!((5, 1, 1), (next.get(), errors.get(), completed.get()));
94 }
95
96 #[test]
97 fn completion_is_ignored_without_a_closure() {
98 AnonymousObserver::new(|_: i32| {}).on_completed();
99 AnonymousObserver::new_with_error(|_: i32| {}, |_| {}).on_completed();
100 }
101
102 #[test]
103 #[should_panic]
104 fn an_error_is_rethrown_without_a_closure() {
105 AnonymousObserver::new_with_completed(|_: i32| {}, || {}).on_error(error());
106 }
107}