Skip to content

Commit 6019349

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 82bf2b0 commit 6019349

File tree

2 files changed

+144
-1
lines changed

2 files changed

+144
-1
lines changed

uefi-raw/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
- Added `HiiConfigAccessProtocol`.
88
- Added `::octets()` for `Ipv4Address`, `Ipv6Address`, and
99
`MacAddress` to streamline the API with `core::net`.
10+
- 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`
1019

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

uefi-raw/src/net.rs

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ use core::fmt;
1212
use core::fmt::{Debug, Formatter};
1313

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

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

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

166+
impl From<core::net::Ipv4Addr> for IpAddress {
167+
fn from(value: core::net::Ipv4Addr) -> Self {
168+
Self::new_v4(value.octets())
169+
}
170+
}
171+
172+
impl From<core::net::Ipv6Addr> for IpAddress {
173+
fn from(value: core::net::Ipv6Addr) -> Self {
174+
Self::new_v6(value.octets())
175+
}
176+
}
177+
178+
impl From<[u8; 4]> for IpAddress {
179+
fn from(octets: [u8; 4]) -> Self {
180+
Self::new_v4(octets)
181+
}
182+
}
183+
184+
impl From<[u8; 16]> for IpAddress {
185+
fn from(octets: [u8; 16]) -> Self {
186+
Self::new_v6(octets)
187+
}
188+
}
189+
131190
/// UEFI Media Access Control (MAC) address.
132191
///
133192
/// UEFI supports multiple network protocols and hardware types, not just
@@ -137,6 +196,13 @@ impl From<core::net::IpAddr> for IpAddress {
137196
///
138197
/// In most cases, this is just a typical `[u8; 6]` Ethernet style MAC
139198
/// address with the rest of the bytes being zero.
199+
///
200+
/// # Conversions and Relation to [`core::net`]
201+
///
202+
/// There is no matching type in [`core::net`] but the following [`From`]
203+
/// implementations exist:
204+
/// - `[u8; 6]` <-> [`MacAddress`]
205+
/// - `[u8; 32]` -> [`MacAddress`]
140206
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
141207
#[repr(transparent)]
142208
pub struct MacAddress(pub [u8; 32]);
@@ -149,7 +215,7 @@ impl MacAddress {
149215
}
150216
}
151217

152-
// Normal/typical MAC addresses, such as in Ethernet.
218+
// Normal Ethernet MAC address.
153219
impl From<[u8; 6]> for MacAddress {
154220
fn from(octets: [u8; 6]) -> Self {
155221
let mut buffer = [0; 32];
@@ -158,12 +224,20 @@ impl From<[u8; 6]> for MacAddress {
158224
}
159225
}
160226

227+
// Normal Ethernet MAC address.
161228
impl From<MacAddress> for [u8; 6] {
162229
fn from(MacAddress(o): MacAddress) -> Self {
163230
[o[0], o[1], o[2], o[3], o[4], o[5]]
164231
}
165232
}
166233

234+
// UEFI MAC addresses.
235+
impl From<[u8; 32]> for MacAddress {
236+
fn from(octets: [u8; 32]) -> Self {
237+
Self(octets)
238+
}
239+
}
240+
167241
#[cfg(test)]
168242
mod tests {
169243
use super::*;
@@ -216,4 +290,64 @@ mod tests {
216290
assert_eq!(align_of::<PackedHelper<IpAddress>>(), 1);
217291
assert_eq!(size_of::<PackedHelper<IpAddress>>(), 16);
218292
}
293+
294+
/// Tests the From-impls from the documentation.
295+
#[test]
296+
fn test_promised_from_impls() {
297+
// octets -> Ipv4Address
298+
{
299+
let octets = [0_u8, 1, 2, 3];
300+
assert_eq!(Ipv4Address::from(octets), Ipv4Address(octets));
301+
let uefi_addr = IpAddress::from(octets);
302+
assert_eq!(&octets, &unsafe { uefi_addr.v4.octets() });
303+
}
304+
// octets -> Ipv6Address
305+
{
306+
let octets = [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
307+
assert_eq!(Ipv6Address::from(octets), Ipv6Address(octets));
308+
let uefi_addr = IpAddress::from(octets);
309+
assert_eq!(&octets, &unsafe { uefi_addr.v6.octets() });
310+
}
311+
// StdIpv4Addr -> Ipv4Address
312+
{
313+
let octets = [7, 5, 3, 1];
314+
let core_ipv4_addr = core::net::Ipv4Addr::from(octets);
315+
assert_eq!(Ipv4Address::from(core_ipv4_addr).octets(), octets);
316+
assert_eq!(
317+
unsafe { IpAddress::from(core_ipv4_addr).v4.octets() },
318+
octets
319+
);
320+
}
321+
// StdIpv6Addr -> Ipv6Address
322+
{
323+
let octets = [7, 5, 3, 1, 6, 3, 8, 5, 2, 5, 2, 7, 3, 5, 2, 6];
324+
let core_ipv6_addr = core::net::Ipv6Addr::from(octets);
325+
assert_eq!(Ipv6Address::from(core_ipv6_addr).octets(), octets);
326+
assert_eq!(
327+
unsafe { IpAddress::from(core_ipv6_addr).v6.octets() },
328+
octets
329+
);
330+
}
331+
// StdIpAddr -> IpAddress
332+
{
333+
let octets = [8, 8, 2, 6];
334+
let core_ip_addr = core::net::IpAddr::from(octets);
335+
assert_eq!(unsafe { IpAddress::from(core_ip_addr).v4.octets() }, octets);
336+
}
337+
// octets -> MacAddress
338+
{
339+
let octets = [8, 8, 2, 6, 6, 7];
340+
let uefi_mac_addr = MacAddress::from(octets);
341+
assert_eq!(uefi_mac_addr.octets()[0..6], octets);
342+
}
343+
// octets -> MacAddress
344+
{
345+
let octets = [
346+
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,
347+
0, 0, 0, 0, 42,
348+
];
349+
let uefi_mac_addr = MacAddress::from(octets);
350+
assert_eq!(uefi_mac_addr.octets(), octets);
351+
}
352+
}
219353
}

0 commit comments

Comments
 (0)