Skip to main content

ipnet/
ipnet_serde.rs

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            // This is too painful, but Token::Bytes() seems to be
225            // an array with a length, which is not what we serialize.
226            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            // This is too painful, but Token::Bytes() seems to be
271            // an array with a length, which is not what we serialize.
272            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}