weekday/
serde.rs

1use core::{convert::TryFrom as _, fmt};
2
3use serde::{
4    de::{self, Visitor},
5    Deserialize, Deserializer, Serialize, Serializer,
6};
7
8use crate::Weekday;
9
10pub mod serde_str {
11    use serde::{Deserializer, Serializer};
12
13    use super::{Weekday, WeekdayVisitor};
14
15    pub fn serialize<S>(weekday: &Weekday, serializer: S) -> Result<S::Ok, S::Error>
16    where
17        S: Serializer,
18    {
19        serializer.serialize_str(weekday.to_string().as_str())
20    }
21
22    pub fn deserialize<'de, D>(deserializer: D) -> Result<Weekday, D::Error>
23    where
24        D: Deserializer<'de>,
25    {
26        deserializer.deserialize_str(WeekdayVisitor)
27    }
28}
29
30pub mod serde_u64 {
31    use serde::{Deserializer, Serializer};
32
33    use super::{Weekday, WeekdayVisitor};
34
35    pub fn serialize<S>(weekday: &Weekday, serializer: S) -> Result<S::Ok, S::Error>
36    where
37        S: Serializer,
38    {
39        serializer.serialize_u64(weekday.to_owned() as u64)
40    }
41
42    pub fn deserialize<'de, D>(deserializer: D) -> Result<Weekday, D::Error>
43    where
44        D: Deserializer<'de>,
45    {
46        deserializer.deserialize_u64(WeekdayVisitor)
47    }
48}
49
50impl Serialize for Weekday {
51    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
52    where
53        S: Serializer,
54    {
55        serializer.serialize_str(self.to_string().as_str())
56    }
57}
58impl<'de> Deserialize<'de> for Weekday {
59    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60    where
61        D: Deserializer<'de>,
62    {
63        deserializer.deserialize_any(WeekdayVisitor)
64    }
65}
66
67struct WeekdayVisitor;
68impl<'de> Visitor<'de> for WeekdayVisitor {
69    type Value = Weekday;
70
71    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
72        formatter.write_str("str or u8")
73    }
74
75    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
76    where
77        E: de::Error,
78    {
79        v.parse::<Self::Value>().map_err(de::Error::custom)
80    }
81
82    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
83    where
84        E: de::Error,
85    {
86        Self::Value::try_from(v as u8).map_err(de::Error::custom)
87    }
88
89    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
90    where
91        E: de::Error,
92    {
93        Self::Value::try_from(v as u8).map_err(de::Error::custom)
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    use serde_json::json;
102
103    #[derive(Deserialize, Serialize, PartialEq, Debug)]
104    struct Foo {
105        #[serde(with = "crate::serde_str")]
106        w1: Weekday,
107        #[serde(with = "crate::serde_u64")]
108        w2: Weekday,
109        #[serde(
110            serialize_with = "crate::serde_str::serialize",
111            deserialize_with = "crate::serde_u64::deserialize"
112        )]
113        w3: Weekday,
114        w4: Weekday,
115    }
116
117    #[test]
118    fn de() {
119        let json = r#"{ "w1": "Monday", "w2": 2, "w3": 3, "w4": "Thu" }"#;
120        assert_eq!(
121            serde_json::from_str::<Foo>(json).unwrap(),
122            Foo {
123                w1: Weekday::Mon,
124                w2: Weekday::Tue,
125                w3: Weekday::Wed,
126                w4: Weekday::Thu,
127            }
128        );
129
130        let json = r#"{ "w1": "Monday", "w2": 2, "w3": 3, "w4": 4 }"#;
131        assert_eq!(
132            serde_json::from_str::<Foo>(json).unwrap(),
133            Foo {
134                w1: Weekday::Mon,
135                w2: Weekday::Tue,
136                w3: Weekday::Wed,
137                w4: Weekday::Thu,
138            }
139        );
140    }
141
142    #[test]
143    fn ser() {
144        assert_eq!(
145            serde_json::to_value(&Foo {
146                w1: Weekday::Mon,
147                w2: Weekday::Tue,
148                w3: Weekday::Wed,
149                w4: Weekday::Thu,
150            })
151            .unwrap(),
152            json!({
153                "w1": "Mon", "w2": 2, "w3": "Wed", "w4": "Thu"
154            })
155        );
156    }
157}