diff --git a/src/lib.rs b/src/lib.rs index 3a10954..9185354 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,6 +82,51 @@ impl Ipv4Network { (u32::from(ip) & mask) == net } + /// Returns number of possible host addresses in this `Ipv4Network`. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// use ipnetwork::Ipv4Network; + /// + /// let net = Ipv4Network::from_cidr("10.1.0.0/16").unwrap(); + /// assert_eq!(net.size(), 65536); + /// + /// let tinynet = Ipv4Network::from_cidr("0.0.0.0/32").unwrap(); + /// assert_eq!(tinynet.size(), 1); + /// ``` + pub fn size(&self) -> u64 { + let host_bits = (IPV4_BITS - self.prefix) as u32; + (2 as u64).pow(host_bits) + } + + /// Returns the `n`:th address within this network. + /// The adresses are indexed from 0 and `n` must be smaller than the size of the network. + /// + /// # Examples + /// + /// ``` + /// use std::net::Ipv4Addr; + /// use ipnetwork::Ipv4Network; + /// + /// let net = Ipv4Network::from_cidr("192.168.0.0/24").unwrap(); + /// assert_eq!(net.nth(0).unwrap(), Ipv4Addr::new(192, 168, 0, 0)); + /// assert_eq!(net.nth(15).unwrap(), Ipv4Addr::new(192, 168, 0, 15)); + /// assert!(net.nth(256).is_none()); + /// + /// let net2 = Ipv4Network::from_cidr("10.0.0.0/16").unwrap(); + /// assert_eq!(net2.nth(256).unwrap(), Ipv4Addr::new(10, 0, 1, 0)); + /// ``` + pub fn nth(&self, n: u32) -> Option { + if (n as u64) < self.size() { + let (_, net) = self.network(); + Some(Ipv4Addr::from(net + n)) + } else { + None + } + } + fn parse_addr(addr: &str) -> Result { let byte_strs = addr.split('.') .map(|b| b.parse::()) @@ -235,6 +280,45 @@ mod test { assert!(cidr.is_err()); } + #[test] + fn size_v4_24bit() { + let net = Ipv4Network::from_cidr("0/24").unwrap(); + assert_eq!(net.size(), 256); + } + + #[test] + fn size_v4_1bit() { + let net = Ipv4Network::from_cidr("0/31").unwrap(); + assert_eq!(net.size(), 2); + } + + #[test] + fn size_v4_max() { + let net = Ipv4Network::from_cidr("0/0").unwrap(); + assert_eq!(net.size(), 4_294_967_296); + } + + #[test] + fn size_v4_min() { + let net = Ipv4Network::from_cidr("0/32").unwrap(); + assert_eq!(net.size(), 1); + } + + #[test] + fn nth_v4() { + let cidr = Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), 24); + assert_eq!(cidr.nth(0).unwrap(), Ipv4Addr::new(127, 0, 0, 0)); + assert_eq!(cidr.nth(1).unwrap(), Ipv4Addr::new(127, 0, 0, 1)); + assert_eq!(cidr.nth(255).unwrap(), Ipv4Addr::new(127, 0, 0, 255)); + assert!(cidr.nth(256).is_none()); + } + + #[test] + fn nth_v4_fail() { + let cidr = Ipv4Network::new(Ipv4Addr::new(10, 0, 0, 0), 32); + assert!(cidr.nth(1).is_none()); + } + #[test] fn create_v6() { let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);