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