crux_time/protocol/
duration.rs1use facet::Facet;
2use serde::{Deserialize, Serialize};
3
4const NANOS_PER_SEC: u32 = 1_000_000_000;
6const NANOS_PER_MILLI: u32 = 1_000_000;
8
9#[derive(Facet, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct Duration {
13 pub(crate) nanos: u64,
14}
15
16impl Duration {
17 #[must_use]
19 #[allow(clippy::missing_const_for_fn)]
20 pub fn new(nanos: u64) -> Self {
21 Self { nanos }
22 }
23
24 #[must_use]
29 pub fn from_millis(millis: u64) -> Self {
30 let nanos = millis
31 .checked_mul(u64::from(NANOS_PER_MILLI))
32 .expect("millis overflow");
33 Self { nanos }
34 }
35
36 #[must_use]
41 pub fn from_secs(seconds: u64) -> Self {
42 let nanos = seconds
43 .checked_mul(u64::from(NANOS_PER_SEC))
44 .expect("seconds overflow");
45 Self { nanos }
46 }
47}
48
49impl From<std::time::Duration> for Duration {
50 fn from(duration: std::time::Duration) -> Self {
51 Self {
52 #[allow(clippy::cast_possible_truncation)]
54 nanos: duration.as_nanos() as u64,
55 }
56 }
57}
58
59impl From<Duration> for std::time::Duration {
60 fn from(duration: Duration) -> Self {
61 Self::from_nanos(duration.nanos)
62 }
63}
64
65#[cfg(test)]
66mod test {
67 use super::Duration;
68 use std::time::Duration as StdDuration;
69
70 #[test]
71 fn duration_from_millis() {
72 let duration = Duration::from_millis(1_000);
73 assert_eq!(duration.nanos, 1_000_000_000);
74 }
75
76 #[test]
77 fn duration_from_secs() {
78 let duration = Duration::from_secs(1);
79 assert_eq!(duration.nanos, 1_000_000_000);
80 }
81
82 #[test]
83 fn std_into_duration() {
84 let actual: Duration = StdDuration::from_millis(100).into();
85 let expected = Duration { nanos: 100_000_000 };
86 assert_eq!(actual, expected);
87 }
88
89 #[test]
90 fn duration_into_std() {
91 let actual: StdDuration = Duration { nanos: 100_000_000 }.into();
92 let expected = StdDuration::from_millis(100);
93 assert_eq!(actual, expected);
94 }
95}