Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b3edd38

Browse files
committed
uefi-raw: add convenient From impls
1 parent 31a08af commit b3edd38

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 {
@@ -162,6 +197,30 @@ impl From<StdIpAddr> for IpAddress {
162197
}
163198
}
164199

200+
impl From<StdIpv4Addr> for IpAddress {
201+
fn from(value: StdIpv4Addr) -> Self {
202+
Self::new_v4(value.octets())
203+
}
204+
}
205+
206+
impl From<StdIpv6Addr> for IpAddress {
207+
fn from(value: StdIpv6Addr) -> Self {
208+
Self::new_v6(value.octets())
209+
}
210+
}
211+
212+
impl From<[u8; 4]> for IpAddress {
213+
fn from(octets: [u8; 4]) -> Self {
214+
Self::new_v4(octets)
215+
}
216+
}
217+
218+
impl From<[u8; 16]> for IpAddress {
219+
fn from(octets: [u8; 16]) -> Self {
220+
Self::new_v6(octets)
221+
}
222+
}
223+
165224
/// UEFI Media Access Control (MAC) address.
166225
///
167226
/// UEFI supports multiple network protocols and hardware types, not just
@@ -171,6 +230,13 @@ impl From<StdIpAddr> for IpAddress {
171230
///
172231
/// In most cases, this is just a typical `[u8; 6]` Ethernet style MAC
173232
/// address with the rest of the bytes being zero.
233+
///
234+
/// # Conversions and Relation to [`core::net`]
235+
///
236+
/// There is no matching type in [`core::net`] but the following [`From`]
237+
/// implementations exist:
238+
/// - `[u8; 6]` -> [`MacAddress`]
239+
/// - `[u8; 32]` -> [`MacAddress`]
174240
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
175241
#[repr(transparent)]
176242
pub struct MacAddress(pub [u8; 32]);
@@ -192,9 +258,10 @@ impl From<[u8; 6]> for MacAddress {
192258
}
193259
}
194260

195-
impl From<MacAddress> for [u8; 6] {
196-
fn from(MacAddress(o): MacAddress) -> Self {
197-
[o[0], o[1], o[2], o[3], o[4], o[5]]
261+
// UEFI MAC addresses.
262+
impl From<[u8; 32]> for MacAddress {
263+
fn from(octets: [u8; 32]) -> Self {
264+
Self(octets)
198265
}
199266
}
200267

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

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /