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 pub fn new(nanos: u64) -> Self {
20 Self { nanos }
21 }
22
23 #[must_use]
28 pub fn from_millis(millis: u64) -> Self {
29 let nanos = millis
30 .checked_mul(u64::from(NANOS_PER_MILLI))
31 .expect("millis overflow");
32 Self { nanos }
33 }
34
35 #[must_use]
40 pub fn from_secs(seconds: u64) -> Self {
41 let nanos = seconds
42 .checked_mul(u64::from(NANOS_PER_SEC))
43 .expect("seconds overflow");
44 Self { nanos }
45 }
46}
47
48impl From<std::time::Duration> for Duration {
49 fn from(duration: std::time::Duration) -> Self {
50 Duration {
51 #[allow(clippy::cast_possible_truncation)]
53 nanos: duration.as_nanos() as u64,
54 }
55 }
56}
57
58impl From<Duration> for std::time::Duration {
59 fn from(duration: Duration) -> Self {
60 std::time::Duration::from_nanos(duration.nanos)
61 }
62}
63
64#[cfg(test)]
65mod test {
66 use super::Duration;
67 use std::time::Duration as StdDuration;
68
69 #[test]
70 fn duration_from_millis() {
71 let duration = Duration::from_millis(1_000);
72 assert_eq!(duration.nanos, 1_000_000_000);
73 }
74
75 #[test]
76 fn duration_from_secs() {
77 let duration = Duration::from_secs(1);
78 assert_eq!(duration.nanos, 1_000_000_000);
79 }
80
81 #[test]
82 fn std_into_duration() {
83 let actual: Duration = StdDuration::from_millis(100).into();
84 let expected = Duration { nanos: 100_000_000 };
85 assert_eq!(actual, expected);
86 }
87
88 #[test]
89 fn duration_into_std() {
90 let actual: StdDuration = Duration { nanos: 100_000_000 }.into();
91 let expected = StdDuration::from_millis(100);
92 assert_eq!(actual, expected);
93 }
94}