1use serde::{Deserialize, Serialize, Deserializer};
2use serde::ser::Serializer;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct Dns {
6 pub zone: Option<String>
7}
8
9pub fn is_dns_none(dns: &Option<Dns>) -> bool {
11 match dns {
12 None => true,
13 Some(dns) => dns.zone.is_none(),
14 }
15}
16
17impl Serialize for Dns {
19 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
20 where
21 S: Serializer,
22 {
23 match &self.zone {
24 Some(zone) => serializer.serialize_str(zone),
25 None => serializer.serialize_none()
26 }
27 }
28}
29
30impl<'de> Deserialize<'de> for Dns {
32 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
33 where
34 D: Deserializer<'de>,
35 {
36 let value = serde::de::DeserializeSeed::deserialize(
38 StringOrStruct::default(),
39 deserializer
40 )?;
41 Ok(value)
42 }
43}
44
45#[derive(Default)]
46struct StringOrStruct {
47 _private: ()
48}
49
50impl<'de> serde::de::DeserializeSeed<'de> for StringOrStruct {
51 type Value = Dns;
52
53 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
54 where
55 D: Deserializer<'de>,
56 {
57 struct StringVisitor;
59
60 impl<'de> serde::de::Visitor<'de> for StringVisitor {
61 type Value = Dns;
62
63 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
64 formatter.write_str("string or dns object")
65 }
66
67 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
68 where
69 E: serde::de::Error,
70 {
71 Ok(Dns { zone: Some(value.to_string()) })
72 }
73
74 fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
75 where
76 E: serde::de::Error,
77 {
78 Ok(Dns { zone: Some(value) })
79 }
80
81 fn visit_none<E>(self) -> Result<Self::Value, E>
82 where
83 E: serde::de::Error,
84 {
85 Ok(Dns { zone: None })
86 }
87
88 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
89 where
90 D: Deserializer<'de>,
91 {
92 Deserialize::deserialize(deserializer)
93 }
94
95 fn visit_unit<E>(self) -> Result<Self::Value, E>
96 where
97 E: serde::de::Error,
98 {
99 Ok(Dns { zone: None })
100 }
101
102 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
103 where
104 A: serde::de::MapAccess<'de>,
105 {
106 let mut zone = None;
107 while let Some(key) = map.next_key::<String>()? {
108 if key == "zone" {
109 zone = map.next_value()?;
110 } else {
111 map.next_value::<serde::de::IgnoredAny>()?;
112 }
113 }
114 Ok(Dns { zone })
115 }
116 }
117
118 deserializer.deserialize_any(StringVisitor)
119 }
120}
121
122impl Default for Dns {
123 fn default() -> Self {
124 Self { zone: None }
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use serde_json;
132
133 #[test]
134 fn test_dns_serialization() {
135 let dns = Dns {
137 zone: Some("example.com".to_string()),
138 };
139 let json = serde_json::to_string(&dns).unwrap();
140 assert_eq!(json, r#""example.com""#);
141
142 let dns = Dns { zone: None };
144 let json = serde_json::to_string(&dns).unwrap();
145 assert_eq!(json, "null");
146
147 let dns = Dns::default();
149 let json = serde_json::to_string(&dns).unwrap();
150 assert_eq!(json, "null");
151 }
152
153 #[test]
154 fn test_dns_in_struct() {
155 #[derive(Serialize)]
157 struct Container {
158 #[serde(skip_serializing_if = "is_dns_none")]
159 dns: Option<Dns>,
160 other: String,
161 }
162
163 let container = Container {
165 dns: Some(Dns {
166 zone: Some("example.com".to_string()),
167 }),
168 other: "test".to_string(),
169 };
170 let json = serde_json::to_string(&container).unwrap();
171 assert_eq!(json, r#"{"dns":"example.com","other":"test"}"#);
172
173 let container = Container {
175 dns: Some(Dns { zone: None }),
176 other: "test".to_string(),
177 };
178 let json = serde_json::to_string(&container).unwrap();
179 assert_eq!(json, r#"{"other":"test"}"#);
180
181 let container = Container {
183 dns: None,
184 other: "test".to_string(),
185 };
186 let json = serde_json::to_string(&container).unwrap();
187 assert_eq!(json, r#"{"other":"test"}"#);
188 }
189
190 #[test]
191 fn test_dns_deserialization() {
192 let dns: Dns = serde_json::from_str(r#""example.com""#).unwrap();
194 assert_eq!(dns.zone, Some("example.com".to_string()));
195
196 let dns: Dns = serde_json::from_str("null").unwrap();
198 assert_eq!(dns.zone, None);
199
200 let dns: Dns = serde_json::from_str("{}").unwrap();
202 assert_eq!(dns.zone, None);
203
204 let dns: Dns = serde_json::from_str(r#"{"zone":null}"#).unwrap();
206 assert_eq!(dns.zone, None);
207
208 let dns: Dns = serde_json::from_str(r#"{"zone":"example.com"}"#).unwrap();
210 assert_eq!(dns.zone, Some("example.com".to_string()));
211 }
212}