Skip to content

Commit 9fa22d9

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 ff424b5 commit 9fa22d9

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

uefi-raw/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
- Added `::octets()` for `Ipv4Address`, `Ipv6Address`, and
99
`MacAddress` to streamline the API with `core::net`.
1010
- Added `::ZERO` constant for `IpAddress`
11+
- Added comprehensive integration with `core::net::{IpAddr, Ipv4Addr, Ipv6Addr}`
12+
via `From` impls to better integrate uefi-raw types `IpAddress`,
13+
`Ipv4Address`, and `Ipv6Address` with the Rust ecosystem.
14+
- Added convenient `From` impls:
15+
- `[u8; 6]` --> `MacAddress`
16+
- `[u8; 32]` --> `MacAddress`
17+
- `[u8; 4]` --> `Ipv4Address`, `IpAddress`
18+
- `[u8; 16]` --> `Ipv6Address`, `IpAddress`
1119

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

uefi-raw/src/net.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
use core::fmt::{self, Debug, 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,7 +42,20 @@ 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
/// An IPv6 internet protocol address.
52+
///
53+
/// # Conversions and Relation to [`core::net`]
54+
///
55+
/// The following [`From`] implementations exist:
56+
/// - `[u8; 16]` -> [`Ipv6Address`]
57+
/// - [`core::net::Ipv6Addr`] -> [`Ipv6Address`]
58+
/// - [`core::net::IpAddr`] -> [`Ipv6Address`]
3959
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
4060
#[repr(transparent)]
4161
pub struct Ipv6Address(pub [u8; 16]);
@@ -60,12 +80,27 @@ impl From<Ipv6Address> for core::net::Ipv6Addr {
6080
}
6181
}
6282

83+
impl From<[u8; 16]> for Ipv6Address {
84+
fn from(octets: [u8; 16]) -> Self {
85+
Self(octets)
86+
}
87+
}
88+
6389
/// An IPv4 or IPv6 internet protocol address that is ABI compatible with EFI.
6490
///
6591
/// Corresponds to the `EFI_IP_ADDRESS` type in the UEFI specification. This
6692
/// type is defined in the same way as edk2 for compatibility with C code. Note
6793
/// that this is an untagged union, so there's no way to tell which type of
6894
/// address an `IpAddress` value contains without additional context.
95+
///
96+
/// # Conversions and Relation to [`core::net`]
97+
///
98+
/// The following [`From`] implementations exist:
99+
/// - `[u8; 4]` -> [`IpAddress`]
100+
/// - `[u8; 16]` -> [`IpAddress`]
101+
/// - [`core::net::Ipv4Addr`] -> [`IpAddress`]
102+
/// - [`core::net::Ipv6Addr`] -> [`IpAddress`]
103+
/// - [`core::net::IpAddr`] -> [`IpAddress`]
69104
#[derive(Clone, Copy)]
70105
#[repr(C)]
71106
pub union IpAddress {
@@ -135,6 +170,30 @@ impl From<core::net::IpAddr> for IpAddress {
135170
}
136171
}
137172

173+
impl From<core::net::Ipv4Addr> for IpAddress {
174+
fn from(value: core::net::Ipv4Addr) -> Self {
175+
Self::new_v4(value.octets())
176+
}
177+
}
178+
179+
impl From<core::net::Ipv6Addr> for IpAddress {
180+
fn from(value: core::net::Ipv6Addr) -> Self {
181+
Self::new_v6(value.octets())
182+
}
183+
}
184+
185+
impl From<[u8; 4]> for IpAddress {
186+
fn from(octets: [u8; 4]) -> Self {
187+
Self::new_v4(octets)
188+
}
189+
}
190+
191+
impl From<[u8; 16]> for IpAddress {
192+
fn from(octets: [u8; 16]) -> Self {
193+
Self::new_v6(octets)
194+
}
195+
}
196+
138197
/// UEFI Media Access Control (MAC) address.
139198
///
140199
/// UEFI supports multiple network protocols and hardware types, not just
@@ -144,6 +203,13 @@ impl From<core::net::IpAddr> for IpAddress {
144203
///
145204
/// In most cases, this is just a typical `[u8; 6]` Ethernet style MAC
146205
/// address with the rest of the bytes being zero.
206+
///
207+
/// # Conversions and Relation to [`core::net`]
208+
///
209+
/// There is no matching type in [`core::net`] but the following [`From`]
210+
/// implementations exist:
211+
/// - `[u8; 6]` -> [`MacAddress`]
212+
/// - `[u8; 32]` -> [`MacAddress`]
147213
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
148214
#[repr(transparent)]
149215
pub struct MacAddress(pub [u8; 32]);
@@ -171,6 +237,13 @@ impl From<MacAddress> for [u8; 6] {
171237
}
172238
}
173239

240+
// UEFI MAC addresses.
241+
impl From<[u8; 32]> for MacAddress {
242+
fn from(octets: [u8; 32]) -> Self {
243+
Self(octets)
244+
}
245+
}
246+
174247
#[cfg(test)]
175248
mod tests {
176249
use super::*;
@@ -223,4 +296,64 @@ mod tests {
223296
assert_eq!(align_of::<PackedHelper<IpAddress>>(), 1);
224297
assert_eq!(size_of::<PackedHelper<IpAddress>>(), 16);
225298
}
299+
300+
/// Tests the From-impls from the documentation.
301+
#[test]
302+
fn test_promised_from_impls() {
303+
// octets -> Ipv4Address
304+
{
305+
let octets = [0_u8, 1, 2, 3];
306+
assert_eq!(Ipv4Address::from(octets), Ipv4Address(octets));
307+
let uefi_addr = IpAddress::from(octets);
308+
assert_eq!(&octets, &unsafe { uefi_addr.v4.octets() });
309+
}
310+
// octets -> Ipv6Address
311+
{
312+
let octets = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
313+
assert_eq!(Ipv6Address::from(octets), Ipv6Address(octets));
314+
let uefi_addr = IpAddress::from(octets);
315+
assert_eq!(&octets, &unsafe { uefi_addr.v6.octets() });
316+
}
317+
// StdIpv4Addr -> Ipv4Address
318+
{
319+
let octets = [7, 5, 3, 1];
320+
let core_ipv4_addr = core::net::Ipv4Addr::from(octets);
321+
assert_eq!(Ipv4Address::from(core_ipv4_addr).octets(), octets);
322+
assert_eq!(
323+
unsafe { IpAddress::from(core_ipv4_addr).v4.octets() },
324+
octets
325+
);
326+
}
327+
// StdIpv6Addr -> Ipv6Address
328+
{
329+
let octets = [7, 5, 3, 1, 6, 3, 8, 5, 2, 5, 2, 7, 3, 5, 2, 6];
330+
let core_ipv6_addr = core::net::Ipv6Addr::from(octets);
331+
assert_eq!(Ipv6Address::from(core_ipv6_addr).octets(), octets);
332+
assert_eq!(
333+
unsafe { IpAddress::from(core_ipv6_addr).v6.octets() },
334+
octets
335+
);
336+
}
337+
// StdIpAddr -> IpAddress
338+
{
339+
let octets = [8, 8, 2, 6];
340+
let core_ip_addr = core::net::IpAddr::from(octets);
341+
assert_eq!(unsafe { IpAddress::from(core_ip_addr).v4.octets() }, octets);
342+
}
343+
// octets -> MacAddress
344+
{
345+
let octets = [8, 8, 2, 6, 6, 7];
346+
let uefi_mac_addr = MacAddress::from(octets);
347+
assert_eq!(uefi_mac_addr.octets()[0..6], octets);
348+
}
349+
// octets -> MacAddress
350+
{
351+
let octets = [
352+
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,
353+
0, 0, 0, 0, 42,
354+
];
355+
let uefi_mac_addr = MacAddress::from(octets);
356+
assert_eq!(uefi_mac_addr.octets(), octets);
357+
}
358+
}
226359
}

0 commit comments

Comments
 (0)