core/net: add Ipv[46]Addr::from_octets, Ipv6Addr::from_segments

This commit is contained in:
Dario Nieuwenhuis 2024-10-07 16:11:39 +02:00
parent 0b16baa570
commit 725d1f7905
3 changed files with 101 additions and 1 deletions

View File

@ -600,6 +600,24 @@ pub const fn from_bits(bits: u32) -> Ipv4Addr {
self.octets self.octets
} }
/// Creates an `Ipv4Addr` from a four element byte array.
///
/// # Examples
///
/// ```
/// #![feature(ip_from)]
/// use std::net::Ipv4Addr;
///
/// let addr = Ipv4Addr::from_octets([13u8, 12u8, 11u8, 10u8]);
/// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
/// ```
#[unstable(feature = "ip_from", issue = "131360")]
#[must_use]
#[inline]
pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr {
Ipv4Addr { octets }
}
/// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`). /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
/// ///
/// This property is defined in _UNIX Network Programming, Second Edition_, /// This property is defined in _UNIX Network Programming, Second Edition_,
@ -1400,6 +1418,36 @@ pub const fn from_bits(bits: u128) -> Ipv6Addr {
] ]
} }
/// Creates an `Ipv6Addr` from an eight element 16-bit array.
///
/// # Examples
///
/// ```
/// #![feature(ip_from)]
/// use std::net::Ipv6Addr;
///
/// let addr = Ipv6Addr::from_segments([
/// 525u16, 524u16, 523u16, 522u16,
/// 521u16, 520u16, 519u16, 518u16,
/// ]);
/// assert_eq!(
/// Ipv6Addr::new(
/// 0x20d, 0x20c,
/// 0x20b, 0x20a,
/// 0x209, 0x208,
/// 0x207, 0x206
/// ),
/// addr
/// );
/// ```
#[unstable(feature = "ip_from", issue = "131360")]
#[must_use]
#[inline]
pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr {
let [a, b, c, d, e, f, g, h] = segments;
Ipv6Addr::new(a, b, c, d, e, f, g, h)
}
/// Returns [`true`] for the special 'unspecified' address (`::`). /// Returns [`true`] for the special 'unspecified' address (`::`).
/// ///
/// This property is defined in [IETF RFC 4291]. /// This property is defined in [IETF RFC 4291].
@ -1941,6 +1989,35 @@ pub const fn to_canonical(&self) -> IpAddr {
pub const fn octets(&self) -> [u8; 16] { pub const fn octets(&self) -> [u8; 16] {
self.octets self.octets
} }
/// Creates an `Ipv6Addr` from a sixteen element byte array.
///
/// # Examples
///
/// ```
/// #![feature(ip_from)]
/// use std::net::Ipv6Addr;
///
/// let addr = Ipv6Addr::from_octets([
/// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
/// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
/// ]);
/// assert_eq!(
/// Ipv6Addr::new(
/// 0x1918, 0x1716,
/// 0x1514, 0x1312,
/// 0x1110, 0x0f0e,
/// 0x0d0c, 0x0b0a
/// ),
/// addr
/// );
/// ```
#[unstable(feature = "ip_from", issue = "131360")]
#[must_use]
#[inline]
pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr {
Ipv6Addr { octets }
}
} }
/// Writes an Ipv6Addr, conforming to the canonical style described by /// Writes an Ipv6Addr, conforming to the canonical style described by

View File

@ -57,6 +57,7 @@
#![feature(hashmap_internals)] #![feature(hashmap_internals)]
#![feature(int_roundings)] #![feature(int_roundings)]
#![feature(ip)] #![feature(ip)]
#![feature(ip_from)]
#![feature(is_ascii_octdigit)] #![feature(is_ascii_octdigit)]
#![feature(isqrt)] #![feature(isqrt)]
#![feature(iter_advance_by)] #![feature(iter_advance_by)]

View File

@ -494,6 +494,7 @@ macro_rules! check {
let octets = &[$($octet),*]; let octets = &[$($octet),*];
assert_eq!(&ip!($s).octets(), octets); assert_eq!(&ip!($s).octets(), octets);
assert_eq!(Ipv6Addr::from(*octets), ip!($s)); assert_eq!(Ipv6Addr::from(*octets), ip!($s));
assert_eq!(Ipv6Addr::from_octets(*octets), ip!($s));
let unspecified: u32 = 1 << 0; let unspecified: u32 = 1 << 0;
let loopback: u32 = 1 << 1; let loopback: u32 = 1 << 1;
@ -846,15 +847,19 @@ fn ipv6_from_constructors() {
#[test] #[test]
fn ipv4_from_octets() { fn ipv4_from_octets() {
assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1)) assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1));
assert_eq!(Ipv4Addr::from_octets([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1));
} }
#[test] #[test]
fn ipv6_from_segments() { fn ipv6_from_segments() {
let from_u16s = let from_u16s =
Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]); Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
let from_u16s_explicit =
Ipv6Addr::from_segments([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff); let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
assert_eq!(new, from_u16s); assert_eq!(new, from_u16s);
assert_eq!(new, from_u16s_explicit);
} }
#[test] #[test]
@ -865,7 +870,15 @@ fn ipv6_from_octets() {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
0xff, 0xff,
]); ]);
let from_u16s_explicit =
Ipv6Addr::from_segments([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
let from_u8s_explicit = Ipv6Addr::from_octets([
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
0xff,
]);
assert_eq!(from_u16s, from_u8s); assert_eq!(from_u16s, from_u8s);
assert_eq!(from_u16s, from_u16s_explicit);
assert_eq!(from_u16s_explicit, from_u8s_explicit);
} }
#[test] #[test]
@ -915,6 +928,9 @@ fn ipv4_const() {
const OCTETS: [u8; 4] = IP_ADDRESS.octets(); const OCTETS: [u8; 4] = IP_ADDRESS.octets();
assert_eq!(OCTETS, [127, 0, 0, 1]); assert_eq!(OCTETS, [127, 0, 0, 1]);
const FROM_OCTETS: Ipv4Addr = Ipv4Addr::from_octets(OCTETS);
assert_eq!(IP_ADDRESS, FROM_OCTETS);
const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
assert!(!IS_UNSPECIFIED); assert!(!IS_UNSPECIFIED);
@ -971,9 +987,15 @@ fn ipv6_const() {
const SEGMENTS: [u16; 8] = IP_ADDRESS.segments(); const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]); assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
const FROM_SEGMENTS: Ipv6Addr = Ipv6Addr::from_segments(SEGMENTS);
assert_eq!(IP_ADDRESS, FROM_SEGMENTS);
const OCTETS: [u8; 16] = IP_ADDRESS.octets(); 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]); assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
const FROM_OCTETS: Ipv6Addr = Ipv6Addr::from_octets(OCTETS);
assert_eq!(IP_ADDRESS, FROM_OCTETS);
const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified(); const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
assert!(!IS_UNSPECIFIED); assert!(!IS_UNSPECIFIED);