rx_rust/operators/utility/do_before_termination.rs
1use crate::utils::types::MaybeSend;
2use crate::{
3 observable::Observable,
4 observable::Subscription,
5 observer::{Flow, Observer, Termination},
6};
7use educe::Educe;
8
9/// Invokes a callback when the source Observable terminates (either completes or errors), before the termination notification has been emitted to the downstream observer.
10/// See <https://reactivex.io/documentation/operators/do.html>
11///
12/// # Examples
13/// ```rust
14/// use rx_rust::{
15/// observable::ObservableExt,
16/// observer::Termination,
17/// operators::{
18/// creating::from_iter::FromIter,
19/// utility::do_before_termination::DoBeforeTermination,
20/// },
21/// };
22/// use std::sync::{Arc, Mutex};
23///
24/// let mut terminations = Vec::new();
25/// let callback_terminations = Arc::new(Mutex::new(Vec::new()));
26/// let callback_terminations_observer = Arc::clone(&callback_terminations);
27///
28/// DoBeforeTermination::new(FromIter::new(vec![1, 2]), move |termination| {
29/// callback_terminations_observer
30/// .lock()
31/// .unwrap()
32/// .push(termination.clone());
33/// })
34/// .subscribe_with_callback(
35/// |_| {},
36/// |termination| terminations.push(termination),
37/// );
38///
39/// assert_eq!(
40/// &*callback_terminations.lock().unwrap(),
41/// &[Termination::Completed]
42/// );
43/// assert_eq!(terminations, vec![Termination::Completed]);
44/// ```
45#[derive(Educe)]
46#[educe(Debug, Clone)]
47pub struct DoBeforeTermination<OE, F> {
48 source: OE,
49 callback: F,
50}
51
52impl<OE, F> DoBeforeTermination<OE, F> {
53 pub fn new<'or, T, E>(source: OE, callback: F) -> Self
54 where
55 OE: Observable<'or, T, E>,
56 F: FnOnce(&Termination<E>),
57 {
58 Self { source, callback }
59 }
60}
61
62impl<'or, T, E, OE, F> Observable<'or, T, E> for DoBeforeTermination<OE, F>
63where
64 T: 'or,
65 E: 'or,
66 OE: Observable<'or, T, E>,
67 F: FnOnce(&Termination<E>) + MaybeSend + 'or,
68{
69 type D = OE::D;
70
71 fn subscribe(self, observer: impl Observer<T, E> + MaybeSend + 'or) -> Subscription<Self::D> {
72 self.source.subscribe(DoBeforeTerminationObserver {
73 observer,
74 callback: self.callback,
75 })
76 }
77}
78
79struct DoBeforeTerminationObserver<OR, F> {
80 observer: OR,
81 callback: F,
82}
83
84impl<T, E, OR, F> Observer<T, E> for DoBeforeTerminationObserver<OR, F>
85where
86 OR: Observer<T, E>,
87 F: FnOnce(&Termination<E>),
88{
89 fn on_next(&mut self, value: T) -> Flow {
90 self.observer.on_next(value)
91 }
92
93 fn on_termination(self, termination: Termination<E>) {
94 (self.callback)(&termination);
95 self.observer.on_termination(termination);
96 }
97}