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