//! Extensions to the standard IP address types for common operations. //! //! The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend //! the `Ipv4Addr` and `Ipv6Addr` types with methods to perform these //! operations. use std::cmp::Ordering::{Less, Equal}; use std::iter::{FusedIterator, DoubleEndedIterator}; use std::mem; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// Provides a `saturating_add()` method for `Ipv4Addr` and `Ipv6Addr`. /// /// Adding an integer to an IP address returns the modified IP address. /// A `u32` may added to an IPv4 address and a `u128` may be added to /// an IPv6 address. /// /// # Examples /// /// ``` /// use std::net::{Ipv4Addr, Ipv6Addr}; /// use ipnet::IpAdd; /// /// let ip0: Ipv4Addr = "192.168.0.0".parse().unwrap(); /// let ip1: Ipv4Addr = "192.168.0.5".parse().unwrap(); /// let ip2: Ipv4Addr = "255.255.255.254".parse().unwrap(); /// let max: Ipv4Addr = "255.255.255.255".parse().unwrap(); /// /// assert_eq!(ip0.saturating_add(5), ip1); /// assert_eq!(ip2.saturating_add(1), max); /// assert_eq!(ip2.saturating_add(5), max); /// /// let ip0: Ipv6Addr = "fd00::".parse().unwrap(); /// let ip1: Ipv6Addr = "fd00::5".parse().unwrap(); /// let ip2: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe".parse().unwrap(); /// let max: Ipv6Addr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap(); /// /// assert_eq!(ip0.saturating_add(5), ip1); /// assert_eq!(ip2.saturating_add(1), max); /// assert_eq!(ip2.saturating_add(5), max); /// ``` pub trait IpAdd { type Output; fn saturating_add(self, rhs: RHS) -> Self::Output; } /// Provides a `saturating_sub()` method for `Ipv4Addr` and `Ipv6Addr`. /// /// Subtracting an integer from an IP address returns the modified IP /// address. A `u32` may be subtracted from an IPv4 address and a `u128` /// may be subtracted from an IPv6 address. /// /// Subtracting an IP address from another IP address of the same type /// returns an integer of the appropriate width. A `u32` for IPv4 and a /// `u128` for IPv6. Subtracting IP addresses is useful for getting /// the range between two IP addresses. /// /// # Examples /// /// ``` /// use std::net::{Ipv4Addr, Ipv6Addr}; /// use ipnet::IpSub; /// /// let min: Ipv4Addr = "0.0.0.0".parse().unwrap(); /// let ip1: Ipv4Addr = "192.168.1.5".parse().unwrap(); /// let ip2: Ipv4Addr = "192.168.1.100".parse().unwrap(); /// /// assert_eq!(min.saturating_sub(ip1), 0); /// assert_eq!(ip2.saturating_sub(ip1), 95); /// assert_eq!(min.saturating_sub(5), min); /// assert_eq!(ip2.saturating_sub(95), ip1); /// /// let min: Ipv6Addr = "::".parse().unwrap(); /// let ip1: Ipv6Addr = "fd00::5".parse().unwrap(); /// let ip2: Ipv6Addr = "fd00::64".parse().unwrap(); /// /// assert_eq!(min.saturating_sub(ip1), 0); /// assert_eq!(ip2.saturating_sub(ip1), 95); /// assert_eq!(min.saturating_sub(5u128), min); /// assert_eq!(ip2.saturating_sub(95u128), ip1); /// ``` pub trait IpSub { type Output; fn saturating_sub(self, rhs: RHS) -> Self::Output; } /// Provides a `bitand()` method for `Ipv4Addr` and `Ipv6Addr`. /// /// # Examples /// /// ``` /// use std::net::{Ipv4Addr, Ipv6Addr}; /// use ipnet::IpBitAnd; /// /// let ip: Ipv4Addr = "192.168.1.1".parse().unwrap(); /// let mask: Ipv4Addr = "255.255.0.0".parse().unwrap(); /// let res: Ipv4Addr = "192.168.0.0".parse().unwrap(); /// /// assert_eq!(ip.bitand(mask), res); /// assert_eq!(ip.bitand(0xffff0000), res); /// /// let ip: Ipv6Addr = "fd00:1234::1".parse().unwrap(); /// let mask: Ipv6Addr = "ffff::".parse().unwrap(); /// let res: Ipv6Addr = "fd00::".parse().unwrap(); /// /// assert_eq!(ip.bitand(mask), res); /// assert_eq!(ip.bitand(0xffff_0000_0000_0000_0000_0000_0000_0000u128), res); /// ``` pub trait IpBitAnd { type Output; fn bitand(self, rhs: RHS) -> Self::Output; } /// Provides a `bitor()` method for `Ipv4Addr` and `Ipv6Addr`. /// /// # Examples /// /// ``` /// use std::net::{Ipv4Addr, Ipv6Addr}; /// use ipnet::IpBitOr; /// /// let ip: Ipv4Addr = "10.1.1.1".parse().unwrap(); /// let mask: Ipv4Addr = "0.0.0.255".parse().unwrap(); /// let res: Ipv4Addr = "10.1.1.255".parse().unwrap(); /// /// assert_eq!(ip.bitor(mask), res); /// assert_eq!(ip.bitor(0x000000ff), res); /// /// let ip: Ipv6Addr = "fd00::1".parse().unwrap(); /// let mask: Ipv6Addr = "::ffff:ffff".parse().unwrap(); /// let res: Ipv6Addr = "fd00::ffff:ffff".parse().unwrap(); /// /// assert_eq!(ip.bitor(mask), res); /// assert_eq!(ip.bitor(u128::from(0xffffffffu32)), res); /// ``` pub trait IpBitOr { type Output; fn bitor(self, rhs: RHS) -> Self::Output; } macro_rules! ip_add_impl { ($lhs:ty, $rhs:ty, $output:ty, $inner:ty) => ( impl IpAdd<$rhs> for $lhs { type Output = $output; fn saturating_add(self, rhs: $rhs) -> $output { let lhs: $inner = self.into(); let rhs: $inner = rhs.into(); (lhs.saturating_add(rhs.into())).into() } } ) } macro_rules! ip_sub_impl { ($lhs:ty, $rhs:ty, $output:ty, $inner:ty) => ( impl IpSub<$rhs> for $lhs { type Output = $output; fn saturating_sub(self, rhs: $rhs) -> $output { let lhs: $inner = self.into(); let rhs: $inner = rhs.into(); (lhs.saturating_sub(rhs.into())).into() } } ) } ip_add_impl!(Ipv4Addr, u32, Ipv4Addr, u32); ip_add_impl!(Ipv6Addr, u128, Ipv6Addr, u128); ip_sub_impl!(Ipv4Addr, Ipv4Addr, u32, u32); ip_sub_impl!(Ipv4Addr, u32, Ipv4Addr, u32); ip_sub_impl!(Ipv6Addr, Ipv6Addr, u128, u128); ip_sub_impl!(Ipv6Addr, u128, Ipv6Addr, u128); macro_rules! ip_bitops_impl { ($(($lhs:ty, $rhs:ty, $t:ty),)*) => { $( impl IpBitAnd<$rhs> for $lhs { type Output = $lhs; fn bitand(self, rhs: $rhs) -> $lhs { let lhs: $t = self.into(); let rhs: $t = rhs.into(); (lhs & rhs).into() } } impl IpBitOr<$rhs> for $lhs { type Output = $lhs; fn bitor(self, rhs: $rhs) -> $lhs { let lhs: $t = self.into(); let rhs: $t = rhs.into(); (lhs | rhs).into() } } )* } } ip_bitops_impl! { (Ipv4Addr, Ipv4Addr, u32), (Ipv4Addr, u32, u32), (Ipv6Addr, Ipv6Addr, u128), (Ipv6Addr, u128, u128), } // A barebones copy of the current unstable Step trait used by the // IpAddrRange, Ipv4AddrRange, and Ipv6AddrRange types below, and the // Subnets types in ipnet. pub trait IpStep { fn replace_one(&mut self) -> Self; fn replace_zero(&mut self) -> Self; fn add_one(&self) -> Self; fn sub_one(&self) -> Self; } impl IpStep for Ipv4Addr { fn replace_one(&mut self) -> Self { mem::replace(self, Ipv4Addr::new(0, 0, 0, 1)) } fn replace_zero(&mut self) -> Self { mem::replace(self, Ipv4Addr::new(0, 0, 0, 0)) } fn add_one(&self) -> Self { self.saturating_add(1) } fn sub_one(&self) -> Self { self.saturating_sub(1) } } impl IpStep for Ipv6Addr { fn replace_one(&mut self) -> Self { mem::replace(self, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)) } fn replace_zero(&mut self) -> Self { mem::replace(self, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)) } fn add_one(&self) -> Self { self.saturating_add(1) } fn sub_one(&self) -> Self { self.saturating_sub(1) } } /// An `Iterator` over a range of IP addresses, either IPv4 or IPv6. /// /// # Examples /// /// ``` /// use std::net::IpAddr; /// use ipnet::{IpAddrRange, Ipv4AddrRange, Ipv6AddrRange}; /// /// let hosts = IpAddrRange::from(Ipv4AddrRange::new( /// "10.0.0.0".parse().unwrap(), /// "10.0.0.3".parse().unwrap(), /// )); /// /// assert_eq!(hosts.collect::>(), vec![ /// "10.0.0.0".parse::().unwrap(), /// "10.0.0.1".parse().unwrap(), /// "10.0.0.2".parse().unwrap(), /// "10.0.0.3".parse().unwrap(), /// ]); /// /// let hosts = IpAddrRange::from(Ipv6AddrRange::new( /// "fd00::".parse().unwrap(), /// "fd00::3".parse().unwrap(), /// )); /// /// assert_eq!(hosts.collect::>(), vec![ /// "fd00::0".parse::().unwrap(), /// "fd00::1".parse().unwrap(), /// "fd00::2".parse().unwrap(), /// "fd00::3".parse().unwrap(), /// ]); /// ``` #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub enum IpAddrRange { V4(Ipv4AddrRange), V6(Ipv6AddrRange), } /// An `Iterator` over a range of IPv4 addresses. /// /// # Examples /// /// ``` /// use std::net::Ipv4Addr; /// use ipnet::Ipv4AddrRange; /// /// let hosts = Ipv4AddrRange::new( /// "10.0.0.0".parse().unwrap(), /// "10.0.0.3".parse().unwrap(), /// ); /// /// assert_eq!(hosts.collect::>(), vec![ /// "10.0.0.0".parse::().unwrap(), /// "10.0.0.1".parse().unwrap(), /// "10.0.0.2".parse().unwrap(), /// "10.0.0.3".parse().unwrap(), /// ]); /// ``` #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub struct Ipv4AddrRange { start: Ipv4Addr, end: Ipv4Addr, } /// An `Iterator` over a range of IPv6 addresses. /// /// # Examples /// /// ``` /// use std::net::Ipv6Addr; /// use ipnet::Ipv6AddrRange; /// /// let hosts = Ipv6AddrRange::new( /// "fd00::".parse().unwrap(), /// "fd00::3".parse().unwrap(), /// ); /// /// assert_eq!(hosts.collect::>(), vec![ /// "fd00::".parse::().unwrap(), /// "fd00::1".parse().unwrap(), /// "fd00::2".parse().unwrap(), /// "fd00::3".parse().unwrap(), /// ]); /// ``` #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub struct Ipv6AddrRange { start: Ipv6Addr, end: Ipv6Addr, } impl From for IpAddrRange { fn from(i: Ipv4AddrRange) -> IpAddrRange { IpAddrRange::V4(i) } } impl From for IpAddrRange { fn from(i: Ipv6AddrRange) -> IpAddrRange { IpAddrRange::V6(i) } } impl Ipv4AddrRange { pub fn new(start: Ipv4Addr, end: Ipv4Addr) -> Self { Ipv4AddrRange { start: start, end: end, } } /// Counts the number of Ipv4Addr in this range. /// This method will never overflow or panic. fn count_u64(&self) -> u64 { match self.start.partial_cmp(&self.end) { Some(Less) => { let count: u32 = self.end.saturating_sub(self.start); let count = count as u64 + 1; // Never overflows count }, Some(Equal) => 1, _ => 0, } } } impl Ipv6AddrRange { pub fn new(start: Ipv6Addr, end: Ipv6Addr) -> Self { Ipv6AddrRange { start: start, end: end, } } /// Counts the number of Ipv6Addr in this range. /// This method may overflow or panic if start /// is 0 and end is u128::MAX fn count_u128(&self) -> u128 { match self.start.partial_cmp(&self.end) { Some(Less) => { let count = self.end.saturating_sub(self.start); // May overflow or panic count + 1 }, Some(Equal) => 1, _ => 0, } } /// True only if count_u128 does not overflow fn can_count_u128(&self) -> bool { self.start != Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0) || self.end != Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff) } } impl Iterator for IpAddrRange { type Item = IpAddr; fn next(&mut self) -> Option { match *self { IpAddrRange::V4(ref mut a) => a.next().map(IpAddr::V4), IpAddrRange::V6(ref mut a) => a.next().map(IpAddr::V6), } } fn count(self) -> usize { match self { IpAddrRange::V4(a) => a.count(), IpAddrRange::V6(a) => a.count(), } } fn last(self) -> Option { match self { IpAddrRange::V4(a) => a.last().map(IpAddr::V4), IpAddrRange::V6(a) => a.last().map(IpAddr::V6), } } fn max(self) -> Option { match self { IpAddrRange::V4(a) => Iterator::max(a).map(IpAddr::V4), IpAddrRange::V6(a) => Iterator::max(a).map(IpAddr::V6), } } fn min(self) -> Option { match self { IpAddrRange::V4(a) => Iterator::min(a).map(IpAddr::V4), IpAddrRange::V6(a) => Iterator::min(a).map(IpAddr::V6), } } fn nth(&mut self, n: usize) -> Option { match *self { IpAddrRange::V4(ref mut a) => a.nth(n).map(IpAddr::V4), IpAddrRange::V6(ref mut a) => a.nth(n).map(IpAddr::V6), } } fn size_hint(&self) -> (usize, Option) { match *self { IpAddrRange::V4(ref a) => a.size_hint(), IpAddrRange::V6(ref a) => a.size_hint(), } } } impl Iterator for Ipv4AddrRange { type Item = Ipv4Addr; fn next(&mut self) -> Option { match self.start.partial_cmp(&self.end) { Some(Less) => { let next = self.start.add_one(); Some(mem::replace(&mut self.start, next)) }, Some(Equal) => { self.end.replace_zero(); Some(self.start.replace_one()) }, _ => None, } } #[allow(arithmetic_overflow)] fn count(self) -> usize { match self.start.partial_cmp(&self.end) { Some(Less) => { // Adding one here might overflow u32. // Instead, wait until after converted to usize let count: u32 = self.end.saturating_sub(self.start); // usize might only be 16 bits, // so need to explicitly check for overflow. // 'usize::MAX as u32' is okay here - if usize is 64 bits, // value truncates to u32::MAX if count <= std::usize::MAX as u32 { count as usize + 1 // count overflows usize } else { // emulate standard overflow/panic behavior std::usize::MAX + 2 + count as usize } }, Some(Equal) => 1, _ => 0 } } fn last(self) -> Option { match self.start.partial_cmp(&self.end) { Some(Less) | Some(Equal) => Some(self.end), _ => None, } } fn max(self) -> Option { self.last() } fn min(self) -> Option { match self.start.partial_cmp(&self.end) { Some(Less) | Some(Equal) => Some(self.start), _ => None } } fn nth(&mut self, n: usize) -> Option { let n = n as u64; let count = self.count_u64(); if n >= count { self.end.replace_zero(); self.start.replace_one(); None } else if n == count - 1 { self.start.replace_one(); Some(self.end.replace_zero()) } else { let nth = self.start.saturating_add(n as u32); self.start = nth.add_one(); Some(nth) } } fn size_hint(&self) -> (usize, Option) { let count = self.count_u64(); if count > std::usize::MAX as u64 { (std::usize::MAX, None) } else { let count = count as usize; (count, Some(count)) } } } impl Iterator for Ipv6AddrRange { type Item = Ipv6Addr; fn next(&mut self) -> Option { match self.start.partial_cmp(&self.end) { Some(Less) => { let next = self.start.add_one(); Some(mem::replace(&mut self.start, next)) }, Some(Equal) => { self.end.replace_zero(); Some(self.start.replace_one()) }, _ => None, } } #[allow(arithmetic_overflow)] fn count(self) -> usize { let count = self.count_u128(); // count fits in usize if count <= std::usize::MAX as u128 { count as usize // count does not fit in usize } else { // emulate standard overflow/panic behavior std::usize::MAX + 1 + count as usize } } fn last(self) -> Option { match self.start.partial_cmp(&self.end) { Some(Less) | Some(Equal) => Some(self.end), _ => None, } } fn max(self) -> Option { self.last() } fn min(self) -> Option { match self.start.partial_cmp(&self.end) { Some(Less) | Some(Equal) => Some(self.start), _ => None } } fn nth(&mut self, n: usize) -> Option { let n = n as u128; if self.can_count_u128() { let count = self.count_u128(); if n >= count { self.end.replace_zero(); self.start.replace_one(); None } else if n == count - 1 { self.start.replace_one(); Some(self.end.replace_zero()) } else { let nth = self.start.saturating_add(n); self.start = nth.add_one(); Some(nth) } // count overflows u128; n is 64-bits at most. // therefore, n can never exceed count } else { let nth = self.start.saturating_add(n); self.start = nth.add_one(); Some(nth) } } fn size_hint(&self) -> (usize, Option) { if self.can_count_u128() { let count = self.count_u128(); if count > std::usize::MAX as u128 { (std::usize::MAX, None) } else { let count = count as usize; (count, Some(count)) } } else { (std::usize::MAX, None) } } } impl DoubleEndedIterator for IpAddrRange { fn next_back(&mut self) -> Option { match *self { IpAddrRange::V4(ref mut a) => a.next_back().map(IpAddr::V4), IpAddrRange::V6(ref mut a) => a.next_back().map(IpAddr::V6), } } fn nth_back(&mut self, n: usize) -> Option { match *self { IpAddrRange::V4(ref mut a) => a.nth_back(n).map(IpAddr::V4), IpAddrRange::V6(ref mut a) => a.nth_back(n).map(IpAddr::V6), } } } impl DoubleEndedIterator for Ipv4AddrRange { fn next_back(&mut self) -> Option { match self.start.partial_cmp(&self.end) { Some(Less) => { let next_back = self.end.sub_one(); Some(mem::replace(&mut self.end, next_back)) }, Some(Equal) => { self.end.replace_zero(); Some(self.start.replace_one()) }, _ => None } } fn nth_back(&mut self, n: usize) -> Option { let n = n as u64; let count = self.count_u64(); if n >= count { self.end.replace_zero(); self.start.replace_one(); None } else if n == count - 1 { self.end.replace_zero(); Some(self.start.replace_one()) } else { let nth_back = self.end.saturating_sub(n as u32); self.end = nth_back.sub_one(); Some(nth_back) } } } impl DoubleEndedIterator for Ipv6AddrRange { fn next_back(&mut self) -> Option { match self.start.partial_cmp(&self.end) { Some(Less) => { let next_back = self.end.sub_one(); Some(mem::replace(&mut self.end, next_back)) }, Some(Equal) => { self.end.replace_zero(); Some(self.start.replace_one()) }, _ => None } } fn nth_back(&mut self, n: usize) -> Option { let n = n as u128; if self.can_count_u128() { let count = self.count_u128(); if n >= count { self.end.replace_zero(); self.start.replace_one(); None } else if n == count - 1 { self.end.replace_zero(); Some(self.start.replace_one()) } else { let nth_back = self.end.saturating_sub(n); self.end = nth_back.sub_one(); Some(nth_back) } // count overflows u128; n is 64-bits at most. // therefore, n can never exceed count } else { let nth_back = self.end.saturating_sub(n); self.end = nth_back.sub_one(); Some(nth_back) } } } impl FusedIterator for IpAddrRange {} impl FusedIterator for Ipv4AddrRange {} impl FusedIterator for Ipv6AddrRange {} #[cfg(test)] mod tests { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::str::FromStr; use super::*; #[test] fn test_ipaddrrange() { // Next, Next-Back let i = Ipv4AddrRange::new( Ipv4Addr::from_str("10.0.0.0").unwrap(), Ipv4Addr::from_str("10.0.0.3").unwrap() ); assert_eq!(i.collect::>(), vec![ Ipv4Addr::from_str("10.0.0.0").unwrap(), Ipv4Addr::from_str("10.0.0.1").unwrap(), Ipv4Addr::from_str("10.0.0.2").unwrap(), Ipv4Addr::from_str("10.0.0.3").unwrap(), ]); let mut v = i.collect::>(); v.reverse(); assert_eq!(v, i.rev().collect::>()); let i = Ipv4AddrRange::new( Ipv4Addr::from_str("255.255.255.254").unwrap(), Ipv4Addr::from_str("255.255.255.255").unwrap() ); assert_eq!(i.collect::>(), vec![ Ipv4Addr::from_str("255.255.255.254").unwrap(), Ipv4Addr::from_str("255.255.255.255").unwrap(), ]); let i = Ipv6AddrRange::new( Ipv6Addr::from_str("fd00::").unwrap(), Ipv6Addr::from_str("fd00::3").unwrap(), ); assert_eq!(i.collect::>(), vec![ Ipv6Addr::from_str("fd00::").unwrap(), Ipv6Addr::from_str("fd00::1").unwrap(), Ipv6Addr::from_str("fd00::2").unwrap(), Ipv6Addr::from_str("fd00::3").unwrap(), ]); let mut v = i.collect::>(); v.reverse(); assert_eq!(v, i.rev().collect::>()); let i = Ipv6AddrRange::new( Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe").unwrap(), Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(), ); assert_eq!(i.collect::>(), vec![ Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe").unwrap(), Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(), ]); let i = IpAddrRange::from(Ipv4AddrRange::new( Ipv4Addr::from_str("10.0.0.0").unwrap(), Ipv4Addr::from_str("10.0.0.3").unwrap(), )); assert_eq!(i.collect::>(), vec![ IpAddr::from_str("10.0.0.0").unwrap(), IpAddr::from_str("10.0.0.1").unwrap(), IpAddr::from_str("10.0.0.2").unwrap(), IpAddr::from_str("10.0.0.3").unwrap(), ]); let mut v = i.collect::>(); v.reverse(); assert_eq!(v, i.rev().collect::>()); let i = IpAddrRange::from(Ipv4AddrRange::new( Ipv4Addr::from_str("255.255.255.254").unwrap(), Ipv4Addr::from_str("255.255.255.255").unwrap() )); assert_eq!(i.collect::>(), vec![ IpAddr::from_str("255.255.255.254").unwrap(), IpAddr::from_str("255.255.255.255").unwrap(), ]); let i = IpAddrRange::from(Ipv6AddrRange::new( Ipv6Addr::from_str("fd00::").unwrap(), Ipv6Addr::from_str("fd00::3").unwrap(), )); assert_eq!(i.collect::>(), vec![ IpAddr::from_str("fd00::").unwrap(), IpAddr::from_str("fd00::1").unwrap(), IpAddr::from_str("fd00::2").unwrap(), IpAddr::from_str("fd00::3").unwrap(), ]); let mut v = i.collect::>(); v.reverse(); assert_eq!(v, i.rev().collect::>()); let i = IpAddrRange::from(Ipv6AddrRange::new( Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe").unwrap(), Ipv6Addr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(), )); assert_eq!(i.collect::>(), vec![ IpAddr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe").unwrap(), IpAddr::from_str("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(), ]); // #11 (infinite iterator when start and stop are 0) let zero4 = Ipv4Addr::from_str("0.0.0.0").unwrap(); let zero6 = Ipv6Addr::from_str("::").unwrap(); let mut i = Ipv4AddrRange::new(zero4, zero4); assert_eq!(Some(zero4), i.next()); assert_eq!(None, i.next()); let mut i = Ipv6AddrRange::new(zero6, zero6); assert_eq!(Some(zero6), i.next()); assert_eq!(None, i.next()); // Count let i = Ipv4AddrRange::new( Ipv4Addr::from_str("10.0.0.0").unwrap(), Ipv4Addr::from_str("10.0.0.3").unwrap() ); assert_eq!(i.count(), 4); let i = Ipv6AddrRange::new( Ipv6Addr::from_str("fd00::").unwrap(), Ipv6Addr::from_str("fd00::3").unwrap(), ); assert_eq!(i.count(), 4); // Size Hint let i = Ipv4AddrRange::new( Ipv4Addr::from_str("10.0.0.0").unwrap(), Ipv4Addr::from_str("10.0.0.3").unwrap() ); assert_eq!(i.size_hint(), (4, Some(4))); let i = Ipv6AddrRange::new( Ipv6Addr::from_str("fd00::").unwrap(), Ipv6Addr::from_str("fd00::3").unwrap(), ); assert_eq!(i.size_hint(), (4, Some(4))); // Size Hint: a range where size clearly overflows usize let i = Ipv6AddrRange::new( Ipv6Addr::from_str("::").unwrap(), Ipv6Addr::from_str("8000::").unwrap(), ); assert_eq!(i.size_hint(), (std::usize::MAX, None)); // Min, Max, Last let i = Ipv4AddrRange::new( Ipv4Addr::from_str("10.0.0.0").unwrap(), Ipv4Addr::from_str("10.0.0.3").unwrap() ); assert_eq!(Iterator::min(i), Some(Ipv4Addr::from_str("10.0.0.0").unwrap())); assert_eq!(Iterator::max(i), Some(Ipv4Addr::from_str("10.0.0.3").unwrap())); assert_eq!(i.last(), Some(Ipv4Addr::from_str("10.0.0.3").unwrap())); let i = Ipv6AddrRange::new( Ipv6Addr::from_str("fd00::").unwrap(), Ipv6Addr::from_str("fd00::3").unwrap(), ); assert_eq!(Iterator::min(i), Some(Ipv6Addr::from_str("fd00::").unwrap())); assert_eq!(Iterator::max(i), Some(Ipv6Addr::from_str("fd00::3").unwrap())); assert_eq!(i.last(), Some(Ipv6Addr::from_str("fd00::3").unwrap())); // Nth let i = Ipv4AddrRange::new( Ipv4Addr::from_str("10.0.0.0").unwrap(), Ipv4Addr::from_str("10.0.0.3").unwrap() ); assert_eq!(i.clone().nth(0), Some(Ipv4Addr::from_str("10.0.0.0").unwrap())); assert_eq!(i.clone().nth(3), Some(Ipv4Addr::from_str("10.0.0.3").unwrap())); assert_eq!(i.clone().nth(4), None); assert_eq!(i.clone().nth(99), None); let mut i2 = i.clone(); assert_eq!(i2.nth(1), Some(Ipv4Addr::from_str("10.0.0.1").unwrap())); assert_eq!(i2.nth(1), Some(Ipv4Addr::from_str("10.0.0.3").unwrap())); assert_eq!(i2.nth(0), None); let mut i3 = i.clone(); assert_eq!(i3.nth(99), None); assert_eq!(i3.next(), None); let i = Ipv6AddrRange::new( Ipv6Addr::from_str("fd00::").unwrap(), Ipv6Addr::from_str("fd00::3").unwrap(), ); assert_eq!(i.clone().nth(0), Some(Ipv6Addr::from_str("fd00::").unwrap())); assert_eq!(i.clone().nth(3), Some(Ipv6Addr::from_str("fd00::3").unwrap())); assert_eq!(i.clone().nth(4), None); assert_eq!(i.clone().nth(99), None); let mut i2 = i.clone(); assert_eq!(i2.nth(1), Some(Ipv6Addr::from_str("fd00::1").unwrap())); assert_eq!(i2.nth(1), Some(Ipv6Addr::from_str("fd00::3").unwrap())); assert_eq!(i2.nth(0), None); let mut i3 = i.clone(); assert_eq!(i3.nth(99), None); assert_eq!(i3.next(), None); // Nth Back let i = Ipv4AddrRange::new( Ipv4Addr::from_str("10.0.0.0").unwrap(), Ipv4Addr::from_str("10.0.0.3").unwrap() ); assert_eq!(i.clone().nth_back(0), Some(Ipv4Addr::from_str("10.0.0.3").unwrap())); assert_eq!(i.clone().nth_back(3), Some(Ipv4Addr::from_str("10.0.0.0").unwrap())); assert_eq!(i.clone().nth_back(4), None); assert_eq!(i.clone().nth_back(99), None); let mut i2 = i.clone(); assert_eq!(i2.nth_back(1), Some(Ipv4Addr::from_str("10.0.0.2").unwrap())); assert_eq!(i2.nth_back(1), Some(Ipv4Addr::from_str("10.0.0.0").unwrap())); assert_eq!(i2.nth_back(0), None); let mut i3 = i.clone(); assert_eq!(i3.nth_back(99), None); assert_eq!(i3.next(), None); let i = Ipv6AddrRange::new( Ipv6Addr::from_str("fd00::").unwrap(), Ipv6Addr::from_str("fd00::3").unwrap(), ); assert_eq!(i.clone().nth_back(0), Some(Ipv6Addr::from_str("fd00::3").unwrap())); assert_eq!(i.clone().nth_back(3), Some(Ipv6Addr::from_str("fd00::").unwrap())); assert_eq!(i.clone().nth_back(4), None); assert_eq!(i.clone().nth_back(99), None); let mut i2 = i.clone(); assert_eq!(i2.nth_back(1), Some(Ipv6Addr::from_str("fd00::2").unwrap())); assert_eq!(i2.nth_back(1), Some(Ipv6Addr::from_str("fd00::").unwrap())); assert_eq!(i2.nth_back(0), None); let mut i3 = i.clone(); assert_eq!(i3.nth_back(99), None); assert_eq!(i3.next(), None); } }