non_empty_string/
serde_support.rs

1use std::fmt;
2
3use serde::{
4    de::{self, Unexpected, Visitor},
5    ser::Serialize,
6};
7
8use crate::NonEmptyString;
9
10impl Serialize for NonEmptyString {
11    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
12    where
13        S: serde::Serializer,
14    {
15        serializer.serialize_str(self.get())
16    }
17}
18
19struct NonEmptyStringVisitor;
20
21impl<'de> de::Deserialize<'de> for NonEmptyString {
22    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
23    where
24        D: serde::Deserializer<'de>,
25    {
26        deserializer.deserialize_string(NonEmptyStringVisitor)
27    }
28}
29
30impl<'de> Visitor<'de> for NonEmptyStringVisitor {
31    type Value = NonEmptyString;
32
33    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
34        formatter.write_str("a string with a length of more than 0")
35    }
36
37    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
38    where
39        E: de::Error,
40    {
41        self.visit_string(value.to_owned())
42    }
43
44    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
45    where
46        E: de::Error,
47    {
48        NonEmptyString::new(value).map_err(|e| de::Error::invalid_value(Unexpected::Str(&e), &self))
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use crate::*;
55    use assert_matches::assert_matches;
56    use serde_json::json;
57
58    #[test]
59    fn serialize_non_empty_string_and_normal_string_give_the_same_result() {
60        let value = NonEmptyString("abc".to_owned());
61        let result = serde_json::to_string(&value);
62
63        assert!(result.is_ok());
64
65        let json = serde_json::to_string(&json!("abc")).unwrap();
66        assert_eq!(result.unwrap(), json)
67    }
68
69    #[test]
70    fn deserialize_works() {
71        let e: Result<NonEmptyString, _> = serde_json::from_value(json!("abc"));
72
73        let expected = NonEmptyString("abc".to_owned());
74
75        assert_matches!(e, Ok(v) if v == expected)
76    }
77
78    fn deserialize_x_fails(value: serde_json::Value, expected_error_message: &'static str) {
79        let e: Result<NonEmptyString, _> = serde_json::from_value(value);
80        assert_matches!(e, Err(error) if &error.to_string() == expected_error_message)
81    }
82
83    #[test]
84    fn deserialize_empty_fails() {
85        deserialize_x_fails(
86            json!(""),
87            "invalid value: string \"\", expected a string with a length of more than 0",
88        )
89    }
90
91    #[test]
92    fn deserialize_number_fails() {
93        deserialize_x_fails(
94            json!(8),
95            "invalid type: integer `8`, expected a string with a length of more than 0",
96        )
97    }
98
99    #[test]
100    fn deserialize_object_fails() {
101        deserialize_x_fails(
102            json!({}),
103            "invalid type: map, expected a string with a length of more than 0",
104        )
105    }
106
107    #[test]
108    fn deserialize_sequence_fails() {
109        deserialize_x_fails(
110            json!([]),
111            "invalid type: sequence, expected a string with a length of more than 0",
112        )
113    }
114}