crux_time/protocol/
instant.rs1use std::time::SystemTime;
2
3use serde::{Deserialize, Serialize};
4
5const NANOS_PER_SEC: u32 = 1_000_000_000;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(rename_all = "camelCase")]
14pub struct Instant {
15 pub(crate) seconds: u64,
16 pub(crate) nanos: u32,
17}
18
19impl Instant {
27 pub fn new(seconds: u64, nanos: u32) -> Self {
28 if nanos >= NANOS_PER_SEC {
29 panic!("nanos must be less than {}", NANOS_PER_SEC);
30 }
31 Self { seconds, nanos }
32 }
33}
34
35impl From<SystemTime> for Instant {
36 fn from(time: SystemTime) -> Self {
37 let duration = time.duration_since(SystemTime::UNIX_EPOCH).unwrap();
38 let seconds = duration.as_secs();
39 let nanos = duration.subsec_nanos();
40 Self { seconds, nanos }
41 }
42}
43
44impl From<Instant> for SystemTime {
45 fn from(time: Instant) -> Self {
46 SystemTime::UNIX_EPOCH + std::time::Duration::new(time.seconds, time.nanos)
47 }
48}
49
50#[cfg(test)]
51mod test {
52 use super::*;
53
54 #[test]
55 fn new_instant() {
56 let instant = Instant::new(1_000_000_000, 10);
57 assert_eq!(instant.seconds, 1_000_000_000);
58 assert_eq!(instant.nanos, 10);
59 }
60
61 #[test]
62 #[should_panic]
63 fn new_instant_invalid_nanos() {
64 Instant::new(1_000_000_000, 1_000_000_000);
65 }
66
67 #[test]
68 fn instant_to_std() {
69 let actual: SystemTime = Instant::new(1_000_000_000, 10).into();
70 let expected = SystemTime::UNIX_EPOCH + std::time::Duration::new(1_000_000_000, 10);
71 assert_eq!(actual, expected);
72 }
73
74 #[test]
75 fn std_to_instant() {
76 let sys_time = SystemTime::UNIX_EPOCH + std::time::Duration::new(1_000_000_000, 10);
77 let actual: Instant = sys_time.into();
78 let expected = Instant::new(1_000_000_000, 10);
79 assert_eq!(actual, expected);
80 }
81}