Skip to content

Commit 1b5d791

Browse files
committed
uefi-raw: 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 3aec8a8 commit 1b5d791

File tree

2 files changed

+139
-4
lines changed

2 files changed

+139
-4
lines changed

uefi-raw/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@
1111
constructor to ensure that always all bytes are initialized.
1212
- Added `::as_ptr()` and `::as_ptr_mut()` for `IpAddress` to simplify usage
1313
with various UEFI functions and protocols.
14+
- Added comprehensive integration with `core::net::{IpAddr, Ipv4Addr, Ipv6Addr}`
15+
via `From` impls to better integrate uefi-raw types `IpAddress`,
16+
`Ipv4Address`, and `Ipv6Address` with the Rust ecosystem.
17+
- Added convenient `From` impls:
18+
- `[u8; 6]` --> `MacAddress`
19+
- `[u8; 32]` --> `MacAddress`
20+
- `[u8; 4]` --> `Ipv4Address`, `IpAddress`
21+
- `[u8; 16]` --> `Ipv6Address`, `IpAddress`
1422

1523
## Changed
1624
- The documentation for UEFI protocols has been streamlined and improved.

uefi-raw/src/net.rs

Lines changed: 131 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ use core::mem;
1313
use core::net::{IpAddr as StdIpAddr, Ipv4Addr as StdIpv4Addr, Ipv6Addr as StdIpv6Addr};
1414

1515
/// An IPv4 internet protocol address.
16+
///
17+
/// # Conversions and Relation to [`core::net`]
18+
///
19+
/// The following [`From`] implementations exist:
20+
/// - `[u8; 4]` -> [`Ipv4Address`]
21+
/// - [`core::net::Ipv4Addr`] -> [`Ipv4Address`]
22+
/// - [`core::net::IpAddr`] -> [`Ipv4Address`]
1623
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
1724
#[repr(transparent)]
1825
pub struct Ipv4Address(pub [u8; 4]);
@@ -37,7 +44,20 @@ impl From<Ipv4Address> for StdIpv4Addr {
3744
}
3845
}
3946

47+
impl From<[u8; 4]> for Ipv4Address {
48+
fn from(octets: [u8; 4]) -> Self {
49+
Self(octets)
50+
}
51+
}
52+
4053
/// An IPv6 internet protocol address.
54+
///
55+
/// # Conversions and Relation to [`core::net`]
56+
///
57+
/// The following [`From`] implementations exist:
58+
/// - `[u8; 16]` -> [`Ipv6Address`]
59+
/// - [`core::net::Ipv6Addr`] -> [`Ipv6Address`]
60+
/// - [`core::net::IpAddr`] -> [`Ipv6Address`]
4161
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
4262
#[repr(transparent)]
4363
pub struct Ipv6Address(pub [u8; 16]);
@@ -62,12 +82,27 @@ impl From<Ipv6Address> for StdIpv6Addr {
6282
}
6383
}
6484

65-
/// An IPv4 or IPv6 internet protocol address that is ABI compatible with EFI.
85+
impl From<[u8; 16]> for Ipv6Address {
86+
fn from(octets: [u8; 16]) -> Self {
87+
Self(octets)
88+
}
89+
}
90+
91+
/// EFI ABI-compatible union of an IPv4 or IPv6 internet protocol address.
6692
///
6793
/// Corresponds to the `EFI_IP_ADDRESS` type in the UEFI specification. This
6894
/// type is defined in the same way as edk2 for compatibility with C code. Note
6995
/// that this is an untagged union, so there's no way to tell which type of
7096
/// address an `IpAddress` value contains without additional context.
97+
///
98+
/// # Conversions and Relation to [`core::net`]
99+
///
100+
/// The following [`From`] implementations exist:
101+
/// - `[u8; 4]` -> [`IpAddress`]
102+
/// - `[u8; 16]` -> [`IpAddress`]
103+
/// - [`core::net::Ipv4Addr`] -> [`IpAddress`]
104+
/// - [`core::net::Ipv6Addr`] -> [`IpAddress`]
105+
/// - [`core::net::IpAddr`] -> [`IpAddress`]
71106
#[derive(Clone, Copy)]
72107
#[repr(C)]
73108
pub union IpAddress {
@@ -152,6 +187,30 @@ impl From<StdIpAddr> for IpAddress {
152187
}
153188
}
154189

190+
impl From<StdIpv4Addr> for IpAddress {
191+
fn from(value: StdIpv4Addr) -> Self {
192+
Self::new_v4(value.octets())
193+
}
194+
}
195+
196+
impl From<StdIpv6Addr> for IpAddress {
197+
fn from(value: StdIpv6Addr) -> Self {
198+
Self::new_v6(value.octets())
199+
}
200+
}
201+
202+
impl From<[u8; 4]> for IpAddress {
203+
fn from(octets: [u8; 4]) -> Self {
204+
Self::new_v4(octets)
205+
}
206+
}
207+
208+
impl From<[u8; 16]> for IpAddress {
209+
fn from(octets: [u8; 16]) -> Self {
210+
Self::new_v6(octets)
211+
}
212+
}
213+
155214
/// UEFI Media Access Control (MAC) address.
156215
///
157216
/// UEFI supports multiple network protocols and hardware types, not just
@@ -161,6 +220,13 @@ impl From<StdIpAddr> for IpAddress {
161220
///
162221
/// In most cases, this is just a typical `[u8; 6]` Ethernet style MAC
163222
/// address with the rest of the bytes being zero.
223+
///
224+
/// # Conversions and Relation to [`core::net`]
225+
///
226+
/// There is no matching type in [`core::net`] but the following [`From`]
227+
/// implementations exist:
228+
/// - `[u8; 6]` -> [`MacAddress`]
229+
/// - `[u8; 32]` -> [`MacAddress`]
164230
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
165231
#[repr(transparent)]
166232
pub struct MacAddress(pub [u8; 32]);
@@ -182,9 +248,10 @@ impl From<[u8; 6]> for MacAddress {
182248
}
183249
}
184250

185-
impl From<MacAddress> for [u8; 6] {
186-
fn from(MacAddress(o): MacAddress) -> Self {
187-
[o[0], o[1], o[2], o[3], o[4], o[5]]
251+
// UEFI MAC addresses.
252+
impl From<[u8; 32]> for MacAddress {
253+
fn from(octets: [u8; 32]) -> Self {
254+
Self(octets)
188255
}
189256
}
190257

@@ -240,4 +307,64 @@ mod tests {
240307
assert_eq!(align_of::<PackedHelper<IpAddress>>(), 1);
241308
assert_eq!(size_of::<PackedHelper<IpAddress>>(), 16);
242309
}
310+
311+
/// Tests the From-impls from the documentation.
312+
#[test]
313+
fn test_promised_from_impls() {
314+
// octets -> Ipv4Address
315+
{
316+
let octets = [0_u8, 1, 2, 3];
317+
assert_eq!(Ipv4Address::from(octets), Ipv4Address(octets));
318+
let uefi_addr = IpAddress::from(octets);
319+
assert_eq!(&octets, &unsafe { uefi_addr.v4.octets() });
320+
}
321+
// octets -> Ipv6Address
322+
{
323+
let octets = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
324+
assert_eq!(Ipv6Address::from(octets), Ipv6Address(octets));
325+
let uefi_addr = IpAddress::from(octets);
326+
assert_eq!(&octets, &unsafe { uefi_addr.v6.octets() });
327+
}
328+
// StdIpv4Addr -> Ipv4Address
329+
{
330+
let octets = [7, 5, 3, 1];
331+
let core_ipv4_addr = StdIpv4Addr::from(octets);
332+
assert_eq!(Ipv4Address::from(core_ipv4_addr).octets(), octets);
333+
assert_eq!(
334+
unsafe { IpAddress::from(core_ipv4_addr).v4.octets() },
335+
octets
336+
);
337+
}
338+
// StdIpv6Addr -> Ipv6Address
339+
{
340+
let octets = [7, 5, 3, 1, 6, 3, 8, 5, 2, 5, 2, 7, 3, 5, 2, 6];
341+
let core_ipv6_addr = StdIpv6Addr::from(octets);
342+
assert_eq!(Ipv6Address::from(core_ipv6_addr).octets(), octets);
343+
assert_eq!(
344+
unsafe { IpAddress::from(core_ipv6_addr).v6.octets() },
345+
octets
346+
);
347+
}
348+
// StdIpAddr -> IpAddress
349+
{
350+
let octets = [8, 8, 2, 6];
351+
let core_ip_addr = StdIpAddr::from(octets);
352+
assert_eq!(unsafe { IpAddress::from(core_ip_addr).v4.octets() }, octets);
353+
}
354+
// octets -> MacAddress
355+
{
356+
let octets = [8, 8, 2, 6, 6, 7];
357+
let uefi_mac_addr = MacAddress::from(octets);
358+
assert_eq!(uefi_mac_addr.octets()[0..6], octets);
359+
}
360+
// octets -> MacAddress
361+
{
362+
let octets = [
363+
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,
364+
0, 0, 0, 0, 42,
365+
];
366+
let uefi_mac_addr = MacAddress::from(octets);
367+
assert_eq!(uefi_mac_addr.octets(), octets);
368+
}
369+
}
243370
}

0 commit comments

Comments
 (0)