3 reason = "extra functionality has not been \
4 scrutinized to the level that it should \
9 use crate::cmp::Ordering;
10 use crate::fmt::{self, Write as FmtWrite};
12 use crate::io::Write as IoWrite;
13 use crate::mem::transmute;
14 use crate::sys::net::netc as c;
15 use crate::sys_common::{AsInner, FromInner, IntoInner};
17 /// An IP address, either IPv4 or IPv6.
19 /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
20 /// respective documentation for more details.
22 /// The size of an `IpAddr` instance may vary depending on the target operating
28 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
30 /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
31 /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
33 /// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
34 /// assert_eq!("::1".parse(), Ok(localhost_v6));
36 /// assert_eq!(localhost_v4.is_ipv6(), false);
37 /// assert_eq!(localhost_v4.is_ipv4(), true);
39 #[stable(feature = "ip_addr", since = "1.7.0")]
40 #[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
43 #[stable(feature = "ip_addr", since = "1.7.0")]
44 V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
46 #[stable(feature = "ip_addr", since = "1.7.0")]
47 V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
52 /// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
53 /// They are usually represented as four octets.
55 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
57 /// The size of an `Ipv4Addr` struct may vary depending on the target operating
60 /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
62 /// # Textual representation
64 /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
65 /// notation, divided by `.` (this is called "dot-decimal notation").
67 /// [`FromStr`]: crate::str::FromStr
72 /// use std::net::Ipv4Addr;
74 /// let localhost = Ipv4Addr::new(127, 0, 0, 1);
75 /// assert_eq!("127.0.0.1".parse(), Ok(localhost));
76 /// assert_eq!(localhost.is_loopback(), true);
79 #[stable(feature = "rust1", since = "1.0.0")]
86 /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
87 /// They are usually represented as eight 16-bit segments.
89 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
91 /// The size of an `Ipv6Addr` struct may vary depending on the target operating
94 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
96 /// # Textual representation
98 /// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
99 /// an IPv6 address in text, but in general, each segments is written in hexadecimal
100 /// notation, and segments are separated by `:`. For more information, see
103 /// [`FromStr`]: crate::str::FromStr
104 /// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
109 /// use std::net::Ipv6Addr;
111 /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
112 /// assert_eq!("::1".parse(), Ok(localhost));
113 /// assert_eq!(localhost.is_loopback(), true);
116 #[stable(feature = "rust1", since = "1.0.0")]
117 pub struct Ipv6Addr {
121 #[allow(missing_docs)]
122 #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
123 pub enum Ipv6MulticastScope {
134 /// Returns [`true`] for the special 'unspecified' address.
136 /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
137 /// [`Ipv6Addr::is_unspecified()`] for more details.
139 /// [`true`]: ../../std/primitive.bool.html
144 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
146 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
147 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
149 #[stable(feature = "ip_shared", since = "1.12.0")]
150 pub fn is_unspecified(&self) -> bool {
152 IpAddr::V4(ip) => ip.is_unspecified(),
153 IpAddr::V6(ip) => ip.is_unspecified(),
157 /// Returns [`true`] if this is a loopback address.
159 /// See the documentation for [`Ipv4Addr::is_loopback()`] and
160 /// [`Ipv6Addr::is_loopback()`] for more details.
162 /// [`true`]: ../../std/primitive.bool.html
167 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
169 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
170 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
172 #[stable(feature = "ip_shared", since = "1.12.0")]
173 pub fn is_loopback(&self) -> bool {
175 IpAddr::V4(ip) => ip.is_loopback(),
176 IpAddr::V6(ip) => ip.is_loopback(),
180 /// Returns [`true`] if the address appears to be globally routable.
182 /// See the documentation for [`Ipv4Addr::is_global()`] and
183 /// [`Ipv6Addr::is_global()`] for more details.
185 /// [`true`]: ../../std/primitive.bool.html
192 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
194 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
195 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
197 pub fn is_global(&self) -> bool {
199 IpAddr::V4(ip) => ip.is_global(),
200 IpAddr::V6(ip) => ip.is_global(),
204 /// Returns [`true`] if this is a multicast address.
206 /// See the documentation for [`Ipv4Addr::is_multicast()`] and
207 /// [`Ipv6Addr::is_multicast()`] for more details.
209 /// [`true`]: ../../std/primitive.bool.html
214 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
216 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
217 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
219 #[stable(feature = "ip_shared", since = "1.12.0")]
220 pub fn is_multicast(&self) -> bool {
222 IpAddr::V4(ip) => ip.is_multicast(),
223 IpAddr::V6(ip) => ip.is_multicast(),
227 /// Returns [`true`] if this address is in a range designated for documentation.
229 /// See the documentation for [`Ipv4Addr::is_documentation()`] and
230 /// [`Ipv6Addr::is_documentation()`] for more details.
232 /// [`true`]: ../../std/primitive.bool.html
239 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
241 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
243 /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(),
247 pub fn is_documentation(&self) -> bool {
249 IpAddr::V4(ip) => ip.is_documentation(),
250 IpAddr::V6(ip) => ip.is_documentation(),
254 /// Returns [`true`] if this address is an [`IPv4` address], and [`false`]
257 /// [`true`]: ../../std/primitive.bool.html
258 /// [`false`]: ../../std/primitive.bool.html
259 /// [`IPv4` address]: IpAddr::V4
264 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
266 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
267 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
269 #[stable(feature = "ipaddr_checker", since = "1.16.0")]
270 pub fn is_ipv4(&self) -> bool {
271 matches!(self, IpAddr::V4(_))
274 /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
277 /// [`true`]: ../../std/primitive.bool.html
278 /// [`false`]: ../../std/primitive.bool.html
279 /// [`IPv6` address]: IpAddr::V6
284 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
286 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
287 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
289 #[stable(feature = "ipaddr_checker", since = "1.16.0")]
290 pub fn is_ipv6(&self) -> bool {
291 matches!(self, IpAddr::V6(_))
296 /// Creates a new IPv4 address from four eight-bit octets.
298 /// The result will represent the IP address `a`.`b`.`c`.`d`.
303 /// use std::net::Ipv4Addr;
305 /// let addr = Ipv4Addr::new(127, 0, 0, 1);
307 #[stable(feature = "rust1", since = "1.0.0")]
308 #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
309 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
310 // `s_addr` is stored as BE on all machine and the array is in BE order.
311 // So the native endian conversion method is used so that it's never swapped.
312 Ipv4Addr { inner: c::in_addr { s_addr: u32::from_ne_bytes([a, b, c, d]) } }
315 /// An IPv4 address with the address pointing to localhost: 127.0.0.1.
320 /// use std::net::Ipv4Addr;
322 /// let addr = Ipv4Addr::LOCALHOST;
323 /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
325 #[stable(feature = "ip_constructors", since = "1.30.0")]
326 pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
328 /// An IPv4 address representing an unspecified address: 0.0.0.0
333 /// use std::net::Ipv4Addr;
335 /// let addr = Ipv4Addr::UNSPECIFIED;
336 /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
338 #[stable(feature = "ip_constructors", since = "1.30.0")]
339 pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
341 /// An IPv4 address representing the broadcast address: 255.255.255.255
346 /// use std::net::Ipv4Addr;
348 /// let addr = Ipv4Addr::BROADCAST;
349 /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
351 #[stable(feature = "ip_constructors", since = "1.30.0")]
352 pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
354 /// Returns the four eight-bit integers that make up this address.
359 /// use std::net::Ipv4Addr;
361 /// let addr = Ipv4Addr::new(127, 0, 0, 1);
362 /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
364 #[stable(feature = "rust1", since = "1.0.0")]
365 pub fn octets(&self) -> [u8; 4] {
366 // This returns the order we want because s_addr is stored in big-endian.
367 self.inner.s_addr.to_ne_bytes()
370 /// Returns [`true`] for the special 'unspecified' address (0.0.0.0).
372 /// This property is defined in _UNIX Network Programming, Second Edition_,
373 /// W. Richard Stevens, p. 891; see also [ip7].
375 /// [`true`]: ../../std/primitive.bool.html
376 /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
381 /// use std::net::Ipv4Addr;
383 /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
384 /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
386 #[stable(feature = "ip_shared", since = "1.12.0")]
387 #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
388 pub const fn is_unspecified(&self) -> bool {
389 self.inner.s_addr == 0
392 /// Returns [`true`] if this is a loopback address (127.0.0.0/8).
394 /// This property is defined by [IETF RFC 1122].
396 /// [`true`]: ../../std/primitive.bool.html
397 /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
402 /// use std::net::Ipv4Addr;
404 /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
405 /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
407 #[stable(since = "1.7.0", feature = "ip_17")]
408 pub fn is_loopback(&self) -> bool {
409 self.octets()[0] == 127
412 /// Returns [`true`] if this is a private address.
414 /// The private address ranges are defined in [IETF RFC 1918] and include:
420 /// [`true`]: ../../std/primitive.bool.html
421 /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
426 /// use std::net::Ipv4Addr;
428 /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
429 /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
430 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
431 /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
432 /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
433 /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
434 /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
436 #[stable(since = "1.7.0", feature = "ip_17")]
437 pub fn is_private(&self) -> bool {
438 match self.octets() {
440 [172, b, ..] if b >= 16 && b <= 31 => true,
441 [192, 168, ..] => true,
446 /// Returns [`true`] if the address is link-local (169.254.0.0/16).
448 /// This property is defined by [IETF RFC 3927].
450 /// [`true`]: ../../std/primitive.bool.html
451 /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
456 /// use std::net::Ipv4Addr;
458 /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
459 /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
460 /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
462 #[stable(since = "1.7.0", feature = "ip_17")]
463 pub fn is_link_local(&self) -> bool {
464 match self.octets() {
465 [169, 254, ..] => true,
470 /// Returns [`true`] if the address appears to be globally routable.
471 /// See [iana-ipv4-special-registry][ipv4-sr].
473 /// The following return [`false`]:
475 /// - private addresses (see [`Ipv4Addr::is_private()`])
476 /// - the loopback address (see [`Ipv4Addr::is_loopback()`])
477 /// - the link-local address (see [`Ipv4Addr::is_link_local()`])
478 /// - the broadcast address (see [`Ipv4Addr::is_broadcast()`])
479 /// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`])
480 /// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole
482 /// - addresses reserved for future protocols (see
483 /// [`Ipv4Addr::is_ietf_protocol_assignment()`], except
484 /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
485 /// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`]
486 /// - addresses reserved for networking devices benchmarking (see
487 /// [`Ipv4Addr::is_benchmarking()`])
489 /// [`true`]: ../../std/primitive.bool.html
490 /// [`false`]: ../../std/primitive.bool.html
491 /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
498 /// use std::net::Ipv4Addr;
500 /// // private addresses are not global
501 /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
502 /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
503 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
505 /// // the 0.0.0.0/8 block is not global
506 /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
507 /// // in particular, the unspecified address is not global
508 /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
510 /// // the loopback address is not global
511 /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
513 /// // link local addresses are not global
514 /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
516 /// // the broadcast address is not global
517 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
519 /// // the address space designated for documentation is not global
520 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
521 /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
522 /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
524 /// // shared addresses are not global
525 /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
527 /// // addresses reserved for protocol assignment are not global
528 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
529 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
531 /// // addresses reserved for future use are not global
532 /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
534 /// // addresses reserved for network devices benchmarking are not global
535 /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
537 /// // All the other addresses are global
538 /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
539 /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
541 pub fn is_global(&self) -> bool {
542 // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
543 // globally routable addresses in the 192.0.0.0/24 range.
544 if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
548 && !self.is_loopback()
549 && !self.is_link_local()
550 && !self.is_broadcast()
551 && !self.is_documentation()
553 && !self.is_ietf_protocol_assignment()
554 && !self.is_reserved()
555 && !self.is_benchmarking()
556 // Make sure the address is not in 0.0.0.0/8
557 && self.octets()[0] != 0
560 /// Returns [`true`] if this address is part of the Shared Address Space defined in
561 /// [IETF RFC 6598] (`100.64.0.0/10`).
563 /// [`true`]: ../../std/primitive.bool.html
564 /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
570 /// use std::net::Ipv4Addr;
572 /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
573 /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
574 /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
576 pub fn is_shared(&self) -> bool {
577 self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
580 /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to
581 /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890].
583 /// Note that parts of this block are in use:
585 /// - `192.0.0.8/32` is the "IPv4 dummy address" (see [IETF RFC 7600])
586 /// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723])
587 /// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155])
589 /// [`true`]: ../../std/primitive.bool.html
590 /// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890
591 /// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600
592 /// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723
593 /// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155
599 /// use std::net::Ipv4Addr;
601 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true);
602 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true);
603 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true);
604 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true);
605 /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false);
606 /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
608 pub fn is_ietf_protocol_assignment(&self) -> bool {
609 self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
612 /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
613 /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
614 /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
616 /// [`true`]: ../../std/primitive.bool.html
617 /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
618 /// [errata 423]: https://www.rfc-editor.org/errata/eid423
624 /// use std::net::Ipv4Addr;
626 /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
627 /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
628 /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
629 /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
631 pub fn is_benchmarking(&self) -> bool {
632 self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
635 /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
636 /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
637 /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
638 /// it is obviously not reserved for future use.
640 /// [`true`]: ../../std/primitive.bool.html
641 /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
645 /// As IANA assigns new addresses, this method will be
646 /// updated. This may result in non-reserved addresses being
647 /// treated as reserved in code that relies on an outdated version
654 /// use std::net::Ipv4Addr;
656 /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
657 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
659 /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
660 /// // The broadcast address is not considered as reserved for future use by this implementation
661 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
663 pub fn is_reserved(&self) -> bool {
664 self.octets()[0] & 240 == 240 && !self.is_broadcast()
667 /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
669 /// Multicast addresses have a most significant octet between 224 and 239,
670 /// and is defined by [IETF RFC 5771].
672 /// [`true`]: ../../std/primitive.bool.html
673 /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
678 /// use std::net::Ipv4Addr;
680 /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
681 /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
682 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
684 #[stable(since = "1.7.0", feature = "ip_17")]
685 pub fn is_multicast(&self) -> bool {
686 self.octets()[0] >= 224 && self.octets()[0] <= 239
689 /// Returns [`true`] if this is a broadcast address (255.255.255.255).
691 /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
693 /// [`true`]: ../../std/primitive.bool.html
694 /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
699 /// use std::net::Ipv4Addr;
701 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
702 /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
704 #[stable(since = "1.7.0", feature = "ip_17")]
705 pub fn is_broadcast(&self) -> bool {
706 self == &Self::BROADCAST
709 /// Returns [`true`] if this address is in a range designated for documentation.
711 /// This is defined in [IETF RFC 5737]:
713 /// - 192.0.2.0/24 (TEST-NET-1)
714 /// - 198.51.100.0/24 (TEST-NET-2)
715 /// - 203.0.113.0/24 (TEST-NET-3)
717 /// [`true`]: ../../std/primitive.bool.html
718 /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
723 /// use std::net::Ipv4Addr;
725 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
726 /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
727 /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
728 /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
730 #[stable(since = "1.7.0", feature = "ip_17")]
731 pub fn is_documentation(&self) -> bool {
732 match self.octets() {
733 [192, 0, 2, _] => true,
734 [198, 51, 100, _] => true,
735 [203, 0, 113, _] => true,
740 /// Converts this address to an IPv4-compatible [`IPv6` address].
742 /// a.b.c.d becomes ::a.b.c.d
744 /// [`IPv6` address]: Ipv6Addr
749 /// use std::net::{Ipv4Addr, Ipv6Addr};
752 /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
753 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)
756 #[stable(feature = "rust1", since = "1.0.0")]
757 pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
758 let [a, b, c, d] = self.octets();
759 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
762 /// Converts this address to an IPv4-mapped [`IPv6` address].
764 /// a.b.c.d becomes ::ffff:a.b.c.d
766 /// [`IPv6` address]: Ipv6Addr
771 /// use std::net::{Ipv4Addr, Ipv6Addr};
773 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
774 /// Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
776 #[stable(feature = "rust1", since = "1.0.0")]
777 pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
778 let [a, b, c, d] = self.octets();
779 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d])
783 #[stable(feature = "ip_addr", since = "1.7.0")]
784 impl fmt::Display for IpAddr {
785 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
787 IpAddr::V4(ip) => ip.fmt(fmt),
788 IpAddr::V6(ip) => ip.fmt(fmt),
793 #[stable(feature = "ip_addr", since = "1.7.0")]
794 impl fmt::Debug for IpAddr {
795 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
796 fmt::Display::fmt(self, fmt)
800 #[stable(feature = "ip_from_ip", since = "1.16.0")]
801 impl From<Ipv4Addr> for IpAddr {
802 /// Copies this address to a new `IpAddr::V4`.
807 /// use std::net::{IpAddr, Ipv4Addr};
809 /// let addr = Ipv4Addr::new(127, 0, 0, 1);
812 /// IpAddr::V4(addr),
813 /// IpAddr::from(addr)
816 fn from(ipv4: Ipv4Addr) -> IpAddr {
821 #[stable(feature = "ip_from_ip", since = "1.16.0")]
822 impl From<Ipv6Addr> for IpAddr {
823 /// Copies this address to a new `IpAddr::V6`.
828 /// use std::net::{IpAddr, Ipv6Addr};
830 /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
833 /// IpAddr::V6(addr),
834 /// IpAddr::from(addr)
837 fn from(ipv6: Ipv6Addr) -> IpAddr {
842 #[stable(feature = "rust1", since = "1.0.0")]
843 impl fmt::Display for Ipv4Addr {
844 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
845 let octets = self.octets();
846 // Fast Path: if there's no alignment stuff, write directly to the buffer
847 if fmt.precision().is_none() && fmt.width().is_none() {
848 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
850 const IPV4_BUF_LEN: usize = 15; // Long enough for the longest possible IPv4 address
851 let mut buf = [0u8; IPV4_BUF_LEN];
852 let mut buf_slice = &mut buf[..];
854 // Note: The call to write should never fail, hence the unwrap
855 write!(buf_slice, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
856 let len = IPV4_BUF_LEN - buf_slice.len();
858 // This unsafe is OK because we know what is being written to the buffer
859 let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
865 #[stable(feature = "rust1", since = "1.0.0")]
866 impl fmt::Debug for Ipv4Addr {
867 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
868 fmt::Display::fmt(self, fmt)
872 #[stable(feature = "rust1", since = "1.0.0")]
873 impl Clone for Ipv4Addr {
874 fn clone(&self) -> Ipv4Addr {
879 #[stable(feature = "rust1", since = "1.0.0")]
880 impl PartialEq for Ipv4Addr {
881 fn eq(&self, other: &Ipv4Addr) -> bool {
882 self.inner.s_addr == other.inner.s_addr
886 #[stable(feature = "ip_cmp", since = "1.16.0")]
887 impl PartialEq<Ipv4Addr> for IpAddr {
888 fn eq(&self, other: &Ipv4Addr) -> bool {
890 IpAddr::V4(v4) => v4 == other,
891 IpAddr::V6(_) => false,
896 #[stable(feature = "ip_cmp", since = "1.16.0")]
897 impl PartialEq<IpAddr> for Ipv4Addr {
898 fn eq(&self, other: &IpAddr) -> bool {
900 IpAddr::V4(v4) => self == v4,
901 IpAddr::V6(_) => false,
906 #[stable(feature = "rust1", since = "1.0.0")]
907 impl Eq for Ipv4Addr {}
909 #[stable(feature = "rust1", since = "1.0.0")]
910 impl hash::Hash for Ipv4Addr {
911 fn hash<H: hash::Hasher>(&self, s: &mut H) {
913 // * hash in big endian order
914 // * in netbsd, `in_addr` has `repr(packed)`, we need to
915 // copy `s_addr` to avoid unsafe borrowing
916 { self.inner.s_addr }.hash(s)
920 #[stable(feature = "rust1", since = "1.0.0")]
921 impl PartialOrd for Ipv4Addr {
922 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
923 Some(self.cmp(other))
927 #[stable(feature = "ip_cmp", since = "1.16.0")]
928 impl PartialOrd<Ipv4Addr> for IpAddr {
929 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
931 IpAddr::V4(v4) => v4.partial_cmp(other),
932 IpAddr::V6(_) => Some(Ordering::Greater),
937 #[stable(feature = "ip_cmp", since = "1.16.0")]
938 impl PartialOrd<IpAddr> for Ipv4Addr {
939 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
941 IpAddr::V4(v4) => self.partial_cmp(v4),
942 IpAddr::V6(_) => Some(Ordering::Less),
947 #[stable(feature = "rust1", since = "1.0.0")]
948 impl Ord for Ipv4Addr {
949 fn cmp(&self, other: &Ipv4Addr) -> Ordering {
950 // Compare as native endian
951 u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
955 impl IntoInner<c::in_addr> for Ipv4Addr {
956 fn into_inner(self) -> c::in_addr {
961 #[stable(feature = "ip_u32", since = "1.1.0")]
962 impl From<Ipv4Addr> for u32 {
963 /// Converts an `Ipv4Addr` into a host byte order `u32`.
968 /// use std::net::Ipv4Addr;
970 /// let addr = Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe);
971 /// assert_eq!(0xcafebabe, u32::from(addr));
973 fn from(ip: Ipv4Addr) -> u32 {
974 let ip = ip.octets();
975 u32::from_be_bytes(ip)
979 #[stable(feature = "ip_u32", since = "1.1.0")]
980 impl From<u32> for Ipv4Addr {
981 /// Converts a host byte order `u32` into an `Ipv4Addr`.
986 /// use std::net::Ipv4Addr;
988 /// let addr = Ipv4Addr::from(0xcafebabe);
989 /// assert_eq!(Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe), addr);
991 fn from(ip: u32) -> Ipv4Addr {
992 Ipv4Addr::from(ip.to_be_bytes())
996 #[stable(feature = "from_slice_v4", since = "1.9.0")]
997 impl From<[u8; 4]> for Ipv4Addr {
998 /// Creates an `Ipv4Addr` from a four element byte array.
1003 /// use std::net::Ipv4Addr;
1005 /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
1006 /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
1008 fn from(octets: [u8; 4]) -> Ipv4Addr {
1009 Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
1013 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1014 impl From<[u8; 4]> for IpAddr {
1015 /// Creates an `IpAddr::V4` from a four element byte array.
1020 /// use std::net::{IpAddr, Ipv4Addr};
1022 /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
1023 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
1025 fn from(octets: [u8; 4]) -> IpAddr {
1026 IpAddr::V4(Ipv4Addr::from(octets))
1031 /// Creates a new IPv6 address from eight 16-bit segments.
1033 /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
1038 /// use std::net::Ipv6Addr;
1040 /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
1042 #[stable(feature = "rust1", since = "1.0.0")]
1043 #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
1044 #[allow_internal_unstable(const_fn_transmute)]
1045 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
1057 inner: c::in6_addr {
1058 // All elements in `addr16` are big endian.
1059 // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
1060 s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
1065 /// An IPv6 address representing localhost: `::1`.
1070 /// use std::net::Ipv6Addr;
1072 /// let addr = Ipv6Addr::LOCALHOST;
1073 /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
1075 #[stable(feature = "ip_constructors", since = "1.30.0")]
1076 pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
1078 /// An IPv6 address representing the unspecified address: `::`
1083 /// use std::net::Ipv6Addr;
1085 /// let addr = Ipv6Addr::UNSPECIFIED;
1086 /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
1088 #[stable(feature = "ip_constructors", since = "1.30.0")]
1089 pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
1091 /// Returns the eight 16-bit segments that make up this address.
1096 /// use std::net::Ipv6Addr;
1098 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
1099 /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
1101 #[stable(feature = "rust1", since = "1.0.0")]
1102 pub fn segments(&self) -> [u16; 8] {
1103 // All elements in `s6_addr` must be big endian.
1104 // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
1105 let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
1106 // We want native endian u16
1119 /// Returns [`true`] for the special 'unspecified' address (::).
1121 /// This property is defined in [IETF RFC 4291].
1123 /// [`true`]: ../../std/primitive.bool.html
1124 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1129 /// use std::net::Ipv6Addr;
1131 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
1132 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
1134 #[stable(since = "1.7.0", feature = "ip_17")]
1135 pub fn is_unspecified(&self) -> bool {
1136 self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
1139 /// Returns [`true`] if this is a loopback address (::1).
1141 /// This property is defined in [IETF RFC 4291].
1143 /// [`true`]: ../../std/primitive.bool.html
1144 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1149 /// use std::net::Ipv6Addr;
1151 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
1152 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
1154 #[stable(since = "1.7.0", feature = "ip_17")]
1155 pub fn is_loopback(&self) -> bool {
1156 self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
1159 /// Returns [`true`] if the address appears to be globally routable.
1161 /// The following return [`false`]:
1163 /// - the loopback address
1164 /// - link-local and unique local unicast addresses
1165 /// - interface-, link-, realm-, admin- and site-local multicast addresses
1167 /// [`true`]: ../../std/primitive.bool.html
1168 /// [`false`]: ../../std/primitive.bool.html
1175 /// use std::net::Ipv6Addr;
1177 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
1178 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
1179 /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
1181 pub fn is_global(&self) -> bool {
1182 match self.multicast_scope() {
1183 Some(Ipv6MulticastScope::Global) => true,
1184 None => self.is_unicast_global(),
1189 /// Returns [`true`] if this is a unique local address (`fc00::/7`).
1191 /// This property is defined in [IETF RFC 4193].
1193 /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
1195 /// [`true`]: ../../std/primitive.bool.html
1202 /// use std::net::Ipv6Addr;
1204 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
1205 /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
1207 pub fn is_unique_local(&self) -> bool {
1208 (self.segments()[0] & 0xfe00) == 0xfc00
1211 /// Returns [`true`] if the address is a unicast link-local address (`fe80::/64`).
1213 /// A common mis-conception is to think that "unicast link-local addresses start with
1214 /// `fe80::`", but the [IETF RFC 4291] actually defines a stricter format for these addresses:
1218 /// | bits | 54 bits | 64 bits |
1219 /// +----------+-------------------------+----------------------------+
1220 /// |1111111010| 0 | interface ID |
1221 /// +----------+-------------------------+----------------------------+
1224 /// This method validates the format defined in the RFC and won't recognize the following
1225 /// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example.
1226 /// If you need a less strict validation use [`Ipv6Addr::is_unicast_link_local()`] instead.
1228 /// [`true`]: ../../std/primitive.bool.html
1235 /// use std::net::Ipv6Addr;
1237 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
1238 /// assert!(ip.is_unicast_link_local_strict());
1240 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
1241 /// assert!(ip.is_unicast_link_local_strict());
1243 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
1244 /// assert!(!ip.is_unicast_link_local_strict());
1245 /// assert!(ip.is_unicast_link_local());
1247 /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
1248 /// assert!(!ip.is_unicast_link_local_strict());
1249 /// assert!(ip.is_unicast_link_local());
1254 /// - [IETF RFC 4291 section 2.5.6]
1255 /// - [RFC 4291 errata 4406] (which has been rejected but provides useful
1257 /// - [`Ipv6Addr::is_unicast_link_local()`]
1259 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1260 /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
1261 /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
1262 pub fn is_unicast_link_local_strict(&self) -> bool {
1263 (self.segments()[0] & 0xffff) == 0xfe80
1264 && (self.segments()[1] & 0xffff) == 0
1265 && (self.segments()[2] & 0xffff) == 0
1266 && (self.segments()[3] & 0xffff) == 0
1269 /// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`).
1271 /// This method returns [`true`] for addresses in the range reserved by [RFC 4291 section 2.4],
1272 /// i.e. addresses with the following format:
1276 /// | bits | 54 bits | 64 bits |
1277 /// +----------+-------------------------+----------------------------+
1278 /// |1111111010| arbitratry value | interface ID |
1279 /// +----------+-------------------------+----------------------------+
1282 /// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be
1283 /// unicast link-local addresses, whereas [`Ipv6Addr::is_unicast_link_local_strict()`] does not.
1284 /// If you need a strict validation fully compliant with the RFC, use
1285 /// [`Ipv6Addr::is_unicast_link_local_strict()`] instead.
1287 /// [`true`]: ../../std/primitive.bool.html
1294 /// use std::net::Ipv6Addr;
1296 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
1297 /// assert!(ip.is_unicast_link_local());
1299 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
1300 /// assert!(ip.is_unicast_link_local());
1302 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
1303 /// assert!(ip.is_unicast_link_local());
1304 /// assert!(!ip.is_unicast_link_local_strict());
1306 /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
1307 /// assert!(ip.is_unicast_link_local());
1308 /// assert!(!ip.is_unicast_link_local_strict());
1313 /// - [IETF RFC 4291 section 2.4]
1314 /// - [RFC 4291 errata 4406] (which has been rejected but provides useful
1317 /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
1318 /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
1319 pub fn is_unicast_link_local(&self) -> bool {
1320 (self.segments()[0] & 0xffc0) == 0xfe80
1323 /// Returns [`true`] if this is a deprecated unicast site-local address (fec0::/10). The
1324 /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as:
1328 /// | bits | 54 bits | 64 bits |
1329 /// +----------+-------------------------+----------------------------+
1330 /// |1111111011| subnet ID | interface ID |
1331 /// +----------+-------------------------+----------------------------+
1334 /// [`true`]: ../../std/primitive.bool.html
1335 /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
1342 /// use std::net::Ipv6Addr;
1345 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(),
1348 /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
1353 /// As per [RFC 3879], the whole `FEC0::/10` prefix is
1354 /// deprecated. New software must not support site-local
1357 /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
1358 pub fn is_unicast_site_local(&self) -> bool {
1359 (self.segments()[0] & 0xffc0) == 0xfec0
1362 /// Returns [`true`] if this is an address reserved for documentation
1363 /// (2001:db8::/32).
1365 /// This property is defined in [IETF RFC 3849].
1367 /// [`true`]: ../../std/primitive.bool.html
1368 /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
1375 /// use std::net::Ipv6Addr;
1377 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
1378 /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
1380 pub fn is_documentation(&self) -> bool {
1381 (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
1384 /// Returns [`true`] if the address is a globally routable unicast address.
1386 /// The following return false:
1388 /// - the loopback address
1389 /// - the link-local addresses
1390 /// - unique local addresses
1391 /// - the unspecified address
1392 /// - the address range reserved for documentation
1394 /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
1397 /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
1398 /// be supported in new implementations (i.e., new implementations must treat this prefix as
1399 /// Global Unicast).
1402 /// [`true`]: ../../std/primitive.bool.html
1403 /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
1410 /// use std::net::Ipv6Addr;
1412 /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
1413 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
1415 pub fn is_unicast_global(&self) -> bool {
1416 !self.is_multicast()
1417 && !self.is_loopback()
1418 && !self.is_unicast_link_local()
1419 && !self.is_unique_local()
1420 && !self.is_unspecified()
1421 && !self.is_documentation()
1424 /// Returns the address's multicast scope if the address is multicast.
1431 /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
1434 /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
1435 /// Some(Ipv6MulticastScope::Global)
1437 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
1439 pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
1440 if self.is_multicast() {
1441 match self.segments()[0] & 0x000f {
1442 1 => Some(Ipv6MulticastScope::InterfaceLocal),
1443 2 => Some(Ipv6MulticastScope::LinkLocal),
1444 3 => Some(Ipv6MulticastScope::RealmLocal),
1445 4 => Some(Ipv6MulticastScope::AdminLocal),
1446 5 => Some(Ipv6MulticastScope::SiteLocal),
1447 8 => Some(Ipv6MulticastScope::OrganizationLocal),
1448 14 => Some(Ipv6MulticastScope::Global),
1456 /// Returns [`true`] if this is a multicast address (ff00::/8).
1458 /// This property is defined by [IETF RFC 4291].
1460 /// [`true`]: ../../std/primitive.bool.html
1461 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1466 /// use std::net::Ipv6Addr;
1468 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
1469 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
1471 #[stable(since = "1.7.0", feature = "ip_17")]
1472 pub fn is_multicast(&self) -> bool {
1473 (self.segments()[0] & 0xff00) == 0xff00
1476 /// Converts this address to an [`IPv4` address] if it's an "IPv4-mapped IPv6 address"
1477 /// defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
1479 /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
1480 /// All addresses *not* starting with `::ffff` will return `None`.
1482 /// [`IPv4` address]: Ipv4Addr
1483 /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1490 /// use std::net::{Ipv4Addr, Ipv6Addr};
1492 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
1493 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
1494 /// Some(Ipv4Addr::new(192, 10, 2, 255)));
1495 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
1497 pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
1498 match self.octets() {
1499 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
1500 Some(Ipv4Addr::new(a, b, c, d))
1506 /// Converts this address to an [`IPv4` address]. Returns [`None`] if this address is
1507 /// neither IPv4-compatible or IPv4-mapped.
1509 /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
1511 /// [`IPv4` address]: Ipv4Addr
1516 /// use std::net::{Ipv4Addr, Ipv6Addr};
1518 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
1519 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
1520 /// Some(Ipv4Addr::new(192, 10, 2, 255)));
1521 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
1522 /// Some(Ipv4Addr::new(0, 0, 0, 1)));
1524 #[stable(feature = "rust1", since = "1.0.0")]
1525 pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
1526 if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
1527 let [a, b] = ab.to_be_bytes();
1528 let [c, d] = cd.to_be_bytes();
1529 Some(Ipv4Addr::new(a, b, c, d))
1535 /// Returns the sixteen eight-bit integers the IPv6 address consists of.
1538 /// use std::net::Ipv6Addr;
1540 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
1541 /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
1543 #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
1544 #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
1545 pub const fn octets(&self) -> [u8; 16] {
1550 /// Write an Ipv6Addr, conforming to the canonical style described by
1551 /// [RFC 5952](https://tools.ietf.org/html/rfc5952).
1552 #[stable(feature = "rust1", since = "1.0.0")]
1553 impl fmt::Display for Ipv6Addr {
1554 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1555 // If there are no alignment requirements, write out the IP address to
1556 // f. Otherwise, write it to a local buffer, then use f.pad.
1557 if f.precision().is_none() && f.width().is_none() {
1558 let segments = self.segments();
1560 // Special case for :: and ::1; otherwise they get written with the
1562 if self.is_unspecified() {
1564 } else if self.is_loopback() {
1566 } else if let Some(ipv4) = self.to_ipv4() {
1568 // IPv4 Compatible address
1569 0 => write!(f, "::{}", ipv4),
1570 // IPv4 Mapped address
1571 0xffff => write!(f, "::ffff:{}", ipv4),
1572 _ => unreachable!(),
1575 #[derive(Copy, Clone, Default)]
1581 // Find the inner 0 span
1583 let mut longest = Span::default();
1584 let mut current = Span::default();
1586 for (i, &segment) in segments.iter().enumerate() {
1588 if current.len == 0 {
1594 if current.len > longest.len {
1598 current = Span::default();
1605 /// Write a colon-separated part of the address
1607 fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
1608 if let Some(first) = chunk.first() {
1609 fmt::LowerHex::fmt(first, f)?;
1610 for segment in &chunk[1..] {
1612 fmt::LowerHex::fmt(segment, f)?;
1619 fmt_subslice(f, &segments[..zeroes.start])?;
1621 fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
1623 fmt_subslice(f, &segments)
1627 // Slow path: write the address to a local buffer, the use f.pad.
1628 // Defined recursively by using the fast path to write to the
1631 // This is the largest possible size of an IPv6 address
1632 const IPV6_BUF_LEN: usize = (4 * 8) + 7;
1633 let mut buf = [0u8; IPV6_BUF_LEN];
1634 let mut buf_slice = &mut buf[..];
1636 // Note: This call to write should never fail, so unwrap is okay.
1637 write!(buf_slice, "{}", self).unwrap();
1638 let len = IPV6_BUF_LEN - buf_slice.len();
1640 // This is safe because we know exactly what can be in this buffer
1641 let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
1647 #[stable(feature = "rust1", since = "1.0.0")]
1648 impl fmt::Debug for Ipv6Addr {
1649 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1650 fmt::Display::fmt(self, fmt)
1654 #[stable(feature = "rust1", since = "1.0.0")]
1655 impl Clone for Ipv6Addr {
1656 fn clone(&self) -> Ipv6Addr {
1661 #[stable(feature = "rust1", since = "1.0.0")]
1662 impl PartialEq for Ipv6Addr {
1663 fn eq(&self, other: &Ipv6Addr) -> bool {
1664 self.inner.s6_addr == other.inner.s6_addr
1668 #[stable(feature = "ip_cmp", since = "1.16.0")]
1669 impl PartialEq<IpAddr> for Ipv6Addr {
1670 fn eq(&self, other: &IpAddr) -> bool {
1672 IpAddr::V4(_) => false,
1673 IpAddr::V6(v6) => self == v6,
1678 #[stable(feature = "ip_cmp", since = "1.16.0")]
1679 impl PartialEq<Ipv6Addr> for IpAddr {
1680 fn eq(&self, other: &Ipv6Addr) -> bool {
1682 IpAddr::V4(_) => false,
1683 IpAddr::V6(v6) => v6 == other,
1688 #[stable(feature = "rust1", since = "1.0.0")]
1689 impl Eq for Ipv6Addr {}
1691 #[stable(feature = "rust1", since = "1.0.0")]
1692 impl hash::Hash for Ipv6Addr {
1693 fn hash<H: hash::Hasher>(&self, s: &mut H) {
1694 self.inner.s6_addr.hash(s)
1698 #[stable(feature = "rust1", since = "1.0.0")]
1699 impl PartialOrd for Ipv6Addr {
1700 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1701 Some(self.cmp(other))
1705 #[stable(feature = "ip_cmp", since = "1.16.0")]
1706 impl PartialOrd<Ipv6Addr> for IpAddr {
1707 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1709 IpAddr::V4(_) => Some(Ordering::Less),
1710 IpAddr::V6(v6) => v6.partial_cmp(other),
1715 #[stable(feature = "ip_cmp", since = "1.16.0")]
1716 impl PartialOrd<IpAddr> for Ipv6Addr {
1717 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
1719 IpAddr::V4(_) => Some(Ordering::Greater),
1720 IpAddr::V6(v6) => self.partial_cmp(v6),
1725 #[stable(feature = "rust1", since = "1.0.0")]
1726 impl Ord for Ipv6Addr {
1727 fn cmp(&self, other: &Ipv6Addr) -> Ordering {
1728 self.segments().cmp(&other.segments())
1732 impl AsInner<c::in6_addr> for Ipv6Addr {
1733 fn as_inner(&self) -> &c::in6_addr {
1737 impl FromInner<c::in6_addr> for Ipv6Addr {
1738 fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
1739 Ipv6Addr { inner: addr }
1743 #[stable(feature = "i128", since = "1.26.0")]
1744 impl From<Ipv6Addr> for u128 {
1745 /// Convert an `Ipv6Addr` into a host byte order `u128`.
1750 /// use std::net::Ipv6Addr;
1752 /// let addr = Ipv6Addr::new(
1753 /// 0x1020, 0x3040, 0x5060, 0x7080,
1754 /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1756 /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
1758 fn from(ip: Ipv6Addr) -> u128 {
1759 let ip = ip.octets();
1760 u128::from_be_bytes(ip)
1763 #[stable(feature = "i128", since = "1.26.0")]
1764 impl From<u128> for Ipv6Addr {
1765 /// Convert a host byte order `u128` into an `Ipv6Addr`.
1770 /// use std::net::Ipv6Addr;
1772 /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
1775 /// 0x1020, 0x3040, 0x5060, 0x7080,
1776 /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1780 fn from(ip: u128) -> Ipv6Addr {
1781 Ipv6Addr::from(ip.to_be_bytes())
1785 #[stable(feature = "ipv6_from_octets", since = "1.9.0")]
1786 impl From<[u8; 16]> for Ipv6Addr {
1787 /// Creates an `Ipv6Addr` from a sixteen element byte array.
1792 /// use std::net::Ipv6Addr;
1794 /// let addr = Ipv6Addr::from([
1795 /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1796 /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1808 fn from(octets: [u8; 16]) -> Ipv6Addr {
1809 let inner = c::in6_addr { s6_addr: octets };
1810 Ipv6Addr::from_inner(inner)
1814 #[stable(feature = "ipv6_from_segments", since = "1.16.0")]
1815 impl From<[u16; 8]> for Ipv6Addr {
1816 /// Creates an `Ipv6Addr` from an eight element 16-bit array.
1821 /// use std::net::Ipv6Addr;
1823 /// let addr = Ipv6Addr::from([
1824 /// 525u16, 524u16, 523u16, 522u16,
1825 /// 521u16, 520u16, 519u16, 518u16,
1837 fn from(segments: [u16; 8]) -> Ipv6Addr {
1838 let [a, b, c, d, e, f, g, h] = segments;
1839 Ipv6Addr::new(a, b, c, d, e, f, g, h)
1843 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1844 impl From<[u8; 16]> for IpAddr {
1845 /// Creates an `IpAddr::V6` from a sixteen element byte array.
1850 /// use std::net::{IpAddr, Ipv6Addr};
1852 /// let addr = IpAddr::from([
1853 /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1854 /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1857 /// IpAddr::V6(Ipv6Addr::new(
1866 fn from(octets: [u8; 16]) -> IpAddr {
1867 IpAddr::V6(Ipv6Addr::from(octets))
1871 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1872 impl From<[u16; 8]> for IpAddr {
1873 /// Creates an `IpAddr::V6` from an eight element 16-bit array.
1878 /// use std::net::{IpAddr, Ipv6Addr};
1880 /// let addr = IpAddr::from([
1881 /// 525u16, 524u16, 523u16, 522u16,
1882 /// 521u16, 520u16, 519u16, 518u16,
1885 /// IpAddr::V6(Ipv6Addr::new(
1894 fn from(segments: [u16; 8]) -> IpAddr {
1895 IpAddr::V6(Ipv6Addr::from(segments))
1899 // Tests for this module
1900 #[cfg(all(test, not(target_os = "emscripten")))]
1902 use crate::net::test::{sa4, sa6, tsa};
1904 use crate::str::FromStr;
1907 fn test_from_str_ipv4() {
1908 assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
1909 assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
1910 assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
1913 let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
1914 assert_eq!(None, none);
1916 let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
1917 assert_eq!(None, none);
1919 let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
1920 assert_eq!(None, none);
1921 // no number between dots
1922 let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
1923 assert_eq!(None, none);
1927 fn test_from_str_ipv6() {
1928 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
1929 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
1931 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
1932 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
1935 Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
1936 "2a02:6b8::11:11".parse()
1940 let none: Option<Ipv6Addr> = "::00000".parse().ok();
1941 assert_eq!(None, none);
1943 let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
1944 assert_eq!(None, none);
1946 let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
1947 assert_eq!(None, none);
1949 let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
1950 assert_eq!(None, none);
1951 // two double colons
1952 let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
1953 assert_eq!(None, none);
1954 // `::` indicating zero groups of zeros
1955 let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
1956 assert_eq!(None, none);
1960 fn test_from_str_ipv4_in_ipv6() {
1961 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
1963 Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
1964 "::FFFF:192.0.2.33".parse()
1967 Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
1968 "64:ff9b::192.0.2.33".parse()
1971 Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
1972 "2001:db8:122:c000:2:2100:192.0.2.33".parse()
1976 let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
1977 assert_eq!(None, none);
1978 // not enough groups
1979 let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok();
1980 assert_eq!(None, none);
1982 let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
1983 assert_eq!(None, none);
1987 fn test_from_str_socket_addr() {
1988 assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
1990 Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)),
1991 "77.88.21.11:80".parse()
1994 Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
1995 "[2a02:6b8:0:1::1]:53".parse()
1998 Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
1999 "[2a02:6b8:0:1::1]:53".parse()
2002 Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
2003 "[::127.0.0.1]:22".parse()
2006 Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
2007 "[::127.0.0.1]:22".parse()
2011 let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
2012 assert_eq!(None, none);
2014 let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
2015 assert_eq!(None, none);
2016 // wrong brackets around v4
2017 let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
2018 assert_eq!(None, none);
2019 // port out of range
2020 let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
2021 assert_eq!(None, none);
2025 fn ipv4_addr_to_string() {
2026 assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1");
2028 assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
2030 assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
2033 assert_eq!(&format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 ");
2034 assert_eq!(&format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1");
2038 fn ipv6_addr_to_string() {
2039 // ipv4-mapped address
2040 let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
2041 assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
2043 // ipv4-compatible address
2044 let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
2045 assert_eq!(a1.to_string(), "::192.0.2.128");
2047 // v6 address with no zero segments
2048 assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
2050 // longest possible IPv6 length
2052 Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888)
2054 "1111:2222:3333:4444:5555:6666:7777:8888"
2058 &format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)),
2062 &format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)),
2066 // reduce a single run of zeros
2069 Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
2072 // don't reduce just a single zero segment
2073 assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
2076 assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
2079 assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
2082 assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
2084 // two runs of zeros, second one is longer
2085 assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
2087 // two runs of zeros, equal length
2088 assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
2094 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
2095 Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
2098 Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
2099 Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
2104 fn ipv6_to_ipv4_mapped() {
2106 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
2107 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2109 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
2115 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
2116 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2119 Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
2120 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2122 assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
2126 fn ip_properties() {
2129 IpAddr::from_str($s).unwrap()
2133 macro_rules! check {
2138 ($s:expr, $mask:expr) => {{
2139 let unspec: u8 = 1 << 0;
2140 let loopback: u8 = 1 << 1;
2141 let global: u8 = 1 << 2;
2142 let multicast: u8 = 1 << 3;
2143 let doc: u8 = 1 << 4;
2145 if ($mask & unspec) == unspec {
2146 assert!(ip!($s).is_unspecified());
2148 assert!(!ip!($s).is_unspecified());
2151 if ($mask & loopback) == loopback {
2152 assert!(ip!($s).is_loopback());
2154 assert!(!ip!($s).is_loopback());
2157 if ($mask & global) == global {
2158 assert!(ip!($s).is_global());
2160 assert!(!ip!($s).is_global());
2163 if ($mask & multicast) == multicast {
2164 assert!(ip!($s).is_multicast());
2166 assert!(!ip!($s).is_multicast());
2169 if ($mask & doc) == doc {
2170 assert!(ip!($s).is_documentation());
2172 assert!(!ip!($s).is_documentation());
2177 let unspec: u8 = 1 << 0;
2178 let loopback: u8 = 1 << 1;
2179 let global: u8 = 1 << 2;
2180 let multicast: u8 = 1 << 3;
2181 let doc: u8 = 1 << 4;
2183 check!("0.0.0.0", unspec);
2187 check!("127.1.2.3", loopback);
2188 check!("172.31.254.253");
2189 check!("169.254.253.242");
2190 check!("192.0.2.183", doc);
2191 check!("192.1.2.183", global);
2192 check!("192.168.254.253");
2193 check!("198.51.100.0", doc);
2194 check!("203.0.113.0", doc);
2195 check!("203.2.113.0", global);
2196 check!("224.0.0.0", global | multicast);
2197 check!("239.255.255.255", global | multicast);
2198 check!("255.255.255.255");
2199 // make sure benchmarking addresses are not global
2200 check!("198.18.0.0");
2201 check!("198.18.54.2");
2202 check!("198.19.255.255");
2203 // make sure addresses reserved for protocol assignment are not global
2204 check!("192.0.0.0");
2205 check!("192.0.0.255");
2206 check!("192.0.0.100");
2207 // make sure reserved addresses are not global
2208 check!("240.0.0.0");
2209 check!("251.54.1.76");
2210 check!("254.255.255.255");
2211 // make sure shared addresses are not global
2212 check!("100.64.0.0");
2213 check!("100.127.255.255");
2214 check!("100.100.100.0");
2216 check!("::", unspec);
2217 check!("::1", loopback);
2218 check!("::0.0.0.2", global);
2219 check!("1::", global);
2221 check!("fdff:ffff::");
2222 check!("fe80:ffff::");
2223 check!("febf:ffff::");
2224 check!("fec0::", global);
2225 check!("ff01::", multicast);
2226 check!("ff02::", multicast);
2227 check!("ff03::", multicast);
2228 check!("ff04::", multicast);
2229 check!("ff05::", multicast);
2230 check!("ff08::", multicast);
2231 check!("ff0e::", global | multicast);
2232 check!("2001:db8:85a3::8a2e:370:7334", doc);
2233 check!("102:304:506:708:90a:b0c:d0e:f10", global);
2237 fn ipv4_properties() {
2240 Ipv4Addr::from_str($s).unwrap()
2244 macro_rules! check {
2249 ($s:expr, $mask:expr) => {{
2250 let unspec: u16 = 1 << 0;
2251 let loopback: u16 = 1 << 1;
2252 let private: u16 = 1 << 2;
2253 let link_local: u16 = 1 << 3;
2254 let global: u16 = 1 << 4;
2255 let multicast: u16 = 1 << 5;
2256 let broadcast: u16 = 1 << 6;
2257 let documentation: u16 = 1 << 7;
2258 let benchmarking: u16 = 1 << 8;
2259 let ietf_protocol_assignment: u16 = 1 << 9;
2260 let reserved: u16 = 1 << 10;
2261 let shared: u16 = 1 << 11;
2263 if ($mask & unspec) == unspec {
2264 assert!(ip!($s).is_unspecified());
2266 assert!(!ip!($s).is_unspecified());
2269 if ($mask & loopback) == loopback {
2270 assert!(ip!($s).is_loopback());
2272 assert!(!ip!($s).is_loopback());
2275 if ($mask & private) == private {
2276 assert!(ip!($s).is_private());
2278 assert!(!ip!($s).is_private());
2281 if ($mask & link_local) == link_local {
2282 assert!(ip!($s).is_link_local());
2284 assert!(!ip!($s).is_link_local());
2287 if ($mask & global) == global {
2288 assert!(ip!($s).is_global());
2290 assert!(!ip!($s).is_global());
2293 if ($mask & multicast) == multicast {
2294 assert!(ip!($s).is_multicast());
2296 assert!(!ip!($s).is_multicast());
2299 if ($mask & broadcast) == broadcast {
2300 assert!(ip!($s).is_broadcast());
2302 assert!(!ip!($s).is_broadcast());
2305 if ($mask & documentation) == documentation {
2306 assert!(ip!($s).is_documentation());
2308 assert!(!ip!($s).is_documentation());
2311 if ($mask & benchmarking) == benchmarking {
2312 assert!(ip!($s).is_benchmarking());
2314 assert!(!ip!($s).is_benchmarking());
2317 if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment {
2318 assert!(ip!($s).is_ietf_protocol_assignment());
2320 assert!(!ip!($s).is_ietf_protocol_assignment());
2323 if ($mask & reserved) == reserved {
2324 assert!(ip!($s).is_reserved());
2326 assert!(!ip!($s).is_reserved());
2329 if ($mask & shared) == shared {
2330 assert!(ip!($s).is_shared());
2332 assert!(!ip!($s).is_shared());
2337 let unspec: u16 = 1 << 0;
2338 let loopback: u16 = 1 << 1;
2339 let private: u16 = 1 << 2;
2340 let link_local: u16 = 1 << 3;
2341 let global: u16 = 1 << 4;
2342 let multicast: u16 = 1 << 5;
2343 let broadcast: u16 = 1 << 6;
2344 let documentation: u16 = 1 << 7;
2345 let benchmarking: u16 = 1 << 8;
2346 let ietf_protocol_assignment: u16 = 1 << 9;
2347 let reserved: u16 = 1 << 10;
2348 let shared: u16 = 1 << 11;
2350 check!("0.0.0.0", unspec);
2353 check!("10.9.8.7", private);
2354 check!("127.1.2.3", loopback);
2355 check!("172.31.254.253", private);
2356 check!("169.254.253.242", link_local);
2357 check!("192.0.2.183", documentation);
2358 check!("192.1.2.183", global);
2359 check!("192.168.254.253", private);
2360 check!("198.51.100.0", documentation);
2361 check!("203.0.113.0", documentation);
2362 check!("203.2.113.0", global);
2363 check!("224.0.0.0", global | multicast);
2364 check!("239.255.255.255", global | multicast);
2365 check!("255.255.255.255", broadcast);
2366 check!("198.18.0.0", benchmarking);
2367 check!("198.18.54.2", benchmarking);
2368 check!("198.19.255.255", benchmarking);
2369 check!("192.0.0.0", ietf_protocol_assignment);
2370 check!("192.0.0.255", ietf_protocol_assignment);
2371 check!("192.0.0.100", ietf_protocol_assignment);
2372 check!("240.0.0.0", reserved);
2373 check!("251.54.1.76", reserved);
2374 check!("254.255.255.255", reserved);
2375 check!("100.64.0.0", shared);
2376 check!("100.127.255.255", shared);
2377 check!("100.100.100.0", shared);
2381 fn ipv6_properties() {
2384 Ipv6Addr::from_str($s).unwrap()
2388 macro_rules! check {
2389 ($s:expr, &[$($octet:expr),*], $mask:expr) => {
2390 assert_eq!($s, ip!($s).to_string());
2391 let octets = &[$($octet),*];
2392 assert_eq!(&ip!($s).octets(), octets);
2393 assert_eq!(Ipv6Addr::from(*octets), ip!($s));
2395 let unspecified: u16 = 1 << 0;
2396 let loopback: u16 = 1 << 1;
2397 let unique_local: u16 = 1 << 2;
2398 let global: u16 = 1 << 3;
2399 let unicast_link_local: u16 = 1 << 4;
2400 let unicast_link_local_strict: u16 = 1 << 5;
2401 let unicast_site_local: u16 = 1 << 6;
2402 let unicast_global: u16 = 1 << 7;
2403 let documentation: u16 = 1 << 8;
2404 let multicast_interface_local: u16 = 1 << 9;
2405 let multicast_link_local: u16 = 1 << 10;
2406 let multicast_realm_local: u16 = 1 << 11;
2407 let multicast_admin_local: u16 = 1 << 12;
2408 let multicast_site_local: u16 = 1 << 13;
2409 let multicast_organization_local: u16 = 1 << 14;
2410 let multicast_global: u16 = 1 << 15;
2411 let multicast: u16 = multicast_interface_local
2412 | multicast_admin_local
2414 | multicast_link_local
2415 | multicast_realm_local
2416 | multicast_site_local
2417 | multicast_organization_local;
2419 if ($mask & unspecified) == unspecified {
2420 assert!(ip!($s).is_unspecified());
2422 assert!(!ip!($s).is_unspecified());
2424 if ($mask & loopback) == loopback {
2425 assert!(ip!($s).is_loopback());
2427 assert!(!ip!($s).is_loopback());
2429 if ($mask & unique_local) == unique_local {
2430 assert!(ip!($s).is_unique_local());
2432 assert!(!ip!($s).is_unique_local());
2434 if ($mask & global) == global {
2435 assert!(ip!($s).is_global());
2437 assert!(!ip!($s).is_global());
2439 if ($mask & unicast_link_local) == unicast_link_local {
2440 assert!(ip!($s).is_unicast_link_local());
2442 assert!(!ip!($s).is_unicast_link_local());
2444 if ($mask & unicast_link_local_strict) == unicast_link_local_strict {
2445 assert!(ip!($s).is_unicast_link_local_strict());
2447 assert!(!ip!($s).is_unicast_link_local_strict());
2449 if ($mask & unicast_site_local) == unicast_site_local {
2450 assert!(ip!($s).is_unicast_site_local());
2452 assert!(!ip!($s).is_unicast_site_local());
2454 if ($mask & unicast_global) == unicast_global {
2455 assert!(ip!($s).is_unicast_global());
2457 assert!(!ip!($s).is_unicast_global());
2459 if ($mask & documentation) == documentation {
2460 assert!(ip!($s).is_documentation());
2462 assert!(!ip!($s).is_documentation());
2464 if ($mask & multicast) != 0 {
2465 assert!(ip!($s).multicast_scope().is_some());
2466 assert!(ip!($s).is_multicast());
2468 assert!(ip!($s).multicast_scope().is_none());
2469 assert!(!ip!($s).is_multicast());
2471 if ($mask & multicast_interface_local) == multicast_interface_local {
2472 assert_eq!(ip!($s).multicast_scope().unwrap(),
2473 Ipv6MulticastScope::InterfaceLocal);
2475 if ($mask & multicast_link_local) == multicast_link_local {
2476 assert_eq!(ip!($s).multicast_scope().unwrap(),
2477 Ipv6MulticastScope::LinkLocal);
2479 if ($mask & multicast_realm_local) == multicast_realm_local {
2480 assert_eq!(ip!($s).multicast_scope().unwrap(),
2481 Ipv6MulticastScope::RealmLocal);
2483 if ($mask & multicast_admin_local) == multicast_admin_local {
2484 assert_eq!(ip!($s).multicast_scope().unwrap(),
2485 Ipv6MulticastScope::AdminLocal);
2487 if ($mask & multicast_site_local) == multicast_site_local {
2488 assert_eq!(ip!($s).multicast_scope().unwrap(),
2489 Ipv6MulticastScope::SiteLocal);
2491 if ($mask & multicast_organization_local) == multicast_organization_local {
2492 assert_eq!(ip!($s).multicast_scope().unwrap(),
2493 Ipv6MulticastScope::OrganizationLocal);
2495 if ($mask & multicast_global) == multicast_global {
2496 assert_eq!(ip!($s).multicast_scope().unwrap(),
2497 Ipv6MulticastScope::Global);
2502 let unspecified: u16 = 1 << 0;
2503 let loopback: u16 = 1 << 1;
2504 let unique_local: u16 = 1 << 2;
2505 let global: u16 = 1 << 3;
2506 let unicast_link_local: u16 = 1 << 4;
2507 let unicast_link_local_strict: u16 = 1 << 5;
2508 let unicast_site_local: u16 = 1 << 6;
2509 let unicast_global: u16 = 1 << 7;
2510 let documentation: u16 = 1 << 8;
2511 let multicast_interface_local: u16 = 1 << 9;
2512 let multicast_link_local: u16 = 1 << 10;
2513 let multicast_realm_local: u16 = 1 << 11;
2514 let multicast_admin_local: u16 = 1 << 12;
2515 let multicast_site_local: u16 = 1 << 13;
2516 let multicast_organization_local: u16 = 1 << 14;
2517 let multicast_global: u16 = 1 << 15;
2519 check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);
2521 check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
2525 &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
2526 global | unicast_global
2529 check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
2531 check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
2535 &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2541 &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2547 &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2548 unicast_link_local | unicast_link_local_strict
2553 &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2559 &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2564 "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
2566 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2573 "fe80::ffff:ffff:ffff:ffff",
2575 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2578 unicast_link_local | unicast_link_local_strict
2583 &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
2589 &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2590 unicast_site_local | unicast_global | global
2595 &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2596 multicast_interface_local
2601 &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2602 multicast_link_local
2607 &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2608 multicast_realm_local
2613 &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2614 multicast_admin_local
2619 &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2620 multicast_site_local
2625 &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2626 multicast_organization_local
2631 &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2632 multicast_global | global
2636 "2001:db8:85a3::8a2e:370:7334",
2637 &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
2642 "102:304:506:708:90a:b0c:d0e:f10",
2643 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
2644 global | unicast_global
2649 fn to_socket_addr_socketaddr() {
2650 let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
2651 assert_eq!(Ok(vec![a]), tsa(a));
2655 fn test_ipv4_to_int() {
2656 let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
2657 assert_eq!(u32::from(a), 0x11223344);
2661 fn test_int_to_ipv4() {
2662 let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
2663 assert_eq!(Ipv4Addr::from(0x11223344), a);
2667 fn test_ipv6_to_int() {
2668 let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
2669 assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
2673 fn test_int_to_ipv6() {
2674 let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
2675 assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
2679 fn ipv4_from_constructors() {
2680 assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
2681 assert!(Ipv4Addr::LOCALHOST.is_loopback());
2682 assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
2683 assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
2684 assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
2685 assert!(Ipv4Addr::BROADCAST.is_broadcast());
2689 fn ipv6_from_contructors() {
2690 assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
2691 assert!(Ipv6Addr::LOCALHOST.is_loopback());
2692 assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
2693 assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
2697 fn ipv4_from_octets() {
2698 assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
2702 fn ipv6_from_segments() {
2704 Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
2705 let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
2706 assert_eq!(new, from_u16s);
2710 fn ipv6_from_octets() {
2712 Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
2713 let from_u8s = Ipv6Addr::from([
2714 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
2717 assert_eq!(from_u16s, from_u8s);
2722 let v41 = Ipv4Addr::new(100, 64, 3, 3);
2723 let v42 = Ipv4Addr::new(192, 0, 2, 2);
2724 let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
2725 let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
2729 assert_eq!(v41, IpAddr::V4(v41));
2730 assert_eq!(v61, IpAddr::V6(v61));
2731 assert!(v41 != IpAddr::V4(v42));
2732 assert!(v61 != IpAddr::V6(v62));
2734 assert!(v41 < IpAddr::V4(v42));
2735 assert!(v61 < IpAddr::V6(v62));
2736 assert!(IpAddr::V4(v41) < v42);
2737 assert!(IpAddr::V6(v61) < v62);
2739 assert!(v41 < IpAddr::V6(v61));
2740 assert!(IpAddr::V4(v41) < v61);
2745 let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
2746 assert!(ip.is_ipv4());
2747 assert!(!ip.is_ipv6());
2752 let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
2753 assert!(!ip.is_ipv4());
2754 assert!(ip.is_ipv6());