rs_firebase_admin_sdk/util/
serialize.rs1use serde::de::{self, Visitor};
2use std::fmt;
3use time::OffsetDateTime;
4
5#[derive(Debug, Clone)]
6pub struct StrEpochMs {
7 dt: OffsetDateTime,
8}
9
10impl From<OffsetDateTime> for StrEpochMs {
11 fn from(dt: OffsetDateTime) -> Self {
12 Self { dt }
13 }
14}
15
16impl From<StrEpochMs> for OffsetDateTime {
17 fn from(value: StrEpochMs) -> Self {
18 value.dt
19 }
20}
21
22struct StrEpochMsVisitor;
23
24impl<'de> Visitor<'de> for StrEpochMsVisitor {
25 type Value = StrEpochMs;
26
27 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
28 formatter.write_str("a string containing count of miliseconds since UNIX epoch")
29 }
30
31 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
32 where
33 E: de::Error,
34 {
35 let unix_ts_ms: i128 = value.parse().map_err(|e| E::custom(format!("{e:?}")))?;
36
37 let off_dt = OffsetDateTime::from_unix_timestamp_nanos(unix_ts_ms * 1000000)
38 .map_err(|e| E::custom(format!("{e:?}")))?;
39
40 Ok(off_dt.into())
41 }
42}
43
44impl<'de> de::Deserialize<'de> for StrEpochMs {
45 fn deserialize<D>(deserializer: D) -> Result<StrEpochMs, D::Error>
46 where
47 D: de::Deserializer<'de>,
48 {
49 deserializer.deserialize_str(StrEpochMsVisitor)
50 }
51}
52
53#[derive(Debug, Clone)]
54pub struct StrEpochSec {
55 dt: OffsetDateTime,
56}
57
58impl From<OffsetDateTime> for StrEpochSec {
59 fn from(dt: OffsetDateTime) -> Self {
60 Self { dt }
61 }
62}
63
64impl From<StrEpochSec> for OffsetDateTime {
65 fn from(value: StrEpochSec) -> Self {
66 value.dt
67 }
68}
69
70struct StrEpochSecVisitor;
71
72impl<'de> Visitor<'de> for StrEpochSecVisitor {
73 type Value = StrEpochSec;
74
75 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
76 formatter.write_str("a string containing count of seconds since UNIX epoch")
77 }
78
79 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
80 where
81 E: de::Error,
82 {
83 let unix_ts: i64 = value.parse().map_err(|e| E::custom(format!("{e:?}")))?;
84
85 let off_dt = OffsetDateTime::from_unix_timestamp(unix_ts)
86 .map_err(|e| E::custom(format!("{e:?}")))?;
87
88 Ok(off_dt.into())
89 }
90}
91
92impl<'de> de::Deserialize<'de> for StrEpochSec {
93 fn deserialize<D>(deserializer: D) -> Result<StrEpochSec, D::Error>
94 where
95 D: de::Deserializer<'de>,
96 {
97 deserializer.deserialize_str(StrEpochSecVisitor)
98 }
99}
100
101#[derive(Debug, Clone)]
102pub struct I128EpochMs {
103 dt: OffsetDateTime,
104}
105
106impl From<OffsetDateTime> for I128EpochMs {
107 fn from(dt: OffsetDateTime) -> Self {
108 Self { dt }
109 }
110}
111
112impl From<I128EpochMs> for OffsetDateTime {
113 fn from(value: I128EpochMs) -> Self {
114 value.dt
115 }
116}
117
118struct I128EpochMsVisitor;
119
120impl<'de> Visitor<'de> for I128EpochMsVisitor {
121 type Value = I128EpochMs;
122
123 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
124 formatter.write_str("an integer containing count of miliseconds since UNIX epoch")
125 }
126
127 fn visit_i128<E>(self, value: i128) -> Result<Self::Value, E>
128 where
129 E: de::Error,
130 {
131 let off_dt = OffsetDateTime::from_unix_timestamp_nanos(value * 1000000)
132 .map_err(|e| E::custom(format!("{e:?}")))?;
133
134 Ok(off_dt.into())
135 }
136}
137
138impl<'de> de::Deserialize<'de> for I128EpochMs {
139 fn deserialize<D>(deserializer: D) -> Result<I128EpochMs, D::Error>
140 where
141 D: de::Deserializer<'de>,
142 {
143 deserializer.deserialize_i128(I128EpochMsVisitor)
144 }
145}