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
25 /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
26 /// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
31 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
33 /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
34 /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
36 /// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
37 /// assert_eq!("::1".parse(), Ok(localhost_v6));
39 /// assert_eq!(localhost_v4.is_ipv6(), false);
40 /// assert_eq!(localhost_v4.is_ipv4(), true);
42 #[stable(feature = "ip_addr", since = "1.7.0")]
43 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
46 #[stable(feature = "ip_addr", since = "1.7.0")]
47 V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
49 #[stable(feature = "ip_addr", since = "1.7.0")]
50 V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
55 /// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
56 /// They are usually represented as four octets.
58 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
60 /// The size of an `Ipv4Addr` struct may vary depending on the target operating
63 /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
64 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
66 /// # Textual representation
68 /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
69 /// notation, divided by `.` (this is called "dot-decimal notation").
71 /// [`FromStr`]: ../../std/str/trait.FromStr.html
76 /// use std::net::Ipv4Addr;
78 /// let localhost = Ipv4Addr::new(127, 0, 0, 1);
79 /// assert_eq!("127.0.0.1".parse(), Ok(localhost));
80 /// assert_eq!(localhost.is_loopback(), true);
83 #[stable(feature = "rust1", since = "1.0.0")]
90 /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
91 /// They are usually represented as eight 16-bit segments.
93 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
95 /// The size of an `Ipv6Addr` struct may vary depending on the target operating
98 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
99 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
101 /// # Textual representation
103 /// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
104 /// an IPv6 address in text, but in general, each segments is written in hexadecimal
105 /// notation, and segments are separated by `:`. For more information, see
108 /// [`FromStr`]: ../../std/str/trait.FromStr.html
109 /// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
114 /// use std::net::Ipv6Addr;
116 /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
117 /// assert_eq!("::1".parse(), Ok(localhost));
118 /// assert_eq!(localhost.is_loopback(), true);
121 #[stable(feature = "rust1", since = "1.0.0")]
122 pub struct Ipv6Addr {
126 #[allow(missing_docs)]
127 #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
128 pub enum Ipv6MulticastScope {
139 /// Returns [`true`] for the special 'unspecified' address.
141 /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and
142 /// [`Ipv6Addr::is_unspecified`][IPv6] for more details.
144 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
145 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
146 /// [`true`]: ../../std/primitive.bool.html
151 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
153 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
154 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
156 #[stable(feature = "ip_shared", since = "1.12.0")]
157 pub fn is_unspecified(&self) -> bool {
159 IpAddr::V4(ip) => ip.is_unspecified(),
160 IpAddr::V6(ip) => ip.is_unspecified(),
164 /// Returns [`true`] if this is a loopback address.
166 /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and
167 /// [`Ipv6Addr::is_loopback`][IPv6] for more details.
169 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
170 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
171 /// [`true`]: ../../std/primitive.bool.html
176 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
178 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
179 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
181 #[stable(feature = "ip_shared", since = "1.12.0")]
182 pub fn is_loopback(&self) -> bool {
184 IpAddr::V4(ip) => ip.is_loopback(),
185 IpAddr::V6(ip) => ip.is_loopback(),
189 /// Returns [`true`] if the address appears to be globally routable.
191 /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and
192 /// [`Ipv6Addr::is_global`][IPv6] for more details.
194 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
195 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
196 /// [`true`]: ../../std/primitive.bool.html
203 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
205 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
206 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
208 pub fn is_global(&self) -> bool {
210 IpAddr::V4(ip) => ip.is_global(),
211 IpAddr::V6(ip) => ip.is_global(),
215 /// Returns [`true`] if this is a multicast address.
217 /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and
218 /// [`Ipv6Addr::is_multicast`][IPv6] for more details.
220 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
221 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
222 /// [`true`]: ../../std/primitive.bool.html
227 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
229 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
230 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
232 #[stable(feature = "ip_shared", since = "1.12.0")]
233 pub fn is_multicast(&self) -> bool {
235 IpAddr::V4(ip) => ip.is_multicast(),
236 IpAddr::V6(ip) => ip.is_multicast(),
240 /// Returns [`true`] if this address is in a range designated for documentation.
242 /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and
243 /// [`Ipv6Addr::is_documentation`][IPv6] for more details.
245 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
246 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
247 /// [`true`]: ../../std/primitive.bool.html
254 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
256 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
258 /// IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(),
262 pub fn is_documentation(&self) -> bool {
264 IpAddr::V4(ip) => ip.is_documentation(),
265 IpAddr::V6(ip) => ip.is_documentation(),
269 /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise.
271 /// [`true`]: ../../std/primitive.bool.html
272 /// [`false`]: ../../std/primitive.bool.html
273 /// [IPv4 address]: #variant.V4
278 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
280 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
281 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
283 #[stable(feature = "ipaddr_checker", since = "1.16.0")]
284 pub fn is_ipv4(&self) -> bool {
285 matches!(self, IpAddr::V4(_))
288 /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
290 /// [`true`]: ../../std/primitive.bool.html
291 /// [`false`]: ../../std/primitive.bool.html
292 /// [IPv6 address]: #variant.V6
297 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
299 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
300 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
302 #[stable(feature = "ipaddr_checker", since = "1.16.0")]
303 pub fn is_ipv6(&self) -> bool {
304 matches!(self, IpAddr::V6(_))
309 /// Creates a new IPv4 address from four eight-bit octets.
311 /// The result will represent the IP address `a`.`b`.`c`.`d`.
316 /// use std::net::Ipv4Addr;
318 /// let addr = Ipv4Addr::new(127, 0, 0, 1);
320 #[stable(feature = "rust1", since = "1.0.0")]
321 #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
322 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
323 // `s_addr` is stored as BE on all machine and the array is in BE order.
324 // So the native endian conversion method is used so that it's never swapped.
325 Ipv4Addr { inner: c::in_addr { s_addr: u32::from_ne_bytes([a, b, c, d]) } }
328 /// An IPv4 address with the address pointing to localhost: 127.0.0.1.
333 /// use std::net::Ipv4Addr;
335 /// let addr = Ipv4Addr::LOCALHOST;
336 /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
338 #[stable(feature = "ip_constructors", since = "1.30.0")]
339 pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
341 /// An IPv4 address representing an unspecified address: 0.0.0.0
346 /// use std::net::Ipv4Addr;
348 /// let addr = Ipv4Addr::UNSPECIFIED;
349 /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
351 #[stable(feature = "ip_constructors", since = "1.30.0")]
352 pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
354 /// An IPv4 address representing the broadcast address: 255.255.255.255
359 /// use std::net::Ipv4Addr;
361 /// let addr = Ipv4Addr::BROADCAST;
362 /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
364 #[stable(feature = "ip_constructors", since = "1.30.0")]
365 pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
367 /// Returns the four eight-bit integers that make up this address.
372 /// use std::net::Ipv4Addr;
374 /// let addr = Ipv4Addr::new(127, 0, 0, 1);
375 /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
377 #[stable(feature = "rust1", since = "1.0.0")]
378 pub fn octets(&self) -> [u8; 4] {
379 // This returns the order we want because s_addr is stored in big-endian.
380 self.inner.s_addr.to_ne_bytes()
383 /// Returns [`true`] for the special 'unspecified' address (0.0.0.0).
385 /// This property is defined in _UNIX Network Programming, Second Edition_,
386 /// W. Richard Stevens, p. 891; see also [ip7].
388 /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
389 /// [`true`]: ../../std/primitive.bool.html
394 /// use std::net::Ipv4Addr;
396 /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
397 /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
399 #[stable(feature = "ip_shared", since = "1.12.0")]
400 #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")]
401 pub const fn is_unspecified(&self) -> bool {
402 self.inner.s_addr == 0
405 /// Returns [`true`] if this is a loopback address (127.0.0.0/8).
407 /// This property is defined by [IETF RFC 1122].
409 /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
410 /// [`true`]: ../../std/primitive.bool.html
415 /// use std::net::Ipv4Addr;
417 /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
418 /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
420 #[stable(since = "1.7.0", feature = "ip_17")]
421 pub fn is_loopback(&self) -> bool {
422 self.octets()[0] == 127
425 /// Returns [`true`] if this is a private address.
427 /// The private address ranges are defined in [IETF RFC 1918] and include:
433 /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
434 /// [`true`]: ../../std/primitive.bool.html
439 /// use std::net::Ipv4Addr;
441 /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
442 /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
443 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
444 /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
445 /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
446 /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
447 /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
449 #[stable(since = "1.7.0", feature = "ip_17")]
450 pub fn is_private(&self) -> bool {
451 match self.octets() {
453 [172, b, ..] if b >= 16 && b <= 31 => true,
454 [192, 168, ..] => true,
459 /// Returns [`true`] if the address is link-local (169.254.0.0/16).
461 /// This property is defined by [IETF RFC 3927].
463 /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
464 /// [`true`]: ../../std/primitive.bool.html
469 /// use std::net::Ipv4Addr;
471 /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
472 /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
473 /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
475 #[stable(since = "1.7.0", feature = "ip_17")]
476 pub fn is_link_local(&self) -> bool {
477 match self.octets() {
478 [169, 254, ..] => true,
483 /// Returns [`true`] if the address appears to be globally routable.
484 /// See [iana-ipv4-special-registry][ipv4-sr].
486 /// The following return false:
488 /// - private addresses (see [`is_private()`](#method.is_private))
489 /// - the loopback address (see [`is_loopback()`](#method.is_loopback))
490 /// - the link-local address (see [`is_link_local()`](#method.is_link_local))
491 /// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast))
492 /// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation))
493 /// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole
495 /// - addresses reserved for future protocols (see
496 /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except
497 /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
498 /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved)
499 /// - addresses reserved for networking devices benchmarking (see
500 /// [`is_benchmarking`](#method.is_benchmarking))
502 /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
503 /// [`true`]: ../../std/primitive.bool.html
510 /// use std::net::Ipv4Addr;
512 /// // private addresses are not global
513 /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
514 /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
515 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
517 /// // the 0.0.0.0/8 block is not global
518 /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
519 /// // in particular, the unspecified address is not global
520 /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
522 /// // the loopback address is not global
523 /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
525 /// // link local addresses are not global
526 /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
528 /// // the broadcast address is not global
529 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
531 /// // the address space designated for documentation is not global
532 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
533 /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
534 /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
536 /// // shared addresses are not global
537 /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
539 /// // addresses reserved for protocol assignment are not global
540 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
541 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
543 /// // addresses reserved for future use are not global
544 /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
546 /// // addresses reserved for network devices benchmarking are not global
547 /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
549 /// // All the other addresses are global
550 /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
551 /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
553 pub fn is_global(&self) -> bool {
554 // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
555 // globally routable addresses in the 192.0.0.0/24 range.
556 if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
560 && !self.is_loopback()
561 && !self.is_link_local()
562 && !self.is_broadcast()
563 && !self.is_documentation()
565 && !self.is_ietf_protocol_assignment()
566 && !self.is_reserved()
567 && !self.is_benchmarking()
568 // Make sure the address is not in 0.0.0.0/8
569 && self.octets()[0] != 0
572 /// Returns [`true`] if this address is part of the Shared Address Space defined in
573 /// [IETF RFC 6598] (`100.64.0.0/10`).
575 /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
576 /// [`true`]: ../../std/primitive.bool.html
582 /// use std::net::Ipv4Addr;
584 /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
585 /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
586 /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
588 pub fn is_shared(&self) -> bool {
589 self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
592 /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to
593 /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890].
595 /// Note that parts of this block are in use:
597 /// - `192.0.0.8/32` is the "IPv4 dummy address" (see [IETF RFC 7600])
598 /// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723])
599 /// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155])
601 /// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890
602 /// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600
603 /// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723
604 /// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155
605 /// [`true`]: ../../std/primitive.bool.html
611 /// use std::net::Ipv4Addr;
613 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true);
614 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true);
615 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true);
616 /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true);
617 /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false);
618 /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
620 pub fn is_ietf_protocol_assignment(&self) -> bool {
621 self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
624 /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
625 /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
626 /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
628 /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
629 /// [errata 423]: https://www.rfc-editor.org/errata/eid423
630 /// [`true`]: ../../std/primitive.bool.html
636 /// use std::net::Ipv4Addr;
638 /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
639 /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
640 /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
641 /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
643 pub fn is_benchmarking(&self) -> bool {
644 self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
647 /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
648 /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
649 /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
650 /// it is obviously not reserved for future use.
652 /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
653 /// [`true`]: ../../std/primitive.bool.html
657 /// As IANA assigns new addresses, this method will be
658 /// updated. This may result in non-reserved addresses being
659 /// treated as reserved in code that relies on an outdated version
666 /// use std::net::Ipv4Addr;
668 /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
669 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
671 /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
672 /// // The broadcast address is not considered as reserved for future use by this implementation
673 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
675 pub fn is_reserved(&self) -> bool {
676 self.octets()[0] & 240 == 240 && !self.is_broadcast()
679 /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
681 /// Multicast addresses have a most significant octet between 224 and 239,
682 /// and is defined by [IETF RFC 5771].
684 /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
685 /// [`true`]: ../../std/primitive.bool.html
690 /// use std::net::Ipv4Addr;
692 /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
693 /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
694 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
696 #[stable(since = "1.7.0", feature = "ip_17")]
697 pub fn is_multicast(&self) -> bool {
698 self.octets()[0] >= 224 && self.octets()[0] <= 239
701 /// Returns [`true`] if this is a broadcast address (255.255.255.255).
703 /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
705 /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
706 /// [`true`]: ../../std/primitive.bool.html
711 /// use std::net::Ipv4Addr;
713 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
714 /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
716 #[stable(since = "1.7.0", feature = "ip_17")]
717 pub fn is_broadcast(&self) -> bool {
718 self == &Self::BROADCAST
721 /// Returns [`true`] if this address is in a range designated for documentation.
723 /// This is defined in [IETF RFC 5737]:
725 /// - 192.0.2.0/24 (TEST-NET-1)
726 /// - 198.51.100.0/24 (TEST-NET-2)
727 /// - 203.0.113.0/24 (TEST-NET-3)
729 /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
730 /// [`true`]: ../../std/primitive.bool.html
735 /// use std::net::Ipv4Addr;
737 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
738 /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
739 /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
740 /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
742 #[stable(since = "1.7.0", feature = "ip_17")]
743 pub fn is_documentation(&self) -> bool {
744 match self.octets() {
745 [192, 0, 2, _] => true,
746 [198, 51, 100, _] => true,
747 [203, 0, 113, _] => true,
752 /// Converts this address to an IPv4-compatible [IPv6 address].
754 /// a.b.c.d becomes ::a.b.c.d
756 /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
761 /// use std::net::{Ipv4Addr, Ipv6Addr};
764 /// Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
765 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)
768 #[stable(feature = "rust1", since = "1.0.0")]
769 pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
770 let [a, b, c, d] = self.octets();
771 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
774 /// Converts this address to an IPv4-mapped [IPv6 address].
776 /// a.b.c.d becomes ::ffff:a.b.c.d
778 /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
783 /// use std::net::{Ipv4Addr, Ipv6Addr};
785 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
786 /// Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
788 #[stable(feature = "rust1", since = "1.0.0")]
789 pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
790 let [a, b, c, d] = self.octets();
791 Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d])
795 #[stable(feature = "ip_addr", since = "1.7.0")]
796 impl fmt::Display for IpAddr {
797 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
799 IpAddr::V4(ip) => ip.fmt(fmt),
800 IpAddr::V6(ip) => ip.fmt(fmt),
805 #[stable(feature = "ip_from_ip", since = "1.16.0")]
806 impl From<Ipv4Addr> for IpAddr {
807 /// Copies this address to a new `IpAddr::V4`.
812 /// use std::net::{IpAddr, Ipv4Addr};
814 /// let addr = Ipv4Addr::new(127, 0, 0, 1);
817 /// IpAddr::V4(addr),
818 /// IpAddr::from(addr)
821 fn from(ipv4: Ipv4Addr) -> IpAddr {
826 #[stable(feature = "ip_from_ip", since = "1.16.0")]
827 impl From<Ipv6Addr> for IpAddr {
828 /// Copies this address to a new `IpAddr::V6`.
833 /// use std::net::{IpAddr, Ipv6Addr};
835 /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
838 /// IpAddr::V6(addr),
839 /// IpAddr::from(addr)
842 fn from(ipv6: Ipv6Addr) -> IpAddr {
847 #[stable(feature = "rust1", since = "1.0.0")]
848 impl fmt::Display for Ipv4Addr {
849 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
850 let octets = self.octets();
851 // Fast Path: if there's no alignment stuff, write directly to the buffer
852 if fmt.precision().is_none() && fmt.width().is_none() {
853 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
855 const IPV4_BUF_LEN: usize = 15; // Long enough for the longest possible IPv4 address
856 let mut buf = [0u8; IPV4_BUF_LEN];
857 let mut buf_slice = &mut buf[..];
859 // Note: The call to write should never fail, hence the unwrap
860 write!(buf_slice, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
861 let len = IPV4_BUF_LEN - buf_slice.len();
863 // This unsafe is OK because we know what is being written to the buffer
864 let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
870 #[stable(feature = "rust1", since = "1.0.0")]
871 impl fmt::Debug for Ipv4Addr {
872 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
873 fmt::Display::fmt(self, fmt)
877 #[stable(feature = "rust1", since = "1.0.0")]
878 impl Clone for Ipv4Addr {
879 fn clone(&self) -> Ipv4Addr {
884 #[stable(feature = "rust1", since = "1.0.0")]
885 impl PartialEq for Ipv4Addr {
886 fn eq(&self, other: &Ipv4Addr) -> bool {
887 self.inner.s_addr == other.inner.s_addr
891 #[stable(feature = "ip_cmp", since = "1.16.0")]
892 impl PartialEq<Ipv4Addr> for IpAddr {
893 fn eq(&self, other: &Ipv4Addr) -> bool {
895 IpAddr::V4(v4) => v4 == other,
896 IpAddr::V6(_) => false,
901 #[stable(feature = "ip_cmp", since = "1.16.0")]
902 impl PartialEq<IpAddr> for Ipv4Addr {
903 fn eq(&self, other: &IpAddr) -> bool {
905 IpAddr::V4(v4) => self == v4,
906 IpAddr::V6(_) => false,
911 #[stable(feature = "rust1", since = "1.0.0")]
912 impl Eq for Ipv4Addr {}
914 #[stable(feature = "rust1", since = "1.0.0")]
915 impl hash::Hash for Ipv4Addr {
916 fn hash<H: hash::Hasher>(&self, s: &mut H) {
917 // `inner` is #[repr(packed)], so we need to copy `s_addr`.
918 { self.inner.s_addr }.hash(s)
922 #[stable(feature = "rust1", since = "1.0.0")]
923 impl PartialOrd for Ipv4Addr {
924 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
925 Some(self.cmp(other))
929 #[stable(feature = "ip_cmp", since = "1.16.0")]
930 impl PartialOrd<Ipv4Addr> for IpAddr {
931 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
933 IpAddr::V4(v4) => v4.partial_cmp(other),
934 IpAddr::V6(_) => Some(Ordering::Greater),
939 #[stable(feature = "ip_cmp", since = "1.16.0")]
940 impl PartialOrd<IpAddr> for Ipv4Addr {
941 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
943 IpAddr::V4(v4) => self.partial_cmp(v4),
944 IpAddr::V6(_) => Some(Ordering::Less),
949 #[stable(feature = "rust1", since = "1.0.0")]
950 impl Ord for Ipv4Addr {
951 fn cmp(&self, other: &Ipv4Addr) -> Ordering {
952 u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
956 impl AsInner<c::in_addr> for Ipv4Addr {
957 fn as_inner(&self) -> &c::in_addr {
962 #[stable(feature = "ip_u32", since = "1.1.0")]
963 impl From<Ipv4Addr> for u32 {
964 /// Converts an `Ipv4Addr` into a host byte order `u32`.
969 /// use std::net::Ipv4Addr;
971 /// let addr = Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe);
972 /// assert_eq!(0xcafebabe, u32::from(addr));
974 fn from(ip: Ipv4Addr) -> u32 {
975 let ip = ip.octets();
976 u32::from_be_bytes(ip)
980 #[stable(feature = "ip_u32", since = "1.1.0")]
981 impl From<u32> for Ipv4Addr {
982 /// Converts a host byte order `u32` into an `Ipv4Addr`.
987 /// use std::net::Ipv4Addr;
989 /// let addr = Ipv4Addr::from(0xcafebabe);
990 /// assert_eq!(Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe), addr);
992 fn from(ip: u32) -> Ipv4Addr {
993 Ipv4Addr::from(ip.to_be_bytes())
997 #[stable(feature = "from_slice_v4", since = "1.9.0")]
998 impl From<[u8; 4]> for Ipv4Addr {
999 /// Creates an `Ipv4Addr` from a four element byte array.
1004 /// use std::net::Ipv4Addr;
1006 /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
1007 /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
1009 fn from(octets: [u8; 4]) -> Ipv4Addr {
1010 Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
1014 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1015 impl From<[u8; 4]> for IpAddr {
1016 /// Creates an `IpAddr::V4` from a four element byte array.
1021 /// use std::net::{IpAddr, Ipv4Addr};
1023 /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
1024 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
1026 fn from(octets: [u8; 4]) -> IpAddr {
1027 IpAddr::V4(Ipv4Addr::from(octets))
1032 /// Creates a new IPv6 address from eight 16-bit segments.
1034 /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
1039 /// use std::net::Ipv6Addr;
1041 /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
1043 #[stable(feature = "rust1", since = "1.0.0")]
1044 #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
1045 #[allow_internal_unstable(const_fn_transmute)]
1046 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
1058 inner: c::in6_addr {
1059 // All elements in `addr16` are big endian.
1060 // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
1061 s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
1066 /// An IPv6 address representing localhost: `::1`.
1071 /// use std::net::Ipv6Addr;
1073 /// let addr = Ipv6Addr::LOCALHOST;
1074 /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
1076 #[stable(feature = "ip_constructors", since = "1.30.0")]
1077 pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
1079 /// An IPv6 address representing the unspecified address: `::`
1084 /// use std::net::Ipv6Addr;
1086 /// let addr = Ipv6Addr::UNSPECIFIED;
1087 /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
1089 #[stable(feature = "ip_constructors", since = "1.30.0")]
1090 pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
1092 /// Returns the eight 16-bit segments that make up this address.
1097 /// use std::net::Ipv6Addr;
1099 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
1100 /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
1102 #[stable(feature = "rust1", since = "1.0.0")]
1103 pub fn segments(&self) -> [u16; 8] {
1104 // All elements in `s6_addr` must be big endian.
1105 // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
1106 let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
1107 // We want native endian u16
1120 /// Returns [`true`] for the special 'unspecified' address (::).
1122 /// This property is defined in [IETF RFC 4291].
1124 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1125 /// [`true`]: ../../std/primitive.bool.html
1130 /// use std::net::Ipv6Addr;
1132 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
1133 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
1135 #[stable(since = "1.7.0", feature = "ip_17")]
1136 pub fn is_unspecified(&self) -> bool {
1137 self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
1140 /// Returns [`true`] if this is a loopback address (::1).
1142 /// This property is defined in [IETF RFC 4291].
1144 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1145 /// [`true`]: ../../std/primitive.bool.html
1150 /// use std::net::Ipv6Addr;
1152 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
1153 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
1155 #[stable(since = "1.7.0", feature = "ip_17")]
1156 pub fn is_loopback(&self) -> bool {
1157 self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
1160 /// Returns [`true`] if the address appears to be globally routable.
1162 /// The following return [`false`]:
1164 /// - the loopback address
1165 /// - link-local and unique local unicast addresses
1166 /// - interface-, link-, realm-, admin- and site-local multicast addresses
1168 /// [`true`]: ../../std/primitive.bool.html
1169 /// [`false`]: ../../std/primitive.bool.html
1176 /// use std::net::Ipv6Addr;
1178 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
1179 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
1180 /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
1182 pub fn is_global(&self) -> bool {
1183 match self.multicast_scope() {
1184 Some(Ipv6MulticastScope::Global) => true,
1185 None => self.is_unicast_global(),
1190 /// Returns [`true`] if this is a unique local address (`fc00::/7`).
1192 /// This property is defined in [IETF RFC 4193].
1194 /// [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 [`is_unicast_link_local()`] instead.
1233 /// use std::net::Ipv6Addr;
1235 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
1236 /// assert!(ip.is_unicast_link_local_strict());
1238 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
1239 /// assert!(ip.is_unicast_link_local_strict());
1241 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
1242 /// assert!(!ip.is_unicast_link_local_strict());
1243 /// assert!(ip.is_unicast_link_local());
1245 /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
1246 /// assert!(!ip.is_unicast_link_local_strict());
1247 /// assert!(ip.is_unicast_link_local());
1252 /// - [IETF RFC 4291 section 2.5.6]
1253 /// - [RFC 4291 errata 4406] (which has been rejected but provides useful
1255 /// - [`is_unicast_link_local()`]
1257 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1258 /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
1259 /// [`true`]: ../../std/primitive.bool.html
1260 /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
1261 /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local
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 [`is_unicast_link_local_strict()`] does not. If you
1284 /// need a strict validation fully compliant with the RFC, use
1285 /// [`is_unicast_link_local_strict()`].
1292 /// use std::net::Ipv6Addr;
1294 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
1295 /// assert!(ip.is_unicast_link_local());
1297 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
1298 /// assert!(ip.is_unicast_link_local());
1300 /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
1301 /// assert!(ip.is_unicast_link_local());
1302 /// assert!(!ip.is_unicast_link_local_strict());
1304 /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
1305 /// assert!(ip.is_unicast_link_local());
1306 /// assert!(!ip.is_unicast_link_local_strict());
1311 /// - [IETF RFC 4291 section 2.4]
1312 /// - [RFC 4291 errata 4406] (which has been rejected but provides useful
1315 /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
1316 /// [`true`]: ../../std/primitive.bool.html
1317 /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
1318 /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict
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 /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
1368 /// [`true`]: ../../std/primitive.bool.html
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 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1461 /// [`true`]: ../../std/primitive.bool.html
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]: ../../std/net/struct.Ipv4Addr.html
1483 /// [`None`]: ../../std/option/enum.Option.html#variant.None
1484 /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1491 /// use std::net::{Ipv4Addr, Ipv6Addr};
1493 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
1494 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
1495 /// Some(Ipv4Addr::new(192, 10, 2, 255)));
1496 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
1498 pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
1499 match self.octets() {
1500 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
1501 Some(Ipv4Addr::new(a, b, c, d))
1507 /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
1508 /// neither IPv4-compatible or IPv4-mapped.
1510 /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
1512 /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
1513 /// [`None`]: ../../std/option/enum.Option.html#variant.None
1518 /// use std::net::{Ipv4Addr, Ipv6Addr};
1520 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
1521 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
1522 /// Some(Ipv4Addr::new(192, 10, 2, 255)));
1523 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
1524 /// Some(Ipv4Addr::new(0, 0, 0, 1)));
1526 #[stable(feature = "rust1", since = "1.0.0")]
1527 pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
1528 if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
1529 let [a, b] = ab.to_be_bytes();
1530 let [c, d] = cd.to_be_bytes();
1531 Some(Ipv4Addr::new(a, b, c, d))
1537 /// Returns the sixteen eight-bit integers the IPv6 address consists of.
1540 /// use std::net::Ipv6Addr;
1542 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
1543 /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
1545 #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
1546 #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
1547 pub const fn octets(&self) -> [u8; 16] {
1552 /// Write an Ipv6Addr, conforming to the canonical style described by
1553 /// [RFC 5952](https://tools.ietf.org/html/rfc5952).
1554 #[stable(feature = "rust1", since = "1.0.0")]
1555 impl fmt::Display for Ipv6Addr {
1556 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1557 // If there are no alignment requirements, write out the IP address to
1558 // f. Otherwise, write it to a local buffer, then use f.pad.
1559 if f.precision().is_none() && f.width().is_none() {
1560 let segments = self.segments();
1562 // Special case for :: and ::1; otherwise they get written with the
1564 if self.is_unspecified() {
1566 } else if self.is_loopback() {
1568 } else if let Some(ipv4) = self.to_ipv4() {
1570 // IPv4 Compatible address
1571 0 => write!(f, "::{}", ipv4),
1572 // IPv4 Mapped address
1573 0xffff => write!(f, "::ffff:{}", ipv4),
1574 _ => unreachable!(),
1577 #[derive(Copy, Clone, Default)]
1583 // Find the inner 0 span
1585 let mut longest = Span::default();
1586 let mut current = Span::default();
1588 for (i, &segment) in segments.iter().enumerate() {
1590 if current.len == 0 {
1596 if current.len > longest.len {
1600 current = Span::default();
1607 /// Write a colon-separated part of the address
1609 fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
1610 if let Some(first) = chunk.first() {
1611 fmt::LowerHex::fmt(first, f)?;
1612 for segment in &chunk[1..] {
1614 fmt::LowerHex::fmt(segment, f)?;
1621 fmt_subslice(f, &segments[..zeroes.start])?;
1623 fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
1625 fmt_subslice(f, &segments)
1629 // Slow path: write the address to a local buffer, the use f.pad.
1630 // Defined recursively by using the fast path to write to the
1633 // This is the largest possible size of an IPv6 address
1634 const IPV6_BUF_LEN: usize = (4 * 8) + 7;
1635 let mut buf = [0u8; IPV6_BUF_LEN];
1636 let mut buf_slice = &mut buf[..];
1638 // Note: This call to write should never fail, so unwrap is okay.
1639 write!(buf_slice, "{}", self).unwrap();
1640 let len = IPV6_BUF_LEN - buf_slice.len();
1642 // This is safe because we know exactly what can be in this buffer
1643 let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
1649 #[stable(feature = "rust1", since = "1.0.0")]
1650 impl fmt::Debug for Ipv6Addr {
1651 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1652 fmt::Display::fmt(self, fmt)
1656 #[stable(feature = "rust1", since = "1.0.0")]
1657 impl Clone for Ipv6Addr {
1658 fn clone(&self) -> Ipv6Addr {
1663 #[stable(feature = "rust1", since = "1.0.0")]
1664 impl PartialEq for Ipv6Addr {
1665 fn eq(&self, other: &Ipv6Addr) -> bool {
1666 self.inner.s6_addr == other.inner.s6_addr
1670 #[stable(feature = "ip_cmp", since = "1.16.0")]
1671 impl PartialEq<IpAddr> for Ipv6Addr {
1672 fn eq(&self, other: &IpAddr) -> bool {
1674 IpAddr::V4(_) => false,
1675 IpAddr::V6(v6) => self == v6,
1680 #[stable(feature = "ip_cmp", since = "1.16.0")]
1681 impl PartialEq<Ipv6Addr> for IpAddr {
1682 fn eq(&self, other: &Ipv6Addr) -> bool {
1684 IpAddr::V4(_) => false,
1685 IpAddr::V6(v6) => v6 == other,
1690 #[stable(feature = "rust1", since = "1.0.0")]
1691 impl Eq for Ipv6Addr {}
1693 #[stable(feature = "rust1", since = "1.0.0")]
1694 impl hash::Hash for Ipv6Addr {
1695 fn hash<H: hash::Hasher>(&self, s: &mut H) {
1696 self.inner.s6_addr.hash(s)
1700 #[stable(feature = "rust1", since = "1.0.0")]
1701 impl PartialOrd for Ipv6Addr {
1702 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1703 Some(self.cmp(other))
1707 #[stable(feature = "ip_cmp", since = "1.16.0")]
1708 impl PartialOrd<Ipv6Addr> for IpAddr {
1709 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1711 IpAddr::V4(_) => Some(Ordering::Less),
1712 IpAddr::V6(v6) => v6.partial_cmp(other),
1717 #[stable(feature = "ip_cmp", since = "1.16.0")]
1718 impl PartialOrd<IpAddr> for Ipv6Addr {
1719 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
1721 IpAddr::V4(_) => Some(Ordering::Greater),
1722 IpAddr::V6(v6) => self.partial_cmp(v6),
1727 #[stable(feature = "rust1", since = "1.0.0")]
1728 impl Ord for Ipv6Addr {
1729 fn cmp(&self, other: &Ipv6Addr) -> Ordering {
1730 self.segments().cmp(&other.segments())
1734 impl AsInner<c::in6_addr> for Ipv6Addr {
1735 fn as_inner(&self) -> &c::in6_addr {
1739 impl FromInner<c::in6_addr> for Ipv6Addr {
1740 fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
1741 Ipv6Addr { inner: addr }
1745 #[stable(feature = "i128", since = "1.26.0")]
1746 impl From<Ipv6Addr> for u128 {
1747 /// Convert an `Ipv6Addr` into a host byte order `u128`.
1752 /// use std::net::Ipv6Addr;
1754 /// let addr = Ipv6Addr::new(
1755 /// 0x1020, 0x3040, 0x5060, 0x7080,
1756 /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1758 /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
1760 fn from(ip: Ipv6Addr) -> u128 {
1761 let ip = ip.octets();
1762 u128::from_be_bytes(ip)
1765 #[stable(feature = "i128", since = "1.26.0")]
1766 impl From<u128> for Ipv6Addr {
1767 /// Convert a host byte order `u128` into an `Ipv6Addr`.
1772 /// use std::net::Ipv6Addr;
1774 /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
1777 /// 0x1020, 0x3040, 0x5060, 0x7080,
1778 /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1782 fn from(ip: u128) -> Ipv6Addr {
1783 Ipv6Addr::from(ip.to_be_bytes())
1787 #[stable(feature = "ipv6_from_octets", since = "1.9.0")]
1788 impl From<[u8; 16]> for Ipv6Addr {
1789 /// Creates an `Ipv6Addr` from a sixteen element byte array.
1794 /// use std::net::Ipv6Addr;
1796 /// let addr = Ipv6Addr::from([
1797 /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1798 /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1810 fn from(octets: [u8; 16]) -> Ipv6Addr {
1811 let inner = c::in6_addr { s6_addr: octets };
1812 Ipv6Addr::from_inner(inner)
1816 #[stable(feature = "ipv6_from_segments", since = "1.16.0")]
1817 impl From<[u16; 8]> for Ipv6Addr {
1818 /// Creates an `Ipv6Addr` from an eight element 16-bit array.
1823 /// use std::net::Ipv6Addr;
1825 /// let addr = Ipv6Addr::from([
1826 /// 525u16, 524u16, 523u16, 522u16,
1827 /// 521u16, 520u16, 519u16, 518u16,
1839 fn from(segments: [u16; 8]) -> Ipv6Addr {
1840 let [a, b, c, d, e, f, g, h] = segments;
1841 Ipv6Addr::new(a, b, c, d, e, f, g, h)
1845 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1846 impl From<[u8; 16]> for IpAddr {
1847 /// Creates an `IpAddr::V6` from a sixteen element byte array.
1852 /// use std::net::{IpAddr, Ipv6Addr};
1854 /// let addr = IpAddr::from([
1855 /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1856 /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1859 /// IpAddr::V6(Ipv6Addr::new(
1868 fn from(octets: [u8; 16]) -> IpAddr {
1869 IpAddr::V6(Ipv6Addr::from(octets))
1873 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1874 impl From<[u16; 8]> for IpAddr {
1875 /// Creates an `IpAddr::V6` from an eight element 16-bit array.
1880 /// use std::net::{IpAddr, Ipv6Addr};
1882 /// let addr = IpAddr::from([
1883 /// 525u16, 524u16, 523u16, 522u16,
1884 /// 521u16, 520u16, 519u16, 518u16,
1887 /// IpAddr::V6(Ipv6Addr::new(
1896 fn from(segments: [u16; 8]) -> IpAddr {
1897 IpAddr::V6(Ipv6Addr::from(segments))
1901 // Tests for this module
1902 #[cfg(all(test, not(target_os = "emscripten")))]
1904 use crate::net::test::{sa4, sa6, tsa};
1906 use crate::str::FromStr;
1909 fn test_from_str_ipv4() {
1910 assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
1911 assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
1912 assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
1915 let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
1916 assert_eq!(None, none);
1918 let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
1919 assert_eq!(None, none);
1921 let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
1922 assert_eq!(None, none);
1923 // no number between dots
1924 let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
1925 assert_eq!(None, none);
1929 fn test_from_str_ipv6() {
1930 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
1931 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
1933 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
1934 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
1937 Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
1938 "2a02:6b8::11:11".parse()
1942 let none: Option<Ipv6Addr> = "::00000".parse().ok();
1943 assert_eq!(None, none);
1945 let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
1946 assert_eq!(None, none);
1948 let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
1949 assert_eq!(None, none);
1951 let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
1952 assert_eq!(None, none);
1953 // two double colons
1954 let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
1955 assert_eq!(None, none);
1956 // `::` indicating zero groups of zeros
1957 let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
1958 assert_eq!(None, none);
1962 fn test_from_str_ipv4_in_ipv6() {
1963 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
1965 Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
1966 "::FFFF:192.0.2.33".parse()
1969 Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
1970 "64:ff9b::192.0.2.33".parse()
1973 Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
1974 "2001:db8:122:c000:2:2100:192.0.2.33".parse()
1978 let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
1979 assert_eq!(None, none);
1980 // not enough groups
1981 let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok();
1982 assert_eq!(None, none);
1984 let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
1985 assert_eq!(None, none);
1989 fn test_from_str_socket_addr() {
1990 assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
1992 Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)),
1993 "77.88.21.11:80".parse()
1996 Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
1997 "[2a02:6b8:0:1::1]:53".parse()
2000 Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
2001 "[2a02:6b8:0:1::1]:53".parse()
2004 Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
2005 "[::127.0.0.1]:22".parse()
2008 Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
2009 "[::127.0.0.1]:22".parse()
2013 let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
2014 assert_eq!(None, none);
2016 let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
2017 assert_eq!(None, none);
2018 // wrong brackets around v4
2019 let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
2020 assert_eq!(None, none);
2021 // port out of range
2022 let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
2023 assert_eq!(None, none);
2027 fn ipv4_addr_to_string() {
2029 assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
2031 assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
2034 assert_eq!(&format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1 ");
2035 assert_eq!(&format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), " 1.1.1.1");
2039 fn ipv6_addr_to_string() {
2040 // ipv4-mapped address
2041 let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
2042 assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
2044 // ipv4-compatible address
2045 let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
2046 assert_eq!(a1.to_string(), "::192.0.2.128");
2048 // v6 address with no zero segments
2049 assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
2051 // longest possible IPv6 length
2053 Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888)
2055 "1111:2222:3333:4444:5555:6666:7777:8888"
2059 &format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)),
2063 &format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)),
2067 // reduce a single run of zeros
2070 Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
2073 // don't reduce just a single zero segment
2074 assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
2077 assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
2080 assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
2083 assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
2085 // two runs of zeros, second one is longer
2086 assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
2088 // two runs of zeros, equal length
2089 assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
2095 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
2096 Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
2099 Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
2100 Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
2105 fn ipv6_to_ipv4_mapped() {
2107 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
2108 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2110 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
2116 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
2117 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2120 Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
2121 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
2123 assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
2127 fn ip_properties() {
2130 IpAddr::from_str($s).unwrap()
2134 macro_rules! check {
2139 ($s:expr, $mask:expr) => {{
2140 let unspec: u8 = 1 << 0;
2141 let loopback: u8 = 1 << 1;
2142 let global: u8 = 1 << 2;
2143 let multicast: u8 = 1 << 3;
2144 let doc: u8 = 1 << 4;
2146 if ($mask & unspec) == unspec {
2147 assert!(ip!($s).is_unspecified());
2149 assert!(!ip!($s).is_unspecified());
2152 if ($mask & loopback) == loopback {
2153 assert!(ip!($s).is_loopback());
2155 assert!(!ip!($s).is_loopback());
2158 if ($mask & global) == global {
2159 assert!(ip!($s).is_global());
2161 assert!(!ip!($s).is_global());
2164 if ($mask & multicast) == multicast {
2165 assert!(ip!($s).is_multicast());
2167 assert!(!ip!($s).is_multicast());
2170 if ($mask & doc) == doc {
2171 assert!(ip!($s).is_documentation());
2173 assert!(!ip!($s).is_documentation());
2178 let unspec: u8 = 1 << 0;
2179 let loopback: u8 = 1 << 1;
2180 let global: u8 = 1 << 2;
2181 let multicast: u8 = 1 << 3;
2182 let doc: u8 = 1 << 4;
2184 check!("0.0.0.0", unspec);
2188 check!("127.1.2.3", loopback);
2189 check!("172.31.254.253");
2190 check!("169.254.253.242");
2191 check!("192.0.2.183", doc);
2192 check!("192.1.2.183", global);
2193 check!("192.168.254.253");
2194 check!("198.51.100.0", doc);
2195 check!("203.0.113.0", doc);
2196 check!("203.2.113.0", global);
2197 check!("224.0.0.0", global | multicast);
2198 check!("239.255.255.255", global | multicast);
2199 check!("255.255.255.255");
2200 // make sure benchmarking addresses are not global
2201 check!("198.18.0.0");
2202 check!("198.18.54.2");
2203 check!("198.19.255.255");
2204 // make sure addresses reserved for protocol assignment are not global
2205 check!("192.0.0.0");
2206 check!("192.0.0.255");
2207 check!("192.0.0.100");
2208 // make sure reserved addresses are not global
2209 check!("240.0.0.0");
2210 check!("251.54.1.76");
2211 check!("254.255.255.255");
2212 // make sure shared addresses are not global
2213 check!("100.64.0.0");
2214 check!("100.127.255.255");
2215 check!("100.100.100.0");
2217 check!("::", unspec);
2218 check!("::1", loopback);
2219 check!("::0.0.0.2", global);
2220 check!("1::", global);
2222 check!("fdff:ffff::");
2223 check!("fe80:ffff::");
2224 check!("febf:ffff::");
2225 check!("fec0::", global);
2226 check!("ff01::", multicast);
2227 check!("ff02::", multicast);
2228 check!("ff03::", multicast);
2229 check!("ff04::", multicast);
2230 check!("ff05::", multicast);
2231 check!("ff08::", multicast);
2232 check!("ff0e::", global | multicast);
2233 check!("2001:db8:85a3::8a2e:370:7334", doc);
2234 check!("102:304:506:708:90a:b0c:d0e:f10", global);
2238 fn ipv4_properties() {
2241 Ipv4Addr::from_str($s).unwrap()
2245 macro_rules! check {
2250 ($s:expr, $mask:expr) => {{
2251 let unspec: u16 = 1 << 0;
2252 let loopback: u16 = 1 << 1;
2253 let private: u16 = 1 << 2;
2254 let link_local: u16 = 1 << 3;
2255 let global: u16 = 1 << 4;
2256 let multicast: u16 = 1 << 5;
2257 let broadcast: u16 = 1 << 6;
2258 let documentation: u16 = 1 << 7;
2259 let benchmarking: u16 = 1 << 8;
2260 let ietf_protocol_assignment: u16 = 1 << 9;
2261 let reserved: u16 = 1 << 10;
2262 let shared: u16 = 1 << 11;
2264 if ($mask & unspec) == unspec {
2265 assert!(ip!($s).is_unspecified());
2267 assert!(!ip!($s).is_unspecified());
2270 if ($mask & loopback) == loopback {
2271 assert!(ip!($s).is_loopback());
2273 assert!(!ip!($s).is_loopback());
2276 if ($mask & private) == private {
2277 assert!(ip!($s).is_private());
2279 assert!(!ip!($s).is_private());
2282 if ($mask & link_local) == link_local {
2283 assert!(ip!($s).is_link_local());
2285 assert!(!ip!($s).is_link_local());
2288 if ($mask & global) == global {
2289 assert!(ip!($s).is_global());
2291 assert!(!ip!($s).is_global());
2294 if ($mask & multicast) == multicast {
2295 assert!(ip!($s).is_multicast());
2297 assert!(!ip!($s).is_multicast());
2300 if ($mask & broadcast) == broadcast {
2301 assert!(ip!($s).is_broadcast());
2303 assert!(!ip!($s).is_broadcast());
2306 if ($mask & documentation) == documentation {
2307 assert!(ip!($s).is_documentation());
2309 assert!(!ip!($s).is_documentation());
2312 if ($mask & benchmarking) == benchmarking {
2313 assert!(ip!($s).is_benchmarking());
2315 assert!(!ip!($s).is_benchmarking());
2318 if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment {
2319 assert!(ip!($s).is_ietf_protocol_assignment());
2321 assert!(!ip!($s).is_ietf_protocol_assignment());
2324 if ($mask & reserved) == reserved {
2325 assert!(ip!($s).is_reserved());
2327 assert!(!ip!($s).is_reserved());
2330 if ($mask & shared) == shared {
2331 assert!(ip!($s).is_shared());
2333 assert!(!ip!($s).is_shared());
2338 let unspec: u16 = 1 << 0;
2339 let loopback: u16 = 1 << 1;
2340 let private: u16 = 1 << 2;
2341 let link_local: u16 = 1 << 3;
2342 let global: u16 = 1 << 4;
2343 let multicast: u16 = 1 << 5;
2344 let broadcast: u16 = 1 << 6;
2345 let documentation: u16 = 1 << 7;
2346 let benchmarking: u16 = 1 << 8;
2347 let ietf_protocol_assignment: u16 = 1 << 9;
2348 let reserved: u16 = 1 << 10;
2349 let shared: u16 = 1 << 11;
2351 check!("0.0.0.0", unspec);
2354 check!("10.9.8.7", private);
2355 check!("127.1.2.3", loopback);
2356 check!("172.31.254.253", private);
2357 check!("169.254.253.242", link_local);
2358 check!("192.0.2.183", documentation);
2359 check!("192.1.2.183", global);
2360 check!("192.168.254.253", private);
2361 check!("198.51.100.0", documentation);
2362 check!("203.0.113.0", documentation);
2363 check!("203.2.113.0", global);
2364 check!("224.0.0.0", global | multicast);
2365 check!("239.255.255.255", global | multicast);
2366 check!("255.255.255.255", broadcast);
2367 check!("198.18.0.0", benchmarking);
2368 check!("198.18.54.2", benchmarking);
2369 check!("198.19.255.255", benchmarking);
2370 check!("192.0.0.0", ietf_protocol_assignment);
2371 check!("192.0.0.255", ietf_protocol_assignment);
2372 check!("192.0.0.100", ietf_protocol_assignment);
2373 check!("240.0.0.0", reserved);
2374 check!("251.54.1.76", reserved);
2375 check!("254.255.255.255", reserved);
2376 check!("100.64.0.0", shared);
2377 check!("100.127.255.255", shared);
2378 check!("100.100.100.0", shared);
2382 fn ipv6_properties() {
2385 Ipv6Addr::from_str($s).unwrap()
2389 macro_rules! check {
2390 ($s:expr, &[$($octet:expr),*], $mask:expr) => {
2391 assert_eq!($s, ip!($s).to_string());
2392 let octets = &[$($octet),*];
2393 assert_eq!(&ip!($s).octets(), octets);
2394 assert_eq!(Ipv6Addr::from(*octets), ip!($s));
2396 let unspecified: u16 = 1 << 0;
2397 let loopback: u16 = 1 << 1;
2398 let unique_local: u16 = 1 << 2;
2399 let global: u16 = 1 << 3;
2400 let unicast_link_local: u16 = 1 << 4;
2401 let unicast_link_local_strict: u16 = 1 << 5;
2402 let unicast_site_local: u16 = 1 << 6;
2403 let unicast_global: u16 = 1 << 7;
2404 let documentation: u16 = 1 << 8;
2405 let multicast_interface_local: u16 = 1 << 9;
2406 let multicast_link_local: u16 = 1 << 10;
2407 let multicast_realm_local: u16 = 1 << 11;
2408 let multicast_admin_local: u16 = 1 << 12;
2409 let multicast_site_local: u16 = 1 << 13;
2410 let multicast_organization_local: u16 = 1 << 14;
2411 let multicast_global: u16 = 1 << 15;
2412 let multicast: u16 = multicast_interface_local
2413 | multicast_admin_local
2415 | multicast_link_local
2416 | multicast_realm_local
2417 | multicast_site_local
2418 | multicast_organization_local;
2420 if ($mask & unspecified) == unspecified {
2421 assert!(ip!($s).is_unspecified());
2423 assert!(!ip!($s).is_unspecified());
2425 if ($mask & loopback) == loopback {
2426 assert!(ip!($s).is_loopback());
2428 assert!(!ip!($s).is_loopback());
2430 if ($mask & unique_local) == unique_local {
2431 assert!(ip!($s).is_unique_local());
2433 assert!(!ip!($s).is_unique_local());
2435 if ($mask & global) == global {
2436 assert!(ip!($s).is_global());
2438 assert!(!ip!($s).is_global());
2440 if ($mask & unicast_link_local) == unicast_link_local {
2441 assert!(ip!($s).is_unicast_link_local());
2443 assert!(!ip!($s).is_unicast_link_local());
2445 if ($mask & unicast_link_local_strict) == unicast_link_local_strict {
2446 assert!(ip!($s).is_unicast_link_local_strict());
2448 assert!(!ip!($s).is_unicast_link_local_strict());
2450 if ($mask & unicast_site_local) == unicast_site_local {
2451 assert!(ip!($s).is_unicast_site_local());
2453 assert!(!ip!($s).is_unicast_site_local());
2455 if ($mask & unicast_global) == unicast_global {
2456 assert!(ip!($s).is_unicast_global());
2458 assert!(!ip!($s).is_unicast_global());
2460 if ($mask & documentation) == documentation {
2461 assert!(ip!($s).is_documentation());
2463 assert!(!ip!($s).is_documentation());
2465 if ($mask & multicast) != 0 {
2466 assert!(ip!($s).multicast_scope().is_some());
2467 assert!(ip!($s).is_multicast());
2469 assert!(ip!($s).multicast_scope().is_none());
2470 assert!(!ip!($s).is_multicast());
2472 if ($mask & multicast_interface_local) == multicast_interface_local {
2473 assert_eq!(ip!($s).multicast_scope().unwrap(),
2474 Ipv6MulticastScope::InterfaceLocal);
2476 if ($mask & multicast_link_local) == multicast_link_local {
2477 assert_eq!(ip!($s).multicast_scope().unwrap(),
2478 Ipv6MulticastScope::LinkLocal);
2480 if ($mask & multicast_realm_local) == multicast_realm_local {
2481 assert_eq!(ip!($s).multicast_scope().unwrap(),
2482 Ipv6MulticastScope::RealmLocal);
2484 if ($mask & multicast_admin_local) == multicast_admin_local {
2485 assert_eq!(ip!($s).multicast_scope().unwrap(),
2486 Ipv6MulticastScope::AdminLocal);
2488 if ($mask & multicast_site_local) == multicast_site_local {
2489 assert_eq!(ip!($s).multicast_scope().unwrap(),
2490 Ipv6MulticastScope::SiteLocal);
2492 if ($mask & multicast_organization_local) == multicast_organization_local {
2493 assert_eq!(ip!($s).multicast_scope().unwrap(),
2494 Ipv6MulticastScope::OrganizationLocal);
2496 if ($mask & multicast_global) == multicast_global {
2497 assert_eq!(ip!($s).multicast_scope().unwrap(),
2498 Ipv6MulticastScope::Global);
2503 let unspecified: u16 = 1 << 0;
2504 let loopback: u16 = 1 << 1;
2505 let unique_local: u16 = 1 << 2;
2506 let global: u16 = 1 << 3;
2507 let unicast_link_local: u16 = 1 << 4;
2508 let unicast_link_local_strict: u16 = 1 << 5;
2509 let unicast_site_local: u16 = 1 << 6;
2510 let unicast_global: u16 = 1 << 7;
2511 let documentation: u16 = 1 << 8;
2512 let multicast_interface_local: u16 = 1 << 9;
2513 let multicast_link_local: u16 = 1 << 10;
2514 let multicast_realm_local: u16 = 1 << 11;
2515 let multicast_admin_local: u16 = 1 << 12;
2516 let multicast_site_local: u16 = 1 << 13;
2517 let multicast_organization_local: u16 = 1 << 14;
2518 let multicast_global: u16 = 1 << 15;
2520 check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);
2522 check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
2526 &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
2527 global | unicast_global
2530 check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
2532 check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
2536 &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2542 &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2548 &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2549 unicast_link_local | unicast_link_local_strict
2554 &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2560 &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2565 "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
2567 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2574 "fe80::ffff:ffff:ffff:ffff",
2576 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2579 unicast_link_local | unicast_link_local_strict
2584 &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
2590 &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2591 unicast_site_local | unicast_global | global
2596 &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2597 multicast_interface_local
2602 &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2603 multicast_link_local
2608 &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2609 multicast_realm_local
2614 &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2615 multicast_admin_local
2620 &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2621 multicast_site_local
2626 &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2627 multicast_organization_local
2632 &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2633 multicast_global | global
2637 "2001:db8:85a3::8a2e:370:7334",
2638 &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
2643 "102:304:506:708:90a:b0c:d0e:f10",
2644 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
2645 global | unicast_global
2650 fn to_socket_addr_socketaddr() {
2651 let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
2652 assert_eq!(Ok(vec![a]), tsa(a));
2656 fn test_ipv4_to_int() {
2657 let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
2658 assert_eq!(u32::from(a), 0x11223344);
2662 fn test_int_to_ipv4() {
2663 let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
2664 assert_eq!(Ipv4Addr::from(0x11223344), a);
2668 fn test_ipv6_to_int() {
2669 let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
2670 assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
2674 fn test_int_to_ipv6() {
2675 let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
2676 assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
2680 fn ipv4_from_constructors() {
2681 assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
2682 assert!(Ipv4Addr::LOCALHOST.is_loopback());
2683 assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
2684 assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
2685 assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
2686 assert!(Ipv4Addr::BROADCAST.is_broadcast());
2690 fn ipv6_from_contructors() {
2691 assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
2692 assert!(Ipv6Addr::LOCALHOST.is_loopback());
2693 assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
2694 assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
2698 fn ipv4_from_octets() {
2699 assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
2703 fn ipv6_from_segments() {
2705 Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
2706 let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
2707 assert_eq!(new, from_u16s);
2711 fn ipv6_from_octets() {
2713 Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
2714 let from_u8s = Ipv6Addr::from([
2715 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
2718 assert_eq!(from_u16s, from_u8s);
2723 let v41 = Ipv4Addr::new(100, 64, 3, 3);
2724 let v42 = Ipv4Addr::new(192, 0, 2, 2);
2725 let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
2726 let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
2730 assert_eq!(v41, IpAddr::V4(v41));
2731 assert_eq!(v61, IpAddr::V6(v61));
2732 assert!(v41 != IpAddr::V4(v42));
2733 assert!(v61 != IpAddr::V6(v62));
2735 assert!(v41 < IpAddr::V4(v42));
2736 assert!(v61 < IpAddr::V6(v62));
2737 assert!(IpAddr::V4(v41) < v42);
2738 assert!(IpAddr::V6(v61) < v62);
2740 assert!(v41 < IpAddr::V6(v61));
2741 assert!(IpAddr::V4(v41) < v61);
2746 let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
2747 assert!(ip.is_ipv4());
2748 assert!(!ip.is_ipv6());
2753 let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
2754 assert!(!ip.is_ipv4());
2755 assert!(ip.is_ipv6());