use alloc::vec::Vec;
use core::cmp::{min, max};
use core::cmp::Ordering::{Less, Equal};
use core::convert::From;
use core::fmt;
use core::iter::FusedIterator;
use core::option::Option::{Some, None};
#[cfg(not(feature = "std"))]
use core::error::Error;
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(not(feature = "std"))]
use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
#[cfg(feature = "std")]
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use crate::ipext::{IpAdd, IpSub, IpStep, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
use crate::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix};
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum IpNet {
V4(Ipv4Net),
V6(Ipv6Net),
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Ipv4Net {
addr: Ipv4Addr,
prefix_len: u8,
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Ipv6Net {
addr: Ipv6Addr,
prefix_len: u8,
}
#[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 {
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(),
})
}
pub const fn new_assert(ip: IpAddr, prefix_len: u8) -> IpNet {
match ip {
IpAddr::V4(a) => IpNet::V4(Ipv4Net::new_assert(a, prefix_len)),
IpAddr::V6(a) => IpNet::V6(Ipv6Net::new_assert(a, prefix_len)),
}
}
pub fn with_netmask(ip: IpAddr, netmask: IpAddr) -> Result<IpNet, PrefixLenError> {
let prefix = ip_mask_to_prefix(netmask)?;
Self::new(ip, prefix)
}
pub fn trunc(&self) -> IpNet {
match *self {
IpNet::V4(ref a) => IpNet::V4(a.trunc()),
IpNet::V6(ref a) => IpNet::V6(a.trunc()),
}
}
pub fn addr(&self) -> IpAddr {
match *self {
IpNet::V4(ref a) => IpAddr::V4(a.addr),
IpNet::V6(ref a) => IpAddr::V6(a.addr),
}
}
pub fn prefix_len(&self) -> u8 {
match *self {
IpNet::V4(ref a) => a.prefix_len(),
IpNet::V6(ref a) => a.prefix_len(),
}
}
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(),
}
}
pub fn netmask(&self) -> IpAddr {
match *self {
IpNet::V4(ref a) => IpAddr::V4(a.netmask()),
IpNet::V6(ref a) => IpAddr::V6(a.netmask()),
}
}
pub fn hostmask(&self) -> IpAddr {
match *self {
IpNet::V4(ref a) => IpAddr::V4(a.hostmask()),
IpNet::V6(ref a) => IpAddr::V6(a.hostmask()),
}
}
pub fn network(&self) -> IpAddr {
match *self {
IpNet::V4(ref a) => IpAddr::V4(a.network()),
IpNet::V6(ref a) => IpAddr::V6(a.network()),
}
}
pub fn broadcast(&self) -> IpAddr {
match *self {
IpNet::V4(ref a) => IpAddr::V4(a.broadcast()),
IpNet::V6(ref a) => IpAddr::V6(a.broadcast()),
}
}
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),
}
}
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,
}
}
pub fn hosts(&self) -> IpAddrRange {
match *self {
IpNet::V4(ref a) => IpAddrRange::V4(a.hosts()),
IpNet::V6(ref a) => IpAddrRange::V6(a.hosts()),
}
}
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),
}
}
pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
Contains::contains(self, other)
}
pub fn aggregate(networks: &Vec<IpNet>) -> Vec<IpNet> {
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 {
#[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 })
}
#[inline]
pub const fn new_assert(ip: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
assert!(prefix_len <= 32, "PREFIX_LEN must be less then or equal to 32 for Ipv4Net");
Ipv4Net { addr: ip, prefix_len: prefix_len }
}
pub fn with_netmask(ip: Ipv4Addr, netmask: Ipv4Addr) -> Result<Ipv4Net, PrefixLenError> {
let prefix = ipv4_mask_to_prefix(netmask)?;
Self::new(ip, prefix)
}
pub fn trunc(&self) -> Ipv4Net {
Ipv4Net::new(self.network(), self.prefix_len).unwrap()
}
#[inline]
pub const fn addr(&self) -> Ipv4Addr {
self.addr
}
#[inline]
pub const fn prefix_len(&self) -> u8 {
self.prefix_len
}
#[inline]
pub const fn max_prefix_len(&self) -> u8 {
32
}
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)
}
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)
}
pub fn network(&self) -> Ipv4Addr {
Ipv4Addr::from(u32::from(self.addr) & self.netmask_u32())
}
pub fn broadcast(&self) -> Ipv4Addr {
Ipv4Addr::from(u32::from(self.addr) | self.hostmask_u32())
}
pub fn supernet(&self) -> Option<Ipv4Net> {
Ipv4Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok()
}
pub fn is_sibling(&self, other: &Ipv4Net) -> bool {
self.prefix_len > 0 &&
self.prefix_len == other.prefix_len &&
self.supernet().unwrap().contains(other)
}
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)
}
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,
))
}
pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
Contains::contains(self, other)
}
fn interval(&self) -> (u32, u32) {
(
u32::from(self.network()),
u32::from(self.broadcast()).saturating_add(1),
)
}
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 != core::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 {
#[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 })
}
#[inline]
pub const fn new_assert(ip: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
assert!(prefix_len <= 128, "PREFIX_LEN must be less then or equal to 128 for Ipv6Net");
Ipv6Net { addr: ip, prefix_len: prefix_len }
}
pub fn with_netmask(ip: Ipv6Addr, netmask: Ipv6Addr) -> Result<Ipv6Net, PrefixLenError> {
let prefix = ipv6_mask_to_prefix(netmask)?;
Self::new(ip, prefix)
}
pub fn trunc(&self) -> Ipv6Net {
Ipv6Net::new(self.network(), self.prefix_len).unwrap()
}
#[inline]
pub const fn addr(&self) -> Ipv6Addr {
self.addr
}
#[inline]
pub const fn prefix_len(&self) -> u8 {
self.prefix_len
}
#[inline]
pub const fn max_prefix_len(&self) -> u8 {
128
}
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())
}
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())
}
pub fn network(&self) -> Ipv6Addr {
(u128::from(self.addr) & self.netmask_u128()).into()
}
pub fn broadcast(&self) -> Ipv6Addr {
(u128::from(self.addr) | self.hostmask_u128()).into()
}
pub fn supernet(&self) -> Option<Ipv6Net> {
Ipv6Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok()
}
pub fn is_sibling(&self, other: &Ipv6Net) -> bool {
self.prefix_len > 0 &&
self.prefix_len == other.prefix_len &&
self.supernet().unwrap().contains(other)
}
pub fn hosts(&self) -> Ipv6AddrRange {
Ipv6AddrRange::new(self.network(), self.broadcast())
}
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,
))
}
pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
Contains::contains(self, other)
}
fn interval(&self) -> (u128, u128) {
(
u128::from(self.network()),
u128::from(self.broadcast()).saturating_add(1),
)
}
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 != core::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 }
}
}
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()
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum IpSubnets {
V4(Ipv4Subnets),
V6(Ipv6Subnets),
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Ipv4Subnets {
start: Ipv4Addr,
end: Ipv4Addr, min_prefix_len: u8,
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Ipv6Subnets {
start: Ipv6Addr,
end: Ipv6Addr, 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 == core::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 == core::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);
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);
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 {}
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());
}
#[test]
fn new_assert() {
const _: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 0);
const _: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 32);
const _: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0);
const _: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128);
let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 0);
let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 32);
let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0);
let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128);
}
#[test]
#[should_panic]
fn ipv4net_new_assert_panics() {
let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 33);
}
#[test]
#[should_panic]
fn ipv6net_new_assert_panics() {
let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 129);
}
}