summaryrefslogtreecommitdiffstats
path: root/vendor/ipnet/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:24 +0000
commit023939b627b7dc93b01471f7d41fb8553ddb4ffa (patch)
tree60fc59477c605c72b0a1051409062ddecc43f877 /vendor/ipnet/src
parentAdding debian version 1.72.1+dfsg1-1. (diff)
downloadrustc-023939b627b7dc93b01471f7d41fb8553ddb4ffa.tar.xz
rustc-023939b627b7dc93b01471f7d41fb8553ddb4ffa.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ipnet/src')
-rw-r--r--vendor/ipnet/src/ipext.rs964
-rw-r--r--vendor/ipnet/src/ipnet.rs1872
-rw-r--r--vendor/ipnet/src/ipnet_schemars.rs86
-rw-r--r--vendor/ipnet/src/ipnet_serde.rs276
-rw-r--r--vendor/ipnet/src/lib.rs98
-rw-r--r--vendor/ipnet/src/mask.rs128
-rw-r--r--vendor/ipnet/src/parser.rs345
7 files changed, 3769 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);
+ }
+}
diff --git a/vendor/ipnet/src/ipnet.rs b/vendor/ipnet/src/ipnet.rs
new file mode 100644
index 000000000..e190f0669
--- /dev/null
+++ b/vendor/ipnet/src/ipnet.rs
@@ -0,0 +1,1872 @@
+use std::cmp::{min, max};
+use std::cmp::Ordering::{Less, Equal};
+use std::convert::From;
+use std::error::Error;
+use std::fmt;
+use std::iter::FusedIterator;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+use std::option::Option::{Some, None};
+
+use crate::ipext::{IpAdd, IpSub, IpStep, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
+use crate::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix};
+
+/// An IP network address, either IPv4 or IPv6.
+///
+/// This enum can contain either an [`Ipv4Net`] or an [`Ipv6Net`]. A
+/// [`From`] implementation is provided to convert these into an
+/// `IpNet`.
+///
+/// # Textual representation
+///
+/// `IpNet` provides a [`FromStr`] implementation for parsing network
+/// addresses represented in CIDR notation. See [IETF RFC 4632] for the
+/// CIDR notation.
+///
+/// [`Ipv4Net`]: struct.Ipv4Net.html
+/// [`Ipv6Net`]: struct.Ipv6Net.html
+/// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
+/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
+/// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632
+///
+/// # Examples
+///
+/// ```
+/// use std::net::IpAddr;
+/// use ipnet::IpNet;
+///
+/// let net: IpNet = "10.1.1.0/24".parse().unwrap();
+/// assert_eq!(Ok(net.network()), "10.1.1.0".parse());
+///
+/// let net: IpNet = "fd00::/32".parse().unwrap();
+/// assert_eq!(Ok(net.network()), "fd00::".parse());
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub enum IpNet {
+ V4(Ipv4Net),
+ V6(Ipv6Net),
+}
+
+/// An IPv4 network address.
+///
+/// See [`IpNet`] for a type encompassing both IPv4 and IPv6 network
+/// addresses.
+///
+/// # Textual representation
+///
+/// `Ipv4Net` provides a [`FromStr`] implementation for parsing network
+/// addresses represented in CIDR notation. See [IETF RFC 4632] for the
+/// CIDR notation.
+///
+/// [`IpNet`]: enum.IpNet.html
+/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
+/// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv4Addr;
+/// use ipnet::Ipv4Net;
+///
+/// let net: Ipv4Net = "10.1.1.0/24".parse().unwrap();
+/// assert_eq!(Ok(net.network()), "10.1.1.0".parse());
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub struct Ipv4Net {
+ addr: Ipv4Addr,
+ prefix_len: u8,
+}
+
+/// An IPv6 network address.
+///
+/// See [`IpNet`] for a type encompassing both IPv4 and IPv6 network
+/// addresses.
+///
+/// # Textual representation
+///
+/// `Ipv6Net` provides a [`FromStr`] implementation for parsing network
+/// addresses represented in CIDR notation. See [IETF RFC 4632] for the
+/// CIDR notation.
+///
+/// [`IpNet`]: enum.IpNet.html
+/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
+/// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv6Addr;
+/// use ipnet::Ipv6Net;
+///
+/// let net: Ipv6Net = "fd00::/32".parse().unwrap();
+/// assert_eq!(Ok(net.network()), "fd00::".parse());
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub struct Ipv6Net {
+ addr: Ipv6Addr,
+ prefix_len: u8,
+}
+
+/// An error which can be returned when the prefix length is invalid.
+///
+/// Valid prefix lengths are 0 to 32 for IPv4 and 0 to 128 for IPv6.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct PrefixLenError;
+
+impl fmt::Display for PrefixLenError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.write_str("invalid IP prefix length")
+ }
+}
+
+impl Error for PrefixLenError {}
+
+impl IpNet {
+ /// Creates a new IP network address from an `IpAddr` and prefix
+ /// length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ /// use ipnet::{IpNet, PrefixLenError};
+ ///
+ /// let net = IpNet::new(Ipv6Addr::LOCALHOST.into(), 48);
+ /// assert!(net.is_ok());
+ ///
+ /// let bad_prefix_len = IpNet::new(Ipv6Addr::LOCALHOST.into(), 129);
+ /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
+ /// ```
+ pub fn new(ip: IpAddr, prefix_len: u8) -> Result<IpNet, PrefixLenError> {
+ Ok(match ip {
+ IpAddr::V4(a) => Ipv4Net::new(a, prefix_len)?.into(),
+ IpAddr::V6(a) => Ipv6Net::new(a, prefix_len)?.into(),
+ })
+ }
+
+ /// Creates a new IP network address from an `IpAddr` and netmask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ /// use ipnet::{IpNet, PrefixLenError};
+ ///
+ /// let net = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0000_0000_0000_0000).into());
+ /// assert!(net.is_ok());
+ ///
+ /// let bad_prefix_len = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0001_0000_0000_0000).into());
+ /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
+ /// ```
+ pub fn with_netmask(ip: IpAddr, netmask: IpAddr) -> Result<IpNet, PrefixLenError> {
+ let prefix = ip_mask_to_prefix(netmask)?;
+ Self::new(ip, prefix)
+ }
+
+ /// Returns a copy of the network with the address truncated to the
+ /// prefix length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::IpNet;
+ /// #
+ /// assert_eq!(
+ /// "192.168.12.34/16".parse::<IpNet>().unwrap().trunc(),
+ /// "192.168.0.0/16".parse().unwrap()
+ /// );
+ ///
+ /// assert_eq!(
+ /// "fd00::1:2:3:4/16".parse::<IpNet>().unwrap().trunc(),
+ /// "fd00::/16".parse().unwrap()
+ /// );
+ /// ```
+ pub fn trunc(&self) -> IpNet {
+ match *self {
+ IpNet::V4(ref a) => IpNet::V4(a.trunc()),
+ IpNet::V6(ref a) => IpNet::V6(a.trunc()),
+ }
+ }
+
+ /// Returns the address.
+ pub fn addr(&self) -> IpAddr {
+ match *self {
+ IpNet::V4(ref a) => IpAddr::V4(a.addr),
+ IpNet::V6(ref a) => IpAddr::V6(a.addr),
+ }
+ }
+
+ /// Returns the prefix length.
+ pub fn prefix_len(&self) -> u8 {
+ match *self {
+ IpNet::V4(ref a) => a.prefix_len(),
+ IpNet::V6(ref a) => a.prefix_len(),
+ }
+ }
+
+ /// Returns the maximum valid prefix length.
+ pub fn max_prefix_len(&self) -> u8 {
+ match *self {
+ IpNet::V4(ref a) => a.max_prefix_len(),
+ IpNet::V6(ref a) => a.max_prefix_len(),
+ }
+ }
+
+ /// Returns the network mask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::IpAddr;
+ /// # use ipnet::IpNet;
+ /// #
+ /// let net: IpNet = "10.1.0.0/20".parse().unwrap();
+ /// assert_eq!(Ok(net.netmask()), "255.255.240.0".parse());
+ ///
+ /// let net: IpNet = "fd00::/24".parse().unwrap();
+ /// assert_eq!(Ok(net.netmask()), "ffff:ff00::".parse());
+ /// ```
+ pub fn netmask(&self) -> IpAddr {
+ match *self {
+ IpNet::V4(ref a) => IpAddr::V4(a.netmask()),
+ IpNet::V6(ref a) => IpAddr::V6(a.netmask()),
+ }
+ }
+
+ /// Returns the host mask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::IpAddr;
+ /// # use ipnet::IpNet;
+ /// #
+ /// let net: IpNet = "10.1.0.0/20".parse().unwrap();
+ /// assert_eq!(Ok(net.hostmask()), "0.0.15.255".parse());
+ ///
+ /// let net: IpNet = "fd00::/24".parse().unwrap();
+ /// assert_eq!(Ok(net.hostmask()), "::ff:ffff:ffff:ffff:ffff:ffff:ffff".parse());
+ /// ```
+ pub fn hostmask(&self) -> IpAddr {
+ match *self {
+ IpNet::V4(ref a) => IpAddr::V4(a.hostmask()),
+ IpNet::V6(ref a) => IpAddr::V6(a.hostmask()),
+ }
+ }
+
+ /// Returns the network address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::IpAddr;
+ /// # use ipnet::IpNet;
+ /// #
+ /// let net: IpNet = "172.16.123.123/16".parse().unwrap();
+ /// assert_eq!(Ok(net.network()), "172.16.0.0".parse());
+ ///
+ /// let net: IpNet = "fd00:1234:5678::/24".parse().unwrap();
+ /// assert_eq!(Ok(net.network()), "fd00:1200::".parse());
+ /// ```
+ pub fn network(&self) -> IpAddr {
+ match *self {
+ IpNet::V4(ref a) => IpAddr::V4(a.network()),
+ IpNet::V6(ref a) => IpAddr::V6(a.network()),
+ }
+ }
+
+ /// Returns the broadcast address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::IpAddr;
+ /// # use ipnet::IpNet;
+ /// #
+ /// let net: IpNet = "172.16.0.0/22".parse().unwrap();
+ /// assert_eq!(Ok(net.broadcast()), "172.16.3.255".parse());
+ ///
+ /// let net: IpNet = "fd00:1234:5678::/24".parse().unwrap();
+ /// assert_eq!(Ok(net.broadcast()), "fd00:12ff:ffff:ffff:ffff:ffff:ffff:ffff".parse());
+ /// ```
+ pub fn broadcast(&self) -> IpAddr {
+ match *self {
+ IpNet::V4(ref a) => IpAddr::V4(a.broadcast()),
+ IpNet::V6(ref a) => IpAddr::V6(a.broadcast()),
+ }
+ }
+
+ /// Returns the `IpNet` that contains this one.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::IpNet;
+ /// #
+ /// let n1: IpNet = "172.16.1.0/24".parse().unwrap();
+ /// let n2: IpNet = "172.16.0.0/23".parse().unwrap();
+ /// let n3: IpNet = "172.16.0.0/0".parse().unwrap();
+ ///
+ /// assert_eq!(n1.supernet().unwrap(), n2);
+ /// assert_eq!(n3.supernet(), None);
+ ///
+ /// let n1: IpNet = "fd00:ff00::/24".parse().unwrap();
+ /// let n2: IpNet = "fd00:fe00::/23".parse().unwrap();
+ /// let n3: IpNet = "fd00:fe00::/0".parse().unwrap();
+ ///
+ /// assert_eq!(n1.supernet().unwrap(), n2);
+ /// assert_eq!(n3.supernet(), None);
+ /// ```
+ pub fn supernet(&self) -> Option<IpNet> {
+ match *self {
+ IpNet::V4(ref a) => a.supernet().map(IpNet::V4),
+ IpNet::V6(ref a) => a.supernet().map(IpNet::V6),
+ }
+ }
+
+ /// Returns `true` if this network and the given network are
+ /// children of the same supernet.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::IpNet;
+ /// #
+ /// let n4_1: IpNet = "10.1.0.0/24".parse().unwrap();
+ /// let n4_2: IpNet = "10.1.1.0/24".parse().unwrap();
+ /// let n4_3: IpNet = "10.1.2.0/24".parse().unwrap();
+ /// let n6_1: IpNet = "fd00::/18".parse().unwrap();
+ /// let n6_2: IpNet = "fd00:4000::/18".parse().unwrap();
+ /// let n6_3: IpNet = "fd00:8000::/18".parse().unwrap();
+ ///
+ /// assert!( n4_1.is_sibling(&n4_2));
+ /// assert!(!n4_2.is_sibling(&n4_3));
+ /// assert!( n6_1.is_sibling(&n6_2));
+ /// assert!(!n6_2.is_sibling(&n6_3));
+ /// assert!(!n4_1.is_sibling(&n6_2));
+ /// ```
+ pub fn is_sibling(&self, other: &IpNet) -> bool {
+ match (*self, *other) {
+ (IpNet::V4(ref a), IpNet::V4(ref b)) => a.is_sibling(b),
+ (IpNet::V6(ref a), IpNet::V6(ref b)) => a.is_sibling(b),
+ _ => false,
+ }
+ }
+
+ /// Return an `Iterator` over the host addresses in this network.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::IpAddr;
+ /// # use ipnet::IpNet;
+ /// #
+ /// let net: IpNet = "10.0.0.0/30".parse().unwrap();
+ /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![
+ /// "10.0.0.1".parse::<IpAddr>().unwrap(),
+ /// "10.0.0.2".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: IpNet = "10.0.0.0/31".parse().unwrap();
+ /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![
+ /// "10.0.0.0".parse::<IpAddr>().unwrap(),
+ /// "10.0.0.1".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: IpNet = "fd00::/126".parse().unwrap();
+ /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![
+ /// "fd00::".parse::<IpAddr>().unwrap(),
+ /// "fd00::1".parse().unwrap(),
+ /// "fd00::2".parse().unwrap(),
+ /// "fd00::3".parse().unwrap(),
+ /// ]);
+ /// ```
+ pub fn hosts(&self) -> IpAddrRange {
+ match *self {
+ IpNet::V4(ref a) => IpAddrRange::V4(a.hosts()),
+ IpNet::V6(ref a) => IpAddrRange::V6(a.hosts()),
+ }
+ }
+
+ /// Returns an `Iterator` over the subnets of this network with the
+ /// given prefix length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::{IpNet, PrefixLenError};
+ /// #
+ /// let net: IpNet = "10.0.0.0/24".parse().unwrap();
+ /// assert_eq!(net.subnets(26).unwrap().collect::<Vec<IpNet>>(), vec![
+ /// "10.0.0.0/26".parse::<IpNet>().unwrap(),
+ /// "10.0.0.64/26".parse().unwrap(),
+ /// "10.0.0.128/26".parse().unwrap(),
+ /// "10.0.0.192/26".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: IpNet = "fd00::/16".parse().unwrap();
+ /// assert_eq!(net.subnets(18).unwrap().collect::<Vec<IpNet>>(), vec![
+ /// "fd00::/18".parse::<IpNet>().unwrap(),
+ /// "fd00:4000::/18".parse().unwrap(),
+ /// "fd00:8000::/18".parse().unwrap(),
+ /// "fd00:c000::/18".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: IpNet = "10.0.0.0/24".parse().unwrap();
+ /// assert_eq!(net.subnets(23), Err(PrefixLenError));
+ ///
+ /// let net: IpNet = "10.0.0.0/24".parse().unwrap();
+ /// assert_eq!(net.subnets(33), Err(PrefixLenError));
+ ///
+ /// let net: IpNet = "fd00::/16".parse().unwrap();
+ /// assert_eq!(net.subnets(15), Err(PrefixLenError));
+ ///
+ /// let net: IpNet = "fd00::/16".parse().unwrap();
+ /// assert_eq!(net.subnets(129), Err(PrefixLenError));
+ /// ```
+ pub fn subnets(&self, new_prefix_len: u8) -> Result<IpSubnets, PrefixLenError> {
+ match *self {
+ IpNet::V4(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V4),
+ IpNet::V6(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V6),
+ }
+ }
+
+ /// Test if a network address contains either another network
+ /// address or an IP address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::IpAddr;
+ /// # use ipnet::IpNet;
+ /// #
+ /// let net4: IpNet = "192.168.0.0/24".parse().unwrap();
+ /// let net4_yes: IpNet = "192.168.0.0/25".parse().unwrap();
+ /// let net4_no: IpNet = "192.168.0.0/23".parse().unwrap();
+ /// let ip4_yes: IpAddr = "192.168.0.1".parse().unwrap();
+ /// let ip4_no: IpAddr = "192.168.1.0".parse().unwrap();
+ ///
+ /// assert!(net4.contains(&net4));
+ /// assert!(net4.contains(&net4_yes));
+ /// assert!(!net4.contains(&net4_no));
+ /// assert!(net4.contains(&ip4_yes));
+ /// assert!(!net4.contains(&ip4_no));
+ ///
+ ///
+ /// let net6: IpNet = "fd00::/16".parse().unwrap();
+ /// let net6_yes: IpNet = "fd00::/17".parse().unwrap();
+ /// let net6_no: IpNet = "fd00::/15".parse().unwrap();
+ /// let ip6_yes: IpAddr = "fd00::1".parse().unwrap();
+ /// let ip6_no: IpAddr = "fd01::".parse().unwrap();
+ ///
+ /// assert!(net6.contains(&net6));
+ /// assert!(net6.contains(&net6_yes));
+ /// assert!(!net6.contains(&net6_no));
+ /// assert!(net6.contains(&ip6_yes));
+ /// assert!(!net6.contains(&ip6_no));
+ ///
+ /// assert!(!net4.contains(&net6));
+ /// assert!(!net6.contains(&net4));
+ /// assert!(!net4.contains(&ip6_no));
+ /// assert!(!net6.contains(&ip4_no));
+ /// ```
+ pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
+ Contains::contains(self, other)
+ }
+
+ /// Aggregate a `Vec` of `IpNet`s and return the result as a new
+ /// `Vec`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::IpNet;
+ /// #
+ /// let nets = vec![
+ /// "10.0.0.0/24".parse::<IpNet>().unwrap(),
+ /// "10.0.1.0/24".parse().unwrap(),
+ /// "10.0.2.0/24".parse().unwrap(),
+ /// "fd00::/18".parse().unwrap(),
+ /// "fd00:4000::/18".parse().unwrap(),
+ /// "fd00:8000::/18".parse().unwrap(),
+ /// ];
+ ///
+ /// assert_eq!(IpNet::aggregate(&nets), vec![
+ /// "10.0.0.0/23".parse::<IpNet>().unwrap(),
+ /// "10.0.2.0/24".parse().unwrap(),
+ /// "fd00::/17".parse().unwrap(),
+ /// "fd00:8000::/18".parse().unwrap(),
+ /// ]);
+ /// ```
+ pub fn aggregate(networks: &Vec<IpNet>) -> Vec<IpNet> {
+ // It's 2.5x faster to split the input up and run them using the
+ // specific IPv4 and IPV6 implementations. merge_intervals() and
+ // the comparisons are much faster running over integers.
+ let mut ipv4nets: Vec<Ipv4Net> = Vec::new();
+ let mut ipv6nets: Vec<Ipv6Net> = Vec::new();
+
+ for n in networks {
+ match *n {
+ IpNet::V4(x) => ipv4nets.push(x),
+ IpNet::V6(x) => ipv6nets.push(x),
+ }
+ }
+
+ let mut res: Vec<IpNet> = Vec::new();
+ let ipv4aggs = Ipv4Net::aggregate(&ipv4nets);
+ let ipv6aggs = Ipv6Net::aggregate(&ipv6nets);
+ res.extend::<Vec<IpNet>>(ipv4aggs.into_iter().map(IpNet::V4).collect::<Vec<IpNet>>());
+ res.extend::<Vec<IpNet>>(ipv6aggs.into_iter().map(IpNet::V6).collect::<Vec<IpNet>>());
+ res
+ }
+}
+
+impl Default for IpNet {
+ fn default() -> Self {
+ Self::V4(Ipv4Net::default())
+ }
+}
+
+impl fmt::Debug for IpNet {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+impl fmt::Display for IpNet {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ IpNet::V4(ref a) => a.fmt(fmt),
+ IpNet::V6(ref a) => a.fmt(fmt),
+ }
+ }
+}
+
+impl From<Ipv4Net> for IpNet {
+ fn from(net: Ipv4Net) -> IpNet {
+ IpNet::V4(net)
+ }
+}
+
+impl From<Ipv6Net> for IpNet {
+ fn from(net: Ipv6Net) -> IpNet {
+ IpNet::V6(net)
+ }
+}
+
+impl From<IpAddr> for IpNet {
+ fn from(addr: IpAddr) -> IpNet {
+ match addr {
+ IpAddr::V4(a) => IpNet::V4(a.into()),
+ IpAddr::V6(a) => IpNet::V6(a.into()),
+ }
+ }
+}
+
+impl Ipv4Net {
+ /// Creates a new IPv4 network address from an `Ipv4Addr` and prefix
+ /// length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ /// use ipnet::{Ipv4Net, PrefixLenError};
+ ///
+ /// let net = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 24);
+ /// assert!(net.is_ok());
+ ///
+ /// let bad_prefix_len = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 33);
+ /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
+ /// ```
+ #[inline]
+ pub const fn new(ip: Ipv4Addr, prefix_len: u8) -> Result<Ipv4Net, PrefixLenError> {
+ if prefix_len > 32 {
+ return Err(PrefixLenError);
+ }
+ Ok(Ipv4Net { addr: ip, prefix_len: prefix_len })
+ }
+
+ /// Creates a new IPv4 network address from an `Ipv4Addr` and netmask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv4Addr;
+ /// use ipnet::{Ipv4Net, PrefixLenError};
+ ///
+ /// let net = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 255, 0));
+ /// assert!(net.is_ok());
+ ///
+ /// let bad_prefix_len = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 0, 1));
+ /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
+ /// ```
+ pub fn with_netmask(ip: Ipv4Addr, netmask: Ipv4Addr) -> Result<Ipv4Net, PrefixLenError> {
+ let prefix = ipv4_mask_to_prefix(netmask)?;
+ Self::new(ip, prefix)
+ }
+
+ /// Returns a copy of the network with the address truncated to the
+ /// prefix length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// assert_eq!(
+ /// "192.168.12.34/16".parse::<Ipv4Net>().unwrap().trunc(),
+ /// "192.168.0.0/16".parse().unwrap()
+ /// );
+ /// ```
+ pub fn trunc(&self) -> Ipv4Net {
+ Ipv4Net::new(self.network(), self.prefix_len).unwrap()
+ }
+
+ /// Returns the address.
+ #[inline]
+ pub const fn addr(&self) -> Ipv4Addr {
+ self.addr
+ }
+
+ /// Returns the prefix length.
+ #[inline]
+ pub const fn prefix_len(&self) -> u8 {
+ self.prefix_len
+ }
+
+ /// Returns the maximum valid prefix length.
+ #[inline]
+ pub const fn max_prefix_len(&self) -> u8 {
+ 32
+ }
+
+ /// Returns the network mask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv4Addr;
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let net: Ipv4Net = "10.1.0.0/20".parse().unwrap();
+ /// assert_eq!(Ok(net.netmask()), "255.255.240.0".parse());
+ /// ```
+ pub fn netmask(&self) -> Ipv4Addr {
+ Ipv4Addr::from(self.netmask_u32())
+ }
+
+ fn netmask_u32(&self) -> u32 {
+ u32::max_value().checked_shl(32 - self.prefix_len as u32).unwrap_or(0)
+ }
+
+ /// Returns the host mask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv4Addr;
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let net: Ipv4Net = "10.1.0.0/20".parse().unwrap();
+ /// assert_eq!(Ok(net.hostmask()), "0.0.15.255".parse());
+ /// ```
+ pub fn hostmask(&self) -> Ipv4Addr {
+ Ipv4Addr::from(self.hostmask_u32())
+ }
+
+ fn hostmask_u32(&self) -> u32 {
+ u32::max_value().checked_shr(self.prefix_len as u32).unwrap_or(0)
+ }
+
+ /// Returns the network address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv4Addr;
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let net: Ipv4Net = "172.16.123.123/16".parse().unwrap();
+ /// assert_eq!(Ok(net.network()), "172.16.0.0".parse());
+ /// ```
+ pub fn network(&self) -> Ipv4Addr {
+ Ipv4Addr::from(u32::from(self.addr) & self.netmask_u32())
+ }
+
+ /// Returns the broadcast address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv4Addr;
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let net: Ipv4Net = "172.16.0.0/22".parse().unwrap();
+ /// assert_eq!(Ok(net.broadcast()), "172.16.3.255".parse());
+ /// ```
+ pub fn broadcast(&self) -> Ipv4Addr {
+ Ipv4Addr::from(u32::from(self.addr) | self.hostmask_u32())
+ }
+
+ /// Returns the `Ipv4Net` that contains this one.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let n1: Ipv4Net = "172.16.1.0/24".parse().unwrap();
+ /// let n2: Ipv4Net = "172.16.0.0/23".parse().unwrap();
+ /// let n3: Ipv4Net = "172.16.0.0/0".parse().unwrap();
+ ///
+ /// assert_eq!(n1.supernet().unwrap(), n2);
+ /// assert_eq!(n3.supernet(), None);
+ /// ```
+ pub fn supernet(&self) -> Option<Ipv4Net> {
+ Ipv4Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok()
+ }
+
+ /// Returns `true` if this network and the given network are
+ /// children of the same supernet.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let n1: Ipv4Net = "10.1.0.0/24".parse().unwrap();
+ /// let n2: Ipv4Net = "10.1.1.0/24".parse().unwrap();
+ /// let n3: Ipv4Net = "10.1.2.0/24".parse().unwrap();
+ ///
+ /// assert!(n1.is_sibling(&n2));
+ /// assert!(!n2.is_sibling(&n3));
+ /// ```
+ pub fn is_sibling(&self, other: &Ipv4Net) -> bool {
+ self.prefix_len > 0 &&
+ self.prefix_len == other.prefix_len &&
+ self.supernet().unwrap().contains(other)
+ }
+
+ /// Return an `Iterator` over the host addresses in this network.
+ ///
+ /// If the prefix length is less than 31 both the network address
+ /// and broadcast address are excluded. These are only valid host
+ /// addresses when the prefix length is 31.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv4Addr;
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let net: Ipv4Net = "10.0.0.0/30".parse().unwrap();
+ /// assert_eq!(net.hosts().collect::<Vec<Ipv4Addr>>(), vec![
+ /// "10.0.0.1".parse::<Ipv4Addr>().unwrap(),
+ /// "10.0.0.2".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: Ipv4Net = "10.0.0.0/31".parse().unwrap();
+ /// assert_eq!(net.hosts().collect::<Vec<Ipv4Addr>>(), vec![
+ /// "10.0.0.0".parse::<Ipv4Addr>().unwrap(),
+ /// "10.0.0.1".parse().unwrap(),
+ /// ]);
+ /// ```
+ pub fn hosts(&self) -> Ipv4AddrRange {
+ let mut start = self.network();
+ let mut end = self.broadcast();
+
+ if self.prefix_len < 31 {
+ start = start.saturating_add(1);
+ end = end.saturating_sub(1);
+ }
+
+ Ipv4AddrRange::new(start, end)
+ }
+
+ /// Returns an `Iterator` over the subnets of this network with the
+ /// given prefix length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::{Ipv4Net, PrefixLenError};
+ /// #
+ /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap();
+ /// assert_eq!(net.subnets(26).unwrap().collect::<Vec<Ipv4Net>>(), vec![
+ /// "10.0.0.0/26".parse::<Ipv4Net>().unwrap(),
+ /// "10.0.0.64/26".parse().unwrap(),
+ /// "10.0.0.128/26".parse().unwrap(),
+ /// "10.0.0.192/26".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: Ipv4Net = "10.0.0.0/30".parse().unwrap();
+ /// assert_eq!(net.subnets(32).unwrap().collect::<Vec<Ipv4Net>>(), vec![
+ /// "10.0.0.0/32".parse::<Ipv4Net>().unwrap(),
+ /// "10.0.0.1/32".parse().unwrap(),
+ /// "10.0.0.2/32".parse().unwrap(),
+ /// "10.0.0.3/32".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap();
+ /// assert_eq!(net.subnets(23), Err(PrefixLenError));
+ ///
+ /// let net: Ipv4Net = "10.0.0.0/24".parse().unwrap();
+ /// assert_eq!(net.subnets(33), Err(PrefixLenError));
+ /// ```
+ pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv4Subnets, PrefixLenError> {
+ if self.prefix_len > new_prefix_len || new_prefix_len > 32 {
+ return Err(PrefixLenError);
+ }
+
+ Ok(Ipv4Subnets::new(
+ self.network(),
+ self.broadcast(),
+ new_prefix_len,
+ ))
+ }
+
+ /// Test if a network address contains either another network
+ /// address or an IP address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv4Addr;
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let net: Ipv4Net = "192.168.0.0/24".parse().unwrap();
+ /// let net_yes: Ipv4Net = "192.168.0.0/25".parse().unwrap();
+ /// let net_no: Ipv4Net = "192.168.0.0/23".parse().unwrap();
+ /// let ip_yes: Ipv4Addr = "192.168.0.1".parse().unwrap();
+ /// let ip_no: Ipv4Addr = "192.168.1.0".parse().unwrap();
+ ///
+ /// assert!(net.contains(&net));
+ /// assert!(net.contains(&net_yes));
+ /// assert!(!net.contains(&net_no));
+ /// assert!(net.contains(&ip_yes));
+ /// assert!(!net.contains(&ip_no));
+ /// ```
+ pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
+ Contains::contains(self, other)
+ }
+
+ // It is significantly faster to work on u32 than Ipv4Addr.
+ fn interval(&self) -> (u32, u32) {
+ (
+ u32::from(self.network()),
+ u32::from(self.broadcast()).saturating_add(1),
+ )
+ }
+
+ /// Aggregate a `Vec` of `Ipv4Net`s and return the result as a new
+ /// `Vec`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::Ipv4Net;
+ /// #
+ /// let nets = vec![
+ /// "10.0.0.0/24".parse::<Ipv4Net>().unwrap(),
+ /// "10.0.1.0/24".parse().unwrap(),
+ /// "10.0.2.0/24".parse().unwrap(),
+ /// ];
+ ///
+ /// assert_eq!(Ipv4Net::aggregate(&nets), vec![
+ /// "10.0.0.0/23".parse::<Ipv4Net>().unwrap(),
+ /// "10.0.2.0/24".parse().unwrap(),
+ /// ]);
+ pub fn aggregate(networks: &Vec<Ipv4Net>) -> Vec<Ipv4Net> {
+ let mut intervals: Vec<(_, _)> = networks.iter().map(|n| n.interval()).collect();
+ intervals = merge_intervals(intervals);
+ let mut res: Vec<Ipv4Net> = Vec::new();
+
+ for (start, mut end) in intervals {
+ if end != std::u32::MAX {
+ end = end.saturating_sub(1)
+ }
+ let iter = Ipv4Subnets::new(start.into(), end.into(), 0);
+ res.extend(iter);
+ }
+ res
+ }
+}
+
+impl Default for Ipv4Net {
+ fn default() -> Self {
+ Self {
+ addr: Ipv4Addr::from(0),
+ prefix_len: 0,
+ }
+ }
+}
+
+impl fmt::Debug for Ipv4Net {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+impl fmt::Display for Ipv4Net {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "{}/{}", self.addr, self.prefix_len)
+ }
+}
+
+impl From<Ipv4Addr> for Ipv4Net {
+ fn from(addr: Ipv4Addr) -> Ipv4Net {
+ Ipv4Net { addr, prefix_len: 32 }
+ }
+}
+
+impl Ipv6Net {
+ /// Creates a new IPv6 network address from an `Ipv6Addr` and prefix
+ /// length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ /// use ipnet::{Ipv6Net, PrefixLenError};
+ ///
+ /// let net = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24);
+ /// assert!(net.is_ok());
+ ///
+ /// let bad_prefix_len = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 129);
+ /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
+ /// ```
+ #[inline]
+ pub const fn new(ip: Ipv6Addr, prefix_len: u8) -> Result<Ipv6Net, PrefixLenError> {
+ if prefix_len > 128 {
+ return Err(PrefixLenError);
+ }
+ Ok(Ipv6Net { addr: ip, prefix_len: prefix_len })
+ }
+
+ /// Creates a new IPv6 network address from an `Ipv6Addr` and netmask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::Ipv6Addr;
+ /// use ipnet::{Ipv6Net, PrefixLenError};
+ ///
+ /// let net = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0000_0000_0000_0000));
+ /// assert!(net.is_ok());
+ ///
+ /// let bad_prefix_len = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0001_0000_0000_0000));
+ /// assert_eq!(bad_prefix_len, Err(PrefixLenError));
+ /// ```
+ pub fn with_netmask(ip: Ipv6Addr, netmask: Ipv6Addr) -> Result<Ipv6Net, PrefixLenError> {
+ let prefix = ipv6_mask_to_prefix(netmask)?;
+ Self::new(ip, prefix)
+ }
+
+ /// Returns a copy of the network with the address truncated to the
+ /// prefix length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// assert_eq!(
+ /// "fd00::1:2:3:4/16".parse::<Ipv6Net>().unwrap().trunc(),
+ /// "fd00::/16".parse().unwrap()
+ /// );
+ /// ```
+ pub fn trunc(&self) -> Ipv6Net {
+ Ipv6Net::new(self.network(), self.prefix_len).unwrap()
+ }
+
+ /// Returns the address.
+ #[inline]
+ pub const fn addr(&self) -> Ipv6Addr {
+ self.addr
+ }
+
+ /// Returns the prefix length.
+ #[inline]
+ pub const fn prefix_len(&self) -> u8 {
+ self.prefix_len
+ }
+
+ /// Returns the maximum valid prefix length.
+ #[inline]
+ pub const fn max_prefix_len(&self) -> u8 {
+ 128
+ }
+
+ /// Returns the network mask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv6Addr;
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let net: Ipv6Net = "fd00::/24".parse().unwrap();
+ /// assert_eq!(Ok(net.netmask()), "ffff:ff00::".parse());
+ /// ```
+ pub fn netmask(&self) -> Ipv6Addr {
+ self.netmask_u128().into()
+ }
+
+ fn netmask_u128(&self) -> u128 {
+ u128::max_value().checked_shl((128 - self.prefix_len) as u32).unwrap_or(u128::min_value())
+ }
+
+ /// Returns the host mask.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv6Addr;
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let net: Ipv6Net = "fd00::/24".parse().unwrap();
+ /// assert_eq!(Ok(net.hostmask()), "::ff:ffff:ffff:ffff:ffff:ffff:ffff".parse());
+ /// ```
+ pub fn hostmask(&self) -> Ipv6Addr {
+ self.hostmask_u128().into()
+ }
+
+ fn hostmask_u128(&self) -> u128 {
+ u128::max_value().checked_shr(self.prefix_len as u32).unwrap_or(u128::min_value())
+ }
+
+ /// Returns the network address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv6Addr;
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let net: Ipv6Net = "fd00:1234:5678::/24".parse().unwrap();
+ /// assert_eq!(Ok(net.network()), "fd00:1200::".parse());
+ /// ```
+ pub fn network(&self) -> Ipv6Addr {
+ (u128::from(self.addr) & self.netmask_u128()).into()
+ }
+
+ /// Returns the last address.
+ ///
+ /// Technically there is no such thing as a broadcast address for
+ /// IPv6. The name is used for consistency with colloquial usage.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv6Addr;
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let net: Ipv6Net = "fd00:1234:5678::/24".parse().unwrap();
+ /// assert_eq!(Ok(net.broadcast()), "fd00:12ff:ffff:ffff:ffff:ffff:ffff:ffff".parse());
+ /// ```
+ pub fn broadcast(&self) -> Ipv6Addr {
+ (u128::from(self.addr) | self.hostmask_u128()).into()
+ }
+
+ /// Returns the `Ipv6Net` that contains this one.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::str::FromStr;
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let n1: Ipv6Net = "fd00:ff00::/24".parse().unwrap();
+ /// let n2: Ipv6Net = "fd00:fe00::/23".parse().unwrap();
+ /// let n3: Ipv6Net = "fd00:fe00::/0".parse().unwrap();
+ ///
+ /// assert_eq!(n1.supernet().unwrap(), n2);
+ /// assert_eq!(n3.supernet(), None);
+ /// ```
+ pub fn supernet(&self) -> Option<Ipv6Net> {
+ Ipv6Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok()
+ }
+
+ /// Returns `true` if this network and the given network are
+ /// children of the same supernet.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let n1: Ipv6Net = "fd00::/18".parse().unwrap();
+ /// let n2: Ipv6Net = "fd00:4000::/18".parse().unwrap();
+ /// let n3: Ipv6Net = "fd00:8000::/18".parse().unwrap();
+ ///
+ /// assert!(n1.is_sibling(&n2));
+ /// assert!(!n2.is_sibling(&n3));
+ /// ```
+ pub fn is_sibling(&self, other: &Ipv6Net) -> bool {
+ self.prefix_len > 0 &&
+ self.prefix_len == other.prefix_len &&
+ self.supernet().unwrap().contains(other)
+ }
+
+ /// Return an `Iterator` over the host addresses in this network.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv6Addr;
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let net: Ipv6Net = "fd00::/126".parse().unwrap();
+ /// assert_eq!(net.hosts().collect::<Vec<Ipv6Addr>>(), vec![
+ /// "fd00::".parse::<Ipv6Addr>().unwrap(),
+ /// "fd00::1".parse().unwrap(),
+ /// "fd00::2".parse().unwrap(),
+ /// "fd00::3".parse().unwrap(),
+ /// ]);
+ /// ```
+ pub fn hosts(&self) -> Ipv6AddrRange {
+ Ipv6AddrRange::new(self.network(), self.broadcast())
+ }
+
+ /// Returns an `Iterator` over the subnets of this network with the
+ /// given prefix length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::{Ipv6Net, PrefixLenError};
+ /// #
+ /// let net: Ipv6Net = "fd00::/16".parse().unwrap();
+ /// assert_eq!(net.subnets(18).unwrap().collect::<Vec<Ipv6Net>>(), vec![
+ /// "fd00::/18".parse::<Ipv6Net>().unwrap(),
+ /// "fd00:4000::/18".parse().unwrap(),
+ /// "fd00:8000::/18".parse().unwrap(),
+ /// "fd00:c000::/18".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: Ipv6Net = "fd00::/126".parse().unwrap();
+ /// assert_eq!(net.subnets(128).unwrap().collect::<Vec<Ipv6Net>>(), vec![
+ /// "fd00::/128".parse::<Ipv6Net>().unwrap(),
+ /// "fd00::1/128".parse().unwrap(),
+ /// "fd00::2/128".parse().unwrap(),
+ /// "fd00::3/128".parse().unwrap(),
+ /// ]);
+ ///
+ /// let net: Ipv6Net = "fd00::/16".parse().unwrap();
+ /// assert_eq!(net.subnets(15), Err(PrefixLenError));
+ ///
+ /// let net: Ipv6Net = "fd00::/16".parse().unwrap();
+ /// assert_eq!(net.subnets(129), Err(PrefixLenError));
+ /// ```
+ pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv6Subnets, PrefixLenError> {
+ if self.prefix_len > new_prefix_len || new_prefix_len > 128 {
+ return Err(PrefixLenError);
+ }
+
+ Ok(Ipv6Subnets::new(
+ self.network(),
+ self.broadcast(),
+ new_prefix_len,
+ ))
+ }
+
+ /// Test if a network address contains either another network
+ /// address or an IP address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::net::Ipv6Addr;
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let net: Ipv6Net = "fd00::/16".parse().unwrap();
+ /// let net_yes: Ipv6Net = "fd00::/17".parse().unwrap();
+ /// let net_no: Ipv6Net = "fd00::/15".parse().unwrap();
+ /// let ip_yes: Ipv6Addr = "fd00::1".parse().unwrap();
+ /// let ip_no: Ipv6Addr = "fd01::".parse().unwrap();
+ ///
+ /// assert!(net.contains(&net));
+ /// assert!(net.contains(&net_yes));
+ /// assert!(!net.contains(&net_no));
+ /// assert!(net.contains(&ip_yes));
+ /// assert!(!net.contains(&ip_no));
+ /// ```
+ pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
+ Contains::contains(self, other)
+ }
+
+ // It is significantly faster to work on u128 that Ipv6Addr.
+ fn interval(&self) -> (u128, u128) {
+ (
+ u128::from(self.network()),
+ u128::from(self.broadcast()).saturating_add(1),
+ )
+ }
+
+ /// Aggregate a `Vec` of `Ipv6Net`s and return the result as a new
+ /// `Vec`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use ipnet::Ipv6Net;
+ /// #
+ /// let nets = vec![
+ /// "fd00::/18".parse::<Ipv6Net>().unwrap(),
+ /// "fd00:4000::/18".parse().unwrap(),
+ /// "fd00:8000::/18".parse().unwrap(),
+ /// ];
+ /// assert_eq!(Ipv6Net::aggregate(&nets), vec![
+ /// "fd00::/17".parse::<Ipv6Net>().unwrap(),
+ /// "fd00:8000::/18".parse().unwrap(),
+ /// ]);
+ /// ```
+ pub fn aggregate(networks: &Vec<Ipv6Net>) -> Vec<Ipv6Net> {
+ let mut intervals: Vec<(_, _)> = networks.iter().map(|n| n.interval()).collect();
+ intervals = merge_intervals(intervals);
+ let mut res: Vec<Ipv6Net> = Vec::new();
+
+ for (start, mut end) in intervals {
+ if end != std::u128::MAX {
+ end = end.saturating_sub(1)
+ }
+ let iter = Ipv6Subnets::new(start.into(), end.into(), 0);
+ res.extend(iter);
+ }
+ res
+ }
+}
+
+impl Default for Ipv6Net {
+ fn default() -> Self {
+ Self {
+ addr: Ipv6Addr::from(0),
+ prefix_len: 0,
+ }
+ }
+}
+
+impl fmt::Debug for Ipv6Net {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
+impl fmt::Display for Ipv6Net {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ write!(fmt, "{}/{}", self.addr, self.prefix_len)
+ }
+}
+
+impl From<Ipv6Addr> for Ipv6Net {
+ fn from(addr: Ipv6Addr) -> Ipv6Net {
+ Ipv6Net { addr, prefix_len: 128 }
+ }
+}
+
+/// Provides a method to test if a network address contains either
+/// another network address or an IP address.
+///
+/// # Examples
+///
+/// ```
+/// # use std::net::IpAddr;
+/// # use ipnet::IpNet;
+/// #
+/// let n4_1: IpNet = "10.1.1.0/24".parse().unwrap();
+/// let n4_2: IpNet = "10.1.1.0/26".parse().unwrap();
+/// let n4_3: IpNet = "10.1.2.0/26".parse().unwrap();
+/// let ip4_1: IpAddr = "10.1.1.1".parse().unwrap();
+/// let ip4_2: IpAddr = "10.1.2.1".parse().unwrap();
+///
+/// let n6_1: IpNet = "fd00::/16".parse().unwrap();
+/// let n6_2: IpNet = "fd00::/17".parse().unwrap();
+/// let n6_3: IpNet = "fd01::/17".parse().unwrap();
+/// let ip6_1: IpAddr = "fd00::1".parse().unwrap();
+/// let ip6_2: IpAddr = "fd01::1".parse().unwrap();
+///
+/// assert!(n4_1.contains(&n4_2));
+/// assert!(!n4_1.contains(&n4_3));
+/// assert!(n4_1.contains(&ip4_1));
+/// assert!(!n4_1.contains(&ip4_2));
+///
+/// assert!(n6_1.contains(&n6_2));
+/// assert!(!n6_1.contains(&n6_3));
+/// assert!(n6_1.contains(&ip6_1));
+/// assert!(!n6_1.contains(&ip6_2));
+///
+/// assert!(!n4_1.contains(&n6_1) && !n6_1.contains(&n4_1));
+/// assert!(!n4_1.contains(&ip6_1) && !n6_1.contains(&ip4_1));
+/// ```
+pub trait Contains<T> {
+ fn contains(&self, other: T) -> bool;
+}
+
+impl<'a> Contains<&'a IpNet> for IpNet {
+ fn contains(&self, other: &IpNet) -> bool {
+ match (*self, *other) {
+ (IpNet::V4(ref a), IpNet::V4(ref b)) => a.contains(b),
+ (IpNet::V6(ref a), IpNet::V6(ref b)) => a.contains(b),
+ _ => false,
+ }
+ }
+}
+
+impl<'a> Contains<&'a IpAddr> for IpNet {
+ fn contains(&self, other: &IpAddr) -> bool {
+ match (*self, *other) {
+ (IpNet::V4(ref a), IpAddr::V4(ref b)) => a.contains(b),
+ (IpNet::V6(ref a), IpAddr::V6(ref b)) => a.contains(b),
+ _ => false,
+ }
+ }
+}
+
+impl<'a> Contains<&'a Ipv4Net> for Ipv4Net {
+ fn contains(&self, other: &'a Ipv4Net) -> bool {
+ self.network() <= other.network() && other.broadcast() <= self.broadcast()
+ }
+}
+
+impl<'a> Contains<&'a Ipv4Addr> for Ipv4Net {
+ fn contains(&self, other: &'a Ipv4Addr) -> bool {
+ self.network() <= *other && *other <= self.broadcast()
+ }
+}
+
+impl<'a> Contains<&'a Ipv6Net> for Ipv6Net {
+ fn contains(&self, other: &'a Ipv6Net) -> bool {
+ self.network() <= other.network() && other.broadcast() <= self.broadcast()
+ }
+}
+
+impl<'a> Contains<&'a Ipv6Addr> for Ipv6Net {
+ fn contains(&self, other: &'a Ipv6Addr) -> bool {
+ self.network() <= *other && *other <= self.broadcast()
+ }
+}
+
+/// An `Iterator` that generates IP network addresses, either IPv4 or
+/// IPv6.
+///
+/// Generates the subnets between the provided `start` and `end` IP
+/// addresses inclusive of `end`. Each iteration generates the next
+/// network address of the largest valid size it can, while using a
+/// prefix length not less than `min_prefix_len`.
+///
+/// # Examples
+///
+/// ```
+/// # use std::net::{Ipv4Addr, Ipv6Addr};
+/// # use std::str::FromStr;
+/// # use ipnet::{IpNet, IpSubnets, Ipv4Subnets, Ipv6Subnets};
+/// let subnets = IpSubnets::from(Ipv4Subnets::new(
+/// "10.0.0.0".parse().unwrap(),
+/// "10.0.0.239".parse().unwrap(),
+/// 26,
+/// ));
+///
+/// assert_eq!(subnets.collect::<Vec<IpNet>>(), vec![
+/// "10.0.0.0/26".parse().unwrap(),
+/// "10.0.0.64/26".parse().unwrap(),
+/// "10.0.0.128/26".parse().unwrap(),
+/// "10.0.0.192/27".parse().unwrap(),
+/// "10.0.0.224/28".parse().unwrap(),
+/// ]);
+///
+/// let subnets = IpSubnets::from(Ipv6Subnets::new(
+/// "fd00::".parse().unwrap(),
+/// "fd00:ef:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap(),
+/// 26,
+/// ));
+///
+/// assert_eq!(subnets.collect::<Vec<IpNet>>(), vec![
+/// "fd00::/26".parse().unwrap(),
+/// "fd00:40::/26".parse().unwrap(),
+/// "fd00:80::/26".parse().unwrap(),
+/// "fd00:c0::/27".parse().unwrap(),
+/// "fd00:e0::/28".parse().unwrap(),
+/// ]);
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
+pub enum IpSubnets {
+ V4(Ipv4Subnets),
+ V6(Ipv6Subnets),
+}
+
+/// An `Iterator` that generates IPv4 network addresses.
+///
+/// Generates the subnets between the provided `start` and `end` IP
+/// addresses inclusive of `end`. Each iteration generates the next
+/// network address of the largest valid size it can, while using a
+/// prefix length not less than `min_prefix_len`.
+///
+/// # Examples
+///
+/// ```
+/// # use std::net::Ipv4Addr;
+/// # use std::str::FromStr;
+/// # use ipnet::{Ipv4Net, Ipv4Subnets};
+/// let subnets = Ipv4Subnets::new(
+/// "10.0.0.0".parse().unwrap(),
+/// "10.0.0.239".parse().unwrap(),
+/// 26,
+/// );
+///
+/// assert_eq!(subnets.collect::<Vec<Ipv4Net>>(), vec![
+/// "10.0.0.0/26".parse().unwrap(),
+/// "10.0.0.64/26".parse().unwrap(),
+/// "10.0.0.128/26".parse().unwrap(),
+/// "10.0.0.192/27".parse().unwrap(),
+/// "10.0.0.224/28".parse().unwrap(),
+/// ]);
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
+pub struct Ipv4Subnets {
+ start: Ipv4Addr,
+ end: Ipv4Addr, // end is inclusive
+ min_prefix_len: u8,
+}
+
+/// An `Iterator` that generates IPv6 network addresses.
+///
+/// Generates the subnets between the provided `start` and `end` IP
+/// addresses inclusive of `end`. Each iteration generates the next
+/// network address of the largest valid size it can, while using a
+/// prefix length not less than `min_prefix_len`.
+///
+/// # Examples
+///
+/// ```
+/// # use std::net::Ipv6Addr;
+/// # use std::str::FromStr;
+/// # use ipnet::{Ipv6Net, Ipv6Subnets};
+/// let subnets = Ipv6Subnets::new(
+/// "fd00::".parse().unwrap(),
+/// "fd00:ef:ffff:ffff:ffff:ffff:ffff:ffff".parse().unwrap(),
+/// 26,
+/// );
+///
+/// assert_eq!(subnets.collect::<Vec<Ipv6Net>>(), vec![
+/// "fd00::/26".parse().unwrap(),
+/// "fd00:40::/26".parse().unwrap(),
+/// "fd00:80::/26".parse().unwrap(),
+/// "fd00:c0::/27".parse().unwrap(),
+/// "fd00:e0::/28".parse().unwrap(),
+/// ]);
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
+pub struct Ipv6Subnets {
+ start: Ipv6Addr,
+ end: Ipv6Addr, // end is inclusive
+ min_prefix_len: u8,
+}
+
+impl Ipv4Subnets {
+ pub fn new(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Self {
+ Ipv4Subnets {
+ start: start,
+ end: end,
+ min_prefix_len: min_prefix_len,
+ }
+ }
+}
+
+impl Ipv6Subnets {
+ pub fn new(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Self {
+ Ipv6Subnets {
+ start: start,
+ end: end,
+ min_prefix_len: min_prefix_len,
+ }
+ }
+}
+
+impl From<Ipv4Subnets> for IpSubnets {
+ fn from(i: Ipv4Subnets) -> IpSubnets {
+ IpSubnets::V4(i)
+ }
+}
+
+impl From<Ipv6Subnets> for IpSubnets {
+ fn from(i: Ipv6Subnets) -> IpSubnets {
+ IpSubnets::V6(i)
+ }
+}
+
+impl Iterator for IpSubnets {
+ type Item = IpNet;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match *self {
+ IpSubnets::V4(ref mut a) => a.next().map(IpNet::V4),
+ IpSubnets::V6(ref mut a) => a.next().map(IpNet::V6),
+ }
+ }
+}
+
+fn next_ipv4_subnet(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Ipv4Net {
+ let range = end.saturating_sub(start).saturating_add(1);
+ if range == std::u32::MAX && min_prefix_len == 0 {
+ Ipv4Net::new(start, min_prefix_len).unwrap()
+ }
+ else {
+ let range_bits = 32u32.saturating_sub(range.leading_zeros()).saturating_sub(1);
+ let start_tz = u32::from(start).trailing_zeros();
+ let new_prefix_len = 32 - min(range_bits, start_tz);
+ let next_prefix_len = max(new_prefix_len as u8, min_prefix_len);
+ Ipv4Net::new(start, next_prefix_len).unwrap()
+ }
+}
+
+fn next_ipv6_subnet(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Ipv6Net {
+ let range = end.saturating_sub(start).saturating_add(1);
+ if range == std::u128::MAX && min_prefix_len == 0 {
+ Ipv6Net::new(start, min_prefix_len).unwrap()
+ }
+ else {
+ let range = end.saturating_sub(start).saturating_add(1);
+ let range_bits = 128u32.saturating_sub(range.leading_zeros()).saturating_sub(1);
+ let start_tz = u128::from(start).trailing_zeros();
+ let new_prefix_len = 128 - min(range_bits, start_tz);
+ let next_prefix_len = max(new_prefix_len as u8, min_prefix_len);
+ Ipv6Net::new(start, next_prefix_len).unwrap()
+ }
+}
+
+impl Iterator for Ipv4Subnets {
+ type Item = Ipv4Net;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.start.partial_cmp(&self.end) {
+ Some(Less) => {
+ let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len);
+ self.start = next.broadcast().saturating_add(1);
+
+ // Stop the iterator if we saturated self.start. This
+ // check worsens performance slightly but overall this
+ // approach of operating on Ipv4Addr types is faster
+ // than what we were doing before using Ipv4Net.
+ if self.start == next.broadcast() {
+ self.end.replace_zero();
+ }
+ Some(next)
+ },
+ Some(Equal) => {
+ let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len);
+ self.start = next.broadcast().saturating_add(1);
+ self.end.replace_zero();
+ Some(next)
+ },
+ _ => None,
+ }
+ }
+}
+
+impl Iterator for Ipv6Subnets {
+ type Item = Ipv6Net;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match self.start.partial_cmp(&self.end) {
+ Some(Less) => {
+ let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len);
+ self.start = next.broadcast().saturating_add(1);
+
+ // Stop the iterator if we saturated self.start. This
+ // check worsens performance slightly but overall this
+ // approach of operating on Ipv6Addr types is faster
+ // than what we were doing before using Ipv6Net.
+ if self.start == next.broadcast() {
+ self.end.replace_zero();
+ }
+ Some(next)
+ },
+ Some(Equal) => {
+ let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len);
+ self.start = next.broadcast().saturating_add(1);
+ self.end.replace_zero();
+ Some(next)
+ },
+ _ => None,
+ }
+ }
+}
+
+impl FusedIterator for IpSubnets {}
+impl FusedIterator for Ipv4Subnets {}
+impl FusedIterator for Ipv6Subnets {}
+
+// Generic function for merging a vector of intervals.
+fn merge_intervals<T: Copy + Ord>(mut intervals: Vec<(T, T)>) -> Vec<(T, T)> {
+ if intervals.len() == 0 {
+ return intervals;
+ }
+
+ intervals.sort();
+ let mut res: Vec<(T, T)> = Vec::new();
+ let (mut start, mut end) = intervals[0];
+
+ let mut i = 1;
+ let len = intervals.len();
+ while i < len {
+ let (next_start, next_end) = intervals[i];
+ if end >= next_start {
+ start = min(start, next_start);
+ end = max(end, next_end);
+ }
+ else {
+ res.push((start, end));
+ start = next_start;
+ end = next_end;
+ }
+ i += 1;
+ }
+
+ res.push((start, end));
+ res
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ macro_rules! make_ipnet_vec {
+ ($($x:expr),*) => ( vec![$($x.parse::<IpNet>().unwrap(),)*] );
+ ($($x:expr,)*) => ( make_ipnet_vec![$($x),*] );
+ }
+
+ #[test]
+ fn test_make_ipnet_vec() {
+ assert_eq!(
+ make_ipnet_vec![
+ "10.1.1.1/32", "10.2.2.2/24", "10.3.3.3/16",
+ "fd00::1/128", "fd00::2/127", "fd00::3/126",
+ ],
+ vec![
+ "10.1.1.1/32".parse().unwrap(),
+ "10.2.2.2/24".parse().unwrap(),
+ "10.3.3.3/16".parse().unwrap(),
+ "fd00::1/128".parse().unwrap(),
+ "fd00::2/127".parse().unwrap(),
+ "fd00::3/126".parse().unwrap(),
+ ]
+ );
+ }
+
+ #[test]
+ fn test_merge_intervals() {
+ let v = vec![
+ (0, 1), (1, 2), (2, 3),
+ (11, 12), (13, 14), (10, 15), (11, 13),
+ (20, 25), (24, 29),
+ ];
+
+ let v_ok = vec![
+ (0, 3),
+ (10, 15),
+ (20, 29),
+ ];
+
+ let vv = vec![
+ ([0, 1], [0, 2]), ([0, 2], [0, 3]), ([0, 0], [0, 1]),
+ ([10, 15], [11, 0]), ([10, 0], [10, 16]),
+ ];
+
+ let vv_ok = vec![
+ ([0, 0], [0, 3]),
+ ([10, 0], [11, 0]),
+ ];
+
+ assert_eq!(merge_intervals(v), v_ok);
+ assert_eq!(merge_intervals(vv), vv_ok);
+ }
+
+ macro_rules! make_ipv4_subnets_test {
+ ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => (
+ #[test]
+ fn $name() {
+ let subnets = IpSubnets::from(Ipv4Subnets::new(
+ $start.parse().unwrap(),
+ $end.parse().unwrap(),
+ $min_prefix_len,
+ ));
+ let results = make_ipnet_vec![$($x),*];
+ assert_eq!(subnets.collect::<Vec<IpNet>>(), results);
+ }
+ );
+ ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => (
+ make_ipv4_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*);
+ );
+ }
+
+ macro_rules! make_ipv6_subnets_test {
+ ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => (
+ #[test]
+ fn $name() {
+ let subnets = IpSubnets::from(Ipv6Subnets::new(
+ $start.parse().unwrap(),
+ $end.parse().unwrap(),
+ $min_prefix_len,
+ ));
+ let results = make_ipnet_vec![$($x),*];
+ assert_eq!(subnets.collect::<Vec<IpNet>>(), results);
+ }
+ );
+ ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => (
+ make_ipv6_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*);
+ );
+ }
+
+ make_ipv4_subnets_test!(
+ test_ipv4_subnets_zero_zero,
+ "0.0.0.0", "0.0.0.0", 0,
+ "0.0.0.0/32",
+ );
+
+ make_ipv4_subnets_test!(
+ test_ipv4_subnets_zero_max,
+ "0.0.0.0", "255.255.255.255", 0,
+ "0.0.0.0/0",
+ );
+
+ make_ipv4_subnets_test!(
+ test_ipv4_subnets_max_max,
+ "255.255.255.255", "255.255.255.255", 0,
+ "255.255.255.255/32",
+ );
+
+ make_ipv4_subnets_test!(
+ test_ipv4_subnets_none,
+ "0.0.0.1", "0.0.0.0", 0,
+ );
+
+ make_ipv4_subnets_test!(
+ test_ipv4_subnets_one,
+ "0.0.0.0", "0.0.0.1", 0,
+ "0.0.0.0/31",
+ );
+
+ make_ipv4_subnets_test!(
+ test_ipv4_subnets_two,
+ "0.0.0.0", "0.0.0.2", 0,
+ "0.0.0.0/31",
+ "0.0.0.2/32",
+ );
+
+ make_ipv4_subnets_test!(
+ test_ipv4_subnets_taper,
+ "0.0.0.0", "0.0.0.10", 30,
+ "0.0.0.0/30",
+ "0.0.0.4/30",
+ "0.0.0.8/31",
+ "0.0.0.10/32",
+ );
+
+ make_ipv6_subnets_test!(
+ test_ipv6_subnets_zero_zero,
+ "::", "::", 0,
+ "::/128",
+ );
+
+ make_ipv6_subnets_test!(
+ test_ipv6_subnets_zero_max,
+ "::", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0,
+ "::/0",
+ );
+
+ make_ipv6_subnets_test!(
+ test_ipv6_subnets_max_max,
+ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0,
+ "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128",
+ );
+
+ make_ipv6_subnets_test!(
+ test_ipv6_subnets_none,
+ "::1", "::", 0,
+ );
+
+ make_ipv6_subnets_test!(
+ test_ipv6_subnets_one,
+ "::", "::1", 0,
+ "::/127",
+ );
+
+ make_ipv6_subnets_test!(
+ test_ipv6_subnets_two,
+ "::", "::2", 0,
+ "::/127",
+ "::2/128",
+ );
+
+ make_ipv6_subnets_test!(
+ test_ipv6_subnets_taper,
+ "::", "::a", 126,
+ "::/126",
+ "::4/126",
+ "::8/127",
+ "::a/128",
+ );
+
+ #[test]
+ fn test_aggregate() {
+ let ip_nets = make_ipnet_vec![
+ "10.0.0.0/24", "10.0.1.0/24", "10.0.1.1/24", "10.0.1.2/24",
+ "10.0.2.0/24",
+ "10.1.0.0/24", "10.1.1.0/24",
+ "192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24", "192.168.3.0/24",
+ "fd00::/32", "fd00:1::/32",
+ "fd00:2::/32",
+ ];
+
+ let ip_aggs = make_ipnet_vec![
+ "10.0.0.0/23",
+ "10.0.2.0/24",
+ "10.1.0.0/23",
+ "192.168.0.0/22",
+ "fd00::/31",
+ "fd00:2::/32",
+ ];
+
+ let ipv4_nets: Vec<Ipv4Net> = ip_nets.iter().filter_map(|p| if let IpNet::V4(x) = *p { Some(x) } else { None }).collect();
+ let ipv4_aggs: Vec<Ipv4Net> = ip_aggs.iter().filter_map(|p| if let IpNet::V4(x) = *p { Some(x) } else { None }).collect();
+ let ipv6_nets: Vec<Ipv6Net> = ip_nets.iter().filter_map(|p| if let IpNet::V6(x) = *p { Some(x) } else { None }).collect();
+ let ipv6_aggs: Vec<Ipv6Net> = ip_aggs.iter().filter_map(|p| if let IpNet::V6(x) = *p { Some(x) } else { None }).collect();
+
+ assert_eq!(IpNet::aggregate(&ip_nets), ip_aggs);
+ assert_eq!(Ipv4Net::aggregate(&ipv4_nets), ipv4_aggs);
+ assert_eq!(Ipv6Net::aggregate(&ipv6_nets), ipv6_aggs);
+ }
+
+ #[test]
+ fn test_aggregate_issue44() {
+ let nets: Vec<Ipv4Net> = vec!["128.0.0.0/1".parse().unwrap()];
+ assert_eq!(Ipv4Net::aggregate(&nets), nets);
+
+ let nets: Vec<Ipv4Net> = vec!["0.0.0.0/1".parse().unwrap(), "128.0.0.0/1".parse().unwrap()];
+ assert_eq!(Ipv4Net::aggregate(&nets), vec!["0.0.0.0/0".parse().unwrap()]);
+
+ let nets: Vec<Ipv6Net> = vec!["8000::/1".parse().unwrap()];
+ assert_eq!(Ipv6Net::aggregate(&nets), nets);
+
+ let nets: Vec<Ipv6Net> = vec!["::/1".parse().unwrap(), "8000::/1".parse().unwrap()];
+ assert_eq!(Ipv6Net::aggregate(&nets), vec!["::/0".parse().unwrap()]);
+ }
+
+ #[test]
+ fn ipnet_default() {
+ let ipnet: IpNet = "0.0.0.0/0".parse().unwrap();
+ assert_eq!(ipnet, IpNet::default());
+ }
+
+ #[test]
+ fn ipv4net_default() {
+ let ipnet: Ipv4Net = "0.0.0.0/0".parse().unwrap();
+ assert_eq!(ipnet, Ipv4Net::default());
+ }
+
+ #[test]
+ fn ipv6net_default() {
+ let ipnet: Ipv6Net = "::/0".parse().unwrap();
+ assert_eq!(ipnet, Ipv6Net::default());
+ }
+}
diff --git a/vendor/ipnet/src/ipnet_schemars.rs b/vendor/ipnet/src/ipnet_schemars.rs
new file mode 100644
index 000000000..ac722a995
--- /dev/null
+++ b/vendor/ipnet/src/ipnet_schemars.rs
@@ -0,0 +1,86 @@
+use crate::Ipv4Net;
+use crate::Ipv6Net;
+use crate::IpNet;
+
+use schemars::{JsonSchema, gen::SchemaGenerator, schema::{SubschemaValidation, Schema, SchemaObject, StringValidation, Metadata, SingleOrVec, InstanceType}};
+
+impl JsonSchema for Ipv4Net {
+ fn schema_name() -> String {
+ "Ipv4Net".to_string()
+ }
+
+ fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
+ Schema::Object(SchemaObject {
+ metadata: Some(Box::new(Metadata {
+ title: Some("IPv4 network".to_string()),
+ description: Some("An IPv4 address with prefix length".to_string()),
+ examples: vec![
+ schemars::_serde_json::Value::String("0.0.0.0/0".to_string()),
+ schemars::_serde_json::Value::String("192.168.0.0/24".to_string()),
+ ],
+ ..Default::default()
+ })),
+ instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
+ string: Some(Box::new(StringValidation {
+ max_length: Some(18),
+ min_length: None,
+ pattern: Some(r#"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(?:3[0-2]|[1-2][0-9]|[0-9])$"#.to_string()),
+ ..Default::default()
+ })),
+ ..Default::default()
+ })
+ }
+}
+impl JsonSchema for Ipv6Net {
+ fn schema_name() -> String {
+ "Ipv6Net".to_string()
+ }
+
+ fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
+ Schema::Object(SchemaObject {
+ metadata: Some(Box::new(Metadata {
+ title: Some("IPv6 network".to_string()),
+ description: Some("An IPv6 address with prefix length".to_string()),
+ examples: vec![
+ schemars::_serde_json::Value::String("::/0".to_string()),
+ schemars::_serde_json::Value::String("fd00::/32".to_string()),
+ ],
+ ..Default::default()
+ })),
+ instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
+ string: Some(Box::new(StringValidation {
+ max_length: Some(43),
+ min_length: None,
+ pattern: Some(r#"^[0-9A-Fa-f:\.]+\/(?:[0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$"#.to_string()),
+ ..Default::default()
+ })),
+ ..Default::default()
+ })
+ }
+}
+impl JsonSchema for IpNet {
+ fn schema_name() -> String {
+ "IpNet".to_string()
+ }
+
+ fn json_schema(gen: &mut SchemaGenerator) -> Schema {
+ Schema::Object(SchemaObject {
+ metadata: Some(Box::new(Metadata {
+ title: Some("IP network".to_string()),
+ description: Some("An IPv4 or IPv6 address with prefix length".to_string()),
+ examples: vec![
+ schemars::_serde_json::Value::String("192.168.0.0/24".to_string()),
+ schemars::_serde_json::Value::String("fd00::/32".to_string()),
+ ],
+ ..Default::default()
+ })),
+ subschemas: Some(Box::new(
+ SubschemaValidation {
+ one_of: Some(vec![Ipv4Net::json_schema(gen), Ipv6Net::json_schema(gen)]),
+ ..Default::default()
+ }
+ )),
+ ..Default::default()
+ })
+ }
+}
diff --git a/vendor/ipnet/src/ipnet_serde.rs b/vendor/ipnet/src/ipnet_serde.rs
new file mode 100644
index 000000000..bbf15ac81
--- /dev/null
+++ b/vendor/ipnet/src/ipnet_serde.rs
@@ -0,0 +1,276 @@
+use crate::{IpNet, Ipv4Net, Ipv6Net};
+use std::fmt;
+use std::net::{Ipv4Addr, Ipv6Addr};
+use serde::{self, Serialize, Deserialize, Serializer, Deserializer};
+use serde::ser::SerializeTuple;
+use serde::de::{EnumAccess, Error, VariantAccess, Visitor};
+
+impl Serialize for IpNet {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where S: Serializer
+ {
+ if serializer.is_human_readable() {
+ match *self {
+ IpNet::V4(ref a) => a.serialize(serializer),
+ IpNet::V6(ref a) => a.serialize(serializer),
+ }
+ } else {
+ match *self {
+ IpNet::V4(ref a) => serializer.serialize_newtype_variant("IpNet", 0, "V4", a),
+ IpNet::V6(ref a) => serializer.serialize_newtype_variant("IpNet", 1, "V6", a),
+ }
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for IpNet {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where D: Deserializer<'de>
+ {
+ if deserializer.is_human_readable() {
+ struct IpNetVisitor;
+
+ impl<'de> Visitor<'de> for IpNetVisitor {
+ type Value = IpNet;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("IPv4 or IPv6 network address")
+ }
+
+ fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
+ where E: Error
+ {
+ s.parse().map_err(Error::custom)
+ }
+ }
+
+ deserializer.deserialize_str(IpNetVisitor)
+ } else {
+ struct EnumVisitor;
+
+ #[derive(Serialize, Deserialize)]
+ enum IpNetKind {
+ V4,
+ V6,
+ }
+
+ impl<'de> Visitor<'de> for EnumVisitor {
+ type Value = IpNet;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("IPv4 or IPv6 network address")
+ }
+
+ fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
+ where A: EnumAccess<'de>
+ {
+ match data.variant()? {
+ (IpNetKind::V4, v) => v.newtype_variant().map(IpNet::V4),
+ (IpNetKind::V6, v) => v.newtype_variant().map(IpNet::V6),
+ }
+ }
+ }
+
+ deserializer.deserialize_enum("IpNet", &["V4", "V6"], EnumVisitor)
+ }
+ }
+}
+
+impl Serialize for Ipv4Net {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where S: Serializer
+ {
+ if serializer.is_human_readable() {
+ serializer.collect_str(self)
+ } else {
+ let mut seq = serializer.serialize_tuple(5)?;
+ for octet in &self.addr().octets() {
+ seq.serialize_element(octet)?;
+ }
+ seq.serialize_element(&self.prefix_len())?;
+ seq.end()
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for Ipv4Net {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where D: Deserializer<'de>
+ {
+ if deserializer.is_human_readable() {
+ struct IpAddrVisitor;
+
+ impl<'de> Visitor<'de> for IpAddrVisitor {
+ type Value = Ipv4Net;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("IPv4 network address")
+ }
+
+ fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
+ where E: Error
+ {
+ s.parse().map_err(Error::custom)
+ }
+ }
+
+ deserializer.deserialize_str(IpAddrVisitor)
+ } else {
+ let b = <[u8; 5]>::deserialize(deserializer)?;
+ Ipv4Net::new(Ipv4Addr::new(b[0], b[1], b[2], b[3]), b[4]).map_err(serde::de::Error::custom)
+ }
+ }
+}
+
+impl Serialize for Ipv6Net {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where S: Serializer
+ {
+ if serializer.is_human_readable() {
+ serializer.collect_str(self)
+ } else {
+ let mut seq = serializer.serialize_tuple(17)?;
+ for octet in &self.addr().octets() {
+ seq.serialize_element(octet)?;
+ }
+ seq.serialize_element(&self.prefix_len())?;
+ seq.end()
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for Ipv6Net {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where D: Deserializer<'de>
+ {
+ if deserializer.is_human_readable() {
+ struct IpAddrVisitor;
+
+ impl<'de> Visitor<'de> for IpAddrVisitor {
+ type Value = Ipv6Net;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("IPv6 network address")
+ }
+
+ fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
+ where E: Error
+ {
+ s.parse().map_err(Error::custom)
+ }
+ }
+
+ deserializer.deserialize_str(IpAddrVisitor)
+ } else {
+ let b = <[u8; 17]>::deserialize(deserializer)?;
+ Ipv6Net::new(Ipv6Addr::new(
+ ((b[0] as u16) << 8) | b[1] as u16, ((b[2] as u16) << 8) | b[3] as u16,
+ ((b[4] as u16) << 8) | b[5] as u16, ((b[6] as u16) << 8) | b[7] as u16,
+ ((b[8] as u16) << 8) | b[9] as u16, ((b[10] as u16) << 8) | b[11] as u16,
+ ((b[12] as u16) << 8) | b[13] as u16, ((b[14] as u16) << 8) | b[15] as u16
+ ), b[16]).map_err(Error::custom)
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ extern crate serde_test;
+
+ use crate::{IpNet, Ipv4Net, Ipv6Net};
+ use self::serde_test::{assert_tokens, Configure, Token};
+
+ #[test]
+ fn test_serialize_ipnet_v4() {
+ let net_str = "10.1.1.0/24";
+ let net: IpNet = net_str.parse().unwrap();
+ assert_tokens(&net.readable(), &[Token::Str(net_str)]);
+ assert_tokens(&net.compact(), &[
+ Token::NewtypeVariant { name: "IpNet", variant: "V4", },
+ Token::Tuple { len: 5 },
+ Token::U8(10),
+ Token::U8(1),
+ Token::U8(1),
+ Token::U8(0),
+ Token::U8(24),
+ Token::TupleEnd,
+ ]);
+ }
+
+ #[test]
+ fn test_serialize_ipnet_v6() {
+ let net_str = "fd00::/32";
+ let net: IpNet = net_str.parse().unwrap();
+ assert_tokens(&net.readable(), &[Token::Str(net_str)]);
+ assert_tokens(&net.compact(), &[
+ Token::NewtypeVariant { name: "IpNet", variant: "V6", },
+ // This is too painful, but Token::Bytes() seems to be
+ // an array with a length, which is not what we serialize.
+ Token::Tuple { len: 17 },
+ Token::U8(253u8),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(32),
+ Token::TupleEnd,
+ ]);
+ }
+
+ #[test]
+ fn test_serialize_ipv4_net() {
+ let net_str = "10.1.1.0/24";
+ let net: Ipv4Net = net_str.parse().unwrap();
+ assert_tokens(&net.readable(), &[Token::Str(net_str)]);
+ assert_tokens(&net.compact(), &[
+ Token::Tuple { len: 5 },
+ Token::U8(10),
+ Token::U8(1),
+ Token::U8(1),
+ Token::U8(0),
+ Token::U8(24),
+ Token::TupleEnd,
+ ]);
+ }
+
+ #[test]
+ fn test_serialize_ipv6_net() {
+ let net_str = "fd00::/32";
+ let net: Ipv6Net = net_str.parse().unwrap();
+ assert_tokens(&net.readable(), &[Token::Str(net_str)]);
+ assert_tokens(&net.compact(), &[
+ // This is too painful, but Token::Bytes() seems to be
+ // an array with a length, which is not what we serialize.
+ Token::Tuple { len: 17 },
+ Token::U8(253u8),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(0),
+ Token::U8(32),
+ Token::TupleEnd,
+ ]);
+ }
+}
diff --git a/vendor/ipnet/src/lib.rs b/vendor/ipnet/src/lib.rs
new file mode 100644
index 000000000..4f8fb166a
--- /dev/null
+++ b/vendor/ipnet/src/lib.rs
@@ -0,0 +1,98 @@
+#![doc(html_root_url = "https://docs.rs/ipnet/2.7.2")]
+//! Types for IPv4 and IPv6 network addresses.
+//!
+//! This module provides types and useful methods for working with IPv4
+//! and IPv6 network addresses, commonly called IP prefixes. The new
+//! [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`] types build on the existing
+//! [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`] types already provided in
+//! Rust's standard library and align to their design to stay
+//! consistent.
+//!
+//! The module also provides the [`IpSubnets`], [`Ipv4Subnets`], and
+//! [`Ipv6Subnets`] types for iterating over the subnets contained in
+//! an IP address range. The [`IpAddrRange`], [`Ipv4AddrRange`], and
+//! [`Ipv6AddrRange`] types for iterating over IP addresses in a range.
+//! And traits that extend `Ipv4Addr` and `Ipv6Addr` with methods for
+//! addition, subtraction, bitwise-and, and bitwise-or operations that
+//! are missing in Rust's standard library.
+//!
+//! The module only uses stable features so it is guaranteed to compile
+//! using the stable toolchain.
+//!
+//! # Organization
+//!
+//! * [`IpNet`] represents an IP network address, either IPv4 or IPv6.
+//! * [`Ipv4Net`] and [`Ipv6Net`] are respectively IPv4 and IPv6 network
+//! addresses.
+//! * [`IpSubnets`], [`Ipv4Subnets`], and [`Ipv6Subnets`] are iterators
+//! that generate the smallest set of IP network addresses bound by an
+//! IP address range and minimum prefix length. These can be created
+//! using their constructors. They are also returned by the
+//! [`subnets()`] methods and used within the [`aggregate()`] methods.
+//! * [`IpAddrRange`], [`Ipv4AddrRange`], and [`Ipv6AddrRange`] are
+//! iterators that generate IP addresses. These can be created using
+//! their constructors. They are also returned by the [`hosts()`]
+//! methods.
+//! * The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
+//! the [`Ipv4Addr`] and [`Ipv6Addr`] types with methods to perform
+//! these operations.
+//!
+//! [`IpNet`]: enum.IpNet.html
+//! [`Ipv4Net`]: struct.Ipv4Net.html
+//! [`Ipv6Net`]: struct.Ipv6Net.html
+//! [`IpAddr`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html
+//! [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
+//! [`Ipv6Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
+//! [`IpSubnets`]: enum.IpSubnets.html
+//! [`Ipv4Subnets`]: struct.Ipv4Subnets.html
+//! [`Ipv6Subnets`]: struct.Ipv6Subnets.html
+//! [`subnets()`]: enum.IpNet.html#method.subnets
+//! [`aggregate()`]: enum.IpNet.html#method.aggregate
+//! [`IpAddrRange`]: enum.IpAddrRange.html
+//! [`Ipv4AddrRange`]: struct.Ipv4AddrRange.html
+//! [`Ipv6AddrRange`]: struct.Ipv6AddrRange.html
+//! [`hosts()`]: enum.IpNet.html#method.hosts
+//! [`IpAdd`]: trait.IpAdd.html
+//! [`IpSub`]: trait.IpSub.html
+//! [`IpBitAnd`]: trait.IpBitAnd.html
+//! [`IpBitOr`]: trait.IpBitOr.html
+//!
+//! # Serde support
+//!
+//! This library comes with support for [serde](https://serde.rs) but
+//! it's not enabled by default. Use the `serde` [feature] to enable.
+//!
+//! ```toml
+//! [dependencies]
+//! ipnet = { version = "2", features = ["serde"] }
+//! ```
+//!
+//! For human readable formats (e.g. JSON) the `IpNet`, `Ipv4Net`, and
+//! `Ipv6Net` types will serialize to their `Display` strings.
+//!
+//! For compact binary formats (e.g. Bincode) the `Ipv4Net` and
+//! `Ipv6Net` types will serialize to a string of 5 and 17 bytes that
+//! consist of the network address octects followed by the prefix
+//! length. The `IpNet` type will serialize to an Enum with the V4 or V6
+//! variant index prepending the above string of 5 or 17 bytes.
+//!
+//! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
+
+#[cfg(feature = "serde")]
+extern crate serde;
+#[cfg(feature = "schemars")]
+extern crate schemars;
+
+pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
+pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
+pub use self::parser::AddrParseError;
+pub use self::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix};
+
+mod ipext;
+mod ipnet;
+mod parser;
+mod mask;
+#[cfg(feature = "serde")]
+mod ipnet_serde;
+#[cfg(feature = "schemars")]
+mod ipnet_schemars;
diff --git a/vendor/ipnet/src/mask.rs b/vendor/ipnet/src/mask.rs
new file mode 100644
index 000000000..1047bf980
--- /dev/null
+++ b/vendor/ipnet/src/mask.rs
@@ -0,0 +1,128 @@
+use crate::PrefixLenError;
+use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+
+/// Converts a `IpAddr` network mask into a prefix.
+///
+/// # Errors
+/// If the mask is invalid this will return an `PrefixLenError`.
+pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, PrefixLenError> {
+ match mask {
+ IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
+ IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
+ }
+}
+
+/// Converts a `Ipv4Addr` network mask into a prefix.
+///
+/// # Errors
+/// If the mask is invalid this will return an `PrefixLenError`.
+pub fn ipv4_mask_to_prefix(mask: Ipv4Addr) -> Result<u8, PrefixLenError> {
+ let mask = u32::from(mask);
+
+ let prefix = mask.leading_ones();
+ if mask.checked_shl(prefix).unwrap_or(0) == 0 {
+ Ok(prefix as u8)
+ } else {
+ Err(PrefixLenError)
+ }
+}
+
+/// Converts a `Ipv6Addr` network mask into a prefix.
+///
+/// # Errors
+/// If the mask is invalid this will return an `PrefixLenError`.
+pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, PrefixLenError> {
+ let mask = u128::from(mask);
+
+ let prefix = mask.leading_ones();
+ if mask.checked_shl(prefix).unwrap_or(0) == 0 {
+ Ok(prefix as u8)
+ } else {
+ Err(PrefixLenError)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{Ipv4Net, Ipv6Net};
+
+ #[test]
+ fn v4_mask_to_prefix() {
+ let mask = Ipv4Addr::new(255, 255, 255, 128);
+ let prefix = ipv4_mask_to_prefix(mask);
+ assert_eq!(prefix, Ok(25));
+ }
+
+ #[test]
+ fn v4_mask_to_prefix_max() {
+ let mask = Ipv4Addr::from(u32::MAX);
+ let prefix = ipv4_mask_to_prefix(mask);
+ assert_eq!(prefix, Ok(32));
+ }
+
+ #[test]
+ fn invalid_v4_mask_to_prefix() {
+ let mask = Ipv4Addr::new(255, 0, 255, 0);
+ let prefix = ipv4_mask_to_prefix(mask);
+ assert!(prefix.is_err());
+ }
+
+ #[test]
+ fn ipv4net_with_netmask() {
+ {
+ // Positive test-case.
+ let addr = Ipv4Addr::new(127, 0, 0, 1);
+ let mask = Ipv4Addr::new(255, 0, 0, 0);
+ let net = Ipv4Net::with_netmask(addr, mask).unwrap();
+ let expected = Ipv4Net::new(Ipv4Addr::new(127, 0, 0, 1), 8).unwrap();
+ assert_eq!(net, expected);
+ }
+ {
+ // Negative test-case.
+ let addr = Ipv4Addr::new(127, 0, 0, 1);
+ let mask = Ipv4Addr::new(255, 0, 255, 0);
+ Ipv4Net::with_netmask(addr, mask).unwrap_err();
+ }
+ }
+
+ #[test]
+ fn v6_mask_to_prefix() {
+ let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0);
+ let prefix = ipv6_mask_to_prefix(mask);
+ assert_eq!(prefix, Ok(48));
+ }
+
+ #[test]
+ fn v6_mask_to_prefix_max() {
+ let mask = Ipv6Addr::from(u128::MAX);
+ let prefix = ipv6_mask_to_prefix(mask);
+ assert_eq!(prefix, Ok(128));
+ }
+
+ #[test]
+ fn invalid_v6_mask_to_prefix() {
+ let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0);
+ let prefix = ipv6_mask_to_prefix(mask);
+ assert!(prefix.is_err());
+ }
+
+ #[test]
+ fn ipv6net_with_netmask() {
+ {
+ // Positive test-case.
+ let addr = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2);
+ let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0);
+ let net = Ipv6Net::with_netmask(addr, mask).unwrap();
+ let expected =
+ Ipv6Net::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 48).unwrap();
+ assert_eq!(net, expected);
+ }
+ {
+ // Negative test-case.
+ let addr = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2);
+ let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0);
+ Ipv6Net::with_netmask(addr, mask).unwrap_err();
+ }
+ }
+}
diff --git a/vendor/ipnet/src/parser.rs b/vendor/ipnet/src/parser.rs
new file mode 100644
index 000000000..7ec999128
--- /dev/null
+++ b/vendor/ipnet/src/parser.rs
@@ -0,0 +1,345 @@
+//! A private parser implementation of IPv4 and IPv6 network addresses.
+//!
+//! The existing `std::net::parser` module cannot be extended because it
+//! is private. It is copied and extended here with methods for parsing
+//! IP network addresses.
+
+use std::error::Error;
+use std::fmt;
+use std::net::{Ipv4Addr, Ipv6Addr};
+use std::str::FromStr;
+
+use crate::ipnet::{IpNet, Ipv4Net, Ipv6Net};
+
+pub struct Parser<'a> {
+ // parsing as ASCII, so can use byte array
+ s: &'a [u8],
+ pos: usize,
+}
+
+impl<'a> Parser<'a> {
+ fn new(s: &'a str) -> Parser<'a> {
+ Parser {
+ s: s.as_bytes(),
+ pos: 0,
+ }
+ }
+
+ fn is_eof(&self) -> bool {
+ self.pos == self.s.len()
+ }
+
+ // Commit only if parser returns Some
+ fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
+ F: FnOnce(&mut Parser) -> Option<T>,
+ {
+ let pos = self.pos;
+ let r = cb(self);
+ if r.is_none() {
+ self.pos = pos;
+ }
+ r
+ }
+
+ // Commit only if parser read till EOF
+ fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
+ F: FnOnce(&mut Parser) -> Option<T>,
+ {
+ self.read_atomically(move |p| {
+ match cb(p) {
+ Some(x) => if p.is_eof() {Some(x)} else {None},
+ None => None,
+ }
+ })
+ }
+
+ // Return result of first successful parser
+ fn read_or<T>(&mut self, parsers: &mut [Box<dyn FnMut(&mut Parser) -> Option<T> + 'static>])
+ -> Option<T> {
+ for pf in parsers {
+ if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
+ return Some(r);
+ }
+ }
+ None
+ }
+
+ // Apply 3 parsers sequentially
+ fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
+ pa: PA,
+ pb: PB,
+ pc: PC)
+ -> Option<(A, B, C)> where
+ PA: FnOnce(&mut Parser) -> Option<A>,
+ PB: FnOnce(&mut Parser) -> Option<B>,
+ PC: FnOnce(&mut Parser) -> Option<C>,
+ {
+ self.read_atomically(move |p| {
+ let a = pa(p);
+ let b = if a.is_some() { pb(p) } else { None };
+ let c = if b.is_some() { pc(p) } else { None };
+ match (a, b, c) {
+ (Some(a), Some(b), Some(c)) => Some((a, b, c)),
+ _ => None
+ }
+ })
+ }
+
+ // Read next char
+ fn read_char(&mut self) -> Option<char> {
+ if self.is_eof() {
+ None
+ } else {
+ let r = self.s[self.pos] as char;
+ self.pos += 1;
+ Some(r)
+ }
+ }
+
+ // Return char and advance iff next char is equal to requested
+ fn read_given_char(&mut self, c: char) -> Option<char> {
+ self.read_atomically(|p| {
+ match p.read_char() {
+ Some(next) if next == c => Some(next),
+ _ => None,
+ }
+ })
+ }
+
+ // Read digit
+ fn read_digit(&mut self, radix: u8) -> Option<u8> {
+ fn parse_digit(c: char, radix: u8) -> Option<u8> {
+ let c = c as u8;
+ // assuming radix is either 10 or 16
+ if c >= b'0' && c <= b'9' {
+ Some(c - b'0')
+ } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
+ Some(c - b'a' + 10)
+ } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
+ Some(c - b'A' + 10)
+ } else {
+ None
+ }
+ }
+
+ self.read_atomically(|p| {
+ p.read_char().and_then(|c| parse_digit(c, radix))
+ })
+ }
+
+ fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
+ let mut r = 0;
+ let mut digit_count = 0;
+ loop {
+ match self.read_digit(radix) {
+ Some(d) => {
+ r = r * (radix as u32) + (d as u32);
+ digit_count += 1;
+ if digit_count > max_digits || r >= upto {
+ return None
+ }
+ }
+ None => {
+ if digit_count == 0 {
+ return None
+ } else {
+ return Some(r)
+ }
+ }
+ };
+ }
+ }
+
+ // Read number, failing if max_digits of number value exceeded
+ fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
+ self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
+ }
+
+ fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
+ let mut bs = [0; 4];
+ let mut i = 0;
+ while i < 4 {
+ if i != 0 && self.read_given_char('.').is_none() {
+ return None;
+ }
+
+ let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
+ match octet {
+ Some(d) => bs[i] = d,
+ None => return None,
+ };
+ i += 1;
+ }
+ Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
+ }
+
+ // Read IPv4 address
+ fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
+ self.read_atomically(|p| p.read_ipv4_addr_impl())
+ }
+
+ fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
+ fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
+ assert!(head.len() + tail.len() <= 8);
+ let mut gs = [0; 8];
+ gs[..head.len()].copy_from_slice(head);
+ gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
+ Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
+ }
+
+ fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
+ -> (usize, bool) {
+ let mut i = 0;
+ while i < limit {
+ if i < limit - 1 {
+ let ipv4 = p.read_atomically(|p| {
+ if i == 0 || p.read_given_char(':').is_some() {
+ p.read_ipv4_addr()
+ } else {
+ None
+ }
+ });
+ if let Some(v4_addr) = ipv4 {
+ let octets = v4_addr.octets();
+ groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
+ groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
+ return (i + 2, true);
+ }
+ }
+
+ let group = p.read_atomically(|p| {
+ if i == 0 || p.read_given_char(':').is_some() {
+ p.read_number(16, 4, 0x10000).map(|n| n as u16)
+ } else {
+ None
+ }
+ });
+ match group {
+ Some(g) => groups[i] = g,
+ None => return (i, false)
+ }
+ i += 1;
+ }
+ (i, false)
+ }
+
+ let mut head = [0; 8];
+ let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
+
+ if head_size == 8 {
+ return Some(Ipv6Addr::new(
+ head[0], head[1], head[2], head[3],
+ head[4], head[5], head[6], head[7]))
+ }
+
+ // IPv4 part is not allowed before `::`
+ if head_ipv4 {
+ return None
+ }
+
+ // read `::` if previous code parsed less than 8 groups
+ if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
+ return None;
+ }
+
+ let mut tail = [0; 8];
+ let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
+ Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
+ }
+
+ fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
+ self.read_atomically(|p| p.read_ipv6_addr_impl())
+ }
+
+ /* Additions for IpNet below. */
+
+ // Read IPv4 network
+ fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
+ let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
+ let slash = |p: &mut Parser| p.read_given_char('/');
+ let prefix_len = |p: &mut Parser| {
+ p.read_number(10, 2, 33).map(|n| n as u8)
+ };
+
+ self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
+ let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
+ Ipv4Net::new(ip, prefix_len).unwrap()
+ })
+ }
+
+ // Read Ipv6 network
+ fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
+ let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
+ let slash = |p: &mut Parser| p.read_given_char('/');
+ let prefix_len = |p: &mut Parser| {
+ p.read_number(10, 3, 129).map(|n| n as u8)
+ };
+
+ self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
+ let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
+ Ipv6Net::new(ip, prefix_len).unwrap()
+ })
+ }
+
+ fn read_ip_net(&mut self) -> Option<IpNet> {
+ let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
+ let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
+ self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
+ }
+
+ /* Additions for IpNet above. */
+}
+
+/* Additions for IpNet below. */
+
+impl FromStr for IpNet {
+ type Err = AddrParseError;
+ fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
+ match Parser::new(s).read_till_eof(|p| p.read_ip_net()) {
+ Some(s) => Ok(s),
+ None => Err(AddrParseError(()))
+ }
+ }
+}
+
+impl FromStr for Ipv4Net {
+ type Err = AddrParseError;
+ fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
+ match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) {
+ Some(s) => Ok(s),
+ None => Err(AddrParseError(()))
+ }
+ }
+}
+
+impl FromStr for Ipv6Net {
+ type Err = AddrParseError;
+ fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
+ match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) {
+ Some(s) => Ok(s),
+ None => Err(AddrParseError(()))
+ }
+ }
+}
+
+/* Additions for IpNet above. */
+
+/// An error which can be returned when parsing an IP network address.
+///
+/// This error is used as the error type for the [`FromStr`] implementation for
+/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
+///
+/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
+/// [`IpNet`]: enum.IpNet.html
+/// [`Ipv4Net`]: struct.Ipv4Net.html
+/// [`Ipv6Net`]: struct.Ipv6Net.html
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct AddrParseError(());
+
+impl fmt::Display for AddrParseError {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.write_str("invalid IP address syntax")
+ }
+}
+
+impl Error for AddrParseError {}