Skip to content

Commit

Permalink
Rollup merge of #76206 - CDirkx:const-ipv6, r=ecstatic-morse
Browse files Browse the repository at this point in the history
Make all methods of `std::net::Ipv6Addr` const

Make the following methods of `std::net::Ipv6Addr` unstable const under the `const_ipv6` feature:
- `segments`
- `is_unspecified`
- `is_loopback`
- `is_global` (unstable)
- `is_unique_local`
- `is_unicast_link_local_strict`
- `is_documentation`
- `multicast_scope`
- `is_multicast`
- `to_ipv4_mapped`
- `to_ipv4`

This would make all methods of `Ipv6Addr` const.

Changed the implementation of `is_unspecified` and `is_loopback` to use a `match` instead of `==`, all other methods did not require a change.

All these methods are dependent on `segments`, the current implementation of which requires unstable `const_fn_transmute` ([PR#75085](#75085)).

Part of #76205
  • Loading branch information
tmandry authored Sep 2, 2020
2 parents 17fa733 + 9afe97c commit 11ff32f
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 16 deletions.
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@
#![feature(concat_idents)]
#![feature(const_cstr_unchecked)]
#![feature(const_fn_transmute)]
#![feature(const_ipv6)]
#![feature(const_raw_ptr_deref)]
#![feature(container_error_extra)]
#![feature(core_intrinsics)]
Expand Down
46 changes: 30 additions & 16 deletions library/std/src/net/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1102,8 +1102,9 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
/// [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
/// ```
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn segments(&self) -> [u16; 8] {
pub const fn segments(&self) -> [u16; 8] {
// All elements in `s6_addr` must be big endian.
// SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
Expand Down Expand Up @@ -1135,9 +1136,10 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
/// ```
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_unspecified(&self) -> bool {
self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
pub const fn is_unspecified(&self) -> bool {
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
}

/// Returns [`true`] if this is a loopback address (::1).
Expand All @@ -1155,9 +1157,10 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
/// ```
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_loopback(&self) -> bool {
self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
pub const fn is_loopback(&self) -> bool {
u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
}

/// Returns [`true`] if the address appears to be globally routable.
Expand All @@ -1182,7 +1185,8 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
/// ```
pub fn is_global(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn is_global(&self) -> bool {
match self.multicast_scope() {
Some(Ipv6MulticastScope::Global) => true,
None => self.is_unicast_global(),
Expand All @@ -1208,7 +1212,8 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
/// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
/// ```
pub fn is_unique_local(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn is_unique_local(&self) -> bool {
(self.segments()[0] & 0xfe00) == 0xfc00
}

Expand Down Expand Up @@ -1263,7 +1268,8 @@ impl Ipv6Addr {
/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
/// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
pub fn is_unicast_link_local_strict(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn is_unicast_link_local_strict(&self) -> bool {
(self.segments()[0] & 0xffff) == 0xfe80
&& (self.segments()[1] & 0xffff) == 0
&& (self.segments()[2] & 0xffff) == 0
Expand Down Expand Up @@ -1320,7 +1326,8 @@ impl Ipv6Addr {
///
/// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
pub fn is_unicast_link_local(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn is_unicast_link_local(&self) -> bool {
(self.segments()[0] & 0xffc0) == 0xfe80
}

Expand Down Expand Up @@ -1359,7 +1366,8 @@ impl Ipv6Addr {
/// addresses.
///
/// [RFC 3879]: https://tools.ietf.org/html/rfc3879
pub fn is_unicast_site_local(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn is_unicast_site_local(&self) -> bool {
(self.segments()[0] & 0xffc0) == 0xfec0
}

Expand All @@ -1381,7 +1389,8 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
/// ```
pub fn is_documentation(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn is_documentation(&self) -> bool {
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
}

Expand Down Expand Up @@ -1416,7 +1425,8 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
/// ```
pub fn is_unicast_global(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn is_unicast_global(&self) -> bool {
!self.is_multicast()
&& !self.is_loopback()
&& !self.is_unicast_link_local()
Expand All @@ -1440,7 +1450,8 @@ impl Ipv6Addr {
/// );
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
/// ```
pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
if self.is_multicast() {
match self.segments()[0] & 0x000f {
1 => Some(Ipv6MulticastScope::InterfaceLocal),
Expand Down Expand Up @@ -1472,8 +1483,9 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_multicast(&self) -> bool {
pub const fn is_multicast(&self) -> bool {
(self.segments()[0] & 0xff00) == 0xff00
}

Expand All @@ -1498,7 +1510,8 @@ impl Ipv6Addr {
/// Some(Ipv4Addr::new(192, 10, 2, 255)));
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
/// ```
pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
match self.octets() {
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
Some(Ipv4Addr::new(a, b, c, d))
Expand All @@ -1525,8 +1538,9 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
/// Some(Ipv4Addr::new(0, 0, 0, 1)));
/// ```
#[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
let [a, b] = ab.to_be_bytes();
let [c, d] = cd.to_be_bytes();
Expand Down
53 changes: 53 additions & 0 deletions src/test/ui/consts/std/net/ipv6.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// run-pass

#![feature(ip)]
#![feature(const_ipv6)]

use std::net::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};

fn main() {
const IP_ADDRESS : Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);

const SEGMENTS : [u16; 8] = IP_ADDRESS.segments();
assert_eq!(SEGMENTS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 1]);

const OCTETS : [u8; 16] = IP_ADDRESS.octets();
assert_eq!(OCTETS, [0 ,0 ,0 ,0 ,0 ,0 ,0, 0 ,0 ,0 ,0 ,0 ,0 ,0, 0, 1]);

const IS_UNSPECIFIED : bool = IP_ADDRESS.is_unspecified();
assert!(!IS_UNSPECIFIED);

const IS_LOOPBACK : bool = IP_ADDRESS.is_loopback();
assert!(IS_LOOPBACK);

const IS_GLOBAL : bool = IP_ADDRESS.is_global();
assert!(!IS_GLOBAL);

const IS_UNIQUE_LOCAL : bool = IP_ADDRESS.is_unique_local();
assert!(!IS_UNIQUE_LOCAL);

const IS_UNICAST_LINK_LOCAL_STRICT : bool = IP_ADDRESS.is_unicast_link_local_strict();
assert!(!IS_UNICAST_LINK_LOCAL_STRICT);

const IS_UNICAST_LINK_LOCAL : bool = IP_ADDRESS.is_unicast_link_local();
assert!(!IS_UNICAST_LINK_LOCAL);

const IS_UNICAST_SITE_LOCAL : bool = IP_ADDRESS.is_unicast_site_local();
assert!(!IS_UNICAST_SITE_LOCAL);

const IS_DOCUMENTATION : bool = IP_ADDRESS.is_documentation();
assert!(!IS_DOCUMENTATION);

const IS_UNICAST_GLOBAL : bool = IP_ADDRESS.is_unicast_global();
assert!(!IS_UNICAST_GLOBAL);

const MULTICAST_SCOPE : Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
assert_eq!(MULTICAST_SCOPE, None);

const IS_MULTICAST : bool = IP_ADDRESS.is_multicast();
assert!(!IS_MULTICAST);

const IP_V4 : Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
}

0 comments on commit 11ff32f

Please sign in to comment.