diff --git a/src/common.rs b/src/common.rs index 7016990..17ac193 100644 --- a/src/common.rs +++ b/src/common.rs @@ -32,15 +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 { - Err(IpNetworkError::InvalidCidrFormat(format!( - "CIDR must contain '/': {}", - cidr - ))) + 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 76af8b4..e0fd721 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)); /// ``` @@ -190,7 +192,10 @@ 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 = match prefix_str { + Some(v) => parse_prefix(v, IPV4_BITS)?, + None => IPV4_BITS, + }; Ipv4Network::new(addr, prefix) } } @@ -276,6 +281,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 850654f..711423e 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)); /// ``` @@ -170,7 +172,10 @@ 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 = match prefix_str { + Some(v) => parse_prefix(v, IPV6_BITS)?, + None => IPV6_BITS, + }; Ipv6Network::new(addr, prefix) } } @@ -277,6 +282,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 e3b6925..21f99df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,7 +62,10 @@ 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".parse().unwrap()).prefix(), 128u8); /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8); /// ``` pub fn prefix(&self) -> u8 { @@ -80,8 +83,13 @@ 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".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)); ///```