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 {
20 #[must_use]
28 pub fn new(seconds: u64, nanos: u32) -> Self {
29 assert!(
30 nanos < NANOS_PER_SEC,
31 "nanos must be less than {NANOS_PER_SEC}"
32 );
33 Self { seconds, nanos }
34 }
35}
36
37impl From<SystemTime> for Instant {
38 fn from(time: SystemTime) -> Self {
39 let duration = time.duration_since(SystemTime::UNIX_EPOCH).unwrap();
40 let seconds = duration.as_secs();
41 let nanos = duration.subsec_nanos();
42 Self { seconds, nanos }
43 }
44}
45
46impl From<Instant> for SystemTime {
47 fn from(time: Instant) -> Self {
48 SystemTime::UNIX_EPOCH + std::time::Duration::new(time.seconds, time.nanos)
49 }
50}
51
52#[cfg(test)]
53mod test {
54 use super::*;
55
56 #[test]
57 fn new_instant() {
58 let instant = Instant::new(1_000_000_000, 10);
59 assert_eq!(instant.seconds, 1_000_000_000);
60 assert_eq!(instant.nanos, 10);
61 }
62
63 #[test]
64 #[should_panic = "nanos must be less than 1000000000"]
65 fn new_instant_invalid_nanos() {
66 let _ = Instant::new(1_000_000_000, 1_000_000_000);
67 }
68
69 #[test]
70 fn instant_to_std() {
71 let actual: SystemTime = Instant::new(1_000_000_000, 10).into();
72 let expected = SystemTime::UNIX_EPOCH + std::time::Duration::new(1_000_000_000, 10);
73 assert_eq!(actual, expected);
74 }
75
76 #[test]
77 fn std_to_instant() {
78 let sys_time = SystemTime::UNIX_EPOCH + std::time::Duration::new(1_000_000_000, 10);
79 let actual: Instant = sys_time.into();
80 let expected = Instant::new(1_000_000_000, 10);
81 assert_eq!(actual, expected);
82 }
83}