From 746342c0afcd61ba0c65c36e9d6573d3bd63f300 Mon Sep 17 00:00:00 2001 From: sharks Date: Tue, 27 Mar 2018 20:34:07 -0500 Subject: [PATCH 1/7] Default to /32 for an IP --- src/common.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/common.rs b/src/common.rs index 7016990..6c7f346 100644 --- a/src/common.rs +++ b/src/common.rs @@ -35,10 +35,7 @@ impl Error for IpNetworkError { pub fn cidr_parts(cidr: &str) -> Result<(&str, &str), IpNetworkError> { let parts = cidr.split('/').collect::>(); if parts.len() == 1 { - Err(IpNetworkError::InvalidCidrFormat(format!( - "CIDR must contain '/': {}", - cidr - ))) + Ok((parts[0], "32")) } else if parts.len() == 2 { Ok((parts[0], parts[1])) } else { From 82fef85a0249fc266bb2ac821017e45158cd2652 Mon Sep 17 00:00:00 2001 From: sharks Date: Tue, 27 Mar 2018 20:34:12 -0500 Subject: [PATCH 2/7] Doc tests --- src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index e3b6925..f68a644 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,6 +62,7 @@ impl IpNetwork { /// ``` /// use ipnetwork::IpNetwork; /// + /// assert_eq!(IpNetwork::V4("10.9.0.1".parse().unwrap()).prefix(), 32u8); /// assert_eq!(IpNetwork::V4("10.9.0.32/16".parse().unwrap()).prefix(), 16u8); /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8); /// ``` @@ -80,6 +81,8 @@ impl IpNetwork { /// use ipnetwork::IpNetwork; /// use std::net::{Ipv4Addr, Ipv6Addr}; /// + /// let v4_net: IpNetwork = "10.9.0.1".parse().unwrap(); + /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 255, 255)); /// let v4_net: IpNetwork = "10.9.0.32/16".parse().unwrap(); /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 0, 0)); /// let v6_net: IpNetwork = "ff01::0/32".parse().unwrap(); From 5fabbc91d50a4c6926b83b2d923600071b039296 Mon Sep 17 00:00:00 2001 From: sharks Date: Tue, 27 Mar 2018 21:36:39 -0500 Subject: [PATCH 3/7] If there is no prefix, default to number of bits ipv4/32, ipv6/128 --- src/common.rs | 2 +- src/ipv4.rs | 9 ++++++++- src/ipv6.rs | 9 ++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/common.rs b/src/common.rs index 6c7f346..904e52f 100644 --- a/src/common.rs +++ b/src/common.rs @@ -35,7 +35,7 @@ impl Error for IpNetworkError { pub fn cidr_parts(cidr: &str) -> Result<(&str, &str), IpNetworkError> { let parts = cidr.split('/').collect::>(); if parts.len() == 1 { - Ok((parts[0], "32")) + Ok((parts[0], "")) } else if parts.len() == 2 { Ok((parts[0], parts[1])) } else { diff --git a/src/ipv4.rs b/src/ipv4.rs index 76af8b4..9e02141 100644 --- a/src/ipv4.rs +++ b/src/ipv4.rs @@ -190,7 +190,14 @@ impl FromStr for Ipv4Network { fn from_str(s: &str) -> Result { let (addr_str, prefix_str) = cidr_parts(s)?; let addr = parse_addr(addr_str)?; - let prefix = parse_prefix(prefix_str, IPV4_BITS)?; + let prefix = parse_prefix( + if prefix_str.is_empty() { + IPV4_BITS.to_string() + } else { + prefix_str + }, + IPV4_BITS, + )?; Ipv4Network::new(addr, prefix) } } diff --git a/src/ipv6.rs b/src/ipv6.rs index 850654f..d2818fc 100644 --- a/src/ipv6.rs +++ b/src/ipv6.rs @@ -170,7 +170,14 @@ impl FromStr for Ipv6Network { let (addr_str, prefix_str) = cidr_parts(s)?; let addr = Ipv6Addr::from_str(addr_str) .map_err(|_| IpNetworkError::InvalidAddr(addr_str.to_string()))?; - let prefix = parse_prefix(prefix_str, IPV6_BITS)?; + let prefix = parse_prefix( + if prefix_str.is_empty() { + IPV6_BITS.to_string() + } else { + prefix_str + }, + IPV6_BITS, + )?; Ipv6Network::new(addr, prefix) } } From fcdb0c6b87261728163ca9a575143e0a2b5850cf Mon Sep 17 00:00:00 2001 From: sharks Date: Tue, 27 Mar 2018 21:39:15 -0500 Subject: [PATCH 4/7] simpler way of doing it --- src/ipv4.rs | 13 +++++-------- src/ipv6.rs | 13 +++++-------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/ipv4.rs b/src/ipv4.rs index 9e02141..4ca54ad 100644 --- a/src/ipv4.rs +++ b/src/ipv4.rs @@ -190,14 +190,11 @@ impl FromStr for Ipv4Network { fn from_str(s: &str) -> Result { let (addr_str, prefix_str) = cidr_parts(s)?; let addr = parse_addr(addr_str)?; - let prefix = parse_prefix( - if prefix_str.is_empty() { - IPV4_BITS.to_string() - } else { - prefix_str - }, - IPV4_BITS, - )?; + let prefix = if prefix_str.is_empty() { + IPV4_BITS + }else { + parse_prefix(prefix_str, IPV4_BITS)? + }; Ipv4Network::new(addr, prefix) } } diff --git a/src/ipv6.rs b/src/ipv6.rs index d2818fc..c0819c9 100644 --- a/src/ipv6.rs +++ b/src/ipv6.rs @@ -170,14 +170,11 @@ impl FromStr for Ipv6Network { let (addr_str, prefix_str) = cidr_parts(s)?; let addr = Ipv6Addr::from_str(addr_str) .map_err(|_| IpNetworkError::InvalidAddr(addr_str.to_string()))?; - let prefix = parse_prefix( - if prefix_str.is_empty() { - IPV6_BITS.to_string() - } else { - prefix_str - }, - IPV6_BITS, - )?; + let prefix = if prefix_str.is_empty() { + IPV6_BITS + }else { + parse_prefix(prefix_str, IPV6_BITS)? + }; Ipv6Network::new(addr, prefix) } } From cc24cceb1affe8e13cf2c93eb07d7820a2f122e5 Mon Sep 17 00:00:00 2001 From: sharks Date: Tue, 27 Mar 2018 21:48:29 -0500 Subject: [PATCH 5/7] add test cases --- src/ipv4.rs | 9 +++++++++ src/ipv6.rs | 9 +++++++++ src/lib.rs | 5 +++++ 3 files changed, 23 insertions(+) diff --git a/src/ipv4.rs b/src/ipv4.rs index 4ca54ad..f585e07 100644 --- a/src/ipv4.rs +++ b/src/ipv4.rs @@ -57,6 +57,8 @@ impl Ipv4Network { /// use std::net::Ipv4Addr; /// use ipnetwork::Ipv4Network; /// + /// let net: Ipv4Network = "127.0.0.0".parse().unwrap(); + /// assert_eq!(net.mask(), Ipv4Addr::new(255, 255, 255, 255)); /// let net: Ipv4Network = "127.0.0.0/16".parse().unwrap(); /// assert_eq!(net.mask(), Ipv4Addr::new(255, 255, 0, 0)); /// ``` @@ -280,6 +282,13 @@ mod test { assert_eq!(cidr.prefix(), 32); } + #[test] + fn parse_v4_noprefix() { + let cidr: Ipv4Network = "127.0.0.0".parse().unwrap(); + assert_eq!(cidr.ip(), Ipv4Addr::new(127, 0, 0, 0)); + assert_eq!(cidr.prefix(), 32); + } + #[test] fn parse_v4_fail_addr() { let cidr: Option = "10.a.b/8".parse().ok(); diff --git a/src/ipv6.rs b/src/ipv6.rs index c0819c9..6825652 100644 --- a/src/ipv6.rs +++ b/src/ipv6.rs @@ -106,6 +106,8 @@ impl Ipv6Network { /// use std::net::Ipv6Addr; /// use ipnetwork::Ipv6Network; /// + /// let net: Ipv6Network = "ff01::0".parse().unwrap(); + /// assert_eq!(net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff)); /// let net: Ipv6Network = "ff01::0/32".parse().unwrap(); /// assert_eq!(net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0)); /// ``` @@ -281,6 +283,13 @@ mod test { assert_eq!(cidr.prefix(), 64); } + #[test] + fn parse_v6_noprefix() { + let cidr: Ipv6Network = "::1".parse().unwrap(); + assert_eq!(cidr.ip(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + assert_eq!(cidr.prefix(), 128); + } + #[test] fn parse_v6_fail_addr() { let cidr: Option = "2001::1::/8".parse().ok(); diff --git a/src/lib.rs b/src/lib.rs index f68a644..21f99df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,8 @@ impl IpNetwork { /// /// assert_eq!(IpNetwork::V4("10.9.0.1".parse().unwrap()).prefix(), 32u8); /// assert_eq!(IpNetwork::V4("10.9.0.32/16".parse().unwrap()).prefix(), 16u8); + /// + /// assert_eq!(IpNetwork::V6("ff01::0".parse().unwrap()).prefix(), 128u8); /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8); /// ``` pub fn prefix(&self) -> u8 { @@ -85,6 +87,9 @@ impl IpNetwork { /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 255, 255)); /// let v4_net: IpNetwork = "10.9.0.32/16".parse().unwrap(); /// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 0, 0)); + /// + /// let v6_net: IpNetwork = "ff01::0".parse().unwrap(); + /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff)); /// let v6_net: IpNetwork = "ff01::0/32".parse().unwrap(); /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0)); ///``` From 411c71e9005f4a73fb0a122dbfb68309dfd685b8 Mon Sep 17 00:00:00 2001 From: sharks Date: Tue, 27 Mar 2018 21:48:34 -0500 Subject: [PATCH 6/7] cargo fmt --- src/ipv4.rs | 2 +- src/ipv6.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ipv4.rs b/src/ipv4.rs index f585e07..c5cc660 100644 --- a/src/ipv4.rs +++ b/src/ipv4.rs @@ -194,7 +194,7 @@ impl FromStr for Ipv4Network { let addr = parse_addr(addr_str)?; let prefix = if prefix_str.is_empty() { IPV4_BITS - }else { + } else { parse_prefix(prefix_str, IPV4_BITS)? }; Ipv4Network::new(addr, prefix) diff --git a/src/ipv6.rs b/src/ipv6.rs index 6825652..cbee659 100644 --- a/src/ipv6.rs +++ b/src/ipv6.rs @@ -174,7 +174,7 @@ impl FromStr for Ipv6Network { .map_err(|_| IpNetworkError::InvalidAddr(addr_str.to_string()))?; let prefix = if prefix_str.is_empty() { IPV6_BITS - }else { + } else { parse_prefix(prefix_str, IPV6_BITS)? }; Ipv6Network::new(addr, prefix) From 72326bd96f262ab6e9490a07c6664100a43c0ea1 Mon Sep 17 00:00:00 2001 From: sharks Date: Tue, 27 Mar 2018 21:58:10 -0500 Subject: [PATCH 7/7] use an option --- src/common.rs | 6 +++--- src/ipv4.rs | 7 +++---- src/ipv6.rs | 7 +++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/common.rs b/src/common.rs index 904e52f..17ac193 100644 --- a/src/common.rs +++ b/src/common.rs @@ -32,12 +32,12 @@ impl Error for IpNetworkError { } } -pub fn cidr_parts(cidr: &str) -> Result<(&str, &str), IpNetworkError> { +pub fn cidr_parts(cidr: &str) -> Result<(&str, Option<&str>), IpNetworkError> { let parts = cidr.split('/').collect::>(); if parts.len() == 1 { - Ok((parts[0], "")) + Ok((parts[0], None)) } else if parts.len() == 2 { - Ok((parts[0], parts[1])) + Ok((parts[0], Some(parts[1]))) } else { Err(IpNetworkError::InvalidCidrFormat(format!( "CIDR must contain a single '/': {}", diff --git a/src/ipv4.rs b/src/ipv4.rs index c5cc660..e0fd721 100644 --- a/src/ipv4.rs +++ b/src/ipv4.rs @@ -192,10 +192,9 @@ impl FromStr for Ipv4Network { fn from_str(s: &str) -> Result { let (addr_str, prefix_str) = cidr_parts(s)?; let addr = parse_addr(addr_str)?; - let prefix = if prefix_str.is_empty() { - IPV4_BITS - } else { - parse_prefix(prefix_str, IPV4_BITS)? + let prefix = match prefix_str { + Some(v) => parse_prefix(v, IPV4_BITS)?, + None => IPV4_BITS, }; Ipv4Network::new(addr, prefix) } diff --git a/src/ipv6.rs b/src/ipv6.rs index cbee659..711423e 100644 --- a/src/ipv6.rs +++ b/src/ipv6.rs @@ -172,10 +172,9 @@ impl FromStr for Ipv6Network { let (addr_str, prefix_str) = cidr_parts(s)?; let addr = Ipv6Addr::from_str(addr_str) .map_err(|_| IpNetworkError::InvalidAddr(addr_str.to_string()))?; - let prefix = if prefix_str.is_empty() { - IPV6_BITS - } else { - parse_prefix(prefix_str, IPV6_BITS)? + let prefix = match prefix_str { + Some(v) => parse_prefix(v, IPV6_BITS)?, + None => IPV6_BITS, }; Ipv6Network::new(addr, prefix) }