use serde::{Deserialize, Serialize};
use thiserror::Error;
pub type RpcResult<T> = Result<T, RuntimeError>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(i32)]
pub enum RuntimeErrorCode {
UnknownMessageKind = 1001,
UnsupportedProtocolVersion = 1002,
InvalidEnvelope = 1003,
InvalidRequestId = 1004,
InvalidInstanceId = 1005,
InstanceNotFound = 1006,
MethodNotFound = 1007,
NotificationNotFound = 1008,
PayloadDecodeFailed = 1009,
PayloadEncodeFailed = 1010,
ServiceActivationNotSupported = 1011,
ServiceGuidNotFound = 1012,
InstanceReleaseNotAllowed = 1013,
RequestTimeout = 1014,
UnsupportedCapability = 1015,
BusinessErrorDeclared = 1016,
DuplicateRequestId = 1017,
RequestCancelUnsupported = 1018,
AccessDenied = 1019,
InternalRuntimeError = 1020,
}
impl RuntimeErrorCode {
pub const fn as_i32(self) -> i32 {
self as i32
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u8)]
pub enum ErrorKind {
Transport = 1,
Protocol = 2,
Runtime = 3,
Business = 4,
Timeout = 5,
Cancelled = 6,
}
impl ErrorKind {
pub const fn as_u8(self) -> u8 {
self as u8
}
}
#[derive(Debug, Clone, PartialEq, Eq, Error, Serialize, Deserialize)]
#[error("{kind:?} error {code:?}: {message}")]
pub struct RuntimeError {
pub code: RuntimeErrorCode,
pub kind: ErrorKind,
pub message: String,
}
impl RuntimeError {
pub fn new(code: RuntimeErrorCode, kind: ErrorKind, message: impl Into<String>) -> Self {
Self {
code,
kind,
message: message.into(),
}
}
pub fn protocol(code: RuntimeErrorCode, message: impl Into<String>) -> Self {
Self::new(code, ErrorKind::Protocol, message)
}
pub fn transport(code: RuntimeErrorCode, message: impl Into<String>) -> Self {
Self::new(code, ErrorKind::Transport, message)
}
pub fn runtime(code: RuntimeErrorCode, message: impl Into<String>) -> Self {
Self::new(code, ErrorKind::Runtime, message)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn runtime_error_code_values_are_stable() {
assert_eq!(RuntimeErrorCode::UnknownMessageKind.as_i32(), 1001);
assert_eq!(RuntimeErrorCode::UnsupportedProtocolVersion.as_i32(), 1002);
assert_eq!(RuntimeErrorCode::InvalidEnvelope.as_i32(), 1003);
assert_eq!(RuntimeErrorCode::InvalidRequestId.as_i32(), 1004);
assert_eq!(RuntimeErrorCode::InvalidInstanceId.as_i32(), 1005);
assert_eq!(RuntimeErrorCode::InstanceNotFound.as_i32(), 1006);
assert_eq!(RuntimeErrorCode::MethodNotFound.as_i32(), 1007);
assert_eq!(RuntimeErrorCode::NotificationNotFound.as_i32(), 1008);
assert_eq!(RuntimeErrorCode::PayloadDecodeFailed.as_i32(), 1009);
assert_eq!(RuntimeErrorCode::PayloadEncodeFailed.as_i32(), 1010);
assert_eq!(
RuntimeErrorCode::ServiceActivationNotSupported.as_i32(),
1011
);
assert_eq!(RuntimeErrorCode::ServiceGuidNotFound.as_i32(), 1012);
assert_eq!(RuntimeErrorCode::InstanceReleaseNotAllowed.as_i32(), 1013);
assert_eq!(RuntimeErrorCode::RequestTimeout.as_i32(), 1014);
assert_eq!(RuntimeErrorCode::UnsupportedCapability.as_i32(), 1015);
assert_eq!(RuntimeErrorCode::BusinessErrorDeclared.as_i32(), 1016);
assert_eq!(RuntimeErrorCode::DuplicateRequestId.as_i32(), 1017);
assert_eq!(RuntimeErrorCode::RequestCancelUnsupported.as_i32(), 1018);
assert_eq!(RuntimeErrorCode::AccessDenied.as_i32(), 1019);
assert_eq!(RuntimeErrorCode::InternalRuntimeError.as_i32(), 1020);
}
#[test]
fn error_kind_values_are_stable() {
assert_eq!(ErrorKind::Transport.as_u8(), 1);
assert_eq!(ErrorKind::Protocol.as_u8(), 2);
assert_eq!(ErrorKind::Runtime.as_u8(), 3);
assert_eq!(ErrorKind::Business.as_u8(), 4);
assert_eq!(ErrorKind::Timeout.as_u8(), 5);
assert_eq!(ErrorKind::Cancelled.as_u8(), 6);
}
}