1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 #![unstable(feature = "ip", reason = "extra functionality has not been \
12 scrutinized to the level that it should \
19 use sys::net::netc as c;
20 use sys_common::{AsInner, FromInner};
22 /// An IP address, either IPv4 or IPv6.
24 /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
25 /// respective documentation for more details.
27 /// The size of an `IpAddr` instance may vary depending on the target operating
30 /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
31 /// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
36 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
38 /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
39 /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
41 /// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
42 /// assert_eq!("::1".parse(), Ok(localhost_v6));
44 /// assert_eq!(localhost_v4.is_ipv6(), false);
45 /// assert_eq!(localhost_v4.is_ipv4(), true);
47 #[stable(feature = "ip_addr", since = "1.7.0")]
48 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
51 #[stable(feature = "ip_addr", since = "1.7.0")]
52 V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
54 #[stable(feature = "ip_addr", since = "1.7.0")]
55 V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
60 /// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
61 /// They are usually represented as four octets.
63 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
65 /// The size of an `Ipv4Addr` struct may vary depending on the target operating
68 /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
69 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
71 /// # Textual representation
73 /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
74 /// notation, divided by `.` (this is called "dot-decimal notation").
76 /// [`FromStr`]: ../../std/str/trait.FromStr.html
81 /// use std::net::Ipv4Addr;
83 /// let localhost = Ipv4Addr::new(127, 0, 0, 1);
84 /// assert_eq!("127.0.0.1".parse(), Ok(localhost));
85 /// assert_eq!(localhost.is_loopback(), true);
88 #[stable(feature = "rust1", since = "1.0.0")]
95 /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
96 /// They are usually represented as eight 16-bit segments.
98 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
100 /// The size of an `Ipv6Addr` struct may vary depending on the target operating
103 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
104 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
106 /// # Textual representation
108 /// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
109 /// an IPv6 address in text, but in general, each segments is written in hexadecimal
110 /// notation, and segments are separated by `:`. For more information, see
113 /// [`FromStr`]: ../../std/str/trait.FromStr.html
114 /// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
119 /// use std::net::Ipv6Addr;
121 /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
122 /// assert_eq!("::1".parse(), Ok(localhost));
123 /// assert_eq!(localhost.is_loopback(), true);
126 #[stable(feature = "rust1", since = "1.0.0")]
127 pub struct Ipv6Addr {
131 #[allow(missing_docs)]
132 #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
133 pub enum Ipv6MulticastScope {
144 /// Returns [`true`] for the special 'unspecified' address.
146 /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and
147 /// [`Ipv6Addr::is_unspecified`][IPv6] for more details.
149 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
150 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
151 /// [`true`]: ../../std/primitive.bool.html
156 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
158 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
159 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
161 #[stable(feature = "ip_shared", since = "1.12.0")]
162 pub fn is_unspecified(&self) -> bool {
164 IpAddr::V4(ref a) => a.is_unspecified(),
165 IpAddr::V6(ref a) => a.is_unspecified(),
169 /// Returns [`true`] if this is a loopback address.
171 /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and
172 /// [`Ipv6Addr::is_loopback`][IPv6] for more details.
174 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
175 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
176 /// [`true`]: ../../std/primitive.bool.html
181 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
183 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
184 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
186 #[stable(feature = "ip_shared", since = "1.12.0")]
187 pub fn is_loopback(&self) -> bool {
189 IpAddr::V4(ref a) => a.is_loopback(),
190 IpAddr::V6(ref a) => a.is_loopback(),
194 /// Returns [`true`] if the address appears to be globally routable.
196 /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and
197 /// [`Ipv6Addr::is_global`][IPv6] for more details.
199 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
200 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
201 /// [`true`]: ../../std/primitive.bool.html
208 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
211 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
212 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(),
216 pub fn is_global(&self) -> bool {
218 IpAddr::V4(ref a) => a.is_global(),
219 IpAddr::V6(ref a) => a.is_global(),
223 /// Returns [`true`] if this is a multicast address.
225 /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and
226 /// [`Ipv6Addr::is_multicast`][IPv6] for more details.
228 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
229 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
230 /// [`true`]: ../../std/primitive.bool.html
235 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
237 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
238 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
240 #[stable(feature = "ip_shared", since = "1.12.0")]
241 pub fn is_multicast(&self) -> bool {
243 IpAddr::V4(ref a) => a.is_multicast(),
244 IpAddr::V6(ref a) => a.is_multicast(),
248 /// Returns [`true`] if this address is in a range designated for documentation.
250 /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and
251 /// [`Ipv6Addr::is_documentation`][IPv6] for more details.
253 /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
254 /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
255 /// [`true`]: ../../std/primitive.bool.html
262 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
265 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
266 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0))
267 /// .is_documentation(), true);
270 pub fn is_documentation(&self) -> bool {
272 IpAddr::V4(ref a) => a.is_documentation(),
273 IpAddr::V6(ref a) => a.is_documentation(),
277 /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise.
279 /// [`true`]: ../../std/primitive.bool.html
280 /// [`false`]: ../../std/primitive.bool.html
281 /// [IPv4 address]: #variant.V4
286 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
289 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
290 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(),
294 #[stable(feature = "ipaddr_checker", since = "1.16.0")]
295 pub fn is_ipv4(&self) -> bool {
297 IpAddr::V4(_) => true,
298 IpAddr::V6(_) => false,
302 /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
304 /// [`true`]: ../../std/primitive.bool.html
305 /// [`false`]: ../../std/primitive.bool.html
306 /// [IPv6 address]: #variant.V6
311 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
314 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
315 /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(),
319 #[stable(feature = "ipaddr_checker", since = "1.16.0")]
320 pub fn is_ipv6(&self) -> bool {
322 IpAddr::V4(_) => false,
323 IpAddr::V6(_) => true,
329 /// Creates a new IPv4 address from four eight-bit octets.
331 /// The result will represent the IP address `a`.`b`.`c`.`d`.
336 /// use std::net::Ipv4Addr;
338 /// let addr = Ipv4Addr::new(127, 0, 0, 1);
340 #[stable(feature = "rust1", since = "1.0.0")]
341 #[rustc_const_unstable(feature = "const_ip")]
342 pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
355 /// An IPv4 address with the address pointing to localhost: 127.0.0.1.
360 /// #![feature(ip_constructors)]
361 /// use std::net::Ipv4Addr;
363 /// let addr = Ipv4Addr::LOCALHOST;
364 /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
366 #[unstable(feature = "ip_constructors",
367 reason = "requires greater scrutiny before stabilization",
369 pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
371 /// An IPv4 address representing an unspecified address: 0.0.0.0
376 /// #![feature(ip_constructors)]
377 /// use std::net::Ipv4Addr;
379 /// let addr = Ipv4Addr::UNSPECIFIED;
380 /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
382 #[unstable(feature = "ip_constructors",
383 reason = "requires greater scrutiny before stabilization",
385 pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
387 /// An IPv4 address representing the broadcast address: 255.255.255.255
392 /// #![feature(ip_constructors)]
393 /// use std::net::Ipv4Addr;
395 /// let addr = Ipv4Addr::BROADCAST;
396 /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
398 #[unstable(feature = "ip_constructors",
399 reason = "requires greater scrutiny before stabilization",
401 pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
403 /// Returns the four eight-bit integers that make up this address.
408 /// use std::net::Ipv4Addr;
410 /// let addr = Ipv4Addr::new(127, 0, 0, 1);
411 /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
413 #[stable(feature = "rust1", since = "1.0.0")]
414 pub fn octets(&self) -> [u8; 4] {
415 let bits = u32::from_be(self.inner.s_addr);
416 [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
419 /// Returns [`true`] for the special 'unspecified' address (0.0.0.0).
421 /// This property is defined in _UNIX Network Programming, Second Edition_,
422 /// W. Richard Stevens, p. 891; see also [ip7].
424 /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
425 /// [`true`]: ../../std/primitive.bool.html
430 /// use std::net::Ipv4Addr;
432 /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
433 /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
435 #[stable(feature = "ip_shared", since = "1.12.0")]
436 pub fn is_unspecified(&self) -> bool {
437 self.inner.s_addr == 0
440 /// Returns [`true`] if this is a loopback address (127.0.0.0/8).
442 /// This property is defined by [IETF RFC 1122].
444 /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
445 /// [`true`]: ../../std/primitive.bool.html
450 /// use std::net::Ipv4Addr;
452 /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
453 /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
455 #[stable(since = "1.7.0", feature = "ip_17")]
456 pub fn is_loopback(&self) -> bool {
457 self.octets()[0] == 127
460 /// Returns [`true`] if this is a private address.
462 /// The private address ranges are defined in [IETF RFC 1918] and include:
468 /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
469 /// [`true`]: ../../std/primitive.bool.html
474 /// use std::net::Ipv4Addr;
476 /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
477 /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
478 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
479 /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
480 /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
481 /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
482 /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
484 #[stable(since = "1.7.0", feature = "ip_17")]
485 pub fn is_private(&self) -> bool {
486 match (self.octets()[0], self.octets()[1]) {
488 (172, b) if b >= 16 && b <= 31 => true,
494 /// Returns [`true`] if the address is link-local (169.254.0.0/16).
496 /// This property is defined by [IETF RFC 3927].
498 /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
499 /// [`true`]: ../../std/primitive.bool.html
504 /// use std::net::Ipv4Addr;
506 /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
507 /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
508 /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
510 #[stable(since = "1.7.0", feature = "ip_17")]
511 pub fn is_link_local(&self) -> bool {
512 self.octets()[0] == 169 && self.octets()[1] == 254
515 /// Returns [`true`] if the address appears to be globally routable.
516 /// See [iana-ipv4-special-registry][ipv4-sr].
518 /// The following return false:
520 /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16)
521 /// - the loopback address (127.0.0.0/8)
522 /// - the link-local address (169.254.0.0/16)
523 /// - the broadcast address (255.255.255.255/32)
524 /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
525 /// - the unspecified address (0.0.0.0)
527 /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
528 /// [`true`]: ../../std/primitive.bool.html
535 /// use std::net::Ipv4Addr;
538 /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
539 /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
540 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
541 /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
542 /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
545 pub fn is_global(&self) -> bool {
546 !self.is_private() && !self.is_loopback() && !self.is_link_local() &&
547 !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified()
550 /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
552 /// Multicast addresses have a most significant octet between 224 and 239,
553 /// and is defined by [IETF RFC 5771].
555 /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
556 /// [`true`]: ../../std/primitive.bool.html
561 /// use std::net::Ipv4Addr;
563 /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
564 /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
565 /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
567 #[stable(since = "1.7.0", feature = "ip_17")]
568 pub fn is_multicast(&self) -> bool {
569 self.octets()[0] >= 224 && self.octets()[0] <= 239
572 /// Returns [`true`] if this is a broadcast address (255.255.255.255).
574 /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
576 /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
577 /// [`true`]: ../../std/primitive.bool.html
582 /// use std::net::Ipv4Addr;
584 /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
585 /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
587 #[stable(since = "1.7.0", feature = "ip_17")]
588 pub fn is_broadcast(&self) -> bool {
589 self == &Self::BROADCAST
592 /// Returns [`true`] if this address is in a range designated for documentation.
594 /// This is defined in [IETF RFC 5737]:
596 /// - 192.0.2.0/24 (TEST-NET-1)
597 /// - 198.51.100.0/24 (TEST-NET-2)
598 /// - 203.0.113.0/24 (TEST-NET-3)
600 /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
601 /// [`true`]: ../../std/primitive.bool.html
606 /// use std::net::Ipv4Addr;
608 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
609 /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
610 /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
611 /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
613 #[stable(since = "1.7.0", feature = "ip_17")]
614 pub fn is_documentation(&self) -> bool {
615 match(self.octets()[0], self.octets()[1], self.octets()[2], self.octets()[3]) {
616 (192, 0, 2, _) => true,
617 (198, 51, 100, _) => true,
618 (203, 0, 113, _) => true,
623 /// Converts this address to an IPv4-compatible [IPv6 address].
625 /// a.b.c.d becomes ::a.b.c.d
627 /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
632 /// use std::net::{Ipv4Addr, Ipv6Addr};
634 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
635 /// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767));
637 #[stable(feature = "rust1", since = "1.0.0")]
638 pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
639 Ipv6Addr::new(0, 0, 0, 0, 0, 0,
640 ((self.octets()[0] as u16) << 8) | self.octets()[1] as u16,
641 ((self.octets()[2] as u16) << 8) | self.octets()[3] as u16)
644 /// Converts this address to an IPv4-mapped [IPv6 address].
646 /// a.b.c.d becomes ::ffff:a.b.c.d
648 /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
653 /// use std::net::{Ipv4Addr, Ipv6Addr};
655 /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
656 /// Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
658 #[stable(feature = "rust1", since = "1.0.0")]
659 pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
660 Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff,
661 ((self.octets()[0] as u16) << 8) | self.octets()[1] as u16,
662 ((self.octets()[2] as u16) << 8) | self.octets()[3] as u16)
666 #[stable(feature = "ip_addr", since = "1.7.0")]
667 impl fmt::Display for IpAddr {
668 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
670 IpAddr::V4(ref a) => a.fmt(fmt),
671 IpAddr::V6(ref a) => a.fmt(fmt),
676 #[stable(feature = "ip_from_ip", since = "1.16.0")]
677 impl From<Ipv4Addr> for IpAddr {
678 fn from(ipv4: Ipv4Addr) -> IpAddr {
683 #[stable(feature = "ip_from_ip", since = "1.16.0")]
684 impl From<Ipv6Addr> for IpAddr {
685 fn from(ipv6: Ipv6Addr) -> IpAddr {
690 #[stable(feature = "rust1", since = "1.0.0")]
691 impl fmt::Display for Ipv4Addr {
692 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
693 let octets = self.octets();
694 write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
698 #[stable(feature = "rust1", since = "1.0.0")]
699 impl fmt::Debug for Ipv4Addr {
700 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
701 fmt::Display::fmt(self, fmt)
705 #[stable(feature = "rust1", since = "1.0.0")]
706 impl Clone for Ipv4Addr {
707 fn clone(&self) -> Ipv4Addr { *self }
710 #[stable(feature = "rust1", since = "1.0.0")]
711 impl PartialEq for Ipv4Addr {
712 fn eq(&self, other: &Ipv4Addr) -> bool {
713 self.inner.s_addr == other.inner.s_addr
717 #[stable(feature = "ip_cmp", since = "1.16.0")]
718 impl PartialEq<Ipv4Addr> for IpAddr {
719 fn eq(&self, other: &Ipv4Addr) -> bool {
721 IpAddr::V4(ref v4) => v4 == other,
722 IpAddr::V6(_) => false,
727 #[stable(feature = "ip_cmp", since = "1.16.0")]
728 impl PartialEq<IpAddr> for Ipv4Addr {
729 fn eq(&self, other: &IpAddr) -> bool {
731 IpAddr::V4(ref v4) => self == v4,
732 IpAddr::V6(_) => false,
737 #[stable(feature = "rust1", since = "1.0.0")]
738 impl Eq for Ipv4Addr {}
740 #[stable(feature = "rust1", since = "1.0.0")]
741 impl hash::Hash for Ipv4Addr {
742 fn hash<H: hash::Hasher>(&self, s: &mut H) {
743 // `inner` is #[repr(packed)], so we need to copy `s_addr`.
744 {self.inner.s_addr}.hash(s)
748 #[stable(feature = "rust1", since = "1.0.0")]
749 impl PartialOrd for Ipv4Addr {
750 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
751 Some(self.cmp(other))
755 #[stable(feature = "ip_cmp", since = "1.16.0")]
756 impl PartialOrd<Ipv4Addr> for IpAddr {
757 fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
759 IpAddr::V4(ref v4) => v4.partial_cmp(other),
760 IpAddr::V6(_) => Some(Ordering::Greater),
765 #[stable(feature = "ip_cmp", since = "1.16.0")]
766 impl PartialOrd<IpAddr> for Ipv4Addr {
767 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
769 IpAddr::V4(ref v4) => self.partial_cmp(v4),
770 IpAddr::V6(_) => Some(Ordering::Less),
775 #[stable(feature = "rust1", since = "1.0.0")]
776 impl Ord for Ipv4Addr {
777 fn cmp(&self, other: &Ipv4Addr) -> Ordering {
778 u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
782 impl AsInner<c::in_addr> for Ipv4Addr {
783 fn as_inner(&self) -> &c::in_addr { &self.inner }
785 impl FromInner<c::in_addr> for Ipv4Addr {
786 fn from_inner(addr: c::in_addr) -> Ipv4Addr {
787 Ipv4Addr { inner: addr }
791 #[stable(feature = "ip_u32", since = "1.1.0")]
792 impl From<Ipv4Addr> for u32 {
793 /// Convert an `Ipv4Addr` into a host byte order `u32`.
798 /// use std::net::Ipv4Addr;
800 /// let addr = Ipv4Addr::new(13, 12, 11, 10);
801 /// assert_eq!(0x0d0c0b0au32, u32::from(addr));
803 fn from(ip: Ipv4Addr) -> u32 {
804 let ip = ip.octets();
805 ((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32)
809 #[stable(feature = "ip_u32", since = "1.1.0")]
810 impl From<u32> for Ipv4Addr {
811 /// Convert a host byte order `u32` into an `Ipv4Addr`.
816 /// use std::net::Ipv4Addr;
818 /// let addr = Ipv4Addr::from(0x0d0c0b0au32);
819 /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
821 fn from(ip: u32) -> Ipv4Addr {
822 Ipv4Addr::new((ip >> 24) as u8, (ip >> 16) as u8, (ip >> 8) as u8, ip as u8)
826 #[stable(feature = "from_slice_v4", since = "1.9.0")]
827 impl From<[u8; 4]> for Ipv4Addr {
831 /// use std::net::Ipv4Addr;
833 /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
834 /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
836 fn from(octets: [u8; 4]) -> Ipv4Addr {
837 Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
841 #[stable(feature = "ip_from_slice", since = "1.17.0")]
842 impl From<[u8; 4]> for IpAddr {
843 /// Create an `IpAddr::V4` from a four element byte array.
848 /// use std::net::{IpAddr, Ipv4Addr};
850 /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
851 /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
853 fn from(octets: [u8; 4]) -> IpAddr {
854 IpAddr::V4(Ipv4Addr::from(octets))
859 /// Creates a new IPv6 address from eight 16-bit segments.
861 /// The result will represent the IP address a:b:c:d:e:f:g:h.
866 /// use std::net::Ipv6Addr;
868 /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
870 #[stable(feature = "rust1", since = "1.0.0")]
871 #[rustc_const_unstable(feature = "const_ip")]
872 pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16,
873 g: u16, h: u16) -> Ipv6Addr {
877 (a >> 8) as u8, a as u8,
878 (b >> 8) as u8, b as u8,
879 (c >> 8) as u8, c as u8,
880 (d >> 8) as u8, d as u8,
881 (e >> 8) as u8, e as u8,
882 (f >> 8) as u8, f as u8,
883 (g >> 8) as u8, g as u8,
884 (h >> 8) as u8, h as u8
891 /// An IPv6 address representing localhost: `::1`.
896 /// #![feature(ip_constructors)]
897 /// use std::net::Ipv6Addr;
899 /// let addr = Ipv6Addr::LOCALHOST;
900 /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
902 #[unstable(feature = "ip_constructors",
903 reason = "requires greater scrutiny before stabilization",
905 pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
907 /// An IPv6 address representing the unspecified address: `::`
912 /// #![feature(ip_constructors)]
913 /// use std::net::Ipv6Addr;
915 /// let addr = Ipv6Addr::UNSPECIFIED;
916 /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
918 #[unstable(feature = "ip_constructors",
919 reason = "requires greater scrutiny before stabilization",
921 pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
923 /// Returns the eight 16-bit segments that make up this address.
928 /// use std::net::Ipv6Addr;
930 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
931 /// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
933 #[stable(feature = "rust1", since = "1.0.0")]
934 pub fn segments(&self) -> [u16; 8] {
935 let arr = &self.inner.s6_addr;
937 (arr[0] as u16) << 8 | (arr[1] as u16),
938 (arr[2] as u16) << 8 | (arr[3] as u16),
939 (arr[4] as u16) << 8 | (arr[5] as u16),
940 (arr[6] as u16) << 8 | (arr[7] as u16),
941 (arr[8] as u16) << 8 | (arr[9] as u16),
942 (arr[10] as u16) << 8 | (arr[11] as u16),
943 (arr[12] as u16) << 8 | (arr[13] as u16),
944 (arr[14] as u16) << 8 | (arr[15] as u16),
948 /// Returns [`true`] for the special 'unspecified' address (::).
950 /// This property is defined in [IETF RFC 4291].
952 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
953 /// [`true`]: ../../std/primitive.bool.html
958 /// use std::net::Ipv6Addr;
960 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
961 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
963 #[stable(since = "1.7.0", feature = "ip_17")]
964 pub fn is_unspecified(&self) -> bool {
965 self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
968 /// Returns [`true`] if this is a loopback address (::1).
970 /// This property is defined in [IETF RFC 4291].
972 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
973 /// [`true`]: ../../std/primitive.bool.html
978 /// use std::net::Ipv6Addr;
980 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
981 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
983 #[stable(since = "1.7.0", feature = "ip_17")]
984 pub fn is_loopback(&self) -> bool {
985 self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
988 /// Returns [`true`] if the address appears to be globally routable.
990 /// The following return [`false`]:
992 /// - the loopback address
993 /// - link-local, site-local, and unique local unicast addresses
994 /// - interface-, link-, realm-, admin- and site-local multicast addresses
996 /// [`true`]: ../../std/primitive.bool.html
997 /// [`false`]: ../../std/primitive.bool.html
1004 /// use std::net::Ipv6Addr;
1007 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
1008 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
1009 /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
1012 pub fn is_global(&self) -> bool {
1013 match self.multicast_scope() {
1014 Some(Ipv6MulticastScope::Global) => true,
1015 None => self.is_unicast_global(),
1020 /// Returns [`true`] if this is a unique local address (fc00::/7).
1022 /// This property is defined in [IETF RFC 4193].
1024 /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
1025 /// [`true`]: ../../std/primitive.bool.html
1032 /// use std::net::Ipv6Addr;
1035 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(),
1037 /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
1040 pub fn is_unique_local(&self) -> bool {
1041 (self.segments()[0] & 0xfe00) == 0xfc00
1044 /// Returns [`true`] if the address is unicast and link-local (fe80::/10).
1046 /// This property is defined in [IETF RFC 4291].
1048 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1049 /// [`true`]: ../../std/primitive.bool.html
1056 /// use std::net::Ipv6Addr;
1059 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(),
1061 /// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
1064 pub fn is_unicast_link_local(&self) -> bool {
1065 (self.segments()[0] & 0xffc0) == 0xfe80
1068 /// Returns [`true`] if this is a deprecated unicast site-local address
1071 /// [`true`]: ../../std/primitive.bool.html
1078 /// use std::net::Ipv6Addr;
1081 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(),
1083 /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
1086 pub fn is_unicast_site_local(&self) -> bool {
1087 (self.segments()[0] & 0xffc0) == 0xfec0
1090 /// Returns [`true`] if this is an address reserved for documentation
1091 /// (2001:db8::/32).
1093 /// This property is defined in [IETF RFC 3849].
1095 /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
1096 /// [`true`]: ../../std/primitive.bool.html
1103 /// use std::net::Ipv6Addr;
1106 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(),
1108 /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
1111 pub fn is_documentation(&self) -> bool {
1112 (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
1115 /// Returns [`true`] if the address is a globally routable unicast address.
1117 /// The following return false:
1119 /// - the loopback address
1120 /// - the link-local addresses
1121 /// - the (deprecated) site-local addresses
1122 /// - unique local addresses
1123 /// - the unspecified address
1124 /// - the address range reserved for documentation
1126 /// [`true`]: ../../std/primitive.bool.html
1133 /// use std::net::Ipv6Addr;
1136 /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
1137 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(),
1141 pub fn is_unicast_global(&self) -> bool {
1142 !self.is_multicast()
1143 && !self.is_loopback() && !self.is_unicast_link_local()
1144 && !self.is_unicast_site_local() && !self.is_unique_local()
1145 && !self.is_unspecified() && !self.is_documentation()
1148 /// Returns the address's multicast scope if the address is multicast.
1155 /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
1158 /// assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
1159 /// Some(Ipv6MulticastScope::Global));
1160 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
1163 pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
1164 if self.is_multicast() {
1165 match self.segments()[0] & 0x000f {
1166 1 => Some(Ipv6MulticastScope::InterfaceLocal),
1167 2 => Some(Ipv6MulticastScope::LinkLocal),
1168 3 => Some(Ipv6MulticastScope::RealmLocal),
1169 4 => Some(Ipv6MulticastScope::AdminLocal),
1170 5 => Some(Ipv6MulticastScope::SiteLocal),
1171 8 => Some(Ipv6MulticastScope::OrganizationLocal),
1172 14 => Some(Ipv6MulticastScope::Global),
1180 /// Returns [`true`] if this is a multicast address (ff00::/8).
1182 /// This property is defined by [IETF RFC 4291].
1184 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1185 /// [`true`]: ../../std/primitive.bool.html
1190 /// use std::net::Ipv6Addr;
1192 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
1193 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
1195 #[stable(since = "1.7.0", feature = "ip_17")]
1196 pub fn is_multicast(&self) -> bool {
1197 (self.segments()[0] & 0xff00) == 0xff00
1200 /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
1201 /// neither IPv4-compatible or IPv4-mapped.
1203 /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
1205 /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
1206 /// [`None`]: ../../std/option/enum.Option.html#variant.None
1211 /// use std::net::{Ipv4Addr, Ipv6Addr};
1213 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
1214 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
1215 /// Some(Ipv4Addr::new(192, 10, 2, 255)));
1216 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
1217 /// Some(Ipv4Addr::new(0, 0, 0, 1)));
1219 #[stable(feature = "rust1", since = "1.0.0")]
1220 pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
1221 match self.segments() {
1222 [0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => {
1223 Some(Ipv4Addr::new((g >> 8) as u8, g as u8,
1224 (h >> 8) as u8, h as u8))
1230 /// Returns the sixteen eight-bit integers the IPv6 address consists of.
1233 /// use std::net::Ipv6Addr;
1235 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
1236 /// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
1238 #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
1239 pub fn octets(&self) -> [u8; 16] {
1244 #[stable(feature = "rust1", since = "1.0.0")]
1245 impl fmt::Display for Ipv6Addr {
1246 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1247 match self.segments() {
1248 // We need special cases for :: and ::1, otherwise they're formatted
1250 [0, 0, 0, 0, 0, 0, 0, 0] => write!(fmt, "::"),
1251 [0, 0, 0, 0, 0, 0, 0, 1] => write!(fmt, "::1"),
1252 // Ipv4 Compatible address
1253 [0, 0, 0, 0, 0, 0, g, h] => {
1254 write!(fmt, "::{}.{}.{}.{}", (g >> 8) as u8, g as u8,
1255 (h >> 8) as u8, h as u8)
1257 // Ipv4-Mapped address
1258 [0, 0, 0, 0, 0, 0xffff, g, h] => {
1259 write!(fmt, "::ffff:{}.{}.{}.{}", (g >> 8) as u8, g as u8,
1260 (h >> 8) as u8, h as u8)
1263 fn find_zero_slice(segments: &[u16; 8]) -> (usize, usize) {
1264 let mut longest_span_len = 0;
1265 let mut longest_span_at = 0;
1266 let mut cur_span_len = 0;
1267 let mut cur_span_at = 0;
1270 if segments[i] == 0 {
1271 if cur_span_len == 0 {
1277 if cur_span_len > longest_span_len {
1278 longest_span_len = cur_span_len;
1279 longest_span_at = cur_span_at;
1287 (longest_span_at, longest_span_len)
1290 let (zeros_at, zeros_len) = find_zero_slice(&self.segments());
1293 fn fmt_subslice(segments: &[u16], fmt: &mut fmt::Formatter) -> fmt::Result {
1294 if !segments.is_empty() {
1295 write!(fmt, "{:x}", segments[0])?;
1296 for &seg in &segments[1..] {
1297 write!(fmt, ":{:x}", seg)?;
1303 fmt_subslice(&self.segments()[..zeros_at], fmt)?;
1304 fmt.write_str("::")?;
1305 fmt_subslice(&self.segments()[zeros_at + zeros_len..], fmt)
1307 let &[a, b, c, d, e, f, g, h] = &self.segments();
1308 write!(fmt, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
1309 a, b, c, d, e, f, g, h)
1316 #[stable(feature = "rust1", since = "1.0.0")]
1317 impl fmt::Debug for Ipv6Addr {
1318 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1319 fmt::Display::fmt(self, fmt)
1323 #[stable(feature = "rust1", since = "1.0.0")]
1324 impl Clone for Ipv6Addr {
1325 fn clone(&self) -> Ipv6Addr { *self }
1328 #[stable(feature = "rust1", since = "1.0.0")]
1329 impl PartialEq for Ipv6Addr {
1330 fn eq(&self, other: &Ipv6Addr) -> bool {
1331 self.inner.s6_addr == other.inner.s6_addr
1335 #[stable(feature = "ip_cmp", since = "1.16.0")]
1336 impl PartialEq<IpAddr> for Ipv6Addr {
1337 fn eq(&self, other: &IpAddr) -> bool {
1339 IpAddr::V4(_) => false,
1340 IpAddr::V6(ref v6) => self == v6,
1345 #[stable(feature = "ip_cmp", since = "1.16.0")]
1346 impl PartialEq<Ipv6Addr> for IpAddr {
1347 fn eq(&self, other: &Ipv6Addr) -> bool {
1349 IpAddr::V4(_) => false,
1350 IpAddr::V6(ref v6) => v6 == other,
1355 #[stable(feature = "rust1", since = "1.0.0")]
1356 impl Eq for Ipv6Addr {}
1358 #[stable(feature = "rust1", since = "1.0.0")]
1359 impl hash::Hash for Ipv6Addr {
1360 fn hash<H: hash::Hasher>(&self, s: &mut H) {
1361 self.inner.s6_addr.hash(s)
1365 #[stable(feature = "rust1", since = "1.0.0")]
1366 impl PartialOrd for Ipv6Addr {
1367 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1368 Some(self.cmp(other))
1372 #[stable(feature = "ip_cmp", since = "1.16.0")]
1373 impl PartialOrd<Ipv6Addr> for IpAddr {
1374 fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1376 IpAddr::V4(_) => Some(Ordering::Less),
1377 IpAddr::V6(ref v6) => v6.partial_cmp(other),
1382 #[stable(feature = "ip_cmp", since = "1.16.0")]
1383 impl PartialOrd<IpAddr> for Ipv6Addr {
1384 fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
1386 IpAddr::V4(_) => Some(Ordering::Greater),
1387 IpAddr::V6(ref v6) => self.partial_cmp(v6),
1392 #[stable(feature = "rust1", since = "1.0.0")]
1393 impl Ord for Ipv6Addr {
1394 fn cmp(&self, other: &Ipv6Addr) -> Ordering {
1395 self.segments().cmp(&other.segments())
1399 impl AsInner<c::in6_addr> for Ipv6Addr {
1400 fn as_inner(&self) -> &c::in6_addr { &self.inner }
1402 impl FromInner<c::in6_addr> for Ipv6Addr {
1403 fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
1404 Ipv6Addr { inner: addr }
1408 #[stable(feature = "i128", since = "1.26.0")]
1409 impl From<Ipv6Addr> for u128 {
1410 fn from(ip: Ipv6Addr) -> u128 {
1411 let ip = ip.segments();
1412 ((ip[0] as u128) << 112) + ((ip[1] as u128) << 96) + ((ip[2] as u128) << 80) +
1413 ((ip[3] as u128) << 64) + ((ip[4] as u128) << 48) + ((ip[5] as u128) << 32) +
1414 ((ip[6] as u128) << 16) + (ip[7] as u128)
1417 #[stable(feature = "i128", since = "1.26.0")]
1418 impl From<u128> for Ipv6Addr {
1419 fn from(ip: u128) -> Ipv6Addr {
1421 (ip >> 112) as u16, (ip >> 96) as u16, (ip >> 80) as u16,
1422 (ip >> 64) as u16, (ip >> 48) as u16, (ip >> 32) as u16,
1423 (ip >> 16) as u16, ip as u16,
1428 #[stable(feature = "ipv6_from_octets", since = "1.9.0")]
1429 impl From<[u8; 16]> for Ipv6Addr {
1430 fn from(octets: [u8; 16]) -> Ipv6Addr {
1431 let inner = c::in6_addr { s6_addr: octets };
1432 Ipv6Addr::from_inner(inner)
1436 #[stable(feature = "ipv6_from_segments", since = "1.16.0")]
1437 impl From<[u16; 8]> for Ipv6Addr {
1438 fn from(segments: [u16; 8]) -> Ipv6Addr {
1439 let [a, b, c, d, e, f, g, h] = segments;
1440 Ipv6Addr::new(a, b, c, d, e, f, g, h)
1445 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1446 impl From<[u8; 16]> for IpAddr {
1447 /// Create an `IpAddr::V6` from a sixteen element byte array.
1452 /// use std::net::{IpAddr, Ipv6Addr};
1454 /// let addr = IpAddr::from([
1455 /// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1456 /// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1459 /// IpAddr::V6(Ipv6Addr::new(
1468 fn from(octets: [u8; 16]) -> IpAddr {
1469 IpAddr::V6(Ipv6Addr::from(octets))
1473 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1474 impl From<[u16; 8]> for IpAddr {
1475 /// Create an `IpAddr::V6` from an eight element 16-bit array.
1480 /// use std::net::{IpAddr, Ipv6Addr};
1482 /// let addr = IpAddr::from([
1483 /// 525u16, 524u16, 523u16, 522u16,
1484 /// 521u16, 520u16, 519u16, 518u16,
1487 /// IpAddr::V6(Ipv6Addr::new(
1496 fn from(segments: [u16; 8]) -> IpAddr {
1497 IpAddr::V6(Ipv6Addr::from(segments))
1501 // Tests for this module
1502 #[cfg(all(test, not(target_os = "emscripten")))]
1505 use net::Ipv6MulticastScope::*;
1506 use net::test::{tsa, sa6, sa4};
1509 fn test_from_str_ipv4() {
1510 assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
1511 assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
1512 assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
1515 let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
1516 assert_eq!(None, none);
1518 let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
1519 assert_eq!(None, none);
1521 let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
1522 assert_eq!(None, none);
1523 // no number between dots
1524 let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
1525 assert_eq!(None, none);
1529 fn test_from_str_ipv6() {
1530 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
1531 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
1533 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
1534 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
1536 assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
1537 "2a02:6b8::11:11".parse());
1540 let none: Option<Ipv6Addr> = "::00000".parse().ok();
1541 assert_eq!(None, none);
1543 let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
1544 assert_eq!(None, none);
1546 let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
1547 assert_eq!(None, none);
1549 let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
1550 assert_eq!(None, none);
1551 // two double colons
1552 let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
1553 assert_eq!(None, none);
1554 // `::` indicating zero groups of zeros
1555 let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
1556 assert_eq!(None, none);
1560 fn test_from_str_ipv4_in_ipv6() {
1561 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)),
1562 "::192.0.2.33".parse());
1563 assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
1564 "::FFFF:192.0.2.33".parse());
1565 assert_eq!(Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
1566 "64:ff9b::192.0.2.33".parse());
1567 assert_eq!(Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
1568 "2001:db8:122:c000:2:2100:192.0.2.33".parse());
1571 let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
1572 assert_eq!(None, none);
1573 // not enough groups
1574 let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok();
1575 assert_eq!(None, none);
1577 let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
1578 assert_eq!(None, none);
1582 fn test_from_str_socket_addr() {
1583 assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)),
1584 "77.88.21.11:80".parse());
1585 assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)),
1586 "77.88.21.11:80".parse());
1587 assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
1588 "[2a02:6b8:0:1::1]:53".parse());
1589 assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1,
1590 0, 0, 0, 1), 53, 0, 0)),
1591 "[2a02:6b8:0:1::1]:53".parse());
1592 assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
1593 "[::127.0.0.1]:22".parse());
1594 assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0,
1595 0x7F00, 1), 22, 0, 0)),
1596 "[::127.0.0.1]:22".parse());
1599 let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
1600 assert_eq!(None, none);
1602 let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
1603 assert_eq!(None, none);
1604 // wrong brackets around v4
1605 let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
1606 assert_eq!(None, none);
1607 // port out of range
1608 let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
1609 assert_eq!(None, none);
1613 fn ipv6_addr_to_string() {
1614 // ipv4-mapped address
1615 let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
1616 assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
1618 // ipv4-compatible address
1619 let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
1620 assert_eq!(a1.to_string(), "::192.0.2.128");
1622 // v6 address with no zero segments
1623 assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
1626 // reduce a single run of zeros
1627 assert_eq!("ae::ffff:102:304",
1628 Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string());
1630 // don't reduce just a single zero segment
1631 assert_eq!("1:2:3:4:5:6:0:8",
1632 Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
1635 assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
1638 assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
1641 assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
1643 // two runs of zeros, second one is longer
1644 assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
1646 // two runs of zeros, equal length
1647 assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
1652 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
1653 Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped());
1654 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
1655 Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible());
1660 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
1661 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)));
1662 assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
1663 Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)));
1664 assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
1669 fn ip_properties() {
1670 fn check4(octets: &[u8; 4], unspec: bool, loopback: bool,
1671 global: bool, multicast: bool, documentation: bool) {
1672 let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]));
1673 assert_eq!(ip.is_unspecified(), unspec);
1674 assert_eq!(ip.is_loopback(), loopback);
1675 assert_eq!(ip.is_global(), global);
1676 assert_eq!(ip.is_multicast(), multicast);
1677 assert_eq!(ip.is_documentation(), documentation);
1680 fn check6(str_addr: &str, unspec: bool, loopback: bool,
1681 global: bool, u_doc: bool, mcast: bool) {
1682 let ip = IpAddr::V6(str_addr.parse().unwrap());
1683 assert_eq!(ip.is_unspecified(), unspec);
1684 assert_eq!(ip.is_loopback(), loopback);
1685 assert_eq!(ip.is_global(), global);
1686 assert_eq!(ip.is_documentation(), u_doc);
1687 assert_eq!(ip.is_multicast(), mcast);
1690 // address unspec loopbk global multicast doc
1691 check4(&[0, 0, 0, 0], true, false, false, false, false);
1692 check4(&[0, 0, 0, 1], false, false, true, false, false);
1693 check4(&[0, 1, 0, 0], false, false, true, false, false);
1694 check4(&[10, 9, 8, 7], false, false, false, false, false);
1695 check4(&[127, 1, 2, 3], false, true, false, false, false);
1696 check4(&[172, 31, 254, 253], false, false, false, false, false);
1697 check4(&[169, 254, 253, 242], false, false, false, false, false);
1698 check4(&[192, 0, 2, 183], false, false, false, false, true);
1699 check4(&[192, 1, 2, 183], false, false, true, false, false);
1700 check4(&[192, 168, 254, 253], false, false, false, false, false);
1701 check4(&[198, 51, 100, 0], false, false, false, false, true);
1702 check4(&[203, 0, 113, 0], false, false, false, false, true);
1703 check4(&[203, 2, 113, 0], false, false, true, false, false);
1704 check4(&[224, 0, 0, 0], false, false, true, true, false);
1705 check4(&[239, 255, 255, 255], false, false, true, true, false);
1706 check4(&[255, 255, 255, 255], false, false, false, false, false);
1708 // address unspec loopbk global doc mcast
1709 check6("::", true, false, false, false, false);
1710 check6("::1", false, true, false, false, false);
1711 check6("::0.0.0.2", false, false, true, false, false);
1712 check6("1::", false, false, true, false, false);
1713 check6("fc00::", false, false, false, false, false);
1714 check6("fdff:ffff::", false, false, false, false, false);
1715 check6("fe80:ffff::", false, false, false, false, false);
1716 check6("febf:ffff::", false, false, false, false, false);
1717 check6("fec0::", false, false, false, false, false);
1718 check6("ff01::", false, false, false, false, true);
1719 check6("ff02::", false, false, false, false, true);
1720 check6("ff03::", false, false, false, false, true);
1721 check6("ff04::", false, false, false, false, true);
1722 check6("ff05::", false, false, false, false, true);
1723 check6("ff08::", false, false, false, false, true);
1724 check6("ff0e::", false, false, true, false, true);
1725 check6("2001:db8:85a3::8a2e:370:7334", false, false, false, true, false);
1726 check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true, false, false);
1730 fn ipv4_properties() {
1731 fn check(octets: &[u8; 4], unspec: bool, loopback: bool,
1732 private: bool, link_local: bool, global: bool,
1733 multicast: bool, broadcast: bool, documentation: bool) {
1734 let ip = Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]);
1735 assert_eq!(octets, &ip.octets());
1737 assert_eq!(ip.is_unspecified(), unspec);
1738 assert_eq!(ip.is_loopback(), loopback);
1739 assert_eq!(ip.is_private(), private);
1740 assert_eq!(ip.is_link_local(), link_local);
1741 assert_eq!(ip.is_global(), global);
1742 assert_eq!(ip.is_multicast(), multicast);
1743 assert_eq!(ip.is_broadcast(), broadcast);
1744 assert_eq!(ip.is_documentation(), documentation);
1747 // address unspec loopbk privt linloc global multicast brdcast doc
1748 check(&[0, 0, 0, 0], true, false, false, false, false, false, false, false);
1749 check(&[0, 0, 0, 1], false, false, false, false, true, false, false, false);
1750 check(&[0, 1, 0, 0], false, false, false, false, true, false, false, false);
1751 check(&[10, 9, 8, 7], false, false, true, false, false, false, false, false);
1752 check(&[127, 1, 2, 3], false, true, false, false, false, false, false, false);
1753 check(&[172, 31, 254, 253], false, false, true, false, false, false, false, false);
1754 check(&[169, 254, 253, 242], false, false, false, true, false, false, false, false);
1755 check(&[192, 0, 2, 183], false, false, false, false, false, false, false, true);
1756 check(&[192, 1, 2, 183], false, false, false, false, true, false, false, false);
1757 check(&[192, 168, 254, 253], false, false, true, false, false, false, false, false);
1758 check(&[198, 51, 100, 0], false, false, false, false, false, false, false, true);
1759 check(&[203, 0, 113, 0], false, false, false, false, false, false, false, true);
1760 check(&[203, 2, 113, 0], false, false, false, false, true, false, false, false);
1761 check(&[224, 0, 0, 0], false, false, false, false, true, true, false, false);
1762 check(&[239, 255, 255, 255], false, false, false, false, true, true, false, false);
1763 check(&[255, 255, 255, 255], false, false, false, false, false, false, true, false);
1767 fn ipv6_properties() {
1768 fn check(str_addr: &str, octets: &[u8; 16], unspec: bool, loopback: bool,
1769 unique_local: bool, global: bool,
1770 u_link_local: bool, u_site_local: bool, u_global: bool, u_doc: bool,
1771 m_scope: Option<Ipv6MulticastScope>) {
1772 let ip: Ipv6Addr = str_addr.parse().unwrap();
1773 assert_eq!(str_addr, ip.to_string());
1774 assert_eq!(&ip.octets(), octets);
1775 assert_eq!(Ipv6Addr::from(*octets), ip);
1777 assert_eq!(ip.is_unspecified(), unspec);
1778 assert_eq!(ip.is_loopback(), loopback);
1779 assert_eq!(ip.is_unique_local(), unique_local);
1780 assert_eq!(ip.is_global(), global);
1781 assert_eq!(ip.is_unicast_link_local(), u_link_local);
1782 assert_eq!(ip.is_unicast_site_local(), u_site_local);
1783 assert_eq!(ip.is_unicast_global(), u_global);
1784 assert_eq!(ip.is_documentation(), u_doc);
1785 assert_eq!(ip.multicast_scope(), m_scope);
1786 assert_eq!(ip.is_multicast(), m_scope.is_some());
1789 // unspec loopbk uniqlo global unill unisl uniglo doc mscope
1790 check("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1791 true, false, false, false, false, false, false, false, None);
1792 check("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
1793 false, true, false, false, false, false, false, false, None);
1794 check("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
1795 false, false, false, true, false, false, true, false, None);
1796 check("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1797 false, false, false, true, false, false, true, false, None);
1798 check("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1799 false, false, true, false, false, false, false, false, None);
1800 check("fdff:ffff::", &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1801 false, false, true, false, false, false, false, false, None);
1802 check("fe80:ffff::", &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1803 false, false, false, false, true, false, false, false, None);
1804 check("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1805 false, false, false, false, true, false, false, false, None);
1806 check("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1807 false, false, false, false, false, true, false, false, None);
1808 check("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1809 false, false, false, false, false, false, false, false, Some(InterfaceLocal));
1810 check("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1811 false, false, false, false, false, false, false, false, Some(LinkLocal));
1812 check("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1813 false, false, false, false, false, false, false, false, Some(RealmLocal));
1814 check("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1815 false, false, false, false, false, false, false, false, Some(AdminLocal));
1816 check("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1817 false, false, false, false, false, false, false, false, Some(SiteLocal));
1818 check("ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1819 false, false, false, false, false, false, false, false, Some(OrganizationLocal));
1820 check("ff0e::", &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1821 false, false, false, true, false, false, false, false, Some(Global));
1822 check("2001:db8:85a3::8a2e:370:7334",
1823 &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
1824 false, false, false, false, false, false, false, true, None);
1825 check("102:304:506:708:90a:b0c:d0e:f10",
1826 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
1827 false, false, false, true, false, false, true, false, None);
1831 fn to_socket_addr_socketaddr() {
1832 let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
1833 assert_eq!(Ok(vec![a]), tsa(a));
1837 fn test_ipv4_to_int() {
1838 let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
1839 assert_eq!(u32::from(a), 0x11223344);
1843 fn test_int_to_ipv4() {
1844 let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
1845 assert_eq!(Ipv4Addr::from(0x11223344), a);
1849 fn test_ipv6_to_int() {
1850 let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
1851 assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
1855 fn test_int_to_ipv6() {
1856 let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
1857 assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
1861 fn ipv4_from_constructors() {
1862 assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
1863 assert!(Ipv4Addr::LOCALHOST.is_loopback());
1864 assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
1865 assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
1866 assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
1867 assert!(Ipv4Addr::BROADCAST.is_broadcast());
1871 fn ipv6_from_contructors() {
1872 assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
1873 assert!(Ipv6Addr::LOCALHOST.is_loopback());
1874 assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
1875 assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
1879 fn ipv4_from_octets() {
1880 assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
1884 fn ipv6_from_segments() {
1885 let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677,
1886 0x8899, 0xaabb, 0xccdd, 0xeeff]);
1887 let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677,
1888 0x8899, 0xaabb, 0xccdd, 0xeeff);
1889 assert_eq!(new, from_u16s);
1893 fn ipv6_from_octets() {
1894 let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677,
1895 0x8899, 0xaabb, 0xccdd, 0xeeff]);
1896 let from_u8s = Ipv6Addr::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
1897 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]);
1898 assert_eq!(from_u16s, from_u8s);
1903 let v41 = Ipv4Addr::new(100, 64, 3, 3);
1904 let v42 = Ipv4Addr::new(192, 0, 2, 2);
1905 let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
1906 let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
1910 assert_eq!(v41, IpAddr::V4(v41));
1911 assert_eq!(v61, IpAddr::V6(v61));
1912 assert!(v41 != IpAddr::V4(v42));
1913 assert!(v61 != IpAddr::V6(v62));
1915 assert!(v41 < IpAddr::V4(v42));
1916 assert!(v61 < IpAddr::V6(v62));
1917 assert!(IpAddr::V4(v41) < v42);
1918 assert!(IpAddr::V6(v61) < v62);
1920 assert!(v41 < IpAddr::V6(v61));
1921 assert!(IpAddr::V4(v41) < v61);
1926 let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
1927 assert!(ip.is_ipv4());
1928 assert!(!ip.is_ipv6());
1933 let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
1934 assert!(!ip.is_ipv4());
1935 assert!(ip.is_ipv6());