rx_rust/utils/
subscribe_with_auto_dispose_on_termination.rs1use crate::{
2 delegate_disposal,
3 disposable::{Disposable, DisposableExt, shared_disposal::SharedDisposal},
4 observable::Subscription,
5 observer::{Flow, Observer, Termination},
6 utils::on_panic::on_panic,
7};
8use educe::Educe;
9
10delegate_disposal!(
11 Disposal<D>,
12 SharedDisposal<Subscription<D>>,
13 where D: Disposable
14);
15
16pub fn subscribe_with_auto_dispose_on_termination<OR, D, F>(
18 observer: OR,
19 builder: F,
20) -> Subscription<Disposal<D>>
21where
22 D: Disposable,
23 F: FnOnce(AutoDisposeOnTerminationObserver<OR, D>) -> Subscription<D>,
24{
25 let shared_disposal = SharedDisposal::default();
26 let observer = AutoDisposeOnTerminationObserver {
27 observer,
28 shared_disposal: shared_disposal.clone(),
29 };
30 shared_disposal.replace(|| builder(observer));
31
32 shared_disposal.into_subscription()
33}
34
35pub(crate) fn is_auto_dispose_on_termination_observer<OR>() -> bool {
41 fn type_name_without_generics<T>() -> &'static str {
42 let name = std::any::type_name::<T>();
43 name.split_once('<').map_or(name, |(name, _)| name)
44 }
45
46 type_name_without_generics::<OR>()
47 == type_name_without_generics::<AutoDisposeOnTerminationObserver<(), ()>>()
48}
49
50#[derive(Educe)]
51#[educe(Debug)]
52pub struct AutoDisposeOnTerminationObserver<OR, D: Disposable> {
53 observer: OR,
54 shared_disposal: SharedDisposal<Subscription<D>>,
55}
56
57impl<T, E, OR, D> Observer<T, E> for AutoDisposeOnTerminationObserver<OR, D>
58where
59 OR: Observer<T, E>,
60 D: Disposable,
61{
62 fn on_next(&mut self, value: T) -> Flow {
63 let flow = self.observer.on_next(value);
64 if flow.is_stop() {
65 self.shared_disposal.clone().dispose();
69 }
70 flow
71 }
72
73 fn on_termination(self, termination: Termination<E>) {
74 let Self {
75 observer,
76 shared_disposal,
77 } = self;
78 let guard = on_panic(|| shared_disposal.clone().dispose());
83 observer.on_termination(termination);
84 drop(guard);
85 shared_disposal.dispose();
86 }
87}