Skip to main content

rx_rust/operators/utility/
timestamp.rs

1use crate::{
2    observable::Observable,
3    observable::Subscription,
4    observer::{Flow, Observer, Termination},
5    utils::types::MaybeSend,
6};
7use educe::Educe;
8use std::time::Instant;
9
10/// Attaches a timestamp to each item emitted by an Observable.
11/// See <https://reactivex.io/documentation/operators/timestamp.html>
12///
13/// # Examples
14/// ```rust
15/// use rx_rust::{
16///     observable::ObservableExt,
17///     observer::{Observer, Termination},
18///     operators::utility::timestamp::Timestamp,
19///     subject::publish_subject::PublishSubject,
20/// };
21/// use std::{convert::Infallible, time::{Duration, Instant}};
22///
23/// let mut timestamped = Vec::new();
24/// let mut terminations = Vec::new();
25/// let mut subject: PublishSubject<'_, i32, Infallible> = PublishSubject::default();
26/// let start = Instant::now();
27///
28/// let subscription = Timestamp::new(subject.clone()).subscribe_with_callback(
29///     |(value, instant)| timestamped.push((value, instant)),
30///     |termination| terminations.push(termination),
31/// );
32///
33/// subject.on_next(1);
34/// subject.on_next(2);
35/// subject.on_termination(Termination::Completed);
36/// drop(subscription);
37///
38/// assert_eq!(
39///     timestamped.iter().map(|(value, _)| *value).collect::<Vec<_>>(),
40///     vec![1, 2]
41/// );
42/// assert!(timestamped[0].1.duration_since(start) >= Duration::from_millis(0));
43/// assert!(timestamped[1].1.duration_since(timestamped[0].1) >= Duration::from_millis(0));
44/// assert_eq!(terminations, vec![Termination::Completed]);
45/// ```
46#[derive(Educe)]
47#[educe(Debug, Clone)]
48pub struct Timestamp<OE> {
49    source: OE,
50}
51
52impl<OE> Timestamp<OE> {
53    pub fn new(source: OE) -> Self {
54        Self { source }
55    }
56}
57
58impl<'or, T, E, OE> Observable<'or, (T, Instant), E> for Timestamp<OE>
59where
60    OE: Observable<'or, T, E>,
61{
62    type D = OE::D;
63
64    fn subscribe(
65        self,
66        observer: impl Observer<(T, Instant), E> + MaybeSend + 'or,
67    ) -> Subscription<Self::D> {
68        let observer = TimestampObserver { observer };
69        self.source.subscribe(observer)
70    }
71}
72
73struct TimestampObserver<OR> {
74    observer: OR,
75}
76
77impl<T, E, OR> Observer<T, E> for TimestampObserver<OR>
78where
79    OR: Observer<(T, Instant), E>,
80{
81    fn on_next(&mut self, value: T) -> Flow {
82        self.observer.on_next((value, Instant::now()))
83    }
84
85    fn on_termination(self, termination: Termination<E>) {
86        self.observer.on_termination(termination);
87    }
88}