kekbit_core/tick.rs
1//! Time granularity units used in kekbit.
2use std::time::Duration;
3use std::time::{SystemTime, UNIX_EPOCH};
4
5///A TickUnit represents a specific time duration but does not maintain time information, it only helps define the time granularity
6///required to used in various contexts by all kekbit components which *share a given channel*.
7///For each channel it's TickUnit will be spcified at creation and will *never be changed*
8#[derive(PartialEq, Eq, Debug, Copy, Clone)]
9pub enum TickUnit {
10 ///TickUnit representing one thousandth of a microsecond.
11 Nanos,
12 ///TickUnit representing one thousandth of a millisecond.
13 Micros,
14 ///TickUnit representing one thousandth of a second.
15 Millis,
16 ///TickUnit representing one second.
17 Secs,
18}
19
20impl TickUnit {
21 ///Returns the unique u8 id assigned to every TickUnit. This id it's used for serialization it would never change.
22 ///
23 /// # Examples
24 /// ```
25 /// use kekbit_core::tick::TickUnit::*;
26 ///
27 /// assert_eq!(Nanos.id(), 9);
28 /// assert_eq!(Micros.id(), 6);
29 /// assert_eq!(Millis.id(), 3);
30 /// assert_eq!(Secs.id(), 0);
31 /// ```
32 #[inline]
33 pub fn id(self) -> u8 {
34 match self {
35 TickUnit::Nanos => 9,
36 TickUnit::Micros => 6,
37 TickUnit::Millis => 3,
38 TickUnit::Secs => 0,
39 }
40 }
41
42 /// Returns the tick unit with the given id
43 ///
44 /// # Arguments
45 ///
46 /// * `id` - The identifier of the tick unit as u8. In the curent kekbit version it must be **0, 3, 6 or 9**
47 ///
48 /// # Panics
49 ///
50 /// If the specified id has no tick unit attached
51 ///
52 #[inline]
53 pub fn from_id(id: u8) -> TickUnit {
54 match id {
55 9 => TickUnit::Nanos,
56 6 => TickUnit::Micros,
57 3 => TickUnit::Millis,
58 0 => TickUnit::Secs,
59 _ => panic!("Unknown time unit id {}", id),
60 }
61 }
62 /// Returns the total number of tick units contained by this `Duration` as a u64.
63 /// If the tiemstamp size is longer than 64 bits, it will be truncated to the lower 64 bits
64 ///
65 /// # Examples
66 ///
67 /// ```
68 /// use std::time::Duration;
69 /// use kekbit_core::tick::TickUnit::*;
70 ///
71 ///let duration = Duration::new(1, 500_000_000); //1 sec and a half
72 ///assert_eq!(Nanos.convert(duration), 1_500_000_000);
73 ///assert_eq!(Micros.convert(duration), 1_500_000);
74 ///assert_eq!(Millis.convert(duration), 1_500);
75 ///assert_eq!(Secs.convert(duration), 1);
76 /// ```
77 #[inline]
78 pub fn convert(self, duration: Duration) -> u64 {
79 match self {
80 TickUnit::Nanos => duration.as_nanos() as u64,
81 TickUnit::Micros => duration.as_micros() as u64,
82 TickUnit::Millis => duration.as_millis() as u64,
83 TickUnit::Secs => duration.as_secs(),
84 }
85 }
86 ///Returns the difference, measured in the current tick unit, between the current time and midnight, January 1, 1970 UTC.
87 ///
88 /// # Examples
89 /// ```
90 /// use kekbit_core::tick::TickUnit::*;
91 ///
92 /// println!("{}ms since January 1, 1970 UTC", Millis.nix_time());
93 /// ```
94 #[inline]
95 pub fn nix_time(self) -> u64 {
96 self.convert(SystemTime::now().duration_since(UNIX_EPOCH).unwrap())
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::TickUnit::*;
103 use super::*;
104 use std::time::Duration;
105 #[test]
106 fn check_ids_symetry() {
107 assert_eq!(Nanos.id(), TickUnit::from_id(Nanos.id()).id());
108 assert_eq!(Micros.id(), TickUnit::from_id(Micros.id()).id());
109 assert_eq!(Millis.id(), TickUnit::from_id(Millis.id()).id());
110 assert_eq!(Secs.id(), TickUnit::from_id(Secs.id()).id());
111 }
112
113 #[test]
114 #[should_panic]
115 fn check_wrong_id() {
116 TickUnit::from_id(123);
117 }
118
119 #[test]
120 fn test_coversion() {
121 let duration = Duration::new(1, 500_000_000); //1 sec and a half
122 assert_eq!(Nanos.convert(duration), 1_500_000_000);
123 assert_eq!(Micros.convert(duration), 1_500_000);
124 assert_eq!(Millis.convert(duration), 1_500);
125 assert_eq!(Secs.convert(duration), 1);
126 }
127
128 #[test]
129 fn check_ids() {
130 assert_eq!(Nanos.id(), 9);
131 assert_eq!(Micros.id(), 6);
132 assert_eq!(Millis.id(), 3);
133 assert_eq!(Secs.id(), 0);
134 }
135
136 #[test]
137 fn check_nix_time() {
138 let t1 = Nanos.nix_time();
139 let t2 = Nanos.nix_time();
140 assert!(t1 <= t2);
141 }
142}