Skip to main content

rx_rust/operators/creating/
interval.rs

1use crate::utils::types::MaybeSend;
2use crate::{
3    observable::{Observable, Subscription},
4    observer::Observer,
5    scheduler::Scheduler,
6};
7use educe::Educe;
8use std::{convert::Infallible, time::Duration};
9
10/// Creates an Observable that emits a sequence of integers spaced by a given time interval.
11/// See <https://reactivex.io/documentation/operators/interval.html>
12///
13/// # Examples
14/// ```rust
15/// # #[cfg(not(feature = "tokio-scheduler"))]
16/// # fn main() {}
17/// # #[cfg(feature = "tokio-scheduler")]
18/// #[tokio::main]
19/// async fn main() {
20///     use rx_rust::{
21///         observable::ObservableExt,
22///         observer::Termination,
23///         operators::creating::interval::Interval,
24///     };
25///     use std::sync::{Arc, Mutex};
26///     use std::time::Duration;
27///     use tokio::time::sleep;
28///
29///     let handle = tokio::runtime::Handle::current();
30///     let values = Arc::new(Mutex::new(Vec::new()));
31///     let terminations = Arc::new(Mutex::new(Vec::new()));
32///     let values_observer = Arc::clone(&values);
33///     let terminations_observer = Arc::clone(&terminations);
34///     let subscription = Interval::new(Duration::from_millis(1), handle, None)
35///         .take(3)
36///         .subscribe_with_callback(
37///             move |value| values_observer.lock().unwrap().push(value),
38///             move |termination| terminations_observer
39///                 .lock()
40///                 .unwrap()
41///                 .push(termination),
42///         );
43///
44///     sleep(Duration::from_millis(10)).await;
45///     drop(subscription);
46///
47///     assert_eq!(&*values.lock().unwrap(), &[0, 1, 2]);
48///     assert_eq!(
49///         &*terminations.lock().unwrap(),
50///         &[Termination::Completed]
51///     );
52/// }
53/// ```
54#[derive(Educe)]
55#[educe(Debug, Clone)]
56pub struct Interval<S> {
57    period: Duration,
58    scheduler: S,
59    delay: Option<Duration>,
60}
61
62impl<S> Interval<S> {
63    pub fn new(period: Duration, scheduler: S, delay: Option<Duration>) -> Self {
64        Self {
65            period,
66            scheduler,
67            delay,
68        }
69    }
70}
71
72impl<S> Observable<'static, usize, Infallible> for Interval<S>
73where
74    S: Scheduler + Clone + MaybeSend + 'static,
75{
76    type D = S::D;
77
78    fn subscribe(
79        self,
80        mut observer: impl Observer<usize, Infallible> + MaybeSend + 'static,
81    ) -> Subscription<Self::D> {
82        self.scheduler.schedule_periodically(
83            // The callback's answer is what keeps the schedule running, so an observer that
84            // stopped ends it: nothing is completed, since an interval never completes anyway.
85            move |count| observer.on_next(count).is_continue(),
86            self.period,
87            self.delay,
88        )
89    }
90}