core/net/
ip_addr.rs

1use super::display_buffer::DisplayBuffer;
2use crate::cmp::Ordering;
3use crate::fmt::{self, Write};
4use crate::hash::{Hash, Hasher};
5use crate::iter;
6use crate::mem::transmute;
7use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
8
9/// An IP address, either IPv4 or IPv6.
10///
11/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
12/// respective documentation for more details.
13///
14/// # Examples
15///
16/// ```
17/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
18///
19/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
20/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
21///
22/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
23/// assert_eq!("::1".parse(), Ok(localhost_v6));
24///
25/// assert_eq!(localhost_v4.is_ipv6(), false);
26/// assert_eq!(localhost_v4.is_ipv4(), true);
27/// ```
28#[rustc_diagnostic_item = "IpAddr"]
29#[stable(feature = "ip_addr", since = "1.7.0")]
30#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
31pub enum IpAddr {
32    /// An IPv4 address.
33    #[stable(feature = "ip_addr", since = "1.7.0")]
34    V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
35    /// An IPv6 address.
36    #[stable(feature = "ip_addr", since = "1.7.0")]
37    V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
38}
39
40/// An IPv4 address.
41///
42/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
43/// They are usually represented as four octets.
44///
45/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
46///
47/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
48///
49/// # Textual representation
50///
51/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
52/// notation, divided by `.` (this is called "dot-decimal notation").
53/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which
54/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943].
55///
56/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1
57/// [`FromStr`]: crate::str::FromStr
58///
59/// # Examples
60///
61/// ```
62/// use std::net::Ipv4Addr;
63///
64/// let localhost = Ipv4Addr::new(127, 0, 0, 1);
65/// assert_eq!("127.0.0.1".parse(), Ok(localhost));
66/// assert_eq!(localhost.is_loopback(), true);
67/// assert!("012.004.002.000".parse::<Ipv4Addr>().is_err()); // all octets are in octal
68/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
69/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
70/// ```
71#[derive(Copy, Clone, PartialEq, Eq)]
72#[stable(feature = "rust1", since = "1.0.0")]
73pub struct Ipv4Addr {
74    octets: [u8; 4],
75}
76
77#[stable(feature = "rust1", since = "1.0.0")]
78impl Hash for Ipv4Addr {
79    fn hash<H: Hasher>(&self, state: &mut H) {
80        // Hashers are often more efficient at hashing a fixed-width integer
81        // than a bytestring, so convert before hashing. We don't use to_bits()
82        // here as that may involve a byteswap which is unnecessary.
83        u32::from_ne_bytes(self.octets).hash(state);
84    }
85}
86
87/// An IPv6 address.
88///
89/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
90/// They are usually represented as eight 16-bit segments.
91///
92/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
93///
94/// # Embedding IPv4 Addresses
95///
96/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
97///
98/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined:
99/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated.
100///
101/// Both types of addresses are not assigned any special meaning by this implementation,
102/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`,
103/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is.
104/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address.
105///
106/// ### IPv4-Compatible IPv6 Addresses
107///
108/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated.
109/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows:
110///
111/// ```text
112/// |                80 bits               | 16 |      32 bits        |
113/// +--------------------------------------+--------------------------+
114/// |0000..............................0000|0000|    IPv4 address     |
115/// +--------------------------------------+----+---------------------+
116/// ```
117/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`.
118///
119/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`].
120/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address.
121///
122/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1
123///
124/// ### IPv4-Mapped IPv6 Addresses
125///
126/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2].
127/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows:
128///
129/// ```text
130/// |                80 bits               | 16 |      32 bits        |
131/// +--------------------------------------+--------------------------+
132/// |0000..............................0000|FFFF|    IPv4 address     |
133/// +--------------------------------------+----+---------------------+
134/// ```
135/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`.
136///
137/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`].
138/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address.
139/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use
140/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
141///
142/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2
143///
144/// # Textual representation
145///
146/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
147/// an IPv6 address in text, but in general, each segments is written in hexadecimal
148/// notation, and segments are separated by `:`. For more information, see
149/// [IETF RFC 5952].
150///
151/// [`FromStr`]: crate::str::FromStr
152/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
153///
154/// # Examples
155///
156/// ```
157/// use std::net::Ipv6Addr;
158///
159/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
160/// assert_eq!("::1".parse(), Ok(localhost));
161/// assert_eq!(localhost.is_loopback(), true);
162/// ```
163#[derive(Copy, Clone, PartialEq, Eq)]
164#[stable(feature = "rust1", since = "1.0.0")]
165pub struct Ipv6Addr {
166    octets: [u8; 16],
167}
168
169#[stable(feature = "rust1", since = "1.0.0")]
170impl Hash for Ipv6Addr {
171    fn hash<H: Hasher>(&self, state: &mut H) {
172        // Hashers are often more efficient at hashing a fixed-width integer
173        // than a bytestring, so convert before hashing. We don't use to_bits()
174        // here as that may involve unnecessary byteswaps.
175        u128::from_ne_bytes(self.octets).hash(state);
176    }
177}
178
179/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
180///
181/// # Stability Guarantees
182///
183/// Not all possible values for a multicast scope have been assigned.
184/// Future RFCs may introduce new scopes, which will be added as variants to this enum;
185/// because of this the enum is marked as `#[non_exhaustive]`.
186///
187/// # Examples
188/// ```
189/// #![feature(ip)]
190///
191/// use std::net::Ipv6Addr;
192/// use std::net::Ipv6MulticastScope::*;
193///
194/// // An IPv6 multicast address with global scope (`ff0e::`).
195/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0);
196///
197/// // Will print "Global scope".
198/// match address.multicast_scope() {
199///     Some(InterfaceLocal) => println!("Interface-Local scope"),
200///     Some(LinkLocal) => println!("Link-Local scope"),
201///     Some(RealmLocal) => println!("Realm-Local scope"),
202///     Some(AdminLocal) => println!("Admin-Local scope"),
203///     Some(SiteLocal) => println!("Site-Local scope"),
204///     Some(OrganizationLocal) => println!("Organization-Local scope"),
205///     Some(Global) => println!("Global scope"),
206///     Some(_) => println!("Unknown scope"),
207///     None => println!("Not a multicast address!")
208/// }
209///
210/// ```
211///
212/// [IPv6 multicast address]: Ipv6Addr
213/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2
214#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
215#[unstable(feature = "ip", issue = "27709")]
216#[non_exhaustive]
217pub enum Ipv6MulticastScope {
218    /// Interface-Local scope.
219    InterfaceLocal,
220    /// Link-Local scope.
221    LinkLocal,
222    /// Realm-Local scope.
223    RealmLocal,
224    /// Admin-Local scope.
225    AdminLocal,
226    /// Site-Local scope.
227    SiteLocal,
228    /// Organization-Local scope.
229    OrganizationLocal,
230    /// Global scope.
231    Global,
232}
233
234impl IpAddr {
235    /// Returns [`true`] for the special 'unspecified' address.
236    ///
237    /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
238    /// [`Ipv6Addr::is_unspecified()`] for more details.
239    ///
240    /// # Examples
241    ///
242    /// ```
243    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
244    ///
245    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
246    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
247    /// ```
248    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
249    #[stable(feature = "ip_shared", since = "1.12.0")]
250    #[must_use]
251    #[inline]
252    pub const fn is_unspecified(&self) -> bool {
253        match self {
254            IpAddr::V4(ip) => ip.is_unspecified(),
255            IpAddr::V6(ip) => ip.is_unspecified(),
256        }
257    }
258
259    /// Returns [`true`] if this is a loopback address.
260    ///
261    /// See the documentation for [`Ipv4Addr::is_loopback()`] and
262    /// [`Ipv6Addr::is_loopback()`] for more details.
263    ///
264    /// # Examples
265    ///
266    /// ```
267    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
268    ///
269    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
270    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
271    /// ```
272    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
273    #[stable(feature = "ip_shared", since = "1.12.0")]
274    #[must_use]
275    #[inline]
276    pub const fn is_loopback(&self) -> bool {
277        match self {
278            IpAddr::V4(ip) => ip.is_loopback(),
279            IpAddr::V6(ip) => ip.is_loopback(),
280        }
281    }
282
283    /// Returns [`true`] if the address appears to be globally routable.
284    ///
285    /// See the documentation for [`Ipv4Addr::is_global()`] and
286    /// [`Ipv6Addr::is_global()`] for more details.
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// #![feature(ip)]
292    ///
293    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
294    ///
295    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
296    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
297    /// ```
298    #[unstable(feature = "ip", issue = "27709")]
299    #[must_use]
300    #[inline]
301    pub const fn is_global(&self) -> bool {
302        match self {
303            IpAddr::V4(ip) => ip.is_global(),
304            IpAddr::V6(ip) => ip.is_global(),
305        }
306    }
307
308    /// Returns [`true`] if this is a multicast address.
309    ///
310    /// See the documentation for [`Ipv4Addr::is_multicast()`] and
311    /// [`Ipv6Addr::is_multicast()`] for more details.
312    ///
313    /// # Examples
314    ///
315    /// ```
316    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
317    ///
318    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
319    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
320    /// ```
321    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
322    #[stable(feature = "ip_shared", since = "1.12.0")]
323    #[must_use]
324    #[inline]
325    pub const fn is_multicast(&self) -> bool {
326        match self {
327            IpAddr::V4(ip) => ip.is_multicast(),
328            IpAddr::V6(ip) => ip.is_multicast(),
329        }
330    }
331
332    /// Returns [`true`] if this address is in a range designated for documentation.
333    ///
334    /// See the documentation for [`Ipv4Addr::is_documentation()`] and
335    /// [`Ipv6Addr::is_documentation()`] for more details.
336    ///
337    /// # Examples
338    ///
339    /// ```
340    /// #![feature(ip)]
341    ///
342    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
343    ///
344    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
345    /// assert_eq!(
346    ///     IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(),
347    ///     true
348    /// );
349    /// ```
350    #[unstable(feature = "ip", issue = "27709")]
351    #[must_use]
352    #[inline]
353    pub const fn is_documentation(&self) -> bool {
354        match self {
355            IpAddr::V4(ip) => ip.is_documentation(),
356            IpAddr::V6(ip) => ip.is_documentation(),
357        }
358    }
359
360    /// Returns [`true`] if this address is in a range designated for benchmarking.
361    ///
362    /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and
363    /// [`Ipv6Addr::is_benchmarking()`] for more details.
364    ///
365    /// # Examples
366    ///
367    /// ```
368    /// #![feature(ip)]
369    ///
370    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
371    ///
372    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true);
373    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true);
374    /// ```
375    #[unstable(feature = "ip", issue = "27709")]
376    #[must_use]
377    #[inline]
378    pub const fn is_benchmarking(&self) -> bool {
379        match self {
380            IpAddr::V4(ip) => ip.is_benchmarking(),
381            IpAddr::V6(ip) => ip.is_benchmarking(),
382        }
383    }
384
385    /// Returns [`true`] if this address is an [`IPv4` address], and [`false`]
386    /// otherwise.
387    ///
388    /// [`IPv4` address]: IpAddr::V4
389    ///
390    /// # Examples
391    ///
392    /// ```
393    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
394    ///
395    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
396    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
397    /// ```
398    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
399    #[stable(feature = "ipaddr_checker", since = "1.16.0")]
400    #[must_use]
401    #[inline]
402    pub const fn is_ipv4(&self) -> bool {
403        matches!(self, IpAddr::V4(_))
404    }
405
406    /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
407    /// otherwise.
408    ///
409    /// [`IPv6` address]: IpAddr::V6
410    ///
411    /// # Examples
412    ///
413    /// ```
414    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
415    ///
416    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
417    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
418    /// ```
419    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
420    #[stable(feature = "ipaddr_checker", since = "1.16.0")]
421    #[must_use]
422    #[inline]
423    pub const fn is_ipv6(&self) -> bool {
424        matches!(self, IpAddr::V6(_))
425    }
426
427    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6
428    /// address, otherwise returns `self` as-is.
429    ///
430    /// # Examples
431    ///
432    /// ```
433    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
434    ///
435    /// let localhost_v4 = Ipv4Addr::new(127, 0, 0, 1);
436    ///
437    /// assert_eq!(IpAddr::V4(localhost_v4).to_canonical(), localhost_v4);
438    /// assert_eq!(IpAddr::V6(localhost_v4.to_ipv6_mapped()).to_canonical(), localhost_v4);
439    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
440    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
441    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true);
442    /// ```
443    #[inline]
444    #[must_use = "this returns the result of the operation, \
445                  without modifying the original"]
446    #[stable(feature = "ip_to_canonical", since = "1.75.0")]
447    #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")]
448    pub const fn to_canonical(&self) -> IpAddr {
449        match self {
450            IpAddr::V4(_) => *self,
451            IpAddr::V6(v6) => v6.to_canonical(),
452        }
453    }
454
455    /// Returns the eight-bit integers this address consists of as a slice.
456    ///
457    /// # Examples
458    ///
459    /// ```
460    /// #![feature(ip_as_octets)]
461    ///
462    /// use std::net::{Ipv4Addr, Ipv6Addr, IpAddr};
463    ///
464    /// assert_eq!(IpAddr::V4(Ipv4Addr::LOCALHOST).as_octets(), &[127, 0, 0, 1]);
465    /// assert_eq!(IpAddr::V6(Ipv6Addr::LOCALHOST).as_octets(),
466    ///            &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
467    /// ```
468    #[unstable(feature = "ip_as_octets", issue = "137259")]
469    #[inline]
470    pub const fn as_octets(&self) -> &[u8] {
471        match self {
472            IpAddr::V4(ip) => ip.as_octets().as_slice(),
473            IpAddr::V6(ip) => ip.as_octets().as_slice(),
474        }
475    }
476}
477
478impl Ipv4Addr {
479    /// Creates a new IPv4 address from four eight-bit octets.
480    ///
481    /// The result will represent the IP address `a`.`b`.`c`.`d`.
482    ///
483    /// # Examples
484    ///
485    /// ```
486    /// use std::net::Ipv4Addr;
487    ///
488    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
489    /// ```
490    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
491    #[stable(feature = "rust1", since = "1.0.0")]
492    #[must_use]
493    #[inline]
494    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
495        Ipv4Addr { octets: [a, b, c, d] }
496    }
497
498    /// The size of an IPv4 address in bits.
499    ///
500    /// # Examples
501    ///
502    /// ```
503    /// use std::net::Ipv4Addr;
504    ///
505    /// assert_eq!(Ipv4Addr::BITS, 32);
506    /// ```
507    #[stable(feature = "ip_bits", since = "1.80.0")]
508    pub const BITS: u32 = 32;
509
510    /// Converts an IPv4 address into a `u32` representation using native byte order.
511    ///
512    /// Although IPv4 addresses are big-endian, the `u32` value will use the target platform's
513    /// native byte order. That is, the `u32` value is an integer representation of the IPv4
514    /// address and not an integer interpretation of the IPv4 address's big-endian bitstring. This
515    /// means that the `u32` value masked with `0xffffff00` will set the last octet in the address
516    /// to 0, regardless of the target platform's endianness.
517    ///
518    /// # Examples
519    ///
520    /// ```
521    /// use std::net::Ipv4Addr;
522    ///
523    /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
524    /// assert_eq!(0x12345678, addr.to_bits());
525    /// ```
526    ///
527    /// ```
528    /// use std::net::Ipv4Addr;
529    ///
530    /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
531    /// let addr_bits = addr.to_bits() & 0xffffff00;
532    /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x00), Ipv4Addr::from_bits(addr_bits));
533    ///
534    /// ```
535    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
536    #[stable(feature = "ip_bits", since = "1.80.0")]
537    #[must_use]
538    #[inline]
539    pub const fn to_bits(self) -> u32 {
540        u32::from_be_bytes(self.octets)
541    }
542
543    /// Converts a native byte order `u32` into an IPv4 address.
544    ///
545    /// See [`Ipv4Addr::to_bits`] for an explanation on endianness.
546    ///
547    /// # Examples
548    ///
549    /// ```
550    /// use std::net::Ipv4Addr;
551    ///
552    /// let addr = Ipv4Addr::from_bits(0x12345678);
553    /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);
554    /// ```
555    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
556    #[stable(feature = "ip_bits", since = "1.80.0")]
557    #[must_use]
558    #[inline]
559    pub const fn from_bits(bits: u32) -> Ipv4Addr {
560        Ipv4Addr { octets: bits.to_be_bytes() }
561    }
562
563    /// An IPv4 address with the address pointing to localhost: `127.0.0.1`
564    ///
565    /// # Examples
566    ///
567    /// ```
568    /// use std::net::Ipv4Addr;
569    ///
570    /// let addr = Ipv4Addr::LOCALHOST;
571    /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
572    /// ```
573    #[stable(feature = "ip_constructors", since = "1.30.0")]
574    pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
575
576    /// An IPv4 address representing an unspecified address: `0.0.0.0`
577    ///
578    /// This corresponds to the constant `INADDR_ANY` in other languages.
579    ///
580    /// # Examples
581    ///
582    /// ```
583    /// use std::net::Ipv4Addr;
584    ///
585    /// let addr = Ipv4Addr::UNSPECIFIED;
586    /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
587    /// ```
588    #[doc(alias = "INADDR_ANY")]
589    #[stable(feature = "ip_constructors", since = "1.30.0")]
590    pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
591
592    /// An IPv4 address representing the broadcast address: `255.255.255.255`.
593    ///
594    /// # Examples
595    ///
596    /// ```
597    /// use std::net::Ipv4Addr;
598    ///
599    /// let addr = Ipv4Addr::BROADCAST;
600    /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
601    /// ```
602    #[stable(feature = "ip_constructors", since = "1.30.0")]
603    pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
604
605    /// Returns the four eight-bit integers that make up this address.
606    ///
607    /// # Examples
608    ///
609    /// ```
610    /// use std::net::Ipv4Addr;
611    ///
612    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
613    /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
614    /// ```
615    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
616    #[stable(feature = "rust1", since = "1.0.0")]
617    #[must_use]
618    #[inline]
619    pub const fn octets(&self) -> [u8; 4] {
620        self.octets
621    }
622
623    /// Creates an `Ipv4Addr` from a four element byte array.
624    ///
625    /// # Examples
626    ///
627    /// ```
628    /// #![feature(ip_from)]
629    /// use std::net::Ipv4Addr;
630    ///
631    /// let addr = Ipv4Addr::from_octets([13u8, 12u8, 11u8, 10u8]);
632    /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
633    /// ```
634    #[unstable(feature = "ip_from", issue = "131360")]
635    #[must_use]
636    #[inline]
637    pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr {
638        Ipv4Addr { octets }
639    }
640
641    /// Returns the four eight-bit integers that make up this address
642    /// as a slice.
643    ///
644    /// # Examples
645    ///
646    /// ```
647    /// #![feature(ip_as_octets)]
648    ///
649    /// use std::net::Ipv4Addr;
650    ///
651    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
652    /// assert_eq!(addr.as_octets(), &[127, 0, 0, 1]);
653    /// ```
654    #[unstable(feature = "ip_as_octets", issue = "137259")]
655    #[inline]
656    pub const fn as_octets(&self) -> &[u8; 4] {
657        &self.octets
658    }
659
660    /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
661    ///
662    /// This property is defined in _UNIX Network Programming, Second Edition_,
663    /// W. Richard Stevens, p. 891; see also [ip7].
664    ///
665    /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html
666    ///
667    /// # Examples
668    ///
669    /// ```
670    /// use std::net::Ipv4Addr;
671    ///
672    /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
673    /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
674    /// ```
675    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
676    #[stable(feature = "ip_shared", since = "1.12.0")]
677    #[must_use]
678    #[inline]
679    pub const fn is_unspecified(&self) -> bool {
680        u32::from_be_bytes(self.octets) == 0
681    }
682
683    /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`).
684    ///
685    /// This property is defined by [IETF RFC 1122].
686    ///
687    /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
688    ///
689    /// # Examples
690    ///
691    /// ```
692    /// use std::net::Ipv4Addr;
693    ///
694    /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
695    /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
696    /// ```
697    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
698    #[stable(since = "1.7.0", feature = "ip_17")]
699    #[must_use]
700    #[inline]
701    pub const fn is_loopback(&self) -> bool {
702        self.octets()[0] == 127
703    }
704
705    /// Returns [`true`] if this is a private address.
706    ///
707    /// The private address ranges are defined in [IETF RFC 1918] and include:
708    ///
709    ///  - `10.0.0.0/8`
710    ///  - `172.16.0.0/12`
711    ///  - `192.168.0.0/16`
712    ///
713    /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
714    ///
715    /// # Examples
716    ///
717    /// ```
718    /// use std::net::Ipv4Addr;
719    ///
720    /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
721    /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
722    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
723    /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
724    /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
725    /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
726    /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
727    /// ```
728    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
729    #[stable(since = "1.7.0", feature = "ip_17")]
730    #[must_use]
731    #[inline]
732    pub const fn is_private(&self) -> bool {
733        match self.octets() {
734            [10, ..] => true,
735            [172, b, ..] if b >= 16 && b <= 31 => true,
736            [192, 168, ..] => true,
737            _ => false,
738        }
739    }
740
741    /// Returns [`true`] if the address is link-local (`169.254.0.0/16`).
742    ///
743    /// This property is defined by [IETF RFC 3927].
744    ///
745    /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
746    ///
747    /// # Examples
748    ///
749    /// ```
750    /// use std::net::Ipv4Addr;
751    ///
752    /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
753    /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
754    /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
755    /// ```
756    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
757    #[stable(since = "1.7.0", feature = "ip_17")]
758    #[must_use]
759    #[inline]
760    pub const fn is_link_local(&self) -> bool {
761        matches!(self.octets(), [169, 254, ..])
762    }
763
764    /// Returns [`true`] if the address appears to be globally reachable
765    /// as specified by the [IANA IPv4 Special-Purpose Address Registry].
766    ///
767    /// Whether or not an address is practically reachable will depend on your
768    /// network configuration. Most IPv4 addresses are globally reachable, unless
769    /// they are specifically defined as *not* globally reachable.
770    ///
771    /// Non-exhaustive list of notable addresses that are not globally reachable:
772    ///
773    /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified))
774    /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private))
775    /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared))
776    /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback))
777    /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local))
778    /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation))
779    /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking))
780    /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved))
781    /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast))
782    ///
783    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry].
784    ///
785    /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
786    /// [unspecified address]: Ipv4Addr::UNSPECIFIED
787    /// [broadcast address]: Ipv4Addr::BROADCAST
788
789    ///
790    /// # Examples
791    ///
792    /// ```
793    /// #![feature(ip)]
794    ///
795    /// use std::net::Ipv4Addr;
796    ///
797    /// // Most IPv4 addresses are globally reachable:
798    /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
799    ///
800    /// // However some addresses have been assigned a special meaning
801    /// // that makes them not globally reachable. Some examples are:
802    ///
803    /// // The unspecified address (`0.0.0.0`)
804    /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false);
805    ///
806    /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16)
807    /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
808    /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
809    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
810    ///
811    /// // Addresses in the shared address space (`100.64.0.0/10`)
812    /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
813    ///
814    /// // The loopback addresses (`127.0.0.0/8`)
815    /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false);
816    ///
817    /// // Link-local addresses (`169.254.0.0/16`)
818    /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
819    ///
820    /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)
821    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
822    /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
823    /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
824    ///
825    /// // Addresses reserved for benchmarking (`198.18.0.0/15`)
826    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
827    ///
828    /// // Reserved addresses (`240.0.0.0/4`)
829    /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
830    ///
831    /// // The broadcast address (`255.255.255.255`)
832    /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false);
833    ///
834    /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
835    /// ```
836    #[unstable(feature = "ip", issue = "27709")]
837    #[must_use]
838    #[inline]
839    pub const fn is_global(&self) -> bool {
840        !(self.octets()[0] == 0 // "This network"
841            || self.is_private()
842            || self.is_shared()
843            || self.is_loopback()
844            || self.is_link_local()
845            // addresses reserved for future protocols (`192.0.0.0/24`)
846            // .9 and .10 are documented as globally reachable so they're excluded
847            || (
848                self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
849                && self.octets()[3] != 9 && self.octets()[3] != 10
850            )
851            || self.is_documentation()
852            || self.is_benchmarking()
853            || self.is_reserved()
854            || self.is_broadcast())
855    }
856
857    /// Returns [`true`] if this address is part of the Shared Address Space defined in
858    /// [IETF RFC 6598] (`100.64.0.0/10`).
859    ///
860    /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
861    ///
862    /// # Examples
863    ///
864    /// ```
865    /// #![feature(ip)]
866    /// use std::net::Ipv4Addr;
867    ///
868    /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
869    /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
870    /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
871    /// ```
872    #[unstable(feature = "ip", issue = "27709")]
873    #[must_use]
874    #[inline]
875    pub const fn is_shared(&self) -> bool {
876        self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
877    }
878
879    /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
880    /// network devices benchmarking.
881    ///
882    /// This range is defined in [IETF RFC 2544] as `192.18.0.0` through
883    /// `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
884    ///
885    /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
886    /// [errata 423]: https://www.rfc-editor.org/errata/eid423
887    ///
888    /// # Examples
889    ///
890    /// ```
891    /// #![feature(ip)]
892    /// use std::net::Ipv4Addr;
893    ///
894    /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
895    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
896    /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
897    /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
898    /// ```
899    #[unstable(feature = "ip", issue = "27709")]
900    #[must_use]
901    #[inline]
902    pub const fn is_benchmarking(&self) -> bool {
903        self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
904    }
905
906    /// Returns [`true`] if this address is reserved by IANA for future use.
907    ///
908    /// [IETF RFC 1112] defines the block of reserved addresses as `240.0.0.0/4`.
909    /// This range normally includes the broadcast address `255.255.255.255`, but
910    /// this implementation explicitly excludes it, since it is obviously not
911    /// reserved for future use.
912    ///
913    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
914    ///
915    /// # Warning
916    ///
917    /// As IANA assigns new addresses, this method will be
918    /// updated. This may result in non-reserved addresses being
919    /// treated as reserved in code that relies on an outdated version
920    /// of this method.
921    ///
922    /// # Examples
923    ///
924    /// ```
925    /// #![feature(ip)]
926    /// use std::net::Ipv4Addr;
927    ///
928    /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
929    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
930    ///
931    /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
932    /// // The broadcast address is not considered as reserved for future use by this implementation
933    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
934    /// ```
935    #[unstable(feature = "ip", issue = "27709")]
936    #[must_use]
937    #[inline]
938    pub const fn is_reserved(&self) -> bool {
939        self.octets()[0] & 240 == 240 && !self.is_broadcast()
940    }
941
942    /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`).
943    ///
944    /// Multicast addresses have a most significant octet between `224` and `239`,
945    /// and is defined by [IETF RFC 5771].
946    ///
947    /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
948    ///
949    /// # Examples
950    ///
951    /// ```
952    /// use std::net::Ipv4Addr;
953    ///
954    /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
955    /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
956    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
957    /// ```
958    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
959    #[stable(since = "1.7.0", feature = "ip_17")]
960    #[must_use]
961    #[inline]
962    pub const fn is_multicast(&self) -> bool {
963        self.octets()[0] >= 224 && self.octets()[0] <= 239
964    }
965
966    /// Returns [`true`] if this is a broadcast address (`255.255.255.255`).
967    ///
968    /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919].
969    ///
970    /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
971    ///
972    /// # Examples
973    ///
974    /// ```
975    /// use std::net::Ipv4Addr;
976    ///
977    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
978    /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
979    /// ```
980    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
981    #[stable(since = "1.7.0", feature = "ip_17")]
982    #[must_use]
983    #[inline]
984    pub const fn is_broadcast(&self) -> bool {
985        u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
986    }
987
988    /// Returns [`true`] if this address is in a range designated for documentation.
989    ///
990    /// This is defined in [IETF RFC 5737]:
991    ///
992    /// - `192.0.2.0/24` (TEST-NET-1)
993    /// - `198.51.100.0/24` (TEST-NET-2)
994    /// - `203.0.113.0/24` (TEST-NET-3)
995    ///
996    /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
997    ///
998    /// # Examples
999    ///
1000    /// ```
1001    /// use std::net::Ipv4Addr;
1002    ///
1003    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
1004    /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
1005    /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
1006    /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
1007    /// ```
1008    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1009    #[stable(since = "1.7.0", feature = "ip_17")]
1010    #[must_use]
1011    #[inline]
1012    pub const fn is_documentation(&self) -> bool {
1013        matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
1014    }
1015
1016    /// Converts this address to an [IPv4-compatible] [`IPv6` address].
1017    ///
1018    /// `a.b.c.d` becomes `::a.b.c.d`
1019    ///
1020    /// Note that IPv4-compatible addresses have been officially deprecated.
1021    /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead.
1022    ///
1023    /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
1024    /// [`IPv6` address]: Ipv6Addr
1025    ///
1026    /// # Examples
1027    ///
1028    /// ```
1029    /// use std::net::{Ipv4Addr, Ipv6Addr};
1030    ///
1031    /// assert_eq!(
1032    ///     Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
1033    ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff)
1034    /// );
1035    /// ```
1036    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1037    #[stable(feature = "rust1", since = "1.0.0")]
1038    #[must_use = "this returns the result of the operation, \
1039                  without modifying the original"]
1040    #[inline]
1041    pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
1042        let [a, b, c, d] = self.octets();
1043        Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }
1044    }
1045
1046    /// Converts this address to an [IPv4-mapped] [`IPv6` address].
1047    ///
1048    /// `a.b.c.d` becomes `::ffff:a.b.c.d`
1049    ///
1050    /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
1051    /// [`IPv6` address]: Ipv6Addr
1052    ///
1053    /// # Examples
1054    ///
1055    /// ```
1056    /// use std::net::{Ipv4Addr, Ipv6Addr};
1057    ///
1058    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
1059    ///            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff));
1060    /// ```
1061    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1062    #[stable(feature = "rust1", since = "1.0.0")]
1063    #[must_use = "this returns the result of the operation, \
1064                  without modifying the original"]
1065    #[inline]
1066    pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
1067        let [a, b, c, d] = self.octets();
1068        Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }
1069    }
1070}
1071
1072#[stable(feature = "ip_addr", since = "1.7.0")]
1073impl fmt::Display for IpAddr {
1074    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1075        match self {
1076            IpAddr::V4(ip) => ip.fmt(fmt),
1077            IpAddr::V6(ip) => ip.fmt(fmt),
1078        }
1079    }
1080}
1081
1082#[stable(feature = "ip_addr", since = "1.7.0")]
1083impl fmt::Debug for IpAddr {
1084    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1085        fmt::Display::fmt(self, fmt)
1086    }
1087}
1088
1089#[stable(feature = "ip_from_ip", since = "1.16.0")]
1090impl From<Ipv4Addr> for IpAddr {
1091    /// Copies this address to a new `IpAddr::V4`.
1092    ///
1093    /// # Examples
1094    ///
1095    /// ```
1096    /// use std::net::{IpAddr, Ipv4Addr};
1097    ///
1098    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
1099    ///
1100    /// assert_eq!(
1101    ///     IpAddr::V4(addr),
1102    ///     IpAddr::from(addr)
1103    /// )
1104    /// ```
1105    #[inline]
1106    fn from(ipv4: Ipv4Addr) -> IpAddr {
1107        IpAddr::V4(ipv4)
1108    }
1109}
1110
1111#[stable(feature = "ip_from_ip", since = "1.16.0")]
1112impl From<Ipv6Addr> for IpAddr {
1113    /// Copies this address to a new `IpAddr::V6`.
1114    ///
1115    /// # Examples
1116    ///
1117    /// ```
1118    /// use std::net::{IpAddr, Ipv6Addr};
1119    ///
1120    /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
1121    ///
1122    /// assert_eq!(
1123    ///     IpAddr::V6(addr),
1124    ///     IpAddr::from(addr)
1125    /// );
1126    /// ```
1127    #[inline]
1128    fn from(ipv6: Ipv6Addr) -> IpAddr {
1129        IpAddr::V6(ipv6)
1130    }
1131}
1132
1133#[stable(feature = "rust1", since = "1.0.0")]
1134impl fmt::Display for Ipv4Addr {
1135    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1136        let octets = self.octets();
1137
1138        // If there are no alignment requirements, write the IP address directly to `f`.
1139        // Otherwise, write it to a local buffer and then use `f.pad`.
1140        if fmt.precision().is_none() && fmt.width().is_none() {
1141            write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
1142        } else {
1143            const LONGEST_IPV4_ADDR: &str = "255.255.255.255";
1144
1145            let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
1146            // Buffer is long enough for the longest possible IPv4 address, so this should never fail.
1147            write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
1148
1149            fmt.pad(buf.as_str())
1150        }
1151    }
1152}
1153
1154#[stable(feature = "rust1", since = "1.0.0")]
1155impl fmt::Debug for Ipv4Addr {
1156    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1157        fmt::Display::fmt(self, fmt)
1158    }
1159}
1160
1161#[stable(feature = "ip_cmp", since = "1.16.0")]
1162impl PartialEq<Ipv4Addr> for IpAddr {
1163    #[inline]
1164    fn eq(&self, other: &Ipv4Addr) -> bool {
1165        match self {
1166            IpAddr::V4(v4) => v4 == other,
1167            IpAddr::V6(_) => false,
1168        }
1169    }
1170}
1171
1172#[stable(feature = "ip_cmp", since = "1.16.0")]
1173impl PartialEq<IpAddr> for Ipv4Addr {
1174    #[inline]
1175    fn eq(&self, other: &IpAddr) -> bool {
1176        match other {
1177            IpAddr::V4(v4) => self == v4,
1178            IpAddr::V6(_) => false,
1179        }
1180    }
1181}
1182
1183#[stable(feature = "rust1", since = "1.0.0")]
1184impl PartialOrd for Ipv4Addr {
1185    #[inline]
1186    fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
1187        Some(self.cmp(other))
1188    }
1189}
1190
1191#[stable(feature = "ip_cmp", since = "1.16.0")]
1192impl PartialOrd<Ipv4Addr> for IpAddr {
1193    #[inline]
1194    fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
1195        match self {
1196            IpAddr::V4(v4) => v4.partial_cmp(other),
1197            IpAddr::V6(_) => Some(Ordering::Greater),
1198        }
1199    }
1200}
1201
1202#[stable(feature = "ip_cmp", since = "1.16.0")]
1203impl PartialOrd<IpAddr> for Ipv4Addr {
1204    #[inline]
1205    fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
1206        match other {
1207            IpAddr::V4(v4) => self.partial_cmp(v4),
1208            IpAddr::V6(_) => Some(Ordering::Less),
1209        }
1210    }
1211}
1212
1213#[stable(feature = "rust1", since = "1.0.0")]
1214impl Ord for Ipv4Addr {
1215    #[inline]
1216    fn cmp(&self, other: &Ipv4Addr) -> Ordering {
1217        self.octets.cmp(&other.octets)
1218    }
1219}
1220
1221#[stable(feature = "ip_u32", since = "1.1.0")]
1222impl From<Ipv4Addr> for u32 {
1223    /// Uses [`Ipv4Addr::to_bits`] to convert an IPv4 address to a host byte order `u32`.
1224    #[inline]
1225    fn from(ip: Ipv4Addr) -> u32 {
1226        ip.to_bits()
1227    }
1228}
1229
1230#[stable(feature = "ip_u32", since = "1.1.0")]
1231impl From<u32> for Ipv4Addr {
1232    /// Uses [`Ipv4Addr::from_bits`] to convert a host byte order `u32` into an IPv4 address.
1233    #[inline]
1234    fn from(ip: u32) -> Ipv4Addr {
1235        Ipv4Addr::from_bits(ip)
1236    }
1237}
1238
1239#[stable(feature = "from_slice_v4", since = "1.9.0")]
1240impl From<[u8; 4]> for Ipv4Addr {
1241    /// Creates an `Ipv4Addr` from a four element byte array.
1242    ///
1243    /// # Examples
1244    ///
1245    /// ```
1246    /// use std::net::Ipv4Addr;
1247    ///
1248    /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
1249    /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
1250    /// ```
1251    #[inline]
1252    fn from(octets: [u8; 4]) -> Ipv4Addr {
1253        Ipv4Addr { octets }
1254    }
1255}
1256
1257#[stable(feature = "ip_from_slice", since = "1.17.0")]
1258impl From<[u8; 4]> for IpAddr {
1259    /// Creates an `IpAddr::V4` from a four element byte array.
1260    ///
1261    /// # Examples
1262    ///
1263    /// ```
1264    /// use std::net::{IpAddr, Ipv4Addr};
1265    ///
1266    /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
1267    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
1268    /// ```
1269    #[inline]
1270    fn from(octets: [u8; 4]) -> IpAddr {
1271        IpAddr::V4(Ipv4Addr::from(octets))
1272    }
1273}
1274
1275impl Ipv6Addr {
1276    /// Creates a new IPv6 address from eight 16-bit segments.
1277    ///
1278    /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
1279    ///
1280    /// # Examples
1281    ///
1282    /// ```
1283    /// use std::net::Ipv6Addr;
1284    ///
1285    /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
1286    /// ```
1287    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
1288    #[stable(feature = "rust1", since = "1.0.0")]
1289    #[must_use]
1290    #[inline]
1291    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
1292        let addr16 = [
1293            a.to_be(),
1294            b.to_be(),
1295            c.to_be(),
1296            d.to_be(),
1297            e.to_be(),
1298            f.to_be(),
1299            g.to_be(),
1300            h.to_be(),
1301        ];
1302        Ipv6Addr {
1303            // All elements in `addr16` are big endian.
1304            // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
1305            octets: unsafe { transmute::<_, [u8; 16]>(addr16) },
1306        }
1307    }
1308
1309    /// The size of an IPv6 address in bits.
1310    ///
1311    /// # Examples
1312    ///
1313    /// ```
1314    /// use std::net::Ipv6Addr;
1315    ///
1316    /// assert_eq!(Ipv6Addr::BITS, 128);
1317    /// ```
1318    #[stable(feature = "ip_bits", since = "1.80.0")]
1319    pub const BITS: u32 = 128;
1320
1321    /// Converts an IPv6 address into a `u128` representation using native byte order.
1322    ///
1323    /// Although IPv6 addresses are big-endian, the `u128` value will use the target platform's
1324    /// native byte order. That is, the `u128` value is an integer representation of the IPv6
1325    /// address and not an integer interpretation of the IPv6 address's big-endian bitstring. This
1326    /// means that the `u128` value masked with `0xffffffffffffffffffffffffffff0000_u128` will set
1327    /// the last segment in the address to 0, regardless of the target platform's endianness.
1328    ///
1329    /// # Examples
1330    ///
1331    /// ```
1332    /// use std::net::Ipv6Addr;
1333    ///
1334    /// let addr = Ipv6Addr::new(
1335    ///     0x1020, 0x3040, 0x5060, 0x7080,
1336    ///     0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1337    /// );
1338    /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, addr.to_bits());
1339    /// ```
1340    ///
1341    /// ```
1342    /// use std::net::Ipv6Addr;
1343    ///
1344    /// let addr = Ipv6Addr::new(
1345    ///     0x1020, 0x3040, 0x5060, 0x7080,
1346    ///     0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1347    /// );
1348    /// let addr_bits = addr.to_bits() & 0xffffffffffffffffffffffffffff0000_u128;
1349    /// assert_eq!(
1350    ///     Ipv6Addr::new(
1351    ///         0x1020, 0x3040, 0x5060, 0x7080,
1352    ///         0x90A0, 0xB0C0, 0xD0E0, 0x0000,
1353    ///     ),
1354    ///     Ipv6Addr::from_bits(addr_bits));
1355    ///
1356    /// ```
1357    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
1358    #[stable(feature = "ip_bits", since = "1.80.0")]
1359    #[must_use]
1360    #[inline]
1361    pub const fn to_bits(self) -> u128 {
1362        u128::from_be_bytes(self.octets)
1363    }
1364
1365    /// Converts a native byte order `u128` into an IPv6 address.
1366    ///
1367    /// See [`Ipv6Addr::to_bits`] for an explanation on endianness.
1368    ///
1369    /// # Examples
1370    ///
1371    /// ```
1372    /// use std::net::Ipv6Addr;
1373    ///
1374    /// let addr = Ipv6Addr::from_bits(0x102030405060708090A0B0C0D0E0F00D_u128);
1375    /// assert_eq!(
1376    ///     Ipv6Addr::new(
1377    ///         0x1020, 0x3040, 0x5060, 0x7080,
1378    ///         0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
1379    ///     ),
1380    ///     addr);
1381    /// ```
1382    #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
1383    #[stable(feature = "ip_bits", since = "1.80.0")]
1384    #[must_use]
1385    #[inline]
1386    pub const fn from_bits(bits: u128) -> Ipv6Addr {
1387        Ipv6Addr { octets: bits.to_be_bytes() }
1388    }
1389
1390    /// An IPv6 address representing localhost: `::1`.
1391    ///
1392    /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other
1393    /// languages.
1394    ///
1395    /// # Examples
1396    ///
1397    /// ```
1398    /// use std::net::Ipv6Addr;
1399    ///
1400    /// let addr = Ipv6Addr::LOCALHOST;
1401    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
1402    /// ```
1403    #[doc(alias = "IN6ADDR_LOOPBACK_INIT")]
1404    #[doc(alias = "in6addr_loopback")]
1405    #[stable(feature = "ip_constructors", since = "1.30.0")]
1406    pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
1407
1408    /// An IPv6 address representing the unspecified address: `::`.
1409    ///
1410    /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages.
1411    ///
1412    /// # Examples
1413    ///
1414    /// ```
1415    /// use std::net::Ipv6Addr;
1416    ///
1417    /// let addr = Ipv6Addr::UNSPECIFIED;
1418    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
1419    /// ```
1420    #[doc(alias = "IN6ADDR_ANY_INIT")]
1421    #[doc(alias = "in6addr_any")]
1422    #[stable(feature = "ip_constructors", since = "1.30.0")]
1423    pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
1424
1425    /// Returns the eight 16-bit segments that make up this address.
1426    ///
1427    /// # Examples
1428    ///
1429    /// ```
1430    /// use std::net::Ipv6Addr;
1431    ///
1432    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
1433    ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
1434    /// ```
1435    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1436    #[stable(feature = "rust1", since = "1.0.0")]
1437    #[must_use]
1438    #[inline]
1439    pub const fn segments(&self) -> [u16; 8] {
1440        // All elements in `self.octets` must be big endian.
1441        // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
1442        let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) };
1443        // We want native endian u16
1444        [
1445            u16::from_be(a),
1446            u16::from_be(b),
1447            u16::from_be(c),
1448            u16::from_be(d),
1449            u16::from_be(e),
1450            u16::from_be(f),
1451            u16::from_be(g),
1452            u16::from_be(h),
1453        ]
1454    }
1455
1456    /// Creates an `Ipv6Addr` from an eight element 16-bit array.
1457    ///
1458    /// # Examples
1459    ///
1460    /// ```
1461    /// #![feature(ip_from)]
1462    /// use std::net::Ipv6Addr;
1463    ///
1464    /// let addr = Ipv6Addr::from_segments([
1465    ///     0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
1466    ///     0x209u16, 0x208u16, 0x207u16, 0x206u16,
1467    /// ]);
1468    /// assert_eq!(
1469    ///     Ipv6Addr::new(
1470    ///         0x20d, 0x20c, 0x20b, 0x20a,
1471    ///         0x209, 0x208, 0x207, 0x206,
1472    ///     ),
1473    ///     addr
1474    /// );
1475    /// ```
1476    #[unstable(feature = "ip_from", issue = "131360")]
1477    #[must_use]
1478    #[inline]
1479    pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr {
1480        let [a, b, c, d, e, f, g, h] = segments;
1481        Ipv6Addr::new(a, b, c, d, e, f, g, h)
1482    }
1483
1484    /// Returns [`true`] for the special 'unspecified' address (`::`).
1485    ///
1486    /// This property is defined in [IETF RFC 4291].
1487    ///
1488    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1489    ///
1490    /// # Examples
1491    ///
1492    /// ```
1493    /// use std::net::Ipv6Addr;
1494    ///
1495    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
1496    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
1497    /// ```
1498    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1499    #[stable(since = "1.7.0", feature = "ip_17")]
1500    #[must_use]
1501    #[inline]
1502    pub const fn is_unspecified(&self) -> bool {
1503        u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
1504    }
1505
1506    /// Returns [`true`] if this is the [loopback address] (`::1`),
1507    /// as defined in [IETF RFC 4291 section 2.5.3].
1508    ///
1509    /// Contrary to IPv4, in IPv6 there is only one loopback address.
1510    ///
1511    /// [loopback address]: Ipv6Addr::LOCALHOST
1512    /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
1513    ///
1514    /// # Examples
1515    ///
1516    /// ```
1517    /// use std::net::Ipv6Addr;
1518    ///
1519    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
1520    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
1521    /// ```
1522    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1523    #[stable(since = "1.7.0", feature = "ip_17")]
1524    #[must_use]
1525    #[inline]
1526    pub const fn is_loopback(&self) -> bool {
1527        u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
1528    }
1529
1530    /// Returns [`true`] if the address appears to be globally reachable
1531    /// as specified by the [IANA IPv6 Special-Purpose Address Registry].
1532    ///
1533    /// Whether or not an address is practically reachable will depend on your
1534    /// network configuration. Most IPv6 addresses are globally reachable, unless
1535    /// they are specifically defined as *not* globally reachable.
1536    ///
1537    /// Non-exhaustive list of notable addresses that are not globally reachable:
1538    /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
1539    /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback))
1540    /// - IPv4-mapped addresses
1541    /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv6Addr::is_benchmarking))
1542    /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation))
1543    /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local))
1544    /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local))
1545    ///
1546    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry].
1547    ///
1548    /// Note that an address having global scope is not the same as being globally reachable,
1549    /// and there is no direct relation between the two concepts: There exist addresses with global scope
1550    /// that are not globally reachable (for example unique local addresses),
1551    /// and addresses that are globally reachable without having global scope
1552    /// (multicast addresses with non-global scope).
1553    ///
1554    /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
1555    /// [unspecified address]: Ipv6Addr::UNSPECIFIED
1556    /// [loopback address]: Ipv6Addr::LOCALHOST
1557    ///
1558    /// # Examples
1559    ///
1560    /// ```
1561    /// #![feature(ip)]
1562    ///
1563    /// use std::net::Ipv6Addr;
1564    ///
1565    /// // Most IPv6 addresses are globally reachable:
1566    /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true);
1567    ///
1568    /// // However some addresses have been assigned a special meaning
1569    /// // that makes them not globally reachable. Some examples are:
1570    ///
1571    /// // The unspecified address (`::`)
1572    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false);
1573    ///
1574    /// // The loopback address (`::1`)
1575    /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false);
1576    ///
1577    /// // IPv4-mapped addresses (`::ffff:0:0/96`)
1578    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false);
1579    ///
1580    /// // Addresses reserved for benchmarking (`2001:2::/48`)
1581    /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
1582    ///
1583    /// // Addresses reserved for documentation (`2001:db8::/32` and `3fff::/20`)
1584    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
1585    /// assert_eq!(Ipv6Addr::new(0x3fff, 0, 0, 0, 0, 0, 0, 0).is_global(), false);
1586    ///
1587    /// // Unique local addresses (`fc00::/7`)
1588    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
1589    ///
1590    /// // Unicast addresses with link-local scope (`fe80::/10`)
1591    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
1592    ///
1593    /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
1594    /// ```
1595    #[unstable(feature = "ip", issue = "27709")]
1596    #[must_use]
1597    #[inline]
1598    pub const fn is_global(&self) -> bool {
1599        !(self.is_unspecified()
1600            || self.is_loopback()
1601            // IPv4-mapped Address (`::ffff:0:0/96`)
1602            || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
1603            // IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
1604            || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
1605            // Discard-Only Address Block (`100::/64`)
1606            || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
1607            // IETF Protocol Assignments (`2001::/23`)
1608            || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
1609                && !(
1610                    // Port Control Protocol Anycast (`2001:1::1`)
1611                    u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
1612                    // Traversal Using Relays around NAT Anycast (`2001:1::2`)
1613                    || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
1614                    // AMT (`2001:3::/32`)
1615                    || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
1616                    // AS112-v6 (`2001:4:112::/48`)
1617                    || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
1618                    // ORCHIDv2 (`2001:20::/28`)
1619                    // Drone Remote ID Protocol Entity Tags (DETs) Prefix (`2001:30::/28`)`
1620                    || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x3F)
1621                ))
1622            // 6to4 (`2002::/16`) – it's not explicitly documented as globally reachable,
1623            // IANA says N/A.
1624            || matches!(self.segments(), [0x2002, _, _, _, _, _, _, _])
1625            || self.is_documentation()
1626            // Segment Routing (SRv6) SIDs (`5f00::/16`)
1627            || matches!(self.segments(), [0x5f00, ..])
1628            || self.is_unique_local()
1629            || self.is_unicast_link_local())
1630    }
1631
1632    /// Returns [`true`] if this is a unique local address (`fc00::/7`).
1633    ///
1634    /// This property is defined in [IETF RFC 4193].
1635    ///
1636    /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
1637    ///
1638    /// # Examples
1639    ///
1640    /// ```
1641    /// use std::net::Ipv6Addr;
1642    ///
1643    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
1644    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
1645    /// ```
1646    #[must_use]
1647    #[inline]
1648    #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")]
1649    #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")]
1650    pub const fn is_unique_local(&self) -> bool {
1651        (self.segments()[0] & 0xfe00) == 0xfc00
1652    }
1653
1654    /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291].
1655    /// Any address that is not a [multicast address] (`ff00::/8`) is unicast.
1656    ///
1657    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1658    /// [multicast address]: Ipv6Addr::is_multicast
1659    ///
1660    /// # Examples
1661    ///
1662    /// ```
1663    /// #![feature(ip)]
1664    ///
1665    /// use std::net::Ipv6Addr;
1666    ///
1667    /// // The unspecified and loopback addresses are unicast.
1668    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true);
1669    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true);
1670    ///
1671    /// // Any address that is not a multicast address (`ff00::/8`) is unicast.
1672    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
1673    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
1674    /// ```
1675    #[unstable(feature = "ip", issue = "27709")]
1676    #[must_use]
1677    #[inline]
1678    pub const fn is_unicast(&self) -> bool {
1679        !self.is_multicast()
1680    }
1681
1682    /// Returns `true` if the address is a unicast address with link-local scope,
1683    /// as defined in [RFC 4291].
1684    ///
1685    /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4].
1686    /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6],
1687    /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format:
1688    ///
1689    /// ```text
1690    /// | 10 bits  |         54 bits         |          64 bits           |
1691    /// +----------+-------------------------+----------------------------+
1692    /// |1111111010|           0             |       interface ID         |
1693    /// +----------+-------------------------+----------------------------+
1694    /// ```
1695    /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`,
1696    /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated,
1697    /// and those addresses will have link-local scope.
1698    ///
1699    /// 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",
1700    /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it.
1701    ///
1702    /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
1703    /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
1704    /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
1705    /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
1706    /// [loopback address]: Ipv6Addr::LOCALHOST
1707    ///
1708    /// # Examples
1709    ///
1710    /// ```
1711    /// use std::net::Ipv6Addr;
1712    ///
1713    /// // The loopback address (`::1`) does not actually have link-local scope.
1714    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false);
1715    ///
1716    /// // Only addresses in `fe80::/10` have link-local scope.
1717    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false);
1718    /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
1719    ///
1720    /// // Addresses outside the stricter `fe80::/64` also have link-local scope.
1721    /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true);
1722    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
1723    /// ```
1724    #[must_use]
1725    #[inline]
1726    #[stable(feature = "ipv6_is_unique_local", since = "1.84.0")]
1727    #[rustc_const_stable(feature = "ipv6_is_unique_local", since = "1.84.0")]
1728    pub const fn is_unicast_link_local(&self) -> bool {
1729        (self.segments()[0] & 0xffc0) == 0xfe80
1730    }
1731
1732    /// Returns [`true`] if this is an address reserved for documentation
1733    /// (`2001:db8::/32` and `3fff::/20`).
1734    ///
1735    /// This property is defined by [IETF RFC 3849] and [IETF RFC 9637].
1736    ///
1737    /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
1738    /// [IETF RFC 9637]: https://tools.ietf.org/html/rfc9637
1739    ///
1740    /// # Examples
1741    ///
1742    /// ```
1743    /// #![feature(ip)]
1744    ///
1745    /// use std::net::Ipv6Addr;
1746    ///
1747    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
1748    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
1749    /// assert_eq!(Ipv6Addr::new(0x3fff, 0, 0, 0, 0, 0, 0, 0).is_documentation(), true);
1750    /// ```
1751    #[unstable(feature = "ip", issue = "27709")]
1752    #[must_use]
1753    #[inline]
1754    pub const fn is_documentation(&self) -> bool {
1755        matches!(self.segments(), [0x2001, 0xdb8, ..] | [0x3fff, 0..=0x0fff, ..])
1756    }
1757
1758    /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`).
1759    ///
1760    /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`.
1761    /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`.
1762    ///
1763    /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180
1764    /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752
1765    ///
1766    /// ```
1767    /// #![feature(ip)]
1768    ///
1769    /// use std::net::Ipv6Addr;
1770    ///
1771    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false);
1772    /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true);
1773    /// ```
1774    #[unstable(feature = "ip", issue = "27709")]
1775    #[must_use]
1776    #[inline]
1777    pub const fn is_benchmarking(&self) -> bool {
1778        (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0)
1779    }
1780
1781    /// Returns [`true`] if the address is a globally routable unicast address.
1782    ///
1783    /// The following return false:
1784    ///
1785    /// - the loopback address
1786    /// - the link-local addresses
1787    /// - unique local addresses
1788    /// - the unspecified address
1789    /// - the address range reserved for documentation
1790    ///
1791    /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
1792    ///
1793    /// ```no_rust
1794    /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
1795    /// be supported in new implementations (i.e., new implementations must treat this prefix as
1796    /// Global Unicast).
1797    /// ```
1798    ///
1799    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
1800    ///
1801    /// # Examples
1802    ///
1803    /// ```
1804    /// #![feature(ip)]
1805    ///
1806    /// use std::net::Ipv6Addr;
1807    ///
1808    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
1809    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
1810    /// ```
1811    #[unstable(feature = "ip", issue = "27709")]
1812    #[must_use]
1813    #[inline]
1814    pub const fn is_unicast_global(&self) -> bool {
1815        self.is_unicast()
1816            && !self.is_loopback()
1817            && !self.is_unicast_link_local()
1818            && !self.is_unique_local()
1819            && !self.is_unspecified()
1820            && !self.is_documentation()
1821            && !self.is_benchmarking()
1822    }
1823
1824    /// Returns the address's multicast scope if the address is multicast.
1825    ///
1826    /// # Examples
1827    ///
1828    /// ```
1829    /// #![feature(ip)]
1830    ///
1831    /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
1832    ///
1833    /// assert_eq!(
1834    ///     Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
1835    ///     Some(Ipv6MulticastScope::Global)
1836    /// );
1837    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
1838    /// ```
1839    #[unstable(feature = "ip", issue = "27709")]
1840    #[must_use]
1841    #[inline]
1842    pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
1843        if self.is_multicast() {
1844            match self.segments()[0] & 0x000f {
1845                1 => Some(Ipv6MulticastScope::InterfaceLocal),
1846                2 => Some(Ipv6MulticastScope::LinkLocal),
1847                3 => Some(Ipv6MulticastScope::RealmLocal),
1848                4 => Some(Ipv6MulticastScope::AdminLocal),
1849                5 => Some(Ipv6MulticastScope::SiteLocal),
1850                8 => Some(Ipv6MulticastScope::OrganizationLocal),
1851                14 => Some(Ipv6MulticastScope::Global),
1852                _ => None,
1853            }
1854        } else {
1855            None
1856        }
1857    }
1858
1859    /// Returns [`true`] if this is a multicast address (`ff00::/8`).
1860    ///
1861    /// This property is defined by [IETF RFC 4291].
1862    ///
1863    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
1864    ///
1865    /// # Examples
1866    ///
1867    /// ```
1868    /// use std::net::Ipv6Addr;
1869    ///
1870    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
1871    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
1872    /// ```
1873    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1874    #[stable(since = "1.7.0", feature = "ip_17")]
1875    #[must_use]
1876    #[inline]
1877    pub const fn is_multicast(&self) -> bool {
1878        (self.segments()[0] & 0xff00) == 0xff00
1879    }
1880
1881    /// Returns [`true`] if the address is an IPv4-mapped address (`::ffff:0:0/96`).
1882    ///
1883    /// IPv4-mapped addresses can be converted to their canonical IPv4 address with
1884    /// [`to_ipv4_mapped`](Ipv6Addr::to_ipv4_mapped).
1885    ///
1886    /// # Examples
1887    /// ```
1888    /// #![feature(ip)]
1889    ///
1890    /// use std::net::{Ipv4Addr, Ipv6Addr};
1891    ///
1892    /// let ipv4_mapped = Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped();
1893    /// assert_eq!(ipv4_mapped.is_ipv4_mapped(), true);
1894    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff).is_ipv4_mapped(), true);
1895    ///
1896    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false);
1897    /// ```
1898    #[unstable(feature = "ip", issue = "27709")]
1899    #[must_use]
1900    #[inline]
1901    pub const fn is_ipv4_mapped(&self) -> bool {
1902        matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
1903    }
1904
1905    /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address,
1906    /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
1907    ///
1908    /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
1909    /// All addresses *not* starting with `::ffff` will return `None`.
1910    ///
1911    /// [`IPv4` address]: Ipv4Addr
1912    /// [IPv4-mapped]: Ipv6Addr
1913    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1914    ///
1915    /// # Examples
1916    ///
1917    /// ```
1918    /// use std::net::{Ipv4Addr, Ipv6Addr};
1919    ///
1920    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
1921    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
1922    ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
1923    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
1924    /// ```
1925    #[inline]
1926    #[must_use = "this returns the result of the operation, \
1927                  without modifying the original"]
1928    #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
1929    #[rustc_const_stable(feature = "const_ipv6_to_ipv4_mapped", since = "1.75.0")]
1930    pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
1931        match self.octets() {
1932            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
1933                Some(Ipv4Addr::new(a, b, c, d))
1934            }
1935            _ => None,
1936        }
1937    }
1938
1939    /// Converts this address to an [`IPv4` address] if it is either
1940    /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1],
1941    /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2],
1942    /// otherwise returns [`None`].
1943    ///
1944    /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use
1945    /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
1946    ///
1947    /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`.
1948    /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`.
1949    ///
1950    /// [`IPv4` address]: Ipv4Addr
1951    /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
1952    /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
1953    /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1
1954    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
1955    ///
1956    /// # Examples
1957    ///
1958    /// ```
1959    /// use std::net::{Ipv4Addr, Ipv6Addr};
1960    ///
1961    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
1962    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
1963    ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
1964    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
1965    ///            Some(Ipv4Addr::new(0, 0, 0, 1)));
1966    /// ```
1967    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
1968    #[stable(feature = "rust1", since = "1.0.0")]
1969    #[must_use = "this returns the result of the operation, \
1970                  without modifying the original"]
1971    #[inline]
1972    pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
1973        if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
1974            let [a, b] = ab.to_be_bytes();
1975            let [c, d] = cd.to_be_bytes();
1976            Some(Ipv4Addr::new(a, b, c, d))
1977        } else {
1978            None
1979        }
1980    }
1981
1982    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped address,
1983    /// otherwise returns self wrapped in an `IpAddr::V6`.
1984    ///
1985    /// # Examples
1986    ///
1987    /// ```
1988    /// use std::net::Ipv6Addr;
1989    ///
1990    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
1991    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true);
1992    /// ```
1993    #[inline]
1994    #[must_use = "this returns the result of the operation, \
1995                  without modifying the original"]
1996    #[stable(feature = "ip_to_canonical", since = "1.75.0")]
1997    #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")]
1998    pub const fn to_canonical(&self) -> IpAddr {
1999        if let Some(mapped) = self.to_ipv4_mapped() {
2000            return IpAddr::V4(mapped);
2001        }
2002        IpAddr::V6(*self)
2003    }
2004
2005    /// Returns the sixteen eight-bit integers the IPv6 address consists of.
2006    ///
2007    /// ```
2008    /// use std::net::Ipv6Addr;
2009    ///
2010    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
2011    ///            [0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
2012    /// ```
2013    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
2014    #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
2015    #[must_use]
2016    #[inline]
2017    pub const fn octets(&self) -> [u8; 16] {
2018        self.octets
2019    }
2020
2021    /// Creates an `Ipv6Addr` from a sixteen element byte array.
2022    ///
2023    /// # Examples
2024    ///
2025    /// ```
2026    /// #![feature(ip_from)]
2027    /// use std::net::Ipv6Addr;
2028    ///
2029    /// let addr = Ipv6Addr::from_octets([
2030    ///     0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
2031    ///     0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
2032    /// ]);
2033    /// assert_eq!(
2034    ///     Ipv6Addr::new(
2035    ///         0x1918, 0x1716, 0x1514, 0x1312,
2036    ///         0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
2037    ///     ),
2038    ///     addr
2039    /// );
2040    /// ```
2041    #[unstable(feature = "ip_from", issue = "131360")]
2042    #[must_use]
2043    #[inline]
2044    pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr {
2045        Ipv6Addr { octets }
2046    }
2047
2048    /// Returns the sixteen eight-bit integers the IPv6 address consists of
2049    /// as a slice.
2050    ///
2051    /// # Examples
2052    ///
2053    /// ```
2054    /// #![feature(ip_as_octets)]
2055    ///
2056    /// use std::net::Ipv6Addr;
2057    ///
2058    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).as_octets(),
2059    ///            &[255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
2060    /// ```
2061    #[unstable(feature = "ip_as_octets", issue = "137259")]
2062    #[inline]
2063    pub const fn as_octets(&self) -> &[u8; 16] {
2064        &self.octets
2065    }
2066}
2067
2068/// Writes an Ipv6Addr, conforming to the canonical style described by
2069/// [RFC 5952](https://tools.ietf.org/html/rfc5952).
2070#[stable(feature = "rust1", since = "1.0.0")]
2071impl fmt::Display for Ipv6Addr {
2072    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2073        // If there are no alignment requirements, write the IP address directly to `f`.
2074        // Otherwise, write it to a local buffer and then use `f.pad`.
2075        if f.precision().is_none() && f.width().is_none() {
2076            let segments = self.segments();
2077
2078            if let Some(ipv4) = self.to_ipv4_mapped() {
2079                write!(f, "::ffff:{}", ipv4)
2080            } else {
2081                #[derive(Copy, Clone, Default)]
2082                struct Span {
2083                    start: usize,
2084                    len: usize,
2085                }
2086
2087                // Find the inner 0 span
2088                let zeroes = {
2089                    let mut longest = Span::default();
2090                    let mut current = Span::default();
2091
2092                    for (i, &segment) in segments.iter().enumerate() {
2093                        if segment == 0 {
2094                            if current.len == 0 {
2095                                current.start = i;
2096                            }
2097
2098                            current.len += 1;
2099
2100                            if current.len > longest.len {
2101                                longest = current;
2102                            }
2103                        } else {
2104                            current = Span::default();
2105                        }
2106                    }
2107
2108                    longest
2109                };
2110
2111                /// Writes a colon-separated part of the address.
2112                #[inline]
2113                fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
2114                    if let Some((first, tail)) = chunk.split_first() {
2115                        write!(f, "{:x}", first)?;
2116                        for segment in tail {
2117                            f.write_char(':')?;
2118                            write!(f, "{:x}", segment)?;
2119                        }
2120                    }
2121                    Ok(())
2122                }
2123
2124                if zeroes.len > 1 {
2125                    fmt_subslice(f, &segments[..zeroes.start])?;
2126                    f.write_str("::")?;
2127                    fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
2128                } else {
2129                    fmt_subslice(f, &segments)
2130                }
2131            }
2132        } else {
2133            const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
2134
2135            let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
2136            // Buffer is long enough for the longest possible IPv6 address, so this should never fail.
2137            write!(buf, "{}", self).unwrap();
2138
2139            f.pad(buf.as_str())
2140        }
2141    }
2142}
2143
2144#[stable(feature = "rust1", since = "1.0.0")]
2145impl fmt::Debug for Ipv6Addr {
2146    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2147        fmt::Display::fmt(self, fmt)
2148    }
2149}
2150
2151#[stable(feature = "ip_cmp", since = "1.16.0")]
2152impl PartialEq<IpAddr> for Ipv6Addr {
2153    #[inline]
2154    fn eq(&self, other: &IpAddr) -> bool {
2155        match other {
2156            IpAddr::V4(_) => false,
2157            IpAddr::V6(v6) => self == v6,
2158        }
2159    }
2160}
2161
2162#[stable(feature = "ip_cmp", since = "1.16.0")]
2163impl PartialEq<Ipv6Addr> for IpAddr {
2164    #[inline]
2165    fn eq(&self, other: &Ipv6Addr) -> bool {
2166        match self {
2167            IpAddr::V4(_) => false,
2168            IpAddr::V6(v6) => v6 == other,
2169        }
2170    }
2171}
2172
2173#[stable(feature = "rust1", since = "1.0.0")]
2174impl PartialOrd for Ipv6Addr {
2175    #[inline]
2176    fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
2177        Some(self.cmp(other))
2178    }
2179}
2180
2181#[stable(feature = "ip_cmp", since = "1.16.0")]
2182impl PartialOrd<Ipv6Addr> for IpAddr {
2183    #[inline]
2184    fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
2185        match self {
2186            IpAddr::V4(_) => Some(Ordering::Less),
2187            IpAddr::V6(v6) => v6.partial_cmp(other),
2188        }
2189    }
2190}
2191
2192#[stable(feature = "ip_cmp", since = "1.16.0")]
2193impl PartialOrd<IpAddr> for Ipv6Addr {
2194    #[inline]
2195    fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
2196        match other {
2197            IpAddr::V4(_) => Some(Ordering::Greater),
2198            IpAddr::V6(v6) => self.partial_cmp(v6),
2199        }
2200    }
2201}
2202
2203#[stable(feature = "rust1", since = "1.0.0")]
2204impl Ord for Ipv6Addr {
2205    #[inline]
2206    fn cmp(&self, other: &Ipv6Addr) -> Ordering {
2207        self.segments().cmp(&other.segments())
2208    }
2209}
2210
2211#[stable(feature = "i128", since = "1.26.0")]
2212impl From<Ipv6Addr> for u128 {
2213    /// Uses [`Ipv6Addr::to_bits`] to convert an IPv6 address to a host byte order `u128`.
2214    #[inline]
2215    fn from(ip: Ipv6Addr) -> u128 {
2216        ip.to_bits()
2217    }
2218}
2219#[stable(feature = "i128", since = "1.26.0")]
2220impl From<u128> for Ipv6Addr {
2221    /// Uses [`Ipv6Addr::from_bits`] to convert a host byte order `u128` to an IPv6 address.
2222    #[inline]
2223    fn from(ip: u128) -> Ipv6Addr {
2224        Ipv6Addr::from_bits(ip)
2225    }
2226}
2227
2228#[stable(feature = "ipv6_from_octets", since = "1.9.0")]
2229impl From<[u8; 16]> for Ipv6Addr {
2230    /// Creates an `Ipv6Addr` from a sixteen element byte array.
2231    ///
2232    /// # Examples
2233    ///
2234    /// ```
2235    /// use std::net::Ipv6Addr;
2236    ///
2237    /// let addr = Ipv6Addr::from([
2238    ///     0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
2239    ///     0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
2240    /// ]);
2241    /// assert_eq!(
2242    ///     Ipv6Addr::new(
2243    ///         0x1918, 0x1716, 0x1514, 0x1312,
2244    ///         0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
2245    ///     ),
2246    ///     addr
2247    /// );
2248    /// ```
2249    #[inline]
2250    fn from(octets: [u8; 16]) -> Ipv6Addr {
2251        Ipv6Addr { octets }
2252    }
2253}
2254
2255#[stable(feature = "ipv6_from_segments", since = "1.16.0")]
2256impl From<[u16; 8]> for Ipv6Addr {
2257    /// Creates an `Ipv6Addr` from an eight element 16-bit array.
2258    ///
2259    /// # Examples
2260    ///
2261    /// ```
2262    /// use std::net::Ipv6Addr;
2263    ///
2264    /// let addr = Ipv6Addr::from([
2265    ///     0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
2266    ///     0x209u16, 0x208u16, 0x207u16, 0x206u16,
2267    /// ]);
2268    /// assert_eq!(
2269    ///     Ipv6Addr::new(
2270    ///         0x20d, 0x20c, 0x20b, 0x20a,
2271    ///         0x209, 0x208, 0x207, 0x206,
2272    ///     ),
2273    ///     addr
2274    /// );
2275    /// ```
2276    #[inline]
2277    fn from(segments: [u16; 8]) -> Ipv6Addr {
2278        let [a, b, c, d, e, f, g, h] = segments;
2279        Ipv6Addr::new(a, b, c, d, e, f, g, h)
2280    }
2281}
2282
2283#[stable(feature = "ip_from_slice", since = "1.17.0")]
2284impl From<[u8; 16]> for IpAddr {
2285    /// Creates an `IpAddr::V6` from a sixteen element byte array.
2286    ///
2287    /// # Examples
2288    ///
2289    /// ```
2290    /// use std::net::{IpAddr, Ipv6Addr};
2291    ///
2292    /// let addr = IpAddr::from([
2293    ///     0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
2294    ///     0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
2295    /// ]);
2296    /// assert_eq!(
2297    ///     IpAddr::V6(Ipv6Addr::new(
2298    ///         0x1918, 0x1716, 0x1514, 0x1312,
2299    ///         0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
2300    ///     )),
2301    ///     addr
2302    /// );
2303    /// ```
2304    #[inline]
2305    fn from(octets: [u8; 16]) -> IpAddr {
2306        IpAddr::V6(Ipv6Addr::from(octets))
2307    }
2308}
2309
2310#[stable(feature = "ip_from_slice", since = "1.17.0")]
2311impl From<[u16; 8]> for IpAddr {
2312    /// Creates an `IpAddr::V6` from an eight element 16-bit array.
2313    ///
2314    /// # Examples
2315    ///
2316    /// ```
2317    /// use std::net::{IpAddr, Ipv6Addr};
2318    ///
2319    /// let addr = IpAddr::from([
2320    ///     0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
2321    ///     0x209u16, 0x208u16, 0x207u16, 0x206u16,
2322    /// ]);
2323    /// assert_eq!(
2324    ///     IpAddr::V6(Ipv6Addr::new(
2325    ///         0x20d, 0x20c, 0x20b, 0x20a,
2326    ///         0x209, 0x208, 0x207, 0x206,
2327    ///     )),
2328    ///     addr
2329    /// );
2330    /// ```
2331    #[inline]
2332    fn from(segments: [u16; 8]) -> IpAddr {
2333        IpAddr::V6(Ipv6Addr::from(segments))
2334    }
2335}
2336
2337#[stable(feature = "ip_bitops", since = "1.75.0")]
2338impl Not for Ipv4Addr {
2339    type Output = Ipv4Addr;
2340
2341    #[inline]
2342    fn not(mut self) -> Ipv4Addr {
2343        for octet in &mut self.octets {
2344            *octet = !*octet;
2345        }
2346        self
2347    }
2348}
2349
2350#[stable(feature = "ip_bitops", since = "1.75.0")]
2351impl Not for &'_ Ipv4Addr {
2352    type Output = Ipv4Addr;
2353
2354    #[inline]
2355    fn not(self) -> Ipv4Addr {
2356        !*self
2357    }
2358}
2359
2360#[stable(feature = "ip_bitops", since = "1.75.0")]
2361impl Not for Ipv6Addr {
2362    type Output = Ipv6Addr;
2363
2364    #[inline]
2365    fn not(mut self) -> Ipv6Addr {
2366        for octet in &mut self.octets {
2367            *octet = !*octet;
2368        }
2369        self
2370    }
2371}
2372
2373#[stable(feature = "ip_bitops", since = "1.75.0")]
2374impl Not for &'_ Ipv6Addr {
2375    type Output = Ipv6Addr;
2376
2377    #[inline]
2378    fn not(self) -> Ipv6Addr {
2379        !*self
2380    }
2381}
2382
2383macro_rules! bitop_impls {
2384    ($(
2385        $(#[$attr:meta])*
2386        impl ($BitOp:ident, $BitOpAssign:ident) for $ty:ty = ($bitop:ident, $bitop_assign:ident);
2387    )*) => {
2388        $(
2389            $(#[$attr])*
2390            impl $BitOpAssign for $ty {
2391                fn $bitop_assign(&mut self, rhs: $ty) {
2392                    for (lhs, rhs) in iter::zip(&mut self.octets, rhs.octets) {
2393                        lhs.$bitop_assign(rhs);
2394                    }
2395                }
2396            }
2397
2398            $(#[$attr])*
2399            impl $BitOpAssign<&'_ $ty> for $ty {
2400                fn $bitop_assign(&mut self, rhs: &'_ $ty) {
2401                    self.$bitop_assign(*rhs);
2402                }
2403            }
2404
2405            $(#[$attr])*
2406            impl $BitOp for $ty {
2407                type Output = $ty;
2408
2409                #[inline]
2410                fn $bitop(mut self, rhs: $ty) -> $ty {
2411                    self.$bitop_assign(rhs);
2412                    self
2413                }
2414            }
2415
2416            $(#[$attr])*
2417            impl $BitOp<&'_ $ty> for $ty {
2418                type Output = $ty;
2419
2420                #[inline]
2421                fn $bitop(mut self, rhs: &'_ $ty) -> $ty {
2422                    self.$bitop_assign(*rhs);
2423                    self
2424                }
2425            }
2426
2427            $(#[$attr])*
2428            impl $BitOp<$ty> for &'_ $ty {
2429                type Output = $ty;
2430
2431                #[inline]
2432                fn $bitop(self, rhs: $ty) -> $ty {
2433                    let mut lhs = *self;
2434                    lhs.$bitop_assign(rhs);
2435                    lhs
2436                }
2437            }
2438
2439            $(#[$attr])*
2440            impl $BitOp<&'_ $ty> for &'_ $ty {
2441                type Output = $ty;
2442
2443                #[inline]
2444                fn $bitop(self, rhs: &'_ $ty) -> $ty {
2445                    let mut lhs = *self;
2446                    lhs.$bitop_assign(*rhs);
2447                    lhs
2448                }
2449            }
2450        )*
2451    };
2452}
2453
2454bitop_impls! {
2455    #[stable(feature = "ip_bitops", since = "1.75.0")]
2456    impl (BitAnd, BitAndAssign) for Ipv4Addr = (bitand, bitand_assign);
2457    #[stable(feature = "ip_bitops", since = "1.75.0")]
2458    impl (BitOr, BitOrAssign) for Ipv4Addr = (bitor, bitor_assign);
2459
2460    #[stable(feature = "ip_bitops", since = "1.75.0")]
2461    impl (BitAnd, BitAndAssign) for Ipv6Addr = (bitand, bitand_assign);
2462    #[stable(feature = "ip_bitops", since = "1.75.0")]
2463    impl (BitOr, BitOrAssign) for Ipv6Addr = (bitor, bitor_assign);
2464}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy