1use crate::{IpNet, Ipv4Net, Ipv6Net};
2use core::fmt;
3#[cfg(not(feature = "std"))]
4use core::net::{Ipv4Addr, Ipv6Addr};
5#[cfg(feature = "std")]
6use std::net::{Ipv4Addr, Ipv6Addr};
7use serde::{self, Serialize, Deserialize, Serializer, Deserializer};
8use serde::ser::SerializeTuple;
9use serde::de::{EnumAccess, Error, VariantAccess, Visitor};
10
11impl Serialize for IpNet {
12 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
13 where S: Serializer
14 {
15 if serializer.is_human_readable() {
16 match *self {
17 IpNet::V4(ref a) => a.serialize(serializer),
18 IpNet::V6(ref a) => a.serialize(serializer),
19 }
20 } else {
21 match *self {
22 IpNet::V4(ref a) => serializer.serialize_newtype_variant("IpNet", 0, "V4", a),
23 IpNet::V6(ref a) => serializer.serialize_newtype_variant("IpNet", 1, "V6", a),
24 }
25 }
26 }
27}
28
29impl<'de> Deserialize<'de> for IpNet {
30 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
31 where D: Deserializer<'de>
32 {
33 if deserializer.is_human_readable() {
34 struct IpNetVisitor;
35
36 impl<'de> Visitor<'de> for IpNetVisitor {
37 type Value = IpNet;
38
39 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
40 formatter.write_str("IPv4 or IPv6 network address")
41 }
42
43 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
44 where E: Error
45 {
46 s.parse().map_err(Error::custom)
47 }
48 }
49
50 deserializer.deserialize_str(IpNetVisitor)
51 } else {
52 struct EnumVisitor;
53
54 #[derive(Serialize, Deserialize)]
55 enum IpNetKind {
56 V4,
57 V6,
58 }
59
60 impl<'de> Visitor<'de> for EnumVisitor {
61 type Value = IpNet;
62
63 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
64 formatter.write_str("IPv4 or IPv6 network address")
65 }
66
67 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
68 where A: EnumAccess<'de>
69 {
70 match data.variant()? {
71 (IpNetKind::V4, v) => v.newtype_variant().map(IpNet::V4),
72 (IpNetKind::V6, v) => v.newtype_variant().map(IpNet::V6),
73 }
74 }
75 }
76
77 deserializer.deserialize_enum("IpNet", &["V4", "V6"], EnumVisitor)
78 }
79 }
80}
81
82impl Serialize for Ipv4Net {
83 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
84 where S: Serializer
85 {
86 if serializer.is_human_readable() {
87 #[cfg(feature = "ser_as_str")]
88 {
89 let mut buf = heapless::String::<18>::new();
90 fmt::write(&mut buf, format_args!("{self}")).unwrap();
91 serializer.serialize_str(&buf)
92 }
93 #[cfg(not(feature = "ser_as_str"))]
94 serializer.collect_str(self)
95 } else {
96 let mut seq = serializer.serialize_tuple(5)?;
97 for octet in &self.addr().octets() {
98 seq.serialize_element(octet)?;
99 }
100 seq.serialize_element(&self.prefix_len())?;
101 seq.end()
102 }
103 }
104}
105
106impl<'de> Deserialize<'de> for Ipv4Net {
107 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
108 where D: Deserializer<'de>
109 {
110 if deserializer.is_human_readable() {
111 struct IpAddrVisitor;
112
113 impl<'de> Visitor<'de> for IpAddrVisitor {
114 type Value = Ipv4Net;
115
116 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
117 formatter.write_str("IPv4 network address")
118 }
119
120 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
121 where E: Error
122 {
123 s.parse().map_err(Error::custom)
124 }
125 }
126
127 deserializer.deserialize_str(IpAddrVisitor)
128 } else {
129 let b = <[u8; 5]>::deserialize(deserializer)?;
130 Ipv4Net::new(Ipv4Addr::new(b[0], b[1], b[2], b[3]), b[4]).map_err(serde::de::Error::custom)
131 }
132 }
133}
134
135impl Serialize for Ipv6Net {
136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where S: Serializer
138 {
139 if serializer.is_human_readable() {
140 #[cfg(feature = "ser_as_str")]
141 {
142 let mut buf = heapless::String::<43>::new();
143 fmt::write(&mut buf, format_args!("{self}")).unwrap();
144 serializer.serialize_str(&buf)
145 }
146 #[cfg(not(feature = "ser_as_str"))]
147 serializer.collect_str(self)
148 } else {
149 let mut seq = serializer.serialize_tuple(17)?;
150 for octet in &self.addr().octets() {
151 seq.serialize_element(octet)?;
152 }
153 seq.serialize_element(&self.prefix_len())?;
154 seq.end()
155 }
156 }
157}
158
159impl<'de> Deserialize<'de> for Ipv6Net {
160 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
161 where D: Deserializer<'de>
162 {
163 if deserializer.is_human_readable() {
164 struct IpAddrVisitor;
165
166 impl<'de> Visitor<'de> for IpAddrVisitor {
167 type Value = Ipv6Net;
168
169 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
170 formatter.write_str("IPv6 network address")
171 }
172
173 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
174 where E: Error
175 {
176 s.parse().map_err(Error::custom)
177 }
178 }
179
180 deserializer.deserialize_str(IpAddrVisitor)
181 } else {
182 let b = <[u8; 17]>::deserialize(deserializer)?;
183 Ipv6Net::new(Ipv6Addr::new(
184 ((b[0] as u16) << 8) | b[1] as u16, ((b[2] as u16) << 8) | b[3] as u16,
185 ((b[4] as u16) << 8) | b[5] as u16, ((b[6] as u16) << 8) | b[7] as u16,
186 ((b[8] as u16) << 8) | b[9] as u16, ((b[10] as u16) << 8) | b[11] as u16,
187 ((b[12] as u16) << 8) | b[13] as u16, ((b[14] as u16) << 8) | b[15] as u16
188 ), b[16]).map_err(Error::custom)
189 }
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 extern crate serde_test;
196
197 use crate::{IpNet, Ipv4Net, Ipv6Net};
198 use self::serde_test::{assert_tokens, Configure, Token};
199
200 #[test]
201 fn test_serialize_ipnet_v4() {
202 let net_str = "10.1.1.0/24";
203 let net: IpNet = net_str.parse().unwrap();
204 assert_tokens(&net.readable(), &[Token::Str(net_str)]);
205 assert_tokens(&net.compact(), &[
206 Token::NewtypeVariant { name: "IpNet", variant: "V4", },
207 Token::Tuple { len: 5 },
208 Token::U8(10),
209 Token::U8(1),
210 Token::U8(1),
211 Token::U8(0),
212 Token::U8(24),
213 Token::TupleEnd,
214 ]);
215 }
216
217 #[test]
218 fn test_serialize_ipnet_v6() {
219 let net_str = "fd00::/32";
220 let net: IpNet = net_str.parse().unwrap();
221 assert_tokens(&net.readable(), &[Token::Str(net_str)]);
222 assert_tokens(&net.compact(), &[
223 Token::NewtypeVariant { name: "IpNet", variant: "V6", },
224 Token::Tuple { len: 17 },
227 Token::U8(253u8),
228 Token::U8(0),
229 Token::U8(0),
230 Token::U8(0),
231 Token::U8(0),
232 Token::U8(0),
233 Token::U8(0),
234 Token::U8(0),
235 Token::U8(0),
236 Token::U8(0),
237 Token::U8(0),
238 Token::U8(0),
239 Token::U8(0),
240 Token::U8(0),
241 Token::U8(0),
242 Token::U8(0),
243 Token::U8(32),
244 Token::TupleEnd,
245 ]);
246 }
247
248 #[test]
249 fn test_serialize_ipv4_net() {
250 let net_str = "10.1.1.0/24";
251 let net: Ipv4Net = net_str.parse().unwrap();
252 assert_tokens(&net.readable(), &[Token::Str(net_str)]);
253 assert_tokens(&net.compact(), &[
254 Token::Tuple { len: 5 },
255 Token::U8(10),
256 Token::U8(1),
257 Token::U8(1),
258 Token::U8(0),
259 Token::U8(24),
260 Token::TupleEnd,
261 ]);
262 }
263
264 #[test]
265 fn test_serialize_ipv6_net() {
266 let net_str = "fd00::/32";
267 let net: Ipv6Net = net_str.parse().unwrap();
268 assert_tokens(&net.readable(), &[Token::Str(net_str)]);
269 assert_tokens(&net.compact(), &[
270 Token::Tuple { len: 17 },
273 Token::U8(253u8),
274 Token::U8(0),
275 Token::U8(0),
276 Token::U8(0),
277 Token::U8(0),
278 Token::U8(0),
279 Token::U8(0),
280 Token::U8(0),
281 Token::U8(0),
282 Token::U8(0),
283 Token::U8(0),
284 Token::U8(0),
285 Token::U8(0),
286 Token::U8(0),
287 Token::U8(0),
288 Token::U8(0),
289 Token::U8(32),
290 Token::TupleEnd,
291 ]);
292 }
293}