wmi/
duration.rs

1use crate::WMIError;
2use serde::{de, ser};
3use std::{fmt, str::FromStr, time::Duration};
4
5/// A wrapper type around Duration, which supports parsing from WMI-format strings.
6///
7#[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}