From 4414ae4f0f65a0f1b932f75cdb1370c758c0ecee Mon Sep 17 00:00:00 2001 From: sharks Date: Mon, 16 Apr 2018 19:25:22 -0500 Subject: [PATCH] direct serialize/deserialize from string/to string --- src/ipv4.rs | 25 ++++++++++++++++++++++++- src/ipv6.rs | 25 ++++++++++++++++++++++++- src/lib.rs | 25 ++++++++++++++++++++++++- tests/test_json.rs | 6 +++--- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/ipv4.rs b/src/ipv4.rs index 1ad4e1c..b15f7aa 100644 --- a/src/ipv4.rs +++ b/src/ipv4.rs @@ -2,18 +2,41 @@ use std::fmt; use std::net::Ipv4Addr; use std::str::FromStr; +#[cfg(feature = "with-serde")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + use common::{cidr_parts, parse_addr, parse_prefix, IpNetworkError}; const IPV4_BITS: u8 = 32; /// Represents a network range where the IP addresses are of v4 -#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Ipv4Network { addr: Ipv4Addr, prefix: u8, } +#[cfg(feature = "with-serde")] +impl<'de> Deserialize<'de> for Ipv4Network { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = <&str>::deserialize(deserializer)?; + Ipv4Network::from_str(s).map_err(de::Error::custom) + } +} + +#[cfg(feature = "with-serde")] +impl Serialize for Ipv4Network { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + impl Ipv4Network { /// Constructs a new `Ipv4Network` from any `Ipv4Addr` and a prefix denoting the network size. /// If the prefix is larger than 32 this will return an `IpNetworkError::InvalidPrefix`. diff --git a/src/ipv6.rs b/src/ipv6.rs index edd53a0..fa57116 100644 --- a/src/ipv6.rs +++ b/src/ipv6.rs @@ -3,19 +3,42 @@ use std::fmt; use std::net::Ipv6Addr; use std::str::FromStr; +#[cfg(feature = "with-serde")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + use common::{cidr_parts, parse_prefix, IpNetworkError}; const IPV6_BITS: u8 = 128; const IPV6_SEGMENT_BITS: u8 = 16; /// Represents a network range where the IP addresses are of v6 -#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Ipv6Network { addr: Ipv6Addr, prefix: u8, } +#[cfg(feature = "with-serde")] +impl<'de> Deserialize<'de> for Ipv6Network { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = <&str>::deserialize(deserializer)?; + Ipv6Network::from_str(s).map_err(de::Error::custom) + } +} + +#[cfg(feature = "with-serde")] +impl Serialize for Ipv6Network { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + impl Ipv6Network { /// Constructs a new `Ipv6Network` from any `Ipv6Addr` and a prefix denoting the network size. /// If the prefix is larger than 128 this will return an `IpNetworkError::InvalidPrefix`. diff --git a/src/lib.rs b/src/lib.rs index 3722773..5fa5f27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,9 @@ extern crate serde; #[macro_use] extern crate serde_derive; +#[cfg(feature = "with-serde")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + use std::fmt; use std::net::IpAddr; @@ -29,13 +32,33 @@ pub use ipv6::{ipv6_mask_to_prefix, Ipv6Network}; /// Represents a generic network range. This type can have two variants: /// the v4 and the v6 case. -#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum IpNetwork { V4(Ipv4Network), V6(Ipv6Network), } +#[cfg(feature = "with-serde")] +impl<'de> Deserialize<'de> for IpNetwork { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = <&str>::deserialize(deserializer)?; + IpNetwork::from_str(s).map_err(de::Error::custom) + } +} + +#[cfg(feature = "with-serde")] +impl Serialize for IpNetwork { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + impl IpNetwork { /// Constructs a new `IpNetwork` from a given `IpAddr` and a prefix denoting the /// network size. If the prefix is larger than 32 (for IPv4) or 128 (for IPv6), this diff --git a/tests/test_json.rs b/tests/test_json.rs index 5876cad..383fc28 100644 --- a/tests/test_json.rs +++ b/tests/test_json.rs @@ -17,7 +17,7 @@ mod tests { #[cfg(feature = "with-serde")] #[test] fn test_ipv4_json() { - let json_string = r#"{"ipnetwork":{"addr":"127.1.0.0","prefix":24}}"#; + let json_string = r#"{"ipnetwork":"127.1.0.0/24"}"#; #[derive(Serialize, Deserialize)] struct MyStruct { @@ -35,7 +35,7 @@ mod tests { #[cfg(feature = "with-serde")] #[test] fn test_ipv6_json() { - let json_string = r#"{"ipnetwork":{"addr":"::1","prefix":0}}"#; + let json_string = r#"{"ipnetwork":"::1/0"}"#; #[derive(Serialize, Deserialize)] struct MyStruct { @@ -56,7 +56,7 @@ mod tests { #[cfg(feature = "with-serde")] #[test] fn test_ipnetwork_json() { - let json_string = r#"{"ipnetwork":[{"V4":{"addr":"127.1.0.0","prefix":24}},{"V6":{"addr":"::1","prefix":0}}]}"#; + let json_string = r#"{"ipnetwork":["127.1.0.0/24","::1/0"]}"#; #[derive(Serialize, Deserialize)] struct MyStruct {