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