Skip to content

Commit a5cdff3

Browse files
committed
Add convenience for handling ipv4-mapped addresses by canonicalizing them
This simplifies checking common properties in an address-family-agnostic way since since #86335 commits to not checking IPv4 semantics of IPv4-mapped addresses in the `Ipv6Addr` property methods.
1 parent a985d8e commit a5cdff3

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

library/std/src/net/ip.rs

+45
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,29 @@ impl IpAddr {
291291
pub const fn is_ipv6(&self) -> bool {
292292
matches!(self, IpAddr::V6(_))
293293
}
294+
295+
/// Converts this address to an `IpAddr::V4` if it is a IPv4-mapped IPv6 addresses, otherwise it
296+
/// return `self` as-is.
297+
///
298+
/// # Examples
299+
///
300+
/// ```
301+
/// #![feature(ip)]
302+
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
303+
///
304+
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
305+
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
306+
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true);
307+
/// ```
308+
#[inline]
309+
#[rustc_const_unstable(feature = "const_ip", issue = "76205")]
310+
#[unstable(feature = "ip", issue = "27709")]
311+
pub const fn to_canonical(&self) -> IpAddr {
312+
match self {
313+
&v4 @ IpAddr::V4(_) => v4,
314+
IpAddr::V6(v6) => v6.to_canonical(),
315+
}
316+
}
294317
}
295318

296319
impl Ipv4Addr {
@@ -1532,6 +1555,28 @@ impl Ipv6Addr {
15321555
}
15331556
}
15341557

1558+
/// Converts this address to an `IpAddr::V4` if it is a IPv4-mapped addresses, otherwise it
1559+
/// returns self wrapped in a `IpAddr::V6`.
1560+
///
1561+
/// # Examples
1562+
///
1563+
/// ```
1564+
/// #![feature(ip)]
1565+
/// use std::net::Ipv6Addr;
1566+
///
1567+
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
1568+
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true);
1569+
/// ```
1570+
#[inline]
1571+
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
1572+
#[unstable(feature = "ip", issue = "27709")]
1573+
pub const fn to_canonical(&self) -> IpAddr {
1574+
if let Some(mapped) = self.to_ipv4_mapped() {
1575+
return IpAddr::V4(mapped);
1576+
}
1577+
IpAddr::V6(*self)
1578+
}
1579+
15351580
/// Returns the sixteen eight-bit integers the IPv6 address consists of.
15361581
///
15371582
/// ```

0 commit comments

Comments
 (0)