diff options
Diffstat (limited to 'vendor/ipnet/src/ipext.rs')
-rw-r--r-- | vendor/ipnet/src/ipext.rs | 964 |
1 files changed, 964 insertions, 0 deletions
diff --git a/vendor/ipnet/src/ipext.rs b/vendor/ipnet/src/ipext.rs new file mode 100644 index 000000000..aff793086 --- /dev/null +++ b/vendor/ipnet/src/ipext.rs @@ -0,0 +1,964 @@ +//! 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<RHS = Self> { + 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<RHS = Self> { + 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<RHS = Self> { + 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<RHS = Self> { + 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<IpAddr>>(), vec![ +/// "10.0.0.0".parse::<IpAddr>().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<IpAddr>>(), vec![ +/// "fd00::0".parse::<IpAddr>().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<Ipv4Addr>>(), vec![ +/// "10.0.0.0".parse::<Ipv4Addr>().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<Ipv6Addr>>(), vec![ +/// "fd00::".parse::<Ipv6Addr>().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<Ipv4AddrRange> for IpAddrRange { + fn from(i: Ipv4AddrRange) -> IpAddrRange { + IpAddrRange::V4(i) + } +} + +impl From<Ipv6AddrRange> 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<Self::Item> { + 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<Self::Item> { + match self { + IpAddrRange::V4(a) => a.last().map(IpAddr::V4), + IpAddrRange::V6(a) => a.last().map(IpAddr::V6), + } + } + + fn max(self) -> Option<Self::Item> { + match self { + IpAddrRange::V4(a) => Iterator::max(a).map(IpAddr::V4), + IpAddrRange::V6(a) => Iterator::max(a).map(IpAddr::V6), + } + } + + fn min(self) -> Option<Self::Item> { + 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<Self::Item> { + 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<usize>) { + 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<Self::Item> { + 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<Self::Item> { + match self.start.partial_cmp(&self.end) { + Some(Less) | Some(Equal) => Some(self.end), + _ => None, + } + } + + fn max(self) -> Option<Self::Item> { + self.last() + } + + fn min(self) -> Option<Self::Item> { + match self.start.partial_cmp(&self.end) { + Some(Less) | Some(Equal) => Some(self.start), + _ => None + } + } + + fn nth(&mut self, n: usize) -> Option<Self::Item> { + 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<usize>) { + 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<Self::Item> { + 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<Self::Item> { + match self.start.partial_cmp(&self.end) { + Some(Less) | Some(Equal) => Some(self.end), + _ => None, + } + } + + fn max(self) -> Option<Self::Item> { + self.last() + } + + fn min(self) -> Option<Self::Item> { + match self.start.partial_cmp(&self.end) { + Some(Less) | Some(Equal) => Some(self.start), + _ => None + } + } + + fn nth(&mut self, n: usize) -> Option<Self::Item> { + 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<usize>) { + 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<Self::Item> { + 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<Self::Item> { + 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<Self::Item> { + 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<Self::Item> { + 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<Self::Item> { + 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<Self::Item> { + 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>>(), 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::<Vec<_>>(); + v.reverse(); + assert_eq!(v, i.rev().collect::<Vec<_>>()); + + 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>>(), 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>>(), 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::<Vec<_>>(); + v.reverse(); + assert_eq!(v, i.rev().collect::<Vec<_>>()); + + 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>>(), 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>>(), 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::<Vec<_>>(); + v.reverse(); + assert_eq!(v, i.rev().collect::<Vec<_>>()); + + 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>>(), 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>>(), 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::<Vec<_>>(); + v.reverse(); + assert_eq!(v, i.rev().collect::<Vec<_>>()); + + 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>>(), 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); + } +} |