diff options
Diffstat (limited to 'vendor/ipnet/src/ipnet_serde.rs')
-rw-r--r-- | vendor/ipnet/src/ipnet_serde.rs | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/vendor/ipnet/src/ipnet_serde.rs b/vendor/ipnet/src/ipnet_serde.rs new file mode 100644 index 000000000..bbf15ac81 --- /dev/null +++ b/vendor/ipnet/src/ipnet_serde.rs @@ -0,0 +1,276 @@ +use crate::{IpNet, Ipv4Net, Ipv6Net}; +use std::fmt; +use std::net::{Ipv4Addr, Ipv6Addr}; +use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; +use serde::ser::SerializeTuple; +use serde::de::{EnumAccess, Error, VariantAccess, Visitor}; + +impl Serialize for IpNet { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where S: Serializer + { + if serializer.is_human_readable() { + match *self { + IpNet::V4(ref a) => a.serialize(serializer), + IpNet::V6(ref a) => a.serialize(serializer), + } + } else { + match *self { + IpNet::V4(ref a) => serializer.serialize_newtype_variant("IpNet", 0, "V4", a), + IpNet::V6(ref a) => serializer.serialize_newtype_variant("IpNet", 1, "V6", a), + } + } + } +} + +impl<'de> Deserialize<'de> for IpNet { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: Deserializer<'de> + { + if deserializer.is_human_readable() { + struct IpNetVisitor; + + impl<'de> Visitor<'de> for IpNetVisitor { + type Value = IpNet; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("IPv4 or IPv6 network address") + } + + fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> + where E: Error + { + s.parse().map_err(Error::custom) + } + } + + deserializer.deserialize_str(IpNetVisitor) + } else { + struct EnumVisitor; + + #[derive(Serialize, Deserialize)] + enum IpNetKind { + V4, + V6, + } + + impl<'de> Visitor<'de> for EnumVisitor { + type Value = IpNet; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("IPv4 or IPv6 network address") + } + + fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error> + where A: EnumAccess<'de> + { + match data.variant()? { + (IpNetKind::V4, v) => v.newtype_variant().map(IpNet::V4), + (IpNetKind::V6, v) => v.newtype_variant().map(IpNet::V6), + } + } + } + + deserializer.deserialize_enum("IpNet", &["V4", "V6"], EnumVisitor) + } + } +} + +impl Serialize for Ipv4Net { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where S: Serializer + { + if serializer.is_human_readable() { + serializer.collect_str(self) + } else { + let mut seq = serializer.serialize_tuple(5)?; + for octet in &self.addr().octets() { + seq.serialize_element(octet)?; + } + seq.serialize_element(&self.prefix_len())?; + seq.end() + } + } +} + +impl<'de> Deserialize<'de> for Ipv4Net { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: Deserializer<'de> + { + if deserializer.is_human_readable() { + struct IpAddrVisitor; + + impl<'de> Visitor<'de> for IpAddrVisitor { + type Value = Ipv4Net; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("IPv4 network address") + } + + fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> + where E: Error + { + s.parse().map_err(Error::custom) + } + } + + deserializer.deserialize_str(IpAddrVisitor) + } else { + let b = <[u8; 5]>::deserialize(deserializer)?; + Ipv4Net::new(Ipv4Addr::new(b[0], b[1], b[2], b[3]), b[4]).map_err(serde::de::Error::custom) + } + } +} + +impl Serialize for Ipv6Net { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where S: Serializer + { + if serializer.is_human_readable() { + serializer.collect_str(self) + } else { + let mut seq = serializer.serialize_tuple(17)?; + for octet in &self.addr().octets() { + seq.serialize_element(octet)?; + } + seq.serialize_element(&self.prefix_len())?; + seq.end() + } + } +} + +impl<'de> Deserialize<'de> for Ipv6Net { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: Deserializer<'de> + { + if deserializer.is_human_readable() { + struct IpAddrVisitor; + + impl<'de> Visitor<'de> for IpAddrVisitor { + type Value = Ipv6Net; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("IPv6 network address") + } + + fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> + where E: Error + { + s.parse().map_err(Error::custom) + } + } + + deserializer.deserialize_str(IpAddrVisitor) + } else { + let b = <[u8; 17]>::deserialize(deserializer)?; + Ipv6Net::new(Ipv6Addr::new( + ((b[0] as u16) << 8) | b[1] as u16, ((b[2] as u16) << 8) | b[3] as u16, + ((b[4] as u16) << 8) | b[5] as u16, ((b[6] as u16) << 8) | b[7] as u16, + ((b[8] as u16) << 8) | b[9] as u16, ((b[10] as u16) << 8) | b[11] as u16, + ((b[12] as u16) << 8) | b[13] as u16, ((b[14] as u16) << 8) | b[15] as u16 + ), b[16]).map_err(Error::custom) + } + } +} + +#[cfg(test)] +mod tests { + extern crate serde_test; + + use crate::{IpNet, Ipv4Net, Ipv6Net}; + use self::serde_test::{assert_tokens, Configure, Token}; + + #[test] + fn test_serialize_ipnet_v4() { + let net_str = "10.1.1.0/24"; + let net: IpNet = net_str.parse().unwrap(); + assert_tokens(&net.readable(), &[Token::Str(net_str)]); + assert_tokens(&net.compact(), &[ + Token::NewtypeVariant { name: "IpNet", variant: "V4", }, + Token::Tuple { len: 5 }, + Token::U8(10), + Token::U8(1), + Token::U8(1), + Token::U8(0), + Token::U8(24), + Token::TupleEnd, + ]); + } + + #[test] + fn test_serialize_ipnet_v6() { + let net_str = "fd00::/32"; + let net: IpNet = net_str.parse().unwrap(); + assert_tokens(&net.readable(), &[Token::Str(net_str)]); + assert_tokens(&net.compact(), &[ + Token::NewtypeVariant { name: "IpNet", variant: "V6", }, + // This is too painful, but Token::Bytes() seems to be + // an array with a length, which is not what we serialize. + Token::Tuple { len: 17 }, + Token::U8(253u8), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(32), + Token::TupleEnd, + ]); + } + + #[test] + fn test_serialize_ipv4_net() { + let net_str = "10.1.1.0/24"; + let net: Ipv4Net = net_str.parse().unwrap(); + assert_tokens(&net.readable(), &[Token::Str(net_str)]); + assert_tokens(&net.compact(), &[ + Token::Tuple { len: 5 }, + Token::U8(10), + Token::U8(1), + Token::U8(1), + Token::U8(0), + Token::U8(24), + Token::TupleEnd, + ]); + } + + #[test] + fn test_serialize_ipv6_net() { + let net_str = "fd00::/32"; + let net: Ipv6Net = net_str.parse().unwrap(); + assert_tokens(&net.readable(), &[Token::Str(net_str)]); + assert_tokens(&net.compact(), &[ + // This is too painful, but Token::Bytes() seems to be + // an array with a length, which is not what we serialize. + Token::Tuple { len: 17 }, + Token::U8(253u8), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(0), + Token::U8(32), + Token::TupleEnd, + ]); + } +} |