Skip to main content

rx_rust/operators/creating/
from_stream.rs

1use crate::utils::types::MaybeSend;
2use crate::{
3    observable::{Observable, Subscription},
4    observer::{Flow, Observer, Termination},
5    scheduler::Scheduler,
6};
7use educe::Educe;
8use futures::Stream;
9use std::convert::Infallible;
10
11/// Converts a `Stream` into an Observable.
12/// See <https://reactivex.io/documentation/operators/from.html>
13///
14/// # Examples
15/// ```rust
16/// # #[cfg(not(feature = "tokio-scheduler"))]
17/// # fn main() {}
18/// # #[cfg(feature = "tokio-scheduler")]
19/// #[tokio::main]
20/// async fn main() {
21///     use futures::stream;
22///     use rx_rust::{
23///         observable::ObservableExt,
24///         observer::Termination,
25///         operators::creating::from_stream::FromStream,
26///     };
27///     use std::sync::{Arc, Mutex};
28///     use tokio::time::{sleep, Duration};
29///
30///     let handle = tokio::runtime::Handle::current();
31///     let values = Arc::new(Mutex::new(Vec::new()));
32///     let terminations = Arc::new(Mutex::new(Vec::new()));
33///     let values_observer = Arc::clone(&values);
34///     let terminations_observer = Arc::clone(&terminations);
35///     let stream = stream::iter([10, 20]);
36///
37///     let subscription = FromStream::new(stream, handle).subscribe_with_callback(
38///         move |value| values_observer.lock().unwrap().push(value),
39///         move |termination| terminations_observer
40///             .lock()
41///             .unwrap()
42///             .push(termination),
43///     );
44///
45///     sleep(Duration::from_millis(10)).await;
46///     drop(subscription);
47///
48///     assert_eq!(&*values.lock().unwrap(), &[10, 20]);
49///     assert_eq!(
50///         &*terminations.lock().unwrap(),
51///         &[Termination::Completed]
52///     );
53/// }
54/// ```
55#[derive(Educe)]
56#[educe(Debug, Clone)]
57pub struct FromStream<SM, S> {
58    stream: SM,
59    scheduler: S,
60}
61
62impl<SM, S> FromStream<SM, S> {
63    pub fn new(stream: SM, scheduler: S) -> Self {
64        Self { stream, scheduler }
65    }
66}
67
68impl<T, SM, S> Observable<'static, T, Infallible> for FromStream<SM, S>
69where
70    SM: Stream<Item = T> + MaybeSend + 'static,
71    S: Scheduler,
72{
73    type D = S::D;
74
75    fn subscribe(
76        self,
77        observer: impl Observer<T, Infallible> + MaybeSend + 'static,
78    ) -> Subscription<Self::D> {
79        let mut observer = Some(observer);
80        self.scheduler
81            .schedule_stream(self.stream, move |result| match result {
82                Some(value) => {
83                    let flow = match observer.as_mut() {
84                        Some(observer) => observer.on_next(value),
85                        None => Flow::Stop,
86                    };
87                    if flow.is_stop() {
88                        // The observer ended its own stream: release it here and tell the
89                        // scheduler to stop polling the stream, so an infinite one is not driven
90                        // for values that have nothing to be delivered to.
91                        drop(observer.take());
92                    }
93                    flow.is_continue()
94                }
95                None => {
96                    if let Some(observer) = observer.take() {
97                        observer.on_termination(Termination::Completed)
98                    }
99                    false
100                }
101            })
102    }
103}