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