Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make all methods of std::net::Ipv4Addr const #76142

Merged
merged 4 commits into from
Sep 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
#![feature(const_cstr_unchecked)]
#![feature(const_fn_transmute)]
#![feature(const_raw_ptr_deref)]
#![feature(const_ipv4)]
#![feature(container_error_extra)]
#![feature(core_intrinsics)]
#![feature(custom_test_frameworks)]
Expand Down
56 changes: 38 additions & 18 deletions library/std/src/net/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,9 @@ impl Ipv4Addr {
/// let addr = Ipv4Addr::new(127, 0, 0, 1);
/// assert_eq!(addr.octets(), [127, 0, 0, 1]);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn octets(&self) -> [u8; 4] {
pub const fn octets(&self) -> [u8; 4] {
// This returns the order we want because s_addr is stored in big-endian.
self.inner.s_addr.to_ne_bytes()
}
Expand Down Expand Up @@ -404,8 +405,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
/// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_loopback(&self) -> bool {
pub const fn is_loopback(&self) -> bool {
self.octets()[0] == 127
}

Expand Down Expand Up @@ -433,8 +435,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
/// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_private(&self) -> bool {
pub const fn is_private(&self) -> bool {
match self.octets() {
[10, ..] => true,
[172, b, ..] if b >= 16 && b <= 31 => true,
Expand All @@ -459,8 +462,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
/// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_link_local(&self) -> bool {
pub const fn is_link_local(&self) -> bool {
match self.octets() {
[169, 254, ..] => true,
_ => false,
Expand Down Expand Up @@ -538,10 +542,13 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
/// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
/// ```
pub fn is_global(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_global(&self) -> bool {
// check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
// globally routable addresses in the 192.0.0.0/24 range.
if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
if u32::from_be_bytes(self.octets()) == 0xc0000009
|| u32::from_be_bytes(self.octets()) == 0xc000000a
{
return true;
}
!self.is_private()
Expand Down Expand Up @@ -573,7 +580,8 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
/// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
/// ```
pub fn is_shared(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_shared(&self) -> bool {
self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
}

Expand Down Expand Up @@ -605,7 +613,8 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false);
/// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
/// ```
pub fn is_ietf_protocol_assignment(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_ietf_protocol_assignment(&self) -> bool {
self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
}

Expand All @@ -628,7 +637,8 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
/// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
/// ```
pub fn is_benchmarking(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_benchmarking(&self) -> bool {
self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
}

Expand Down Expand Up @@ -660,7 +670,8 @@ impl Ipv4Addr {
/// // The broadcast address is not considered as reserved for future use by this implementation
/// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
/// ```
pub fn is_reserved(&self) -> bool {
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
pub const fn is_reserved(&self) -> bool {
self.octets()[0] & 240 == 240 && !self.is_broadcast()
}

Expand All @@ -681,8 +692,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
/// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_multicast(&self) -> bool {
pub const fn is_multicast(&self) -> bool {
self.octets()[0] >= 224 && self.octets()[0] <= 239
}

Expand All @@ -701,9 +713,10 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
/// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_broadcast(&self) -> bool {
self == &Self::BROADCAST
pub const fn is_broadcast(&self) -> bool {
u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
}

/// Returns [`true`] if this address is in a range designated for documentation.
Expand All @@ -727,8 +740,9 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
/// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(since = "1.7.0", feature = "ip_17")]
pub fn is_documentation(&self) -> bool {
pub const fn is_documentation(&self) -> bool {
match self.octets() {
[192, 0, 2, _] => true,
[198, 51, 100, _] => true,
Expand All @@ -753,10 +767,13 @@ impl Ipv4Addr {
/// Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)
/// );
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
let [a, b, c, d] = self.octets();
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
Ipv6Addr {
inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] },
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not the prettiest solution, using implementation details from Ipv6Addr. Considered adding a non-pub method from_octets to Ipv6Addr, but it seemed out of place.

}
}

/// Converts this address to an IPv4-mapped [`IPv6` address].
Expand All @@ -773,10 +790,13 @@ impl Ipv4Addr {
/// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
/// Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
/// ```
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
let [a, b, c, d] = self.octets();
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d])
Ipv6Addr {
inner: c::in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] },
}
}
}

Expand Down
58 changes: 58 additions & 0 deletions src/test/ui/consts/std/net/ipv4.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// run-pass

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

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

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

const OCTETS: [u8; 4] = IP_ADDRESS.octets();
assert_eq!(OCTETS, [127, 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_PRIVATE : bool = IP_ADDRESS.is_private();
assert!(!IS_PRIVATE);

const IS_LINK_LOCAL : bool = IP_ADDRESS.is_link_local();
assert!(!IS_LINK_LOCAL);

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

const IS_SHARED : bool = IP_ADDRESS.is_shared();
assert!(!IS_SHARED);

const IS_IETF_PROTOCOL_ASSIGNMENT : bool = IP_ADDRESS.is_ietf_protocol_assignment();
assert!(!IS_IETF_PROTOCOL_ASSIGNMENT);

const IS_BENCHMARKING : bool = IP_ADDRESS.is_benchmarking();
assert!(!IS_BENCHMARKING);

const IS_RESERVED : bool = IP_ADDRESS.is_reserved();
assert!(!IS_RESERVED);

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

const IS_BROADCAST : bool = IP_ADDRESS.is_broadcast();
assert!(!IS_BROADCAST);

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

const IP_V6_COMPATIBLE : Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
assert_eq!(IP_V6_COMPATIBLE,
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1]));

const IP_V6_MAPPED : Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
assert_eq!(IP_V6_MAPPED,
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1]));
}