]> git.lizzy.rs Git - rust.git/blob - src/libstd/net/ip.rs
Ensure `record_layout_for_printing()` is inlined.
[rust.git] / src / libstd / net / ip.rs
1 #![unstable(feature = "ip", reason = "extra functionality has not been \
2                                       scrutinized to the level that it should \
3                                       be to be stable",
4             issue = "27709")]
5
6 use cmp::Ordering;
7 use fmt;
8 use hash;
9 use sys::net::netc as c;
10 use sys_common::{AsInner, FromInner};
11
12 /// An IP address, either IPv4 or IPv6.
13 ///
14 /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
15 /// respective documentation for more details.
16 ///
17 /// The size of an `IpAddr` instance may vary depending on the target operating
18 /// system.
19 ///
20 /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
21 /// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
22 ///
23 /// # Examples
24 ///
25 /// ```
26 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
27 ///
28 /// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
29 /// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
30 ///
31 /// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
32 /// assert_eq!("::1".parse(), Ok(localhost_v6));
33 ///
34 /// assert_eq!(localhost_v4.is_ipv6(), false);
35 /// assert_eq!(localhost_v4.is_ipv4(), true);
36 /// ```
37 #[stable(feature = "ip_addr", since = "1.7.0")]
38 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
39 pub enum IpAddr {
40     /// An IPv4 address.
41     #[stable(feature = "ip_addr", since = "1.7.0")]
42     V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
43     /// An IPv6 address.
44     #[stable(feature = "ip_addr", since = "1.7.0")]
45     V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
46 }
47
48 /// An IPv4 address.
49 ///
50 /// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
51 /// They are usually represented as four octets.
52 ///
53 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
54 ///
55 /// The size of an `Ipv4Addr` struct may vary depending on the target operating
56 /// system.
57 ///
58 /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
59 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
60 ///
61 /// # Textual representation
62 ///
63 /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
64 /// notation, divided by `.` (this is called "dot-decimal notation").
65 ///
66 /// [`FromStr`]: ../../std/str/trait.FromStr.html
67 ///
68 /// # Examples
69 ///
70 /// ```
71 /// use std::net::Ipv4Addr;
72 ///
73 /// let localhost = Ipv4Addr::new(127, 0, 0, 1);
74 /// assert_eq!("127.0.0.1".parse(), Ok(localhost));
75 /// assert_eq!(localhost.is_loopback(), true);
76 /// ```
77 #[derive(Copy)]
78 #[stable(feature = "rust1", since = "1.0.0")]
79 pub struct Ipv4Addr {
80     inner: c::in_addr,
81 }
82
83 /// An IPv6 address.
84 ///
85 /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
86 /// They are usually represented as eight 16-bit segments.
87 ///
88 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
89 ///
90 /// The size of an `Ipv6Addr` struct may vary depending on the target operating
91 /// system.
92 ///
93 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
94 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
95 ///
96 /// # Textual representation
97 ///
98 /// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
99 /// an IPv6 address in text, but in general, each segments is written in hexadecimal
100 /// notation, and segments are separated by `:`. For more information, see
101 /// [IETF RFC 5952].
102 ///
103 /// [`FromStr`]: ../../std/str/trait.FromStr.html
104 /// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
105 ///
106 /// # Examples
107 ///
108 /// ```
109 /// use std::net::Ipv6Addr;
110 ///
111 /// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
112 /// assert_eq!("::1".parse(), Ok(localhost));
113 /// assert_eq!(localhost.is_loopback(), true);
114 /// ```
115 #[derive(Copy)]
116 #[stable(feature = "rust1", since = "1.0.0")]
117 pub struct Ipv6Addr {
118     inner: c::in6_addr,
119 }
120
121 #[allow(missing_docs)]
122 #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
123 pub enum Ipv6MulticastScope {
124     InterfaceLocal,
125     LinkLocal,
126     RealmLocal,
127     AdminLocal,
128     SiteLocal,
129     OrganizationLocal,
130     Global
131 }
132
133 impl IpAddr {
134     /// Returns [`true`] for the special 'unspecified' address.
135     ///
136     /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and
137     /// [`Ipv6Addr::is_unspecified`][IPv6] for more details.
138     ///
139     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
140     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
141     /// [`true`]: ../../std/primitive.bool.html
142     ///
143     /// # Examples
144     ///
145     /// ```
146     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
147     ///
148     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
149     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
150     /// ```
151     #[stable(feature = "ip_shared", since = "1.12.0")]
152     pub fn is_unspecified(&self) -> bool {
153         match self {
154             IpAddr::V4(ip) => ip.is_unspecified(),
155             IpAddr::V6(ip) => ip.is_unspecified(),
156         }
157     }
158
159     /// Returns [`true`] if this is a loopback address.
160     ///
161     /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and
162     /// [`Ipv6Addr::is_loopback`][IPv6] for more details.
163     ///
164     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
165     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
166     /// [`true`]: ../../std/primitive.bool.html
167     ///
168     /// # Examples
169     ///
170     /// ```
171     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
172     ///
173     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
174     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
175     /// ```
176     #[stable(feature = "ip_shared", since = "1.12.0")]
177     pub fn is_loopback(&self) -> bool {
178         match self {
179             IpAddr::V4(ip) => ip.is_loopback(),
180             IpAddr::V6(ip) => ip.is_loopback(),
181         }
182     }
183
184     /// Returns [`true`] if the address appears to be globally routable.
185     ///
186     /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and
187     /// [`Ipv6Addr::is_global`][IPv6] for more details.
188     ///
189     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
190     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
191     /// [`true`]: ../../std/primitive.bool.html
192     ///
193     /// # Examples
194     ///
195     /// ```
196     /// #![feature(ip)]
197     ///
198     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
199     ///
200     /// fn main() {
201     ///     assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
202     ///     assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(),
203     ///                true);
204     /// }
205     /// ```
206     pub fn is_global(&self) -> bool {
207         match self {
208             IpAddr::V4(ip) => ip.is_global(),
209             IpAddr::V6(ip) => ip.is_global(),
210         }
211     }
212
213     /// Returns [`true`] if this is a multicast address.
214     ///
215     /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and
216     /// [`Ipv6Addr::is_multicast`][IPv6] for more details.
217     ///
218     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
219     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
220     /// [`true`]: ../../std/primitive.bool.html
221     ///
222     /// # Examples
223     ///
224     /// ```
225     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
226     ///
227     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
228     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
229     /// ```
230     #[stable(feature = "ip_shared", since = "1.12.0")]
231     pub fn is_multicast(&self) -> bool {
232         match self {
233             IpAddr::V4(ip) => ip.is_multicast(),
234             IpAddr::V6(ip) => ip.is_multicast(),
235         }
236     }
237
238     /// Returns [`true`] if this address is in a range designated for documentation.
239     ///
240     /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and
241     /// [`Ipv6Addr::is_documentation`][IPv6] for more details.
242     ///
243     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
244     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
245     /// [`true`]: ../../std/primitive.bool.html
246     ///
247     /// # Examples
248     ///
249     /// ```
250     /// #![feature(ip)]
251     ///
252     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
253     ///
254     /// fn main() {
255     ///     assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
256     ///     assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0))
257     ///                       .is_documentation(), true);
258     /// }
259     /// ```
260     pub fn is_documentation(&self) -> bool {
261         match self {
262             IpAddr::V4(ip) => ip.is_documentation(),
263             IpAddr::V6(ip) => ip.is_documentation(),
264         }
265     }
266
267     /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise.
268     ///
269     /// [`true`]: ../../std/primitive.bool.html
270     /// [`false`]: ../../std/primitive.bool.html
271     /// [IPv4 address]: #variant.V4
272     ///
273     /// # Examples
274     ///
275     /// ```
276     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
277     ///
278     /// fn main() {
279     ///     assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
280     ///     assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(),
281     ///                false);
282     /// }
283     /// ```
284     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
285     pub fn is_ipv4(&self) -> bool {
286         match self {
287             IpAddr::V4(_) => true,
288             IpAddr::V6(_) => false,
289         }
290     }
291
292     /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
293     ///
294     /// [`true`]: ../../std/primitive.bool.html
295     /// [`false`]: ../../std/primitive.bool.html
296     /// [IPv6 address]: #variant.V6
297     ///
298     /// # Examples
299     ///
300     /// ```
301     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
302     ///
303     /// fn main() {
304     ///     assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
305     ///     assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(),
306     ///                true);
307     /// }
308     /// ```
309     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
310     pub fn is_ipv6(&self) -> bool {
311         match self {
312             IpAddr::V4(_) => false,
313             IpAddr::V6(_) => true,
314         }
315     }
316 }
317
318 impl Ipv4Addr {
319     /// Creates a new IPv4 address from four eight-bit octets.
320     ///
321     /// The result will represent the IP address `a`.`b`.`c`.`d`.
322     ///
323     /// # Examples
324     ///
325     /// ```
326     /// use std::net::Ipv4Addr;
327     ///
328     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
329     /// ```
330     #[stable(feature = "rust1", since = "1.0.0")]
331     pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
332         // FIXME: should just be u32::from_be_bytes([a, b, c, d]),
333         // once that method is no longer rustc_const_unstable
334         Ipv4Addr {
335             inner: c::in_addr {
336                 s_addr: u32::to_be(
337                     ((a as u32) << 24) |
338                     ((b as u32) << 16) |
339                     ((c as u32) <<  8) |
340                     (d as u32)
341                 ),
342             }
343         }
344     }
345
346     /// An IPv4 address with the address pointing to localhost: 127.0.0.1.
347     ///
348     /// # Examples
349     ///
350     /// ```
351     /// use std::net::Ipv4Addr;
352     ///
353     /// let addr = Ipv4Addr::LOCALHOST;
354     /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
355     /// ```
356     #[stable(feature = "ip_constructors", since = "1.30.0")]
357     pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
358
359     /// An IPv4 address representing an unspecified address: 0.0.0.0
360     ///
361     /// # Examples
362     ///
363     /// ```
364     /// use std::net::Ipv4Addr;
365     ///
366     /// let addr = Ipv4Addr::UNSPECIFIED;
367     /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
368     /// ```
369     #[stable(feature = "ip_constructors", since = "1.30.0")]
370     pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
371
372     /// An IPv4 address representing the broadcast address: 255.255.255.255
373     ///
374     /// # Examples
375     ///
376     /// ```
377     /// use std::net::Ipv4Addr;
378     ///
379     /// let addr = Ipv4Addr::BROADCAST;
380     /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
381     /// ```
382     #[stable(feature = "ip_constructors", since = "1.30.0")]
383     pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
384
385     /// Returns the four eight-bit integers that make up this address.
386     ///
387     /// # Examples
388     ///
389     /// ```
390     /// use std::net::Ipv4Addr;
391     ///
392     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
393     /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
394     /// ```
395     #[stable(feature = "rust1", since = "1.0.0")]
396     pub fn octets(&self) -> [u8; 4] {
397         // This returns the order we want because s_addr is stored in big-endian.
398         self.inner.s_addr.to_ne_bytes()
399     }
400
401     /// Returns [`true`] for the special 'unspecified' address (0.0.0.0).
402     ///
403     /// This property is defined in _UNIX Network Programming, Second Edition_,
404     /// W. Richard Stevens, p. 891; see also [ip7].
405     ///
406     /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
407     /// [`true`]: ../../std/primitive.bool.html
408     ///
409     /// # Examples
410     ///
411     /// ```
412     /// use std::net::Ipv4Addr;
413     ///
414     /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
415     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
416     /// ```
417     #[stable(feature = "ip_shared", since = "1.12.0")]
418     pub const fn is_unspecified(&self) -> bool {
419         self.inner.s_addr == 0
420     }
421
422     /// Returns [`true`] if this is a loopback address (127.0.0.0/8).
423     ///
424     /// This property is defined by [IETF RFC 1122].
425     ///
426     /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
427     /// [`true`]: ../../std/primitive.bool.html
428     ///
429     /// # Examples
430     ///
431     /// ```
432     /// use std::net::Ipv4Addr;
433     ///
434     /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
435     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
436     /// ```
437     #[stable(since = "1.7.0", feature = "ip_17")]
438     pub fn is_loopback(&self) -> bool {
439         self.octets()[0] == 127
440     }
441
442     /// Returns [`true`] if this is a private address.
443     ///
444     /// The private address ranges are defined in [IETF RFC 1918] and include:
445     ///
446     ///  - 10.0.0.0/8
447     ///  - 172.16.0.0/12
448     ///  - 192.168.0.0/16
449     ///
450     /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
451     /// [`true`]: ../../std/primitive.bool.html
452     ///
453     /// # Examples
454     ///
455     /// ```
456     /// use std::net::Ipv4Addr;
457     ///
458     /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
459     /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
460     /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
461     /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
462     /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
463     /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
464     /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
465     /// ```
466     #[stable(since = "1.7.0", feature = "ip_17")]
467     pub fn is_private(&self) -> bool {
468         match self.octets() {
469             [10, ..] => true,
470             [172, b, ..] if b >= 16 && b <= 31 => true,
471             [192, 168, ..] => true,
472             _ => false,
473         }
474     }
475
476     /// Returns [`true`] if the address is link-local (169.254.0.0/16).
477     ///
478     /// This property is defined by [IETF RFC 3927].
479     ///
480     /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
481     /// [`true`]: ../../std/primitive.bool.html
482     ///
483     /// # Examples
484     ///
485     /// ```
486     /// use std::net::Ipv4Addr;
487     ///
488     /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
489     /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
490     /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
491     /// ```
492     #[stable(since = "1.7.0", feature = "ip_17")]
493     pub fn is_link_local(&self) -> bool {
494         match self.octets() {
495             [169, 254, ..] => true,
496             _ => false,
497         }
498     }
499
500     /// Returns [`true`] if the address appears to be globally routable.
501     /// See [iana-ipv4-special-registry][ipv4-sr].
502     ///
503     /// The following return false:
504     ///
505     /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16)
506     /// - the loopback address (127.0.0.0/8)
507     /// - the link-local address (169.254.0.0/16)
508     /// - the broadcast address (255.255.255.255/32)
509     /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
510     /// - the unspecified address (0.0.0.0)
511     ///
512     /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
513     /// [`true`]: ../../std/primitive.bool.html
514     ///
515     /// # Examples
516     ///
517     /// ```
518     /// #![feature(ip)]
519     ///
520     /// use std::net::Ipv4Addr;
521     ///
522     /// fn main() {
523     ///     assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
524     ///     assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
525     ///     assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
526     ///     assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
527     ///     assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
528     /// }
529     /// ```
530     pub fn is_global(&self) -> bool {
531         !self.is_private() && !self.is_loopback() && !self.is_link_local() &&
532         !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified()
533     }
534
535     /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
536     ///
537     /// Multicast addresses have a most significant octet between 224 and 239,
538     /// and is defined by [IETF RFC 5771].
539     ///
540     /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
541     /// [`true`]: ../../std/primitive.bool.html
542     ///
543     /// # Examples
544     ///
545     /// ```
546     /// use std::net::Ipv4Addr;
547     ///
548     /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
549     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
550     /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
551     /// ```
552     #[stable(since = "1.7.0", feature = "ip_17")]
553     pub fn is_multicast(&self) -> bool {
554         self.octets()[0] >= 224 && self.octets()[0] <= 239
555     }
556
557     /// Returns [`true`] if this is a broadcast address (255.255.255.255).
558     ///
559     /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
560     ///
561     /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
562     /// [`true`]: ../../std/primitive.bool.html
563     ///
564     /// # Examples
565     ///
566     /// ```
567     /// use std::net::Ipv4Addr;
568     ///
569     /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
570     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
571     /// ```
572     #[stable(since = "1.7.0", feature = "ip_17")]
573     pub fn is_broadcast(&self) -> bool {
574         self == &Self::BROADCAST
575     }
576
577     /// Returns [`true`] if this address is in a range designated for documentation.
578     ///
579     /// This is defined in [IETF RFC 5737]:
580     ///
581     /// - 192.0.2.0/24 (TEST-NET-1)
582     /// - 198.51.100.0/24 (TEST-NET-2)
583     /// - 203.0.113.0/24 (TEST-NET-3)
584     ///
585     /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
586     /// [`true`]: ../../std/primitive.bool.html
587     ///
588     /// # Examples
589     ///
590     /// ```
591     /// use std::net::Ipv4Addr;
592     ///
593     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
594     /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
595     /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
596     /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
597     /// ```
598     #[stable(since = "1.7.0", feature = "ip_17")]
599     pub fn is_documentation(&self) -> bool {
600         match self.octets() {
601             [192, 0, 2, _] => true,
602             [198, 51, 100, _] => true,
603             [203, 0, 113, _] => true,
604             _ => false,
605         }
606     }
607
608     /// Converts this address to an IPv4-compatible [IPv6 address].
609     ///
610     /// a.b.c.d becomes ::a.b.c.d
611     ///
612     /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
613     ///
614     /// # Examples
615     ///
616     /// ```
617     /// use std::net::{Ipv4Addr, Ipv6Addr};
618     ///
619     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
620     ///            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767));
621     /// ```
622     #[stable(feature = "rust1", since = "1.0.0")]
623     pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
624         let octets = self.octets();
625         Ipv6Addr::from([
626             0, 0, 0, 0,
627             0, 0, 0, 0,
628             0, 0, 0, 0,
629             octets[0], octets[1], octets[2], octets[3],
630         ])
631     }
632
633     /// Converts this address to an IPv4-mapped [IPv6 address].
634     ///
635     /// a.b.c.d becomes ::ffff:a.b.c.d
636     ///
637     /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
638     ///
639     /// # Examples
640     ///
641     /// ```
642     /// use std::net::{Ipv4Addr, Ipv6Addr};
643     ///
644     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
645     ///            Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
646     /// ```
647     #[stable(feature = "rust1", since = "1.0.0")]
648     pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
649         let octets = self.octets();
650         Ipv6Addr::from([
651             0, 0, 0, 0,
652             0, 0, 0, 0,
653             0, 0, 0xFF, 0xFF,
654             octets[0], octets[1], octets[2], octets[3],
655         ])
656     }
657 }
658
659 #[stable(feature = "ip_addr", since = "1.7.0")]
660 impl fmt::Display for IpAddr {
661     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
662         match self {
663             IpAddr::V4(ip) => ip.fmt(fmt),
664             IpAddr::V6(ip) => ip.fmt(fmt),
665         }
666     }
667 }
668
669 #[stable(feature = "ip_from_ip", since = "1.16.0")]
670 impl From<Ipv4Addr> for IpAddr {
671     fn from(ipv4: Ipv4Addr) -> IpAddr {
672         IpAddr::V4(ipv4)
673     }
674 }
675
676 #[stable(feature = "ip_from_ip", since = "1.16.0")]
677 impl From<Ipv6Addr> for IpAddr {
678     fn from(ipv6: Ipv6Addr) -> IpAddr {
679         IpAddr::V6(ipv6)
680     }
681 }
682
683 #[stable(feature = "rust1", since = "1.0.0")]
684 impl fmt::Display for Ipv4Addr {
685     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
686         let octets = self.octets();
687         write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
688     }
689 }
690
691 #[stable(feature = "rust1", since = "1.0.0")]
692 impl fmt::Debug for Ipv4Addr {
693     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
694         fmt::Display::fmt(self, fmt)
695     }
696 }
697
698 #[stable(feature = "rust1", since = "1.0.0")]
699 impl Clone for Ipv4Addr {
700     fn clone(&self) -> Ipv4Addr { *self }
701 }
702
703 #[stable(feature = "rust1", since = "1.0.0")]
704 impl PartialEq for Ipv4Addr {
705     fn eq(&self, other: &Ipv4Addr) -> bool {
706         self.inner.s_addr == other.inner.s_addr
707     }
708 }
709
710 #[stable(feature = "ip_cmp", since = "1.16.0")]
711 impl PartialEq<Ipv4Addr> for IpAddr {
712     fn eq(&self, other: &Ipv4Addr) -> bool {
713         match self {
714             IpAddr::V4(v4) => v4 == other,
715             IpAddr::V6(_) => false,
716         }
717     }
718 }
719
720 #[stable(feature = "ip_cmp", since = "1.16.0")]
721 impl PartialEq<IpAddr> for Ipv4Addr {
722     fn eq(&self, other: &IpAddr) -> bool {
723         match other {
724             IpAddr::V4(v4) => self == v4,
725             IpAddr::V6(_) => false,
726         }
727     }
728 }
729
730 #[stable(feature = "rust1", since = "1.0.0")]
731 impl Eq for Ipv4Addr {}
732
733 #[stable(feature = "rust1", since = "1.0.0")]
734 impl hash::Hash for Ipv4Addr {
735     fn hash<H: hash::Hasher>(&self, s: &mut H) {
736         // `inner` is #[repr(packed)], so we need to copy `s_addr`.
737         {self.inner.s_addr}.hash(s)
738     }
739 }
740
741 #[stable(feature = "rust1", since = "1.0.0")]
742 impl PartialOrd for Ipv4Addr {
743     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
744         Some(self.cmp(other))
745     }
746 }
747
748 #[stable(feature = "ip_cmp", since = "1.16.0")]
749 impl PartialOrd<Ipv4Addr> for IpAddr {
750     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
751         match self {
752             IpAddr::V4(v4) => v4.partial_cmp(other),
753             IpAddr::V6(_) => Some(Ordering::Greater),
754         }
755     }
756 }
757
758 #[stable(feature = "ip_cmp", since = "1.16.0")]
759 impl PartialOrd<IpAddr> for Ipv4Addr {
760     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
761         match other {
762             IpAddr::V4(v4) => self.partial_cmp(v4),
763             IpAddr::V6(_) => Some(Ordering::Less),
764         }
765     }
766 }
767
768 #[stable(feature = "rust1", since = "1.0.0")]
769 impl Ord for Ipv4Addr {
770     fn cmp(&self, other: &Ipv4Addr) -> Ordering {
771         u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr))
772     }
773 }
774
775 impl AsInner<c::in_addr> for Ipv4Addr {
776     fn as_inner(&self) -> &c::in_addr { &self.inner }
777 }
778 impl FromInner<c::in_addr> for Ipv4Addr {
779     fn from_inner(addr: c::in_addr) -> Ipv4Addr {
780         Ipv4Addr { inner: addr }
781     }
782 }
783
784 #[stable(feature = "ip_u32", since = "1.1.0")]
785 impl From<Ipv4Addr> for u32 {
786     /// Converts an `Ipv4Addr` into a host byte order `u32`.
787     ///
788     /// # Examples
789     ///
790     /// ```
791     /// use std::net::Ipv4Addr;
792     ///
793     /// let addr = Ipv4Addr::new(13, 12, 11, 10);
794     /// assert_eq!(0x0d0c0b0au32, u32::from(addr));
795     /// ```
796     fn from(ip: Ipv4Addr) -> u32 {
797         let ip = ip.octets();
798         u32::from_be_bytes(ip)
799     }
800 }
801
802 #[stable(feature = "ip_u32", since = "1.1.0")]
803 impl From<u32> for Ipv4Addr {
804     /// Converts a host byte order `u32` into an `Ipv4Addr`.
805     ///
806     /// # Examples
807     ///
808     /// ```
809     /// use std::net::Ipv4Addr;
810     ///
811     /// let addr = Ipv4Addr::from(0x0d0c0b0au32);
812     /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
813     /// ```
814     fn from(ip: u32) -> Ipv4Addr {
815         Ipv4Addr::from(ip.to_be_bytes())
816     }
817 }
818
819 #[stable(feature = "from_slice_v4", since = "1.9.0")]
820 impl From<[u8; 4]> for Ipv4Addr {
821     /// # Examples
822     ///
823     /// ```
824     /// use std::net::Ipv4Addr;
825     ///
826     /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
827     /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
828     /// ```
829     fn from(octets: [u8; 4]) -> Ipv4Addr {
830         Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
831     }
832 }
833
834 #[stable(feature = "ip_from_slice", since = "1.17.0")]
835 impl From<[u8; 4]> for IpAddr {
836     /// Creates an `IpAddr::V4` from a four element byte array.
837     ///
838     /// # Examples
839     ///
840     /// ```
841     /// use std::net::{IpAddr, Ipv4Addr};
842     ///
843     /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
844     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
845     /// ```
846     fn from(octets: [u8; 4]) -> IpAddr {
847         IpAddr::V4(Ipv4Addr::from(octets))
848     }
849 }
850
851 impl Ipv6Addr {
852     /// Creates a new IPv6 address from eight 16-bit segments.
853     ///
854     /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
855     ///
856     /// # Examples
857     ///
858     /// ```
859     /// use std::net::Ipv6Addr;
860     ///
861     /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
862     /// ```
863     #[stable(feature = "rust1", since = "1.0.0")]
864     pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16,
865                      g: u16, h: u16) -> Ipv6Addr {
866         Ipv6Addr {
867             inner: c::in6_addr {
868                 s6_addr: [
869                     (a >> 8) as u8, a as u8,
870                     (b >> 8) as u8, b as u8,
871                     (c >> 8) as u8, c as u8,
872                     (d >> 8) as u8, d as u8,
873                     (e >> 8) as u8, e as u8,
874                     (f >> 8) as u8, f as u8,
875                     (g >> 8) as u8, g as u8,
876                     (h >> 8) as u8, h as u8
877                 ],
878             }
879         }
880
881     }
882
883     /// An IPv6 address representing localhost: `::1`.
884     ///
885     /// # Examples
886     ///
887     /// ```
888     /// use std::net::Ipv6Addr;
889     ///
890     /// let addr = Ipv6Addr::LOCALHOST;
891     /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
892     /// ```
893     #[stable(feature = "ip_constructors", since = "1.30.0")]
894     pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
895
896     /// An IPv6 address representing the unspecified address: `::`
897     ///
898     /// # Examples
899     ///
900     /// ```
901     /// use std::net::Ipv6Addr;
902     ///
903     /// let addr = Ipv6Addr::UNSPECIFIED;
904     /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
905     /// ```
906     #[stable(feature = "ip_constructors", since = "1.30.0")]
907     pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
908
909     /// Returns the eight 16-bit segments that make up this address.
910     ///
911     /// # Examples
912     ///
913     /// ```
914     /// use std::net::Ipv6Addr;
915     ///
916     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
917     ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
918     /// ```
919     #[stable(feature = "rust1", since = "1.0.0")]
920     pub fn segments(&self) -> [u16; 8] {
921         let arr = &self.inner.s6_addr;
922         [
923             u16::from_be_bytes([arr[0], arr[1]]),
924             u16::from_be_bytes([arr[2], arr[3]]),
925             u16::from_be_bytes([arr[4], arr[5]]),
926             u16::from_be_bytes([arr[6], arr[7]]),
927             u16::from_be_bytes([arr[8], arr[9]]),
928             u16::from_be_bytes([arr[10], arr[11]]),
929             u16::from_be_bytes([arr[12], arr[13]]),
930             u16::from_be_bytes([arr[14], arr[15]]),
931         ]
932     }
933
934     /// Returns [`true`] for the special 'unspecified' address (::).
935     ///
936     /// This property is defined in [IETF RFC 4291].
937     ///
938     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
939     /// [`true`]: ../../std/primitive.bool.html
940     ///
941     /// # Examples
942     ///
943     /// ```
944     /// use std::net::Ipv6Addr;
945     ///
946     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
947     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
948     /// ```
949     #[stable(since = "1.7.0", feature = "ip_17")]
950     pub fn is_unspecified(&self) -> bool {
951         self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
952     }
953
954     /// Returns [`true`] if this is a loopback address (::1).
955     ///
956     /// This property is defined in [IETF RFC 4291].
957     ///
958     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
959     /// [`true`]: ../../std/primitive.bool.html
960     ///
961     /// # Examples
962     ///
963     /// ```
964     /// use std::net::Ipv6Addr;
965     ///
966     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
967     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
968     /// ```
969     #[stable(since = "1.7.0", feature = "ip_17")]
970     pub fn is_loopback(&self) -> bool {
971         self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
972     }
973
974     /// Returns [`true`] if the address appears to be globally routable.
975     ///
976     /// The following return [`false`]:
977     ///
978     /// - the loopback address
979     /// - link-local, site-local, and unique local unicast addresses
980     /// - interface-, link-, realm-, admin- and site-local multicast addresses
981     ///
982     /// [`true`]: ../../std/primitive.bool.html
983     /// [`false`]: ../../std/primitive.bool.html
984     ///
985     /// # Examples
986     ///
987     /// ```
988     /// #![feature(ip)]
989     ///
990     /// use std::net::Ipv6Addr;
991     ///
992     /// fn main() {
993     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
994     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
995     ///     assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
996     /// }
997     /// ```
998     pub fn is_global(&self) -> bool {
999         match self.multicast_scope() {
1000             Some(Ipv6MulticastScope::Global) => true,
1001             None => self.is_unicast_global(),
1002             _ => false
1003         }
1004     }
1005
1006     /// Returns [`true`] if this is a unique local address (fc00::/7).
1007     ///
1008     /// This property is defined in [IETF RFC 4193].
1009     ///
1010     /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
1011     /// [`true`]: ../../std/primitive.bool.html
1012     ///
1013     /// # Examples
1014     ///
1015     /// ```
1016     /// #![feature(ip)]
1017     ///
1018     /// use std::net::Ipv6Addr;
1019     ///
1020     /// fn main() {
1021     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(),
1022     ///                false);
1023     ///     assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
1024     /// }
1025     /// ```
1026     pub fn is_unique_local(&self) -> bool {
1027         (self.segments()[0] & 0xfe00) == 0xfc00
1028     }
1029
1030     /// Returns [`true`] if the address is unicast and link-local (fe80::/10).
1031     ///
1032     /// This property is defined in [IETF RFC 4291].
1033     ///
1034     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1035     /// [`true`]: ../../std/primitive.bool.html
1036     ///
1037     /// # Examples
1038     ///
1039     /// ```
1040     /// #![feature(ip)]
1041     ///
1042     /// use std::net::Ipv6Addr;
1043     ///
1044     /// fn main() {
1045     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(),
1046     ///                false);
1047     ///     assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
1048     /// }
1049     /// ```
1050     pub fn is_unicast_link_local(&self) -> bool {
1051         (self.segments()[0] & 0xffc0) == 0xfe80
1052     }
1053
1054     /// Returns [`true`] if this is a deprecated unicast site-local address
1055     /// (fec0::/10).
1056     ///
1057     /// [`true`]: ../../std/primitive.bool.html
1058     ///
1059     /// # Examples
1060     ///
1061     /// ```
1062     /// #![feature(ip)]
1063     ///
1064     /// use std::net::Ipv6Addr;
1065     ///
1066     /// fn main() {
1067     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(),
1068     ///                false);
1069     ///     assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
1070     /// }
1071     /// ```
1072     pub fn is_unicast_site_local(&self) -> bool {
1073         (self.segments()[0] & 0xffc0) == 0xfec0
1074     }
1075
1076     /// Returns [`true`] if this is an address reserved for documentation
1077     /// (2001:db8::/32).
1078     ///
1079     /// This property is defined in [IETF RFC 3849].
1080     ///
1081     /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
1082     /// [`true`]: ../../std/primitive.bool.html
1083     ///
1084     /// # Examples
1085     ///
1086     /// ```
1087     /// #![feature(ip)]
1088     ///
1089     /// use std::net::Ipv6Addr;
1090     ///
1091     /// fn main() {
1092     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(),
1093     ///                false);
1094     ///     assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
1095     /// }
1096     /// ```
1097     pub fn is_documentation(&self) -> bool {
1098         (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
1099     }
1100
1101     /// Returns [`true`] if the address is a globally routable unicast address.
1102     ///
1103     /// The following return false:
1104     ///
1105     /// - the loopback address
1106     /// - the link-local addresses
1107     /// - the (deprecated) site-local addresses
1108     /// - unique local addresses
1109     /// - the unspecified address
1110     /// - the address range reserved for documentation
1111     ///
1112     /// [`true`]: ../../std/primitive.bool.html
1113     ///
1114     /// # Examples
1115     ///
1116     /// ```
1117     /// #![feature(ip)]
1118     ///
1119     /// use std::net::Ipv6Addr;
1120     ///
1121     /// fn main() {
1122     ///     assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
1123     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(),
1124     ///                true);
1125     /// }
1126     /// ```
1127     pub fn is_unicast_global(&self) -> bool {
1128         !self.is_multicast()
1129             && !self.is_loopback() && !self.is_unicast_link_local()
1130             && !self.is_unicast_site_local() && !self.is_unique_local()
1131             && !self.is_unspecified() && !self.is_documentation()
1132     }
1133
1134     /// Returns the address's multicast scope if the address is multicast.
1135     ///
1136     /// # Examples
1137     ///
1138     /// ```
1139     /// #![feature(ip)]
1140     ///
1141     /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
1142     ///
1143     /// fn main() {
1144     ///     assert_eq!(Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
1145     ///                              Some(Ipv6MulticastScope::Global));
1146     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
1147     /// }
1148     /// ```
1149     pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
1150         if self.is_multicast() {
1151             match self.segments()[0] & 0x000f {
1152                 1 => Some(Ipv6MulticastScope::InterfaceLocal),
1153                 2 => Some(Ipv6MulticastScope::LinkLocal),
1154                 3 => Some(Ipv6MulticastScope::RealmLocal),
1155                 4 => Some(Ipv6MulticastScope::AdminLocal),
1156                 5 => Some(Ipv6MulticastScope::SiteLocal),
1157                 8 => Some(Ipv6MulticastScope::OrganizationLocal),
1158                 14 => Some(Ipv6MulticastScope::Global),
1159                 _ => None
1160             }
1161         } else {
1162             None
1163         }
1164     }
1165
1166     /// Returns [`true`] if this is a multicast address (ff00::/8).
1167     ///
1168     /// This property is defined by [IETF RFC 4291].
1169     ///
1170     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1171     /// [`true`]: ../../std/primitive.bool.html
1172     ///
1173     /// # Examples
1174     ///
1175     /// ```
1176     /// use std::net::Ipv6Addr;
1177     ///
1178     /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
1179     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
1180     /// ```
1181     #[stable(since = "1.7.0", feature = "ip_17")]
1182     pub fn is_multicast(&self) -> bool {
1183         (self.segments()[0] & 0xff00) == 0xff00
1184     }
1185
1186     /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
1187     /// neither IPv4-compatible or IPv4-mapped.
1188     ///
1189     /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
1190     ///
1191     /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
1192     /// [`None`]: ../../std/option/enum.Option.html#variant.None
1193     ///
1194     /// # Examples
1195     ///
1196     /// ```
1197     /// use std::net::{Ipv4Addr, Ipv6Addr};
1198     ///
1199     /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
1200     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
1201     ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
1202     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
1203     ///            Some(Ipv4Addr::new(0, 0, 0, 1)));
1204     /// ```
1205     #[stable(feature = "rust1", since = "1.0.0")]
1206     pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
1207         match self.segments() {
1208             [0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => {
1209                 Some(Ipv4Addr::new((g >> 8) as u8, g as u8,
1210                                    (h >> 8) as u8, h as u8))
1211             },
1212             _ => None
1213         }
1214     }
1215
1216     /// Returns the sixteen eight-bit integers the IPv6 address consists of.
1217     ///
1218     /// ```
1219     /// use std::net::Ipv6Addr;
1220     ///
1221     /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
1222     ///            [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
1223     /// ```
1224     #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
1225     pub const fn octets(&self) -> [u8; 16] {
1226         self.inner.s6_addr
1227     }
1228 }
1229
1230 #[stable(feature = "rust1", since = "1.0.0")]
1231 impl fmt::Display for Ipv6Addr {
1232     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1233         match self.segments() {
1234             // We need special cases for :: and ::1, otherwise they're formatted
1235             // as ::0.0.0.[01]
1236             [0, 0, 0, 0, 0, 0, 0, 0] => write!(fmt, "::"),
1237             [0, 0, 0, 0, 0, 0, 0, 1] => write!(fmt, "::1"),
1238             // Ipv4 Compatible address
1239             [0, 0, 0, 0, 0, 0, g, h] => {
1240                 write!(fmt, "::{}.{}.{}.{}", (g >> 8) as u8, g as u8,
1241                        (h >> 8) as u8, h as u8)
1242             }
1243             // Ipv4-Mapped address
1244             [0, 0, 0, 0, 0, 0xffff, g, h] => {
1245                 write!(fmt, "::ffff:{}.{}.{}.{}", (g >> 8) as u8, g as u8,
1246                        (h >> 8) as u8, h as u8)
1247             },
1248             _ => {
1249                 fn find_zero_slice(segments: &[u16; 8]) -> (usize, usize) {
1250                     let mut longest_span_len = 0;
1251                     let mut longest_span_at = 0;
1252                     let mut cur_span_len = 0;
1253                     let mut cur_span_at = 0;
1254
1255                     for i in 0..8 {
1256                         if segments[i] == 0 {
1257                             if cur_span_len == 0 {
1258                                 cur_span_at = i;
1259                             }
1260
1261                             cur_span_len += 1;
1262
1263                             if cur_span_len > longest_span_len {
1264                                 longest_span_len = cur_span_len;
1265                                 longest_span_at = cur_span_at;
1266                             }
1267                         } else {
1268                             cur_span_len = 0;
1269                             cur_span_at = 0;
1270                         }
1271                     }
1272
1273                     (longest_span_at, longest_span_len)
1274                 }
1275
1276                 let (zeros_at, zeros_len) = find_zero_slice(&self.segments());
1277
1278                 if zeros_len > 1 {
1279                     fn fmt_subslice(segments: &[u16], fmt: &mut fmt::Formatter) -> fmt::Result {
1280                         if !segments.is_empty() {
1281                             write!(fmt, "{:x}", segments[0])?;
1282                             for &seg in &segments[1..] {
1283                                 write!(fmt, ":{:x}", seg)?;
1284                             }
1285                         }
1286                         Ok(())
1287                     }
1288
1289                     fmt_subslice(&self.segments()[..zeros_at], fmt)?;
1290                     fmt.write_str("::")?;
1291                     fmt_subslice(&self.segments()[zeros_at + zeros_len..], fmt)
1292                 } else {
1293                     let &[a, b, c, d, e, f, g, h] = &self.segments();
1294                     write!(fmt, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
1295                            a, b, c, d, e, f, g, h)
1296                 }
1297             }
1298         }
1299     }
1300 }
1301
1302 #[stable(feature = "rust1", since = "1.0.0")]
1303 impl fmt::Debug for Ipv6Addr {
1304     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1305         fmt::Display::fmt(self, fmt)
1306     }
1307 }
1308
1309 #[stable(feature = "rust1", since = "1.0.0")]
1310 impl Clone for Ipv6Addr {
1311     fn clone(&self) -> Ipv6Addr { *self }
1312 }
1313
1314 #[stable(feature = "rust1", since = "1.0.0")]
1315 impl PartialEq for Ipv6Addr {
1316     fn eq(&self, other: &Ipv6Addr) -> bool {
1317         self.inner.s6_addr == other.inner.s6_addr
1318     }
1319 }
1320
1321 #[stable(feature = "ip_cmp", since = "1.16.0")]
1322 impl PartialEq<IpAddr> for Ipv6Addr {
1323     fn eq(&self, other: &IpAddr) -> bool {
1324         match other {
1325             IpAddr::V4(_) => false,
1326             IpAddr::V6(v6) => self == v6,
1327         }
1328     }
1329 }
1330
1331 #[stable(feature = "ip_cmp", since = "1.16.0")]
1332 impl PartialEq<Ipv6Addr> for IpAddr {
1333     fn eq(&self, other: &Ipv6Addr) -> bool {
1334         match self {
1335             IpAddr::V4(_) => false,
1336             IpAddr::V6(v6) => v6 == other,
1337         }
1338     }
1339 }
1340
1341 #[stable(feature = "rust1", since = "1.0.0")]
1342 impl Eq for Ipv6Addr {}
1343
1344 #[stable(feature = "rust1", since = "1.0.0")]
1345 impl hash::Hash for Ipv6Addr {
1346     fn hash<H: hash::Hasher>(&self, s: &mut H) {
1347         self.inner.s6_addr.hash(s)
1348     }
1349 }
1350
1351 #[stable(feature = "rust1", since = "1.0.0")]
1352 impl PartialOrd for Ipv6Addr {
1353     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1354         Some(self.cmp(other))
1355     }
1356 }
1357
1358 #[stable(feature = "ip_cmp", since = "1.16.0")]
1359 impl PartialOrd<Ipv6Addr> for IpAddr {
1360     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1361         match self {
1362             IpAddr::V4(_) => Some(Ordering::Less),
1363             IpAddr::V6(v6) => v6.partial_cmp(other),
1364         }
1365     }
1366 }
1367
1368 #[stable(feature = "ip_cmp", since = "1.16.0")]
1369 impl PartialOrd<IpAddr> for Ipv6Addr {
1370     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
1371         match other {
1372             IpAddr::V4(_) => Some(Ordering::Greater),
1373             IpAddr::V6(v6) => self.partial_cmp(v6),
1374         }
1375     }
1376 }
1377
1378 #[stable(feature = "rust1", since = "1.0.0")]
1379 impl Ord for Ipv6Addr {
1380     fn cmp(&self, other: &Ipv6Addr) -> Ordering {
1381         self.segments().cmp(&other.segments())
1382     }
1383 }
1384
1385 impl AsInner<c::in6_addr> for Ipv6Addr {
1386     fn as_inner(&self) -> &c::in6_addr { &self.inner }
1387 }
1388 impl FromInner<c::in6_addr> for Ipv6Addr {
1389     fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
1390         Ipv6Addr { inner: addr }
1391     }
1392 }
1393
1394 #[stable(feature = "i128", since = "1.26.0")]
1395 impl From<Ipv6Addr> for u128 {
1396     /// Convert an `Ipv6Addr` into a host byte order `u128`.
1397     ///
1398     /// # Examples
1399     ///
1400     /// ```
1401     /// use std::net::Ipv6Addr;
1402     ///
1403     /// let addr = Ipv6Addr::new(
1404     ///     0x1020, 0x3040, 0x5060, 0x7080,
1405     ///     0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1406     /// );
1407     /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
1408     /// ```
1409     fn from(ip: Ipv6Addr) -> u128 {
1410         let ip = ip.octets();
1411         u128::from_be_bytes(ip)
1412     }
1413 }
1414 #[stable(feature = "i128", since = "1.26.0")]
1415 impl From<u128> for Ipv6Addr {
1416     /// Convert a host byte order `u128` into an `Ipv6Addr`.
1417     ///
1418     /// # Examples
1419     ///
1420     /// ```
1421     /// use std::net::Ipv6Addr;
1422     ///
1423     /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
1424     /// assert_eq!(
1425     ///     Ipv6Addr::new(
1426     ///         0x1020, 0x3040, 0x5060, 0x7080,
1427     ///         0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1428     ///     ),
1429     ///     addr);
1430     /// ```
1431     fn from(ip: u128) -> Ipv6Addr {
1432         Ipv6Addr::from(ip.to_be_bytes())
1433     }
1434 }
1435
1436 #[stable(feature = "ipv6_from_octets", since = "1.9.0")]
1437 impl From<[u8; 16]> for Ipv6Addr {
1438     fn from(octets: [u8; 16]) -> Ipv6Addr {
1439         let inner = c::in6_addr { s6_addr: octets };
1440         Ipv6Addr::from_inner(inner)
1441     }
1442 }
1443
1444 #[stable(feature = "ipv6_from_segments", since = "1.16.0")]
1445 impl From<[u16; 8]> for Ipv6Addr {
1446     fn from(segments: [u16; 8]) -> Ipv6Addr {
1447         let [a, b, c, d, e, f, g, h] = segments;
1448         Ipv6Addr::new(a, b, c, d, e, f, g, h)
1449     }
1450 }
1451
1452
1453 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1454 impl From<[u8; 16]> for IpAddr {
1455     /// Creates an `IpAddr::V6` from a sixteen element byte array.
1456     ///
1457     /// # Examples
1458     ///
1459     /// ```
1460     /// use std::net::{IpAddr, Ipv6Addr};
1461     ///
1462     /// let addr = IpAddr::from([
1463     ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1464     ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1465     /// ]);
1466     /// assert_eq!(
1467     ///     IpAddr::V6(Ipv6Addr::new(
1468     ///         0x1918, 0x1716,
1469     ///         0x1514, 0x1312,
1470     ///         0x1110, 0x0f0e,
1471     ///         0x0d0c, 0x0b0a
1472     ///     )),
1473     ///     addr
1474     /// );
1475     /// ```
1476     fn from(octets: [u8; 16]) -> IpAddr {
1477         IpAddr::V6(Ipv6Addr::from(octets))
1478     }
1479 }
1480
1481 #[stable(feature = "ip_from_slice", since = "1.17.0")]
1482 impl From<[u16; 8]> for IpAddr {
1483     /// Creates an `IpAddr::V6` from an eight element 16-bit array.
1484     ///
1485     /// # Examples
1486     ///
1487     /// ```
1488     /// use std::net::{IpAddr, Ipv6Addr};
1489     ///
1490     /// let addr = IpAddr::from([
1491     ///     525u16, 524u16, 523u16, 522u16,
1492     ///     521u16, 520u16, 519u16, 518u16,
1493     /// ]);
1494     /// assert_eq!(
1495     ///     IpAddr::V6(Ipv6Addr::new(
1496     ///         0x20d, 0x20c,
1497     ///         0x20b, 0x20a,
1498     ///         0x209, 0x208,
1499     ///         0x207, 0x206
1500     ///     )),
1501     ///     addr
1502     /// );
1503     /// ```
1504     fn from(segments: [u16; 8]) -> IpAddr {
1505         IpAddr::V6(Ipv6Addr::from(segments))
1506     }
1507 }
1508
1509 // Tests for this module
1510 #[cfg(all(test, not(target_os = "emscripten")))]
1511 mod tests {
1512     use net::*;
1513     use net::Ipv6MulticastScope::*;
1514     use net::test::{tsa, sa6, sa4};
1515
1516     #[test]
1517     fn test_from_str_ipv4() {
1518         assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
1519         assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
1520         assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
1521
1522         // out of range
1523         let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
1524         assert_eq!(None, none);
1525         // too short
1526         let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
1527         assert_eq!(None, none);
1528         // too long
1529         let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
1530         assert_eq!(None, none);
1531         // no number between dots
1532         let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
1533         assert_eq!(None, none);
1534     }
1535
1536     #[test]
1537     fn test_from_str_ipv6() {
1538         assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
1539         assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
1540
1541         assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
1542         assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
1543
1544         assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
1545                 "2a02:6b8::11:11".parse());
1546
1547         // too long group
1548         let none: Option<Ipv6Addr> = "::00000".parse().ok();
1549         assert_eq!(None, none);
1550         // too short
1551         let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
1552         assert_eq!(None, none);
1553         // too long
1554         let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
1555         assert_eq!(None, none);
1556         // triple colon
1557         let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
1558         assert_eq!(None, none);
1559         // two double colons
1560         let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
1561         assert_eq!(None, none);
1562         // `::` indicating zero groups of zeros
1563         let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
1564         assert_eq!(None, none);
1565     }
1566
1567     #[test]
1568     fn test_from_str_ipv4_in_ipv6() {
1569         assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)),
1570                 "::192.0.2.33".parse());
1571         assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
1572                 "::FFFF:192.0.2.33".parse());
1573         assert_eq!(Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
1574                 "64:ff9b::192.0.2.33".parse());
1575         assert_eq!(Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
1576                 "2001:db8:122:c000:2:2100:192.0.2.33".parse());
1577
1578         // colon after v4
1579         let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
1580         assert_eq!(None, none);
1581         // not enough groups
1582         let none: Option<Ipv6Addr> = "1.2.3.4.5:127.0.0.1".parse().ok();
1583         assert_eq!(None, none);
1584         // too many groups
1585         let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
1586         assert_eq!(None, none);
1587     }
1588
1589     #[test]
1590     fn test_from_str_socket_addr() {
1591         assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)),
1592                    "77.88.21.11:80".parse());
1593         assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)),
1594                    "77.88.21.11:80".parse());
1595         assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
1596                    "[2a02:6b8:0:1::1]:53".parse());
1597         assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1,
1598                                                       0, 0, 0, 1), 53, 0, 0)),
1599                    "[2a02:6b8:0:1::1]:53".parse());
1600         assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
1601                    "[::127.0.0.1]:22".parse());
1602         assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0,
1603                                                       0x7F00, 1), 22, 0, 0)),
1604                    "[::127.0.0.1]:22".parse());
1605
1606         // without port
1607         let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
1608         assert_eq!(None, none);
1609         // without port
1610         let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
1611         assert_eq!(None, none);
1612         // wrong brackets around v4
1613         let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
1614         assert_eq!(None, none);
1615         // port out of range
1616         let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
1617         assert_eq!(None, none);
1618     }
1619
1620     #[test]
1621     fn ipv6_addr_to_string() {
1622         // ipv4-mapped address
1623         let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
1624         assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
1625
1626         // ipv4-compatible address
1627         let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
1628         assert_eq!(a1.to_string(), "::192.0.2.128");
1629
1630         // v6 address with no zero segments
1631         assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
1632                    "8:9:a:b:c:d:e:f");
1633
1634         // reduce a single run of zeros
1635         assert_eq!("ae::ffff:102:304",
1636                    Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string());
1637
1638         // don't reduce just a single zero segment
1639         assert_eq!("1:2:3:4:5:6:0:8",
1640                    Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
1641
1642         // 'any' address
1643         assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
1644
1645         // loopback address
1646         assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
1647
1648         // ends in zeros
1649         assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
1650
1651         // two runs of zeros, second one is longer
1652         assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
1653
1654         // two runs of zeros, equal length
1655         assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
1656     }
1657
1658     #[test]
1659     fn ipv4_to_ipv6() {
1660         assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
1661                    Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped());
1662         assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
1663                    Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible());
1664     }
1665
1666     #[test]
1667     fn ipv6_to_ipv4() {
1668         assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
1669                    Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)));
1670         assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
1671                    Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78)));
1672         assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
1673                    None);
1674     }
1675
1676     #[test]
1677     fn ip_properties() {
1678         fn check4(octets: &[u8; 4], unspec: bool, loopback: bool,
1679                   global: bool, multicast: bool, documentation: bool) {
1680             let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]));
1681             assert_eq!(ip.is_unspecified(), unspec);
1682             assert_eq!(ip.is_loopback(), loopback);
1683             assert_eq!(ip.is_global(), global);
1684             assert_eq!(ip.is_multicast(), multicast);
1685             assert_eq!(ip.is_documentation(), documentation);
1686         }
1687
1688         fn check6(str_addr: &str, unspec: bool, loopback: bool,
1689                   global: bool, u_doc: bool, mcast: bool) {
1690             let ip = IpAddr::V6(str_addr.parse().unwrap());
1691             assert_eq!(ip.is_unspecified(), unspec);
1692             assert_eq!(ip.is_loopback(), loopback);
1693             assert_eq!(ip.is_global(), global);
1694             assert_eq!(ip.is_documentation(), u_doc);
1695             assert_eq!(ip.is_multicast(), mcast);
1696         }
1697
1698         //     address                unspec loopbk global multicast doc
1699         check4(&[0, 0, 0, 0],         true,  false, false,  false,   false);
1700         check4(&[0, 0, 0, 1],         false, false, true,   false,   false);
1701         check4(&[0, 1, 0, 0],         false, false, true,   false,   false);
1702         check4(&[10, 9, 8, 7],        false, false, false,  false,   false);
1703         check4(&[127, 1, 2, 3],       false, true,  false,  false,   false);
1704         check4(&[172, 31, 254, 253],  false, false, false,  false,   false);
1705         check4(&[169, 254, 253, 242], false, false, false,  false,   false);
1706         check4(&[192, 0, 2, 183],     false, false, false,  false,   true);
1707         check4(&[192, 1, 2, 183],     false, false, true,   false,   false);
1708         check4(&[192, 168, 254, 253], false, false, false,  false,   false);
1709         check4(&[198, 51, 100, 0],    false, false, false,  false,   true);
1710         check4(&[203, 0, 113, 0],     false, false, false,  false,   true);
1711         check4(&[203, 2, 113, 0],     false, false, true,   false,   false);
1712         check4(&[224, 0, 0, 0],       false, false, true,   true,    false);
1713         check4(&[239, 255, 255, 255], false, false, true,   true,    false);
1714         check4(&[255, 255, 255, 255], false, false, false,  false,   false);
1715
1716         //     address                            unspec loopbk global doc    mcast
1717         check6("::",                              true,  false, false, false, false);
1718         check6("::1",                             false, true,  false, false, false);
1719         check6("::0.0.0.2",                       false, false, true,  false, false);
1720         check6("1::",                             false, false, true,  false, false);
1721         check6("fc00::",                          false, false, false, false, false);
1722         check6("fdff:ffff::",                     false, false, false, false, false);
1723         check6("fe80:ffff::",                     false, false, false, false, false);
1724         check6("febf:ffff::",                     false, false, false, false, false);
1725         check6("fec0::",                          false, false, false, false, false);
1726         check6("ff01::",                          false, false, false, false, true);
1727         check6("ff02::",                          false, false, false, false, true);
1728         check6("ff03::",                          false, false, false, false, true);
1729         check6("ff04::",                          false, false, false, false, true);
1730         check6("ff05::",                          false, false, false, false, true);
1731         check6("ff08::",                          false, false, false, false, true);
1732         check6("ff0e::",                          false, false, true,  false, true);
1733         check6("2001:db8:85a3::8a2e:370:7334",    false, false, false, true,  false);
1734         check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true,  false, false);
1735     }
1736
1737     #[test]
1738     fn ipv4_properties() {
1739         fn check(octets: &[u8; 4], unspec: bool, loopback: bool,
1740                  private: bool, link_local: bool, global: bool,
1741                  multicast: bool, broadcast: bool, documentation: bool) {
1742             let ip = Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]);
1743             assert_eq!(octets, &ip.octets());
1744
1745             assert_eq!(ip.is_unspecified(), unspec);
1746             assert_eq!(ip.is_loopback(), loopback);
1747             assert_eq!(ip.is_private(), private);
1748             assert_eq!(ip.is_link_local(), link_local);
1749             assert_eq!(ip.is_global(), global);
1750             assert_eq!(ip.is_multicast(), multicast);
1751             assert_eq!(ip.is_broadcast(), broadcast);
1752             assert_eq!(ip.is_documentation(), documentation);
1753         }
1754
1755         //    address                unspec loopbk privt  linloc global multicast brdcast doc
1756         check(&[0, 0, 0, 0],         true,  false, false, false, false,  false,    false,  false);
1757         check(&[0, 0, 0, 1],         false, false, false, false, true,   false,    false,  false);
1758         check(&[0, 1, 0, 0],         false, false, false, false, true,   false,    false,  false);
1759         check(&[10, 9, 8, 7],        false, false, true,  false, false,  false,    false,  false);
1760         check(&[127, 1, 2, 3],       false, true,  false, false, false,  false,    false,  false);
1761         check(&[172, 31, 254, 253],  false, false, true,  false, false,  false,    false,  false);
1762         check(&[169, 254, 253, 242], false, false, false, true,  false,  false,    false,  false);
1763         check(&[192, 0, 2, 183],     false, false, false, false, false,  false,    false,  true);
1764         check(&[192, 1, 2, 183],     false, false, false, false, true,   false,    false,  false);
1765         check(&[192, 168, 254, 253], false, false, true,  false, false,  false,    false,  false);
1766         check(&[198, 51, 100, 0],    false, false, false, false, false,  false,    false,  true);
1767         check(&[203, 0, 113, 0],     false, false, false, false, false,  false,    false,  true);
1768         check(&[203, 2, 113, 0],     false, false, false, false, true,   false,    false,  false);
1769         check(&[224, 0, 0, 0],       false, false, false, false, true,   true,     false,  false);
1770         check(&[239, 255, 255, 255], false, false, false, false, true,   true,     false,  false);
1771         check(&[255, 255, 255, 255], false, false, false, false, false,  false,    true,   false);
1772     }
1773
1774     #[test]
1775     fn ipv6_properties() {
1776         fn check(str_addr: &str, octets: &[u8; 16], unspec: bool, loopback: bool,
1777                  unique_local: bool, global: bool,
1778                  u_link_local: bool, u_site_local: bool, u_global: bool, u_doc: bool,
1779                  m_scope: Option<Ipv6MulticastScope>) {
1780             let ip: Ipv6Addr = str_addr.parse().unwrap();
1781             assert_eq!(str_addr, ip.to_string());
1782             assert_eq!(&ip.octets(), octets);
1783             assert_eq!(Ipv6Addr::from(*octets), ip);
1784
1785             assert_eq!(ip.is_unspecified(), unspec);
1786             assert_eq!(ip.is_loopback(), loopback);
1787             assert_eq!(ip.is_unique_local(), unique_local);
1788             assert_eq!(ip.is_global(), global);
1789             assert_eq!(ip.is_unicast_link_local(), u_link_local);
1790             assert_eq!(ip.is_unicast_site_local(), u_site_local);
1791             assert_eq!(ip.is_unicast_global(), u_global);
1792             assert_eq!(ip.is_documentation(), u_doc);
1793             assert_eq!(ip.multicast_scope(), m_scope);
1794             assert_eq!(ip.is_multicast(), m_scope.is_some());
1795         }
1796
1797         //    unspec loopbk uniqlo global unill  unisl  uniglo doc    mscope
1798         check("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1799               true,  false, false, false, false, false, false, false, None);
1800         check("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
1801               false, true,  false, false, false, false, false, false, None);
1802         check("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
1803               false, false, false, true,  false, false, true,  false, None);
1804         check("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1805               false, false, false, true,  false, false, true,  false, None);
1806         check("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1807               false, false, true,  false, false, false, false, false, None);
1808         check("fdff:ffff::", &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1809               false, false, true,  false, false, false, false, false, None);
1810         check("fe80:ffff::", &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1811               false, false, false, false, true,  false, false, false, None);
1812         check("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1813               false, false, false, false, true,  false, false, false, None);
1814         check("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1815               false, false, false, false, false, true,  false, false, None);
1816         check("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1817               false, false, false, false, false, false, false, false, Some(InterfaceLocal));
1818         check("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1819               false, false, false, false, false, false, false, false, Some(LinkLocal));
1820         check("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1821               false, false, false, false, false, false, false, false, Some(RealmLocal));
1822         check("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1823               false, false, false, false, false, false, false, false, Some(AdminLocal));
1824         check("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1825               false, false, false, false, false, false, false, false, Some(SiteLocal));
1826         check("ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1827               false, false, false, false, false, false, false, false, Some(OrganizationLocal));
1828         check("ff0e::", &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1829               false, false, false, true,  false, false, false, false, Some(Global));
1830         check("2001:db8:85a3::8a2e:370:7334",
1831               &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
1832               false, false, false, false, false, false, false, true, None);
1833         check("102:304:506:708:90a:b0c:d0e:f10",
1834               &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
1835               false, false, false, true,  false, false, true,  false, None);
1836     }
1837
1838     #[test]
1839     fn to_socket_addr_socketaddr() {
1840         let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
1841         assert_eq!(Ok(vec![a]), tsa(a));
1842     }
1843
1844     #[test]
1845     fn test_ipv4_to_int() {
1846         let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
1847         assert_eq!(u32::from(a), 0x11223344);
1848     }
1849
1850     #[test]
1851     fn test_int_to_ipv4() {
1852         let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
1853         assert_eq!(Ipv4Addr::from(0x11223344), a);
1854     }
1855
1856     #[test]
1857     fn test_ipv6_to_int() {
1858         let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
1859         assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
1860     }
1861
1862     #[test]
1863     fn test_int_to_ipv6() {
1864         let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
1865         assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
1866     }
1867
1868     #[test]
1869     fn ipv4_from_constructors() {
1870         assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
1871         assert!(Ipv4Addr::LOCALHOST.is_loopback());
1872         assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
1873         assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
1874         assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
1875         assert!(Ipv4Addr::BROADCAST.is_broadcast());
1876     }
1877
1878     #[test]
1879     fn ipv6_from_contructors() {
1880         assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
1881         assert!(Ipv6Addr::LOCALHOST.is_loopback());
1882         assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
1883         assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
1884     }
1885
1886     #[test]
1887     fn ipv4_from_octets() {
1888         assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
1889     }
1890
1891     #[test]
1892     fn ipv6_from_segments() {
1893         let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677,
1894                                         0x8899, 0xaabb, 0xccdd, 0xeeff]);
1895         let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677,
1896                                 0x8899, 0xaabb, 0xccdd, 0xeeff);
1897         assert_eq!(new, from_u16s);
1898     }
1899
1900     #[test]
1901     fn ipv6_from_octets() {
1902         let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677,
1903                                         0x8899, 0xaabb, 0xccdd, 0xeeff]);
1904         let from_u8s = Ipv6Addr::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
1905                                        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]);
1906         assert_eq!(from_u16s, from_u8s);
1907     }
1908
1909     #[test]
1910     fn cmp() {
1911         let v41 = Ipv4Addr::new(100, 64, 3, 3);
1912         let v42 = Ipv4Addr::new(192, 0, 2, 2);
1913         let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
1914         let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
1915         assert!(v41 < v42);
1916         assert!(v61 < v62);
1917
1918         assert_eq!(v41, IpAddr::V4(v41));
1919         assert_eq!(v61, IpAddr::V6(v61));
1920         assert!(v41 != IpAddr::V4(v42));
1921         assert!(v61 != IpAddr::V6(v62));
1922
1923         assert!(v41 < IpAddr::V4(v42));
1924         assert!(v61 < IpAddr::V6(v62));
1925         assert!(IpAddr::V4(v41) < v42);
1926         assert!(IpAddr::V6(v61) < v62);
1927
1928         assert!(v41 < IpAddr::V6(v61));
1929         assert!(IpAddr::V4(v41) < v61);
1930     }
1931
1932     #[test]
1933     fn is_v4() {
1934         let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
1935         assert!(ip.is_ipv4());
1936         assert!(!ip.is_ipv6());
1937     }
1938
1939     #[test]
1940     fn is_v6() {
1941         let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
1942         assert!(!ip.is_ipv4());
1943         assert!(ip.is_ipv6());
1944     }
1945 }