Skip to content

Commit 5e60ce8

Browse files
committed
uefi-raw: net: add convenient From impls + integration with core::net
- added missing conversions between core::net types and the uefi-raw net types - added missing conversions for "typical byte arrays"
1 parent f7b0f30 commit 5e60ce8

File tree

2 files changed

+145
-1
lines changed

2 files changed

+145
-1
lines changed

uefi-raw/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
- Added `::ZERO` constant for `IpAddress`
1313
- `Ipv4Address` and `Ipv6Address` now implement `Display`. They
1414
use the same formatting as `core::net::{Ipv4Addr, Ipv6Addr}`
15+
- Added comprehensive integration with `core::net::{IpAddr, Ipv4Addr, Ipv6Addr}`
16+
via `From` impls to better integrate uefi-raw types `IpAddress`,
17+
`Ipv4Address`, and `Ipv6Address` with the Rust ecosystem.
18+
- Added convenient `From` impls:
19+
- `[u8; 6]` <--> `MacAddress`
20+
- `[u8; 32]` --> `MacAddress`
21+
- `[u8; 4]` --> `Ipv4Address`, `IpAddress`
22+
- `[u8; 16]` --> `Ipv6Address`, `IpAddress`
1523

1624
## Changed
1725
- **Breaking:** The MSRV is now 1.85.1 and the crate uses the Rust 2024 edition.

uefi-raw/src/net.rs

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
use core::fmt::{self, Debug, Display, Formatter};
1212

1313
/// An IPv4 internet protocol address.
14+
///
15+
/// # Conversions and Relation to [`core::net`]
16+
///
17+
/// The following [`From`] implementations exist:
18+
/// - `[u8; 4]` -> [`Ipv4Address`]
19+
/// - [`core::net::Ipv4Addr`] -> [`Ipv4Address`]
20+
/// - [`core::net::IpAddr`] -> [`Ipv4Address`]
1421
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
1522
#[repr(transparent)]
1623
pub struct Ipv4Address(pub [u8; 4]);
@@ -35,6 +42,12 @@ impl From<Ipv4Address> for core::net::Ipv4Addr {
3542
}
3643
}
3744

45+
impl From<[u8; 4]> for Ipv4Address {
46+
fn from(octets: [u8; 4]) -> Self {
47+
Self(octets)
48+
}
49+
}
50+
3851
impl Display for Ipv4Address {
3952
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
4053
let ip = core::net::Ipv4Addr::from(*self);
@@ -43,6 +56,13 @@ impl Display for Ipv4Address {
4356
}
4457

4558
/// An IPv6 internet protocol address.
59+
///
60+
/// # Conversions and Relation to [`core::net`]
61+
///
62+
/// The following [`From`] implementations exist:
63+
/// - `[u8; 16]` -> [`Ipv6Address`]
64+
/// - [`core::net::Ipv6Addr`] -> [`Ipv6Address`]
65+
/// - [`core::net::IpAddr`] -> [`Ipv6Address`]
4666
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
4767
#[repr(transparent)]
4868
pub struct Ipv6Address(pub [u8; 16]);
@@ -67,6 +87,12 @@ impl From<Ipv6Address> for core::net::Ipv6Addr {
6787
}
6888
}
6989

90+
impl From<[u8; 16]> for Ipv6Address {
91+
fn from(octets: [u8; 16]) -> Self {
92+
Self(octets)
93+
}
94+
}
95+
7096
impl Display for Ipv6Address {
7197
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
7298
let ip = core::net::Ipv6Addr::from(*self);
@@ -80,6 +106,15 @@ impl Display for Ipv6Address {
80106
/// type is defined in the same way as edk2 for compatibility with C code. Note
81107
/// that this is an untagged union, so there's no way to tell which type of
82108
/// address an `IpAddress` value contains without additional context.
109+
///
110+
/// # Conversions and Relation to [`core::net`]
111+
///
112+
/// The following [`From`] implementations exist:
113+
/// - `[u8; 4]` -> [`IpAddress`]
114+
/// - `[u8; 16]` -> [`IpAddress`]
115+
/// - [`core::net::Ipv4Addr`] -> [`IpAddress`]
116+
/// - [`core::net::Ipv6Addr`] -> [`IpAddress`]
117+
/// - [`core::net::IpAddr`] -> [`IpAddress`]
83118
#[derive(Clone, Copy)]
84119
#[repr(C)]
85120
pub union IpAddress {
@@ -170,6 +205,30 @@ impl From<core::net::IpAddr> for IpAddress {
170205
}
171206
}
172207

208+
impl From<core::net::Ipv4Addr> for IpAddress {
209+
fn from(value: core::net::Ipv4Addr) -> Self {
210+
Self::new_v4(value.octets())
211+
}
212+
}
213+
214+
impl From<core::net::Ipv6Addr> for IpAddress {
215+
fn from(value: core::net::Ipv6Addr) -> Self {
216+
Self::new_v6(value.octets())
217+
}
218+
}
219+
220+
impl From<[u8; 4]> for IpAddress {
221+
fn from(octets: [u8; 4]) -> Self {
222+
Self::new_v4(octets)
223+
}
224+
}
225+
226+
impl From<[u8; 16]> for IpAddress {
227+
fn from(octets: [u8; 16]) -> Self {
228+
Self::new_v6(octets)
229+
}
230+
}
231+
173232
/// UEFI Media Access Control (MAC) address.
174233
///
175234
/// UEFI supports multiple network protocols and hardware types, not just
@@ -179,6 +238,13 @@ impl From<core::net::IpAddr> for IpAddress {
179238
///
180239
/// In most cases, this is just a typical `[u8; 6]` Ethernet style MAC
181240
/// address with the rest of the bytes being zero.
241+
///
242+
/// # Conversions and Relation to [`core::net`]
243+
///
244+
/// There is no matching type in [`core::net`] but the following [`From`]
245+
/// implementations exist:
246+
/// - `[u8; 6]` <-> [`MacAddress`]
247+
/// - `[u8; 32]` -> [`MacAddress`]
182248
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
183249
#[repr(transparent)]
184250
pub struct MacAddress(pub [u8; 32]);
@@ -200,7 +266,7 @@ impl MacAddress {
200266
}
201267
}
202268

203-
// Normal/typical MAC addresses, such as in Ethernet.
269+
// Normal Ethernet MAC address.
204270
impl From<[u8; 6]> for MacAddress {
205271
fn from(octets: [u8; 6]) -> Self {
206272
let mut buffer = [0; 32];
@@ -209,12 +275,20 @@ impl From<[u8; 6]> for MacAddress {
209275
}
210276
}
211277

278+
// Normal Ethernet MAC address.
212279
impl From<MacAddress> for [u8; 6] {
213280
fn from(MacAddress(o): MacAddress) -> Self {
214281
[o[0], o[1], o[2], o[3], o[4], o[5]]
215282
}
216283
}
217284

285+
// UEFI MAC addresses.
286+
impl From<[u8; 32]> for MacAddress {
287+
fn from(octets: [u8; 32]) -> Self {
288+
Self(octets)
289+
}
290+
}
291+
218292
#[cfg(test)]
219293
mod tests {
220294
use super::*;
@@ -267,4 +341,66 @@ mod tests {
267341
assert_eq!(align_of::<PackedHelper<IpAddress>>(), 1);
268342
assert_eq!(size_of::<PackedHelper<IpAddress>>(), 16);
269343
}
344+
345+
/// Tests the From-impls from the documentation.
346+
#[test]
347+
fn test_promised_from_impls() {
348+
// octets -> Ipv4Address
349+
{
350+
let octets = [0_u8, 1, 2, 3];
351+
assert_eq!(Ipv4Address::from(octets), Ipv4Address(octets));
352+
let uefi_addr = IpAddress::from(octets);
353+
assert_eq!(&octets, &unsafe { uefi_addr.v4.octets() });
354+
}
355+
// octets -> Ipv6Address
356+
{
357+
let octets = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
358+
assert_eq!(Ipv6Address::from(octets), Ipv6Address(octets));
359+
let uefi_addr = IpAddress::from(octets);
360+
assert_eq!(&octets, &unsafe { uefi_addr.v6.octets() });
361+
}
362+
// StdIpv4Addr -> Ipv4Address
363+
{
364+
let octets = [7, 5, 3, 1];
365+
let core_ipv4_addr = core::net::Ipv4Addr::from(octets);
366+
assert_eq!(Ipv4Address::from(core_ipv4_addr).octets(), octets);
367+
assert_eq!(
368+
unsafe { IpAddress::from(core_ipv4_addr).v4.octets() },
369+
octets
370+
);
371+
}
372+
// StdIpv6Addr -> Ipv6Address
373+
{
374+
let octets = [7, 5, 3, 1, 6, 3, 8, 5, 2, 5, 2, 7, 3, 5, 2, 6];
375+
let core_ipv6_addr = core::net::Ipv6Addr::from(octets);
376+
assert_eq!(Ipv6Address::from(core_ipv6_addr).octets(), octets);
377+
assert_eq!(
378+
unsafe { IpAddress::from(core_ipv6_addr).v6.octets() },
379+
octets
380+
);
381+
}
382+
// StdIpAddr -> IpAddress
383+
{
384+
let octets = [8, 8, 2, 6];
385+
let core_ip_addr = core::net::IpAddr::from(octets);
386+
assert_eq!(unsafe { IpAddress::from(core_ip_addr).v4.octets() }, octets);
387+
}
388+
// octets <-> MacAddress
389+
{
390+
let octets = [8, 8, 2, 6, 6, 7];
391+
let uefi_mac_addr = MacAddress::from(octets);
392+
assert_eq!(uefi_mac_addr.octets()[0..6], octets);
393+
let octets2: [u8; 6] = uefi_mac_addr.into();
394+
assert_eq!(octets2, octets)
395+
}
396+
// octets -> MacAddress
397+
{
398+
let octets = [
399+
8_u8, 8, 2, 6, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0,
400+
0, 0, 0, 0, 42,
401+
];
402+
let uefi_mac_addr = MacAddress::from(octets);
403+
assert_eq!(uefi_mac_addr.octets(), octets);
404+
}
405+
}
270406
}

0 commit comments

Comments
 (0)