netip/net.rs
1//! IPv4/IPv6 network primitives.
2//!
3//! This module provides types for IP networks by extending the standard
4//! library.
5//!
6//! Unlike most open-source libraries, this module is designed to support
7//! non-contiguous masks.
8
9use core::{
10 convert::TryFrom,
11 error::Error,
12 fmt::{Debug, Display, Formatter},
13 net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr},
14 num::ParseIntError,
15 ops::{Deref, Range},
16 str::FromStr,
17};
18
19const IPV4_ALL_BITS: Ipv4Addr = Ipv4Addr::new(0xff, 0xff, 0xff, 0xff);
20const IPV6_ALL_BITS: Ipv6Addr = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff);
21
22/// An error that is returned during IP network conversion from address and CIDR
23/// when the CIDR is too large.
24#[derive(Debug, PartialEq, Eq)]
25pub struct CidrOverflowError(u8, u8);
26
27impl Display for CidrOverflowError {
28 fn fmt(&self, fmt: &mut Formatter) -> Result<(), core::fmt::Error> {
29 let Self(from, to) = self;
30 write!(fmt, "invalid CIDR: {from} must be <= {to}")
31 }
32}
33
34/// An error that is returned during IP network parsing.
35#[derive(Debug, PartialEq)]
36pub enum IpNetParseError {
37 /// Expected IP network, but got something malformed instead.
38 ExpectedIpNetwork,
39 /// Expected IP address.
40 ExpectedIpAddr,
41 /// Failed to parse IP address.
42 AddrParseError(AddrParseError),
43 /// Expected CIDR number after `/`.
44 ExpectedIpCidr,
45 /// Failed to parse CIDR mask.
46 CidrParseError(ParseIntError),
47 /// CIDR mask is too large.
48 CidrOverflow(CidrOverflowError),
49}
50
51impl Display for IpNetParseError {
52 fn fmt(&self, fmt: &mut Formatter) -> Result<(), core::fmt::Error> {
53 match self {
54 Self::ExpectedIpNetwork => {
55 write!(fmt, "expected IP network")
56 }
57 Self::ExpectedIpAddr => {
58 write!(fmt, "expected IP address")
59 }
60 Self::AddrParseError(err) => {
61 write!(fmt, "IP address parse error: {err}")
62 }
63 Self::ExpectedIpCidr => {
64 write!(fmt, "expected IP CIDR")
65 }
66 Self::CidrParseError(err) => {
67 write!(fmt, "CIDR parse error: {err}")
68 }
69 Self::CidrOverflow(err) => {
70 write!(fmt, "CIDR overflow: {err}")
71 }
72 }
73 }
74}
75
76impl Error for IpNetParseError {}
77
78impl From<AddrParseError> for IpNetParseError {
79 #[inline]
80 fn from(err: AddrParseError) -> Self {
81 Self::AddrParseError(err)
82 }
83}
84
85impl From<CidrOverflowError> for IpNetParseError {
86 #[inline]
87 fn from(err: CidrOverflowError) -> Self {
88 Self::CidrOverflow(err)
89 }
90}
91
92/// Returns an [`Ipv4Addr`] that will have exact `cidr` leading bits set to
93/// one.
94///
95/// This function is used to construct IP masks for the given network prefix
96/// size.
97#[inline]
98pub fn ipv4_mask_from_cidr(cidr: u8) -> Result<Ipv4Addr, CidrOverflowError> {
99 if cidr <= 32 {
100 let mask = !(u32::MAX.checked_shr(cidr as u32).unwrap_or_default());
101 Ok(mask.into())
102 } else {
103 Err(CidrOverflowError(cidr, 32))
104 }
105}
106
107/// Returns an [`Ipv6Addr`] that will have exact `cidr` leading bits set to
108/// one.
109///
110/// This function is used to construct IP masks for the given network prefix
111/// size.
112#[inline]
113pub fn ipv6_mask_from_cidr(cidr: u8) -> Result<Ipv6Addr, CidrOverflowError> {
114 if cidr <= 128 {
115 let mask = !(u128::MAX.checked_shr(cidr as u32).unwrap_or_default());
116 Ok(mask.into())
117 } else {
118 Err(CidrOverflowError(cidr, 128))
119 }
120}
121
122/// An IP network, either IPv4 or IPv6.
123///
124/// This enum can contain either an [`Ipv4Network`] or an [`Ipv6Network`], see
125/// their respective documentation for more details.
126#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
127pub enum IpNetwork {
128 /// An IPv4 network.
129 V4(Ipv4Network),
130 /// An IPv6 network.
131 V6(Ipv6Network),
132}
133
134impl IpNetwork {
135 /// Parses specified buffer into an extended IP network.
136 ///
137 /// The following formats are supported:
138 ///
139 /// | Format | Example |
140 /// |--------------------------|-----------------------------------|
141 /// | IPv4 | `77.88.55.242` |
142 /// | IPv4/CIDR | `77.88.0.0/16` |
143 /// | IPv4/IPv4 | `77.88.0.0/255.255.0.0` |
144 /// | IPv6 | `2a02:6b8::2:242` |
145 /// | IPv6/CIDR | `2a02:6b8:c00::/40` |
146 /// | IPv6/IPv6 | `2a02:6b8:c00::/ffff:ffff:ff00::` |
147 ///
148 /// # Note
149 ///
150 /// During construction, the address is normalized using mask, for example
151 /// the network `77.88.55.242/16` becomes `77.88.0.0/16`.
152 ///
153 /// # Examples
154 ///
155 /// ```
156 /// use core::net::{Ipv4Addr, Ipv6Addr};
157 ///
158 /// use netip::{IpNetwork, Ipv4Network, Ipv6Network};
159 ///
160 /// // Here are some examples to show supported formats and the output of this function.
161 ///
162 /// // We can parse IPv4 addresses without explicit `/32` mask.
163 /// assert_eq!(
164 /// IpNetwork::V4(Ipv4Network::new(
165 /// Ipv4Addr::new(77, 88, 55, 242),
166 /// Ipv4Addr::new(255, 255, 255, 255),
167 /// ),),
168 /// // IPv4 address.
169 /// IpNetwork::parse("77.88.55.242").unwrap(),
170 /// );
171 ///
172 /// // When a mask can be represented in common CIDR format, like `/16`,
173 /// // which means "leading 16 bits on the mask is set to one".
174 /// assert_eq!(
175 /// IpNetwork::V4(Ipv4Network::new(
176 /// Ipv4Addr::new(77, 88, 0, 0),
177 /// Ipv4Addr::new(255, 255, 0, 0),
178 /// ),),
179 /// // IPv4 CIDR network.
180 /// IpNetwork::parse("77.88.0.0/16").unwrap(),
181 /// );
182 ///
183 /// // But we can also specify mask explicitly. This is useful when we
184 /// // want non-contiguous mask.
185 /// assert_eq!(
186 /// IpNetwork::V4(Ipv4Network::new(
187 /// Ipv4Addr::new(77, 88, 0, 0),
188 /// Ipv4Addr::new(255, 255, 0, 0),
189 /// ),),
190 /// // IPv4 network with explicit mask.
191 /// IpNetwork::parse("77.88.0.0/255.255.0.0").unwrap(),
192 /// );
193 ///
194 /// // Parse IPv6 addresses without explicit `/128` mask.
195 /// assert_eq!(
196 /// IpNetwork::V6(Ipv6Network::new(
197 /// Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x2, 0x242),
198 /// Ipv6Addr::new(
199 /// 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
200 /// ),
201 /// ),),
202 /// // IPv6 address.
203 /// IpNetwork::parse("2a02:6b8::2:242").unwrap(),
204 /// );
205 ///
206 /// // CIDR format.
207 /// assert_eq!(
208 /// IpNetwork::V6(Ipv6Network::new(
209 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
210 /// Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
211 /// ),),
212 /// // IPv6 CIDR network.
213 /// IpNetwork::parse("2a02:6b8:c00::/40").unwrap(),
214 /// );
215 ///
216 /// // Network with explicit mask (contiguous in this case).
217 /// assert_eq!(
218 /// IpNetwork::V6(Ipv6Network::new(
219 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
220 /// Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
221 /// ),),
222 /// // IPv6 network with explicit mask.
223 /// IpNetwork::parse("2a02:6b8:c00::/ffff:ffff:ff00::").unwrap(),
224 /// );
225 ///
226 /// // Network with explicit non-contiguous mask.
227 /// assert_eq!(
228 /// IpNetwork::V6(Ipv6Network::new(
229 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 0),
230 /// Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0xffff, 0xffff, 0, 0),
231 /// ),),
232 /// // The same network as above, but specified explicitly.
233 /// IpNetwork::parse("2a02:6b8:c00::1234:0:0/ffff:ffff:ff00::ffff:ffff:0:0").unwrap(),
234 /// );
235 /// ```
236 pub fn parse(buf: &str) -> Result<Self, IpNetParseError> {
237 match Ipv4Network::parse(buf) {
238 Ok(net) => {
239 return Ok(Self::V4(net));
240 }
241 Err(IpNetParseError::AddrParseError(..)) => {}
242 Err(err) => {
243 return Err(err);
244 }
245 }
246
247 let net = Ipv6Network::parse(buf)?;
248 Ok(Self::V6(net))
249 }
250
251 /// Checks whether this network is a contiguous, i.e. contains mask with
252 /// only leading bits set to one contiguously.
253 #[inline]
254 pub const fn is_contiguous(&self) -> bool {
255 match self {
256 Self::V4(net) => net.is_contiguous(),
257 Self::V6(net) => net.is_contiguous(),
258 }
259 }
260
261 /// Returns the mask prefix, i.e. the number of leading bits set, if this
262 /// network is a contiguous one, `None` otherwise.
263 ///
264 /// # Examples
265 ///
266 /// ```
267 /// use netip::IpNetwork;
268 ///
269 /// assert_eq!(
270 /// Some(24),
271 /// IpNetwork::parse("192.168.1.0/24").unwrap().prefix()
272 /// );
273 ///
274 /// assert_eq!(
275 /// Some(40),
276 /// IpNetwork::parse("2a02:6b8::/40").unwrap().prefix()
277 /// );
278 /// assert_eq!(Some(128), IpNetwork::parse("2a02:6b8::1").unwrap().prefix());
279 /// ```
280 #[inline]
281 pub const fn prefix(&self) -> Option<u8> {
282 match self {
283 Self::V4(net) => net.prefix(),
284 Self::V6(net) => net.prefix(),
285 }
286 }
287
288 /// Returns the last address in this IP network.
289 ///
290 /// For contiguous networks, this is the broadcast address.
291 ///
292 /// For non-contiguous networks, this is the highest address within the
293 /// network range defined by the mask.
294 ///
295 /// # Examples
296 ///
297 /// ```
298 /// use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
299 ///
300 /// use netip::IpNetwork;
301 ///
302 /// // IPv4 contiguous network.
303 /// assert_eq!(
304 /// IpAddr::V4(Ipv4Addr::new(192, 168, 1, 255)),
305 /// IpNetwork::parse("192.168.1.0/24").unwrap().last_addr()
306 /// );
307 ///
308 /// // IPv6 contiguous network.
309 /// assert_eq!(
310 /// IpAddr::V6(Ipv6Addr::new(
311 /// 0x2001, 0xdb8, 0x1, 0, 0xffff, 0xffff, 0xffff, 0xffff
312 /// )),
313 /// IpNetwork::parse("2001:db8:1::/64").unwrap().last_addr()
314 /// );
315 /// ```
316 #[inline]
317 pub fn last_addr(&self) -> IpAddr {
318 match self {
319 Self::V4(net) => IpAddr::V4(net.last_addr()),
320 Self::V6(net) => IpAddr::V6(net.last_addr()),
321 }
322 }
323}
324
325impl Display for IpNetwork {
326 fn fmt(&self, fmt: &mut Formatter) -> Result<(), core::fmt::Error> {
327 match self {
328 IpNetwork::V4(net) => Display::fmt(&net, fmt),
329 IpNetwork::V6(net) => Display::fmt(&net, fmt),
330 }
331 }
332}
333
334impl From<Ipv4Addr> for IpNetwork {
335 #[inline]
336 fn from(addr: Ipv4Addr) -> Self {
337 // Construct network directly, because no address mutation occurs.
338 Self::V4(Ipv4Network(addr, IPV4_ALL_BITS))
339 }
340}
341
342impl TryFrom<(Ipv4Addr, u8)> for IpNetwork {
343 type Error = CidrOverflowError;
344
345 fn try_from((addr, cidr): (Ipv4Addr, u8)) -> Result<Self, Self::Error> {
346 Ok(Self::V4(Ipv4Network::new(addr, ipv4_mask_from_cidr(cidr)?)))
347 }
348}
349
350impl From<(Ipv4Addr, Ipv4Addr)> for IpNetwork {
351 fn from((addr, mask): (Ipv4Addr, Ipv4Addr)) -> Self {
352 Self::V4(Ipv4Network::new(addr, mask))
353 }
354}
355
356impl From<Ipv4Network> for IpNetwork {
357 #[inline]
358 fn from(net: Ipv4Network) -> Self {
359 Self::V4(net)
360 }
361}
362
363impl From<Ipv6Addr> for IpNetwork {
364 fn from(addr: Ipv6Addr) -> Self {
365 // Construct network directly, because no address mutation occurs.
366 Self::V6(Ipv6Network(addr, IPV6_ALL_BITS))
367 }
368}
369
370impl TryFrom<(Ipv6Addr, u8)> for IpNetwork {
371 type Error = CidrOverflowError;
372
373 fn try_from((addr, cidr): (Ipv6Addr, u8)) -> Result<Self, Self::Error> {
374 Ok(Self::V6(Ipv6Network::new(addr, ipv6_mask_from_cidr(cidr)?)))
375 }
376}
377
378impl From<(Ipv6Addr, Ipv6Addr)> for IpNetwork {
379 fn from((addr, mask): (Ipv6Addr, Ipv6Addr)) -> Self {
380 Self::V6(Ipv6Network::new(addr, mask))
381 }
382}
383
384impl From<Ipv6Network> for IpNetwork {
385 #[inline]
386 fn from(net: Ipv6Network) -> Self {
387 Self::V6(net)
388 }
389}
390
391impl From<IpAddr> for IpNetwork {
392 #[inline]
393 fn from(addr: IpAddr) -> Self {
394 match addr {
395 IpAddr::V4(addr) => Self::from(addr),
396 IpAddr::V6(addr) => Self::from(addr),
397 }
398 }
399}
400
401impl FromStr for IpNetwork {
402 type Err = IpNetParseError;
403
404 #[inline]
405 fn from_str(s: &str) -> Result<Self, Self::Err> {
406 IpNetwork::parse(s)
407 }
408}
409
410/// Represents the network range in which IP addresses are IPv4.
411///
412/// IPv4 networks are defined as pair of two [`Ipv4Addr`]. One for IP address
413/// and the second one - for mask.
414///
415/// See [`IpNetwork`] for a type encompassing both IPv4 and IPv6 networks.
416///
417/// # Note
418///
419/// An IPv4 network represents a range of IPv4 addresses. The most common way to
420/// represent an IP network is through CIDR notation. See [IETF RFC 4632] for
421/// CIDR notation.
422///
423/// An example of such notation is `77.152.124.0/24`.
424///
425/// In CIDR notation, a prefix is shown as a 4-octet quantity, just like a
426/// traditional IPv4 address or network number, followed by the "/" (slash)
427/// character, followed by a decimal value between 0 and 32 that describes the
428/// number of significant bits.
429///
430/// Here, the "/24" indicates that the mask to extract the network portion of
431/// the prefix is a 32-bit value where the most significant 24 bits are
432/// ones and the least significant 8 bits are zeros.
433///
434/// The other way to represent the network above is to use explicit notation,
435/// such as `77.152.124.0/255.255.255.0`.
436///
437/// However, this struct supports non-contiguous masks, i.e. masks with
438/// non-contiguous bits set to one, like `77.152.0.55/255.255.0.255`.
439///
440/// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632
441#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
442pub struct Ipv4Network(Ipv4Addr, Ipv4Addr);
443
444impl Ipv4Network {
445 /// An IPv4 network representing the unspecified network: `0.0.0.0/0`
446 ///
447 /// # Examples
448 ///
449 /// ```
450 /// use core::net::Ipv4Addr;
451 ///
452 /// use netip::Ipv4Network;
453 ///
454 /// let net = Ipv4Network::UNSPECIFIED;
455 /// assert_eq!(
456 /// Ipv4Network::new(Ipv4Addr::new(0, 0, 0, 0), Ipv4Addr::new(0, 0, 0, 0)),
457 /// net
458 /// );
459 /// ```
460 pub const UNSPECIFIED: Self = Self(Ipv4Addr::UNSPECIFIED, Ipv4Addr::UNSPECIFIED);
461
462 /// Initializes a new [`Ipv4Network`] using specified address and mask.
463 ///
464 /// During construction the address is normalized using mask, i.e. in case
465 /// of `192.168.1.1/255.255.255.0` the result will be transformed
466 /// to `192.168.1.0/255.255.255.0`.
467 ///
468 /// # Examples
469 ///
470 /// ```
471 /// use core::net::Ipv4Addr;
472 ///
473 /// use netip::Ipv4Network;
474 ///
475 /// let net = Ipv4Network::new(
476 /// Ipv4Addr::new(192, 168, 1, 1),
477 /// Ipv4Addr::new(255, 255, 255, 0),
478 /// );
479 ///
480 /// assert_eq!(Ipv4Addr::new(192, 168, 1, 0), *net.addr());
481 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 0), *net.mask());
482 /// ```
483 #[inline]
484 pub const fn new(addr: Ipv4Addr, mask: Ipv4Addr) -> Self {
485 let addr = u32::from_be_bytes(addr.octets()) & u32::from_be_bytes(mask.octets());
486
487 Self(Ipv4Addr::from_bits(addr), mask)
488 }
489
490 /// Parses the specified buffer into an IPv4 network.
491 ///
492 /// The following formats are supported:
493 /// - IPv4
494 /// - IPv4/CIDR
495 /// - IPv4/IPv4
496 ///
497 /// # Examples
498 ///
499 /// ```
500 /// use core::net::Ipv4Addr;
501 ///
502 /// use netip::Ipv4Network;
503 ///
504 /// let expected = Ipv4Network::new(
505 /// Ipv4Addr::new(192, 168, 1, 1),
506 /// Ipv4Addr::new(255, 255, 255, 255),
507 /// );
508 ///
509 /// assert_eq!(expected, Ipv4Network::parse("192.168.1.1").unwrap());
510 /// assert_eq!(expected, Ipv4Network::parse("192.168.1.1/32").unwrap());
511 /// assert_eq!(
512 /// expected,
513 /// Ipv4Network::parse("192.168.1.1/255.255.255.255").unwrap()
514 /// );
515 /// ```
516 pub fn parse(buf: &str) -> Result<Self, IpNetParseError> {
517 let mut parts = buf.splitn(2, '/');
518 let addr = parts.next().ok_or(IpNetParseError::ExpectedIpAddr)?;
519 let addr: Ipv4Addr = addr.parse()?;
520 match parts.next() {
521 Some(mask) => match mask.parse::<u8>() {
522 Ok(cidr) => Ok(Self::try_from((addr, cidr))?),
523 Err(..) => {
524 // Maybe explicit mask.
525 let mask: Ipv4Addr = mask.parse()?;
526 Ok(Self::new(addr, mask))
527 }
528 },
529 None => Ok(Self(addr, IPV4_ALL_BITS)),
530 }
531 }
532
533 /// Returns the IP address of this IPv4 network.
534 #[inline]
535 pub const fn addr(&self) -> &Ipv4Addr {
536 match self {
537 Self(addr, ..) => addr,
538 }
539 }
540
541 /// Returns the IP mask of this IPv4 network.
542 #[inline]
543 pub const fn mask(&self) -> &Ipv4Addr {
544 match self {
545 Self(.., mask) => mask,
546 }
547 }
548
549 /// Converts a pair of IPv4 address and mask represented as a pair of host
550 /// byte order `u32` into an IPv4 network.
551 ///
552 /// # Note
553 ///
554 /// During conversion, the address is normalized using mask.
555 ///
556 /// # Examples
557 ///
558 /// ```
559 /// use core::net::Ipv4Addr;
560 ///
561 /// use netip::Ipv4Network;
562 ///
563 /// let expected = Ipv4Network::new(
564 /// Ipv4Addr::new(192, 168, 1, 0),
565 /// Ipv4Addr::new(255, 255, 255, 0),
566 /// );
567 ///
568 /// assert_eq!(expected, Ipv4Network::from_bits(3232235776, 4294967040));
569 /// ```
570 #[inline]
571 pub const fn from_bits(addr: u32, mask: u32) -> Self {
572 Self::new(Ipv4Addr::from_bits(addr), Ipv4Addr::from_bits(mask))
573 }
574
575 /// Converts this IPv4 network's address and mask into pair of host byte
576 /// order `u32`.
577 ///
578 /// # Examples
579 ///
580 /// ```
581 /// use core::net::Ipv4Addr;
582 ///
583 /// use netip::Ipv4Network;
584 ///
585 /// let net = Ipv4Network::new(
586 /// Ipv4Addr::new(192, 168, 1, 0),
587 /// Ipv4Addr::new(255, 255, 255, 0),
588 /// );
589 /// assert_eq!((3232235776, 4294967040), net.to_bits());
590 /// ```
591 #[inline]
592 pub const fn to_bits(&self) -> (u32, u32) {
593 match self {
594 Self(addr, mask) => (u32::from_be_bytes(addr.octets()), u32::from_be_bytes(mask.octets())),
595 }
596 }
597
598 /// Returns `true` if this IPv4 network fully contains the specified one.
599 #[inline]
600 pub const fn contains(&self, other: &Ipv4Network) -> bool {
601 let (a1, m1) = self.to_bits();
602 let (a2, m2) = other.to_bits();
603
604 (a2 & m1 == a1) && (m2 & m1 == m1)
605 }
606
607 /// Checks whether this network is a contiguous, i.e. contains mask with
608 /// only leading bits set to one contiguously.
609 ///
610 /// # Examples
611 ///
612 /// ```
613 /// use netip::Ipv4Network;
614 ///
615 /// assert!(Ipv4Network::parse("0.0.0.0/0").unwrap().is_contiguous());
616 /// assert!(
617 /// Ipv4Network::parse("213.180.192.0/19")
618 /// .unwrap()
619 /// .is_contiguous()
620 /// );
621 ///
622 /// assert!(
623 /// !Ipv4Network::parse("213.180.0.192/255.255.0.255")
624 /// .unwrap()
625 /// .is_contiguous()
626 /// );
627 /// ```
628 #[inline]
629 pub const fn is_contiguous(&self) -> bool {
630 let mask = u32::from_be_bytes(self.mask().octets());
631 mask.count_zeros() == mask.trailing_zeros()
632 }
633
634 /// Returns the mask prefix, i.e. the number of leading bits set, if this
635 /// network is a contiguous one, `None` otherwise.
636 ///
637 /// # Examples
638 ///
639 /// ```
640 /// use core::net::Ipv4Addr;
641 ///
642 /// use netip::Ipv4Network;
643 ///
644 /// assert_eq!(
645 /// Some(24),
646 /// Ipv4Network::new(
647 /// Ipv4Addr::new(192, 168, 1, 0),
648 /// Ipv4Addr::new(255, 255, 255, 0)
649 /// )
650 /// .prefix()
651 /// );
652 /// assert_eq!(
653 /// Some(32),
654 /// Ipv4Network::new(
655 /// Ipv4Addr::new(192, 168, 1, 1),
656 /// Ipv4Addr::new(255, 255, 255, 255)
657 /// )
658 /// .prefix()
659 /// );
660 ///
661 /// assert_eq!(
662 /// None,
663 /// Ipv4Network::new(Ipv4Addr::new(192, 0, 1, 0), Ipv4Addr::new(255, 0, 255, 0)).prefix()
664 /// );
665 /// ```
666 #[inline]
667 pub const fn prefix(&self) -> Option<u8> {
668 let mask = u32::from_be_bytes(self.mask().octets());
669 let ones = mask.leading_ones();
670
671 if mask.count_ones() == ones {
672 Some(ones as u8)
673 } else {
674 None
675 }
676 }
677
678 /// Converts this network to a contiguous network by clearing mask bits set
679 /// to one after the first zero bit.
680 ///
681 /// # Examples
682 ///
683 /// ```
684 /// use core::net::Ipv4Addr;
685 ///
686 /// use netip::Ipv4Network;
687 ///
688 /// let net = Ipv4Network::new(
689 /// Ipv4Addr::new(192, 168, 0, 1),
690 /// Ipv4Addr::new(255, 255, 0, 255),
691 /// );
692 /// let expected = Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 0), Ipv4Addr::new(255, 255, 0, 0));
693 ///
694 /// assert_eq!(expected, net.to_contiguous());
695 /// ```
696 pub fn to_contiguous(&self) -> Self {
697 let (addr, mask) = self.to_bits();
698
699 Self::try_from((addr.into(), mask.leading_ones() as u8)).expect("CIDR must be in range [0; 32]")
700 }
701
702 /// Calculates and returns the [`Ipv4Network`], which will be a supernet,
703 /// i.e. the shortest common network both for this network and the
704 /// specified ones.
705 ///
706 /// # Note
707 ///
708 /// This function works fine for both contiguous and non-contiguous
709 /// networks.
710 ///
711 /// Use [`Ipv4Network::to_contiguous`] method if you need to convert the
712 /// output network.
713 ///
714 /// # Examples
715 ///
716 /// ```
717 /// use core::net::Ipv4Addr;
718 ///
719 /// use netip::Ipv4Network;
720 ///
721 /// let net0 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 0), 25)).unwrap();
722 /// let net1 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 128), 25)).unwrap();
723 ///
724 /// assert_eq!(
725 /// Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 0), 24)).unwrap(),
726 /// net0.supernet_for(&[net1])
727 /// );
728 /// ```
729 pub fn supernet_for(&self, nets: &[Ipv4Network]) -> Ipv4Network {
730 let (addr, mask) = self.to_bits();
731
732 let mut min = addr;
733 let mut max = addr;
734
735 for net in nets {
736 let (addr, ..) = net.to_bits();
737 if addr < min {
738 min = addr;
739 } else if addr > max {
740 max = addr;
741 }
742 }
743
744 let common_addr = min ^ max;
745 let common_addr_len = common_addr.leading_zeros();
746 let mask = mask & !(u32::MAX.checked_shr(common_addr_len).unwrap_or_default());
747
748 Self::new(addr.into(), mask.into())
749 }
750
751 /// Converts this network to an IPv4-mapped IPv6 network.
752 ///
753 /// # Examples
754 ///
755 /// ```
756 /// use core::net::{Ipv4Addr, Ipv6Addr};
757 ///
758 /// use netip::{Ipv4Network, Ipv6Network};
759 ///
760 /// let net = Ipv4Network::new(
761 /// Ipv4Addr::new(192, 168, 1, 42),
762 /// Ipv4Addr::new(255, 255, 252, 0),
763 /// );
764 /// let expected =
765 /// Ipv6Network::parse("::ffff:c0a8:0/ffff:ffff:ffff:ffff:ffff:ffff:ffff:fc00").unwrap();
766 /// assert_eq!(expected, net.to_ipv6_mapped());
767 /// ```
768 #[inline]
769 pub const fn to_ipv6_mapped(&self) -> Ipv6Network {
770 match self {
771 Ipv4Network(addr, mask) => {
772 let [a, b, c, d] = mask.octets();
773 let [a, b, c, d]: [u16; 4] = [a as u16, b as u16, c as u16, d as u16];
774 Ipv6Network(
775 addr.to_ipv6_mapped(),
776 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, a << 8 | b, c << 8 | d),
777 )
778 }
779 }
780 }
781
782 /// Returns the last address in this IPv4 network.
783 ///
784 /// For contiguous networks, this is the broadcast address.
785 ///
786 /// For non-contiguous networks, this is the highest address within the
787 /// network range defined by the mask.
788 ///
789 /// # Examples
790 ///
791 /// ```
792 /// use core::net::Ipv4Addr;
793 ///
794 /// use netip::Ipv4Network;
795 ///
796 /// // Contiguous network.
797 /// let net = Ipv4Network::new(
798 /// Ipv4Addr::new(192, 168, 1, 0),
799 /// Ipv4Addr::new(255, 255, 255, 0),
800 /// );
801 /// assert_eq!(Ipv4Addr::new(192, 168, 1, 255), net.last_addr());
802 ///
803 /// // Single address network.
804 /// let net = Ipv4Network::new(
805 /// Ipv4Addr::new(10, 0, 0, 1),
806 /// Ipv4Addr::new(255, 255, 255, 255),
807 /// );
808 /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1), net.last_addr());
809 ///
810 /// // Non-contiguous network.
811 /// let net = Ipv4Network::new(
812 /// Ipv4Addr::new(192, 168, 0, 1),
813 /// Ipv4Addr::new(255, 255, 0, 255),
814 /// );
815 /// assert_eq!(Ipv4Addr::new(192, 168, 255, 1), net.last_addr());
816 /// ```
817 ///
818 /// # Formal Proof of Correctness
819 ///
820 /// ## Given
821 /// - Network address: `addr`.
822 /// - Network mask: `mask` (may be non-contiguous).
823 /// - Algorithm: `last_addr = addr | !mask`.
824 ///
825 /// ## Definitions
826 /// Let:
827 /// - `N = addr & mask` (network address with host bits zeroed).
828 /// - `H = !mask` (bitmask of host positions).
829 /// - Address `X` belongs to the network iff `(X & mask) = N`.
830 ///
831 /// ## Lemma 1: Contiguous Mask Case
832 ///
833 /// For contiguous masks (standard CIDR), the algorithm is well-established:
834 /// - ` mask` format: `111...100...0`.
835 /// - `!mask` format: `000...011...1`.
836 /// - `addr | !mask` sets all host bits to 1, yielding the broadcast
837 /// address.
838 ///
839 /// ## Lemma 2: Generalization to Non-Contiguous Masks
840 ///
841 /// **Theorem**: `X = addr | !mask` is the maximum address satisfying `(X &
842 /// mask) = N`.
843 ///
844 /// ### Proof:
845 ///
846 /// 1. **Membership**: ```(X & mask) = ((addr | !mask) & mask) = (addr &
847 /// mask) | (!mask & mask) = N | 0 = N ```
848 ///
849 /// Thus, `X` belongs to the network.
850 ///
851 /// 2. **Maximality**:
852 /// - Any network address can be expressed as `X = N | H_val` where
853 /// `H_val` has ones only in host positions
854 /// - The maximum possible `H_val` is `H = !mask` (all host bits set to
855 /// 1)
856 /// - Thus `X_max = N | H = (addr & mask) | !mask`
857 ///
858 /// 3. **Simplification**: since `addr & mask` zeros all host bits: ```
859 /// (addr & mask) | !mask = addr | !mask ```
860 /// - For mask bits = 1: `addr_bit | 0 = addr_bit`
861 /// - For mask bits = 0: `0 | 1 = 1`
862 ///
863 /// ## Edge Case Verification
864 ///
865 /// - **Full mask** (255.255.255.255): `last_addr = addr | 0 = addr` (single
866 /// address network).
867 ///
868 /// - **Zero mask** (0.0.0.0): `last_addr = addr | 0xFFFFFFFF =
869 /// 255.255.255.255` (entire address space).
870 ///
871 /// - **Non-contiguous mask** (e.g., 255.0.255.0): Correctly sets all host
872 /// bits to 1 while preserving network bits.
873 ///
874 /// ## ∴
875 ///
876 /// The algorithm `addr | !mask` correctly computes the maximum address in
877 /// any IPv4 network, including those with non-contiguous masks.
878 #[inline]
879 pub const fn last_addr(&self) -> Ipv4Addr {
880 let (addr, mask) = self.to_bits();
881 Ipv4Addr::from_bits(addr | !mask)
882 }
883
884 /// Returns a double-ended iterator over every address in this network.
885 ///
886 /// The iterator yields addresses in **host-index order**: the *k* host
887 /// positions (bits where the mask is zero) are filled with successive
888 /// values `0 ..= 2^k - 1`, starting from the least-significant host bit.
889 ///
890 /// For a standard (contiguous) CIDR mask this is equivalent to ascending
891 /// numeric order from [`addr()`](Ipv4Network::addr) to
892 /// [`last_addr()`](Ipv4Network::last_addr).
893 ///
894 /// For a non-contiguous mask the numeric order of the produced addresses
895 /// may differ from the iteration order.
896 ///
897 /// The iterator implements [`DoubleEndedIterator`] and
898 /// [`ExactSizeIterator`].
899 ///
900 /// # Examples
901 ///
902 /// ```
903 /// use core::net::Ipv4Addr;
904 ///
905 /// use netip::Ipv4Network;
906 ///
907 /// let net = Ipv4Network::parse("192.168.1.0/24").unwrap();
908 /// let mut addrs = net.addrs();
909 ///
910 /// assert_eq!(256, addrs.len());
911 ///
912 /// assert_eq!(Some(Ipv4Addr::new(192, 168, 1, 0)), addrs.next());
913 /// assert_eq!(Some(Ipv4Addr::new(192, 168, 1, 1)), addrs.next());
914 /// assert_eq!(Some(Ipv4Addr::new(192, 168, 1, 2)), addrs.next());
915 ///
916 /// // It is important to note that both back and forth work on the same
917 /// // range, and do not cross: iteration is over when they meet in the
918 /// // middle.
919 ///
920 /// assert_eq!(Some(Ipv4Addr::new(192, 168, 1, 255)), addrs.next_back());
921 /// assert_eq!(Some(Ipv4Addr::new(192, 168, 1, 254)), addrs.next_back());
922 ///
923 /// assert_eq!(Some(Ipv4Addr::new(192, 168, 1, 3)), addrs.next());
924 /// ```
925 #[inline]
926 pub fn addrs(self) -> Ipv4NetworkAddrs {
927 let (addr, mask) = self.to_bits();
928 let host_bits = (!mask).count_ones();
929 let back = u32::MAX.checked_shr(32 - host_bits).unwrap_or(0);
930
931 Ipv4NetworkAddrs { base: addr, mask, front: 0, back }
932 }
933}
934
935impl Display for Ipv4Network {
936 /// Formats this IPv4 network using the given formatter.
937 ///
938 /// The idea is to format using **the most compact** representation, except
939 /// for non-contiguous networks, which are formatted explicitly.
940 fn fmt(&self, fmt: &mut Formatter) -> Result<(), core::fmt::Error> {
941 match self {
942 Self(addr, mask) => {
943 match self.prefix() {
944 Some(prefix) => fmt.write_fmt(format_args!("{}/{}", addr, prefix)),
945 None => {
946 // This is a non-contiguous network, expand the mask.
947 fmt.write_fmt(format_args!("{}/{}", addr, mask))
948 }
949 }
950 }
951 }
952 }
953}
954
955impl From<Ipv4Addr> for Ipv4Network {
956 fn from(addr: Ipv4Addr) -> Self {
957 Self(addr, IPV4_ALL_BITS)
958 }
959}
960
961impl TryFrom<(Ipv4Addr, u8)> for Ipv4Network {
962 type Error = CidrOverflowError;
963
964 fn try_from((addr, cidr): (Ipv4Addr, u8)) -> Result<Self, Self::Error> {
965 let mask = ipv4_mask_from_cidr(cidr)?;
966 Ok(Self::new(addr, mask))
967 }
968}
969
970impl FromStr for Ipv4Network {
971 type Err = IpNetParseError;
972
973 #[inline]
974 fn from_str(s: &str) -> Result<Self, Self::Err> {
975 Ipv4Network::parse(s)
976 }
977}
978
979impl AsRef<Ipv4Network> for Ipv4Network {
980 #[inline]
981 fn as_ref(&self) -> &Ipv4Network {
982 self
983 }
984}
985
986/// Bidirectional iterator over [`Ipv4Addr`] in an [`Ipv4Network`].
987///
988/// Created by [`Ipv4Network::addrs`].
989///
990/// Yields addresses in host-index order: the *k* host positions (bits where the
991/// mask is zero) are filled with successive values `0 ..= 2^k - 1`, starting
992/// from the least-significant host bit.
993///
994/// When the iterator is exhausted it enters a sentinel state where
995/// `front > back`, so every subsequent call to [`next`](Iterator::next) or
996/// [`next_back`](DoubleEndedIterator::next_back) returns [`None`].
997#[derive(Debug, Clone, Copy, PartialEq, Eq)]
998pub struct Ipv4NetworkAddrs {
999 base: u32,
1000 mask: u32,
1001 front: u32,
1002 back: u32,
1003}
1004
1005impl Iterator for Ipv4NetworkAddrs {
1006 type Item = Ipv4Addr;
1007
1008 #[inline]
1009 fn next(&mut self) -> Option<Self::Item> {
1010 if self.front > self.back {
1011 return None;
1012 }
1013
1014 let index = self.front;
1015 self.front = self.front.wrapping_add(1);
1016
1017 // Wrap-around means front was u32::MAX — only possible for a /0
1018 // network.
1019 //
1020 // Enter sentinel state so the next call returns None.
1021 if self.front == 0 {
1022 self.front = 1;
1023 self.back = 0;
1024 }
1025
1026 Some(Ipv4Addr::from_bits(ipv4_bits_from_host_index(
1027 self.base, self.mask, index,
1028 )))
1029 }
1030
1031 #[inline]
1032 fn size_hint(&self) -> (usize, Option<usize>) {
1033 if self.front > self.back {
1034 return (0, Some(0));
1035 }
1036
1037 let rem = self.back.wrapping_sub(self.front).wrapping_add(1);
1038
1039 if rem == 0 {
1040 (usize::MAX, None)
1041 } else {
1042 let n = rem as usize;
1043 (n, Some(n))
1044 }
1045 }
1046}
1047
1048impl DoubleEndedIterator for Ipv4NetworkAddrs {
1049 #[inline]
1050 fn next_back(&mut self) -> Option<Self::Item> {
1051 if self.front > self.back {
1052 return None;
1053 }
1054
1055 let index = self.back;
1056
1057 if self.front == self.back {
1058 self.front = 1;
1059 self.back = 0;
1060 } else {
1061 self.back = self.back.wrapping_sub(1);
1062 }
1063
1064 Some(Ipv4Addr::from_bits(ipv4_bits_from_host_index(
1065 self.base, self.mask, index,
1066 )))
1067 }
1068}
1069
1070impl ExactSizeIterator for Ipv4NetworkAddrs {
1071 #[inline]
1072 fn len(&self) -> usize {
1073 if self.front > self.back {
1074 return 0;
1075 }
1076
1077 let rem = self.back.wrapping_sub(self.front).wrapping_add(1);
1078
1079 if rem == 0 { 1usize << 32 } else { rem as usize }
1080 }
1081}
1082
1083#[inline]
1084const fn ipv4_bits_from_host_index(base: u32, mask: u32, index: u32) -> u32 {
1085 let host_mask = !mask;
1086
1087 // For contiguous masks (trailing ones only) pdep is identity.
1088 if host_mask & host_mask.wrapping_add(1) == 0 {
1089 base | index
1090 } else {
1091 base | pdep_u32(index, host_mask)
1092 }
1093}
1094
1095#[inline]
1096const fn pdep_u32(mut src: u32, mut mask: u32) -> u32 {
1097 let mut out = 0u32;
1098
1099 while mask != 0 {
1100 let t = mask & mask.wrapping_neg();
1101
1102 if src & 1 != 0 {
1103 out |= t;
1104 }
1105
1106 src >>= 1;
1107 mask ^= t;
1108 }
1109
1110 out
1111}
1112
1113/// Represents the network range in which IP addresses are IPv6.
1114///
1115/// IPv6 networks are defined as pair of two [`Ipv6Addr`]. One for IP address
1116/// and the second one - for mask.
1117///
1118/// See [`IpNetwork`] for a type encompassing both IPv4 and IPv6 networks.
1119///
1120/// # Note
1121///
1122/// An IPv6 network represents a range of IPv6 addresses. The most common way to
1123/// represent an IP network is through CIDR notation. See [IETF RFC 4632] for
1124/// CIDR notation.
1125///
1126/// An example of such notation is `2a02:6b8:c00::/40`.
1127///
1128/// In CIDR notation, a prefix is shown as a 8-hextet quantity, just like a
1129/// traditional IPv6 address or network number, followed by the "/" (slash)
1130/// character, followed by a decimal value between 0 and 128 that describes the
1131/// number of significant bits.
1132///
1133/// Here, the "/40" indicates that the mask to extract the network portion of
1134/// the prefix is a 128-bit value where the most significant 40 bits are
1135/// ones and the least significant 88 bits are zeros.
1136///
1137/// The other way to represent the network above is to use explicit notation,
1138/// such as `2a02:6b8:c00::/ffff:ffff:ff00::`.
1139///
1140/// However, this struct supports non-contiguous masks, i.e. masks with
1141/// non-contiguous bits set to one, like the following one:
1142/// `2a02:6b8:c00::1234:0:0/ffff:ffff:ff00::ffff:ffff:0:0`.
1143///
1144/// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632
1145#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1146pub struct Ipv6Network(Ipv6Addr, Ipv6Addr);
1147
1148impl Ipv6Network {
1149 /// An IPv6 network representing the unspecified network: `::/0`
1150 ///
1151 /// # Examples
1152 ///
1153 /// ```
1154 /// use core::net::Ipv6Addr;
1155 ///
1156 /// use netip::Ipv6Network;
1157 ///
1158 /// let net = Ipv6Network::UNSPECIFIED;
1159 /// assert_eq!(
1160 /// Ipv6Network::new(
1161 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0),
1162 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)
1163 /// ),
1164 /// net
1165 /// );
1166 /// ```
1167 pub const UNSPECIFIED: Self = Self(Ipv6Addr::UNSPECIFIED, Ipv6Addr::UNSPECIFIED);
1168
1169 /// Initializes a new [`Ipv6Network`] using specified address and mask.
1170 ///
1171 /// During construction, the address is normalized using mask.
1172 #[inline]
1173 pub const fn new(addr: Ipv6Addr, mask: Ipv6Addr) -> Self {
1174 let addr = u128::from_be_bytes(addr.octets()) & u128::from_be_bytes(mask.octets());
1175
1176 Self(Ipv6Addr::from_bits(addr), mask)
1177 }
1178
1179 /// Parses the specified buffer into an IPv6 network.
1180 ///
1181 /// The following formats are supported:
1182 ///
1183 /// | Format | Example |
1184 /// |--------------------------|-----------------------------------|
1185 /// | IPv6 | `2a02:6b8::2:242` |
1186 /// | IPv6/CIDR | `2a02:6b8:c00::/40` |
1187 /// | IPv6/IPv6 | `2a02:6b8:c00::/ffff:ffff:ff00::` |
1188 ///
1189 /// # Examples
1190 ///
1191 /// ```
1192 /// use core::net::Ipv6Addr;
1193 ///
1194 /// use netip::Ipv6Network;
1195 ///
1196 /// // Here are some examples to show supported formats and the output of this function.
1197 ///
1198 /// // Parse IPv6 addresses without explicit `/128` mask.
1199 /// assert_eq!(
1200 /// Ipv6Network::new(
1201 /// Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x2, 0x242),
1202 /// Ipv6Addr::new(
1203 /// 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
1204 /// ),
1205 /// ),
1206 /// // IPv6 address.
1207 /// Ipv6Network::parse("2a02:6b8::2:242").unwrap(),
1208 /// );
1209 ///
1210 /// // CIDR format.
1211 /// assert_eq!(
1212 /// Ipv6Network::new(
1213 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
1214 /// Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
1215 /// ),
1216 /// // IPv6 CIDR network.
1217 /// Ipv6Network::parse("2a02:6b8:c00::/40").unwrap(),
1218 /// );
1219 ///
1220 /// // Network with explicit mask (contiguous in this case).
1221 /// assert_eq!(
1222 /// Ipv6Network::new(
1223 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
1224 /// Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
1225 /// ),
1226 /// // IPv6 network with explicit mask.
1227 /// Ipv6Network::parse("2a02:6b8:c00::/ffff:ffff:ff00::").unwrap(),
1228 /// );
1229 ///
1230 /// // Network with explicit non-contiguous mask.
1231 /// assert_eq!(
1232 /// Ipv6Network::new(
1233 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 0),
1234 /// Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0xffff, 0xffff, 0, 0),
1235 /// ),
1236 /// // The same network as above, but specified explicitly.
1237 /// Ipv6Network::parse("2a02:6b8:c00::1234:0:0/ffff:ffff:ff00::ffff:ffff:0:0").unwrap(),
1238 /// );
1239 /// ```
1240 pub fn parse(buf: &str) -> Result<Self, IpNetParseError> {
1241 let mut parts = buf.splitn(2, '/');
1242 let addr = parts.next().ok_or(IpNetParseError::ExpectedIpNetwork)?;
1243 let addr: Ipv6Addr = addr.parse()?;
1244 match parts.next() {
1245 Some(mask) => match mask.parse::<u8>() {
1246 Ok(mask) => Ok(Self::try_from((addr, mask))?),
1247 Err(..) => {
1248 // Maybe explicit mask.
1249 let mask: Ipv6Addr = mask.parse()?;
1250 Ok(Self::new(addr, mask))
1251 }
1252 },
1253 None => Ok(Self(addr, IPV6_ALL_BITS)),
1254 }
1255 }
1256
1257 /// Returns the IP address of this IPv6 network.
1258 #[inline]
1259 pub const fn addr(&self) -> &Ipv6Addr {
1260 match self {
1261 Ipv6Network(addr, ..) => addr,
1262 }
1263 }
1264
1265 /// Returns the IP mask of this IPv6 network.
1266 #[inline]
1267 pub const fn mask(&self) -> &Ipv6Addr {
1268 match self {
1269 Ipv6Network(.., mask) => mask,
1270 }
1271 }
1272
1273 /// Converts a pair of IPv6 address and mask represented as a pair of host
1274 /// byte order `u128` into an IPv6 network.
1275 ///
1276 /// # Note
1277 ///
1278 /// During conversion, the address is normalized using mask.
1279 ///
1280 /// # Examples
1281 ///
1282 /// ```
1283 /// use core::net::Ipv6Addr;
1284 ///
1285 /// use netip::Ipv6Network;
1286 ///
1287 /// let addr = 0x2a0206b8b0817228000000000001000b_u128;
1288 /// let mask = 0xffffffffffffffffffffffffffffffff_u128;
1289 ///
1290 /// let expected = Ipv6Network::new(
1291 /// Ipv6Addr::new(
1292 /// 0x2a02, 0x06b8, 0xb081, 0x7228, 0x0000, 0x0000, 0x0001, 0x000b,
1293 /// ),
1294 /// Ipv6Addr::new(
1295 /// 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1296 /// ),
1297 /// );
1298 ///
1299 /// assert_eq!(expected, Ipv6Network::from_bits(addr, mask));
1300 /// ```
1301 #[inline]
1302 pub const fn from_bits(addr: u128, mask: u128) -> Self {
1303 Self::new(Ipv6Addr::from_bits(addr), Ipv6Addr::from_bits(mask))
1304 }
1305
1306 /// Converts this IPv6 network's address and mask into pair of host byte
1307 /// order `u128`.
1308 ///
1309 /// # Examples
1310 ///
1311 /// ```
1312 /// use core::net::Ipv6Addr;
1313 ///
1314 /// use netip::Ipv6Network;
1315 ///
1316 /// let net = Ipv6Network::new(
1317 /// Ipv6Addr::new(
1318 /// 0x2a02, 0x06b8, 0xb081, 0x7228, 0x0000, 0x0000, 0x0001, 0x000b,
1319 /// ),
1320 /// Ipv6Addr::new(
1321 /// 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1322 /// ),
1323 /// );
1324 /// assert_eq!(
1325 /// (
1326 /// 0x2a0206b8b0817228000000000001000b_u128,
1327 /// 0xffffffffffffffffffffffffffffffff_u128,
1328 /// ),
1329 /// net.to_bits(),
1330 /// );
1331 /// ```
1332 #[inline]
1333 pub const fn to_bits(&self) -> (u128, u128) {
1334 match self {
1335 Self(addr, mask) => (u128::from_be_bytes(addr.octets()), u128::from_be_bytes(mask.octets())),
1336 }
1337 }
1338
1339 /// Returns `true` if this IPv6 network fully contains the specified one.
1340 #[inline]
1341 pub const fn contains(&self, other: &Ipv6Network) -> bool {
1342 let (a1, m1) = self.to_bits();
1343 let (a2, m2) = other.to_bits();
1344
1345 (a2 & m1 == a1) && (m2 & m1 == m1)
1346 }
1347
1348 /// Checks whether this network is a contiguous, i.e. contains mask with
1349 /// only leading bits set to one contiguously.
1350 ///
1351 /// # Examples
1352 ///
1353 /// ```
1354 /// use netip::Ipv6Network;
1355 ///
1356 /// assert!(Ipv6Network::parse("::/0").unwrap().is_contiguous());
1357 /// assert!(
1358 /// Ipv6Network::parse("2a02:6b8:c00::/40")
1359 /// .unwrap()
1360 /// .is_contiguous()
1361 /// );
1362 ///
1363 /// assert!(
1364 /// !Ipv6Network::parse("2a02:6b8:c00::f800:0:0/ffff:ffff:0:0:ffff:ffff::")
1365 /// .unwrap()
1366 /// .is_contiguous()
1367 /// );
1368 /// ```
1369 #[inline]
1370 pub const fn is_contiguous(&self) -> bool {
1371 let mask = u128::from_be_bytes(self.mask().octets());
1372 mask.count_zeros() == mask.trailing_zeros()
1373 }
1374
1375 /// Checks whether this network is an IPv4-mapped IPv6 network.
1376 ///
1377 /// # Examples
1378 ///
1379 /// ```
1380 /// use netip::{Ipv4Network, Ipv6Network};
1381 ///
1382 /// assert!(
1383 /// Ipv4Network::parse("8.8.8.0/24")
1384 /// .unwrap()
1385 /// .to_ipv6_mapped()
1386 /// .is_ipv4_mapped_ipv6()
1387 /// );
1388 ///
1389 /// assert!(
1390 /// !Ipv6Network::parse("2a02:6b8::/40")
1391 /// .unwrap()
1392 /// .is_ipv4_mapped_ipv6()
1393 /// );
1394 /// ```
1395 #[inline]
1396 pub const fn is_ipv4_mapped_ipv6(&self) -> bool {
1397 let (addr, mask) = self.to_bits();
1398
1399 // Suppress clippy a bit, because with return we have a nice aligning.
1400 #[allow(clippy::needless_return)]
1401 return addr & 0xffffffffffffffffffffffff00000000 == 0x00000000000000000000ffff00000000
1402 && mask & 0xffffffffffffffffffffffff00000000 == 0xffffffffffffffffffffffff00000000;
1403 }
1404
1405 /// Converts this network to a contiguous network by clearing mask bits set
1406 /// to one after the first zero bit.
1407 ///
1408 /// # Examples
1409 ///
1410 /// ```
1411 /// use core::net::Ipv6Addr;
1412 ///
1413 /// use netip::Ipv6Network;
1414 ///
1415 /// let net = Ipv6Network::new(
1416 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0xf800, 0, 0),
1417 /// Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0xffff, 0xffff, 0, 0),
1418 /// );
1419 /// let expected = Ipv6Network::new(
1420 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
1421 /// Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0),
1422 /// );
1423 ///
1424 /// assert_eq!(expected, net.to_contiguous());
1425 /// ```
1426 pub fn to_contiguous(&self) -> Self {
1427 let (addr, mask) = self.to_bits();
1428
1429 Self::try_from((addr.into(), mask.leading_ones() as u8)).expect("CIDR must be in range [0; 128]")
1430 }
1431
1432 /// Converts this network to an [`IPv4` network] if it's an IPv4-mapped
1433 /// network, as defined in [IETF RFC 4291 section 2.5.5.2], otherwise
1434 /// returns [`None`].
1435 ///
1436 /// `::ffff:a.b.c.d/N` becomes `a.b.c.d/M`, where `M = N - 96`.
1437 /// All networks with their addresses *not* starting with `::ffff` will
1438 /// return `None`.
1439 ///
1440 /// [`IPv4` network]: Ipv4Network
1441 /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1442 ///
1443 /// # Examples
1444 ///
1445 /// ```
1446 /// use core::net::{Ipv4Addr, Ipv6Addr};
1447 ///
1448 /// use netip::{Ipv4Network, Ipv6Network};
1449 ///
1450 /// let net = Ipv6Network::new(
1451 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff),
1452 /// Ipv6Addr::new(
1453 /// 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff00,
1454 /// ),
1455 /// );
1456 /// let expected = Ipv4Network::new(
1457 /// Ipv4Addr::new(192, 10, 2, 0),
1458 /// Ipv4Addr::new(255, 255, 255, 0),
1459 /// );
1460 /// assert_eq!(Some(expected), net.to_ipv4_mapped());
1461 ///
1462 /// // This networks is IPv4-compatible, but not the IPv4-mapped one.
1463 /// let net = Ipv6Network::new(
1464 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc00a, 0x2ff),
1465 /// Ipv6Addr::new(
1466 /// 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff00,
1467 /// ),
1468 /// );
1469 /// assert_eq!(None, net.to_ipv4_mapped());
1470 /// ```
1471 #[inline]
1472 pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Network> {
1473 if self.is_ipv4_mapped_ipv6() {
1474 let (addr, mask) = self.to_bits();
1475 let addr: u32 = (addr & 0xffffffff) as u32;
1476 let mask: u32 = (mask & 0xffffffff) as u32;
1477
1478 Some(Ipv4Network::from_bits(addr, mask))
1479 } else {
1480 None
1481 }
1482 }
1483
1484 /// Returns the mask prefix, i.e. the number of leading bits set, if this
1485 /// network is a contiguous one, `None` otherwise.
1486 ///
1487 /// # Examples
1488 ///
1489 /// ```
1490 /// use netip::{Ipv4Network, Ipv6Network};
1491 ///
1492 /// assert_eq!(
1493 /// Some(40),
1494 /// Ipv6Network::parse("2a02:6b8::/40").unwrap().prefix()
1495 /// );
1496 /// assert_eq!(
1497 /// Some(128),
1498 /// Ipv6Network::parse("2a02:6b8::1").unwrap().prefix()
1499 /// );
1500 ///
1501 /// // The IPv4-mapped IPv6 equivalent is `::ffff:8.8.8.0/120`.
1502 /// assert_eq!(
1503 /// Some(120),
1504 /// Ipv4Network::parse("8.8.8.0/24")
1505 /// .unwrap()
1506 /// .to_ipv6_mapped()
1507 /// .prefix()
1508 /// );
1509 /// ```
1510 #[inline]
1511 pub const fn prefix(&self) -> Option<u8> {
1512 let mask = u128::from_be_bytes(self.mask().octets());
1513 let ones = mask.leading_ones();
1514
1515 if mask.count_ones() == ones {
1516 Some(ones as u8)
1517 } else {
1518 None
1519 }
1520 }
1521
1522 /// Calculates and returns the `Ipv6Network`, which will be a supernet, i.e.
1523 /// the shortest common network both for this network and the specified
1524 /// ones.
1525 ///
1526 /// # Note
1527 ///
1528 /// This function works fine for both contiguous and non-contiguous
1529 /// networks.
1530 ///
1531 /// Use [`Ipv6Network::to_contiguous`] method if you need to convert the
1532 /// output network.
1533 ///
1534 /// # Examples
1535 ///
1536 /// ```
1537 /// use core::net::Ipv6Addr;
1538 ///
1539 /// use netip::Ipv6Network;
1540 ///
1541 /// // 2013:db8:1::1/64
1542 /// let net0 = Ipv6Network::new(
1543 /// Ipv6Addr::new(0x2013, 0xdb8, 0x1, 0, 0, 0, 0, 0x1),
1544 /// Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0),
1545 /// );
1546 ///
1547 /// // 2013:db8:2::1/64
1548 /// let net1 = Ipv6Network::new(
1549 /// Ipv6Addr::new(0x2013, 0xdb8, 0x2, 0, 0, 0, 0, 0x1),
1550 /// Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0),
1551 /// );
1552 ///
1553 /// // 2013:db8::/46
1554 /// let expected = Ipv6Network::new(
1555 /// Ipv6Addr::new(0x2013, 0xdb8, 0, 0, 0, 0, 0, 0),
1556 /// Ipv6Addr::new(0xffff, 0xffff, 0xfffc, 0, 0, 0, 0, 0),
1557 /// );
1558 /// assert_eq!(expected, net0.supernet_for(&[net1]));
1559 /// ```
1560 pub fn supernet_for(&self, nets: &[Ipv6Network]) -> Ipv6Network {
1561 let (addr, mask) = self.to_bits();
1562
1563 let mut min = addr;
1564 let mut max = addr;
1565
1566 for net in nets {
1567 let (addr, ..) = net.to_bits();
1568 if addr < min {
1569 min = addr;
1570 } else if addr > max {
1571 max = addr;
1572 }
1573 }
1574
1575 let common_addr = min ^ max;
1576 let common_addr_len = common_addr.leading_zeros();
1577 let mask = mask & !(u128::MAX.checked_shr(common_addr_len).unwrap_or_default());
1578
1579 Self::new(addr.into(), mask.into())
1580 }
1581
1582 /// Returns the last address in this IPv6 network.
1583 ///
1584 /// For contiguous networks, this is the broadcast address.
1585 ///
1586 /// For non-contiguous networks, this is the highest address within the
1587 /// network range defined by the mask.
1588 ///
1589 /// # Examples
1590 ///
1591 /// ```
1592 /// use core::net::Ipv6Addr;
1593 ///
1594 /// use netip::Ipv6Network;
1595 ///
1596 /// // Contiguous network.
1597 /// let net = Ipv6Network::new(
1598 /// Ipv6Addr::new(0x2001, 0xdb8, 0x1, 0, 0, 0, 0, 0),
1599 /// Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0),
1600 /// );
1601 /// assert_eq!(
1602 /// Ipv6Addr::new(0x2001, 0xdb8, 0x1, 0, 0, 0, 0xffff, 0xffff),
1603 /// net.last_addr()
1604 /// );
1605 ///
1606 /// // Single address network.
1607 /// let net = Ipv6Network::new(
1608 /// Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x1),
1609 /// Ipv6Addr::new(
1610 /// 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1611 /// ),
1612 /// );
1613 /// assert_eq!(
1614 /// Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x1),
1615 /// net.last_addr()
1616 /// );
1617 ///
1618 /// // Non-contiguous network.
1619 /// let net = Ipv6Network::new(
1620 /// Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 0),
1621 /// Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0xffff, 0xffff, 0, 0),
1622 /// );
1623 /// assert_eq!(
1624 /// Ipv6Addr::new(0x2a02, 0x6b8, 0x0cff, 0xffff, 0, 0x1234, 0xffff, 0xffff),
1625 /// net.last_addr()
1626 /// );
1627 /// ```
1628 ///
1629 /// # Formal Proof of Correctness
1630 ///
1631 /// The algorithm follows the same logic as [`Ipv4Network::last_addr`].
1632 /// See [`Ipv4Network::last_addr`] for the formal proof.
1633 #[inline]
1634 pub const fn last_addr(&self) -> Ipv6Addr {
1635 let (addr, mask) = self.to_bits();
1636 Ipv6Addr::from_bits(addr | !mask)
1637 }
1638
1639 /// Returns a bidirectional iterator over all addresses in this network.
1640 ///
1641 /// The iterator yields addresses in **host-index order**: the *k* host
1642 /// positions (bits where the mask is zero) are filled with successive
1643 /// values `0 ..= 2^k - 1`, starting from the least-significant host bit.
1644 ///
1645 /// For a standard (contiguous) CIDR mask this is equivalent to ascending
1646 /// numeric order from [`addr()`](Ipv6Network::addr) to
1647 /// [`last_addr()`](Ipv6Network::last_addr).
1648 ///
1649 /// For a non-contiguous mask the numeric order of the produced addresses
1650 /// may differ from the iteration order.
1651 ///
1652 /// The iterator implements [`DoubleEndedIterator`].
1653 ///
1654 /// # Examples
1655 ///
1656 /// ```
1657 /// use core::net::Ipv6Addr;
1658 ///
1659 /// use netip::Ipv6Network;
1660 ///
1661 /// let net = Ipv6Network::parse("2a02:6b8:c00::1234:0:0/120").unwrap();
1662 /// let mut addrs = net.addrs();
1663 ///
1664 /// assert_eq!(
1665 /// Some(Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 0)),
1666 /// addrs.next()
1667 /// );
1668 /// assert_eq!(
1669 /// Some(Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 1)),
1670 /// addrs.next()
1671 /// );
1672 ///
1673 /// // Both directions work on the same range and do not cross: iteration
1674 /// // is over when they meet in the middle.
1675 ///
1676 /// assert_eq!(
1677 /// Some(Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 0xff)),
1678 /// addrs.next_back()
1679 /// );
1680 ///
1681 /// assert_eq!(
1682 /// Some(Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 2)),
1683 /// addrs.next()
1684 /// );
1685 /// ```
1686 #[inline]
1687 pub fn addrs(self) -> Ipv6NetworkAddrs {
1688 let (addr, mask) = self.to_bits();
1689 let host_bits = (!mask).count_ones();
1690 let back = u128::MAX.checked_shr(128 - host_bits).unwrap_or(0);
1691
1692 Ipv6NetworkAddrs { base: addr, mask, front: 0, back }
1693 }
1694}
1695
1696/// Bidirectional iterator over [`Ipv6Addr`] in an [`Ipv6Network`].
1697///
1698/// Created by [`Ipv6Network::addrs`].
1699///
1700/// Yields addresses in host-index order: the *k* host positions (bits where the
1701/// mask is zero) are filled with successive values `0 ..= 2^k - 1`, starting
1702/// from the least-significant host bit.
1703///
1704/// When the iterator is exhausted it enters a sentinel state where
1705/// `front > back`, so every subsequent call to [`next`](Iterator::next) or
1706/// [`next_back`](DoubleEndedIterator::next_back) returns [`None`].
1707#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1708pub struct Ipv6NetworkAddrs {
1709 base: u128,
1710 mask: u128,
1711 front: u128,
1712 back: u128,
1713}
1714
1715impl Iterator for Ipv6NetworkAddrs {
1716 type Item = Ipv6Addr;
1717
1718 #[inline]
1719 fn next(&mut self) -> Option<Self::Item> {
1720 if self.front > self.back {
1721 return None;
1722 }
1723
1724 let index = self.front;
1725 self.front = self.front.wrapping_add(1);
1726
1727 // Wrap-around means front was u128::MAX — only possible for a /0
1728 // network.
1729 //
1730 // Enter sentinel state so the next call returns None.
1731 if self.front == 0 {
1732 self.front = 1;
1733 self.back = 0;
1734 }
1735
1736 Some(Ipv6Addr::from_bits(ipv6_bits_from_host_index(
1737 self.base, self.mask, index,
1738 )))
1739 }
1740
1741 #[inline]
1742 fn size_hint(&self) -> (usize, Option<usize>) {
1743 if self.front > self.back {
1744 return (0, Some(0));
1745 }
1746
1747 let rem = self.back.wrapping_sub(self.front).wrapping_add(1);
1748
1749 if rem == 0 {
1750 (usize::MAX, None)
1751 } else {
1752 match usize::try_from(rem) {
1753 Ok(n) => (n, Some(n)),
1754 Err(..) => (usize::MAX, None),
1755 }
1756 }
1757 }
1758}
1759
1760impl DoubleEndedIterator for Ipv6NetworkAddrs {
1761 #[inline]
1762 fn next_back(&mut self) -> Option<Self::Item> {
1763 if self.front > self.back {
1764 return None;
1765 }
1766
1767 let bits = ipv6_bits_from_host_index(self.base, self.mask, self.back);
1768
1769 if self.front == self.back {
1770 self.front = 1;
1771 self.back = 0;
1772 } else {
1773 self.back = self.back.wrapping_sub(1);
1774 }
1775
1776 Some(Ipv6Addr::from_bits(bits))
1777 }
1778}
1779
1780#[inline]
1781const fn ipv6_bits_from_host_index(base: u128, mask: u128, index: u128) -> u128 {
1782 let host_mask = !mask;
1783
1784 // For contiguous masks (trailing ones only) pdep is identity.
1785 if host_mask & host_mask.wrapping_add(1) == 0 {
1786 base | index
1787 } else {
1788 base | pdep_u128(index, host_mask)
1789 }
1790}
1791
1792#[inline]
1793const fn pdep_u128(mut src: u128, mut mask: u128) -> u128 {
1794 let mut out = 0u128;
1795
1796 while mask != 0 {
1797 let t = mask & mask.wrapping_neg();
1798
1799 if src & 1 != 0 {
1800 out |= t;
1801 }
1802
1803 src >>= 1;
1804 mask ^= t;
1805 }
1806
1807 out
1808}
1809
1810impl Display for Ipv6Network {
1811 /// Formats this IPv6 network using the given formatter.
1812 ///
1813 /// The idea is to format using **the most compact** representation, except
1814 /// for non-contiguous networks, which are formatted explicitly.
1815 fn fmt(&self, fmt: &mut Formatter) -> Result<(), core::fmt::Error> {
1816 match self {
1817 Ipv6Network(addr, mask) => {
1818 match self.prefix() {
1819 Some(prefix) => fmt.write_fmt(format_args!("{}/{}", addr, prefix)),
1820 None => {
1821 // This is a non-contiguous network, expand the mask.
1822 fmt.write_fmt(format_args!("{}/{}", addr, mask))
1823 }
1824 }
1825 }
1826 }
1827 }
1828}
1829
1830impl From<Ipv4Network> for Ipv6Network {
1831 #[inline]
1832 fn from(net: Ipv4Network) -> Self {
1833 net.to_ipv6_mapped()
1834 }
1835}
1836
1837impl From<Ipv6Addr> for Ipv6Network {
1838 fn from(addr: Ipv6Addr) -> Self {
1839 Ipv6Network(addr, IPV6_ALL_BITS)
1840 }
1841}
1842
1843impl TryFrom<(Ipv6Addr, u8)> for Ipv6Network {
1844 type Error = CidrOverflowError;
1845
1846 fn try_from((addr, cidr): (Ipv6Addr, u8)) -> Result<Self, Self::Error> {
1847 let mask = ipv6_mask_from_cidr(cidr)?;
1848 Ok(Ipv6Network::new(addr, mask))
1849 }
1850}
1851
1852impl FromStr for Ipv6Network {
1853 type Err = IpNetParseError;
1854
1855 #[inline]
1856 fn from_str(s: &str) -> Result<Self, Self::Err> {
1857 Ipv6Network::parse(s)
1858 }
1859}
1860
1861impl AsRef<Ipv6Network> for Ipv6Network {
1862 #[inline]
1863 fn as_ref(&self) -> &Ipv6Network {
1864 self
1865 }
1866}
1867
1868/// Finds the shortest common network for the given slice of networks that
1869/// covers at least half of slice.
1870///
1871/// Shortest means that it will have the shortest segment of subnets, or the
1872/// largest mask.
1873///
1874/// Imagine that you are building a radix tree or graph from networks and at
1875/// some point you need to split one of the nodes into two parts.
1876///
1877/// In other words, it is necessary to find the shortest network that contains
1878/// at least half of the child networks.
1879///
1880/// This function implements such an algorithm.
1881///
1882/// For example, suppose we have the following tree:
1883/// ```text
1884/// .
1885/// ├─ 127.0.0.1
1886/// ├─ 127.0.0.2
1887/// └─ 127.0.0.3
1888/// ```
1889///
1890/// After splitting:
1891///
1892/// ```text
1893/// .
1894/// ├─ 127.0.0.1
1895/// └─ 127.0.0.2/31
1896/// ├─ 127.0.0.2
1897/// └─ 127.0.0.3
1898/// ```
1899///
1900/// Another more interesting example:
1901///
1902/// ```text
1903/// .
1904/// ├─ 10.204.46.54/31
1905/// ├─ 10.204.46.68/31
1906/// ├─ 10.204.49.12/31
1907/// ├─ 10.204.49.14/31
1908/// ├─ 10.204.49.18/31
1909/// ├─ 10.204.49.32/31
1910/// ├─ 10.204.49.34/31
1911/// ├─ 10.204.49.36/31
1912/// ├─ 10.204.49.38/31
1913/// └─ 10.204.49.40/31
1914/// ```
1915///
1916/// After splitting:
1917///
1918/// ```text
1919/// .
1920/// ├─ 10.204.46.50/31
1921/// ├─ 10.204.46.54/31
1922/// ├─ 10.204.47.22/31
1923/// ├─ 10.204.49.0/26 [*]
1924/// │ ├─ 10.204.49.24/31
1925/// │ ├─ 10.204.49.26/31
1926/// │ ├─ 10.204.49.28/31
1927/// │ ├─ 10.204.49.32/31
1928/// │ ├─ 10.204.49.34/31
1929/// │ └─ 10.204.49.36/31
1930/// ├─ 10.204.50.38/31
1931/// └─ 10.204.50.40/31
1932/// ```
1933///
1934/// # Complexity
1935///
1936/// This function runs in `O(N)` and requires `O(1)` memory.
1937///
1938/// # Warning
1939///
1940/// The specified slice must be sorted, otherwise the result is unspecified and
1941/// meaningless.
1942///
1943/// Specified networks must not overlap.
1944///
1945/// # Examples
1946///
1947/// ```
1948/// use netip::{Ipv4Network, ipv4_binary_split};
1949///
1950/// let nets = &["127.0.0.1", "127.0.0.2", "127.0.0.3"];
1951/// let mut nets: Vec<_> = nets
1952/// .iter()
1953/// .map(|net| Ipv4Network::parse(net).unwrap())
1954/// .collect();
1955/// nets.sort();
1956/// nets.dedup();
1957///
1958/// let (supernet, range) = ipv4_binary_split(&nets).unwrap();
1959/// // 127.0.0.2/31 in binary is "0b...10/0b...10", which contains both "127.0.0.2" and "127.0.0.3".
1960/// assert_eq!(Ipv4Network::parse("127.0.0.2/31").unwrap(), supernet);
1961///
1962/// for (idx, net) in nets.iter().enumerate() {
1963/// assert_eq!(range.contains(&idx), supernet.contains(net));
1964/// }
1965///
1966/// // For the second example above.
1967///
1968/// let nets = &[
1969/// "10.204.46.50/31",
1970/// "10.204.46.54/31",
1971/// "10.204.47.22/31",
1972/// "10.204.49.24/31",
1973/// "10.204.49.26/31",
1974/// "10.204.49.28/31",
1975/// "10.204.49.32/31",
1976/// "10.204.49.34/31",
1977/// "10.204.49.36/31",
1978/// "10.204.50.38/31",
1979/// "10.204.50.40/31",
1980/// ];
1981/// let mut nets: Vec<_> = nets
1982/// .iter()
1983/// .map(|net| Ipv4Network::parse(net).unwrap())
1984/// .collect();
1985/// nets.sort();
1986/// nets.dedup();
1987///
1988/// let (supernet, range) = ipv4_binary_split(&nets).unwrap();
1989///
1990/// assert_eq!(Ipv4Network::parse("10.204.49.0/26").unwrap(), supernet);
1991///
1992/// for (idx, net) in nets.iter().enumerate() {
1993/// assert_eq!(range.contains(&idx), supernet.contains(net));
1994/// }
1995/// ```
1996pub fn ipv4_binary_split<T>(nets: &[T]) -> Option<(Ipv4Network, Range<usize>)>
1997where
1998 T: AsRef<Ipv4Network>,
1999{
2000 ip_binary_split(nets)
2001}
2002
2003/// Finds the shortest common network for the given slice of networks that
2004/// covers at least half of slice.
2005///
2006/// Shortest means that it will have the shortest segment of subnets, or the
2007/// largest mask.
2008///
2009/// Imagine that you are building a radix tree or graph from networks and at
2010/// some point you need to split one of the nodes into two parts.
2011///
2012/// In other words, it is necessary to find the shortest network that contains
2013/// at least half of the child networks.
2014///
2015/// This function implements such an algorithm.
2016///
2017/// For example, suppose we have the following tree:
2018/// ```text
2019/// .
2020/// ├─ ::1
2021/// ├─ ::2
2022/// └─ ::3
2023/// ```
2024///
2025/// After splitting:
2026///
2027/// ```text
2028/// .
2029/// ├─ ::1
2030/// └─ ::2/127
2031/// ├─ ::2
2032/// └─ ::3
2033/// ```
2034///
2035/// Another more interesting example:
2036///
2037/// ```text
2038/// .
2039/// ├─ 2a02:6b8:0:2302::/64
2040/// ├─ 2a02:6b8:0:2303::/64
2041/// ├─ 2a02:6b8:0:2305::/64
2042/// ├─ 2a02:6b8:0:2308::/64
2043/// ├─ 2a02:6b8:0:2309::/64
2044/// ├─ 2a02:6b8:0:230a::/64
2045/// ├─ 2a02:6b8:0:230b::/64
2046/// ├─ 2a02:6b8:0:230c::/64
2047/// ├─ 2a02:6b8:0:230d::/64
2048/// ├─ 2a02:6b8:0:2314::/64
2049/// └─ 2a02:6b8:0:231f::/64
2050/// ```
2051///
2052/// After splitting:
2053///
2054/// ```text
2055/// .
2056/// ├─ 2a02:6b8:0:2302::/64
2057/// ├─ 2a02:6b8:0:2303::/64
2058/// ├─ 2a02:6b8:0:2305::/64
2059/// └─ 2a02:6b8:0:2308::/61
2060/// │ ├─ 2a02:6b8:0:2308::/64
2061/// │ ├─ 2a02:6b8:0:2309::/64
2062/// │ ├─ 2a02:6b8:0:230a::/64
2063/// │ ├─ 2a02:6b8:0:230b::/64
2064/// │ ├─ 2a02:6b8:0:230c::/64
2065/// │ └─ 2a02:6b8:0:230d::/64
2066/// ├─ 2a02:6b8:0:2314::/64
2067/// └─ 2a02:6b8:0:231f::/64
2068/// ```
2069///
2070/// # Complexity
2071///
2072/// This function runs in `O(N)` and requires `O(1)` memory.
2073///
2074/// # Warning
2075///
2076/// The specified slice must be sorted, otherwise the result is unspecified and
2077/// meaningless.
2078///
2079/// Specified networks must not overlap.
2080///
2081/// # Examples
2082///
2083/// ```
2084/// use netip::{Ipv6Network, ipv6_binary_split};
2085///
2086/// let nets = &["::1", "::2", "::3"];
2087/// let mut nets: Vec<_> = nets
2088/// .iter()
2089/// .map(|net| Ipv6Network::parse(net).unwrap())
2090/// .collect();
2091///
2092/// // The input must be sorted.
2093/// nets.sort();
2094///
2095/// let (supernet, range) = ipv6_binary_split(&nets).unwrap();
2096/// // ::2/127 in binary is "0b...10/0b...10", which contains both "::2" and "::3".
2097/// assert_eq!(Ipv6Network::parse("::2/127").unwrap(), supernet);
2098///
2099/// for (idx, net) in nets.iter().enumerate() {
2100/// assert_eq!(range.contains(&idx), supernet.contains(net));
2101/// }
2102///
2103/// // For the second example above.
2104///
2105/// let nets = &[
2106/// "2a02:6b8:0:2302::/64",
2107/// "2a02:6b8:0:2303::/64",
2108/// "2a02:6b8:0:2305::/64",
2109/// "2a02:6b8:0:2308::/64",
2110/// "2a02:6b8:0:2309::/64",
2111/// "2a02:6b8:0:230a::/64",
2112/// "2a02:6b8:0:230b::/64",
2113/// "2a02:6b8:0:230c::/64",
2114/// "2a02:6b8:0:230d::/64",
2115/// "2a02:6b8:0:2314::/64",
2116/// "2a02:6b8:0:231f::/64",
2117/// ];
2118/// let mut nets: Vec<_> = nets
2119/// .iter()
2120/// .map(|net| Ipv6Network::parse(net).unwrap())
2121/// .collect();
2122/// nets.sort();
2123///
2124/// let (supernet, range) = ipv6_binary_split(&nets).unwrap();
2125/// assert_eq!(
2126/// Ipv6Network::parse("2a02:6b8:0:2308::/61").unwrap(),
2127/// supernet
2128/// );
2129///
2130/// for (idx, net) in nets.iter().enumerate() {
2131/// assert_eq!(range.contains(&idx), supernet.contains(net));
2132/// }
2133/// ```
2134pub fn ipv6_binary_split<T>(nets: &[T]) -> Option<(Ipv6Network, Range<usize>)>
2135where
2136 T: AsRef<Ipv6Network>,
2137{
2138 ip_binary_split(nets)
2139}
2140
2141#[inline]
2142fn ip_binary_split<T, U>(nets: &[T]) -> Option<(U, Range<usize>)>
2143where
2144 T: AsRef<U>,
2145 U: BinarySplit + Copy,
2146{
2147 if nets.len() < 3 {
2148 return None;
2149 }
2150
2151 // Window size.
2152 let size = nets.len().div_ceil(2);
2153
2154 // We start with supernet that covers all given networks.
2155 let mut range = 0..nets.len() - 1;
2156 let mut candidate = nets[range.start].as_ref().supernet_for(&[*nets[range.end].as_ref()]);
2157
2158 for (idx, window) in nets.windows(size).enumerate() {
2159 let supernet = window[0].as_ref().supernet_for(&[*window[size - 1].as_ref()]);
2160
2161 if supernet.mask() > candidate.mask() {
2162 range = idx..(idx + size);
2163 candidate = supernet;
2164 }
2165 }
2166
2167 // Adjust range from both sides, since our supernet may cover more networks.
2168 while range.start > 0 {
2169 if candidate.contains(nets[range.start - 1].as_ref()) {
2170 range.start -= 1;
2171 } else {
2172 break;
2173 }
2174 }
2175 while range.end < nets.len() {
2176 // Remember, range end is exclusive.
2177 if candidate.contains(nets[range.end].as_ref()) {
2178 range.end += 1;
2179 } else {
2180 break;
2181 }
2182 }
2183
2184 Some((candidate, range))
2185}
2186
2187trait BinarySplit: Sized {
2188 type Mask: PartialOrd;
2189
2190 fn mask(&self) -> &Self::Mask;
2191 fn contains(&self, other: &Self) -> bool;
2192 fn supernet_for(&self, nets: &[Self]) -> Self;
2193}
2194
2195impl BinarySplit for Ipv4Network {
2196 type Mask = Ipv4Addr;
2197
2198 #[inline]
2199 fn mask(&self) -> &Self::Mask {
2200 self.mask()
2201 }
2202
2203 #[inline]
2204 fn contains(&self, other: &Self) -> bool {
2205 self.contains(other)
2206 }
2207
2208 #[inline]
2209 fn supernet_for(&self, nets: &[Self]) -> Ipv4Network {
2210 self.supernet_for(nets)
2211 }
2212}
2213
2214impl BinarySplit for Ipv6Network {
2215 type Mask = Ipv6Addr;
2216
2217 #[inline]
2218 fn mask(&self) -> &Self::Mask {
2219 self.mask()
2220 }
2221
2222 #[inline]
2223 fn contains(&self, other: &Self) -> bool {
2224 self.contains(other)
2225 }
2226
2227 #[inline]
2228 fn supernet_for(&self, nets: &[Self]) -> Ipv6Network {
2229 self.supernet_for(nets)
2230 }
2231}
2232
2233/// An error that occurs when parsing a contiguous IP network.
2234#[derive(Debug, PartialEq)]
2235pub enum ContiguousIpNetParseError {
2236 /// The network is not contiguous.
2237 NonContiguousNetwork,
2238 /// An error occurred while parsing the IP network.
2239 IpNetParseError(IpNetParseError),
2240}
2241
2242impl From<IpNetParseError> for ContiguousIpNetParseError {
2243 #[inline]
2244 fn from(err: IpNetParseError) -> Self {
2245 ContiguousIpNetParseError::IpNetParseError(err)
2246 }
2247}
2248
2249impl Display for ContiguousIpNetParseError {
2250 fn fmt(&self, fmt: &mut Formatter) -> Result<(), core::fmt::Error> {
2251 match self {
2252 Self::NonContiguousNetwork => write!(fmt, "non-contiguous network"),
2253 Self::IpNetParseError(err) => write!(fmt, "{}", err),
2254 }
2255 }
2256}
2257
2258impl Error for ContiguousIpNetParseError {}
2259
2260/// A contiguous IP network.
2261///
2262/// Represents a wrapper around an IP network that is **guaranteed to be
2263/// contiguous**.
2264#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
2265pub struct Contiguous<T>(T);
2266
2267impl Contiguous<IpNetwork> {
2268 /// Parses an IP network from a string and returns a contiguous network.
2269 pub fn parse(buf: &str) -> Result<Self, ContiguousIpNetParseError> {
2270 let net = IpNetwork::parse(buf)?;
2271
2272 if net.is_contiguous() {
2273 Ok(Self(net))
2274 } else {
2275 Err(ContiguousIpNetParseError::NonContiguousNetwork)
2276 }
2277 }
2278
2279 /// Returns the prefix length of the network.
2280 ///
2281 /// # Examples
2282 ///
2283 /// ```
2284 /// use netip::{Contiguous, IpNetwork};
2285 ///
2286 /// let net = Contiguous::<IpNetwork>::parse("192.168.1.0/24").unwrap();
2287 /// assert_eq!(24, net.prefix());
2288 /// ```
2289 #[inline]
2290 pub const fn prefix(&self) -> u8 {
2291 match self {
2292 Self(IpNetwork::V4(net)) => Contiguous(*net).prefix(),
2293 Self(IpNetwork::V6(net)) => Contiguous(*net).prefix(),
2294 }
2295 }
2296}
2297
2298impl Contiguous<Ipv4Network> {
2299 /// Parses an IPv4 network from a string and returns a contiguous network.
2300 pub fn parse(buf: &str) -> Result<Self, ContiguousIpNetParseError> {
2301 let net = Ipv4Network::parse(buf)?;
2302
2303 if net.is_contiguous() {
2304 Ok(Self(net))
2305 } else {
2306 Err(ContiguousIpNetParseError::NonContiguousNetwork)
2307 }
2308 }
2309
2310 /// Returns the prefix length of the network.
2311 ///
2312 /// # Examples
2313 ///
2314 /// ```
2315 /// use netip::{Contiguous, Ipv4Network};
2316 ///
2317 /// let net = Contiguous::<Ipv4Network>::parse("172.16.0.0/12").unwrap();
2318 /// assert_eq!(12, net.prefix());
2319 /// ```
2320 #[inline]
2321 pub const fn prefix(&self) -> u8 {
2322 match self {
2323 Self(net) => {
2324 let mask = u32::from_be_bytes(net.mask().octets());
2325 let ones = mask.leading_ones();
2326 ones as u8
2327 }
2328 }
2329 }
2330}
2331
2332impl Contiguous<Ipv6Network> {
2333 /// Parses an IPv6 network from a string and returns a contiguous network.
2334 pub fn parse(buf: &str) -> Result<Self, ContiguousIpNetParseError> {
2335 let net = Ipv6Network::parse(buf)?;
2336
2337 if net.is_contiguous() {
2338 Ok(Self(net))
2339 } else {
2340 Err(ContiguousIpNetParseError::NonContiguousNetwork)
2341 }
2342 }
2343
2344 /// Returns the prefix length of the network.
2345 ///
2346 /// # Examples
2347 ///
2348 /// ```
2349 /// use netip::{Contiguous, Ipv6Network};
2350 ///
2351 /// let net = Contiguous::<Ipv6Network>::parse("2a02:6b8:c00::/40").unwrap();
2352 /// assert_eq!(40, net.prefix());
2353 /// ```
2354 #[inline]
2355 pub const fn prefix(&self) -> u8 {
2356 match self {
2357 Self(net) => {
2358 let mask = u128::from_be_bytes(net.mask().octets());
2359 let ones = mask.leading_ones();
2360 ones as u8
2361 }
2362 }
2363 }
2364}
2365
2366impl<T> Deref for Contiguous<T> {
2367 type Target = T;
2368
2369 #[inline]
2370 fn deref(&self) -> &Self::Target {
2371 match self {
2372 Self(net) => net,
2373 }
2374 }
2375}
2376
2377impl<T> Display for Contiguous<T>
2378where
2379 T: Display,
2380{
2381 #[inline]
2382 fn fmt(&self, fmt: &mut Formatter) -> Result<(), core::fmt::Error> {
2383 match self {
2384 Self(net) => Display::fmt(net, fmt),
2385 }
2386 }
2387}
2388
2389impl FromStr for Contiguous<IpNetwork> {
2390 type Err = ContiguousIpNetParseError;
2391
2392 fn from_str(s: &str) -> Result<Self, Self::Err> {
2393 Self::parse(s)
2394 }
2395}
2396
2397impl FromStr for Contiguous<Ipv4Network> {
2398 type Err = ContiguousIpNetParseError;
2399
2400 fn from_str(s: &str) -> Result<Self, Self::Err> {
2401 Self::parse(s)
2402 }
2403}
2404
2405impl FromStr for Contiguous<Ipv6Network> {
2406 type Err = ContiguousIpNetParseError;
2407
2408 fn from_str(s: &str) -> Result<Self, Self::Err> {
2409 Self::parse(s)
2410 }
2411}
2412
2413#[cfg(test)]
2414mod test {
2415 use super::*;
2416
2417 #[test]
2418 fn test_ipv4_mask_from_cidr() {
2419 let masks = &[
2420 0u32,
2421 0b10000000000000000000000000000000,
2422 0b11000000000000000000000000000000,
2423 0b11100000000000000000000000000000,
2424 0b11110000000000000000000000000000,
2425 0b11111000000000000000000000000000,
2426 0b11111100000000000000000000000000,
2427 0b11111110000000000000000000000000,
2428 0b11111111000000000000000000000000,
2429 0b11111111100000000000000000000000,
2430 0b11111111110000000000000000000000,
2431 0b11111111111000000000000000000000,
2432 0b11111111111100000000000000000000,
2433 0b11111111111110000000000000000000,
2434 0b11111111111111000000000000000000,
2435 0b11111111111111100000000000000000,
2436 0b11111111111111110000000000000000,
2437 0b11111111111111111000000000000000,
2438 0b11111111111111111100000000000000,
2439 0b11111111111111111110000000000000,
2440 0b11111111111111111111000000000000,
2441 0b11111111111111111111100000000000,
2442 0b11111111111111111111110000000000,
2443 0b11111111111111111111111000000000,
2444 0b11111111111111111111111100000000,
2445 0b11111111111111111111111110000000,
2446 0b11111111111111111111111111000000,
2447 0b11111111111111111111111111100000,
2448 0b11111111111111111111111111110000,
2449 0b11111111111111111111111111111000,
2450 0b11111111111111111111111111111100,
2451 0b11111111111111111111111111111110,
2452 0b11111111111111111111111111111111,
2453 ];
2454
2455 for (idx, &mask) in masks.iter().enumerate() {
2456 assert_eq!(Ipv4Addr::from(mask), ipv4_mask_from_cidr(idx as u8).unwrap());
2457 }
2458
2459 assert!(ipv4_mask_from_cidr(33).is_err());
2460 }
2461
2462 #[test]
2463 fn test_ipv6_mask_from_cidr() {
2464 assert_eq!(Ipv6Addr::UNSPECIFIED, ipv6_mask_from_cidr(0).unwrap());
2465 assert_eq!(
2466 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x8000, 0),
2467 ipv6_mask_from_cidr(97).unwrap()
2468 );
2469 assert_eq!(
2470 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
2471 ipv6_mask_from_cidr(128).unwrap()
2472 );
2473
2474 assert!(ipv6_mask_from_cidr(129).is_err());
2475 }
2476
2477 #[test]
2478 fn parse_ipv4() {
2479 assert_eq!(
2480 Ipv4Network::new("127.0.0.1".parse().unwrap(), "255.255.255.255".parse().unwrap()),
2481 Ipv4Network::parse("127.0.0.1").unwrap()
2482 );
2483 }
2484
2485 #[test]
2486 fn parse_ipv4_cidr() {
2487 assert_eq!(
2488 Ipv4Network::new("192.168.0.0".parse().unwrap(), "255.255.255.0".parse().unwrap()),
2489 Ipv4Network::parse("192.168.0.1/24").unwrap()
2490 );
2491
2492 assert_eq!(
2493 Ipv4Network::new("192.168.0.1".parse().unwrap(), "255.255.255.255".parse().unwrap()),
2494 Ipv4Network::parse("192.168.0.1/32").unwrap()
2495 );
2496 }
2497
2498 #[test]
2499 fn parse_ipv4_explicit_mask() {
2500 assert_eq!(
2501 Ipv4Network::new("192.168.0.0".parse().unwrap(), "255.255.255.0".parse().unwrap()),
2502 Ipv4Network::parse("192.168.0.1/255.255.255.0").unwrap()
2503 );
2504 }
2505
2506 #[test]
2507 fn ipv4_contains() {
2508 assert!(
2509 Ipv4Network::parse("0.0.0.0/0")
2510 .unwrap()
2511 .contains(&Ipv4Network::parse("127.0.0.1").unwrap())
2512 );
2513 assert!(
2514 Ipv4Network::parse("0.0.0.0/8")
2515 .unwrap()
2516 .contains(&Ipv4Network::parse("0.0.0.0/9").unwrap())
2517 );
2518 }
2519
2520 #[test]
2521 fn ipv4_not_contains() {
2522 assert!(
2523 !Ipv4Network::parse("0.0.0.0/9")
2524 .unwrap()
2525 .contains(&Ipv4Network::parse("0.0.0.0/8").unwrap())
2526 );
2527 }
2528
2529 #[test]
2530 fn ipv4_contains_self() {
2531 assert!(
2532 Ipv4Network::parse("127.0.0.1")
2533 .unwrap()
2534 .contains(&Ipv4Network::parse("127.0.0.1").unwrap())
2535 );
2536 }
2537
2538 #[test]
2539 fn ipv4_addrs_non_contiguous_matches_expected_grid() {
2540 let net = Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 1), Ipv4Addr::new(255, 255, 0, 255));
2541 let mut expected: Vec<_> = (0u16..256).map(|a| Ipv4Addr::new(192, 168, a as u8, 1)).collect();
2542 let mut actual: Vec<_> = net.addrs().collect();
2543 expected.sort();
2544 actual.sort();
2545
2546 assert_eq!(expected, actual);
2547 }
2548
2549 #[test]
2550 fn ipv4_addrs_slash24_matches_incrementing_u32() {
2551 let net = Ipv4Network::parse("192.168.1.0/24").unwrap();
2552 let mut ip = net.addr().to_bits();
2553 for a in net.addrs() {
2554 assert_eq!(a.to_bits(), ip);
2555 ip = ip.wrapping_add(1);
2556 }
2557
2558 assert_eq!(256, net.addrs().count());
2559 }
2560
2561 #[test]
2562 fn ipv4_addrs_slash32_single() {
2563 let net = Ipv4Network::parse("10.0.0.1/32").unwrap();
2564 assert_eq!(net.addrs().next(), net.addrs().next_back());
2565
2566 let mut addrs = net.addrs();
2567 assert_eq!(addrs.next(), Some(Ipv4Addr::new(10, 0, 0, 1)));
2568 assert_eq!(addrs.next(), None);
2569 assert_eq!(addrs.next_back(), None);
2570 }
2571
2572 #[test]
2573 fn ipv4_addrs_non_contiguous_unique_and_endpoints() {
2574 let net = Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 1), Ipv4Addr::new(255, 255, 0, 255));
2575
2576 let addrs: Vec<_> = net.addrs().collect();
2577 assert_eq!(256, addrs.len());
2578
2579 let mut sorted = addrs.clone();
2580 sorted.sort();
2581 sorted.dedup();
2582
2583 assert_eq!(sorted.len(), addrs.len());
2584 assert_eq!(addrs.first().copied(), Some(*net.addr()));
2585 assert_eq!(addrs.last().copied(), Some(net.last_addr()));
2586 }
2587
2588 #[test]
2589 fn ipv4_addrs_interleaved_exhausts_uniquely() {
2590 let net = Ipv4Network::parse("192.168.1.0/24").unwrap();
2591 let mut addrs = net.addrs();
2592 let mut seen = Vec::new();
2593 loop {
2594 match (addrs.next(), addrs.next_back()) {
2595 (Some(a), Some(b)) => {
2596 seen.push(a);
2597 seen.push(b);
2598 }
2599 (Some(a), None) => seen.push(a),
2600 (None, Some(b)) => seen.push(b),
2601 (None, None) => break,
2602 }
2603 }
2604
2605 assert_eq!(256, seen.len());
2606 seen.sort();
2607 seen.dedup();
2608 assert_eq!(256, seen.len());
2609 }
2610
2611 #[test]
2612 fn ipv4_addrs_unspecified_both_ends() {
2613 let net = Ipv4Network::UNSPECIFIED;
2614 let mut addrs = net.addrs();
2615 assert_eq!(addrs.next(), Some(Ipv4Addr::new(0, 0, 0, 0)));
2616 assert_eq!(addrs.next_back(), Some(Ipv4Addr::new(255, 255, 255, 255)));
2617 }
2618
2619 #[test]
2620 fn ipv6_addrs_slash120_matches_incrementing_u128() {
2621 let net = Ipv6Network::parse("2a02:6b8:c00::1234:0:0/120").unwrap();
2622 let mut ip = net.addr().to_bits();
2623
2624 for addr in net.addrs() {
2625 assert_eq!(addr.to_bits(), ip);
2626 ip = ip.wrapping_add(1);
2627 }
2628
2629 assert_eq!(256, net.addrs().count());
2630 }
2631
2632 #[test]
2633 fn ipv6_addrs_slash128_single() {
2634 let net = Ipv6Network::parse("::1/128").unwrap();
2635 assert_eq!(net.addrs().next(), net.addrs().next_back());
2636
2637 let mut addrs = net.addrs();
2638 assert_eq!(addrs.next(), Some(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)));
2639 assert_eq!(addrs.next(), None);
2640 assert_eq!(addrs.next_back(), None);
2641 }
2642
2643 #[test]
2644 fn ipv6_addrs_non_contiguous_unique_and_endpoints() {
2645 let net = Ipv6Network::new(
2646 Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 0),
2647 Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
2648 );
2649
2650 let addrs: Vec<_> = net.addrs().collect();
2651 assert_eq!(256, addrs.len());
2652
2653 let mut sorted = addrs.clone();
2654 sorted.sort();
2655 sorted.dedup();
2656 assert_eq!(sorted.len(), addrs.len());
2657 assert_eq!(addrs.first().copied(), Some(*net.addr()));
2658 assert_eq!(addrs.last().copied(), Some(net.last_addr()));
2659 }
2660
2661 #[test]
2662 fn ipv6_addrs_interleaved_exhausts_uniquely() {
2663 let net = Ipv6Network::parse("2a02:6b8:c00::1234:0:0/120").unwrap();
2664 let mut addrs = net.addrs();
2665 let mut seen = Vec::new();
2666
2667 loop {
2668 match (addrs.next(), addrs.next_back()) {
2669 (Some(a), Some(b)) => {
2670 seen.push(a);
2671 seen.push(b);
2672 }
2673 (Some(a), None) => seen.push(a),
2674 (None, Some(b)) => seen.push(b),
2675 (None, None) => break,
2676 }
2677 }
2678
2679 assert_eq!(256, seen.len());
2680 seen.sort();
2681 seen.dedup();
2682 assert_eq!(256, seen.len());
2683 }
2684
2685 #[test]
2686 fn ipv6_addrs_unspecified_both_ends() {
2687 let net = Ipv6Network::UNSPECIFIED;
2688 let mut addrs = net.addrs();
2689 assert_eq!(addrs.next(), Some(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)));
2690 assert_eq!(
2691 addrs.next_back(),
2692 Some(Ipv6Addr::new(
2693 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
2694 ))
2695 );
2696 }
2697
2698 #[test]
2699 fn ipv6_addrs_non_contiguous_matches_expected_grid() {
2700 let net = Ipv6Network::new(
2701 Ipv6Addr::new(0x2a02, 0x6b8, 0x0c00, 0, 0, 0, 0, 1),
2702 Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
2703 );
2704
2705 let mut expected: Vec<_> = (0u16..256)
2706 .map(|a| Ipv6Addr::new(0x2a02, 0x6b8, 0x0c00 | a, 0, 0, 0, 0, 1))
2707 .collect();
2708 let mut actual: Vec<_> = net.addrs().collect();
2709 expected.sort();
2710 actual.sort();
2711 assert_eq!(expected, actual);
2712 }
2713
2714 #[test]
2715 fn ipv4_supernet_for() {
2716 let net0 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 0), 25)).unwrap();
2717 let net1 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 128), 25)).unwrap();
2718
2719 let expected = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 0), 24)).unwrap();
2720 assert_eq!(expected, net0.supernet_for(&[net1]));
2721 assert_eq!(expected, net1.supernet_for(&[net0]));
2722 }
2723
2724 #[test]
2725 fn ipv4_supernet_for_equal_nets() {
2726 let net0 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 128), 25)).unwrap();
2727 let net1 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 128), 25)).unwrap();
2728
2729 let expected = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 128), 25)).unwrap();
2730 assert_eq!(expected, net0.supernet_for(&[net1]));
2731 assert_eq!(expected, net1.supernet_for(&[net0]));
2732 }
2733
2734 #[test]
2735 fn ipv4_supernet_for_many() {
2736 let net0 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 0), 27)).unwrap();
2737 let net1 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 32), 27)).unwrap();
2738 let net2 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 64), 27)).unwrap();
2739 let net3 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 96), 27)).unwrap();
2740 let net4 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 128), 27)).unwrap();
2741 let net5 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 160), 27)).unwrap();
2742 let net6 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 192), 27)).unwrap();
2743 let net7 = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 224), 27)).unwrap();
2744
2745 let expected = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 0), 24)).unwrap();
2746 assert_eq!(expected, net0.supernet_for(&[net1, net2, net3, net4, net5, net6, net7]));
2747 assert_eq!(expected, net1.supernet_for(&[net0, net2, net3, net4, net5, net6, net7]));
2748 assert_eq!(expected, net2.supernet_for(&[net0, net1, net3, net4, net5, net6, net7]));
2749 assert_eq!(expected, net3.supernet_for(&[net0, net1, net2, net4, net5, net6, net7]));
2750 assert_eq!(expected, net4.supernet_for(&[net0, net1, net2, net3, net5, net6, net7]));
2751 assert_eq!(expected, net5.supernet_for(&[net0, net1, net2, net3, net4, net6, net7]));
2752 assert_eq!(expected, net6.supernet_for(&[net0, net1, net2, net3, net4, net5, net7]));
2753 assert_eq!(expected, net7.supernet_for(&[net0, net1, net2, net3, net4, net5, net6]));
2754 }
2755
2756 #[test]
2757 fn ipv4_supernet_for_many_more() {
2758 let nets = &[
2759 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 0), 28)).unwrap(),
2760 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 16), 28)).unwrap(),
2761 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 32), 28)).unwrap(),
2762 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 48), 28)).unwrap(),
2763 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 64), 28)).unwrap(),
2764 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 80), 28)).unwrap(),
2765 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 96), 28)).unwrap(),
2766 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 112), 28)).unwrap(),
2767 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 128), 28)).unwrap(),
2768 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 144), 28)).unwrap(),
2769 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 160), 28)).unwrap(),
2770 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 176), 28)).unwrap(),
2771 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 192), 28)).unwrap(),
2772 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 208), 28)).unwrap(),
2773 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 224), 28)).unwrap(),
2774 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 240), 28)).unwrap(),
2775 ];
2776
2777 let expected = Ipv4Network::try_from((Ipv4Addr::new(192, 0, 2, 0), 24)).unwrap();
2778 assert_eq!(expected, nets[0].supernet_for(&nets[1..]).to_contiguous());
2779 }
2780
2781 #[test]
2782 fn ipv4_supernet_for_wide() {
2783 let nets = &[
2784 Ipv4Network::try_from((Ipv4Addr::new(10, 40, 101, 1), 32)).unwrap(),
2785 Ipv4Network::try_from((Ipv4Addr::new(10, 40, 102, 1), 32)).unwrap(),
2786 Ipv4Network::try_from((Ipv4Addr::new(10, 40, 103, 1), 32)).unwrap(),
2787 ];
2788
2789 let expected = Ipv4Network::try_from((Ipv4Addr::new(10, 40, 100, 0), 22)).unwrap();
2790 assert_eq!(expected, nets[0].supernet_for(&nets[1..]).to_contiguous());
2791 }
2792
2793 #[test]
2794 fn ipv4_supernet_for_wide_more() {
2795 let nets = &[
2796 Ipv4Network::try_from((Ipv4Addr::new(10, 40, 101, 1), 32)).unwrap(),
2797 Ipv4Network::try_from((Ipv4Addr::new(10, 40, 102, 1), 32)).unwrap(),
2798 Ipv4Network::try_from((Ipv4Addr::new(11, 40, 103, 1), 32)).unwrap(),
2799 ];
2800
2801 let expected = Ipv4Network::try_from((Ipv4Addr::new(10, 0, 0, 0), 7)).unwrap();
2802 assert_eq!(expected, nets[0].supernet_for(&nets[1..]).to_contiguous());
2803 }
2804
2805 #[test]
2806 fn ipv4_supernet_for_min() {
2807 let nets = &[
2808 Ipv4Network::try_from((Ipv4Addr::new(192, 168, 0, 0), 24)).unwrap(),
2809 Ipv4Network::try_from((Ipv4Addr::new(192, 168, 1, 0), 24)).unwrap(),
2810 Ipv4Network::try_from((Ipv4Addr::new(192, 168, 2, 0), 24)).unwrap(),
2811 Ipv4Network::try_from((Ipv4Addr::new(192, 168, 100, 0), 24)).unwrap(),
2812 Ipv4Network::try_from((Ipv4Addr::new(192, 168, 200, 0), 24)).unwrap(),
2813 ];
2814
2815 let expected = Ipv4Network::try_from((Ipv4Addr::new(192, 168, 0, 0), 16)).unwrap();
2816 assert_eq!(expected, nets[0].supernet_for(&nets[1..]).to_contiguous());
2817 }
2818
2819 #[test]
2820 fn ipv4_supernet_for_unspecified() {
2821 let nets = &[
2822 Ipv4Network::try_from((Ipv4Addr::new(128, 0, 0, 0), 24)).unwrap(),
2823 Ipv4Network::try_from((Ipv4Addr::new(192, 0, 0, 0), 24)).unwrap(),
2824 Ipv4Network::try_from((Ipv4Addr::new(65, 0, 0, 0), 24)).unwrap(),
2825 ];
2826
2827 let expected = Ipv4Network::try_from((Ipv4Addr::new(0, 0, 0, 0), 0)).unwrap();
2828 assert_eq!(expected, nets[0].supernet_for(&nets[1..]).to_contiguous());
2829 }
2830
2831 #[test]
2832 fn ipv4_supernet_for_non_contiguous() {
2833 let nets = &[
2834 Ipv4Network::new(Ipv4Addr::new(10, 40, 0, 1), Ipv4Addr::new(255, 255, 0, 255)),
2835 Ipv4Network::new(Ipv4Addr::new(10, 40, 0, 2), Ipv4Addr::new(255, 255, 0, 255)),
2836 Ipv4Network::new(Ipv4Addr::new(11, 40, 0, 3), Ipv4Addr::new(255, 255, 0, 255)),
2837 ];
2838
2839 let expected = Ipv4Network::try_from((Ipv4Addr::new(10, 0, 0, 0), 7)).unwrap();
2840 assert_eq!(expected, nets[0].supernet_for(&nets[1..]).to_contiguous());
2841 }
2842
2843 #[test]
2844 fn ipv4_last_addr() {
2845 // Contiguous networks (broadcast addresses).
2846 let net = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), Ipv4Addr::new(255, 255, 255, 0));
2847 assert_eq!(Ipv4Addr::new(192, 168, 1, 255), net.last_addr());
2848
2849 let net = Ipv4Network::new(Ipv4Addr::new(10, 0, 0, 0), Ipv4Addr::new(255, 255, 255, 0));
2850 assert_eq!(Ipv4Addr::new(10, 0, 0, 255), net.last_addr());
2851
2852 let net = Ipv4Network::new(Ipv4Addr::new(172, 16, 0, 0), Ipv4Addr::new(255, 255, 0, 0));
2853 assert_eq!(Ipv4Addr::new(172, 16, 255, 255), net.last_addr());
2854
2855 // Single address networks.
2856 let net = Ipv4Network::new(Ipv4Addr::new(10, 0, 0, 1), Ipv4Addr::new(255, 255, 255, 255));
2857 assert_eq!(Ipv4Addr::new(10, 0, 0, 1), net.last_addr());
2858
2859 // Unspecified network.
2860 let net = Ipv4Network::UNSPECIFIED;
2861 assert_eq!(Ipv4Addr::new(255, 255, 255, 255), net.last_addr());
2862
2863 // Non-contiguous networks.
2864 let net = Ipv4Network::new(Ipv4Addr::new(192, 168, 0, 1), Ipv4Addr::new(255, 255, 0, 255));
2865 assert_eq!(Ipv4Addr::new(192, 168, 255, 1), net.last_addr());
2866
2867 let net = Ipv4Network::new(Ipv4Addr::new(10, 0, 0, 42), Ipv4Addr::new(255, 0, 255, 255));
2868 assert_eq!(Ipv4Addr::new(10, 255, 0, 42), net.last_addr());
2869
2870 // Edge cases.
2871 let net = Ipv4Network::new(Ipv4Addr::new(255, 255, 255, 255), Ipv4Addr::new(255, 255, 255, 255));
2872 assert_eq!(Ipv4Addr::new(255, 255, 255, 255), net.last_addr());
2873
2874 let net = Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 0), Ipv4Addr::new(255, 0, 0, 0));
2875 assert_eq!(Ipv4Addr::new(127, 255, 255, 255), net.last_addr());
2876 }
2877
2878 #[test]
2879 fn parse_ipv6_explicit_mask_normalizes_addr() {
2880 // Address bits outside the mask should be cleared.
2881 assert_eq!(
2882 Ipv6Network::new(
2883 Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
2884 Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
2885 ),
2886 Ipv6Network::parse("2a02:6b8:c00:1:2:3:4:5/ffff:ffff:ff00::").unwrap()
2887 );
2888 }
2889
2890 #[test]
2891 fn test_ipv6_addr_as_u128() {
2892 assert_eq!(
2893 0x2a02_06b8_0c00_0000_0000_f800_0000_0000u128,
2894 (*Ipv6Network::parse("2a02:6b8:c00::f800:0:0/ffff:ffff:ff00:0:ffff:f800::")
2895 .unwrap()
2896 .addr())
2897 .into()
2898 );
2899 }
2900
2901 #[test]
2902 fn test_net_ipv6_contains() {
2903 assert!(
2904 Ipv6Network::parse("::/0")
2905 .unwrap()
2906 .contains(&Ipv6Network::parse("::1").unwrap())
2907 );
2908 assert!(
2909 Ipv6Network::parse("::/32")
2910 .unwrap()
2911 .contains(&Ipv6Network::parse("::/33").unwrap())
2912 );
2913
2914 assert!(
2915 !Ipv6Network::parse("::/33")
2916 .unwrap()
2917 .contains(&Ipv6Network::parse("::/32").unwrap())
2918 );
2919 }
2920
2921 #[test]
2922 fn test_net_ipv6_contains_self() {
2923 assert!(
2924 Ipv6Network::parse("::1")
2925 .unwrap()
2926 .contains(&Ipv6Network::parse("::1").unwrap())
2927 );
2928 }
2929
2930 #[test]
2931 fn test_net_ipv6_non_contiguous_contains_contiguous() {
2932 assert!(
2933 Ipv6Network::parse("2a02:6b8:c00::4d71:0:0/ffff:ffff:ff00::ffff:ffff:0:0")
2934 .unwrap()
2935 .contains(&Ipv6Network::parse("2a02:6b8:c00:1234:0:4d71::1").unwrap())
2936 );
2937 }
2938
2939 #[test]
2940 fn test_net_ipv6_is_contiguous() {
2941 assert!(Ipv6Network::parse("::/0").unwrap().is_contiguous());
2942 assert!(Ipv6Network::parse("::1").unwrap().is_contiguous());
2943 assert!(Ipv6Network::parse("2a02:6b8:c00::/40").unwrap().is_contiguous());
2944 assert!(
2945 Ipv6Network::parse("2a02:6b8:c00:1:2:3:4:1/127")
2946 .unwrap()
2947 .is_contiguous()
2948 );
2949 assert!(
2950 Ipv6Network::parse("2a02:6b8:c00:1:2:3:4:1/128")
2951 .unwrap()
2952 .is_contiguous()
2953 );
2954 assert!(Ipv6Network::parse("2a02:6b8:c00:1:2:3:4:1").unwrap().is_contiguous());
2955
2956 assert!(
2957 !Ipv6Network::parse("2a02:6b8:c00::f800:0:0/ffff:ffff:ff00::ffff:ffff:0:0")
2958 .unwrap()
2959 .is_contiguous()
2960 );
2961 assert!(
2962 !Ipv6Network::parse("2a02:6b8:c00::f800:0:0/ffff:ffff:ff00:0:ffff:f800::")
2963 .unwrap()
2964 .is_contiguous()
2965 );
2966 assert!(
2967 !Ipv6Network::parse("2a02:6b8:0:0:1234:5678::/ffff:ffff:0:0:ffff:ffff:0:0")
2968 .unwrap()
2969 .is_contiguous()
2970 );
2971 assert!(
2972 !Ipv6Network::parse("2a02:6b8:0:0:1234:5678::/ffff:ffff:0:0:f0f0:f0f0:f0f0:f0f0")
2973 .unwrap()
2974 .is_contiguous()
2975 );
2976 }
2977
2978 #[test]
2979 fn ipv6_supernet_for() {
2980 let nets = &[
2981 Ipv6Network::parse("2001:db8:1::/32").unwrap(),
2982 Ipv6Network::parse("2001:db8:2::/39").unwrap(),
2983 ];
2984
2985 let expected = Ipv6Network::parse("2001:db8::/32").unwrap();
2986 assert_eq!(expected, nets[0].supernet_for(&nets[1..]));
2987 }
2988
2989 #[test]
2990 fn ipv6_supernet_for_wide() {
2991 let nets = &[
2992 Ipv6Network::parse("2013:db8:1::1/64").unwrap(),
2993 Ipv6Network::parse("2013:db8:2::1/64").unwrap(),
2994 ];
2995
2996 let expected = Ipv6Network::parse("2013:db8::/46").unwrap();
2997 assert_eq!(expected, nets[0].supernet_for(&nets[1..]));
2998 }
2999
3000 #[test]
3001 fn ipv6_supernet_for_unspecified() {
3002 let nets = &[
3003 Ipv6Network::parse("8001:db8:1::/34").unwrap(),
3004 Ipv6Network::parse("2013:db8:2::/32").unwrap(),
3005 ];
3006
3007 let expected = Ipv6Network::parse("::/0").unwrap();
3008 assert_eq!(expected, nets[0].supernet_for(&nets[1..]));
3009 }
3010
3011 #[test]
3012 fn ipv6_supernet_for_non_contiguous() {
3013 let nets = &[
3014 Ipv6Network::parse("2a02:6b8:c00::48aa:0:0/ffff:ffff:ff00::ffff:ffff:0:0").unwrap(),
3015 Ipv6Network::parse("2a02:6b8:c00::4707:0:0/ffff:ffff:ff00::ffff:ffff:0:0").unwrap(),
3016 ];
3017
3018 let expected = Ipv6Network::parse("2a02:6b8:c00::4000:0:0/ffff:ffff:ff00::ffff:f000:0:0").unwrap();
3019 assert_eq!(expected, nets[0].supernet_for(&nets[1..]));
3020 }
3021
3022 #[test]
3023 fn ipv6_supernet_for_non_contiguous_different_aggregates() {
3024 let nets = &[
3025 Ipv6Network::parse("2a02:6b8:c00::48aa:0:0/ffff:ffff:ff00::ffff:ffff:0:0").unwrap(),
3026 Ipv6Network::parse("2a02:6b8:fc00::4707:0:0/ffff:ffff:ff00::ffff:ffff:0:0").unwrap(),
3027 ];
3028
3029 let expected = Ipv6Network::parse("2a02:6b8::/32").unwrap();
3030 assert_eq!(expected, nets[0].supernet_for(&nets[1..]));
3031 }
3032
3033 #[test]
3034 fn test_net_display_addr() {
3035 let net = Ipv4Network::new(Ipv4Addr::new(127, 0, 0, 1), Ipv4Addr::new(255, 255, 255, 255));
3036 assert_eq!("127.0.0.1/32", &format!("{net}"));
3037
3038 let net = Ipv6Network::new(
3039 Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0, 1),
3040 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
3041 );
3042 assert_eq!("2a02:6b8::1/128", &format!("{net}"));
3043 }
3044
3045 #[test]
3046 fn test_net_display_cidr() {
3047 let net = Ipv4Network::parse("10.0.0.0/24").unwrap();
3048 assert_eq!("10.0.0.0/24", &format!("{net}"));
3049
3050 let net = Ipv6Network::parse("2a02:6b8:c00:0:1:2::/96").unwrap();
3051 assert_eq!("2a02:6b8:c00:0:1:2::/96", &format!("{net}"));
3052 }
3053
3054 #[test]
3055 fn test_net_display_non_contiguous() {
3056 let net = Ipv4Network::parse("10.0.1.0/255.0.255.0").unwrap();
3057 assert_eq!("10.0.1.0/255.0.255.0", &format!("{net}"));
3058
3059 let net = Ipv6Network(
3060 "2a02:6b8:0:0:0:1234::".parse().unwrap(),
3061 "ffff:ffff:0:0:ffff:ffff:0:0".parse().unwrap(),
3062 );
3063 assert_eq!("2a02:6b8::1234:0:0/ffff:ffff::ffff:ffff:0:0", &format!("{net}"));
3064
3065 let net = Ipv6Network(
3066 "2a02:6b8:0:0:1234:5678::".parse().unwrap(),
3067 "ffff:ffff:0:0:ffff:ffff:0:0".parse().unwrap(),
3068 );
3069 assert_eq!("2a02:6b8::1234:5678:0:0/ffff:ffff::ffff:ffff:0:0", &format!("{net}"));
3070 }
3071
3072 #[test]
3073 fn test_ipv4_binary_split_empty() {
3074 assert!(ipv4_binary_split::<Ipv4Network>(&[]).is_none());
3075 }
3076
3077 #[test]
3078 fn test_ipv4_binary_split_less_than_required_networks() {
3079 let nets = &["127.0.0.1", "127.0.0.2"];
3080 let mut nets: Vec<_> = nets.iter().map(|net| Ipv4Network::parse(net).unwrap()).collect();
3081 nets.sort();
3082 nets.dedup();
3083
3084 assert!(ipv4_binary_split(&nets).is_none());
3085 }
3086
3087 #[test]
3088 fn test_ipv4_binary_split_three_nets() {
3089 let nets = &["127.0.0.1", "127.0.0.2", "127.0.0.3"];
3090 let mut nets: Vec<_> = nets.iter().map(|net| Ipv4Network::parse(net).unwrap()).collect();
3091 nets.sort();
3092 nets.dedup();
3093
3094 let (supernet, range) = ipv4_binary_split(&nets).unwrap();
3095 // 127.0.0.2/31 in binary is "0b...10/0b...10", which contains both "127.0.0.2"
3096 // and "127.0.0.3".
3097 assert_eq!(Ipv4Network::parse("127.0.0.2/31").unwrap(), supernet);
3098
3099 for (idx, net) in nets.iter().enumerate() {
3100 assert_eq!(range.contains(&idx), supernet.contains(net));
3101 }
3102 }
3103
3104 #[test]
3105 fn test_ipv4_binary_split_more_nets() {
3106 // .
3107 // ├─ 10.204.46.68/31
3108 // ├─ 10.204.49.12/31
3109 // ├─ 10.204.49.14/31
3110 // ├─ 10.204.49.18/31
3111 // └─ 10.204.49.32/28 [*]
3112 // ├─ 10.204.49.32/31
3113 // ├─ 10.204.49.34/31
3114 // ├─ 10.204.49.36/31
3115 // ├─ 10.204.49.38/31
3116 // └─ 10.204.49.40/31
3117
3118 let nets = &[
3119 "10.204.46.68/31",
3120 "10.204.49.12/31",
3121 "10.204.49.14/31",
3122 "10.204.49.18/31",
3123 "10.204.49.32/31",
3124 "10.204.49.34/31",
3125 "10.204.49.36/31",
3126 "10.204.49.38/31",
3127 "10.204.49.40/31",
3128 ];
3129 let mut nets: Vec<_> = nets.iter().map(|net| Ipv4Network::parse(net).unwrap()).collect();
3130 nets.sort();
3131 nets.dedup();
3132
3133 let (supernet, range) = ipv4_binary_split(&nets).unwrap();
3134
3135 assert_eq!(Ipv4Network::parse("10.204.49.32/28").unwrap(), supernet);
3136
3137 for (idx, net) in nets.iter().enumerate() {
3138 assert_eq!(range.contains(&idx), supernet.contains(net));
3139 }
3140 }
3141
3142 #[test]
3143 fn test_ipv4_binary_split_even_number_of_nets() {
3144 // .
3145 // ├─ 10.204.46.54/31
3146 // ├─ 10.204.46.68/31
3147 // ├─ 10.204.49.12/31
3148 // ├─ 10.204.49.14/31
3149 // ├─ 10.204.49.18/31
3150 // └─ 10.204.49.32/28 [*]
3151 // ├─ 10.204.49.32/31
3152 // ├─ 10.204.49.34/31
3153 // ├─ 10.204.49.36/31
3154 // ├─ 10.204.49.38/31
3155 // └─ 10.204.49.40/31
3156
3157 let nets = &[
3158 "10.204.46.54/31",
3159 "10.204.46.68/31",
3160 "10.204.49.12/31",
3161 "10.204.49.14/31",
3162 "10.204.49.18/31",
3163 "10.204.49.32/31",
3164 "10.204.49.34/31",
3165 "10.204.49.36/31",
3166 "10.204.49.38/31",
3167 "10.204.49.40/31",
3168 ];
3169 let mut nets: Vec<_> = nets.iter().map(|net| Ipv4Network::parse(net).unwrap()).collect();
3170 nets.sort();
3171 nets.dedup();
3172
3173 let (supernet, range) = ipv4_binary_split(&nets).unwrap();
3174
3175 assert_eq!(Ipv4Network::parse("10.204.49.32/28").unwrap(), supernet);
3176
3177 for (idx, net) in nets.iter().enumerate() {
3178 assert_eq!(range.contains(&idx), supernet.contains(net));
3179 }
3180 }
3181
3182 #[test]
3183 fn test_ipv4_binary_split_in_the_middle() {
3184 // .
3185 // ├─ 10.204.46.50/31
3186 // ├─ 10.204.46.54/31
3187 // ├─ 10.204.47.22/31
3188 // ├─ 10.204.49.0/26 [*]
3189 // │ ├─ 10.204.49.24/31
3190 // │ ├─ 10.204.49.26/31
3191 // │ ├─ 10.204.49.28/31
3192 // │ ├─ 10.204.49.32/31
3193 // │ ├─ 10.204.49.34/31
3194 // │ └─ 10.204.49.36/31
3195 // ├─ 10.204.50.38/31
3196 // └─ 10.204.50.40/31
3197
3198 let nets = &[
3199 "10.204.46.50/31",
3200 "10.204.46.54/31",
3201 "10.204.47.22/31",
3202 "10.204.49.24/31",
3203 "10.204.49.26/31",
3204 "10.204.49.28/31",
3205 "10.204.49.32/31",
3206 "10.204.49.34/31",
3207 "10.204.49.36/31",
3208 "10.204.50.38/31",
3209 "10.204.50.40/31",
3210 ];
3211 let mut nets: Vec<_> = nets.iter().map(|net| Ipv4Network::parse(net).unwrap()).collect();
3212 nets.sort();
3213 nets.dedup();
3214
3215 let (supernet, range) = ipv4_binary_split(&nets).unwrap();
3216
3217 assert_eq!(Ipv4Network::parse("10.204.49.0/26").unwrap(), supernet);
3218
3219 for (idx, net) in nets.iter().enumerate() {
3220 assert_eq!(range.contains(&idx), supernet.contains(net));
3221 }
3222 }
3223
3224 #[test]
3225 fn test_ipv6_binary_split_empty() {
3226 assert!(ipv6_binary_split::<Ipv6Network>(&[]).is_none());
3227 }
3228
3229 #[test]
3230 fn test_ipv6_binary_split_less_than_required_networks() {
3231 let nets = &["::1", "::2"];
3232 let mut nets: Vec<_> = nets.iter().map(|net| Ipv6Network::parse(net).unwrap()).collect();
3233 nets.sort();
3234 nets.dedup();
3235
3236 assert!(ipv6_binary_split(&nets).is_none());
3237 }
3238
3239 #[test]
3240 fn test_ipv6_binary_split_three_nets() {
3241 let nets = &["::1", "::2", "::3"];
3242 let mut nets: Vec<_> = nets.iter().map(|net| Ipv6Network::parse(net).unwrap()).collect();
3243 nets.sort();
3244 nets.dedup();
3245
3246 let (supernet, range) = ipv6_binary_split(&nets).unwrap();
3247 // ::2/127 in binary is "0b...10/0b...10", which contains both "::2" and "::3".
3248 assert_eq!(Ipv6Network::parse("::2/127").unwrap(), supernet);
3249
3250 for (idx, net) in nets.iter().enumerate() {
3251 assert_eq!(range.contains(&idx), supernet.contains(net));
3252 }
3253 }
3254
3255 #[test]
3256 fn test_ipv6_binary_split_more_nets() {
3257 let nets = &[
3258 "2a02:6b8:0:2a03::/64",
3259 "2a02:6b8:0:2a13::/64",
3260 "2a02:6b8:0:2a16::/64",
3261 "2a02:6b8:0:2a18::/64",
3262 "2a02:6b8:0:2a19::/64",
3263 "2a02:6b8:0:2a1c::/64",
3264 "2a02:6b8:0:2a1d::/64",
3265 "2a02:6b8:0:2a24::/64",
3266 "2a02:6b8:0:2800::/55",
3267 ];
3268 let mut nets: Vec<_> = nets.iter().map(|net| Ipv6Network::parse(net).unwrap()).collect();
3269 nets.sort();
3270 nets.dedup();
3271
3272 let (supernet, range) = ipv6_binary_split(&nets).unwrap();
3273
3274 assert_eq!(Ipv6Network::parse("2a02:6b8:0:2a10::/60").unwrap(), supernet);
3275
3276 for (idx, net) in nets.iter().enumerate() {
3277 assert_eq!(range.contains(&idx), supernet.contains(net));
3278 }
3279 }
3280
3281 #[test]
3282 fn test_ipv6_binary_split_even_number_of_nets() {
3283 let nets = &[
3284 "2a02:6b8:0:2318::/64",
3285 "2a02:6b8:0:231e::/64",
3286 "2a02:6b8:0:231f::/64",
3287 "2a02:6b8:0:2302::/64",
3288 "2a02:6b8:0:2303::/64",
3289 "2a02:6b8:0:2305::/64",
3290 "2a02:6b8:0:2306::/64",
3291 "2a02:6b8:0:2307::/64",
3292 "2a02:6b8:0:2311::/64",
3293 "2a02:6b8:0:2314::/64",
3294 ];
3295 let mut nets: Vec<_> = nets.iter().map(|net| Ipv6Network::parse(net).unwrap()).collect();
3296 nets.sort();
3297 nets.dedup();
3298
3299 let (supernet, range) = ipv6_binary_split(&nets).unwrap();
3300
3301 assert_eq!(Ipv6Network::parse("2a02:6b8:0:2300::/61").unwrap(), supernet);
3302
3303 for (idx, net) in nets.iter().enumerate() {
3304 assert_eq!(range.contains(&idx), supernet.contains(net));
3305 }
3306 }
3307
3308 #[test]
3309 fn test_ipv6_binary_split_in_the_middle() {
3310 let nets = &[
3311 "2a02:6b8:0:2302::/64",
3312 "2a02:6b8:0:2303::/64",
3313 "2a02:6b8:0:2305::/64",
3314 "2a02:6b8:0:2308::/64",
3315 "2a02:6b8:0:2309::/64",
3316 "2a02:6b8:0:230a::/64",
3317 "2a02:6b8:0:230b::/64",
3318 "2a02:6b8:0:230c::/64",
3319 "2a02:6b8:0:230d::/64",
3320 "2a02:6b8:0:2314::/64",
3321 "2a02:6b8:0:231f::/64",
3322 ];
3323 let mut nets: Vec<_> = nets.iter().map(|net| Ipv6Network::parse(net).unwrap()).collect();
3324 nets.sort();
3325 nets.dedup();
3326
3327 let (supernet, range) = ipv6_binary_split(&nets).unwrap();
3328
3329 assert_eq!(Ipv6Network::parse("2a02:6b8:0:2308::/61").unwrap(), supernet);
3330
3331 for (idx, net) in nets.iter().enumerate() {
3332 assert_eq!(range.contains(&idx), supernet.contains(net));
3333 }
3334 }
3335
3336 #[test]
3337 fn test_ipv6_binary_split_non_contiguous() {
3338 let nets = &[
3339 "2a02:6b8:c00::4510:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3340 "2a02:6b8:c00::4511:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3341 "2a02:6b8:c00::4512:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3342 "2a02:6b8:c00::4513:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3343 "2a02:6b8:c00::4514:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3344 "2a02:6b8:c00::4515:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3345 "2a02:6b8:c00::4516:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3346 "2a02:6b8:c00::4517:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3347 "2a02:6b8:c00::4518:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3348 "2a02:6b8:c00::4519:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3349 "2a02:6b8:c00::451a:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3350 ];
3351 let mut nets: Vec<_> = nets.iter().map(|net| Ipv6Network::parse(net).unwrap()).collect();
3352 nets.sort();
3353 nets.dedup();
3354
3355 let (supernet, range) = ipv6_binary_split(&nets).unwrap();
3356
3357 assert_eq!(
3358 Ipv6Network::parse("2a02:6b8:c00::4510:0:0/ffff:ffff:ff00:0:ffff:fff8::").unwrap(),
3359 supernet
3360 );
3361
3362 for (idx, net) in nets.iter().enumerate() {
3363 assert_eq!(range.contains(&idx), supernet.contains(net));
3364 }
3365 }
3366
3367 #[test]
3368 fn test_ipv6_binary_split_non_contiguous_in_the_middle() {
3369 let nets = &[
3370 "2a02:6b8:c00::2302:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3371 "2a02:6b8:c00::2303:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3372 "2a02:6b8:c00::2305:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3373 "2a02:6b8:c00::2308:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3374 "2a02:6b8:c00::2309:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3375 "2a02:6b8:c00::230a:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3376 "2a02:6b8:c00::230b:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3377 "2a02:6b8:c00::230c:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3378 "2a02:6b8:c00::230d:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3379 "2a02:6b8:c00::2314:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3380 "2a02:6b8:c00::231f:0:0/ffff:ffff:ff00::ffff:ffff:0:0",
3381 ];
3382 let mut nets: Vec<_> = nets.iter().map(|net| Ipv6Network::parse(net).unwrap()).collect();
3383 nets.sort();
3384 nets.dedup();
3385
3386 let (supernet, range) = ipv6_binary_split(&nets).unwrap();
3387
3388 assert_eq!(
3389 Ipv6Network::parse("2a02:6b8:c00::2308:0:0/ffff:ffff:ff00:0:ffff:fff8::").unwrap(),
3390 supernet
3391 );
3392
3393 for (idx, net) in nets.iter().enumerate() {
3394 assert_eq!(range.contains(&idx), supernet.contains(net));
3395 }
3396 }
3397
3398 #[test]
3399 fn test_ipnetwork_parse_v4() {
3400 let expected = IpNetwork::V4(Ipv4Network::new(
3401 Ipv4Addr::new(192, 168, 1, 0),
3402 Ipv4Addr::new(255, 255, 255, 0),
3403 ));
3404
3405 assert_eq!(expected, IpNetwork::parse("192.168.1.0/24").unwrap());
3406 }
3407
3408 #[test]
3409 fn test_ipnetwork_parse_v6() {
3410 let expected = IpNetwork::V6(Ipv6Network::new(
3411 Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
3412 Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
3413 ));
3414
3415 assert_eq!(expected, IpNetwork::parse("2a02:6b8:c00::/40").unwrap());
3416 }
3417
3418 #[test]
3419 fn test_ipnetwork_parse_invalid() {
3420 assert_eq!(
3421 IpNetParseError::CidrOverflow(CidrOverflowError(33, 32)),
3422 IpNetwork::parse("192.168.1.0/33").unwrap_err(),
3423 );
3424 }
3425
3426 #[test]
3427 fn test_ipnetwork_parse_invalid_v6() {
3428 assert_eq!(
3429 IpNetParseError::CidrOverflow(CidrOverflowError(129, 128)),
3430 IpNetwork::parse("2a02:6b8:c00::/129").unwrap_err(),
3431 );
3432 }
3433
3434 #[test]
3435 fn test_contiguous_ip_network_parse_v4() {
3436 let expected = Contiguous(Ipv4Network::new(
3437 Ipv4Addr::new(192, 168, 1, 0),
3438 Ipv4Addr::new(255, 255, 255, 0),
3439 ));
3440
3441 assert_eq!(expected, Contiguous::<Ipv4Network>::parse("192.168.1.0/24").unwrap(),);
3442 }
3443
3444 #[test]
3445 fn test_contiguous_ip_network_parse_v4_invalid() {
3446 assert_eq!(
3447 ContiguousIpNetParseError::NonContiguousNetwork,
3448 Contiguous::<Ipv4Network>::parse("192.168.0.1/255.255.0.255").unwrap_err(),
3449 );
3450 }
3451
3452 #[test]
3453 fn test_contiguous_ip_network_parse_v6() {
3454 let expected = Contiguous(Ipv6Network::new(
3455 Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
3456 Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
3457 ));
3458
3459 assert_eq!(expected, Contiguous::<Ipv6Network>::parse("2a02:6b8:c00::/40").unwrap(),);
3460 }
3461
3462 #[test]
3463 fn test_contiguous_ip_network_parse_v6_invalid() {
3464 assert_eq!(
3465 ContiguousIpNetParseError::NonContiguousNetwork,
3466 Contiguous::<Ipv6Network>::parse("2a02:6b8:c00::1234:0:0/ffff:ffff:ff00::ffff:ffff:0:0").unwrap_err(),
3467 );
3468 }
3469
3470 #[test]
3471 fn ipv6_last_addr() {
3472 // Contiguous networks (broadcast-like addresses).
3473 let net = Ipv6Network::new(
3474 Ipv6Addr::new(0x2001, 0xdb8, 0x1, 0, 0, 0, 0, 0),
3475 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0, 0),
3476 );
3477 assert_eq!(
3478 Ipv6Addr::new(0x2001, 0xdb8, 0x1, 0, 0, 0, 0xffff, 0xffff),
3479 net.last_addr()
3480 );
3481
3482 let net = Ipv6Network::new(
3483 Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
3484 Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
3485 );
3486 assert_eq!(
3487 Ipv6Addr::new(0x2a02, 0x6b8, 0x0cff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
3488 net.last_addr()
3489 );
3490
3491 let net = Ipv6Network::new(
3492 Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0, 0),
3493 Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0),
3494 );
3495 assert_eq!(
3496 Ipv6Addr::new(0x2a02, 0x6b8, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
3497 net.last_addr()
3498 );
3499
3500 // Single address networks.
3501 let net = Ipv6Network::new(
3502 Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x1),
3503 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
3504 );
3505 assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x1), net.last_addr());
3506
3507 // Unspecified network.
3508 let net = Ipv6Network::UNSPECIFIED;
3509 assert_eq!(
3510 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
3511 net.last_addr()
3512 );
3513
3514 // Non-contiguous networks.
3515 let net = Ipv6Network::new(
3516 Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0x1234, 0, 0),
3517 Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0xffff, 0xffff, 0, 0),
3518 );
3519 assert_eq!(
3520 Ipv6Addr::new(0x2a02, 0x6b8, 0x0cff, 0xffff, 0, 0x1234, 0xffff, 0xffff),
3521 net.last_addr()
3522 );
3523
3524 // Edge cases.
3525 let net = Ipv6Network::new(
3526 Ipv6Addr::new(0x2a02, 0x6b8, 0xc00, 0, 0, 0, 0, 0),
3527 Ipv6Addr::new(0xffff, 0xffff, 0xff00, 0, 0, 0, 0, 0),
3528 );
3529 assert_eq!(
3530 Ipv6Addr::new(0x2a02, 0x6b8, 0x0cff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff),
3531 net.last_addr()
3532 );
3533
3534 let net = Ipv6Network::new(
3535 Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0, 0),
3536 Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0xffff, 0, 0, 0, 0),
3537 );
3538 assert_eq!(
3539 Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff),
3540 net.last_addr()
3541 );
3542 }
3543
3544 #[test]
3545 fn ipnetwork_last_addr() {
3546 use core::net::IpAddr;
3547
3548 // IPv4 networks.
3549 let net = IpNetwork::parse("192.168.1.0/24").unwrap();
3550 assert_eq!(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 255)), net.last_addr());
3551
3552 let net = IpNetwork::parse("10.0.0.1").unwrap();
3553 assert_eq!(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)), net.last_addr());
3554
3555 let net = IpNetwork::parse("0.0.0.0/0").unwrap();
3556 assert_eq!(IpAddr::V4(Ipv4Addr::new(255, 255, 255, 255)), net.last_addr());
3557
3558 // IPv6 networks.
3559 let net = IpNetwork::parse("2001:db8:1::/64").unwrap();
3560 assert_eq!(
3561 IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0x1, 0, 0xffff, 0xffff, 0xffff, 0xffff)),
3562 net.last_addr()
3563 );
3564
3565 let net = IpNetwork::parse("2a02:6b8::1").unwrap();
3566 assert_eq!(
3567 IpAddr::V6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0, 0x1)),
3568 net.last_addr()
3569 );
3570
3571 let net = IpNetwork::parse("::/0").unwrap();
3572 assert_eq!(
3573 IpAddr::V6(Ipv6Addr::new(
3574 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
3575 )),
3576 net.last_addr()
3577 );
3578 }
3579}