Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error enhancements #128

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ embedded-hal-0-2 = { package = "embedded-hal", version = "0.2.4", features = ["u
embedded-hal = "1"
switch-hal = "0.4.0"
nb = "0.1.1"
riot-sys = "0.7.13"
riot-sys = "0.7.14"
num-traits = { version = "0.2", default-features = false }
mutex-trait = "0.2"

Expand Down
2 changes: 2 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ fn main() {
"sock_aux_local",
"sock_tcp",
"sock_udp",
"tiny_strerror",
"tiny_strerror_minimal",
"udp",
"vfs",
"ws281x",
Expand Down
60 changes: 47 additions & 13 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//! Common error handling components for the RIOT operating system
//!
//! Most fallible operations in the wrappers produce a [NumericError], which is a slightly more
//! precise wrapper around a negative integer. The [NegativeErrorExt::negative_to_error()] trait
//! method can be used to produce such errors when creating wrappers around C functions.
//!
//! ## Constants
//!
//! Several commonly used errors are provided as constants rather than requiring the use of
Expand All @@ -8,6 +12,8 @@
//! the list).

use core::convert::TryInto;
use core::ffi::CStr;
use core::num::NonZero;

pub trait NegativeErrorExt {
type Out;
Expand All @@ -25,7 +31,9 @@ pub trait NegativeErrorExt {
/// manually implemented newtype around isize that'd be used to represent the Result.
#[derive(Debug, PartialEq, Eq)]
pub struct NumericError {
number: isize,
// The NonZero doesn't cover the full desired range, but at least Result<(), NumericError> can
// be lean.
number: NonZero<isize>,
}

impl NumericError {
Expand Down Expand Up @@ -55,12 +63,17 @@ impl NumericError {
name > 0,
"Error names are expected to be positive for conversion into negative error numbers."
);
NumericError { number: -name }
// Can be an `.unwrap()` once feature(const_trait_impl) is stabilized
let number = match NonZero::new(name) {
Some(n) => n,
_ => panic!("Error names are expected to be positive for conversion into negative error numbers.")
};
NumericError { number }
}

/// Numeric value of the error
pub const fn number(&self) -> isize {
self.number
self.number.get()
}

/// Convert the error into an [nb::Error] that is [nb::Error::WouldBlock] if the error is
Expand All @@ -71,15 +84,33 @@ impl NumericError {
}
nb::Error::Other(self)
}

fn string(&self) -> Option<&'static CStr> {
#[cfg(all(riot_module_tiny_strerror, not(riot_module_tiny_strerror_minimal)))]
// unsafe: According to C API
// number cast: Disagreements on the numeric error size
// string cast: Disagreements on the signedness of char
return Some(unsafe {
CStr::from_ptr(riot_sys::tiny_strerror(-self.number.get() as _) as _)
});

#[cfg(not(all(riot_module_tiny_strerror, not(riot_module_tiny_strerror_minimal))))]
return None;
}
}

impl core::fmt::Display for NumericError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
if let Some(s) = self.string() {
write!(f, "Error {} ({})", self.number(), s.to_str().unwrap())?;
} else {
write!(f, "Error {}", self.number())?;
}
Ok(())
}
}

// Would be nice, but there's no strerror
//
// impl core::fmt::Display for NumericError {
// fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
// write!(f, "Error {} ({})", self.number(), ...)
// }
// }
impl core::error::Error for NumericError {}

impl<T> NegativeErrorExt for T
where
Expand All @@ -91,9 +122,12 @@ where
if self >= Self::zero() {
Ok(self)
} else {
Err(NumericError {
number: self.try_into().unwrap_or(-(riot_sys::EOVERFLOW as isize)),
})
Err(self
.try_into()
.ok()
.and_then(NonZero::new)
.map(|number| NumericError { number })
.unwrap_or(EOVERFLOW))
}
}
}
Expand Down
Loading