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