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