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