blaze_common/
time.rs

1pub mod system_time_as_timestamps {
2
3    use paste::paste;
4    use serde::{de::Visitor, Deserializer, Serializer};
5    use std::time::{Duration, SystemTime, UNIX_EPOCH};
6
7    pub fn serialize<S>(time: &SystemTime, serializer: S) -> Result<S::Ok, S::Error>
8    where
9        S: Serializer,
10    {
11        serializer.serialize_u128(
12            time.duration_since(UNIX_EPOCH)
13                .map_err(|err| {
14                    serde::ser::Error::custom(format!(
15                        "could not serialize {time:?} as a unix timestamp ({err})"
16                    ))
17                })?
18                .as_millis(),
19        )
20    }
21
22    pub fn deserialize<'de, D>(deserializer: D) -> Result<SystemTime, D::Error>
23    where
24        D: Deserializer<'de>,
25    {
26        macro_rules! visit_convert {
27            ($t:ty) => {
28                paste! {
29                    fn [<visit_ $t>]<E>(self, v: $t) -> Result<Self::Value, E>
30                        where
31                            E: serde::de::Error {
32                        u64::try_from(v)
33                            .map_err(|err| E::custom(err.to_string()))
34                    }
35                }
36            };
37        }
38
39        macro_rules! visit_cast {
40            ($t:ty) => {
41                paste! {
42                    fn [<visit_ $t>]<E>(self, v: $t) -> Result<Self::Value, E>
43                        where
44                            E: serde::de::Error {
45                        Ok(v as u64)
46                    }
47                }
48            };
49        }
50
51        struct U64Visitor;
52
53        impl<'de> Visitor<'de> for U64Visitor {
54            type Value = u64;
55
56            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
57                formatter.write_str("a number of milliseconds representing a unix timestamp")
58            }
59
60            visit_cast!(u8);
61            visit_cast!(u16);
62            visit_cast!(u32);
63
64            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
65            where
66                E: serde::de::Error,
67            {
68                Ok(v)
69            }
70
71            visit_convert!(u128);
72
73            visit_convert!(i8);
74            visit_convert!(i16);
75            visit_convert!(i32);
76            visit_convert!(i64);
77            visit_convert!(i128);
78        }
79
80        let millis = deserializer.deserialize_u64(U64Visitor)?;
81        Ok(UNIX_EPOCH + Duration::from_millis(millis))
82    }
83}