Skip to content

Commit 605504c

Browse files
CDirkxjstasiak
authored andcommitted
Add Ipv6Addr::is_ipv4_mapped
This change consists of cherry-picking the content from the original PR[1], which got closed due to inactivity, and applying the following changes: * Resolving merge conflicts (obviously) * Linked to to_ipv4_mapped instead of to_ipv4 in the documentation (seems more appropriate) * Added the must_use and rustc_const_unstable attributes the original didn't have I think it's a reasonably useful method. [1] rust-lang#86490
1 parent 37340a1 commit 605504c

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

library/core/src/net/ip_addr.rs

+25
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,31 @@ impl Ipv6Addr {
17771777
(self.segments()[0] & 0xff00) == 0xff00
17781778
}
17791779

1780+
/// Returns [`true`] if the address is an IPv4-mapped address (`::ffff:0:0/96`).
1781+
///
1782+
/// IPv4-mapped addresses can be converted to their canonical IPv4 address with
1783+
/// [`to_ipv4_mapped`](Ipv6Addr::to_ipv4_mapped).
1784+
///
1785+
/// # Examples
1786+
/// ```
1787+
/// #![feature(ip)]
1788+
///
1789+
/// use std::net::{Ipv4Addr, Ipv6Addr};
1790+
///
1791+
/// let ipv4_mapped = Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped();
1792+
/// assert_eq!(ipv4_mapped.is_ipv4_mapped(), true);
1793+
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff).is_ipv4_mapped(), true);
1794+
///
1795+
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_ipv4_mapped(), false);
1796+
/// ```
1797+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1798+
#[unstable(feature = "ip", issue = "27709")]
1799+
#[must_use]
1800+
#[inline]
1801+
pub const fn is_ipv4_mapped(&self) -> bool {
1802+
matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
1803+
}
1804+
17801805
/// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address,
17811806
/// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
17821807
///

library/core/tests/net/ip_addr.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ fn ipv6_properties() {
508508
| multicast_realm_local
509509
| multicast_site_local
510510
| multicast_organization_local;
511+
let ipv4_mapped: u32 = 1 << 17;
511512

512513
if ($mask & unspecified) == unspecified {
513514
assert!(ip!($s).is_unspecified());
@@ -584,6 +585,11 @@ fn ipv6_properties() {
584585
assert_eq!(ip!($s).multicast_scope().unwrap(),
585586
Ipv6MulticastScope::Global);
586587
}
588+
if ($mask & ipv4_mapped) == ipv4_mapped {
589+
assert!(ip!($s).is_ipv4_mapped());
590+
} else {
591+
assert!(!ip!($s).is_ipv4_mapped());
592+
}
587593
}
588594
}
589595

@@ -602,6 +608,7 @@ fn ipv6_properties() {
602608
let multicast_site_local: u32 = 1 << 13;
603609
let multicast_organization_local: u32 = 1 << 14;
604610
let multicast_global: u32 = 1 << 15;
611+
let ipv4_mapped: u32 = 1 << 17;
605612

606613
check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);
607614

@@ -614,7 +621,7 @@ fn ipv6_properties() {
614621
check!(
615622
"::ffff:127.0.0.1",
616623
&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1],
617-
unicast_global
624+
unicast_global | ipv4_mapped
618625
);
619626

620627
check!(
@@ -982,6 +989,9 @@ fn ipv6_const() {
982989
const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
983990
assert!(!IS_MULTICAST);
984991

992+
const IS_IPV4_MAPPED: bool = IP_ADDRESS.is_ipv4_mapped();
993+
assert!(!IS_IPV4_MAPPED);
994+
985995
const IP_V4: Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
986996
assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
987997
}

0 commit comments

Comments
 (0)