expiration_date/
serde_impl.rs1use crate::ExpirationDate;
8use chrono::{DateTime, Utc};
9use positive::Positive;
10use serde::{Deserialize, Deserializer, Serialize, Serializer};
11use std::fmt;
12
13impl Serialize for ExpirationDate {
14 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
15 where
16 S: Serializer,
17 {
18 use serde::ser::SerializeMap;
19 let mut state = serializer.serialize_map(Some(1))?;
20 match self {
21 Self::Days(days) => state.serialize_entry("days", &days.to_f64())?,
22 Self::DateTime(dt) => {
23 state.serialize_entry("datetime", &dt.format("%Y-%m-%dT%H:%M:%SZ").to_string())?
24 }
25 }
26 state.end()
27 }
28}
29
30impl<'de> Deserialize<'de> for ExpirationDate {
31 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
32 where
33 D: Deserializer<'de>,
34 {
35 use serde::de::{MapAccess, Visitor};
36 struct ExVisitor;
37 impl<'de> Visitor<'de> for ExVisitor {
38 type Value = ExpirationDate;
39 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 f.write_str("struct ExpirationDate")
41 }
42 fn visit_map<V>(self, mut map: V) -> Result<ExpirationDate, V::Error>
43 where
44 V: MapAccess<'de>,
45 {
46 let mut d = None;
47 let mut t = None;
48 while let Some(k) = map.next_key::<String>()? {
49 match k.as_str() {
50 "days" => {
51 if d.is_some() {
52 return Err(serde::de::Error::duplicate_field("days"));
53 }
54 d = Some(map.next_value::<f64>()?);
55 }
56 "datetime" => {
57 if t.is_some() {
58 return Err(serde::de::Error::duplicate_field("datetime"));
59 }
60 t = Some(map.next_value::<String>()?);
61 }
62 _ => {
63 return Err(serde::de::Error::unknown_field(&k, &["days", "datetime"]));
64 }
65 }
66 }
67 match (d, t) {
68 (Some(v), _) => Ok(ExpirationDate::Days(
69 Positive::new(v).map_err(serde::de::Error::custom)?,
70 )),
71 (_, Some(v)) => Ok(ExpirationDate::DateTime(
72 DateTime::parse_from_rfc3339(&v)
73 .map_err(serde::de::Error::custom)?
74 .with_timezone(&Utc),
75 )),
76 _ => Err(serde::de::Error::missing_field("days or datetime")),
77 }
78 }
79 }
80 deserializer.deserialize_struct("ExpirationDate", &["days", "datetime"], ExVisitor)
81 }
82}