1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
use crate::panic_or_trap;
use core::fmt::{Display, Formatter};
/// The errors that a system call can return.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Error {
CborDecode,
BufferTooShort,
NoSuchComponent,
NoSuchMethod,
BadParameters,
QueueFull,
QueueEmpty,
BadDescriptor,
TooManyDescriptors,
Other,
Unknown,
}
impl Error {
/// Returns a string describing the error.
#[must_use = "This function is only useful for its return value"]
pub fn as_str(self) -> &'static str {
match self {
Self::CborDecode => "CBOR decode error",
Self::BufferTooShort => "Buffer too short",
Self::NoSuchComponent => "No such component",
Self::NoSuchMethod => "No such method",
Self::BadParameters => "Bad parameters",
Self::QueueFull => "Queue full",
Self::QueueEmpty => "Queue empty",
Self::BadDescriptor => "Bad descriptor",
Self::TooManyDescriptors => "Too many descriptors",
Self::Other => "Other error",
Self::Unknown => "Unknown error",
}
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.write_str(self.as_str())
}
}
impl Error {
/// Checks a system call return value of type `isize` for an error value.
///
/// Returns a `Result` containing an `Error` if the value is negative, or the original value if
/// it was nonnegative.
///
/// # Errors
/// This function fails if the parameter is negative, decoding the represented error code.
///
/// # Panics
/// This function panics if the syscall error code is `MemoryFault` or `StringDecode`. These
/// syscall errors should be impossible in safe code because the type system prohibits them:
/// `MemoryFault` should be impossible because all memory regions are taken as slices which are
/// always valid, and `StringDecode` should be impossible because all strings are taken as
/// string-slices (`&str`) which are always valid UTF-8.
pub fn from_isize(value: isize) -> Result<usize> {
match value {
-1 => panic_or_trap!("Memory fault"), // Impossible due to memory safety
-2 => Err(Self::CborDecode),
-3 => panic_or_trap!("String decode error"), // Impossible due to type safety of &str
-4 => Err(Self::BufferTooShort),
-5 => Err(Self::NoSuchComponent),
-6 => Err(Self::NoSuchMethod),
-7 => Err(Self::BadParameters),
-8 => Err(Self::QueueFull),
-9 => Err(Self::QueueEmpty),
-10 => Err(Self::BadDescriptor),
-11 => Err(Self::TooManyDescriptors),
-12 => Err(Self::Other),
x if x < 0 => Err(Self::Unknown),
_ => {
// Cast from isize to usize is safe because the match arm verifies that x ≥ 0.
#[allow(clippy::cast_sign_loss)]
Ok(value as usize)
}
}
}
/// Checks a system call return value of type `i32` for an error value.
///
/// Returns a `Result` containing an `Error` if the value is negative, or the original value if
/// it was nonnegative.
///
/// # Errors
/// This function fails if the parameter is negative, decoding the represented error code.
///
/// # Panics
/// This function panics if the syscall error code is `MemoryFault` or `StringDecode`. These
/// syscall errors should be impossible in safe code because the type system prohibits them:
/// `MemoryFault` should be impossible because all memory regions are taken as slices which are
/// always valid, and `StringDecode` should be impossible because all strings are taken as
/// string-slices (`&str`) which are always valid UTF-8.
pub fn from_i32(value: i32) -> Result<u32> {
// Cast from i32 to isize is safe because Wasm is a 32-bit target (or more), so isize is at
// least 32 bits. Cast from usize back to u32 is safe because the value was originally an
// i32, and from_isize returns an unsigned value.
#[allow(clippy::cast_possible_truncation)]
Ok(Self::from_isize(value as isize)? as u32)
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
pub type Result<T> = core::result::Result<T, Error>;