sqldatetime/
serialize.rs

1//! Impl the `serde::Serialize` and `serde::Deserialize` traits.
2
3use crate::{Date, Formatter, IntervalDT, IntervalYM, Time, Timestamp};
4use once_cell::sync::Lazy;
5use serde_crate::de::Visitor;
6use serde_crate::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
7use stack_buf::StackStr;
8use std::fmt;
9
10static DATE_FORMATTER: Lazy<Formatter> = Lazy::new(|| Formatter::try_new("YYYY-MM-DD").unwrap());
11static TIMESTAMP_FORMATTER: Lazy<Formatter> =
12    Lazy::new(|| Formatter::try_new("YYYY-MM-DD HH24:MI:SS.FF6").unwrap());
13static TIME_FORMATTER: Lazy<Formatter> =
14    Lazy::new(|| Formatter::try_new("HH24:MI:SS.FF6").unwrap());
15static INTERVAL_YM_FORMATTER: Lazy<Formatter> =
16    Lazy::new(|| Formatter::try_new("YYYY-MM").unwrap());
17static INTERVAL_DT_FORMATTER: Lazy<Formatter> =
18    Lazy::new(|| Formatter::try_new("DD HH24:MI:SS.FF6").unwrap());
19
20#[cfg(feature = "oracle")]
21static ORACLE_DATE_FORMATTER: Lazy<Formatter> =
22    Lazy::new(|| Formatter::try_new("YYYY-MM-DD HH24:MI:SS").unwrap());
23
24type StrBuf = StackStr<32>;
25
26#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
27impl Serialize for Date {
28    #[inline]
29    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
30    where
31        S: Serializer,
32    {
33        if serializer.is_human_readable() {
34            let mut buf = StrBuf::new();
35            DATE_FORMATTER
36                .format(*self, &mut buf)
37                .map_err(ser::Error::custom)?;
38            serializer.serialize_str(&buf)
39        } else {
40            serializer.serialize_i32(self.days())
41        }
42    }
43}
44
45#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
46impl<'de> Deserialize<'de> for Date {
47    #[inline]
48    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
49    where
50        D: Deserializer<'de>,
51    {
52        struct DateVisitor;
53
54        impl<'de> Visitor<'de> for DateVisitor {
55            type Value = Date;
56
57            #[inline]
58            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
59                write!(formatter, "a Date")
60            }
61
62            #[inline]
63            fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
64            where
65                E: de::Error,
66            {
67                Ok(unsafe { Date::from_days_unchecked(v) })
68            }
69
70            #[inline]
71            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
72            where
73                E: de::Error,
74            {
75                DATE_FORMATTER.parse(v).map_err(de::Error::custom)
76            }
77        }
78
79        if deserializer.is_human_readable() {
80            deserializer.deserialize_str(DateVisitor)
81        } else {
82            deserializer.deserialize_i32(DateVisitor)
83        }
84    }
85}
86
87#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
88impl Serialize for Timestamp {
89    #[inline]
90    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91    where
92        S: Serializer,
93    {
94        if serializer.is_human_readable() {
95            let mut buf = StrBuf::new();
96            TIMESTAMP_FORMATTER
97                .format(*self, &mut buf)
98                .map_err(ser::Error::custom)?;
99            serializer.serialize_str(&buf)
100        } else {
101            serializer.serialize_i64(self.usecs())
102        }
103    }
104}
105
106#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
107impl<'de> Deserialize<'de> for Timestamp {
108    #[inline]
109    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
110    where
111        D: Deserializer<'de>,
112    {
113        struct TimestampVisitor;
114
115        impl<'de> Visitor<'de> for TimestampVisitor {
116            type Value = Timestamp;
117
118            #[inline]
119            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
120                write!(formatter, "a Timestamp")
121            }
122
123            #[inline]
124            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
125            where
126                E: de::Error,
127            {
128                Ok(unsafe { Timestamp::from_usecs_unchecked(v) })
129            }
130
131            #[inline]
132            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
133            where
134                E: de::Error,
135            {
136                TIMESTAMP_FORMATTER.parse(v).map_err(de::Error::custom)
137            }
138        }
139
140        if deserializer.is_human_readable() {
141            deserializer.deserialize_str(TimestampVisitor)
142        } else {
143            deserializer.deserialize_i64(TimestampVisitor)
144        }
145    }
146}
147
148#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
149impl Serialize for Time {
150    #[inline]
151    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
152    where
153        S: Serializer,
154    {
155        if serializer.is_human_readable() {
156            let mut buf = StrBuf::new();
157            TIME_FORMATTER
158                .format(*self, &mut buf)
159                .map_err(ser::Error::custom)?;
160            serializer.serialize_str(&buf)
161        } else {
162            serializer.serialize_i64(self.usecs())
163        }
164    }
165}
166
167#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
168impl<'de> Deserialize<'de> for Time {
169    #[inline]
170    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
171    where
172        D: Deserializer<'de>,
173    {
174        struct TimeVisitor;
175
176        impl<'de> Visitor<'de> for TimeVisitor {
177            type Value = Time;
178
179            #[inline]
180            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
181                write!(formatter, "a Time")
182            }
183
184            #[inline]
185            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
186            where
187                E: de::Error,
188            {
189                Ok(unsafe { Time::from_usecs_unchecked(v) })
190            }
191
192            #[inline]
193            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
194            where
195                E: de::Error,
196            {
197                TIME_FORMATTER.parse(v).map_err(de::Error::custom)
198            }
199        }
200
201        if deserializer.is_human_readable() {
202            deserializer.deserialize_str(TimeVisitor)
203        } else {
204            deserializer.deserialize_i64(TimeVisitor)
205        }
206    }
207}
208
209#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
210impl Serialize for IntervalYM {
211    #[inline]
212    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
213    where
214        S: Serializer,
215    {
216        if serializer.is_human_readable() {
217            let mut buf = StrBuf::new();
218            INTERVAL_YM_FORMATTER
219                .format(*self, &mut buf)
220                .map_err(ser::Error::custom)?;
221            serializer.serialize_str(&buf)
222        } else {
223            serializer.serialize_i32(self.months())
224        }
225    }
226}
227
228#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
229impl<'de> Deserialize<'de> for IntervalYM {
230    #[inline]
231    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
232    where
233        D: Deserializer<'de>,
234    {
235        struct IntervalVisitor;
236
237        impl<'de> Visitor<'de> for IntervalVisitor {
238            type Value = IntervalYM;
239
240            #[inline]
241            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
242                write!(formatter, "a IntervalYM")
243            }
244
245            #[inline]
246            fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
247            where
248                E: de::Error,
249            {
250                Ok(unsafe { IntervalYM::from_months_unchecked(v) })
251            }
252
253            #[inline]
254            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
255            where
256                E: de::Error,
257            {
258                INTERVAL_YM_FORMATTER.parse(v).map_err(de::Error::custom)
259            }
260        }
261
262        if deserializer.is_human_readable() {
263            deserializer.deserialize_str(IntervalVisitor)
264        } else {
265            deserializer.deserialize_i32(IntervalVisitor)
266        }
267    }
268}
269
270#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
271impl Serialize for IntervalDT {
272    #[inline]
273    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
274    where
275        S: Serializer,
276    {
277        if serializer.is_human_readable() {
278            let mut buf = StrBuf::new();
279            INTERVAL_DT_FORMATTER
280                .format(*self, &mut buf)
281                .map_err(ser::Error::custom)?;
282            serializer.serialize_str(&buf)
283        } else {
284            serializer.serialize_i64(self.usecs())
285        }
286    }
287}
288
289#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
290impl<'de> Deserialize<'de> for IntervalDT {
291    #[inline]
292    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
293    where
294        D: Deserializer<'de>,
295    {
296        struct IntervalVisitor;
297
298        impl<'de> Visitor<'de> for IntervalVisitor {
299            type Value = IntervalDT;
300
301            #[inline]
302            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
303                write!(formatter, "a IntervalDT")
304            }
305
306            #[inline]
307            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
308            where
309                E: de::Error,
310            {
311                Ok(unsafe { IntervalDT::from_usecs_unchecked(v) })
312            }
313
314            #[inline]
315            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
316            where
317                E: de::Error,
318            {
319                INTERVAL_DT_FORMATTER.parse(v).map_err(de::Error::custom)
320            }
321        }
322
323        if deserializer.is_human_readable() {
324            deserializer.deserialize_str(IntervalVisitor)
325        } else {
326            deserializer.deserialize_i64(IntervalVisitor)
327        }
328    }
329}
330
331#[cfg_attr(docsrs, doc(cfg(all(feature = "oracle", feature = "serde"))))]
332#[cfg(feature = "oracle")]
333impl Serialize for crate::oracle::Date {
334    #[inline]
335    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
336    where
337        S: Serializer,
338    {
339        if serializer.is_human_readable() {
340            let mut buf = StrBuf::new();
341            ORACLE_DATE_FORMATTER
342                .format(*self, &mut buf)
343                .map_err(ser::Error::custom)?;
344            serializer.serialize_str(&buf)
345        } else {
346            serializer.serialize_i64(self.usecs())
347        }
348    }
349}
350
351#[cfg_attr(docsrs, doc(cfg(all(feature = "oracle", feature = "serde"))))]
352#[cfg(feature = "oracle")]
353impl<'de> Deserialize<'de> for crate::oracle::Date {
354    #[inline]
355    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
356    where
357        D: Deserializer<'de>,
358    {
359        struct DateVisitor;
360
361        impl<'de> Visitor<'de> for DateVisitor {
362            type Value = crate::oracle::Date;
363
364            #[inline]
365            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
366                write!(formatter, "a Oracle Date")
367            }
368
369            #[inline]
370            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
371            where
372                E: de::Error,
373            {
374                Ok(unsafe { crate::oracle::Date::from_usecs_unchecked(v) })
375            }
376
377            #[inline]
378            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
379            where
380                E: de::Error,
381            {
382                ORACLE_DATE_FORMATTER.parse(v).map_err(de::Error::custom)
383            }
384        }
385
386        if deserializer.is_human_readable() {
387            deserializer.deserialize_str(DateVisitor)
388        } else {
389            deserializer.deserialize_i64(DateVisitor)
390        }
391    }
392}
393
394#[cfg(test)]
395mod tests {
396    use super::*;
397
398    fn test_date(year: i32, mon: u32, day: u32) {
399        let date = Date::try_from_ymd(year, mon, day).unwrap();
400        let date_json = serde_json::to_string(&date).unwrap();
401        let json_decode: Date = serde_json::from_str(&date_json).unwrap();
402        assert_eq!(
403            date_json,
404            format!("\"{}\"", date.format("YYYY-MM-DD").unwrap())
405        );
406        assert_eq!(json_decode, date);
407
408        let bin = bincode::serialize(&date).unwrap();
409        let bin_decode: Date = bincode::deserialize(&bin).unwrap();
410        assert_eq!(bin_decode, date);
411    }
412
413    #[test]
414    fn test_serde_date() {
415        test_date(1, 1, 1);
416        test_date(1234, 12, 31);
417        test_date(1969, 12, 30);
418        test_date(1969, 12, 31);
419        test_date(1970, 1, 1);
420        test_date(2000, 1, 1);
421        test_date(9999, 12, 31);
422    }
423
424    fn test_timestamp(year: i32, mon: u32, day: u32, hour: u32, min: u32, sec: u32, usec: u32) {
425        let date = Date::try_from_ymd(year, mon, day).unwrap();
426        let time = Time::try_from_hms(hour, min, sec, usec).unwrap();
427        let timestamp = Timestamp::new(date, time);
428        let ts_json = serde_json::to_string(&timestamp).unwrap();
429        assert_eq!(
430            ts_json,
431            format!(
432                "\"{}\"",
433                timestamp.format("YYYY-MM-DD HH24:MI:SS.FF6").unwrap()
434            )
435        );
436        let json_decode: Timestamp = serde_json::from_str(&ts_json).unwrap();
437        assert_eq!(json_decode, timestamp);
438
439        let bin = bincode::serialize(&timestamp).unwrap();
440        let bin_decode: Timestamp = bincode::deserialize(&bin).unwrap();
441        assert_eq!(bin_decode, timestamp);
442    }
443
444    #[test]
445    fn test_serde_timestamp() {
446        test_timestamp(1, 1, 1, 0, 0, 0, 0);
447        test_timestamp(1, 1, 1, 1, 1, 1, 1);
448        test_timestamp(1969, 12, 30, 23, 30, 30, 30);
449        test_timestamp(1969, 12, 31, 23, 59, 59, 999999);
450        test_timestamp(1970, 1, 1, 0, 0, 0, 0);
451        test_timestamp(1970, 10, 1, 23, 30, 0, 0);
452        test_timestamp(9999, 12, 31, 23, 59, 59, 999999);
453    }
454
455    fn test_time(hour: u32, min: u32, sec: u32, usec: u32) {
456        let time = Time::try_from_hms(hour, min, sec, usec).unwrap();
457        let time_json = serde_json::to_string(&time).unwrap();
458
459        let json_decode: Time = serde_json::from_str(&time_json).unwrap();
460        assert_eq!(
461            time_json,
462            format!("\"{}\"", time.format("hh24:mi:ss.ff6").unwrap())
463        );
464        assert_eq!(json_decode, time);
465
466        let bin = bincode::serialize(&time).unwrap();
467        let bin_decode: Time = bincode::deserialize(&bin).unwrap();
468        assert_eq!(bin_decode, time);
469    }
470
471    #[test]
472    fn test_serde_time() {
473        test_time(0, 0, 0, 0);
474        test_time(1, 1, 1, 1);
475        test_time(23, 59, 59, 999999);
476    }
477
478    fn test_interval_ym(negate: bool, year: u32, mon: u32) {
479        let interval = if negate {
480            IntervalYM::try_from_ym(year, mon).unwrap().negate()
481        } else {
482            IntervalYM::try_from_ym(year, mon).unwrap()
483        };
484        let interval_json = serde_json::to_string(&interval).unwrap();
485        let json_decode: IntervalYM = serde_json::from_str(&interval_json).unwrap();
486        assert_eq!(
487            interval_json,
488            format!("\"{}\"", interval.format("YYYY-MM").unwrap())
489        );
490        assert_eq!(json_decode, interval);
491
492        let bin = bincode::serialize(&interval).unwrap();
493        let bin_decode: IntervalYM = bincode::deserialize(&bin).unwrap();
494        assert_eq!(bin_decode, interval);
495    }
496
497    #[test]
498    fn test_serde_interval_ym() {
499        test_interval_ym(false, 0, 0);
500        test_interval_ym(false, 0, 1);
501        test_interval_ym(false, 1, 1);
502        test_interval_ym(false, 178000000, 0);
503        test_interval_ym(true, 0000, 1);
504        test_interval_ym(true, 1, 1);
505        test_interval_ym(true, 178000000, 0);
506    }
507
508    fn test_interval_dt(negate: bool, day: u32, hour: u32, min: u32, sec: u32, usec: u32) {
509        let interval = if negate {
510            IntervalDT::try_from_dhms(day, hour, min, sec, usec)
511                .unwrap()
512                .negate()
513        } else {
514            IntervalDT::try_from_dhms(day, hour, min, sec, usec).unwrap()
515        };
516        let interval_json = serde_json::to_string(&interval).unwrap();
517        let json_decode: IntervalDT = serde_json::from_str(&interval_json).unwrap();
518        assert_eq!(
519            interval_json,
520            format!("\"{}\"", interval.format("DD hh24:mi:ss.ff6").unwrap())
521        );
522        assert_eq!(json_decode, interval);
523
524        let bin = bincode::serialize(&interval).unwrap();
525        let bin_decode: IntervalDT = bincode::deserialize(&bin).unwrap();
526        assert_eq!(bin_decode, interval);
527    }
528
529    #[test]
530    fn test_serde_interval_dt() {
531        test_interval_dt(false, 0, 0, 0, 0, 0);
532        test_interval_dt(false, 0, 0, 0, 0, 1);
533        test_interval_dt(false, 1, 1, 1, 1, 1);
534        test_interval_dt(false, 100000000, 0, 0, 0, 0);
535        test_interval_dt(true, 0, 0, 0, 0, 1);
536        test_interval_dt(true, 1, 1, 1, 1, 1);
537        test_interval_dt(true, 100000000, 0, 0, 0, 0);
538    }
539
540    #[cfg(feature = "oracle")]
541    fn test_oracle_date(year: i32, mon: u32, day: u32, hour: u32, min: u32, sec: u32) {
542        let date = Date::try_from_ymd(year, mon, day).unwrap();
543        let time = Time::try_from_hms(hour, min, sec, 0).unwrap();
544        let date = crate::oracle::Date::new(date, time);
545        let date_json = serde_json::to_string(&date).unwrap();
546        assert_eq!(
547            date_json,
548            format!("\"{}\"", date.format("YYYY-MM-DD HH24:MI:SS").unwrap())
549        );
550        let json_decode: crate::oracle::Date = serde_json::from_str(&date_json).unwrap();
551        assert_eq!(json_decode, date);
552
553        let bin = bincode::serialize(&date).unwrap();
554        let bin_decode: crate::oracle::Date = bincode::deserialize(&bin).unwrap();
555        assert_eq!(bin_decode, date);
556    }
557
558    #[cfg(feature = "oracle")]
559    #[test]
560    fn test_serde_oracle_date() {
561        test_oracle_date(1, 1, 1, 0, 0, 0);
562        test_oracle_date(1, 1, 1, 1, 1, 1);
563        test_oracle_date(1969, 12, 30, 23, 30, 30);
564        test_oracle_date(1969, 12, 31, 23, 59, 59);
565        test_oracle_date(1970, 1, 1, 0, 0, 0);
566        test_oracle_date(1970, 10, 1, 23, 30, 0);
567        test_oracle_date(9999, 12, 31, 23, 59, 59);
568    }
569}