Skip to content

Commit 6d8235e

Browse files
authored
Rollup merge of rust-lang#130629 - Dirbaio:net-from-octets, r=tgross35
core/net: add Ipv[46]Addr::from_octets, Ipv6Addr::from_segments. Adds: - `Ipv4Address::from_octets([u8;4])` - `Ipv6Address::from_octets([u8;16])` - `Ipv6Address::from_segments([u16;8])` equivalent to the existing `From` impls. Advantages: - Consistent with `to_bits, from_bits`. - More discoverable than the `From` impls. - Helps with type inference: it's common to want to convert byte slices to IP addrs. If you try this ```rust fn foo(x: &[u8]) -> Ipv4Addr { Ipv4Addr::from(foo.try_into().unwrap()) } ``` it [doesn't work](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0e2873312de275a58fa6e33d1b213bec). You have to write `Ipv4Addr::from(<[u8;4]>::try_from(x).unwrap())` instead, which is not great. With `from_octets` it is able to infer the right types. Found this while porting [smoltcp](https://github.com/smoltcp-rs/smoltcp/) from its own IP address types to the `core::net` types. ~~Tracking issues rust-lang#27709 rust-lang#76205~~ Tracking issue: rust-lang#131360
2 parents 88634c8 + 2cfa6d0 commit 6d8235e

File tree

3 files changed

+114
-26
lines changed

3 files changed

+114
-26
lines changed

core/src/net/ip_addr.rs

+90-25
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,24 @@ impl Ipv4Addr {
600600
self.octets
601601
}
602602

603+
/// Creates an `Ipv4Addr` from a four element byte array.
604+
///
605+
/// # Examples
606+
///
607+
/// ```
608+
/// #![feature(ip_from)]
609+
/// use std::net::Ipv4Addr;
610+
///
611+
/// let addr = Ipv4Addr::from_octets([13u8, 12u8, 11u8, 10u8]);
612+
/// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
613+
/// ```
614+
#[unstable(feature = "ip_from", issue = "131360")]
615+
#[must_use]
616+
#[inline]
617+
pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr {
618+
Ipv4Addr { octets }
619+
}
620+
603621
/// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
604622
///
605623
/// This property is defined in _UNIX Network Programming, Second Edition_,
@@ -1400,6 +1418,34 @@ impl Ipv6Addr {
14001418
]
14011419
}
14021420

1421+
/// Creates an `Ipv6Addr` from an eight element 16-bit array.
1422+
///
1423+
/// # Examples
1424+
///
1425+
/// ```
1426+
/// #![feature(ip_from)]
1427+
/// use std::net::Ipv6Addr;
1428+
///
1429+
/// let addr = Ipv6Addr::from_segments([
1430+
/// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
1431+
/// 0x209u16, 0x208u16, 0x207u16, 0x206u16,
1432+
/// ]);
1433+
/// assert_eq!(
1434+
/// Ipv6Addr::new(
1435+
/// 0x20d, 0x20c, 0x20b, 0x20a,
1436+
/// 0x209, 0x208, 0x207, 0x206,
1437+
/// ),
1438+
/// addr
1439+
/// );
1440+
/// ```
1441+
#[unstable(feature = "ip_from", issue = "131360")]
1442+
#[must_use]
1443+
#[inline]
1444+
pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr {
1445+
let [a, b, c, d, e, f, g, h] = segments;
1446+
Ipv6Addr::new(a, b, c, d, e, f, g, h)
1447+
}
1448+
14031449
/// Returns [`true`] for the special 'unspecified' address (`::`).
14041450
///
14051451
/// This property is defined in [IETF RFC 4291].
@@ -1932,7 +1978,7 @@ impl Ipv6Addr {
19321978
/// use std::net::Ipv6Addr;
19331979
///
19341980
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
1935-
/// [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
1981+
/// [0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
19361982
/// ```
19371983
#[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
19381984
#[stable(feature = "ipv6_to_octets", since = "1.12.0")]
@@ -1941,6 +1987,33 @@ impl Ipv6Addr {
19411987
pub const fn octets(&self) -> [u8; 16] {
19421988
self.octets
19431989
}
1990+
1991+
/// Creates an `Ipv6Addr` from a sixteen element byte array.
1992+
///
1993+
/// # Examples
1994+
///
1995+
/// ```
1996+
/// #![feature(ip_from)]
1997+
/// use std::net::Ipv6Addr;
1998+
///
1999+
/// let addr = Ipv6Addr::from_octets([
2000+
/// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
2001+
/// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
2002+
/// ]);
2003+
/// assert_eq!(
2004+
/// Ipv6Addr::new(
2005+
/// 0x1918, 0x1716, 0x1514, 0x1312,
2006+
/// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
2007+
/// ),
2008+
/// addr
2009+
/// );
2010+
/// ```
2011+
#[unstable(feature = "ip_from", issue = "131360")]
2012+
#[must_use]
2013+
#[inline]
2014+
pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr {
2015+
Ipv6Addr { octets }
2016+
}
19442017
}
19452018

19462019
/// Writes an Ipv6Addr, conforming to the canonical style described by
@@ -2113,15 +2186,13 @@ impl From<[u8; 16]> for Ipv6Addr {
21132186
/// use std::net::Ipv6Addr;
21142187
///
21152188
/// let addr = Ipv6Addr::from([
2116-
/// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
2117-
/// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
2189+
/// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
2190+
/// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
21182191
/// ]);
21192192
/// assert_eq!(
21202193
/// Ipv6Addr::new(
2121-
/// 0x1918, 0x1716,
2122-
/// 0x1514, 0x1312,
2123-
/// 0x1110, 0x0f0e,
2124-
/// 0x0d0c, 0x0b0a
2194+
/// 0x1918, 0x1716, 0x1514, 0x1312,
2195+
/// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
21252196
/// ),
21262197
/// addr
21272198
/// );
@@ -2142,15 +2213,13 @@ impl From<[u16; 8]> for Ipv6Addr {
21422213
/// use std::net::Ipv6Addr;
21432214
///
21442215
/// let addr = Ipv6Addr::from([
2145-
/// 525u16, 524u16, 523u16, 522u16,
2146-
/// 521u16, 520u16, 519u16, 518u16,
2216+
/// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
2217+
/// 0x209u16, 0x208u16, 0x207u16, 0x206u16,
21472218
/// ]);
21482219
/// assert_eq!(
21492220
/// Ipv6Addr::new(
2150-
/// 0x20d, 0x20c,
2151-
/// 0x20b, 0x20a,
2152-
/// 0x209, 0x208,
2153-
/// 0x207, 0x206
2221+
/// 0x20d, 0x20c, 0x20b, 0x20a,
2222+
/// 0x209, 0x208, 0x207, 0x206,
21542223
/// ),
21552224
/// addr
21562225
/// );
@@ -2172,15 +2241,13 @@ impl From<[u8; 16]> for IpAddr {
21722241
/// use std::net::{IpAddr, Ipv6Addr};
21732242
///
21742243
/// let addr = IpAddr::from([
2175-
/// 25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
2176-
/// 17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
2244+
/// 0x19u8, 0x18u8, 0x17u8, 0x16u8, 0x15u8, 0x14u8, 0x13u8, 0x12u8,
2245+
/// 0x11u8, 0x10u8, 0x0fu8, 0x0eu8, 0x0du8, 0x0cu8, 0x0bu8, 0x0au8,
21772246
/// ]);
21782247
/// assert_eq!(
21792248
/// IpAddr::V6(Ipv6Addr::new(
2180-
/// 0x1918, 0x1716,
2181-
/// 0x1514, 0x1312,
2182-
/// 0x1110, 0x0f0e,
2183-
/// 0x0d0c, 0x0b0a
2249+
/// 0x1918, 0x1716, 0x1514, 0x1312,
2250+
/// 0x1110, 0x0f0e, 0x0d0c, 0x0b0a,
21842251
/// )),
21852252
/// addr
21862253
/// );
@@ -2201,15 +2268,13 @@ impl From<[u16; 8]> for IpAddr {
22012268
/// use std::net::{IpAddr, Ipv6Addr};
22022269
///
22032270
/// let addr = IpAddr::from([
2204-
/// 525u16, 524u16, 523u16, 522u16,
2205-
/// 521u16, 520u16, 519u16, 518u16,
2271+
/// 0x20du16, 0x20cu16, 0x20bu16, 0x20au16,
2272+
/// 0x209u16, 0x208u16, 0x207u16, 0x206u16,
22062273
/// ]);
22072274
/// assert_eq!(
22082275
/// IpAddr::V6(Ipv6Addr::new(
2209-
/// 0x20d, 0x20c,
2210-
/// 0x20b, 0x20a,
2211-
/// 0x209, 0x208,
2212-
/// 0x207, 0x206
2276+
/// 0x20d, 0x20c, 0x20b, 0x20a,
2277+
/// 0x209, 0x208, 0x207, 0x206,
22132278
/// )),
22142279
/// addr
22152280
/// );

core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#![feature(hashmap_internals)]
5151
#![feature(int_roundings)]
5252
#![feature(ip)]
53+
#![feature(ip_from)]
5354
#![feature(is_ascii_octdigit)]
5455
#![feature(isqrt)]
5556
#![feature(iter_advance_by)]

core/tests/net/ip_addr.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ fn ipv6_properties() {
494494
let octets = &[$($octet),*];
495495
assert_eq!(&ip!($s).octets(), octets);
496496
assert_eq!(Ipv6Addr::from(*octets), ip!($s));
497+
assert_eq!(Ipv6Addr::from_octets(*octets), ip!($s));
497498

498499
let unspecified: u32 = 1 << 0;
499500
let loopback: u32 = 1 << 1;
@@ -846,15 +847,19 @@ fn ipv6_from_constructors() {
846847

847848
#[test]
848849
fn ipv4_from_octets() {
849-
assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
850+
assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1));
851+
assert_eq!(Ipv4Addr::from_octets([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1));
850852
}
851853

852854
#[test]
853855
fn ipv6_from_segments() {
854856
let from_u16s =
855857
Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
858+
let from_u16s_explicit =
859+
Ipv6Addr::from_segments([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
856860
let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
857861
assert_eq!(new, from_u16s);
862+
assert_eq!(new, from_u16s_explicit);
858863
}
859864

860865
#[test]
@@ -865,7 +870,15 @@ fn ipv6_from_octets() {
865870
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
866871
0xff,
867872
]);
873+
let from_u16s_explicit =
874+
Ipv6Addr::from_segments([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
875+
let from_u8s_explicit = Ipv6Addr::from_octets([
876+
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
877+
0xff,
878+
]);
868879
assert_eq!(from_u16s, from_u8s);
880+
assert_eq!(from_u16s, from_u16s_explicit);
881+
assert_eq!(from_u16s_explicit, from_u8s_explicit);
869882
}
870883

871884
#[test]
@@ -915,6 +928,9 @@ fn ipv4_const() {
915928
const OCTETS: [u8; 4] = IP_ADDRESS.octets();
916929
assert_eq!(OCTETS, [127, 0, 0, 1]);
917930

931+
const FROM_OCTETS: Ipv4Addr = Ipv4Addr::from_octets(OCTETS);
932+
assert_eq!(IP_ADDRESS, FROM_OCTETS);
933+
918934
const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
919935
assert!(!IS_UNSPECIFIED);
920936

@@ -971,9 +987,15 @@ fn ipv6_const() {
971987
const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
972988
assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
973989

990+
const FROM_SEGMENTS: Ipv6Addr = Ipv6Addr::from_segments(SEGMENTS);
991+
assert_eq!(IP_ADDRESS, FROM_SEGMENTS);
992+
974993
const OCTETS: [u8; 16] = IP_ADDRESS.octets();
975994
assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
976995

996+
const FROM_OCTETS: Ipv6Addr = Ipv6Addr::from_octets(OCTETS);
997+
assert_eq!(IP_ADDRESS, FROM_OCTETS);
998+
977999
const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
9781000
assert!(!IS_UNSPECIFIED);
9791001

0 commit comments

Comments
 (0)