1use crate::{
6 FmtUtc2k,
7 Month,
8 Utc2k,
9 Weekday,
10};
11use serde_core::{
12 de,
13 Deserialize,
14 ser,
15 Serialize,
16};
17use std::fmt;
18
19
20
21impl<'de> Deserialize<'de> for FmtUtc2k {
22 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
26 where D: de::Deserializer<'de> {
27 Utc2k::deserialize(deserializer).map(Self::from)
28 }
29}
30
31impl Serialize for FmtUtc2k {
32 #[inline]
33 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
37 where S: ser::Serializer { serializer.serialize_str(self.as_str()) }
38}
39
40
41
42impl<'de> Deserialize<'de> for Utc2k {
43 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
47 where D: de::Deserializer<'de> {
48 struct Visitor;
50
51 macro_rules! invalid {
53 ($fn:ident, $ty:ty) => (
54 fn $fn<S>(self, _src: $ty) -> Result<Self::Value, S>
55 where S: de::Error {
56 Err(de::Error::custom(concat!(stringify!($ty), " is unsupported")))
57 }
58 );
59 }
60
61 impl de::Visitor<'_> for Visitor {
62 type Value = Utc2k;
63
64 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 f.write_str("a timestamp or datetime string")
66 }
67
68 fn visit_str<S>(self, src: &str) -> Result<Self::Value, S>
69 where S: de::Error {
70 Utc2k::try_from(src).map_err(|_| de::Error::custom("invalid datetime string"))
71 }
72
73 fn visit_bytes<S>(self, src: &[u8]) -> Result<Self::Value, S>
74 where S: de::Error {
75 Utc2k::try_from(src).map_err(|_| de::Error::custom("invalid datetime string"))
76 }
77
78 fn visit_i32<S>(self, src: i32) -> Result<Self::Value, S>
79 where S: de::Error {
80 u32::try_from(src)
82 .map(Utc2k::from)
83 .map_err(|_| de::Error::custom("invalid unix timestamp"))
84 }
85
86 fn visit_i64<S>(self, src: i64) -> Result<Self::Value, S>
87 where S: de::Error {
88 u32::try_from(src)
90 .map(Utc2k::from)
91 .map_err(|_| de::Error::custom("invalid unix timestamp"))
92 }
93
94 fn visit_u32<S>(self, src: u32) -> Result<Self::Value, S>
95 where S: de::Error { Ok(Utc2k::from(src)) }
96
97 fn visit_u64<S>(self, src: u64) -> Result<Self::Value, S>
98 where S: de::Error {
99 Ok(u32::try_from(src).map_or_else(|_| Utc2k::MAX, Utc2k::from))
102 }
103
104 invalid!(visit_char, char);
106 invalid!(visit_i8, i8);
107 invalid!(visit_i16, i16);
108 invalid!(visit_u8, u8);
109 invalid!(visit_u16, u16);
110 }
111
112 deserializer.deserialize_any(Visitor)
113 }
114}
115
116impl Serialize for Utc2k {
117 #[inline]
118 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
122 where S: ser::Serializer { serializer.serialize_u32(self.unixtime()) }
123}
124
125
126
127impl<'de> Deserialize<'de> for Month {
128 #[inline]
129 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
133 where D: de::Deserializer<'de> {
134 struct Visitor;
136
137 impl de::Visitor<'_> for Visitor {
138 type Value = Month;
139
140 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 f.write_str("a string representation like 'jan' or 'January'")
142 }
143
144 #[inline]
145 fn visit_str<S>(self, src: &str) -> Result<Self::Value, S>
146 where S: de::Error {
147 Month::try_from(src).map_err(|_| de::Error::custom("invalid month string"))
148 }
149
150 #[inline]
151 fn visit_bytes<S>(self, src: &[u8]) -> Result<Self::Value, S>
152 where S: serde_core::de::Error {
153 Month::try_from(src).map_err(|_| de::Error::custom("invalid month string"))
154 }
155 }
156
157 deserializer.deserialize_str(Visitor)
158 }
159}
160
161impl Serialize for Month {
162 #[inline]
163 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
167 where S: ser::Serializer { serializer.serialize_str(self.as_str()) }
168}
169
170
171
172impl<'de> Deserialize<'de> for Weekday {
173 #[inline]
174 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
178 where D: de::Deserializer<'de> {
179 struct Visitor;
181
182 impl de::Visitor<'_> for Visitor {
183 type Value = Weekday;
184
185 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
186 f.write_str("a string representation like 'mon' or 'Monday'")
187 }
188
189 #[inline]
190 fn visit_str<S>(self, src: &str) -> Result<Self::Value, S>
191 where S: de::Error {
192 Weekday::try_from(src).map_err(|_| de::Error::custom("invalid weekday string"))
193 }
194
195 #[inline]
196 fn visit_bytes<S>(self, src: &[u8]) -> Result<Self::Value, S>
197 where S: serde_core::de::Error {
198 Weekday::try_from(src).map_err(|_| de::Error::custom("invalid weekday string"))
199 }
200 }
201
202 deserializer.deserialize_str(Visitor)
203 }
204}
205
206impl Serialize for Weekday {
207 #[inline]
208 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
212 where S: ser::Serializer { serializer.serialize_str(self.as_str()) }
213}
214
215
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220
221 #[cfg(not(miri))]
222 const SAMPLE_SIZE: usize = 1_000_000;
223
224 #[cfg(miri)]
225 const SAMPLE_SIZE: usize = 1000; #[test]
228 fn t_serde() {
230 const DATESTR: &str = "2021-07-08 11:33:16";
231 const DATENUM: &str = "1625743996";
232 const DATESTR_Q: &str = "\"2021-07-08 11:33:16\"";
233
234 {
235 let date = FmtUtc2k::try_from(DATESTR).unwrap();
237 let serial = serde_json::to_string(&date)
238 .expect("FmtUtc2k serialization failed.");
239 assert_eq!(serial, DATESTR_Q);
240
241 let mut date2: FmtUtc2k = serde_json::from_str(&serial)
242 .expect("FmtUtc2k deserialization (str) failed.");
243 assert_eq!(date, date2);
244
245 date2 = serde_json::from_str(DATENUM)
247 .expect("FmtUtc2k deserialization (u32) failed.");
248 assert_eq!(date, date2);
249 }
250
251 {
252 let date = Utc2k::try_from(DATESTR).unwrap();
254 let serial = serde_json::to_string(&date)
255 .expect("Utc2k serialization failed.");
256 assert_eq!(serial, DATENUM);
257
258 let mut date2: Utc2k = serde_json::from_str(&serial)
259 .expect("Utc2k deserialization (u32) failed.");
260 assert_eq!(date, date2);
261
262 date2 = serde_json::from_str(DATESTR_Q)
264 .expect("Utc2k deserialization (str) failed.");
265 assert_eq!(date, date2);
266 }
267 }
268
269 #[test]
270 fn t_serde_fmtutc2k_rng() {
271 let mut rng = fastrand::Rng::new();
272 for i in std::iter::repeat_with(|| rng.u32(Utc2k::MIN_UNIXTIME..=Utc2k::MAX_UNIXTIME)).take(SAMPLE_SIZE) {
273 let date = FmtUtc2k::from(i);
274
275 let s = serde_json::to_string(&date).expect("Serialization failed.");
278 assert_eq!(format!("{:?}", date.as_str()), s);
279
280 let d = serde_json::from_str::<FmtUtc2k>(&s).expect("Deserialization failed.");
282 assert_eq!(date, d);
283 }
284 }
285
286 #[test]
287 fn t_serde_utc2k_rng() {
288 let mut rng = fastrand::Rng::new();
289 for i in std::iter::repeat_with(|| rng.u32(Utc2k::MIN_UNIXTIME..=Utc2k::MAX_UNIXTIME)).take(SAMPLE_SIZE) {
290 let date = Utc2k::from(i);
291
292 let s = serde_json::to_string(&date).expect("Serialization failed.");
294 assert_eq!(s, i.to_string());
295
296 let d = serde_json::from_str::<Utc2k>(&s).expect("Deserialization failed.");
298 assert_eq!(date, d);
299 }
300 }
301
302 #[test]
303 fn t_serde_month() {
304 for month in Month::ALL {
305 let s = serde_json::to_string(&month).expect("Serialization failed.");
306 assert_eq!(s, format!("\"{}\"", month.as_str()));
307
308 let d = serde_json::from_str::<Month>(&s).expect("Deserialization failed.");
309 assert_eq!(d, month);
310
311 let d = serde_json::from_str::<Month>(&format!("\"{}\"", month.abbreviation()))
313 .expect("Deserialization (abbr) failed.");
314 assert_eq!(d, month);
315 }
316 }
317
318 #[test]
319 fn t_serde_weekday() {
320 for day in Weekday::ALL {
321 let s = serde_json::to_string(&day).expect("Serialization failed.");
322 assert_eq!(s, format!("\"{}\"", day.as_str()));
323
324 let d = serde_json::from_str::<Weekday>(&s).expect("Deserialization failed.");
325 assert_eq!(d, day);
326
327 let d = serde_json::from_str::<Weekday>(&format!("\"{}\"", day.abbreviation()))
329 .expect("Deserialization (abbr) failed.");
330 assert_eq!(d, day);
331 }
332 }
333}