use alloc::boxed::Box; use crate::{header::errno::STR_ERROR, platform::types::c_int}; /// Positive error codes (EINVAL, not -EINVAL). #[derive(Debug, Eq, PartialEq)] // TODO: Move to a more generic place. pub struct Errno(pub c_int); impl Errno { pub fn sync(self) -> Self { crate::platform::ERRNO.set(self.0); self } } pub type Result = core::result::Result; #[cfg(target_os = "redox")] impl From for Errno { #[inline] fn from(value: syscall::Error) -> Self { Errno(value.errno) } } #[cfg(target_os = "redox")] impl From for syscall::Error { #[inline] fn from(value: Errno) -> Self { syscall::Error::new(value.0) } } impl From for crate::io::Error { #[inline] fn from(Errno(errno): Errno) -> Self { Self::from_raw_os_error(errno) } } // TODO: core::error::Error impl core::fmt::Display for Errno { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match usize::try_from(self.0).ok().and_then(|i| STR_ERROR.get(i)) { Some(desc) => write!(f, "{desc}"), None => write!(f, "unknown error ({})", self.0), } } } pub trait ResultExt { fn or_minus_one_errno(self) -> T; } impl> ResultExt for Result { fn or_minus_one_errno(self) -> T { match self { Self::Ok(v) => v, Self::Err(Errno(errno)) => { crate::platform::ERRNO.set(errno); T::from(-1) } } } } pub trait ResultExtPtrMut { fn or_errno_null_mut(self) -> *mut T; } impl ResultExtPtrMut for Result<*mut T, Errno> { fn or_errno_null_mut(self) -> *mut T { match self { Self::Ok(ptr) => ptr, Self::Err(Errno(errno)) => { crate::platform::ERRNO.set(errno); core::ptr::null_mut() } } } } impl ResultExtPtrMut for Result, Errno> { fn or_errno_null_mut(self) -> *mut T { match self { Self::Ok(ptr) => Box::into_raw(ptr), Self::Err(Errno(errno)) => { crate::platform::ERRNO.set(errno); core::ptr::null_mut() } } } }