use core::fmt::{self, Display};
#[cfg(feature = "alloc")]
extern crate alloc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorKind {
NotFound,
PermissionDenied,
ConnectionRefused,
ConnectionReset,
ConnectionAborted,
NotConnected,
AddrInUse,
AddrNotAvailable,
BrokenPipe,
AlreadyExists,
WouldBlock,
InvalidInput,
InvalidData,
TimedOut,
WriteZero,
Interrupted,
UnexpectedEof,
OutOfMemory,
Other,
}
impl Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::NotFound => write!(f, "entity not found"),
ErrorKind::PermissionDenied => write!(f, "permission denied"),
ErrorKind::ConnectionRefused => write!(f, "connection refused"),
ErrorKind::ConnectionReset => write!(f, "connection reset"),
ErrorKind::ConnectionAborted => write!(f, "connection aborted"),
ErrorKind::NotConnected => write!(f, "not connected"),
ErrorKind::AddrInUse => write!(f, "address in use"),
ErrorKind::AddrNotAvailable => write!(f, "address not available"),
ErrorKind::BrokenPipe => write!(f, "broken pipe"),
ErrorKind::AlreadyExists => write!(f, "entity already exists"),
ErrorKind::WouldBlock => write!(f, "operation would block"),
ErrorKind::InvalidInput => write!(f, "invalid input parameter"),
ErrorKind::InvalidData => write!(f, "invalid data"),
ErrorKind::TimedOut => write!(f, "operation timed out"),
ErrorKind::WriteZero => write!(f, "write zero"),
ErrorKind::Interrupted => write!(f, "operation interrupted"),
ErrorKind::UnexpectedEof => write!(f, "unexpected end of file"),
ErrorKind::OutOfMemory => write!(f, "out of memory"),
ErrorKind::Other => write!(f, "other error"),
}
}
}
#[derive(Debug)]
enum ErrorMessage {
Static(&'static str),
#[cfg(feature = "alloc")]
Dynamic(alloc::string::String),
}
impl ErrorMessage {
fn as_str(&self) -> &str {
match self {
ErrorMessage::Static(s) => s,
#[cfg(feature = "alloc")]
ErrorMessage::Dynamic(s) => s.as_str(),
}
}
}
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
msg: ErrorMessage,
}
impl Error {
pub const fn new_static(kind: ErrorKind, msg: &'static str) -> Self {
Self {
kind,
msg: ErrorMessage::Static(msg),
}
}
#[cfg(not(feature = "alloc"))]
pub const fn new(kind: ErrorKind, msg: &'static str) -> Self {
Self::new_static(kind, msg)
}
#[cfg(feature = "alloc")]
pub fn new(kind: ErrorKind, msg: impl Into<alloc::string::String>) -> Self {
Self {
kind,
msg: ErrorMessage::Dynamic(msg.into()),
}
}
pub const fn from_kind(kind: ErrorKind) -> Self {
Self {
kind,
msg: ErrorMessage::Static(""),
}
}
#[cfg(not(feature = "alloc"))]
pub const fn other(msg: &'static str) -> Self {
Self {
kind: ErrorKind::Other,
msg: ErrorMessage::Static(msg),
}
}
#[cfg(feature = "alloc")]
pub fn other(msg: impl Into<alloc::string::String>) -> Self {
Self {
kind: ErrorKind::Other,
msg: ErrorMessage::Dynamic(msg.into()),
}
}
pub const fn kind(&self) -> ErrorKind {
self.kind
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Self {
Self::from_kind(kind)
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let msg = self.msg.as_str();
if msg.is_empty() {
write!(f, "{}", self.kind)
} else {
write!(f, "{}: {}", self.kind, msg)
}
}
}
pub type Result<T> = core::result::Result<T, Error>;