pub type Result<T = ()> = core::result::Result<T, alloc::boxed::Box<dyn core::error::Error>>;
pub fn take_errno() -> i32 {
let err = unsafe { *pros_sys::__errno() };
if err != 0 {
unsafe { *pros_sys::__errno() = 0 };
}
err
}
#[macro_export]
macro_rules! map_errno {
{
$err_ty:ty { $($errno:pat => $err:expr),*$(,)? }
$(inherit $base:ty;)?
} => {
impl $crate::error::FromErrno for $err_ty {
fn from_errno(num: i32) -> Option<Self> {
#[allow(unused_imports)]
use pros_sys::error::*;
$(
if let Some(err) = <$base as $crate::error::FromErrno>::from_errno(num) {
return Some(err.into());
}
)?
match num {
$($errno => Some($err),)*
0 => panic!("Expected error state in errno, found 0."),
_ => None,
}
}
}
}
}
#[macro_export]
macro_rules! bail_errno {
() => {{
let errno = $crate::error::take_errno();
if errno != 0 {
let err = $crate::error::FromErrno::from_errno(errno)
.unwrap_or_else(|| panic!("Unknown errno code {errno}"));
return Err(err);
}
}};
}
#[macro_export]
macro_rules! bail_on {
($err_state:expr, $val:expr) => {{
let val = $val;
#[allow(clippy::cmp_null)]
if val == $err_state {
let errno = $crate::error::take_errno();
let err = $crate::error::FromErrno::from_errno(errno)
.unwrap_or_else(|| panic!("Unknown errno code {errno}"));
return Err(err); }
val
}};
}
use snafu::Snafu;
pub trait FromErrno {
fn from_errno(num: i32) -> Option<Self>
where
Self: Sized;
}
#[derive(Debug, Snafu)]
pub enum PortError {
PortOutOfRange,
PortCannotBeConfigured,
AlreadyInUse,
}
map_errno!(PortError {
ENXIO => Self::PortOutOfRange,
ENODEV => Self::PortCannotBeConfigured,
EADDRINUSE => Self::AlreadyInUse,
});