diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 4d8b95f8..4db468a8 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -14,6 +14,7 @@ use std::collections::{ use collections::enum_set::{CLike, EnumSet}; use std::hash::Hash; use std::marker::PhantomData; +use std::net; use std::path; use std::rc::Rc; use std::str; @@ -740,6 +741,83 @@ map_impl!( /////////////////////////////////////////////////////////////////////////////// +#[cfg(feature = "nightly")] +impl Deserialize for net::IpAddr { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer, + { + let s = try!(String::deserialize(deserializer)); + match s.parse() { + Ok(s) => Ok(s), + Err(err) => Err(D::Error::invalid_value(&err.to_string())), + } + } +} + +impl Deserialize for net::Ipv4Addr { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer, + { + let s = try!(String::deserialize(deserializer)); + match s.parse() { + Ok(s) => Ok(s), + Err(err) => Err(D::Error::invalid_value(&err.to_string())), + } + } +} + +impl Deserialize for net::Ipv6Addr { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer, + { + let s = try!(String::deserialize(deserializer)); + match s.parse() { + Ok(s) => Ok(s), + Err(err) => Err(D::Error::invalid_value(&err.to_string())), + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +impl Deserialize for net::SocketAddr { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer, + { + let s = try!(String::deserialize(deserializer)); + match s.parse() { + Ok(s) => Ok(s), + Err(err) => Err(D::Error::invalid_value(&err.to_string())), + } + } +} + +impl Deserialize for net::SocketAddrV4 { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer, + { + let s = try!(String::deserialize(deserializer)); + match s.parse() { + Ok(s) => Ok(s), + Err(err) => Err(D::Error::invalid_value(&err.to_string())), + } + } +} + +impl Deserialize for net::SocketAddrV6 { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer, + { + let s = try!(String::deserialize(deserializer)); + match s.parse() { + Ok(s) => Ok(s), + Err(err) => Err(D::Error::invalid_value(&err.to_string())), + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + struct PathBufVisitor; impl Visitor for PathBufVisitor { diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index cc20f9b6..ac604936 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -15,6 +15,7 @@ use collections::enum_set::{CLike, EnumSet}; use std::hash::Hash; #[cfg(feature = "nightly")] use std::iter; +use std::net; #[cfg(feature = "nightly")] use std::num; #[cfg(feature = "nightly")] @@ -679,6 +680,65 @@ impl Serialize for Result where T: Serialize, E: Serialize { /////////////////////////////////////////////////////////////////////////////// +#[cfg(feature = "nightly")] +impl Serialize for net::IpAddr { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer, + { + match *self { + net::IpAddr::V4(ref addr) => addr.serialize(serializer), + net::IpAddr::V6(ref addr) => addr.serialize(serializer), + } + } +} + +impl Serialize for net::Ipv4Addr { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer, + { + self.to_string().serialize(serializer) + } +} + +impl Serialize for net::Ipv6Addr { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer, + { + self.to_string().serialize(serializer) + } +} + +/////////////////////////////////////////////////////////////////////////////// + +impl Serialize for net::SocketAddr { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer, + { + match *self { + net::SocketAddr::V4(ref addr) => addr.serialize(serializer), + net::SocketAddr::V6(ref addr) => addr.serialize(serializer), + } + } +} + +impl Serialize for net::SocketAddrV4 { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer, + { + self.to_string().serialize(serializer) + } +} + +impl Serialize for net::SocketAddrV6 { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer, + { + self.to_string().serialize(serializer) + } +} + +/////////////////////////////////////////////////////////////////////////////// + impl Serialize for path::Path { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer, diff --git a/serde_tests/tests/test_de.rs b/serde_tests/tests/test_de.rs index 568bfaea..88f6a9ad 100644 --- a/serde_tests/tests/test_de.rs +++ b/serde_tests/tests/test_de.rs @@ -1,4 +1,5 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::net; use std::path::PathBuf; use num::FromPrimitive; @@ -571,6 +572,17 @@ declare_tests! { Token::Unit, ], } + test_net_ipv4addr { + "1.2.3.4".parse::().unwrap() => vec![Token::Str("1.2.3.4")], + } + test_net_ipv6addr { + "::1".parse::().unwrap() => vec![Token::Str("::1")], + } + test_net_socketaddr { + "1.2.3.4:1234".parse::().unwrap() => vec![Token::Str("1.2.3.4:1234")], + "1.2.3.4:1234".parse::().unwrap() => vec![Token::Str("1.2.3.4:1234")], + "[::1]:1234".parse::().unwrap() => vec![Token::Str("[::1]:1234")], + } test_num_bigint { BigInt::from_i64(123).unwrap() => vec![Token::Str("123")], BigInt::from_i64(-123).unwrap() => vec![Token::Str("-123")], @@ -607,6 +619,15 @@ declare_tests! { } } +#[cfg(feature = "nightly")] +#[test] +fn test_net_ipaddr() { + assert_de_tokens( + "1.2.3.4".parse::().unwrap(), + vec![Token::Str("1.2.3.4")], + ); +} + #[test] fn test_enum_error() { assert_de_tokens_error::( diff --git a/serde_tests/tests/test_ser.rs b/serde_tests/tests/test_ser.rs index e08d8c14..bf9bd1ea 100644 --- a/serde_tests/tests/test_ser.rs +++ b/serde_tests/tests/test_ser.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::net; use std::path::{Path, PathBuf}; use std::str; @@ -266,6 +267,17 @@ declare_ser_tests! { Token::EnumMapEnd, ], } + test_net_ipv4addr { + "1.2.3.4".parse::().unwrap() => &[Token::Str("1.2.3.4")], + } + test_net_ipv6addr { + "::1".parse::().unwrap() => &[Token::Str("::1")], + } + test_net_socketaddr { + "1.2.3.4:1234".parse::().unwrap() => &[Token::Str("1.2.3.4:1234")], + "1.2.3.4:1234".parse::().unwrap() => &[Token::Str("1.2.3.4:1234")], + "[::1]:1234".parse::().unwrap() => &[Token::Str("[::1]:1234")], + } test_num_bigint { BigInt::from_i64(123).unwrap() => &[Token::Str("123")], BigInt::from_i64(-123).unwrap() => &[Token::Str("-123")], @@ -307,6 +319,15 @@ declare_ser_tests! { } } +#[cfg(feature = "nightly")] +#[test] +fn test_net_ipaddr() { + assert_ser_tokens( + "1.2.3.4".parse::().unwrap(), + &[Token::Str("1.2.3.4")], + ); +} + #[test] fn test_cannot_serialize_paths() { let path = unsafe {