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