]> git.lizzy.rs Git - rust.git/blob - src/libstd/net/ip.rs
Rollup merge of #53110 - Xanewok:save-analysis-remap-path, r=nrc
[rust.git] / src / libstd / net / ip.rs
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.
4 //
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.
10
11 #![unstable(feature = "ip", reason = "extra functionality has not been \
12                                       scrutinized to the level that it should \
13                                       be to be stable",
14             issue = "27709")]
15
16 use cmp::Ordering;
17 use fmt;
18 use hash;
19 use sys::net::netc as c;
20 use sys_common::{AsInner, FromInner};
21
22 /// An IP address, either IPv4 or IPv6.
23 ///
24 /// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
25 /// respective documentation for more details.
26 ///
27 /// The size of an `IpAddr` instance may vary depending on the target operating
28 /// system.
29 ///
30 /// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
31 /// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
32 ///
33 /// # Examples
34 ///
35 /// ```
36 /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
37 ///
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));
40 ///
41 /// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
42 /// assert_eq!("::1".parse(), Ok(localhost_v6));
43 ///
44 /// assert_eq!(localhost_v4.is_ipv6(), false);
45 /// assert_eq!(localhost_v4.is_ipv4(), true);
46 /// ```
47 #[stable(feature = "ip_addr", since = "1.7.0")]
48 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
49 pub enum IpAddr {
50     /// An IPv4 address.
51     #[stable(feature = "ip_addr", since = "1.7.0")]
52     V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
53     /// An IPv6 address.
54     #[stable(feature = "ip_addr", since = "1.7.0")]
55     V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
56 }
57
58 /// An IPv4 address.
59 ///
60 /// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
61 /// They are usually represented as four octets.
62 ///
63 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
64 ///
65 /// The size of an `Ipv4Addr` struct may vary depending on the target operating
66 /// system.
67 ///
68 /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
69 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
70 ///
71 /// # Textual representation
72 ///
73 /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
74 /// notation, divided by `.` (this is called "dot-decimal notation").
75 ///
76 /// [`FromStr`]: ../../std/str/trait.FromStr.html
77 ///
78 /// # Examples
79 ///
80 /// ```
81 /// use std::net::Ipv4Addr;
82 ///
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);
86 /// ```
87 #[derive(Copy)]
88 #[stable(feature = "rust1", since = "1.0.0")]
89 pub struct Ipv4Addr {
90     inner: c::in_addr,
91 }
92
93 /// An IPv6 address.
94 ///
95 /// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
96 /// They are usually represented as eight 16-bit segments.
97 ///
98 /// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
99 ///
100 /// The size of an `Ipv6Addr` struct may vary depending on the target operating
101 /// system.
102 ///
103 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
104 /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
105 ///
106 /// # Textual representation
107 ///
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
111 /// [IETF RFC 5952].
112 ///
113 /// [`FromStr`]: ../../std/str/trait.FromStr.html
114 /// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
115 ///
116 /// # Examples
117 ///
118 /// ```
119 /// use std::net::Ipv6Addr;
120 ///
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);
124 /// ```
125 #[derive(Copy)]
126 #[stable(feature = "rust1", since = "1.0.0")]
127 pub struct Ipv6Addr {
128     inner: c::in6_addr,
129 }
130
131 #[allow(missing_docs)]
132 #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
133 pub enum Ipv6MulticastScope {
134     InterfaceLocal,
135     LinkLocal,
136     RealmLocal,
137     AdminLocal,
138     SiteLocal,
139     OrganizationLocal,
140     Global
141 }
142
143 impl IpAddr {
144     /// Returns [`true`] for the special 'unspecified' address.
145     ///
146     /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and
147     /// [`Ipv6Addr::is_unspecified`][IPv6] for more details.
148     ///
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
152     ///
153     /// # Examples
154     ///
155     /// ```
156     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
157     ///
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);
160     /// ```
161     #[stable(feature = "ip_shared", since = "1.12.0")]
162     pub fn is_unspecified(&self) -> bool {
163         match *self {
164             IpAddr::V4(ref a) => a.is_unspecified(),
165             IpAddr::V6(ref a) => a.is_unspecified(),
166         }
167     }
168
169     /// Returns [`true`] if this is a loopback address.
170     ///
171     /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and
172     /// [`Ipv6Addr::is_loopback`][IPv6] for more details.
173     ///
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
177     ///
178     /// # Examples
179     ///
180     /// ```
181     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
182     ///
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);
185     /// ```
186     #[stable(feature = "ip_shared", since = "1.12.0")]
187     pub fn is_loopback(&self) -> bool {
188         match *self {
189             IpAddr::V4(ref a) => a.is_loopback(),
190             IpAddr::V6(ref a) => a.is_loopback(),
191         }
192     }
193
194     /// Returns [`true`] if the address appears to be globally routable.
195     ///
196     /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and
197     /// [`Ipv6Addr::is_global`][IPv6] for more details.
198     ///
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
202     ///
203     /// # Examples
204     ///
205     /// ```
206     /// #![feature(ip)]
207     ///
208     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
209     ///
210     /// fn main() {
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(),
213     ///                true);
214     /// }
215     /// ```
216     pub fn is_global(&self) -> bool {
217         match *self {
218             IpAddr::V4(ref a) => a.is_global(),
219             IpAddr::V6(ref a) => a.is_global(),
220         }
221     }
222
223     /// Returns [`true`] if this is a multicast address.
224     ///
225     /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and
226     /// [`Ipv6Addr::is_multicast`][IPv6] for more details.
227     ///
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
231     ///
232     /// # Examples
233     ///
234     /// ```
235     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
236     ///
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);
239     /// ```
240     #[stable(feature = "ip_shared", since = "1.12.0")]
241     pub fn is_multicast(&self) -> bool {
242         match *self {
243             IpAddr::V4(ref a) => a.is_multicast(),
244             IpAddr::V6(ref a) => a.is_multicast(),
245         }
246     }
247
248     /// Returns [`true`] if this address is in a range designated for documentation.
249     ///
250     /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and
251     /// [`Ipv6Addr::is_documentation`][IPv6] for more details.
252     ///
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
256     ///
257     /// # Examples
258     ///
259     /// ```
260     /// #![feature(ip)]
261     ///
262     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
263     ///
264     /// fn main() {
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);
268     /// }
269     /// ```
270     pub fn is_documentation(&self) -> bool {
271         match *self {
272             IpAddr::V4(ref a) => a.is_documentation(),
273             IpAddr::V6(ref a) => a.is_documentation(),
274         }
275     }
276
277     /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise.
278     ///
279     /// [`true`]: ../../std/primitive.bool.html
280     /// [`false`]: ../../std/primitive.bool.html
281     /// [IPv4 address]: #variant.V4
282     ///
283     /// # Examples
284     ///
285     /// ```
286     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
287     ///
288     /// fn main() {
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(),
291     ///                false);
292     /// }
293     /// ```
294     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
295     pub fn is_ipv4(&self) -> bool {
296         match *self {
297             IpAddr::V4(_) => true,
298             IpAddr::V6(_) => false,
299         }
300     }
301
302     /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
303     ///
304     /// [`true`]: ../../std/primitive.bool.html
305     /// [`false`]: ../../std/primitive.bool.html
306     /// [IPv6 address]: #variant.V6
307     ///
308     /// # Examples
309     ///
310     /// ```
311     /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
312     ///
313     /// fn main() {
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(),
316     ///                true);
317     /// }
318     /// ```
319     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
320     pub fn is_ipv6(&self) -> bool {
321         match *self {
322             IpAddr::V4(_) => false,
323             IpAddr::V6(_) => true,
324         }
325     }
326 }
327
328 impl Ipv4Addr {
329     /// Creates a new IPv4 address from four eight-bit octets.
330     ///
331     /// The result will represent the IP address `a`.`b`.`c`.`d`.
332     ///
333     /// # Examples
334     ///
335     /// ```
336     /// use std::net::Ipv4Addr;
337     ///
338     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
339     /// ```
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 {
343         Ipv4Addr {
344             inner: c::in_addr {
345                 s_addr: u32::to_be(
346                     ((a as u32) << 24) |
347                     ((b as u32) << 16) |
348                     ((c as u32) <<  8) |
349                     (d as u32)
350                 ),
351             }
352         }
353     }
354
355     /// An IPv4 address with the address pointing to localhost: 127.0.0.1.
356     ///
357     /// # Examples
358     ///
359     /// ```
360     /// #![feature(ip_constructors)]
361     /// use std::net::Ipv4Addr;
362     ///
363     /// let addr = Ipv4Addr::LOCALHOST;
364     /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
365     /// ```
366     #[unstable(feature = "ip_constructors",
367                reason = "requires greater scrutiny before stabilization",
368                issue = "44582")]
369     pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
370
371     /// An IPv4 address representing an unspecified address: 0.0.0.0
372     ///
373     /// # Examples
374     ///
375     /// ```
376     /// #![feature(ip_constructors)]
377     /// use std::net::Ipv4Addr;
378     ///
379     /// let addr = Ipv4Addr::UNSPECIFIED;
380     /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
381     /// ```
382     #[unstable(feature = "ip_constructors",
383                reason = "requires greater scrutiny before stabilization",
384                issue = "44582")]
385     pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
386
387     /// An IPv4 address representing the broadcast address: 255.255.255.255
388     ///
389     /// # Examples
390     ///
391     /// ```
392     /// #![feature(ip_constructors)]
393     /// use std::net::Ipv4Addr;
394     ///
395     /// let addr = Ipv4Addr::BROADCAST;
396     /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
397     /// ```
398     #[unstable(feature = "ip_constructors",
399                reason = "requires greater scrutiny before stabilization",
400                issue = "44582")]
401     pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
402
403     /// Returns the four eight-bit integers that make up this address.
404     ///
405     /// # Examples
406     ///
407     /// ```
408     /// use std::net::Ipv4Addr;
409     ///
410     /// let addr = Ipv4Addr::new(127, 0, 0, 1);
411     /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
412     /// ```
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]
417     }
418
419     /// Returns [`true`] for the special 'unspecified' address (0.0.0.0).
420     ///
421     /// This property is defined in _UNIX Network Programming, Second Edition_,
422     /// W. Richard Stevens, p. 891; see also [ip7].
423     ///
424     /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
425     /// [`true`]: ../../std/primitive.bool.html
426     ///
427     /// # Examples
428     ///
429     /// ```
430     /// use std::net::Ipv4Addr;
431     ///
432     /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
433     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
434     /// ```
435     #[stable(feature = "ip_shared", since = "1.12.0")]
436     pub fn is_unspecified(&self) -> bool {
437         self.inner.s_addr == 0
438     }
439
440     /// Returns [`true`] if this is a loopback address (127.0.0.0/8).
441     ///
442     /// This property is defined by [IETF RFC 1122].
443     ///
444     /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
445     /// [`true`]: ../../std/primitive.bool.html
446     ///
447     /// # Examples
448     ///
449     /// ```
450     /// use std::net::Ipv4Addr;
451     ///
452     /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
453     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
454     /// ```
455     #[stable(since = "1.7.0", feature = "ip_17")]
456     pub fn is_loopback(&self) -> bool {
457         self.octets()[0] == 127
458     }
459
460     /// Returns [`true`] if this is a private address.
461     ///
462     /// The private address ranges are defined in [IETF RFC 1918] and include:
463     ///
464     ///  - 10.0.0.0/8
465     ///  - 172.16.0.0/12
466     ///  - 192.168.0.0/16
467     ///
468     /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
469     /// [`true`]: ../../std/primitive.bool.html
470     ///
471     /// # Examples
472     ///
473     /// ```
474     /// use std::net::Ipv4Addr;
475     ///
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);
483     /// ```
484     #[stable(since = "1.7.0", feature = "ip_17")]
485     pub fn is_private(&self) -> bool {
486         match (self.octets()[0], self.octets()[1]) {
487             (10, _) => true,
488             (172, b) if b >= 16 && b <= 31 => true,
489             (192, 168) => true,
490             _ => false
491         }
492     }
493
494     /// Returns [`true`] if the address is link-local (169.254.0.0/16).
495     ///
496     /// This property is defined by [IETF RFC 3927].
497     ///
498     /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
499     /// [`true`]: ../../std/primitive.bool.html
500     ///
501     /// # Examples
502     ///
503     /// ```
504     /// use std::net::Ipv4Addr;
505     ///
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);
509     /// ```
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
513     }
514
515     /// Returns [`true`] if the address appears to be globally routable.
516     /// See [iana-ipv4-special-registry][ipv4-sr].
517     ///
518     /// The following return false:
519     ///
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)
526     ///
527     /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
528     /// [`true`]: ../../std/primitive.bool.html
529     ///
530     /// # Examples
531     ///
532     /// ```
533     /// #![feature(ip)]
534     ///
535     /// use std::net::Ipv4Addr;
536     ///
537     /// fn main() {
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);
543     /// }
544     /// ```
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()
548     }
549
550     /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
551     ///
552     /// Multicast addresses have a most significant octet between 224 and 239,
553     /// and is defined by [IETF RFC 5771].
554     ///
555     /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
556     /// [`true`]: ../../std/primitive.bool.html
557     ///
558     /// # Examples
559     ///
560     /// ```
561     /// use std::net::Ipv4Addr;
562     ///
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);
566     /// ```
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
570     }
571
572     /// Returns [`true`] if this is a broadcast address (255.255.255.255).
573     ///
574     /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
575     ///
576     /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
577     /// [`true`]: ../../std/primitive.bool.html
578     ///
579     /// # Examples
580     ///
581     /// ```
582     /// use std::net::Ipv4Addr;
583     ///
584     /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
585     /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
586     /// ```
587     #[stable(since = "1.7.0", feature = "ip_17")]
588     pub fn is_broadcast(&self) -> bool {
589         self == &Self::BROADCAST
590     }
591
592     /// Returns [`true`] if this address is in a range designated for documentation.
593     ///
594     /// This is defined in [IETF RFC 5737]:
595     ///
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)
599     ///
600     /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
601     /// [`true`]: ../../std/primitive.bool.html
602     ///
603     /// # Examples
604     ///
605     /// ```
606     /// use std::net::Ipv4Addr;
607     ///
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);
612     /// ```
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,
619             _ => false
620         }
621     }
622
623     /// Converts this address to an IPv4-compatible [IPv6 address].
624     ///
625     /// a.b.c.d becomes ::a.b.c.d
626     ///
627     /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
628     ///
629     /// # Examples
630     ///
631     /// ```
632     /// use std::net::{Ipv4Addr, Ipv6Addr};
633     ///
634     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
635     ///            Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767));
636     /// ```
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)
642     }
643
644     /// Converts this address to an IPv4-mapped [IPv6 address].
645     ///
646     /// a.b.c.d becomes ::ffff:a.b.c.d
647     ///
648     /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
649     ///
650     /// # Examples
651     ///
652     /// ```
653     /// use std::net::{Ipv4Addr, Ipv6Addr};
654     ///
655     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
656     ///            Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
657     /// ```
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)
663     }
664 }
665
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 {
669         match *self {
670             IpAddr::V4(ref a) => a.fmt(fmt),
671             IpAddr::V6(ref a) => a.fmt(fmt),
672         }
673     }
674 }
675
676 #[stable(feature = "ip_from_ip", since = "1.16.0")]
677 impl From<Ipv4Addr> for IpAddr {
678     fn from(ipv4: Ipv4Addr) -> IpAddr {
679         IpAddr::V4(ipv4)
680     }
681 }
682
683 #[stable(feature = "ip_from_ip", since = "1.16.0")]
684 impl From<Ipv6Addr> for IpAddr {
685     fn from(ipv6: Ipv6Addr) -> IpAddr {
686         IpAddr::V6(ipv6)
687     }
688 }
689
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])
695     }
696 }
697
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)
702     }
703 }
704
705 #[stable(feature = "rust1", since = "1.0.0")]
706 impl Clone for Ipv4Addr {
707     fn clone(&self) -> Ipv4Addr { *self }
708 }
709
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
714     }
715 }
716
717 #[stable(feature = "ip_cmp", since = "1.16.0")]
718 impl PartialEq<Ipv4Addr> for IpAddr {
719     fn eq(&self, other: &Ipv4Addr) -> bool {
720         match *self {
721             IpAddr::V4(ref v4) => v4 == other,
722             IpAddr::V6(_) => false,
723         }
724     }
725 }
726
727 #[stable(feature = "ip_cmp", since = "1.16.0")]
728 impl PartialEq<IpAddr> for Ipv4Addr {
729     fn eq(&self, other: &IpAddr) -> bool {
730         match *other {
731             IpAddr::V4(ref v4) => self == v4,
732             IpAddr::V6(_) => false,
733         }
734     }
735 }
736
737 #[stable(feature = "rust1", since = "1.0.0")]
738 impl Eq for Ipv4Addr {}
739
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)
745     }
746 }
747
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))
752     }
753 }
754
755 #[stable(feature = "ip_cmp", since = "1.16.0")]
756 impl PartialOrd<Ipv4Addr> for IpAddr {
757     fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
758         match *self {
759             IpAddr::V4(ref v4) => v4.partial_cmp(other),
760             IpAddr::V6(_) => Some(Ordering::Greater),
761         }
762     }
763 }
764
765 #[stable(feature = "ip_cmp", since = "1.16.0")]
766 impl PartialOrd<IpAddr> for Ipv4Addr {
767     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
768         match *other {
769             IpAddr::V4(ref v4) => self.partial_cmp(v4),
770             IpAddr::V6(_) => Some(Ordering::Less),
771         }
772     }
773 }
774
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))
779     }
780 }
781
782 impl AsInner<c::in_addr> for Ipv4Addr {
783     fn as_inner(&self) -> &c::in_addr { &self.inner }
784 }
785 impl FromInner<c::in_addr> for Ipv4Addr {
786     fn from_inner(addr: c::in_addr) -> Ipv4Addr {
787         Ipv4Addr { inner: addr }
788     }
789 }
790
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`.
794     ///
795     /// # Examples
796     ///
797     /// ```
798     /// use std::net::Ipv4Addr;
799     ///
800     /// let addr = Ipv4Addr::new(13, 12, 11, 10);
801     /// assert_eq!(0x0d0c0b0au32, u32::from(addr));
802     /// ```
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)
806     }
807 }
808
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`.
812     ///
813     /// # Examples
814     ///
815     /// ```
816     /// use std::net::Ipv4Addr;
817     ///
818     /// let addr = Ipv4Addr::from(0x0d0c0b0au32);
819     /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
820     /// ```
821     fn from(ip: u32) -> Ipv4Addr {
822         Ipv4Addr::new((ip >> 24) as u8, (ip >> 16) as u8, (ip >> 8) as u8, ip as u8)
823     }
824 }
825
826 #[stable(feature = "from_slice_v4", since = "1.9.0")]
827 impl From<[u8; 4]> for Ipv4Addr {
828     /// # Examples
829     ///
830     /// ```
831     /// use std::net::Ipv4Addr;
832     ///
833     /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
834     /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
835     /// ```
836     fn from(octets: [u8; 4]) -> Ipv4Addr {
837         Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
838     }
839 }
840
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.
844     ///
845     /// # Examples
846     ///
847     /// ```
848     /// use std::net::{IpAddr, Ipv4Addr};
849     ///
850     /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
851     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
852     /// ```
853     fn from(octets: [u8; 4]) -> IpAddr {
854         IpAddr::V4(Ipv4Addr::from(octets))
855     }
856 }
857
858 impl Ipv6Addr {
859     /// Creates a new IPv6 address from eight 16-bit segments.
860     ///
861     /// The result will represent the IP address a:b:c:d:e:f:g:h.
862     ///
863     /// # Examples
864     ///
865     /// ```
866     /// use std::net::Ipv6Addr;
867     ///
868     /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
869     /// ```
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 {
874         Ipv6Addr {
875             inner: c::in6_addr {
876                 s6_addr: [
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
885                 ],
886             }
887         }
888
889     }
890
891     /// An IPv6 address representing localhost: `::1`.
892     ///
893     /// # Examples
894     ///
895     /// ```
896     /// #![feature(ip_constructors)]
897     /// use std::net::Ipv6Addr;
898     ///
899     /// let addr = Ipv6Addr::LOCALHOST;
900     /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
901     /// ```
902     #[unstable(feature = "ip_constructors",
903                reason = "requires greater scrutiny before stabilization",
904                issue = "44582")]
905     pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
906
907     /// An IPv6 address representing the unspecified address: `::`
908     ///
909     /// # Examples
910     ///
911     /// ```
912     /// #![feature(ip_constructors)]
913     /// use std::net::Ipv6Addr;
914     ///
915     /// let addr = Ipv6Addr::UNSPECIFIED;
916     /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
917     /// ```
918     #[unstable(feature = "ip_constructors",
919                reason = "requires greater scrutiny before stabilization",
920                issue = "44582")]
921     pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
922
923     /// Returns the eight 16-bit segments that make up this address.
924     ///
925     /// # Examples
926     ///
927     /// ```
928     /// use std::net::Ipv6Addr;
929     ///
930     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
931     ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
932     /// ```
933     #[stable(feature = "rust1", since = "1.0.0")]
934     pub fn segments(&self) -> [u16; 8] {
935         let arr = &self.inner.s6_addr;
936         [
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),
945         ]
946     }
947
948     /// Returns [`true`] for the special 'unspecified' address (::).
949     ///
950     /// This property is defined in [IETF RFC 4291].
951     ///
952     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
953     /// [`true`]: ../../std/primitive.bool.html
954     ///
955     /// # Examples
956     ///
957     /// ```
958     /// use std::net::Ipv6Addr;
959     ///
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);
962     /// ```
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]
966     }
967
968     /// Returns [`true`] if this is a loopback address (::1).
969     ///
970     /// This property is defined in [IETF RFC 4291].
971     ///
972     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
973     /// [`true`]: ../../std/primitive.bool.html
974     ///
975     /// # Examples
976     ///
977     /// ```
978     /// use std::net::Ipv6Addr;
979     ///
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);
982     /// ```
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]
986     }
987
988     /// Returns [`true`] if the address appears to be globally routable.
989     ///
990     /// The following return [`false`]:
991     ///
992     /// - the loopback address
993     /// - link-local, site-local, and unique local unicast addresses
994     /// - interface-, link-, realm-, admin- and site-local multicast addresses
995     ///
996     /// [`true`]: ../../std/primitive.bool.html
997     /// [`false`]: ../../std/primitive.bool.html
998     ///
999     /// # Examples
1000     ///
1001     /// ```
1002     /// #![feature(ip)]
1003     ///
1004     /// use std::net::Ipv6Addr;
1005     ///
1006     /// fn main() {
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);
1010     /// }
1011     /// ```
1012     pub fn is_global(&self) -> bool {
1013         match self.multicast_scope() {
1014             Some(Ipv6MulticastScope::Global) => true,
1015             None => self.is_unicast_global(),
1016             _ => false
1017         }
1018     }
1019
1020     /// Returns [`true`] if this is a unique local address (fc00::/7).
1021     ///
1022     /// This property is defined in [IETF RFC 4193].
1023     ///
1024     /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
1025     /// [`true`]: ../../std/primitive.bool.html
1026     ///
1027     /// # Examples
1028     ///
1029     /// ```
1030     /// #![feature(ip)]
1031     ///
1032     /// use std::net::Ipv6Addr;
1033     ///
1034     /// fn main() {
1035     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(),
1036     ///                false);
1037     ///     assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
1038     /// }
1039     /// ```
1040     pub fn is_unique_local(&self) -> bool {
1041         (self.segments()[0] & 0xfe00) == 0xfc00
1042     }
1043
1044     /// Returns [`true`] if the address is unicast and link-local (fe80::/10).
1045     ///
1046     /// This property is defined in [IETF RFC 4291].
1047     ///
1048     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1049     /// [`true`]: ../../std/primitive.bool.html
1050     ///
1051     /// # Examples
1052     ///
1053     /// ```
1054     /// #![feature(ip)]
1055     ///
1056     /// use std::net::Ipv6Addr;
1057     ///
1058     /// fn main() {
1059     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(),
1060     ///                false);
1061     ///     assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
1062     /// }
1063     /// ```
1064     pub fn is_unicast_link_local(&self) -> bool {
1065         (self.segments()[0] & 0xffc0) == 0xfe80
1066     }
1067
1068     /// Returns [`true`] if this is a deprecated unicast site-local address
1069     /// (fec0::/10).
1070     ///
1071     /// [`true`]: ../../std/primitive.bool.html
1072     ///
1073     /// # Examples
1074     ///
1075     /// ```
1076     /// #![feature(ip)]
1077     ///
1078     /// use std::net::Ipv6Addr;
1079     ///
1080     /// fn main() {
1081     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_site_local(),
1082     ///                false);
1083     ///     assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
1084     /// }
1085     /// ```
1086     pub fn is_unicast_site_local(&self) -> bool {
1087         (self.segments()[0] & 0xffc0) == 0xfec0
1088     }
1089
1090     /// Returns [`true`] if this is an address reserved for documentation
1091     /// (2001:db8::/32).
1092     ///
1093     /// This property is defined in [IETF RFC 3849].
1094     ///
1095     /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
1096     /// [`true`]: ../../std/primitive.bool.html
1097     ///
1098     /// # Examples
1099     ///
1100     /// ```
1101     /// #![feature(ip)]
1102     ///
1103     /// use std::net::Ipv6Addr;
1104     ///
1105     /// fn main() {
1106     ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(),
1107     ///                false);
1108     ///     assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
1109     /// }
1110     /// ```
1111     pub fn is_documentation(&self) -> bool {
1112         (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
1113     }
1114
1115     /// Returns [`true`] if the address is a globally routable unicast address.
1116     ///
1117     /// The following return false:
1118     ///
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
1125     ///
1126     /// [`true`]: ../../std/primitive.bool.html
1127     ///
1128     /// # Examples
1129     ///
1130     /// ```
1131     /// #![feature(ip)]
1132     ///
1133     /// use std::net::Ipv6Addr;
1134     ///
1135     /// fn main() {
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(),
1138     ///                true);
1139     /// }
1140     /// ```
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()
1146     }
1147
1148     /// Returns the address's multicast scope if the address is multicast.
1149     ///
1150     /// # Examples
1151     ///
1152     /// ```
1153     /// #![feature(ip)]
1154     ///
1155     /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
1156     ///
1157     /// fn main() {
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);
1161     /// }
1162     /// ```
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),
1173                 _ => None
1174             }
1175         } else {
1176             None
1177         }
1178     }
1179
1180     /// Returns [`true`] if this is a multicast address (ff00::/8).
1181     ///
1182     /// This property is defined by [IETF RFC 4291].
1183     ///
1184     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1185     /// [`true`]: ../../std/primitive.bool.html
1186     ///
1187     /// # Examples
1188     ///
1189     /// ```
1190     /// use std::net::Ipv6Addr;
1191     ///
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);
1194     /// ```
1195     #[stable(since = "1.7.0", feature = "ip_17")]
1196     pub fn is_multicast(&self) -> bool {
1197         (self.segments()[0] & 0xff00) == 0xff00
1198     }
1199
1200     /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
1201     /// neither IPv4-compatible or IPv4-mapped.
1202     ///
1203     /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
1204     ///
1205     /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
1206     /// [`None`]: ../../std/option/enum.Option.html#variant.None
1207     ///
1208     /// # Examples
1209     ///
1210     /// ```
1211     /// use std::net::{Ipv4Addr, Ipv6Addr};
1212     ///
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)));
1218     /// ```
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))
1225             },
1226             _ => None
1227         }
1228     }
1229
1230     /// Returns the sixteen eight-bit integers the IPv6 address consists of.
1231     ///
1232     /// ```
1233     /// use std::net::Ipv6Addr;
1234     ///
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]);
1237     /// ```
1238     #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
1239     pub fn octets(&self) -> [u8; 16] {
1240         self.inner.s6_addr
1241     }
1242 }
1243
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
1249             // as ::0.0.0.[01]
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)
1256             }
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)
1261             },
1262             _ => {
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;
1268
1269                     for i in 0..8 {
1270                         if segments[i] == 0 {
1271                             if cur_span_len == 0 {
1272                                 cur_span_at = i;
1273                             }
1274
1275                             cur_span_len += 1;
1276
1277                             if cur_span_len > longest_span_len {
1278                                 longest_span_len = cur_span_len;
1279                                 longest_span_at = cur_span_at;
1280                             }
1281                         } else {
1282                             cur_span_len = 0;
1283                             cur_span_at = 0;
1284                         }
1285                     }
1286
1287                     (longest_span_at, longest_span_len)
1288                 }
1289
1290                 let (zeros_at, zeros_len) = find_zero_slice(&self.segments());
1291
1292                 if zeros_len > 1 {
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)?;
1298                             }
1299                         }
1300                         Ok(())
1301                     }
1302
1303                     fmt_subslice(&self.segments()[..zeros_at], fmt)?;
1304                     fmt.write_str("::")?;
1305                     fmt_subslice(&self.segments()[zeros_at + zeros_len..], fmt)
1306                 } else {
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)
1310                 }
1311             }
1312         }
1313     }
1314 }
1315
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)
1320     }
1321 }
1322
1323 #[stable(feature = "rust1", since = "1.0.0")]
1324 impl Clone for Ipv6Addr {
1325     fn clone(&self) -> Ipv6Addr { *self }
1326 }
1327
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
1332     }
1333 }
1334
1335 #[stable(feature = "ip_cmp", since = "1.16.0")]
1336 impl PartialEq<IpAddr> for Ipv6Addr {
1337     fn eq(&self, other: &IpAddr) -> bool {
1338         match *other {
1339             IpAddr::V4(_) => false,
1340             IpAddr::V6(ref v6) => self == v6,
1341         }
1342     }
1343 }
1344
1345 #[stable(feature = "ip_cmp", since = "1.16.0")]
1346 impl PartialEq<Ipv6Addr> for IpAddr {
1347     fn eq(&self, other: &Ipv6Addr) -> bool {
1348         match *self {
1349             IpAddr::V4(_) => false,
1350             IpAddr::V6(ref v6) => v6 == other,
1351         }
1352     }
1353 }
1354
1355 #[stable(feature = "rust1", since = "1.0.0")]
1356 impl Eq for Ipv6Addr {}
1357
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)
1362     }
1363 }
1364
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))
1369     }
1370 }
1371
1372 #[stable(feature = "ip_cmp", since = "1.16.0")]
1373 impl PartialOrd<Ipv6Addr> for IpAddr {
1374     fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
1375         match *self {
1376             IpAddr::V4(_) => Some(Ordering::Less),
1377             IpAddr::V6(ref v6) => v6.partial_cmp(other),
1378         }
1379     }
1380 }
1381
1382 #[stable(feature = "ip_cmp", since = "1.16.0")]
1383 impl PartialOrd<IpAddr> for Ipv6Addr {
1384     fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
1385         match *other {
1386             IpAddr::V4(_) => Some(Ordering::Greater),
1387             IpAddr::V6(ref v6) => self.partial_cmp(v6),
1388         }
1389     }
1390 }
1391
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())
1396     }
1397 }
1398
1399 impl AsInner<c::in6_addr> for Ipv6Addr {
1400     fn as_inner(&self) -> &c::in6_addr { &self.inner }
1401 }
1402 impl FromInner<c::in6_addr> for Ipv6Addr {
1403     fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
1404         Ipv6Addr { inner: addr }
1405     }
1406 }
1407
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)
1415     }
1416 }
1417 #[stable(feature = "i128", since = "1.26.0")]
1418 impl From<u128> for Ipv6Addr {
1419     fn from(ip: u128) -> Ipv6Addr {
1420         Ipv6Addr::new(
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,
1424         )
1425     }
1426 }
1427
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)
1433     }
1434 }
1435
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)
1441     }
1442 }
1443
1444
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.
1448     ///
1449     /// # Examples
1450     ///
1451     /// ```
1452     /// use std::net::{IpAddr, Ipv6Addr};
1453     ///
1454     /// let addr = IpAddr::from([
1455     ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
1456     ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
1457     /// ]);
1458     /// assert_eq!(
1459     ///     IpAddr::V6(Ipv6Addr::new(
1460     ///         0x1918, 0x1716,
1461     ///         0x1514, 0x1312,
1462     ///         0x1110, 0x0f0e,
1463     ///         0x0d0c, 0x0b0a
1464     ///     )),
1465     ///     addr
1466     /// );
1467     /// ```
1468     fn from(octets: [u8; 16]) -> IpAddr {
1469         IpAddr::V6(Ipv6Addr::from(octets))
1470     }
1471 }
1472
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.
1476     ///
1477     /// # Examples
1478     ///
1479     /// ```
1480     /// use std::net::{IpAddr, Ipv6Addr};
1481     ///
1482     /// let addr = IpAddr::from([
1483     ///     525u16, 524u16, 523u16, 522u16,
1484     ///     521u16, 520u16, 519u16, 518u16,
1485     /// ]);
1486     /// assert_eq!(
1487     ///     IpAddr::V6(Ipv6Addr::new(
1488     ///         0x20d, 0x20c,
1489     ///         0x20b, 0x20a,
1490     ///         0x209, 0x208,
1491     ///         0x207, 0x206
1492     ///     )),
1493     ///     addr
1494     /// );
1495     /// ```
1496     fn from(segments: [u16; 8]) -> IpAddr {
1497         IpAddr::V6(Ipv6Addr::from(segments))
1498     }
1499 }
1500
1501 // Tests for this module
1502 #[cfg(all(test, not(target_os = "emscripten")))]
1503 mod tests {
1504     use net::*;
1505     use net::Ipv6MulticastScope::*;
1506     use net::test::{tsa, sa6, sa4};
1507
1508     #[test]
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());
1513
1514         // out of range
1515         let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
1516         assert_eq!(None, none);
1517         // too short
1518         let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
1519         assert_eq!(None, none);
1520         // too long
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);
1526     }
1527
1528     #[test]
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());
1532
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());
1535
1536         assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
1537                 "2a02:6b8::11:11".parse());
1538
1539         // too long group
1540         let none: Option<Ipv6Addr> = "::00000".parse().ok();
1541         assert_eq!(None, none);
1542         // too short
1543         let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
1544         assert_eq!(None, none);
1545         // too long
1546         let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
1547         assert_eq!(None, none);
1548         // triple colon
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);
1557     }
1558
1559     #[test]
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());
1569
1570         // colon after v4
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);
1576         // too many groups
1577         let none: Option<Ipv6Addr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
1578         assert_eq!(None, none);
1579     }
1580
1581     #[test]
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());
1597
1598         // without port
1599         let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
1600         assert_eq!(None, none);
1601         // without port
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);
1610     }
1611
1612     #[test]
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");
1617
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");
1621
1622         // v6 address with no zero segments
1623         assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
1624                    "8:9:a:b:c:d:e:f");
1625
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());
1629
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());
1633
1634         // 'any' address
1635         assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
1636
1637         // loopback address
1638         assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
1639
1640         // ends in zeros
1641         assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
1642
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());
1645
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());
1648     }
1649
1650     #[test]
1651     fn ipv4_to_ipv6() {
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());
1656     }
1657
1658     #[test]
1659     fn ipv6_to_ipv4() {
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(),
1665                    None);
1666     }
1667
1668     #[test]
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);
1678         }
1679
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);
1688         }
1689
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);
1707
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);
1727     }
1728
1729     #[test]
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());
1736
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);
1745         }
1746
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);
1764     }
1765
1766     #[test]
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);
1776
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());
1787         }
1788
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);
1828     }
1829
1830     #[test]
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));
1834     }
1835
1836     #[test]
1837     fn test_ipv4_to_int() {
1838         let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
1839         assert_eq!(u32::from(a), 0x11223344);
1840     }
1841
1842     #[test]
1843     fn test_int_to_ipv4() {
1844         let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
1845         assert_eq!(Ipv4Addr::from(0x11223344), a);
1846     }
1847
1848     #[test]
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);
1852     }
1853
1854     #[test]
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);
1858     }
1859
1860     #[test]
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());
1868     }
1869
1870     #[test]
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());
1876     }
1877
1878     #[test]
1879     fn ipv4_from_octets() {
1880         assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
1881     }
1882
1883     #[test]
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);
1890     }
1891
1892     #[test]
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);
1899     }
1900
1901     #[test]
1902     fn cmp() {
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();
1907         assert!(v41 < v42);
1908         assert!(v61 < v62);
1909
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));
1914
1915         assert!(v41 < IpAddr::V4(v42));
1916         assert!(v61 < IpAddr::V6(v62));
1917         assert!(IpAddr::V4(v41) < v42);
1918         assert!(IpAddr::V6(v61) < v62);
1919
1920         assert!(v41 < IpAddr::V6(v61));
1921         assert!(IpAddr::V4(v41) < v61);
1922     }
1923
1924     #[test]
1925     fn is_v4() {
1926         let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
1927         assert!(ip.is_ipv4());
1928         assert!(!ip.is_ipv6());
1929     }
1930
1931     #[test]
1932     fn is_v6() {
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());
1936     }
1937 }