use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ErrorCode {
pub origin: Origin,
pub kind: Kind,
pub extra: i32,
}
impl ErrorCode {
#[cold]
pub fn new(origin: Origin, kind: Kind) -> Self {
Self {
origin,
kind,
extra: 0,
}
}
#[cold]
pub fn new_with_extra(origin: Origin, kind: Kind, extra: i32) -> Self {
Self {
origin,
kind,
extra,
}
}
#[cold]
pub fn unknown() -> Self {
Self {
origin: Origin::Unknown,
kind: Kind::Unknown,
extra: 0,
}
}
#[must_use]
pub fn update_unknown(
mut self,
o: impl Into<Option<Origin>>,
k: impl Into<Option<Kind>>,
) -> Self {
if let (Origin::Unknown, Some(o)) = (self.origin, o.into()) {
self.origin = o;
}
if let (Kind::Unknown, Some(k)) = (self.kind, k.into()) {
self.kind = k;
}
self
}
}
#[repr(u8)]
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Serialize, Deserialize)]
pub enum Origin {
Unknown = 0,
Application = 1,
Vault = 2,
Transport = 3,
Node = 4,
Api = 5,
Identity = 6,
Channel = 7,
KeyExchange = 8,
Executor = 9,
Core = 10,
Ockam = 11,
Authorization = 12,
Other = 13,
}
#[repr(u8)]
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Kind {
Unknown = 0,
Internal = 1,
Invalid = 2,
Unsupported = 3,
NotFound = 4,
AlreadyExists = 5,
ResourceExhausted = 6,
Misuse = 7,
Cancelled = 8,
Shutdown = 9,
Timeout = 10,
Conflict = 11,
Serialization = 12,
Parse = 13,
Io = 14,
Protocol = 15,
Other = 16,
NotReady = 17,
}
macro_rules! from_prim {
($prim:expr, $typ:tt => $Enum:ident { $($Variant:ident),* $(,)? }) => {{
const _: fn(e: $Enum) = |e: $Enum| match e {
$($Enum::$Variant => ()),*
};
match $prim {
$(v if v == ($Enum::$Variant as $typ) => Some($Enum::$Variant),)*
_ => None,
}
}};
}
impl Origin {
#[track_caller]
pub fn from_u8(n: u8) -> Option<Self> {
from_prim!(n, u8 => Origin {
Unknown,
Application,
Vault,
Transport,
Node,
Api,
Identity,
Channel,
KeyExchange,
Executor,
Core,
Ockam,
Authorization,
Other,
})
}
}
impl From<u8> for Origin {
#[track_caller]
fn from(src: u8) -> Self {
match Self::from_u8(src) {
Some(n) => n,
None => {
warn!("Unknown error origin: {}", src);
Self::Unknown
}
}
}
}
impl Kind {
pub fn from_u8(n: u8) -> Option<Self> {
from_prim!(n, u8 => Kind {
Unknown,
Internal,
Invalid,
Unsupported,
NotFound,
AlreadyExists,
ResourceExhausted,
Misuse,
Cancelled,
Shutdown,
Timeout,
Conflict,
Io,
Protocol,
Serialization,
Other,
Parse,
NotReady
})
}
}
impl From<u8> for Kind {
#[track_caller]
fn from(src: u8) -> Self {
match Self::from_u8(src) {
Some(n) => n,
None => {
warn!("Unknown error origin: {}", src);
Self::Unknown
}
}
}
}
impl core::fmt::Display for ErrorCode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "origin: {:?}, kind: {:?}", self.origin, self.kind,)?;
if self.extra != 0 {
write!(f, ", code = {}", self.extra)?
};
Ok(())
}
}