Skip to main content

rpc_runtime_errors/
lib.rs

1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3
4pub type RpcResult<T> = Result<T, RuntimeError>;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[repr(i32)]
8pub enum RuntimeErrorCode {
9    UnknownMessageKind = 1001,
10    UnsupportedProtocolVersion = 1002,
11    InvalidEnvelope = 1003,
12    InvalidRequestId = 1004,
13    InvalidInstanceId = 1005,
14    InstanceNotFound = 1006,
15    MethodNotFound = 1007,
16    NotificationNotFound = 1008,
17    PayloadDecodeFailed = 1009,
18    PayloadEncodeFailed = 1010,
19    ServiceActivationNotSupported = 1011,
20    ServiceGuidNotFound = 1012,
21    InstanceReleaseNotAllowed = 1013,
22    RequestTimeout = 1014,
23    UnsupportedCapability = 1015,
24    BusinessErrorDeclared = 1016,
25    DuplicateRequestId = 1017,
26    RequestCancelUnsupported = 1018,
27    AccessDenied = 1019,
28    InternalRuntimeError = 1020,
29}
30
31impl RuntimeErrorCode {
32    pub const fn as_i32(self) -> i32 {
33        self as i32
34    }
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
38#[repr(u8)]
39pub enum ErrorKind {
40    Transport = 1,
41    Protocol = 2,
42    Runtime = 3,
43    Business = 4,
44    Timeout = 5,
45    Cancelled = 6,
46}
47
48impl ErrorKind {
49    pub const fn as_u8(self) -> u8 {
50        self as u8
51    }
52}
53
54#[derive(Debug, Clone, PartialEq, Eq, Error, Serialize, Deserialize)]
55#[error("{kind:?} error {code:?}: {message}")]
56pub struct RuntimeError {
57    pub code: RuntimeErrorCode,
58    pub kind: ErrorKind,
59    pub message: String,
60}
61
62impl RuntimeError {
63    pub fn new(code: RuntimeErrorCode, kind: ErrorKind, message: impl Into<String>) -> Self {
64        Self {
65            code,
66            kind,
67            message: message.into(),
68        }
69    }
70
71    pub fn protocol(code: RuntimeErrorCode, message: impl Into<String>) -> Self {
72        Self::new(code, ErrorKind::Protocol, message)
73    }
74
75    pub fn transport(code: RuntimeErrorCode, message: impl Into<String>) -> Self {
76        Self::new(code, ErrorKind::Transport, message)
77    }
78
79    pub fn runtime(code: RuntimeErrorCode, message: impl Into<String>) -> Self {
80        Self::new(code, ErrorKind::Runtime, message)
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn runtime_error_code_values_are_stable() {
90        assert_eq!(RuntimeErrorCode::UnknownMessageKind.as_i32(), 1001);
91        assert_eq!(RuntimeErrorCode::UnsupportedProtocolVersion.as_i32(), 1002);
92        assert_eq!(RuntimeErrorCode::InvalidEnvelope.as_i32(), 1003);
93        assert_eq!(RuntimeErrorCode::InvalidRequestId.as_i32(), 1004);
94        assert_eq!(RuntimeErrorCode::InvalidInstanceId.as_i32(), 1005);
95        assert_eq!(RuntimeErrorCode::InstanceNotFound.as_i32(), 1006);
96        assert_eq!(RuntimeErrorCode::MethodNotFound.as_i32(), 1007);
97        assert_eq!(RuntimeErrorCode::NotificationNotFound.as_i32(), 1008);
98        assert_eq!(RuntimeErrorCode::PayloadDecodeFailed.as_i32(), 1009);
99        assert_eq!(RuntimeErrorCode::PayloadEncodeFailed.as_i32(), 1010);
100        assert_eq!(
101            RuntimeErrorCode::ServiceActivationNotSupported.as_i32(),
102            1011
103        );
104        assert_eq!(RuntimeErrorCode::ServiceGuidNotFound.as_i32(), 1012);
105        assert_eq!(RuntimeErrorCode::InstanceReleaseNotAllowed.as_i32(), 1013);
106        assert_eq!(RuntimeErrorCode::RequestTimeout.as_i32(), 1014);
107        assert_eq!(RuntimeErrorCode::UnsupportedCapability.as_i32(), 1015);
108        assert_eq!(RuntimeErrorCode::BusinessErrorDeclared.as_i32(), 1016);
109        assert_eq!(RuntimeErrorCode::DuplicateRequestId.as_i32(), 1017);
110        assert_eq!(RuntimeErrorCode::RequestCancelUnsupported.as_i32(), 1018);
111        assert_eq!(RuntimeErrorCode::AccessDenied.as_i32(), 1019);
112        assert_eq!(RuntimeErrorCode::InternalRuntimeError.as_i32(), 1020);
113    }
114
115    #[test]
116    fn error_kind_values_are_stable() {
117        assert_eq!(ErrorKind::Transport.as_u8(), 1);
118        assert_eq!(ErrorKind::Protocol.as_u8(), 2);
119        assert_eq!(ErrorKind::Runtime.as_u8(), 3);
120        assert_eq!(ErrorKind::Business.as_u8(), 4);
121        assert_eq!(ErrorKind::Timeout.as_u8(), 5);
122        assert_eq!(ErrorKind::Cancelled.as_u8(), 6);
123    }
124}