|
|
@ -1,4 +1,5 @@ |
|
|
|
use std::error; |
|
|
|
use std::error; |
|
|
|
|
|
|
|
use std::ffi::CStr; |
|
|
|
use std::fmt; |
|
|
|
use std::fmt; |
|
|
|
|
|
|
|
|
|
|
|
use ctru_sys::result::{R_DESCRIPTION, R_LEVEL, R_MODULE, R_SUMMARY}; |
|
|
|
use ctru_sys::result::{R_DESCRIPTION, R_LEVEL, R_MODULE, R_SUMMARY}; |
|
|
@ -9,7 +10,27 @@ pub type Result<T> = ::std::result::Result<T, Error>; |
|
|
|
#[non_exhaustive] |
|
|
|
#[non_exhaustive] |
|
|
|
pub enum Error { |
|
|
|
pub enum Error { |
|
|
|
Os(ctru_sys::Result), |
|
|
|
Os(ctru_sys::Result), |
|
|
|
|
|
|
|
Libc(String), |
|
|
|
ServiceAlreadyActive, |
|
|
|
ServiceAlreadyActive, |
|
|
|
|
|
|
|
OutputAlreadyRedirected, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Error { |
|
|
|
|
|
|
|
/// Create an [`Error`] out of the last set value in `errno`. This can be used
|
|
|
|
|
|
|
|
/// to get a human-readable error string from calls to `libc` functions.
|
|
|
|
|
|
|
|
pub(crate) fn from_errno() -> Self { |
|
|
|
|
|
|
|
let error_str = unsafe { |
|
|
|
|
|
|
|
let errno = ctru_sys::errno(); |
|
|
|
|
|
|
|
let str_ptr = libc::strerror(errno); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Safety: strerror should always return a valid string,
|
|
|
|
|
|
|
|
// even if the error number is unknown
|
|
|
|
|
|
|
|
CStr::from_ptr(str_ptr) |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Copy out of the error string, since it may be changed by other libc calls later
|
|
|
|
|
|
|
|
Self::Libc(error_str.to_string_lossy().into()) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl From<ctru_sys::Result> for Error { |
|
|
|
impl From<ctru_sys::Result> for Error { |
|
|
@ -20,8 +41,8 @@ impl From<ctru_sys::Result> for Error { |
|
|
|
|
|
|
|
|
|
|
|
impl fmt::Debug for Error { |
|
|
|
impl fmt::Debug for Error { |
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
|
|
match *self { |
|
|
|
match self { |
|
|
|
Error::Os(err) => f |
|
|
|
&Self::Os(err) => f |
|
|
|
.debug_struct("Error") |
|
|
|
.debug_struct("Error") |
|
|
|
.field("raw", &format_args!("{:#08X}", err)) |
|
|
|
.field("raw", &format_args!("{:#08X}", err)) |
|
|
|
.field("description", &R_DESCRIPTION(err)) |
|
|
|
.field("description", &R_DESCRIPTION(err)) |
|
|
@ -29,7 +50,9 @@ impl fmt::Debug for Error { |
|
|
|
.field("summary", &R_SUMMARY(err)) |
|
|
|
.field("summary", &R_SUMMARY(err)) |
|
|
|
.field("level", &R_LEVEL(err)) |
|
|
|
.field("level", &R_LEVEL(err)) |
|
|
|
.finish(), |
|
|
|
.finish(), |
|
|
|
Error::ServiceAlreadyActive => f.debug_tuple("ServiceAlreadyActive").finish(), |
|
|
|
Self::Libc(err) => f.debug_tuple("Libc").field(err).finish(), |
|
|
|
|
|
|
|
Self::ServiceAlreadyActive => f.debug_tuple("ServiceAlreadyActive").finish(), |
|
|
|
|
|
|
|
Self::OutputAlreadyRedirected => f.debug_tuple("OutputAlreadyRedirected").finish(), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -39,9 +62,13 @@ impl fmt::Debug for Error { |
|
|
|
// https://github.com/devkitPro/libctru/blob/master/libctru/include/3ds/result.h
|
|
|
|
// https://github.com/devkitPro/libctru/blob/master/libctru/include/3ds/result.h
|
|
|
|
impl fmt::Display for Error { |
|
|
|
impl fmt::Display for Error { |
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
|
|
match *self { |
|
|
|
match self { |
|
|
|
Error::Os(err) => write!(f, "libctru result code: 0x{:08X}", err), |
|
|
|
&Self::Os(err) => write!(f, "libctru result code: 0x{:08X}", err), |
|
|
|
Error::ServiceAlreadyActive => write!(f, "Service already active"), |
|
|
|
Self::Libc(err) => write!(f, "{}", err), |
|
|
|
|
|
|
|
Self::ServiceAlreadyActive => write!(f, "Service already active"), |
|
|
|
|
|
|
|
Self::OutputAlreadyRedirected => { |
|
|
|
|
|
|
|
write!(f, "output streams are already redirected to 3dslink") |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|