1use crate::WMIError;
2use serde::{de, ser};
3use std::{fmt, str::FromStr, time::Duration};
4
5#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
8pub struct WMIDuration(pub Duration);
9
10impl FromStr for WMIDuration {
11 type Err = WMIError;
12
13 fn from_str(s: &str) -> Result<Self, Self::Err> {
14 if s.len() != 25 {
15 return Err(WMIError::ConvertDurationError(s.into()));
16 }
17
18 let (seconds_part, reminder) = s.split_at(14);
19 let (micros_part, _) = reminder[1..].split_at(6);
20
21 let seconds: u64 = seconds_part.parse()?;
22 let micros: u64 = micros_part.parse()?;
23
24 let duration = Duration::from_secs(seconds) + Duration::from_micros(micros);
25
26 Ok(Self(duration))
27 }
28}
29
30#[derive(Debug, Clone)]
31struct DurationVisitor;
32
33impl<'de> de::Visitor<'de> for DurationVisitor {
34 type Value = WMIDuration;
35
36 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
37 write!(formatter, "a timestamp in WMI format")
38 }
39
40 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
41 where
42 E: de::Error,
43 {
44 value.parse().map_err(|err| E::custom(format!("{}", err)))
45 }
46}
47
48impl<'de> de::Deserialize<'de> for WMIDuration {
49 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
50 where
51 D: de::Deserializer<'de>,
52 {
53 deserializer.deserialize_u64(DurationVisitor)
54 }
55}
56
57impl ser::Serialize for WMIDuration {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: ser::Serializer,
61 {
62 serializer.serialize_u64(self.0.as_micros() as u64)
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::WMIDuration;
69 use serde_json;
70
71 #[test]
72 fn it_works() {
73 let duration: WMIDuration = "00000005141436.100001:000".parse().unwrap();
74
75 assert_eq!(duration.0.as_micros(), 5141436100001);
76 assert_eq!(duration.0.as_millis(), 5141436100);
77 assert_eq!(duration.0.as_secs(), 5141436);
78 }
79
80 #[test]
81 fn it_serializes_to_rfc() {
82 let duration: WMIDuration = "00000005141436.100001:000".parse().unwrap();
83
84 let v = serde_json::to_string(&duration).unwrap();
85 assert_eq!(v, "5141436100001");
86 }
87}