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