use std::fmt;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
UnknownCapability(u128),
MethodNotGranted {
method: String,
},
Escalation(&'static str),
ReadOnly,
PathNotGranted(String),
ToolPolicy(&'static str),
Revoked(u128),
BudgetExceeded(&'static str),
UnknownLane(u64),
UnknownChannel(u64),
UnknownPromise(u64),
PromiseCancelled(u64),
PromiseAlreadyResolved(u64),
UnresolvablePromise(u64),
Provider {
code: String,
},
Domain(&'static str),
Payload(String),
Wire(&'static str),
CapabilityTable(&'static str),
Transport(String),
TransportUnavailable(&'static str),
Timeout,
PipelinedCycle,
InvalidArgument(&'static str),
}
impl Error {
pub const fn code(&self) -> &'static str {
match self {
Error::UnknownCapability(_) => "rpc/unknown-capability",
Error::MethodNotGranted { .. } => "rpc/method-not-granted",
Error::Escalation(_) => "rpc/attenuation-escalation",
Error::ReadOnly => "rpc/read-only",
Error::PathNotGranted(_) => "rpc/path-not-granted",
Error::ToolPolicy(_) => "rpc/tool-policy",
Error::Revoked(_) => "rpc/revoked",
Error::BudgetExceeded(_) => "rpc/budget-exceeded",
Error::UnknownLane(_) => "rpc/unknown-lane",
Error::UnknownChannel(_) => "rpc/unknown-channel",
Error::UnknownPromise(_) => "rpc/unknown-promise",
Error::PromiseCancelled(_) => "rpc/promise-cancelled",
Error::PromiseAlreadyResolved(_) => "rpc/promise-resolved",
Error::UnresolvablePromise(_) => "rpc/unresolvable-promise",
Error::Provider { .. } => "rpc/provider",
Error::Domain(_) => "rpc/domain",
Error::Payload(_) => "rpc/payload",
Error::Wire(_) => "rpc/wire",
Error::CapabilityTable(_) => "rpc/capability-table",
Error::Transport(_) => "rpc/transport",
Error::TransportUnavailable(_) => "rpc/transport-unavailable",
Error::Timeout => "rpc/timeout",
Error::PipelinedCycle => "rpc/pipelined-cycle",
Error::InvalidArgument(_) => "rpc/invalid-argument",
}
}
pub const fn is_fatal(&self) -> bool {
matches!(
self,
Error::Wire(_)
| Error::CapabilityTable(_)
| Error::Payload(_)
| Error::UnknownCapability(_)
)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::UnknownCapability(id) => write!(f, "unknown capability {id:032x}"),
Error::MethodNotGranted { method } => write!(f, "method {method} is not granted"),
Error::Escalation(what) => write!(f, "attenuation would widen authority: {what}"),
Error::ReadOnly => write!(f, "capability is read-only"),
Error::PathNotGranted(path) => write!(f, "path {path} is outside the capability"),
Error::ToolPolicy(what) => write!(f, "tool policy rejects the call: {what}"),
Error::Revoked(id) => write!(f, "capability {id:032x} is revoked"),
Error::BudgetExceeded(kind) => write!(f, "{kind} budget exhausted"),
Error::UnknownLane(id) => write!(f, "unknown lane {id}"),
Error::UnknownChannel(id) => write!(f, "unknown channel {id}"),
Error::UnknownPromise(id) => write!(f, "unknown promise {id}"),
Error::PromiseCancelled(id) => write!(f, "promise {id} was cancelled"),
Error::PromiseAlreadyResolved(id) => write!(f, "promise {id} was already resolved"),
Error::UnresolvablePromise(id) => write!(f, "promise {id} can never resolve"),
Error::Provider { code } => write!(f, "provider failed: {code}"),
Error::Domain(code) => write!(f, "domain operation failed: {code}"),
Error::Payload(reason) => write!(f, "invalid payload: {reason}"),
Error::Wire(reason) => write!(f, "malformed envelope: {reason}"),
Error::CapabilityTable(reason) => write!(f, "malformed capability table: {reason}"),
Error::Transport(reason) => write!(f, "transport failure: {reason}"),
Error::TransportUnavailable(name) => write!(f, "transport {name} is unavailable"),
Error::Timeout => write!(f, "deadline elapsed"),
Error::PipelinedCycle => write!(f, "pipelined calls form a cycle"),
Error::InvalidArgument(what) => write!(f, "invalid argument: {what}"),
}
}
}
impl std::error::Error for Error {}
impl From<active_infinity::Error> for Error {
fn from(error: active_infinity::Error) -> Self {
Error::Payload(error.code().to_string())
}
}