indicator/window/
tick_value.rs

1use core::borrow::Borrow;
2use core::ops::Deref;
3
4use super::tick::Tick;
5use super::tickable::Tickable;
6use time::OffsetDateTime;
7
8/// Value with timestamp.
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct TickValue<T> {
12    /// Tick.
13    pub tick: Tick,
14    /// Value.
15    pub value: T,
16}
17
18impl<T> TickValue<T> {
19    /// Create a new [`TickValue`] with the given `value`
20    /// and the `BIG_BANG` tick.
21    pub fn big_bang(value: T) -> Self {
22        Self {
23            tick: Tick::BIG_BANG,
24            value,
25        }
26    }
27
28    /// Create a new [`TickValue`] from `ts` and `value`.
29    pub fn new(ts: OffsetDateTime, value: T) -> Self {
30        Self {
31            tick: Tick::new(ts),
32            value,
33        }
34    }
35
36    /// Map over the tick value.
37    pub fn map<U, F>(self, f: F) -> TickValue<U>
38    where
39        F: FnOnce(T) -> U,
40    {
41        TickValue {
42            tick: self.tick,
43            value: (f)(self.value),
44        }
45    }
46}
47
48impl<T> Tickable for TickValue<T> {
49    type Value = T;
50
51    fn tick(&self) -> Tick {
52        self.tick
53    }
54
55    fn value(&self) -> &Self::Value {
56        &self.value
57    }
58
59    fn into_tick_value(self) -> TickValue<Self::Value> {
60        self
61    }
62}
63
64impl<T> core::fmt::Display for TickValue<T>
65where
66    T: core::fmt::Display,
67{
68    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
69        if let Some(ts) = self.tick.ts() {
70            write!(f, "({ts}, {})", self.value)
71        } else {
72            write!(f, "(*, {})", self.value)
73        }
74    }
75}
76
77impl<T> Deref for TickValue<T> {
78    type Target = T;
79
80    fn deref(&self) -> &Self::Target {
81        &self.value
82    }
83}
84
85impl<T> Borrow<T> for TickValue<T> {
86    fn borrow(&self) -> &T {
87        &self.value
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_tick_value() {
97        let tick_value = TickValue::new(OffsetDateTime::UNIX_EPOCH, 42);
98        assert_eq!(tick_value.tick(), Tick::new(OffsetDateTime::UNIX_EPOCH));
99        assert_eq!(tick_value.value(), &42);
100        assert_eq!(tick_value.into_tick_value(), tick_value);
101    }
102
103    #[cfg(feature = "serde")]
104    #[test]
105    fn serialize_tick_value() {
106        use time::macros::datetime;
107
108        let tick_value = TickValue::new(datetime!(2021-01-01 00:00:00 UTC), 42);
109        let json = serde_json::to_string(&tick_value).unwrap();
110        assert_eq!(json, r#"{"tick":"2021-01-01T00:00:00Z","value":42}"#);
111    }
112
113    #[cfg(feature = "serde")]
114    #[test]
115    fn deserialize_tick_value() {
116        use time::macros::datetime;
117
118        let json = r#"{"tick":"2021-01-01T00:00:00Z","value":42}"#;
119        let tick_value: TickValue<i32> = serde_json::from_str(json).unwrap();
120        assert_eq!(
121            tick_value.tick(),
122            Tick::new(datetime!(2021-01-01 00:00:00 UTC))
123        );
124        assert_eq!(tick_value.value(), &42);
125    }
126}