1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[repr(u16)]
7pub enum RpcStatus {
8 Ok = 0,
9 Cancelled = 1,
10 InvalidArgument = 2,
11 NotFound = 3,
12 AlreadyExists = 4,
13 PermissionDenied = 5,
14 Unauthenticated = 6,
15 ResourceExhausted = 7,
16 Internal = 8,
17 Unavailable = 9,
18 DeadlineExceeded = 10,
19}
20
21impl fmt::Display for RpcStatus {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 RpcStatus::Ok => write!(f, "OK"),
25 RpcStatus::Cancelled => write!(f, "CANCELLED"),
26 RpcStatus::InvalidArgument => write!(f, "INVALID_ARGUMENT"),
27 RpcStatus::NotFound => write!(f, "NOT_FOUND"),
28 RpcStatus::AlreadyExists => write!(f, "ALREADY_EXISTS"),
29 RpcStatus::PermissionDenied => write!(f, "PERMISSION_DENIED"),
30 RpcStatus::Unauthenticated => write!(f, "UNAUTHENTICATED"),
31 RpcStatus::ResourceExhausted => write!(f, "RESOURCE_EXHAUSTED"),
32 RpcStatus::Internal => write!(f, "INTERNAL"),
33 RpcStatus::Unavailable => write!(f, "UNAVAILABLE"),
34 RpcStatus::DeadlineExceeded => write!(f, "DEADLINE_EXCEEDED"),
35 }
36 }
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct RpcError {
42 pub status: RpcStatus,
43 pub message: String,
44}
45
46impl RpcError {
47 pub fn new(status: RpcStatus, message: impl Into<String>) -> Self {
48 Self {
49 status,
50 message: message.into(),
51 }
52 }
53
54 pub fn internal(message: impl Into<String>) -> Self {
55 Self::new(RpcStatus::Internal, message)
56 }
57
58 pub fn invalid_argument(message: impl Into<String>) -> Self {
59 Self::new(RpcStatus::InvalidArgument, message)
60 }
61
62 pub fn not_found(message: impl Into<String>) -> Self {
63 Self::new(RpcStatus::NotFound, message)
64 }
65
66 pub fn method_not_found(method_id: u16) -> Self {
67 Self::new(
68 RpcStatus::NotFound,
69 format!("Method not found: {}", method_id),
70 )
71 }
72
73 pub fn service_not_found(service_id: u16) -> Self {
74 Self::new(
75 RpcStatus::NotFound,
76 format!("Service not found: {}", service_id),
77 )
78 }
79
80 pub fn codec_error(message: impl Into<String>) -> Self {
81 Self::new(RpcStatus::Internal, message)
82 }
83
84 pub fn unavailable(message: impl Into<String>) -> Self {
85 Self::new(RpcStatus::Unavailable, message)
86 }
87
88 pub fn deadline_exceeded(message: impl Into<String>) -> Self {
89 Self::new(RpcStatus::DeadlineExceeded, message)
90 }
91}
92
93impl fmt::Display for RpcError {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 write!(f, "[{}] {}", self.status, self.message)
96 }
97}
98
99impl std::error::Error for RpcError {}
100
101impl From<std::io::Error> for RpcError {
102 fn from(err: std::io::Error) -> Self {
103 RpcError::internal(err.to_string())
104 }
105}
106
107impl From<bincode::Error> for RpcError {
108 fn from(err: bincode::Error) -> Self {
109 RpcError::codec_error(format!("bincode: {}", err))
110 }
111}