1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
pub mod duration_millis {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::time::Duration;
pub fn serialize<S>(value: &Duration, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
to_millis(value).serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where
D: Deserializer<'de>,
{
u64::deserialize(deserializer).map(from_millis)
}
pub(crate) fn to_millis(duration: &Duration) -> u64 {
duration.as_secs() * 1000 + u64::from(duration.subsec_millis())
}
pub(crate) fn from_millis(millis: u64) -> Duration {
Duration::from_millis(millis)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn to_millis_works() {
assert_eq!(0, duration_millis::to_millis(&Duration::from_millis(0)));
assert_eq!(10, duration_millis::to_millis(&Duration::from_millis(10)));
assert_eq!(999, duration_millis::to_millis(&Duration::from_millis(999)));
assert_eq!(0, duration_millis::to_millis(&Duration::from_nanos(3000)));
assert_eq!(
0,
duration_millis::to_millis(&Duration::from_nanos(999_999))
);
assert_eq!(
1,
duration_millis::to_millis(&Duration::from_nanos(1_000_000))
);
assert_eq!(
1,
duration_millis::to_millis(&Duration::from_nanos(1_000_001))
);
assert_eq!(1000, duration_millis::to_millis(&Duration::from_secs(1)));
}
#[derive(PartialEq, Debug, Serialize, Deserialize)]
struct TestStruct {
#[serde(with = "duration_millis")]
pub duration: Duration,
#[serde(default = "default_duration", with = "duration_millis")]
pub default_duration: Duration,
}
fn default_duration() -> Duration {
Duration::from_secs(42)
}
#[test]
fn serialize_and_deserialize_work() -> Result<(), Box<dyn std::error::Error>> {
let test: TestStruct = TestStruct {
duration: Duration::from_millis(42),
default_duration: default_duration(),
};
let yaml = serde_yaml::to_string(&test)?;
let deserialized = serde_yaml::from_str(&yaml)?;
assert_eq!(test, deserialized);
Ok(())
}
#[test]
fn default_and_deserialize_work() -> Result<(), Box<dyn std::error::Error>> {
let yaml = r#"---
duration: 24
"#;
let deserialized: TestStruct = serde_yaml::from_str(&yaml)?;
assert_eq!(deserialized.duration, Duration::from_millis(24));
assert_eq!(deserialized.default_duration, default_duration());
Ok(())
}
}