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 5f59b8a

Browse files
committed
uefi-raw
1 parent 5a30e29 commit 5f59b8a

File tree

1 file changed

+70
-13
lines changed

1 file changed

+70
-13
lines changed

‎uefi-raw/src/lib.rs

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ impl From<Boolean> for bool {
113113
/// type is defined in the same way as edk2 for compatibility with C code. Note
114114
/// that this is an **untagged union**, so there's no way to tell which type of
115115
/// address an `IpAddress` value contains without additional context.
116+
///
117+
/// For convenience, this type is tightly integrated with the Rust standard
118+
/// library types [`IpAddr`], [`Ipv4Addr`], and [`IpV6Addr`].
116119
#[derive(Clone, Copy)]
117120
#[repr(C)]
118121
pub union IpAddress {
@@ -162,14 +165,48 @@ impl IpAddress {
162165
pub fn as_ptr_mut(&mut self) -> *mut Self {
163166
core::ptr::addr_of_mut!(*self)
164167
}
168+
169+
/// Transforms this EFI type to the Rust standard libraries type.
170+
///
171+
/// # Arguments
172+
/// - `is_ipv6`: Whether the internal data should be interpreted as IPv6 or
173+
/// IPv4 address.
174+
pub fn to_ip_addr(self, is_ipv6: bool) -> IpAddr {
175+
if is_ipv6 {
176+
IpAddr::V6(Ipv6Addr::from(unsafe { self.v6.octets() }))
177+
} else {
178+
IpAddr::V4(Ipv4Addr::from(unsafe { self.v4.octets() }))
179+
}
180+
}
181+
182+
/// Returns the underlying data as [`Ipv4Addr`], if only the first four
183+
/// octets are used.
184+
///
185+
/// # Safety
186+
/// This function is not unsafe memory-wise but callers need to ensure with
187+
/// additional context that the IP is indeed an IPv4 address.
188+
pub unsafe fn as_ipv4(&self) -> Result<Ipv4Addr, Ipv6Addr> {
189+
let extra = self.octets()[4..].iter().any(|&x| x != 0);
190+
if extra {
191+
Ok(Ipv4Addr::from(unsafe { self.v4.octets() }))
192+
} else {
193+
Err(Ipv6Addr::from(unsafe { self.v6.octets() }))
194+
}
195+
}
196+
197+
/// Returns the underlying data as [`Ipv6Addr`].
198+
///
199+
/// # Safety
200+
/// This function is not unsafe memory-wise but callers need to ensure with
201+
/// additional context that the IP is indeed an IPv6 address.
202+
pub unsafe fn as_ipv6(&self) -> Ipv6Addr {
203+
Ipv6Addr::from(unsafe { self.v6.octets() })
204+
}
165205
}
166206

167207
impl Debug for IpAddress {
168208
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
169-
// The type is an untagged union, so we don't know whether it contains
170-
// an IPv4 or IPv6 address. It's also not safe to just print the whole
171-
// 16 bytes, since they might not all be initialized.
172-
f.debug_struct("IpAddress").finish()
209+
f.debug_tuple("IpAddress").field(&self.octets()).finish()
173210
}
174211
}
175212

@@ -207,6 +244,14 @@ impl From<&IpAddr> for IpAddress {
207244
}
208245
}
209246

247+
impl From<[u8; 4]> for IpAddress {
248+
fn from(value: [u8; 4]) -> Self {
249+
Self {
250+
v4: Ipv4Addr::from(value),
251+
}
252+
}
253+
}
254+
210255
impl From<[u8; 16]> for IpAddress {
211256
fn from(value: [u8; 16]) -> Self {
212257
Self {
@@ -299,17 +344,29 @@ mod tests {
299344
unsafe { assert_eq!(ip.v4.octets(), [192, 168, 42, 73]) }
300345
}
301346

302-
/// Test conversion from `core::net::IpAddr` to `IpvAddress`.
303-
///
304-
/// Note that conversion in the other direction is not possible.
347+
/// Test conversion from [`IpAddr`] to [`IpAddress`].
305348
#[test]
306349
fn test_ip_addr_conversion() {
307-
let core_addr = IpAddr::V4(Ipv4Addr::from(TEST_IPV4));
308-
let uefi_addr = IpAddress::from(core_addr);
309-
assert_eq!(unsafe { uefi_addr.v4.octets() }, TEST_IPV4);
350+
// Reference: std types
351+
let core_ipv4 = IpAddr::from(TEST_IPV4);
352+
let core_ipv6 = IpAddr::from(TEST_IPV6);
353+
354+
// Test From [u8; N] constructors
355+
assert_eq!(IpAddress::from(TEST_IPV4).octets()[0..4], TEST_IPV4);
356+
assert_eq!(IpAddress::from(TEST_IPV6).octets(), TEST_IPV6);
357+
{
358+
let bytes: [u8; 16] = IpAddress::from(TEST_IPV6).into();
359+
assert_eq!(bytes, TEST_IPV6);
360+
}
361+
362+
// Test from std type constructors
363+
let efi_ipv4 = IpAddress::from(core_ipv4);
364+
assert_eq!(efi_ipv4.octets()[0..4], TEST_IPV4);
365+
assert_eq!(unsafe { efi_ipv4.as_ipv4().unwrap() }, core_ipv4);
310366

311-
let core_addr = IpAddr::V6(Ipv6Addr::from(TEST_IPV6));
312-
let uefi_addr = IpAddress::from(core_addr);
313-
assert_eq!(unsafe { uefi_addr.v6.octets() }, TEST_IPV6);
367+
let efi_ipv6 = IpAddress::from(core_ipv6);
368+
assert_eq!(efi_ipv6.octets(), TEST_IPV6);
369+
assert_eq!(unsafe { efi_ipv4.as_ipv4().unwrap_err() }, core_ipv6);
370+
assert_eq!(unsafe { efi_ipv4.as_ipv6() }, core_ipv6);
314371
}
315372
}

0 commit comments

Comments
(0)

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