monotime/
lib.rs

1use bytes::BufMut;
2use bytes::Bytes;
3use bytes::BytesMut;
4use error::MonotimeError;
5use serde::Deserialize;
6use serde::Serialize;
7use std::time::{SystemTime, UNIX_EPOCH};
8
9pub mod error;
10
11#[derive(
12    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
13)]
14pub struct MonoTime(u128); // nanos << 48 | seq << 32 | node << 16 | 0*16
15
16pub enum TimeResult {
17    Time(MonoTime),
18    Drift(MonoTime, u128),
19}
20
21impl TimeResult {
22    pub fn into_time(self) -> MonoTime {
23        match self {
24            TimeResult::Time(time) => time,
25            TimeResult::Drift(time, _) => time,
26        }
27    }
28
29    pub fn get_time(&self) -> &MonoTime {
30        match self {
31            TimeResult::Time(time) => time,
32            TimeResult::Drift(time, _) => time,
33        }
34    }
35
36    pub fn get_drift(&self) -> Option<u128> {
37        match self {
38            TimeResult::Time(_) => None,
39            TimeResult::Drift(_, drift) => Some(*drift),
40        }
41    }
42}
43
44impl MonoTime {
45    pub fn new(seq: u16, node: u16) -> Self {
46        let nanos = SystemTime::now()
47            .duration_since(UNIX_EPOCH)
48            .unwrap() // This must fail if the system clock is before the UNIX_EPOCH
49            .as_nanos();
50        let time_stamp = nanos << 48 | (seq as u128) << 32 | (node as u128) << 16;
51        assert!(time_stamp.trailing_zeros() >= 16);
52        MonoTime(time_stamp)
53    }
54
55    pub fn get_inner(&self) -> u128 {
56        self.0
57    }
58
59    pub fn get_nanos(&self) -> u128 {
60        self.0 >> 48
61    }
62
63    pub fn get_node(&self) -> u16 {
64        (self.0 << 96 >> 112) as u16 // Shift out nanos and seq, then shift back to get node
65    }
66
67    pub fn get_seq(&self) -> u16 {
68        (self.0 << 80 >> 112) as u16 // Shift out nanos, then shift back to get seq
69    }
70
71    pub fn next(self) -> TimeResult {
72        let nanos = SystemTime::now()
73            .duration_since(UNIX_EPOCH)
74            .unwrap() // This must fail if the system clock is before the UNIX_EPOCH
75            .as_nanos()
76            << 48;
77
78        let seq = (self.get_seq().wrapping_add(1) as u128) << 32; // Shift out the nanos than add 1 to seq
79        let node = (self.get_node() as u128) << 16;
80        if self.0 > nanos {
81            let drift = (self.0 - nanos) >> 48 << 48; // Shift out the seq and node first right than back left
82            if drift != 0 {
83                // Shift out the seq and node than add 1 to nanos
84                // shift back and add new seq and node back
85                let next_time = ((self.0 >> 48) + 1) << 48 | seq | node;
86                return TimeResult::Drift(MonoTime(next_time), drift);
87            }
88        }
89        TimeResult::Time(MonoTime(nanos | seq | node)) // And nanos and increased seq
90    }
91
92    pub fn next_with_node(self, node: u16) -> TimeResult {
93        let nanos = SystemTime::now()
94            .duration_since(UNIX_EPOCH)
95            .unwrap() // This must fail if the system clock is before the UNIX_EPOCH
96            .as_nanos()
97            << 48;
98
99        let seq = (self.get_seq().wrapping_add(1) as u128) << 32; // Shift out the nanos than add 1 to seq
100        let node = (node as u128) << 16;
101        if self.0 > nanos {
102            let drift = (self.0 - nanos) >> 48 << 48; // Shift out the seq and node first right than back left
103            if drift != 0 {
104                // Shift out the seq and node than add 1 to nanos
105                // shift back and add new seq and node back
106                let next_time = ((self.0 >> 48) + 1) << 48 | seq | node;
107                return TimeResult::Drift(MonoTime(next_time), drift);
108            }
109        }
110        TimeResult::Time(MonoTime(nanos | seq | node)) // And nanos and increased seq
111    }
112
113    // Ensures that the time is greater than self and greater than guard
114    pub fn next_with_guard(self, guard: &MonoTime) -> TimeResult {
115        let time = self.next().into_time();
116        if &time < guard {
117            let drift = guard.get_nanos() - time.get_nanos();
118            let seq_node = (time.0 << 80 >> 80) + (1 << 32); // Shift out the nanos than add 1 to seq
119            let next_time = MonoTime((guard.get_nanos() + 1) << 48 | seq_node);
120            TimeResult::Drift(next_time, drift)
121        } else {
122            TimeResult::Time(time)
123        }
124    }
125
126    pub fn next_with_guard_and_node(self, guard: &MonoTime, node: u16) -> TimeResult {
127        let time = self.next_with_node(node).into_time();
128        if &time < guard {
129            let drift = guard.get_nanos() - time.get_nanos();
130            let seq = (time.get_seq() as u128) << 32;
131            let node = (time.get_node() as u128) << 16;
132            let next_time = MonoTime((guard.get_nanos() + 1) << 48 | seq | node);
133            TimeResult::Drift(next_time, drift)
134        } else {
135            TimeResult::Time(time)
136        }
137    }
138
139    #[cfg(feature = "unsafe_time")]
140    pub fn new_with_time(nanos: u128, seq: u16, node: u16) -> Self {
141        let time_stamp = nanos << 48 | (seq as u128) << 32 | (node as u128) << 16;
142        assert!(time_stamp.trailing_zeros() >= 16);
143        MonoTime(time_stamp)
144    }
145}
146
147impl From<u128> for MonoTime {
148    fn from(val: u128) -> Self {
149        MonoTime(val)
150    }
151}
152
153impl From<MonoTime> for u128 {
154    fn from(val: MonoTime) -> Self {
155        val.0
156    }
157}
158
159impl From<MonoTime> for [u8; 16] {
160    fn from(val: MonoTime) -> Self {
161        let mut bytes = [0u8; 16];
162        bytes.copy_from_slice(&val.0.to_be_bytes());
163        bytes
164    }
165}
166
167impl From<MonoTime> for Vec<u8> {
168    fn from(val: MonoTime) -> Self {
169        val.0.to_be_bytes().to_vec()
170    }
171}
172
173impl TryFrom<&[u8]> for MonoTime {
174    type Error = MonotimeError;
175
176    fn try_from(value: &[u8]) -> Result<Self, MonotimeError> {
177        if value.len() != 16 {
178            return Err(MonotimeError::InvalidLength);
179        }
180        let ts = u128::from_be_bytes(value[0..16].try_into()?);
181        Ok(MonoTime(ts))
182    }
183}
184
185impl From<MonoTime> for Bytes {
186    fn from(value: MonoTime) -> Self {
187        let mut bytes = BytesMut::with_capacity(16);
188        bytes.put_u128(value.0);
189        bytes.freeze()
190    }
191}
192
193#[cfg(test)]
194mod tests {
195    use super::*;
196    use std::convert::TryInto;
197
198    #[test]
199    fn test_roundtrip() {
200        let time = MonoTime::new(0, 0);
201        let bytes: [u8; 16] = time.into();
202        let time2: MonoTime = bytes.as_ref().try_into().unwrap();
203        assert_eq!(time.get_nanos(), time2.get_nanos());
204        assert_eq!(time.get_seq(), time2.get_seq());
205        assert_eq!(time.get_node(), time2.get_node());
206    }
207
208    #[test]
209    fn test_next() {
210        let time = MonoTime::new(0, 0);
211        let time2 = time.next().into_time();
212        assert!(time.get_nanos() <= time2.get_nanos());
213        assert_eq!(time.get_seq() + 1, time2.get_seq());
214        assert_eq!(time.get_node(), time2.get_node());
215    }
216
217    #[test]
218    fn test_time_backwards() {
219        let time = MonoTime::new(0, 0);
220        let time2 = MonoTime(
221            (time.get_nanos() + 100000000) << 48
222                | (time.get_seq() as u128) << 32
223                | (time.get_node() as u128) << 16,
224        );
225        assert!(time2.next().get_drift().is_some());
226    }
227
228    #[test]
229    fn test_compare() {
230        for _ in 0..100000 {
231            let time = MonoTime::new(0, 0);
232            let time2 = MonoTime::new(0, 0);
233            assert!(time < time2);
234        }
235        let time = MonoTime::new(0, 0);
236        assert_eq!(
237            time,
238            MonoTime(
239                (time.get_nanos()) << 48
240                    | (time.get_seq() as u128) << 32
241                    | (time.get_node() as u128) << 16
242            )
243        );
244        assert!(
245            time < MonoTime(
246                (time.get_nanos() + 1) << 48
247                    | (time.get_seq() as u128) << 32
248                    | (time.get_node() as u128) << 16
249            )
250        );
251        assert!(
252            time < MonoTime(
253                time.get_nanos() << 48
254                    | (time.get_seq() as u128 + 1) << 32
255                    | (time.get_node() as u128) << 16
256            )
257        );
258        assert!(
259            time < MonoTime(
260                time.get_nanos() << 48
261                    | (time.get_seq() as u128 + 1) << 32
262                    | (time.get_node() as u128 + 1) << 16
263            )
264        );
265    }
266}