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};
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) {
912 // `inner` is #[repr(packed)], so we need to copy `s_addr`.
913 { self.inner.s_addr }.hash(s)
917 #[stable(feature = "rust1", since = "1.0.0")]
918 impl PartialOrd for Ipv4Addr {
919 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
920 Some(self.cmp(other))
924 #[stable(feature = "ip_cmp", since = "1.16.0")]
925 impl PartialOrd<Ipv4Addr> for IpAddr {
926 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
928 IpAddr::V4(v4) => v4.partial_cmp(other),
929 IpAddr::V6(_) => Some(Ordering::Greater),
934 #[stable(feature = "ip_cmp", since = "1.16.0")]
935 impl PartialOrd<IpAddr> for Ipv4Addr {
936 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
938 IpAddr::V4(v4) => self.partial_cmp(v4),
939 IpAddr::V6(_) => Some(Ordering::Less),
944 #[stable(feature = "rust1", since = "1.0.0")]
945 impl Ord for Ipv4Addr {
946 fn cmp(&self, other: &Ipv4Addr) -> Ordering {
947 u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
951 impl AsInner<c::in_addr> for Ipv4Addr {
952 fn as_inner(&self) -> &c::in_addr {
957 #[stable(feature = "ip_u32", since = "1.1.0")]
958 impl From<Ipv4Addr> for u32 {
959 /// Converts an `Ipv4Addr` into a host byte order `u32`.
964 /// use std::net::Ipv4Addr;
966 /// let addr = Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe);
967 /// assert_eq!(0xcafebabe, u32::from(addr));
969 fn from(ip: Ipv4Addr) -> u32 {
970 let ip = ip.octets();
971 u32::from_be_bytes(ip)
975 #[stable(feature = "ip_u32", since = "1.1.0")]
976 impl From<u32> for Ipv4Addr {
977 /// Converts a host byte order `u32` into an `Ipv4Addr`.
982 /// use std::net::Ipv4Addr;
984 /// let addr = Ipv4Addr::from(0xcafebabe);
985 /// assert_eq!(Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe), addr);
987 fn from(ip: u32) -> Ipv4Addr {
988 Ipv4Addr::from(ip.to_be_bytes())
992 #[stable(feature = "from_slice_v4", since = "1.9.0")]
993 impl From<[u8; 4]> for Ipv4Addr {
994 /// Creates an `Ipv4Addr` from a four element byte array.
999 /// use std::net::Ipv4Addr;
1001 /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
1002 /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
1004 fn from(octets: [u8; 4]) -> Ipv4Addr {
1005 Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
1009 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1010 impl From<[u8; 4]> for IpAddr {
1011 /// Creates an `IpAddr::V4` from a four element byte array.
1016 /// use std::net::{IpAddr, Ipv4Addr};
1018 /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
1019 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
1021 fn from(octets: [u8; 4]) -> IpAddr {
1022 IpAddr::V4(Ipv4Addr::from(octets))
1027 /// Creates a new IPv6 address from eight 16-bit segments.
1029 /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
1034 /// use std::net::Ipv6Addr;
1036 /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
1038 #[stable(feature = "rust1", since = "1.0.0")]
1039 #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
1040 #[allow_internal_unstable(const_fn_transmute)]
1041 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
1053 inner: c::in6_addr {
1054 // All elements in `addr16` are big endian.
1055 // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
1056 s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
1061 /// An IPv6 address representing localhost: `::1`.
1066 /// use std::net::Ipv6Addr;
1068 /// let addr = Ipv6Addr::LOCALHOST;
1069 /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
1071 #[stable(feature = "ip_constructors", since = "1.30.0")]
1072 pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
1074 /// An IPv6 address representing the unspecified address: `::`
1079 /// use std::net::Ipv6Addr;
1081 /// let addr = Ipv6Addr::UNSPECIFIED;
1082 /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
1084 #[stable(feature = "ip_constructors", since = "1.30.0")]
1085 pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
1087 /// Returns the eight 16-bit segments that make up this address.
1092 /// use std::net::Ipv6Addr;
1094 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
1095 /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
1097 #[stable(feature = "rust1", since = "1.0.0")]
1098 pub fn segments(&self) -> [u16; 8] {
1099 // All elements in `s6_addr` must be big endian.
1100 // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
1101 let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
1102 // We want native endian u16
1115 /// Returns [`true`] for the special 'unspecified' address (::).
1117 /// This property is defined in [IETF RFC 4291].
1119 /// [`true`]: ../../std/primitive.bool.html
1120 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1125 /// use std::net::Ipv6Addr;
1127 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
1128 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
1130 #[stable(since = "1.7.0", feature = "ip_17")]
1131 pub fn is_unspecified(&self) -> bool {
1132 self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
1135 /// Returns [`true`] if this is a loopback address (::1).
1137 /// This property is defined in [IETF RFC 4291].
1139 /// [`true`]: ../../std/primitive.bool.html
1140 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1145 /// use std::net::Ipv6Addr;
1147 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
1148 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
1150 #[stable(since = "1.7.0", feature = "ip_17")]
1151 pub fn is_loopback(&self) -> bool {
1152 self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
1155 /// Returns [`true`] if the address appears to be globally routable.
1157 /// The following return [`false`]:
1159 /// - the loopback address
1160 /// - link-local and unique local unicast addresses
1161 /// - interface-, link-, realm-, admin- and site-local multicast addresses
1163 /// [`true`]: ../../std/primitive.bool.html
1164 /// [`false`]: ../../std/primitive.bool.html
1171 /// use std::net::Ipv6Addr;
1173 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
1174 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
1175 /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
1177 pub fn is_global(&self) -> bool {
1178 match self.multicast_scope() {
1179 Some(Ipv6MulticastScope::Global) => true,
1180 None => self.is_unicast_global(),
1185 /// Returns [`true`] if this is a unique local address (`fc00::/7`).
1187 /// This property is defined in [IETF RFC 4193].
1189 /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
1191 /// [`true`]: ../../std/primitive.bool.html
1198 /// use std::net::Ipv6Addr;
1200 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
1201 /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
1203 pub fn is_unique_local(&self) -> bool {
1204 (self.segments()[0] & 0xfe00) == 0xfc00
1207 /// Returns [`true`] if the address is a unicast link-local address (`fe80::/64`).
1209 /// A common mis-conception is to think that "unicast link-local addresses start with
1210 /// `fe80::`", but the [IETF RFC 4291] actually defines a stricter format for these addresses:
1214 /// | bits | 54 bits | 64 bits |
1215 /// +----------+-------------------------+----------------------------+
1216 /// |1111111010| 0 | interface ID |
1217 /// +----------+-------------------------+----------------------------+
1220 /// This method validates the format defined in the RFC and won't recognize the following
1221 /// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example.
1222 /// If you need a less strict validation use [`Ipv6Addr::is_unicast_link_local()`] instead.
1224 /// [`true`]: ../../std/primitive.bool.html
1231 /// use std::net::Ipv6Addr;
1233 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
1234 /// assert!(ip.is_unicast_link_local_strict());
1236 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
1237 /// assert!(ip.is_unicast_link_local_strict());
1239 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
1240 /// assert!(!ip.is_unicast_link_local_strict());
1241 /// assert!(ip.is_unicast_link_local());
1243 /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
1244 /// assert!(!ip.is_unicast_link_local_strict());
1245 /// assert!(ip.is_unicast_link_local());
1250 /// - [IETF RFC 4291 section 2.5.6]
1251 /// - [RFC 4291 errata 4406] (which has been rejected but provides useful
1253 /// - [`Ipv6Addr::is_unicast_link_local()`]
1255 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1256 /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
1257 /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
1258 pub fn is_unicast_link_local_strict(&self) -> bool {
1259 (self.segments()[0] & 0xffff) == 0xfe80
1260 && (self.segments()[1] & 0xffff) == 0
1261 && (self.segments()[2] & 0xffff) == 0
1262 && (self.segments()[3] & 0xffff) == 0
1265 /// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`).
1267 /// This method returns [`true`] for addresses in the range reserved by [RFC 4291 section 2.4],
1268 /// i.e. addresses with the following format:
1272 /// | bits | 54 bits | 64 bits |
1273 /// +----------+-------------------------+----------------------------+
1274 /// |1111111010| arbitratry value | interface ID |
1275 /// +----------+-------------------------+----------------------------+
1278 /// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be
1279 /// unicast link-local addresses, whereas [`Ipv6Addr::is_unicast_link_local_strict()`] does not.
1280 /// If you need a strict validation fully compliant with the RFC, use
1281 /// [`Ipv6Addr::is_unicast_link_local_strict()`] instead.
1283 /// [`true`]: ../../std/primitive.bool.html
1290 /// use std::net::Ipv6Addr;
1292 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
1293 /// assert!(ip.is_unicast_link_local());
1295 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
1296 /// assert!(ip.is_unicast_link_local());
1298 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
1299 /// assert!(ip.is_unicast_link_local());
1300 /// assert!(!ip.is_unicast_link_local_strict());
1302 /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
1303 /// assert!(ip.is_unicast_link_local());
1304 /// assert!(!ip.is_unicast_link_local_strict());
1309 /// - [IETF RFC 4291 section 2.4]
1310 /// - [RFC 4291 errata 4406] (which has been rejected but provides useful
1313 /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
1314 /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
1315 pub fn is_unicast_link_local(&self) -> bool {
1316 (self.segments()[0] & 0xffc0) == 0xfe80
1319 /// Returns [`true`] if this is a deprecated unicast site-local address (fec0::/10). The
1320 /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as:
1324 /// | bits | 54 bits | 64 bits |
1325 /// +----------+-------------------------+----------------------------+
1326 /// |1111111011| subnet ID | interface ID |
1327 /// +----------+-------------------------+----------------------------+
1330 /// [`true`]: ../../std/primitive.bool.html
1331 /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
1338 /// use std::net::Ipv6Addr;
1341 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(),
1344 /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
1349 /// As per [RFC 3879], the whole `FEC0::/10` prefix is
1350 /// deprecated. New software must not support site-local
1353 /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
1354 pub fn is_unicast_site_local(&self) -> bool {
1355 (self.segments()[0] & 0xffc0) == 0xfec0
1358 /// Returns [`true`] if this is an address reserved for documentation
1359 /// (2001:db8::/32).
1361 /// This property is defined in [IETF RFC 3849].
1363 /// [`true`]: ../../std/primitive.bool.html
1364 /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
1371 /// use std::net::Ipv6Addr;
1373 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
1374 /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
1376 pub fn is_documentation(&self) -> bool {
1377 (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
1380 /// Returns [`true`] if the address is a globally routable unicast address.
1382 /// The following return false:
1384 /// - the loopback address
1385 /// - the link-local addresses
1386 /// - unique local addresses
1387 /// - the unspecified address
1388 /// - the address range reserved for documentation
1390 /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
1393 /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
1394 /// be supported in new implementations (i.e., new implementations must treat this prefix as
1395 /// Global Unicast).
1398 /// [`true`]: ../../std/primitive.bool.html
1399 /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
1406 /// use std::net::Ipv6Addr;
1408 /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
1409 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
1411 pub fn is_unicast_global(&self) -> bool {
1412 !self.is_multicast()
1413 && !self.is_loopback()
1414 && !self.is_unicast_link_local()
1415 && !self.is_unique_local()
1416 && !self.is_unspecified()
1417 && !self.is_documentation()
1420 /// Returns the address's multicast scope if the address is multicast.
1427 /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
1430 /// Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
1431 /// Some(Ipv6MulticastScope::Global)
1433 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
1435 pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
1436 if self.is_multicast() {
1437 match self.segments()[0] & 0x000f {
1438 1 => Some(Ipv6MulticastScope::InterfaceLocal),
1439 2 => Some(Ipv6MulticastScope::LinkLocal),
1440 3 => Some(Ipv6MulticastScope::RealmLocal),
1441 4 => Some(Ipv6MulticastScope::AdminLocal),
1442 5 => Some(Ipv6MulticastScope::SiteLocal),
1443 8 => Some(Ipv6MulticastScope::OrganizationLocal),
1444 14 => Some(Ipv6MulticastScope::Global),
1452 /// Returns [`true`] if this is a multicast address (ff00::/8).
1454 /// This property is defined by [IETF RFC 4291].
1456 /// [`true`]: ../../std/primitive.bool.html
1457 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1462 /// use std::net::Ipv6Addr;
1464 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
1465 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
1467 #[stable(since = "1.7.0", feature = "ip_17")]
1468 pub fn is_multicast(&self) -> bool {
1469 (self.segments()[0] & 0xff00) == 0xff00
1472 /// Converts this address to an [`IPv4` address] if it's an "IPv4-mapped IPv6 address"
1473 /// defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
1475 /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
1476 /// All addresses *not* starting with `::ffff` will return `None`.
1478 /// [`IPv4` address]: Ipv4Addr
1479 /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1486 /// use std::net::{Ipv4Addr, Ipv6Addr};
1488 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
1489 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
1490 /// Some(Ipv4Addr::new(192, 10, 2, 255)));
1491 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
1493 pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
1494 match self.octets() {
1495 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
1496 Some(Ipv4Addr::new(a, b, c, d))
1502 /// Converts this address to an [`IPv4` address]. Returns [`None`] if this address is
1503 /// neither IPv4-compatible or IPv4-mapped.
1505 /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
1507 /// [`IPv4` address]: Ipv4Addr
1512 /// use std::net::{Ipv4Addr, Ipv6Addr};
1514 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
1515 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
1516 /// Some(Ipv4Addr::new(192, 10, 2, 255)));
1517 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
1518 /// Some(Ipv4Addr::new(0, 0, 0, 1)));
1520 #[stable(feature = "rust1", since = "1.0.0")]
1521 pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
1522 if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
1523 let [a, b] = ab.to_be_bytes();
1524 let [c, d] = cd.to_be_bytes();
1525 Some(Ipv4Addr::new(a, b, c, d))
1531 /// Returns the sixteen eight-bit integers the IPv6 address consists of.
1534 /// use std::net::Ipv6Addr;
1536 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
1537 /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
1539 #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
1540 #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
1541 pub const fn octets(&self) -> [u8; 16] {
1546 /// Write an Ipv6Addr, conforming to the canonical style described by
1547 /// [RFC 5952](https://tools.ietf.org/html/rfc5952).
1548 #[stable(feature = "rust1", since = "1.0.0")]
1549 impl fmt::Display for Ipv6Addr {
1550 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1551 // If there are no alignment requirements, write out the IP address to
1552 // f. Otherwise, write it to a local buffer, then use f.pad.
1553 if f.precision().is_none() && f.width().is_none() {
1554 let segments = self.segments();
1556 // Special case for :: and ::1; otherwise they get written with the
1558 if self.is_unspecified() {
1560 } else if self.is_loopback() {
1562 } else if let Some(ipv4) = self.to_ipv4() {
1564 // IPv4 Compatible address
1565 0 => write!(f, "::{}", ipv4),
1566 // IPv4 Mapped address
1567 0xffff => write!(f, "::ffff:{}", ipv4),
1568 _ => unreachable!(),
1571 #[derive(Copy, Clone, Default)]
1577 // Find the inner 0 span
1579 let mut longest = Span::default();
1580 let mut current = Span::default();
1582 for (i, &segment) in segments.iter().enumerate() {
1584 if current.len == 0 {
1590 if current.len > longest.len {
1594 current = Span::default();
1601 /// Write a colon-separated part of the address
1603 fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
1604 if let Some(first) = chunk.first() {
1605 fmt::LowerHex::fmt(first, f)?;
1606 for segment in &chunk[1..] {
1608 fmt::LowerHex::fmt(segment, f)?;
1615 fmt_subslice(f, &segments[..zeroes.start])?;
1617 fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
1619 fmt_subslice(f, &segments)
1623 // Slow path: write the address to a local buffer, the use f.pad.
1624 // Defined recursively by using the fast path to write to the
1627 // This is the largest possible size of an IPv6 address
1628 const IPV6_BUF_LEN: usize = (4 * 8) + 7;
1629 let mut buf = [0u8; IPV6_BUF_LEN];
1630 let mut buf_slice = &mut buf[..];
1632 // Note: This call to write should never fail, so unwrap is okay.
1633 write!(buf_slice, "{}", self).unwrap();
1634 let len = IPV6_BUF_LEN - buf_slice.len();
1636 // This is safe because we know exactly what can be in this buffer
1637 let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
1643 #[stable(feature = "rust1", since = "1.0.0")]
1644 impl fmt::Debug for Ipv6Addr {
1645 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1646 fmt::Display::fmt(self, fmt)
1650 #[stable(feature = "rust1", since = "1.0.0")]
1651 impl Clone for Ipv6Addr {
1652 fn clone(&self) -> Ipv6Addr {
1657 #[stable(feature = "rust1", since = "1.0.0")]
1658 impl PartialEq for Ipv6Addr {
1659 fn eq(&self, other: &Ipv6Addr) -> bool {
1660 self.inner.s6_addr == other.inner.s6_addr
1664 #[stable(feature = "ip_cmp", since = "1.16.0")]
1665 impl PartialEq<IpAddr> for Ipv6Addr {
1666 fn eq(&self, other: &IpAddr) -> bool {
1668 IpAddr::V4(_) => false,
1669 IpAddr::V6(v6) => self == v6,
1674 #[stable(feature = "ip_cmp", since = "1.16.0")]
1675 impl PartialEq<Ipv6Addr> for IpAddr {
1676 fn eq(&self, other: &Ipv6Addr) -> bool {
1678 IpAddr::V4(_) => false,
1679 IpAddr::V6(v6) => v6 == other,
1684 #[stable(feature = "rust1", since = "1.0.0")]
1685 impl Eq for Ipv6Addr {}
1687 #[stable(feature = "rust1", since = "1.0.0")]
1688 impl hash::Hash for Ipv6Addr {
1689 fn hash<H: hash::Hasher>(&self, s: &mut H) {
1690 self.inner.s6_addr.hash(s)
1694 #[stable(feature = "rust1", since = "1.0.0")]
1695 impl PartialOrd for Ipv6Addr {
1696 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1697 Some(self.cmp(other))
1701 #[stable(feature = "ip_cmp", since = "1.16.0")]
1702 impl PartialOrd<Ipv6Addr> for IpAddr {
1703 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1705 IpAddr::V4(_) => Some(Ordering::Less),
1706 IpAddr::V6(v6) => v6.partial_cmp(other),
1711 #[stable(feature = "ip_cmp", since = "1.16.0")]
1712 impl PartialOrd<IpAddr> for Ipv6Addr {
1713 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
1715 IpAddr::V4(_) => Some(Ordering::Greater),
1716 IpAddr::V6(v6) => self.partial_cmp(v6),
1721 #[stable(feature = "rust1", since = "1.0.0")]
1722 impl Ord for Ipv6Addr {
1723 fn cmp(&self, other: &Ipv6Addr) -> Ordering {
1724 self.segments().cmp(&other.segments())
1728 impl AsInner<c::in6_addr> for Ipv6Addr {
1729 fn as_inner(&self) -> &c::in6_addr {
1733 impl FromInner<c::in6_addr> for Ipv6Addr {
1734 fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
1735 Ipv6Addr { inner: addr }
1739 #[stable(feature = "i128", since = "1.26.0")]
1740 impl From<Ipv6Addr> for u128 {
1741 /// Convert an `Ipv6Addr` into a host byte order `u128`.
1746 /// use std::net::Ipv6Addr;
1748 /// let addr = Ipv6Addr::new(
1749 /// 0x1020, 0x3040, 0x5060, 0x7080,
1750 /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1752 /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
1754 fn from(ip: Ipv6Addr) -> u128 {
1755 let ip = ip.octets();
1756 u128::from_be_bytes(ip)
1759 #[stable(feature = "i128", since = "1.26.0")]
1760 impl From<u128> for Ipv6Addr {
1761 /// Convert a host byte order `u128` into an `Ipv6Addr`.
1766 /// use std::net::Ipv6Addr;
1768 /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
1771 /// 0x1020, 0x3040, 0x5060, 0x7080,
1772 /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1776 fn from(ip: u128) -> Ipv6Addr {
1777 Ipv6Addr::from(ip.to_be_bytes())
1781 #[stable(feature = "ipv6_from_octets", since = "1.9.0")]
1782 impl From<[u8; 16]> for Ipv6Addr {
1783 /// Creates an `Ipv6Addr` from a sixteen element byte array.
1788 /// use std::net::Ipv6Addr;
1790 /// let addr = Ipv6Addr::from([
1791 /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1792 /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1804 fn from(octets: [u8; 16]) -> Ipv6Addr {
1805 let inner = c::in6_addr { s6_addr: octets };
1806 Ipv6Addr::from_inner(inner)
1810 #[stable(feature = "ipv6_from_segments", since = "1.16.0")]
1811 impl From<[u16; 8]> for Ipv6Addr {
1812 /// Creates an `Ipv6Addr` from an eight element 16-bit array.
1817 /// use std::net::Ipv6Addr;
1819 /// let addr = Ipv6Addr::from([
1820 /// 525u16, 524u16, 523u16, 522u16,
1821 /// 521u16, 520u16, 519u16, 518u16,
1833 fn from(segments: [u16; 8]) -> Ipv6Addr {
1834 let [a, b, c, d, e, f, g, h] = segments;
1835 Ipv6Addr::new(a, b, c, d, e, f, g, h)
1839 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1840 impl From<[u8; 16]> for IpAddr {
1841 /// Creates an `IpAddr::V6` from a sixteen element byte array.
1846 /// use std::net::{IpAddr, Ipv6Addr};
1848 /// let addr = IpAddr::from([
1849 /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1850 /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1853 /// IpAddr::V6(Ipv6Addr::new(
1862 fn from(octets: [u8; 16]) -> IpAddr {
1863 IpAddr::V6(Ipv6Addr::from(octets))
1867 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1868 impl From<[u16; 8]> for IpAddr {
1869 /// Creates an `IpAddr::V6` from an eight element 16-bit array.
1874 /// use std::net::{IpAddr, Ipv6Addr};
1876 /// let addr = IpAddr::from([
1877 /// 525u16, 524u16, 523u16, 522u16,
1878 /// 521u16, 520u16, 519u16, 518u16,
1881 /// IpAddr::V6(Ipv6Addr::new(
1890 fn from(segments: [u16; 8]) -> IpAddr {
1891 IpAddr::V6(Ipv6Addr::from(segments))
1895 // Tests for this module
1896 #[cfg(all(test, not(target_os = "emscripten")))]
1898 use crate::net::test::{sa4, sa6, tsa};
1900 use crate::str::FromStr;
1903 fn test_from_str_ipv4() {
1904 assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
1905 assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
1906 assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
1909 let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
1910 assert_eq!(None, none);
1912 let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
1913 assert_eq!(None, none);
1915 let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
1916 assert_eq!(None, none);
1917 // no number between dots
1918 let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
1919 assert_eq!(None, none);
1923 fn test_from_str_ipv6() {
1924 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
1925 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
1927 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
1928 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
1931 Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
1932 "2a02:6b8::11:11".parse()
1936 let none: Option<Ipv6Addr> = "::00000".parse().ok();
1937 assert_eq!(None, none);
1939 let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
1940 assert_eq!(None, none);
1942 let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
1943 assert_eq!(None, none);
1945 let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
1946 assert_eq!(None, none);
1947 // two double colons
1948 let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
1949 assert_eq!(None, none);
1950 // `::` indicating zero groups of zeros
1951 let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
1952 assert_eq!(None, none);
1956 fn test_from_str_ipv4_in_ipv6() {
1957 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
1959 Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
1960 "::FFFF:192.0.2.33".parse()
1963 Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
1964 "64:ff9b::192.0.2.33".parse()
1967 Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
1968 "2001:db8:122:c000:2:2100:192.0.2.33".parse()
1972 let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
1973 assert_eq!(None, none);
1974 // not enough groups
1975 let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok();
1976 assert_eq!(None, none);
1978 let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
1979 assert_eq!(None, none);
1983 fn test_from_str_socket_addr() {
1984 assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
1986 Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)),
1987 "77.88.21.11:80".parse()
1990 Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
1991 "[2a02:6b8:0:1::1]:53".parse()
1994 Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
1995 "[2a02:6b8:0:1::1]:53".parse()
1998 Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
1999 "[::127.0.0.1]:22".parse()
2002 Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
2003 "[::127.0.0.1]:22".parse()
2007 let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
2008 assert_eq!(None, none);
2010 let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
2011 assert_eq!(None, none);
2012 // wrong brackets around v4
2013 let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
2014 assert_eq!(None, none);
2015 // port out of range
2016 let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
2017 assert_eq!(None, none);
2021 fn ipv4_addr_to_string() {
2023 assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
2025 assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
2028 assert_eq!(&format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 ");
2029 assert_eq!(&format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1");
2033 fn ipv6_addr_to_string() {
2034 // ipv4-mapped address
2035 let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
2036 assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
2038 // ipv4-compatible address
2039 let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
2040 assert_eq!(a1.to_string(), "::192.0.2.128");
2042 // v6 address with no zero segments
2043 assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
2045 // longest possible IPv6 length
2047 Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888)
2049 "1111:2222:3333:4444:5555:6666:7777:8888"
2053 &format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)),
2057 &format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)),
2061 // reduce a single run of zeros
2064 Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
2067 // don't reduce just a single zero segment
2068 assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
2071 assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
2074 assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
2077 assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
2079 // two runs of zeros, second one is longer
2080 assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
2082 // two runs of zeros, equal length
2083 assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
2089 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
2090 Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
2093 Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
2094 Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
2099 fn ipv6_to_ipv4_mapped() {
2101 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
2102 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2104 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
2110 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
2111 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2114 Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
2115 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2117 assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
2121 fn ip_properties() {
2124 IpAddr::from_str($s).unwrap()
2128 macro_rules! check {
2133 ($s:expr, $mask:expr) => {{
2134 let unspec: u8 = 1 << 0;
2135 let loopback: u8 = 1 << 1;
2136 let global: u8 = 1 << 2;
2137 let multicast: u8 = 1 << 3;
2138 let doc: u8 = 1 << 4;
2140 if ($mask & unspec) == unspec {
2141 assert!(ip!($s).is_unspecified());
2143 assert!(!ip!($s).is_unspecified());
2146 if ($mask & loopback) == loopback {
2147 assert!(ip!($s).is_loopback());
2149 assert!(!ip!($s).is_loopback());
2152 if ($mask & global) == global {
2153 assert!(ip!($s).is_global());
2155 assert!(!ip!($s).is_global());
2158 if ($mask & multicast) == multicast {
2159 assert!(ip!($s).is_multicast());
2161 assert!(!ip!($s).is_multicast());
2164 if ($mask & doc) == doc {
2165 assert!(ip!($s).is_documentation());
2167 assert!(!ip!($s).is_documentation());
2172 let unspec: u8 = 1 << 0;
2173 let loopback: u8 = 1 << 1;
2174 let global: u8 = 1 << 2;
2175 let multicast: u8 = 1 << 3;
2176 let doc: u8 = 1 << 4;
2178 check!("0.0.0.0", unspec);
2182 check!("127.1.2.3", loopback);
2183 check!("172.31.254.253");
2184 check!("169.254.253.242");
2185 check!("192.0.2.183", doc);
2186 check!("192.1.2.183", global);
2187 check!("192.168.254.253");
2188 check!("198.51.100.0", doc);
2189 check!("203.0.113.0", doc);
2190 check!("203.2.113.0", global);
2191 check!("224.0.0.0", global | multicast);
2192 check!("239.255.255.255", global | multicast);
2193 check!("255.255.255.255");
2194 // make sure benchmarking addresses are not global
2195 check!("198.18.0.0");
2196 check!("198.18.54.2");
2197 check!("198.19.255.255");
2198 // make sure addresses reserved for protocol assignment are not global
2199 check!("192.0.0.0");
2200 check!("192.0.0.255");
2201 check!("192.0.0.100");
2202 // make sure reserved addresses are not global
2203 check!("240.0.0.0");
2204 check!("251.54.1.76");
2205 check!("254.255.255.255");
2206 // make sure shared addresses are not global
2207 check!("100.64.0.0");
2208 check!("100.127.255.255");
2209 check!("100.100.100.0");
2211 check!("::", unspec);
2212 check!("::1", loopback);
2213 check!("::0.0.0.2", global);
2214 check!("1::", global);
2216 check!("fdff:ffff::");
2217 check!("fe80:ffff::");
2218 check!("febf:ffff::");
2219 check!("fec0::", global);
2220 check!("ff01::", multicast);
2221 check!("ff02::", multicast);
2222 check!("ff03::", multicast);
2223 check!("ff04::", multicast);
2224 check!("ff05::", multicast);
2225 check!("ff08::", multicast);
2226 check!("ff0e::", global | multicast);
2227 check!("2001:db8:85a3::8a2e:370:7334", doc);
2228 check!("102:304:506:708:90a:b0c:d0e:f10", global);
2232 fn ipv4_properties() {
2235 Ipv4Addr::from_str($s).unwrap()
2239 macro_rules! check {
2244 ($s:expr, $mask:expr) => {{
2245 let unspec: u16 = 1 << 0;
2246 let loopback: u16 = 1 << 1;
2247 let private: u16 = 1 << 2;
2248 let link_local: u16 = 1 << 3;
2249 let global: u16 = 1 << 4;
2250 let multicast: u16 = 1 << 5;
2251 let broadcast: u16 = 1 << 6;
2252 let documentation: u16 = 1 << 7;
2253 let benchmarking: u16 = 1 << 8;
2254 let ietf_protocol_assignment: u16 = 1 << 9;
2255 let reserved: u16 = 1 << 10;
2256 let shared: u16 = 1 << 11;
2258 if ($mask & unspec) == unspec {
2259 assert!(ip!($s).is_unspecified());
2261 assert!(!ip!($s).is_unspecified());
2264 if ($mask & loopback) == loopback {
2265 assert!(ip!($s).is_loopback());
2267 assert!(!ip!($s).is_loopback());
2270 if ($mask & private) == private {
2271 assert!(ip!($s).is_private());
2273 assert!(!ip!($s).is_private());
2276 if ($mask & link_local) == link_local {
2277 assert!(ip!($s).is_link_local());
2279 assert!(!ip!($s).is_link_local());
2282 if ($mask & global) == global {
2283 assert!(ip!($s).is_global());
2285 assert!(!ip!($s).is_global());
2288 if ($mask & multicast) == multicast {
2289 assert!(ip!($s).is_multicast());
2291 assert!(!ip!($s).is_multicast());
2294 if ($mask & broadcast) == broadcast {
2295 assert!(ip!($s).is_broadcast());
2297 assert!(!ip!($s).is_broadcast());
2300 if ($mask & documentation) == documentation {
2301 assert!(ip!($s).is_documentation());
2303 assert!(!ip!($s).is_documentation());
2306 if ($mask & benchmarking) == benchmarking {
2307 assert!(ip!($s).is_benchmarking());
2309 assert!(!ip!($s).is_benchmarking());
2312 if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment {
2313 assert!(ip!($s).is_ietf_protocol_assignment());
2315 assert!(!ip!($s).is_ietf_protocol_assignment());
2318 if ($mask & reserved) == reserved {
2319 assert!(ip!($s).is_reserved());
2321 assert!(!ip!($s).is_reserved());
2324 if ($mask & shared) == shared {
2325 assert!(ip!($s).is_shared());
2327 assert!(!ip!($s).is_shared());
2332 let unspec: u16 = 1 << 0;
2333 let loopback: u16 = 1 << 1;
2334 let private: u16 = 1 << 2;
2335 let link_local: u16 = 1 << 3;
2336 let global: u16 = 1 << 4;
2337 let multicast: u16 = 1 << 5;
2338 let broadcast: u16 = 1 << 6;
2339 let documentation: u16 = 1 << 7;
2340 let benchmarking: u16 = 1 << 8;
2341 let ietf_protocol_assignment: u16 = 1 << 9;
2342 let reserved: u16 = 1 << 10;
2343 let shared: u16 = 1 << 11;
2345 check!("0.0.0.0", unspec);
2348 check!("10.9.8.7", private);
2349 check!("127.1.2.3", loopback);
2350 check!("172.31.254.253", private);
2351 check!("169.254.253.242", link_local);
2352 check!("192.0.2.183", documentation);
2353 check!("192.1.2.183", global);
2354 check!("192.168.254.253", private);
2355 check!("198.51.100.0", documentation);
2356 check!("203.0.113.0", documentation);
2357 check!("203.2.113.0", global);
2358 check!("224.0.0.0", global | multicast);
2359 check!("239.255.255.255", global | multicast);
2360 check!("255.255.255.255", broadcast);
2361 check!("198.18.0.0", benchmarking);
2362 check!("198.18.54.2", benchmarking);
2363 check!("198.19.255.255", benchmarking);
2364 check!("192.0.0.0", ietf_protocol_assignment);
2365 check!("192.0.0.255", ietf_protocol_assignment);
2366 check!("192.0.0.100", ietf_protocol_assignment);
2367 check!("240.0.0.0", reserved);
2368 check!("251.54.1.76", reserved);
2369 check!("254.255.255.255", reserved);
2370 check!("100.64.0.0", shared);
2371 check!("100.127.255.255", shared);
2372 check!("100.100.100.0", shared);
2376 fn ipv6_properties() {
2379 Ipv6Addr::from_str($s).unwrap()
2383 macro_rules! check {
2384 ($s:expr, &[$($octet:expr),*], $mask:expr) => {
2385 assert_eq!($s, ip!($s).to_string());
2386 let octets = &[$($octet),*];
2387 assert_eq!(&ip!($s).octets(), octets);
2388 assert_eq!(Ipv6Addr::from(*octets), ip!($s));
2390 let unspecified: u16 = 1 << 0;
2391 let loopback: u16 = 1 << 1;
2392 let unique_local: u16 = 1 << 2;
2393 let global: u16 = 1 << 3;
2394 let unicast_link_local: u16 = 1 << 4;
2395 let unicast_link_local_strict: u16 = 1 << 5;
2396 let unicast_site_local: u16 = 1 << 6;
2397 let unicast_global: u16 = 1 << 7;
2398 let documentation: u16 = 1 << 8;
2399 let multicast_interface_local: u16 = 1 << 9;
2400 let multicast_link_local: u16 = 1 << 10;
2401 let multicast_realm_local: u16 = 1 << 11;
2402 let multicast_admin_local: u16 = 1 << 12;
2403 let multicast_site_local: u16 = 1 << 13;
2404 let multicast_organization_local: u16 = 1 << 14;
2405 let multicast_global: u16 = 1 << 15;
2406 let multicast: u16 = multicast_interface_local
2407 | multicast_admin_local
2409 | multicast_link_local
2410 | multicast_realm_local
2411 | multicast_site_local
2412 | multicast_organization_local;
2414 if ($mask & unspecified) == unspecified {
2415 assert!(ip!($s).is_unspecified());
2417 assert!(!ip!($s).is_unspecified());
2419 if ($mask & loopback) == loopback {
2420 assert!(ip!($s).is_loopback());
2422 assert!(!ip!($s).is_loopback());
2424 if ($mask & unique_local) == unique_local {
2425 assert!(ip!($s).is_unique_local());
2427 assert!(!ip!($s).is_unique_local());
2429 if ($mask & global) == global {
2430 assert!(ip!($s).is_global());
2432 assert!(!ip!($s).is_global());
2434 if ($mask & unicast_link_local) == unicast_link_local {
2435 assert!(ip!($s).is_unicast_link_local());
2437 assert!(!ip!($s).is_unicast_link_local());
2439 if ($mask & unicast_link_local_strict) == unicast_link_local_strict {
2440 assert!(ip!($s).is_unicast_link_local_strict());
2442 assert!(!ip!($s).is_unicast_link_local_strict());
2444 if ($mask & unicast_site_local) == unicast_site_local {
2445 assert!(ip!($s).is_unicast_site_local());
2447 assert!(!ip!($s).is_unicast_site_local());
2449 if ($mask & unicast_global) == unicast_global {
2450 assert!(ip!($s).is_unicast_global());
2452 assert!(!ip!($s).is_unicast_global());
2454 if ($mask & documentation) == documentation {
2455 assert!(ip!($s).is_documentation());
2457 assert!(!ip!($s).is_documentation());
2459 if ($mask & multicast) != 0 {
2460 assert!(ip!($s).multicast_scope().is_some());
2461 assert!(ip!($s).is_multicast());
2463 assert!(ip!($s).multicast_scope().is_none());
2464 assert!(!ip!($s).is_multicast());
2466 if ($mask & multicast_interface_local) == multicast_interface_local {
2467 assert_eq!(ip!($s).multicast_scope().unwrap(),
2468 Ipv6MulticastScope::InterfaceLocal);
2470 if ($mask & multicast_link_local) == multicast_link_local {
2471 assert_eq!(ip!($s).multicast_scope().unwrap(),
2472 Ipv6MulticastScope::LinkLocal);
2474 if ($mask & multicast_realm_local) == multicast_realm_local {
2475 assert_eq!(ip!($s).multicast_scope().unwrap(),
2476 Ipv6MulticastScope::RealmLocal);
2478 if ($mask & multicast_admin_local) == multicast_admin_local {
2479 assert_eq!(ip!($s).multicast_scope().unwrap(),
2480 Ipv6MulticastScope::AdminLocal);
2482 if ($mask & multicast_site_local) == multicast_site_local {
2483 assert_eq!(ip!($s).multicast_scope().unwrap(),
2484 Ipv6MulticastScope::SiteLocal);
2486 if ($mask & multicast_organization_local) == multicast_organization_local {
2487 assert_eq!(ip!($s).multicast_scope().unwrap(),
2488 Ipv6MulticastScope::OrganizationLocal);
2490 if ($mask & multicast_global) == multicast_global {
2491 assert_eq!(ip!($s).multicast_scope().unwrap(),
2492 Ipv6MulticastScope::Global);
2497 let unspecified: u16 = 1 << 0;
2498 let loopback: u16 = 1 << 1;
2499 let unique_local: u16 = 1 << 2;
2500 let global: u16 = 1 << 3;
2501 let unicast_link_local: u16 = 1 << 4;
2502 let unicast_link_local_strict: u16 = 1 << 5;
2503 let unicast_site_local: u16 = 1 << 6;
2504 let unicast_global: u16 = 1 << 7;
2505 let documentation: u16 = 1 << 8;
2506 let multicast_interface_local: u16 = 1 << 9;
2507 let multicast_link_local: u16 = 1 << 10;
2508 let multicast_realm_local: u16 = 1 << 11;
2509 let multicast_admin_local: u16 = 1 << 12;
2510 let multicast_site_local: u16 = 1 << 13;
2511 let multicast_organization_local: u16 = 1 << 14;
2512 let multicast_global: u16 = 1 << 15;
2514 check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);
2516 check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
2520 &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
2521 global | unicast_global
2524 check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
2526 check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
2530 &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2536 &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2542 &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2543 unicast_link_local | unicast_link_local_strict
2548 &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2554 &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2559 "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
2561 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2568 "fe80::ffff:ffff:ffff:ffff",
2570 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2573 unicast_link_local | unicast_link_local_strict
2578 &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
2584 &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2585 unicast_site_local | unicast_global | global
2590 &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2591 multicast_interface_local
2596 &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2597 multicast_link_local
2602 &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2603 multicast_realm_local
2608 &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2609 multicast_admin_local
2614 &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2615 multicast_site_local
2620 &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2621 multicast_organization_local
2626 &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2627 multicast_global | global
2631 "2001:db8:85a3::8a2e:370:7334",
2632 &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
2637 "102:304:506:708:90a:b0c:d0e:f10",
2638 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
2639 global | unicast_global
2644 fn to_socket_addr_socketaddr() {
2645 let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
2646 assert_eq!(Ok(vec![a]), tsa(a));
2650 fn test_ipv4_to_int() {
2651 let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
2652 assert_eq!(u32::from(a), 0x11223344);
2656 fn test_int_to_ipv4() {
2657 let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
2658 assert_eq!(Ipv4Addr::from(0x11223344), a);
2662 fn test_ipv6_to_int() {
2663 let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
2664 assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
2668 fn test_int_to_ipv6() {
2669 let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
2670 assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
2674 fn ipv4_from_constructors() {
2675 assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
2676 assert!(Ipv4Addr::LOCALHOST.is_loopback());
2677 assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
2678 assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
2679 assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
2680 assert!(Ipv4Addr::BROADCAST.is_broadcast());
2684 fn ipv6_from_contructors() {
2685 assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
2686 assert!(Ipv6Addr::LOCALHOST.is_loopback());
2687 assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
2688 assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
2692 fn ipv4_from_octets() {
2693 assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
2697 fn ipv6_from_segments() {
2699 Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
2700 let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
2701 assert_eq!(new, from_u16s);
2705 fn ipv6_from_octets() {
2707 Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
2708 let from_u8s = Ipv6Addr::from([
2709 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
2712 assert_eq!(from_u16s, from_u8s);
2717 let v41 = Ipv4Addr::new(100, 64, 3, 3);
2718 let v42 = Ipv4Addr::new(192, 0, 2, 2);
2719 let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
2720 let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
2724 assert_eq!(v41, IpAddr::V4(v41));
2725 assert_eq!(v61, IpAddr::V6(v61));
2726 assert!(v41 != IpAddr::V4(v42));
2727 assert!(v61 != IpAddr::V6(v62));
2729 assert!(v41 < IpAddr::V4(v42));
2730 assert!(v61 < IpAddr::V6(v62));
2731 assert!(IpAddr::V4(v41) < v42);
2732 assert!(IpAddr::V6(v61) < v62);
2734 assert!(v41 < IpAddr::V6(v61));
2735 assert!(IpAddr::V4(v41) < v61);
2740 let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
2741 assert!(ip.is_ipv4());
2742 assert!(!ip.is_ipv6());
2747 let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
2748 assert!(!ip.is_ipv4());
2749 assert!(ip.is_ipv6());