rx_rust/operators/connectable/connectable_controller.rs
1use super::ref_count::RefCount;
2use crate::disposable::Disposable;
3use crate::observable::{Observable, Subscription};
4use crate::observer::Observer;
5use crate::subject::subject_observable::SubjectObservable;
6use crate::utils::types::MaybeSend;
7use educe::Educe;
8
9/// Marker for a connectable controller that is not connected to its source.
10#[derive(Debug, Clone, Copy, Default)]
11pub struct Disconnected;
12
13/// State carried by a connected controller. Dropping it disconnects the source.
14#[derive(Educe)]
15#[educe(Debug)]
16pub struct Connected<D: Disposable>(Subscription<D>);
17
18/// Multicasts a source `Observable` through a `Subject`, but waits until its [`connect`](ConnectableController::connect)
19/// method is called before subscribing to the source and emitting items to its observers.
20/// Subscribe to the multicast output through [`observable`](ConnectableController::observable).
21/// See <https://reactivex.io/documentation/operators/connect.html>
22///
23/// # Examples
24/// ```rust
25/// use rx_rust::{
26/// observable::ObservableExt,
27/// observer::Termination,
28/// operators::{
29/// connectable::connectable_controller::ConnectableController,
30/// creating::from_iter::FromIter,
31/// },
32/// subject::publish_subject::PublishSubject,
33/// };
34///
35/// use std::{convert::Infallible, sync::{Arc, Mutex}};
36///
37/// let values_1 = Arc::new(Mutex::new(Vec::new()));
38/// let values_2 = Arc::new(Mutex::new(Vec::new()));
39/// let terminations = Arc::new(Mutex::new(Vec::new()));
40///
41/// let subject: PublishSubject<'_, i32, Infallible> = PublishSubject::default();
42/// let controller = ConnectableController::new(FromIter::new(vec![1, 2]), subject);
43/// let observable = controller.observable();
44/// let values_1_observer = Arc::clone(&values_1);
45/// let values_2_observer = Arc::clone(&values_2);
46/// let terminations_observer = Arc::clone(&terminations);
47///
48/// let subscription_1 = observable.clone().subscribe_with_callback(
49/// move |value| values_1_observer.lock().unwrap().push(value),
50/// |_| {},
51/// );
52/// let subscription_2 = observable.subscribe_with_callback(
53/// move |value| values_2_observer.lock().unwrap().push(value),
54/// move |termination| terminations_observer
55/// .lock()
56/// .unwrap()
57/// .push(termination),
58/// );
59///
60/// // Nothing is emitted until the source is connected.
61/// let connected = controller.connect();
62/// // Dropping the connected controller disconnects the source.
63/// drop(connected);
64/// drop(subscription_1);
65/// drop(subscription_2);
66///
67/// assert_eq!(&*values_1.lock().unwrap(), &[1, 2]);
68/// assert_eq!(&*values_2.lock().unwrap(), &[1, 2]);
69/// assert_eq!(
70/// &*terminations.lock().unwrap(),
71/// &[Termination::Completed]
72/// );
73/// ```
74#[derive(Educe)]
75#[educe(Debug)]
76pub struct ConnectableController<OE, S, State = Disconnected> {
77 source: OE,
78 subject: S,
79 state: State,
80}
81
82impl<OE, S> ConnectableController<OE, S, Disconnected> {
83 pub fn new(source: OE, subject: S) -> Self {
84 Self {
85 source,
86 subject,
87 state: Disconnected,
88 }
89 }
90
91 /// Connects to the source. The returned controller owns the connection and
92 /// disconnects it when dropped.
93 ///
94 /// Ignoring the returned controller would disconnect at the end of the
95 /// statement, so the compiler warns about it:
96 ///
97 /// ```compile_fail
98 /// #![deny(unused_must_use)]
99 /// use rx_rust::{
100 /// observable::ObservableExt,
101 /// operators::creating::from_iter::FromIter,
102 /// };
103 ///
104 /// FromIter::new([1_i32]).publish().connect();
105 /// ```
106 #[must_use = "the returned controller owns the source connection"]
107 pub fn connect<'or, T, E>(self) -> ConnectableController<OE, S, Connected<OE::D>>
108 where
109 OE: Observable<'or, T, E> + Clone,
110 S: Observer<T, E> + Clone + MaybeSend + 'or,
111 {
112 let sub = self.source.clone().subscribe(self.subject.clone());
113 ConnectableController {
114 source: self.source,
115 subject: self.subject,
116 state: Connected(sub),
117 }
118 }
119
120 pub fn ref_count<'or, T, E>(self) -> RefCount<'or, T, E, OE, S>
121 where
122 OE: Observable<'or, T, E>,
123 S: Clone,
124 {
125 RefCount::new(self)
126 }
127}
128
129impl<OE, S, D> ConnectableController<OE, S, Connected<D>>
130where
131 D: Disposable,
132{
133 /// Disconnects the source and returns the controller in its disconnected state.
134 pub fn disconnect(self) -> ConnectableController<OE, S, Disconnected> {
135 let Self {
136 source,
137 subject,
138 state,
139 } = self;
140 drop(state);
141 ConnectableController {
142 source,
143 subject,
144 state: Disconnected,
145 }
146 }
147}
148
149impl<OE, S, State> ConnectableController<OE, S, State> {
150 pub fn observable(&self) -> SubjectObservable<S>
151 where
152 S: Clone,
153 {
154 SubjectObservable::new(self.subject.clone())
155 }
156}