From 5177253bb6ebb194669d412cd3f90c5209351275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 18 Dec 2024 16:06:42 +0300 Subject: [PATCH 1/3] Allow `Error::raw_os_error` to return non-`i32` codes --- src/error.rs | 46 ++++++++++++++++++++++++++++++------------ src/error_std_impls.rs | 5 ----- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/error.rs b/src/error.rs index 125051ee..629a40bd 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,6 +3,16 @@ extern crate std; use core::{fmt, num::NonZeroU32}; +// This private alias mirrors `std::io::RawOsError`: +// https://doc.rust-lang.org/std/io/type.RawOsError.html) +cfg_if::cfg_if!( + if #[cfg(target_os = "uefi")] { + type RawOsError = usize; + } else { + type RawOsError = i32; + } +); + /// A small and `no_std` compatible error type /// /// The [`Error::raw_os_error()`] will indicate if the error is from the OS, and @@ -57,20 +67,30 @@ impl Error { /// Extract the raw OS error code (if this error came from the OS) /// /// This method is identical to [`std::io::Error::raw_os_error()`][1], except - /// that it works in `no_std` contexts. If this method returns `None`, the - /// error value can still be formatted via the `Display` implementation. + /// that it works in `no_std` contexts. On most targets this method returns + /// `Option`, but some platforms (e.g. UEFI) may use a different primitive + /// type like `usize`. Consult with the [`RawOsError`] docs for more information. + /// + /// If this method returns `None`, the error value can still be formatted via + /// the `Display` implementation. /// /// [1]: https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error + /// [`RawOsError`]: https://doc.rust-lang.org/std/io/type.RawOsError.html #[inline] - pub fn raw_os_error(self) -> Option { - i32::try_from(self.0.get()).ok().map(|errno| { - // On SOLID, negate the error code again to obtain the original error code. - if cfg!(target_os = "solid_asp3") { - -errno - } else { - errno - } - }) + pub fn raw_os_error(self) -> Option { + let code = self.0.get(); + if code < Self::INTERNAL_START { + RawOsError::try_from(code).ok().map(|errno| { + // On SOLID, negate the error code again to obtain the original error code. + if cfg!(target_os = "solid_asp3") { + -errno + } else { + errno + } + }) + } else { + None + } } /// Creates a new instance of an `Error` from a particular custom error code. @@ -134,7 +154,7 @@ impl fmt::Debug for Error { let mut dbg = f.debug_struct("Error"); if let Some(errno) = self.raw_os_error() { dbg.field("os_error", &errno); - #[cfg(all(feature = "std", not(target_os = "uefi")))] + #[cfg(feature = "std")] dbg.field("description", &std::io::Error::from_raw_os_error(errno)); } else if let Some(desc) = self.internal_desc() { dbg.field("internal_code", &self.0.get()); @@ -150,7 +170,7 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(errno) = self.raw_os_error() { cfg_if! { - if #[cfg(all(feature = "std", not(target_os = "uefi")))] { + if #[cfg(feature = "std")] { std::io::Error::from_raw_os_error(errno).fmt(f) } else { write!(f, "OS Error: {}", errno) diff --git a/src/error_std_impls.rs b/src/error_std_impls.rs index 569165e3..2c326012 100644 --- a/src/error_std_impls.rs +++ b/src/error_std_impls.rs @@ -5,15 +5,10 @@ use std::io; impl From for io::Error { fn from(err: Error) -> Self { - #[cfg(not(target_os = "uefi"))] match err.raw_os_error() { Some(errno) => io::Error::from_raw_os_error(errno), None => io::Error::new(io::ErrorKind::Other, err), } - #[cfg(target_os = "uefi")] - { - io::Error::new(io::ErrorKind::Other, err) - } } } From 43f9e6edafb6b65ea77437825e551ba905a31e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 18 Dec 2024 16:19:43 +0300 Subject: [PATCH 2/3] Fix compilation error --- src/error.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/error.rs b/src/error.rs index 629a40bd..7328506f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -80,14 +80,11 @@ impl Error { pub fn raw_os_error(self) -> Option { let code = self.0.get(); if code < Self::INTERNAL_START { - RawOsError::try_from(code).ok().map(|errno| { - // On SOLID, negate the error code again to obtain the original error code. - if cfg!(target_os = "solid_asp3") { - -errno - } else { - errno - } - }) + let res = RawOsError::try_from(code).ok(); + // On SOLID, negate the error code again to obtain the original error code. + #[cfg(target_os = "solid_asp3")] + let res = res.map(|errno| -errno); + res } else { None } From 3e86ef647e48368311dc58954a875e7edadfd4ef Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 19 Dec 2024 00:22:03 +0300 Subject: [PATCH 3/3] Apply review suggestion --- src/error.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/error.rs b/src/error.rs index 7328506f..4004af57 100644 --- a/src/error.rs +++ b/src/error.rs @@ -79,15 +79,13 @@ impl Error { #[inline] pub fn raw_os_error(self) -> Option { let code = self.0.get(); - if code < Self::INTERNAL_START { - let res = RawOsError::try_from(code).ok(); - // On SOLID, negate the error code again to obtain the original error code. - #[cfg(target_os = "solid_asp3")] - let res = res.map(|errno| -errno); - res - } else { - None + if code >= Self::INTERNAL_START { + return None; } + let errno = RawOsError::try_from(code).ok()?; + #[cfg(target_os = "solid_asp3")] + let errno = -errno; + Some(errno) } /// Creates a new instance of an `Error` from a particular custom error code.