Merge pull request #72 from sharksforarms/master

* Default to /32 for an IP
This commit is contained in:
Abhishek Chanda
2018-04-16 00:40:14 +02:00
committed by GitHub
4 changed files with 37 additions and 8 deletions

View File

@ -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::<Vec<&str>>(); let parts = cidr.split('/').collect::<Vec<&str>>();
if parts.len() == 1 { if parts.len() == 1 {
Err(IpNetworkError::InvalidCidrFormat(format!( Ok((parts[0], None))
"CIDR must contain '/': {}",
cidr
)))
} else if parts.len() == 2 { } else if parts.len() == 2 {
Ok((parts[0], parts[1])) Ok((parts[0], Some(parts[1])))
} else { } else {
Err(IpNetworkError::InvalidCidrFormat(format!( Err(IpNetworkError::InvalidCidrFormat(format!(
"CIDR must contain a single '/': {}", "CIDR must contain a single '/': {}",

View File

@ -57,6 +57,8 @@ impl Ipv4Network {
/// use std::net::Ipv4Addr; /// use std::net::Ipv4Addr;
/// use ipnetwork::Ipv4Network; /// 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(); /// let net: Ipv4Network = "127.0.0.0/16".parse().unwrap();
/// assert_eq!(net.mask(), Ipv4Addr::new(255, 255, 0, 0)); /// assert_eq!(net.mask(), Ipv4Addr::new(255, 255, 0, 0));
/// ``` /// ```
@ -190,7 +192,10 @@ impl FromStr for Ipv4Network {
fn from_str(s: &str) -> Result<Ipv4Network, IpNetworkError> { fn from_str(s: &str) -> Result<Ipv4Network, IpNetworkError> {
let (addr_str, prefix_str) = cidr_parts(s)?; let (addr_str, prefix_str) = cidr_parts(s)?;
let addr = parse_addr(addr_str)?; 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) Ipv4Network::new(addr, prefix)
} }
} }
@ -276,6 +281,13 @@ mod test {
assert_eq!(cidr.prefix(), 32); 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] #[test]
fn parse_v4_fail_addr() { fn parse_v4_fail_addr() {
let cidr: Option<Ipv4Network> = "10.a.b/8".parse().ok(); let cidr: Option<Ipv4Network> = "10.a.b/8".parse().ok();

View File

@ -106,6 +106,8 @@ impl Ipv6Network {
/// use std::net::Ipv6Addr; /// use std::net::Ipv6Addr;
/// use ipnetwork::Ipv6Network; /// 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(); /// let net: Ipv6Network = "ff01::0/32".parse().unwrap();
/// assert_eq!(net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0)); /// 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_str, prefix_str) = cidr_parts(s)?;
let addr = Ipv6Addr::from_str(addr_str) let addr = Ipv6Addr::from_str(addr_str)
.map_err(|_| IpNetworkError::InvalidAddr(addr_str.to_string()))?; .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) Ipv6Network::new(addr, prefix)
} }
} }
@ -277,6 +282,13 @@ mod test {
assert_eq!(cidr.prefix(), 64); 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] #[test]
fn parse_v6_fail_addr() { fn parse_v6_fail_addr() {
let cidr: Option<Ipv6Network> = "2001::1::/8".parse().ok(); let cidr: Option<Ipv6Network> = "2001::1::/8".parse().ok();

View File

@ -62,7 +62,10 @@ impl IpNetwork {
/// ``` /// ```
/// use ipnetwork::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::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); /// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8);
/// ``` /// ```
pub fn prefix(&self) -> u8 { pub fn prefix(&self) -> u8 {
@ -80,8 +83,13 @@ impl IpNetwork {
/// use ipnetwork::IpNetwork; /// use ipnetwork::IpNetwork;
/// use std::net::{Ipv4Addr, Ipv6Addr}; /// 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(); /// let v4_net: IpNetwork = "10.9.0.32/16".parse().unwrap();
/// assert_eq!(v4_net.mask(), Ipv4Addr::new(255, 255, 0, 0)); /// 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(); /// let v6_net: IpNetwork = "ff01::0/32".parse().unwrap();
/// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0)); /// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
///``` ///```