1use core::fmt;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10#[repr(u32)]
11pub enum ErrorCode {
12 Ok = 0,
14 Cancelled = 1,
15 DeadlineExceeded = 2,
16 InvalidArgument = 3,
17 NotFound = 4,
18 AlreadyExists = 5,
19 PermissionDenied = 6,
20 ResourceExhausted = 7,
21 FailedPrecondition = 8,
22 Aborted = 9,
23 OutOfRange = 10,
24 Unimplemented = 11,
25 Internal = 12,
26 Unavailable = 13,
27 DataLoss = 14,
28
29 PeerDied = 100,
31 SessionClosed = 101,
32 ValidationFailed = 102,
33 StaleGeneration = 103,
34}
35
36impl ErrorCode {
37 pub fn from_u32(value: u32) -> Option<Self> {
38 match value {
39 0 => Some(Self::Ok),
40 1 => Some(Self::Cancelled),
41 2 => Some(Self::DeadlineExceeded),
42 3 => Some(Self::InvalidArgument),
43 4 => Some(Self::NotFound),
44 5 => Some(Self::AlreadyExists),
45 6 => Some(Self::PermissionDenied),
46 7 => Some(Self::ResourceExhausted),
47 8 => Some(Self::FailedPrecondition),
48 9 => Some(Self::Aborted),
49 10 => Some(Self::OutOfRange),
50 11 => Some(Self::Unimplemented),
51 12 => Some(Self::Internal),
52 13 => Some(Self::Unavailable),
53 14 => Some(Self::DataLoss),
54 100 => Some(Self::PeerDied),
55 101 => Some(Self::SessionClosed),
56 102 => Some(Self::ValidationFailed),
57 103 => Some(Self::StaleGeneration),
58 _ => None,
59 }
60 }
61}
62
63impl fmt::Display for ErrorCode {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 match self {
66 Self::Ok => write!(f, "ok"),
67 Self::Cancelled => write!(f, "cancelled"),
68 Self::DeadlineExceeded => write!(f, "deadline exceeded"),
69 Self::InvalidArgument => write!(f, "invalid argument"),
70 Self::NotFound => write!(f, "not found"),
71 Self::AlreadyExists => write!(f, "already exists"),
72 Self::PermissionDenied => write!(f, "permission denied"),
73 Self::ResourceExhausted => write!(f, "resource exhausted"),
74 Self::FailedPrecondition => write!(f, "failed precondition"),
75 Self::Aborted => write!(f, "aborted"),
76 Self::OutOfRange => write!(f, "out of range"),
77 Self::Unimplemented => write!(f, "unimplemented"),
78 Self::Internal => write!(f, "internal error"),
79 Self::Unavailable => write!(f, "unavailable"),
80 Self::DataLoss => write!(f, "data loss"),
81 Self::PeerDied => write!(f, "peer died"),
82 Self::SessionClosed => write!(f, "session closed"),
83 Self::ValidationFailed => write!(f, "validation failed"),
84 Self::StaleGeneration => write!(f, "stale generation"),
85 }
86 }
87}
88
89#[derive(Debug)]
91pub enum TransportError {
92 Closed,
93 Io(std::io::Error),
94 Validation(ValidationError),
95 Encode(EncodeError),
96 Decode(DecodeError),
97}
98
99impl fmt::Display for TransportError {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match self {
102 Self::Closed => write!(f, "transport closed"),
103 Self::Io(e) => write!(f, "I/O error: {e}"),
104 Self::Validation(e) => write!(f, "validation error: {e}"),
105 Self::Encode(e) => write!(f, "encode error: {e}"),
106 Self::Decode(e) => write!(f, "decode error: {e}"),
107 }
108 }
109}
110
111impl std::error::Error for TransportError {
112 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
113 match self {
114 Self::Io(e) => Some(e),
115 Self::Validation(e) => Some(e),
116 Self::Encode(e) => Some(e),
117 Self::Decode(e) => Some(e),
118 _ => None,
119 }
120 }
121}
122
123impl From<std::io::Error> for TransportError {
124 fn from(e: std::io::Error) -> Self {
125 Self::Io(e)
126 }
127}
128
129impl From<ValidationError> for TransportError {
130 fn from(e: ValidationError) -> Self {
131 Self::Validation(e)
132 }
133}
134
135impl From<EncodeError> for TransportError {
136 fn from(e: EncodeError) -> Self {
137 Self::Encode(e)
138 }
139}
140
141impl From<DecodeError> for TransportError {
142 fn from(e: DecodeError) -> Self {
143 Self::Decode(e)
144 }
145}
146
147#[derive(Debug, Clone, PartialEq, Eq)]
149pub enum ValidationError {
150 SlotOutOfBounds {
151 slot: u32,
152 max: u32,
153 },
154 PayloadOutOfBounds {
155 offset: u32,
156 len: u32,
157 slot_size: u32,
158 },
159 InlinePayloadTooLarge {
160 len: u32,
161 max: u32,
162 },
163 PayloadTooLarge {
164 len: u32,
165 max: u32,
166 },
167 StaleGeneration {
168 expected: u32,
169 actual: u32,
170 },
171 ChannelOutOfBounds {
172 channel: u32,
173 max: u32,
174 },
175 InvalidInlineDescriptor,
176}
177
178impl fmt::Display for ValidationError {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 match self {
181 Self::SlotOutOfBounds { slot, max } => {
182 write!(f, "slot {slot} out of bounds (max {max})")
183 }
184 Self::PayloadOutOfBounds {
185 offset,
186 len,
187 slot_size,
188 } => {
189 write!(
190 f,
191 "payload [{offset}..{offset}+{len}] exceeds slot size {slot_size}"
192 )
193 }
194 Self::InlinePayloadTooLarge { len, max } => {
195 write!(f, "inline payload {len} bytes exceeds max {max}")
196 }
197 Self::PayloadTooLarge { len, max } => {
198 write!(f, "payload {len} bytes exceeds max {max}")
199 }
200 Self::StaleGeneration { expected, actual } => {
201 write!(f, "stale generation: expected {expected}, got {actual}")
202 }
203 Self::ChannelOutOfBounds { channel, max } => {
204 write!(f, "channel {channel} out of bounds (max {max})")
205 }
206 Self::InvalidInlineDescriptor => {
207 write!(f, "inline descriptor has non-zero slot fields")
208 }
209 }
210 }
211}
212
213impl std::error::Error for ValidationError {}
214
215#[derive(Debug)]
217pub enum EncodeError {
218 BufferTooSmall { needed: usize, available: usize },
219 EncodeFailed(String),
220 NoSlotAvailable,
221}
222
223impl fmt::Display for EncodeError {
224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225 match self {
226 Self::BufferTooSmall { needed, available } => {
227 write!(f, "buffer too small: need {needed}, have {available}")
228 }
229 Self::EncodeFailed(msg) => write!(f, "encode failed: {msg}"),
230 Self::NoSlotAvailable => write!(f, "no slot available"),
231 }
232 }
233}
234
235impl std::error::Error for EncodeError {}
236
237#[derive(Debug)]
239pub enum DecodeError {
240 UnexpectedEof,
241 InvalidData(String),
242 UnsupportedEncoding(u16),
243}
244
245impl fmt::Display for DecodeError {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 match self {
248 Self::UnexpectedEof => write!(f, "unexpected end of input"),
249 Self::InvalidData(msg) => write!(f, "invalid data: {msg}"),
250 Self::UnsupportedEncoding(enc) => write!(f, "unsupported encoding: {enc}"),
251 }
252 }
253}
254
255impl std::error::Error for DecodeError {}
256
257#[derive(Debug)]
259pub enum RpcError {
260 Transport(TransportError),
261 Status { code: ErrorCode, message: String },
262 Cancelled,
263 DeadlineExceeded,
264}
265
266impl fmt::Display for RpcError {
267 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268 match self {
269 Self::Transport(e) => write!(f, "transport error: {e}"),
270 Self::Status { code, message } => write!(f, "{code}: {message}"),
271 Self::Cancelled => write!(f, "cancelled"),
272 Self::DeadlineExceeded => write!(f, "deadline exceeded"),
273 }
274 }
275}
276
277impl std::error::Error for RpcError {
278 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
279 match self {
280 Self::Transport(e) => Some(e),
281 _ => None,
282 }
283 }
284}
285
286impl From<TransportError> for RpcError {
287 fn from(e: TransportError) -> Self {
288 Self::Transport(e)
289 }
290}