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}