1use alloc::vec::Vec;
2use core::cmp::max;
3use core::cmp::Ordering::{Less, Equal};
4use core::convert::From;
5use core::fmt;
6use core::iter::FusedIterator;
7use core::option::Option::{Some, None};
8#[cfg(not(feature = "std"))]
9use core::error::Error;
10#[cfg(feature = "std")]
11use std::error::Error;
12#[cfg(not(feature = "std"))]
13use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
14#[cfg(feature = "std")]
15use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
16
17use crate::ipext::{IpAdd, IpSub, IpStep, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
18use crate::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix};
19
20#[derive(#[automatically_derived]
impl ::core::marker::Copy for IpNet { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for IpNet { }
#[automatically_derived]
impl ::core::clone::Clone for IpNet {
#[inline]
fn clone(&self) -> IpNet {
let _: ::core::clone::AssertParamIsClone<Ipv4Net>;
let _: ::core::clone::AssertParamIsClone<Ipv6Net>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for IpNet {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ipv4Net>;
let _: ::core::cmp::AssertParamIsEq<Ipv6Net>;
}
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for IpNet { }
#[automatically_derived]
impl ::core::cmp::PartialEq for IpNet {
#[inline]
fn eq(&self, other: &IpNet) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(IpNet::V4(__self_0), IpNet::V4(__arg1_0)) =>
__self_0 == __arg1_0,
(IpNet::V6(__self_0), IpNet::V6(__arg1_0)) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Ord for IpNet {
#[inline]
fn cmp(&self, other: &IpNet) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(IpNet::V4(__self_0), IpNet::V4(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(IpNet::V6(__self_0), IpNet::V6(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for IpNet {
#[inline]
fn partial_cmp(&self, other: &IpNet)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]
impl ::core::hash::Hash for IpNet {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
IpNet::V4(__self_0) => ::core::hash::Hash::hash(__self_0, state),
IpNet::V6(__self_0) => ::core::hash::Hash::hash(__self_0, state),
}
}
}Hash)]
51pub enum IpNet {
52 V4(Ipv4Net),
53 V6(Ipv6Net),
54}
55
56#[derive(#[automatically_derived]
impl ::core::marker::Copy for Ipv4Net { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Ipv4Net { }
#[automatically_derived]
impl ::core::clone::Clone for Ipv4Net {
#[inline]
fn clone(&self) -> Ipv4Net {
let _: ::core::clone::AssertParamIsClone<Ipv4Addr>;
let _: ::core::clone::AssertParamIsClone<u8>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for Ipv4Net {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ipv4Addr>;
let _: ::core::cmp::AssertParamIsEq<u8>;
}
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Ipv4Net { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Ipv4Net {
#[inline]
fn eq(&self, other: &Ipv4Net) -> bool {
self.prefix_len == other.prefix_len && self.addr == other.addr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Ord for Ipv4Net {
#[inline]
fn cmp(&self, other: &Ipv4Net) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.addr, &other.addr) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.prefix_len, &other.prefix_len),
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for Ipv4Net {
#[inline]
fn partial_cmp(&self, other: &Ipv4Net)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]
impl ::core::hash::Hash for Ipv4Net {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.addr, state);
::core::hash::Hash::hash(&self.prefix_len, state)
}
}Hash)]
84pub struct Ipv4Net {
85 addr: Ipv4Addr,
86 prefix_len: u8,
87}
88
89#[derive(#[automatically_derived]
impl ::core::marker::Copy for Ipv6Net { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Ipv6Net { }
#[automatically_derived]
impl ::core::clone::Clone for Ipv6Net {
#[inline]
fn clone(&self) -> Ipv6Net {
let _: ::core::clone::AssertParamIsClone<Ipv6Addr>;
let _: ::core::clone::AssertParamIsClone<u8>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for Ipv6Net {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ipv6Addr>;
let _: ::core::cmp::AssertParamIsEq<u8>;
}
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Ipv6Net { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Ipv6Net {
#[inline]
fn eq(&self, other: &Ipv6Net) -> bool {
self.prefix_len == other.prefix_len && self.addr == other.addr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Ord for Ipv6Net {
#[inline]
fn cmp(&self, other: &Ipv6Net) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.addr, &other.addr) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.prefix_len, &other.prefix_len),
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for Ipv6Net {
#[inline]
fn partial_cmp(&self, other: &Ipv6Net)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]
impl ::core::hash::Hash for Ipv6Net {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.addr, state);
::core::hash::Hash::hash(&self.prefix_len, state)
}
}Hash)]
114pub struct Ipv6Net {
115 addr: Ipv6Addr,
116 prefix_len: u8,
117}
118
119#[derive(#[automatically_derived]
impl ::core::fmt::Debug for PrefixLenError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "PrefixLenError")
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for PrefixLenError {
#[inline]
fn clone(&self) -> PrefixLenError { PrefixLenError }
}Clone, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for PrefixLenError { }
#[automatically_derived]
impl ::core::cmp::PartialEq for PrefixLenError {
#[inline]
fn eq(&self, other: &PrefixLenError) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PrefixLenError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
123pub struct PrefixLenError;
124
125impl fmt::Display for PrefixLenError {
126 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
127 fmt.write_str("invalid IP prefix length")
128 }
129}
130
131impl Error for PrefixLenError {}
132
133impl IpNet {
134 pub fn new(ip: IpAddr, prefix_len: u8) -> Result<IpNet, PrefixLenError> {
150 Ok(match ip {
151 IpAddr::V4(a) => Ipv4Net::new(a, prefix_len)?.into(),
152 IpAddr::V6(a) => Ipv6Net::new(a, prefix_len)?.into(),
153 })
154 }
155
156 pub const fn new_assert(ip: IpAddr, prefix_len: u8) -> IpNet {
182 match ip {
183 IpAddr::V4(a) => IpNet::V4(Ipv4Net::new_assert(a, prefix_len)),
184 IpAddr::V6(a) => IpNet::V6(Ipv6Net::new_assert(a, prefix_len)),
185 }
186 }
187
188 pub fn with_netmask(ip: IpAddr, netmask: IpAddr) -> Result<IpNet, PrefixLenError> {
203 let prefix = ip_mask_to_prefix(netmask)?;
204 Self::new(ip, prefix)
205 }
206
207 pub fn trunc(&self) -> IpNet {
226 match *self {
227 IpNet::V4(ref a) => IpNet::V4(a.trunc()),
228 IpNet::V6(ref a) => IpNet::V6(a.trunc()),
229 }
230 }
231
232 pub fn addr(&self) -> IpAddr {
234 match *self {
235 IpNet::V4(ref a) => IpAddr::V4(a.addr),
236 IpNet::V6(ref a) => IpAddr::V6(a.addr),
237 }
238 }
239
240 pub fn prefix_len(&self) -> u8 {
242 match *self {
243 IpNet::V4(ref a) => a.prefix_len(),
244 IpNet::V6(ref a) => a.prefix_len(),
245 }
246 }
247
248 pub fn max_prefix_len(&self) -> u8 {
250 match *self {
251 IpNet::V4(ref a) => a.max_prefix_len(),
252 IpNet::V6(ref a) => a.max_prefix_len(),
253 }
254 }
255
256 pub fn netmask(&self) -> IpAddr {
271 match *self {
272 IpNet::V4(ref a) => IpAddr::V4(a.netmask()),
273 IpNet::V6(ref a) => IpAddr::V6(a.netmask()),
274 }
275 }
276
277 pub fn hostmask(&self) -> IpAddr {
292 match *self {
293 IpNet::V4(ref a) => IpAddr::V4(a.hostmask()),
294 IpNet::V6(ref a) => IpAddr::V6(a.hostmask()),
295 }
296 }
297
298 pub fn network(&self) -> IpAddr {
313 match *self {
314 IpNet::V4(ref a) => IpAddr::V4(a.network()),
315 IpNet::V6(ref a) => IpAddr::V6(a.network()),
316 }
317 }
318
319 pub fn broadcast(&self) -> IpAddr {
334 match *self {
335 IpNet::V4(ref a) => IpAddr::V4(a.broadcast()),
336 IpNet::V6(ref a) => IpAddr::V6(a.broadcast()),
337 }
338 }
339
340 pub fn supernet(&self) -> Option<IpNet> {
362 match *self {
363 IpNet::V4(ref a) => a.supernet().map(IpNet::V4),
364 IpNet::V6(ref a) => a.supernet().map(IpNet::V6),
365 }
366 }
367
368 pub fn is_sibling(&self, other: &IpNet) -> bool {
390 match (*self, *other) {
391 (IpNet::V4(ref a), IpNet::V4(ref b)) => a.is_sibling(b),
392 (IpNet::V6(ref a), IpNet::V6(ref b)) => a.is_sibling(b),
393 _ => false,
394 }
395 }
396
397 pub fn hosts(&self) -> IpAddrRange {
426 match *self {
427 IpNet::V4(ref a) => IpAddrRange::V4(a.hosts()),
428 IpNet::V6(ref a) => IpAddrRange::V6(a.hosts()),
429 }
430 }
431
432 pub fn subnets(&self, new_prefix_len: u8) -> Result<IpSubnets, PrefixLenError> {
469 match *self {
470 IpNet::V4(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V4),
471 IpNet::V6(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V6),
472 }
473 }
474
475 pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
515 Contains::contains(self, other)
516 }
517
518 pub fn aggregate(networks: &Vec<IpNet>) -> Vec<IpNet> {
543 let mut ipv4nets: Vec<Ipv4Net> = Vec::new();
547 let mut ipv6nets: Vec<Ipv6Net> = Vec::new();
548
549 for n in networks {
550 match *n {
551 IpNet::V4(x) => ipv4nets.push(x),
552 IpNet::V6(x) => ipv6nets.push(x),
553 }
554 }
555
556 let mut res: Vec<IpNet> = Vec::new();
557 let ipv4aggs = Ipv4Net::aggregate(&ipv4nets);
558 let ipv6aggs = Ipv6Net::aggregate(&ipv6nets);
559 res.extend::<Vec<IpNet>>(ipv4aggs.into_iter().map(IpNet::V4).collect::<Vec<IpNet>>());
560 res.extend::<Vec<IpNet>>(ipv6aggs.into_iter().map(IpNet::V6).collect::<Vec<IpNet>>());
561 res
562 }
563}
564
565impl Default for IpNet {
566 fn default() -> Self {
567 Self::V4(Ipv4Net::default())
568 }
569}
570
571impl fmt::Debug for IpNet {
572 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
573 fmt::Display::fmt(self, fmt)
574 }
575}
576
577impl fmt::Display for IpNet {
578 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
579 match *self {
580 IpNet::V4(ref a) => a.fmt(fmt),
581 IpNet::V6(ref a) => a.fmt(fmt),
582 }
583 }
584}
585
586impl From<Ipv4Net> for IpNet {
587 fn from(net: Ipv4Net) -> IpNet {
588 IpNet::V4(net)
589 }
590}
591
592impl From<Ipv6Net> for IpNet {
593 fn from(net: Ipv6Net) -> IpNet {
594 IpNet::V6(net)
595 }
596}
597
598impl From<IpAddr> for IpNet {
599 fn from(addr: IpAddr) -> IpNet {
600 match addr {
601 IpAddr::V4(a) => IpNet::V4(a.into()),
602 IpAddr::V6(a) => IpNet::V6(a.into()),
603 }
604 }
605}
606
607impl Ipv4Net {
608 #[inline]
624 pub const fn new(ip: Ipv4Addr, prefix_len: u8) -> Result<Ipv4Net, PrefixLenError> {
625 if prefix_len > 32 {
626 return Err(PrefixLenError);
627 }
628 Ok(Ipv4Net { addr: ip, prefix_len: prefix_len })
629 }
630
631 #[inline]
657 pub const fn new_assert(ip: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
658 if !(prefix_len <= 32) {
::core::panicking::panic("prefix_len must be less than or equal to 32 for Ipv4Net")
};assert!(prefix_len <= 32, "prefix_len must be less than or equal to 32 for Ipv4Net");
659 Ipv4Net { addr: ip, prefix_len: prefix_len }
660 }
661
662 pub fn with_netmask(ip: Ipv4Addr, netmask: Ipv4Addr) -> Result<Ipv4Net, PrefixLenError> {
677 let prefix = ipv4_mask_to_prefix(netmask)?;
678 Self::new(ip, prefix)
679 }
680
681 pub fn trunc(&self) -> Ipv4Net {
695 Ipv4Net::new(self.network(), self.prefix_len).unwrap()
696 }
697
698 #[inline]
700 pub const fn addr(&self) -> Ipv4Addr {
701 self.addr
702 }
703
704 #[inline]
706 pub const fn prefix_len(&self) -> u8 {
707 self.prefix_len
708 }
709
710 #[inline]
712 pub const fn max_prefix_len(&self) -> u8 {
713 32
714 }
715
716 pub fn netmask(&self) -> Ipv4Addr {
728 Ipv4Addr::from(self.netmask_u32())
729 }
730
731 fn netmask_u32(&self) -> u32 {
732 u32::max_value().checked_shl(32 - self.prefix_len as u32).unwrap_or(0)
733 }
734
735 pub fn hostmask(&self) -> Ipv4Addr {
747 Ipv4Addr::from(self.hostmask_u32())
748 }
749
750 fn hostmask_u32(&self) -> u32 {
751 u32::max_value().checked_shr(self.prefix_len as u32).unwrap_or(0)
752 }
753
754 pub fn network(&self) -> Ipv4Addr {
766 Ipv4Addr::from(u32::from(self.addr) & self.netmask_u32())
767 }
768
769 pub fn broadcast(&self) -> Ipv4Addr {
781 Ipv4Addr::from(u32::from(self.addr) | self.hostmask_u32())
782 }
783
784 pub fn supernet(&self) -> Option<Ipv4Net> {
799 Ipv4Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok()
800 }
801
802 pub fn is_sibling(&self, other: &Ipv4Net) -> bool {
818 self.prefix_len > 0 &&
819 self.prefix_len == other.prefix_len &&
820 self.supernet().unwrap().contains(other)
821 }
822
823 pub fn hosts(&self) -> Ipv4AddrRange {
848 let mut start = self.network();
849 let mut end = self.broadcast();
850
851 if self.prefix_len < 31 {
852 start = start.saturating_add(1);
853 end = end.saturating_sub(1);
854 }
855
856 Ipv4AddrRange::new(start, end)
857 }
858
859 pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv4Subnets, PrefixLenError> {
890 if self.prefix_len > new_prefix_len || new_prefix_len > 32 {
891 return Err(PrefixLenError);
892 }
893
894 Ok(Ipv4Subnets::new(
895 self.network(),
896 self.broadcast(),
897 new_prefix_len,
898 ))
899 }
900
901 pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
923 Contains::contains(self, other)
924 }
925
926 pub fn aggregate(networks: &Vec<Ipv4Net>) -> Vec<Ipv4Net> {
945 if networks.is_empty() {
946 return Vec::new();
947 }
948
949 let mut intervals: Vec<(u32, u32)> = networks.iter().map(|n| {
950 (u32::from(n.network()), u32::from(n.broadcast()))
951 }).collect();
952
953 intervals.sort_unstable();
954
955 let mut merged: Vec<(u32, u32)> = Vec::with_capacity(intervals.len());
956
957 for (start, end) in intervals {
958 if let Some((_, current_end)) = merged.last_mut() {
959 if start <= current_end.saturating_add(1) {
960 *current_end = (*current_end).max(end);
961 continue;
962 }
963 }
964
965 merged.push((start, end));
966 }
967
968 let mut res: Vec<Ipv4Net> = Vec::new();
969
970 for (start, end) in merged {
971 res.extend(Ipv4Subnets::new(start.into(), end.into(), 0));
972 }
973
974 res
975 }
976}
977
978impl Default for Ipv4Net {
979 fn default() -> Self {
980 Self {
981 addr: Ipv4Addr::from(0),
982 prefix_len: 0,
983 }
984 }
985}
986
987impl fmt::Debug for Ipv4Net {
988 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
989 fmt::Display::fmt(self, fmt)
990 }
991}
992
993impl fmt::Display for Ipv4Net {
994 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
995 fmt.write_fmt(format_args!("{0}/{1}", self.addr, self.prefix_len))write!(fmt, "{}/{}", self.addr, self.prefix_len)
996 }
997}
998
999impl From<Ipv4Addr> for Ipv4Net {
1000 fn from(addr: Ipv4Addr) -> Ipv4Net {
1001 Ipv4Net { addr, prefix_len: 32 }
1002 }
1003}
1004
1005impl Ipv6Net {
1006 #[inline]
1022 pub const fn new(ip: Ipv6Addr, prefix_len: u8) -> Result<Ipv6Net, PrefixLenError> {
1023 if prefix_len > 128 {
1024 return Err(PrefixLenError);
1025 }
1026 Ok(Ipv6Net { addr: ip, prefix_len: prefix_len })
1027 }
1028
1029 #[inline]
1055 pub const fn new_assert(ip: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
1056 if !(prefix_len <= 128) {
::core::panicking::panic("prefix_len must be less than or equal to 128 for Ipv6Net")
};assert!(prefix_len <= 128, "prefix_len must be less than or equal to 128 for Ipv6Net");
1057 Ipv6Net { addr: ip, prefix_len: prefix_len }
1058 }
1059
1060 pub fn with_netmask(ip: Ipv6Addr, netmask: Ipv6Addr) -> Result<Ipv6Net, PrefixLenError> {
1075 let prefix = ipv6_mask_to_prefix(netmask)?;
1076 Self::new(ip, prefix)
1077 }
1078
1079 pub fn trunc(&self) -> Ipv6Net {
1093 Ipv6Net::new(self.network(), self.prefix_len).unwrap()
1094 }
1095
1096 #[inline]
1098 pub const fn addr(&self) -> Ipv6Addr {
1099 self.addr
1100 }
1101
1102 #[inline]
1104 pub const fn prefix_len(&self) -> u8 {
1105 self.prefix_len
1106 }
1107
1108 #[inline]
1110 pub const fn max_prefix_len(&self) -> u8 {
1111 128
1112 }
1113
1114 pub fn netmask(&self) -> Ipv6Addr {
1126 self.netmask_u128().into()
1127 }
1128
1129 fn netmask_u128(&self) -> u128 {
1130 u128::max_value().checked_shl((128 - self.prefix_len) as u32).unwrap_or(u128::min_value())
1131 }
1132
1133 pub fn hostmask(&self) -> Ipv6Addr {
1145 self.hostmask_u128().into()
1146 }
1147
1148 fn hostmask_u128(&self) -> u128 {
1149 u128::max_value().checked_shr(self.prefix_len as u32).unwrap_or(u128::min_value())
1150 }
1151
1152 pub fn network(&self) -> Ipv6Addr {
1164 (u128::from(self.addr) & self.netmask_u128()).into()
1165 }
1166
1167 pub fn broadcast(&self) -> Ipv6Addr {
1182 (u128::from(self.addr) | self.hostmask_u128()).into()
1183 }
1184
1185 pub fn supernet(&self) -> Option<Ipv6Net> {
1201 Ipv6Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok()
1202 }
1203
1204 pub fn is_sibling(&self, other: &Ipv6Net) -> bool {
1220 self.prefix_len > 0 &&
1221 self.prefix_len == other.prefix_len &&
1222 self.supernet().unwrap().contains(other)
1223 }
1224
1225 pub fn hosts(&self) -> Ipv6AddrRange {
1242 Ipv6AddrRange::new(self.network(), self.broadcast())
1243 }
1244
1245 pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv6Subnets, PrefixLenError> {
1276 if self.prefix_len > new_prefix_len || new_prefix_len > 128 {
1277 return Err(PrefixLenError);
1278 }
1279
1280 Ok(Ipv6Subnets::new(
1281 self.network(),
1282 self.broadcast(),
1283 new_prefix_len,
1284 ))
1285 }
1286
1287 pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> {
1309 Contains::contains(self, other)
1310 }
1311
1312 pub fn aggregate(networks: &Vec<Ipv6Net>) -> Vec<Ipv6Net> {
1331 if networks.is_empty() {
1332 return Vec::new();
1333 }
1334
1335 let mut intervals: Vec<(u128, u128)> = networks.iter().map(|n| {
1336 (u128::from(n.network()), u128::from(n.broadcast()))
1337 }).collect();
1338
1339 intervals.sort_unstable();
1340
1341 let mut merged: Vec<(u128, u128)> = Vec::with_capacity(intervals.len());
1342
1343 for (start, end) in intervals {
1344 if let Some((_, current_end)) = merged.last_mut() {
1345 if start <= current_end.saturating_add(1) {
1346 *current_end = (*current_end).max(end);
1347 continue;
1348 }
1349 }
1350
1351 merged.push((start, end));
1352 }
1353
1354 let mut res: Vec<Ipv6Net> = Vec::new();
1355
1356 for (start, end) in merged {
1357 res.extend(Ipv6Subnets::new(start.into(), end.into(), 0));
1358 }
1359
1360 res
1361 }
1362}
1363
1364impl Default for Ipv6Net {
1365 fn default() -> Self {
1366 Self {
1367 addr: Ipv6Addr::from(0),
1368 prefix_len: 0,
1369 }
1370 }
1371}
1372
1373impl fmt::Debug for Ipv6Net {
1374 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1375 fmt::Display::fmt(self, fmt)
1376 }
1377}
1378
1379impl fmt::Display for Ipv6Net {
1380 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1381 fmt.write_fmt(format_args!("{0}/{1}", self.addr, self.prefix_len))write!(fmt, "{}/{}", self.addr, self.prefix_len)
1382 }
1383}
1384
1385impl From<Ipv6Addr> for Ipv6Net {
1386 fn from(addr: Ipv6Addr) -> Ipv6Net {
1387 Ipv6Net { addr, prefix_len: 128 }
1388 }
1389}
1390
1391pub trait Contains<T> {
1426 fn contains(&self, other: T) -> bool;
1427}
1428
1429impl<'a> Contains<&'a IpNet> for IpNet {
1430 fn contains(&self, other: &IpNet) -> bool {
1431 match (*self, *other) {
1432 (IpNet::V4(ref a), IpNet::V4(ref b)) => a.contains(b),
1433 (IpNet::V6(ref a), IpNet::V6(ref b)) => a.contains(b),
1434 _ => false,
1435 }
1436 }
1437}
1438
1439impl<'a> Contains<&'a IpAddr> for IpNet {
1440 fn contains(&self, other: &IpAddr) -> bool {
1441 match (*self, *other) {
1442 (IpNet::V4(ref a), IpAddr::V4(ref b)) => a.contains(b),
1443 (IpNet::V6(ref a), IpAddr::V6(ref b)) => a.contains(b),
1444 _ => false,
1445 }
1446 }
1447}
1448
1449impl<'a> Contains<&'a Ipv4Net> for Ipv4Net {
1450 fn contains(&self, other: &'a Ipv4Net) -> bool {
1451 self.network() <= other.network() && other.broadcast() <= self.broadcast()
1452 }
1453}
1454
1455impl<'a> Contains<&'a Ipv4Addr> for Ipv4Net {
1456 fn contains(&self, other: &'a Ipv4Addr) -> bool {
1457 self.network() <= *other && *other <= self.broadcast()
1458 }
1459}
1460
1461impl<'a> Contains<&'a Ipv6Net> for Ipv6Net {
1462 fn contains(&self, other: &'a Ipv6Net) -> bool {
1463 self.network() <= other.network() && other.broadcast() <= self.broadcast()
1464 }
1465}
1466
1467impl<'a> Contains<&'a Ipv6Addr> for Ipv6Net {
1468 fn contains(&self, other: &'a Ipv6Addr) -> bool {
1469 self.network() <= *other && *other <= self.broadcast()
1470 }
1471}
1472
1473#[derive(#[automatically_derived]
impl ::core::marker::Copy for IpSubnets { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for IpSubnets { }
#[automatically_derived]
impl ::core::clone::Clone for IpSubnets {
#[inline]
fn clone(&self) -> IpSubnets {
let _: ::core::clone::AssertParamIsClone<Ipv4Subnets>;
let _: ::core::clone::AssertParamIsClone<Ipv6Subnets>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for IpSubnets {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ipv4Subnets>;
let _: ::core::cmp::AssertParamIsEq<Ipv6Subnets>;
}
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for IpSubnets { }
#[automatically_derived]
impl ::core::cmp::PartialEq for IpSubnets {
#[inline]
fn eq(&self, other: &IpSubnets) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(IpSubnets::V4(__self_0), IpSubnets::V4(__arg1_0)) =>
__self_0 == __arg1_0,
(IpSubnets::V6(__self_0), IpSubnets::V6(__arg1_0)) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Ord for IpSubnets {
#[inline]
fn cmp(&self, other: &IpSubnets) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(IpSubnets::V4(__self_0), IpSubnets::V4(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(IpSubnets::V6(__self_0), IpSubnets::V6(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for IpSubnets {
#[inline]
fn partial_cmp(&self, other: &IpSubnets)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]
impl ::core::hash::Hash for IpSubnets {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
IpSubnets::V4(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
IpSubnets::V6(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
}
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for IpSubnets {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
IpSubnets::V4(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "V4",
&__self_0),
IpSubnets::V6(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "V6",
&__self_0),
}
}
}Debug)]
1516pub enum IpSubnets {
1517 V4(Ipv4Subnets),
1518 V6(Ipv6Subnets),
1519}
1520
1521#[derive(#[automatically_derived]
impl ::core::marker::Copy for Ipv4Subnets { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Ipv4Subnets { }
#[automatically_derived]
impl ::core::clone::Clone for Ipv4Subnets {
#[inline]
fn clone(&self) -> Ipv4Subnets {
let _: ::core::clone::AssertParamIsClone<Ipv4Addr>;
let _: ::core::clone::AssertParamIsClone<u8>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for Ipv4Subnets {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ipv4Addr>;
let _: ::core::cmp::AssertParamIsEq<u8>;
}
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Ipv4Subnets { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Ipv4Subnets {
#[inline]
fn eq(&self, other: &Ipv4Subnets) -> bool {
self.min_prefix_len == other.min_prefix_len &&
self.start == other.start && self.end == other.end
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Ord for Ipv4Subnets {
#[inline]
fn cmp(&self, other: &Ipv4Subnets) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.start, &other.start) {
::core::cmp::Ordering::Equal =>
match ::core::cmp::Ord::cmp(&self.end, &other.end) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.min_prefix_len,
&other.min_prefix_len),
cmp => cmp,
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for Ipv4Subnets {
#[inline]
fn partial_cmp(&self, other: &Ipv4Subnets)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]
impl ::core::hash::Hash for Ipv4Subnets {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.start, state);
::core::hash::Hash::hash(&self.end, state);
::core::hash::Hash::hash(&self.min_prefix_len, state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Ipv4Subnets {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "Ipv4Subnets",
"start", &self.start, "end", &self.end, "min_prefix_len",
&&self.min_prefix_len)
}
}Debug)]
1549pub struct Ipv4Subnets {
1550 start: Ipv4Addr,
1551 end: Ipv4Addr, min_prefix_len: u8,
1553}
1554
1555#[derive(#[automatically_derived]
impl ::core::marker::Copy for Ipv6Subnets { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Ipv6Subnets { }
#[automatically_derived]
impl ::core::clone::Clone for Ipv6Subnets {
#[inline]
fn clone(&self) -> Ipv6Subnets {
let _: ::core::clone::AssertParamIsClone<Ipv6Addr>;
let _: ::core::clone::AssertParamIsClone<u8>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for Ipv6Subnets {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Ipv6Addr>;
let _: ::core::cmp::AssertParamIsEq<u8>;
}
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Ipv6Subnets { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Ipv6Subnets {
#[inline]
fn eq(&self, other: &Ipv6Subnets) -> bool {
self.min_prefix_len == other.min_prefix_len &&
self.start == other.start && self.end == other.end
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Ord for Ipv6Subnets {
#[inline]
fn cmp(&self, other: &Ipv6Subnets) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.start, &other.start) {
::core::cmp::Ordering::Equal =>
match ::core::cmp::Ord::cmp(&self.end, &other.end) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.min_prefix_len,
&other.min_prefix_len),
cmp => cmp,
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for Ipv6Subnets {
#[inline]
fn partial_cmp(&self, other: &Ipv6Subnets)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]
impl ::core::hash::Hash for Ipv6Subnets {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.start, state);
::core::hash::Hash::hash(&self.end, state);
::core::hash::Hash::hash(&self.min_prefix_len, state)
}
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Ipv6Subnets {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "Ipv6Subnets",
"start", &self.start, "end", &self.end, "min_prefix_len",
&&self.min_prefix_len)
}
}Debug)]
1583pub struct Ipv6Subnets {
1584 start: Ipv6Addr,
1585 end: Ipv6Addr, min_prefix_len: u8,
1587}
1588
1589impl Ipv4Subnets {
1590 pub fn new(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Self {
1591 Ipv4Subnets {
1592 start: start,
1593 end: end,
1594 min_prefix_len: min_prefix_len,
1595 }
1596 }
1597}
1598
1599impl Ipv6Subnets {
1600 pub fn new(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Self {
1601 Ipv6Subnets {
1602 start: start,
1603 end: end,
1604 min_prefix_len: min_prefix_len,
1605 }
1606 }
1607}
1608
1609impl From<Ipv4Subnets> for IpSubnets {
1610 fn from(i: Ipv4Subnets) -> IpSubnets {
1611 IpSubnets::V4(i)
1612 }
1613}
1614
1615impl From<Ipv6Subnets> for IpSubnets {
1616 fn from(i: Ipv6Subnets) -> IpSubnets {
1617 IpSubnets::V6(i)
1618 }
1619}
1620
1621impl Iterator for IpSubnets {
1622 type Item = IpNet;
1623
1624 fn next(&mut self) -> Option<Self::Item> {
1625 match *self {
1626 IpSubnets::V4(ref mut a) => a.next().map(IpNet::V4),
1627 IpSubnets::V6(ref mut a) => a.next().map(IpNet::V6),
1628 }
1629 }
1630}
1631
1632fn next_ipv4_subnet(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Ipv4Net {
1633 let range = u32::from(end) - u32::from(start);
1634 let range_lz = range.leading_zeros();
1635 let range_pl = if range_lz + range.trailing_ones() == u32::BITS { range_lz } else { range_lz + 1 };
1636 let start_pl = 32 - u32::from(start).trailing_zeros();
1637 let new_prefix_len = max(max(range_pl as u8, start_pl as u8), min_prefix_len);
1638 Ipv4Net::new(start, new_prefix_len).unwrap()
1639}
1640
1641fn next_ipv6_subnet(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Ipv6Net {
1642 let range = u128::from(end) - u128::from(start);
1643 let range_lz = range.leading_zeros();
1644 let range_pl = if range_lz + range.trailing_ones() == u128::BITS { range_lz } else { range_lz + 1 };
1645 let start_pl = 128 - u128::from(start).trailing_zeros();
1646 let new_prefix_len = max(max(range_pl as u8, start_pl as u8), min_prefix_len);
1647 Ipv6Net::new(start, new_prefix_len).unwrap()
1648}
1649
1650impl Iterator for Ipv4Subnets {
1651 type Item = Ipv4Net;
1652
1653 fn next(&mut self) -> Option<Self::Item> {
1654 match self.start.partial_cmp(&self.end) {
1655 Some(Less) => {
1656 let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len);
1657 self.start = next.broadcast().saturating_add(1);
1658
1659 if self.start == next.broadcast() {
1661 self.end.replace_zero();
1662 }
1663 Some(next)
1664 },
1665 Some(Equal) => {
1666 let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len);
1667 self.start = next.broadcast().saturating_add(1);
1668 self.end.replace_zero();
1669 Some(next)
1670 },
1671 _ => None,
1672 }
1673 }
1674}
1675
1676impl Iterator for Ipv6Subnets {
1677 type Item = Ipv6Net;
1678
1679 fn next(&mut self) -> Option<Self::Item> {
1680 match self.start.partial_cmp(&self.end) {
1681 Some(Less) => {
1682 let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len);
1683 self.start = next.broadcast().saturating_add(1);
1684
1685 if self.start == next.broadcast() {
1687 self.end.replace_zero();
1688 }
1689 Some(next)
1690 },
1691 Some(Equal) => {
1692 let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len);
1693 self.start = next.broadcast().saturating_add(1);
1694 self.end.replace_zero();
1695 Some(next)
1696 },
1697 _ => None,
1698 }
1699 }
1700}
1701
1702impl FusedIterator for IpSubnets {}
1703impl FusedIterator for Ipv4Subnets {}
1704impl FusedIterator for Ipv6Subnets {}
1705
1706#[cfg(test)]
1707mod tests {
1708 use super::*;
1709
1710 macro_rules! make_ipnet_vec {
1711 ($($x:expr),*) => ( vec![$($x.parse::<IpNet>().unwrap(),)*] );
1712 ($($x:expr,)*) => ( make_ipnet_vec![$($x),*] );
1713 }
1714
1715 #[test]
1716 fn test_make_ipnet_vec() {
1717 assert_eq!(
1718 make_ipnet_vec![
1719 "10.1.1.1/32", "10.2.2.2/24", "10.3.3.3/16",
1720 "fd00::1/128", "fd00::2/127", "fd00::3/126",
1721 ],
1722 vec![
1723 "10.1.1.1/32".parse().unwrap(),
1724 "10.2.2.2/24".parse().unwrap(),
1725 "10.3.3.3/16".parse().unwrap(),
1726 "fd00::1/128".parse().unwrap(),
1727 "fd00::2/127".parse().unwrap(),
1728 "fd00::3/126".parse().unwrap(),
1729 ]
1730 );
1731 }
1732
1733 macro_rules! make_ipv4_subnets_test {
1734 ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => (
1735 #[test]
1736 fn $name() {
1737 let subnets = IpSubnets::from(Ipv4Subnets::new(
1738 $start.parse().unwrap(),
1739 $end.parse().unwrap(),
1740 $min_prefix_len,
1741 ));
1742 let results = make_ipnet_vec![$($x),*];
1743 assert_eq!(subnets.collect::<Vec<IpNet>>(), results);
1744 }
1745 );
1746 ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => (
1747 make_ipv4_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*);
1748 );
1749 }
1750
1751 macro_rules! make_ipv6_subnets_test {
1752 ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => (
1753 #[test]
1754 fn $name() {
1755 let subnets = IpSubnets::from(Ipv6Subnets::new(
1756 $start.parse().unwrap(),
1757 $end.parse().unwrap(),
1758 $min_prefix_len,
1759 ));
1760 let results = make_ipnet_vec![$($x),*];
1761 assert_eq!(subnets.collect::<Vec<IpNet>>(), results);
1762 }
1763 );
1764 ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => (
1765 make_ipv6_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*);
1766 );
1767 }
1768
1769 make_ipv4_subnets_test!(
1770 test_ipv4_subnets_zero_zero,
1771 "0.0.0.0", "0.0.0.0", 0,
1772 "0.0.0.0/32",
1773 );
1774
1775 make_ipv4_subnets_test!(
1776 test_ipv4_subnets_zero_max,
1777 "0.0.0.0", "255.255.255.255", 0,
1778 "0.0.0.0/0",
1779 );
1780
1781 make_ipv4_subnets_test!(
1782 test_ipv4_subnets_max_max,
1783 "255.255.255.255", "255.255.255.255", 0,
1784 "255.255.255.255/32",
1785 );
1786
1787 make_ipv4_subnets_test!(
1788 test_ipv4_subnets_none,
1789 "0.0.0.1", "0.0.0.0", 0,
1790 );
1791
1792 make_ipv4_subnets_test!(
1793 test_ipv4_subnets_one,
1794 "0.0.0.0", "0.0.0.1", 0,
1795 "0.0.0.0/31",
1796 );
1797
1798 make_ipv4_subnets_test!(
1799 test_ipv4_subnets_two,
1800 "0.0.0.0", "0.0.0.2", 0,
1801 "0.0.0.0/31",
1802 "0.0.0.2/32",
1803 );
1804
1805 make_ipv4_subnets_test!(
1806 test_ipv4_subnets_taper,
1807 "0.0.0.0", "0.0.0.10", 30,
1808 "0.0.0.0/30",
1809 "0.0.0.4/30",
1810 "0.0.0.8/31",
1811 "0.0.0.10/32",
1812 );
1813
1814 make_ipv6_subnets_test!(
1815 test_ipv6_subnets_zero_zero,
1816 "::", "::", 0,
1817 "::/128",
1818 );
1819
1820 make_ipv6_subnets_test!(
1821 test_ipv6_subnets_zero_max,
1822 "::", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0,
1823 "::/0",
1824 );
1825
1826 make_ipv6_subnets_test!(
1827 test_ipv6_subnets_max_max,
1828 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0,
1829 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128",
1830 );
1831
1832 make_ipv6_subnets_test!(
1833 test_ipv6_subnets_none,
1834 "::1", "::", 0,
1835 );
1836
1837 make_ipv6_subnets_test!(
1838 test_ipv6_subnets_one,
1839 "::", "::1", 0,
1840 "::/127",
1841 );
1842
1843 make_ipv6_subnets_test!(
1844 test_ipv6_subnets_two,
1845 "::", "::2", 0,
1846 "::/127",
1847 "::2/128",
1848 );
1849
1850 make_ipv6_subnets_test!(
1851 test_ipv6_subnets_taper,
1852 "::", "::a", 126,
1853 "::/126",
1854 "::4/126",
1855 "::8/127",
1856 "::a/128",
1857 );
1858
1859 #[test]
1861 fn test_ipv4_subnets_zero_max_minus_one() {
1862 let subnets: Vec<Ipv4Net> = Ipv4Subnets::new(Ipv4Addr::from(0u32), Ipv4Addr::from(u32::MAX-1), 0).collect();
1863 assert!(!subnets[0].contains(&Ipv4Addr::from(u32::MAX)));
1864 }
1865
1866 #[test]
1868 fn test_ipv6_subnets_zero_max_minus_one() {
1869 let subnets: Vec<Ipv6Net> = Ipv6Subnets::new(Ipv6Addr::from(0u128), Ipv6Addr::from(u128::MAX-1), 0).collect();
1870 assert!(!subnets[0].contains(&Ipv6Addr::from(u128::MAX)));
1871 }
1872
1873 #[test]
1874 fn ipnet_aggregate() {
1875 let ip_nets = make_ipnet_vec![
1876 "10.0.0.0/24", "10.0.1.0/24", "10.0.1.1/24", "10.0.1.2/24",
1877 "10.0.2.0/24",
1878 "10.1.0.0/24", "10.1.1.0/24",
1879 "192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24", "192.168.3.0/24",
1880 "fd00::/32", "fd00:1::/32",
1881 "fd00:2::/32",
1882 ];
1883
1884 let ip_aggs = make_ipnet_vec![
1885 "10.0.0.0/23",
1886 "10.0.2.0/24",
1887 "10.1.0.0/23",
1888 "192.168.0.0/22",
1889 "fd00::/31",
1890 "fd00:2::/32",
1891 ];
1892
1893 assert_eq!(IpNet::aggregate(&ip_nets), ip_aggs);
1894
1895 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["128.0.0.0/1"]), make_ipnet_vec!["128.0.0.0/1"]);
1897 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["0.0.0.0/1", "128.0.0.0/1"]), make_ipnet_vec!["0.0.0.0/0"]);
1898 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["8000::/1"]), make_ipnet_vec!["8000::/1"]);
1899 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["::/1", "8000::/1"]), make_ipnet_vec!["::/0"]);
1900
1901 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["255.255.255.254/32"]), make_ipnet_vec!["255.255.255.254/32"]);
1903 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["255.255.255.255/32"]), make_ipnet_vec!["255.255.255.255/32"]);
1904 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["255.255.255.252/31", "255.255.255.254/32"]), make_ipnet_vec!["255.255.255.252/31", "255.255.255.254/32"]);
1905 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe/128"]), make_ipnet_vec!["ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe/128"]);
1906 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"]), make_ipnet_vec!["ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"]);
1907 assert_eq!(IpNet::aggregate(&make_ipnet_vec!["ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc/127", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe/128"]), make_ipnet_vec!["ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc/127", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe/128"]);
1908 }
1909
1910 #[test]
1911 fn ipnet_default() {
1912 let ipnet: IpNet = "0.0.0.0/0".parse().unwrap();
1913 assert_eq!(ipnet, IpNet::default());
1914 }
1915
1916 #[test]
1917 fn ipv4net_default() {
1918 let ipnet: Ipv4Net = "0.0.0.0/0".parse().unwrap();
1919 assert_eq!(ipnet, Ipv4Net::default());
1920 }
1921
1922 #[test]
1923 fn ipv6net_default() {
1924 let ipnet: Ipv6Net = "::/0".parse().unwrap();
1925 assert_eq!(ipnet, Ipv6Net::default());
1926 }
1927
1928 #[test]
1929 fn new_assert() {
1930 const _: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 0);
1931 const _: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 32);
1932 const _: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0);
1933 const _: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128);
1934
1935 let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 0);
1936 let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 32);
1937 let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0);
1938 let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128);
1939 }
1940
1941 #[test]
1942 #[should_panic]
1943 fn ipv4net_new_assert_panics() {
1944 let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 33);
1945 }
1946
1947 #[test]
1948 #[should_panic]
1949 fn ipv6net_new_assert_panics() {
1950 let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 129);
1951 }
1952}