1use crate::Codec;
2use std::fmt;
3
4pub const RPC_ERR_PREFIX: &'static str = "rpc_";
6
7#[derive(thiserror::Error)]
11pub enum RpcError<E: RpcErrCodec> {
12 User(E),
13 Rpc(RpcIntErr),
14}
15
16impl<E: RpcErrCodec> fmt::Display for RpcError<E> {
17 #[inline]
18 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19 match self {
20 Self::User(e) => RpcErrCodec::fmt(e, f),
21 Self::Rpc(e) => fmt::Display::fmt(e, f),
22 }
23 }
24}
25
26impl<E: RpcErrCodec> fmt::Debug for RpcError<E> {
27 #[inline]
28 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29 fmt::Display::fmt(self, f)
30 }
31}
32
33impl<E: RpcErrCodec> std::cmp::PartialEq<RpcIntErr> for RpcError<E> {
34 #[inline]
35 fn eq(&self, other: &RpcIntErr) -> bool {
36 if let Self::Rpc(r) = self {
37 if r == other {
38 return true;
39 }
40 }
41 false
42 }
43}
44
45impl<E: RpcErrCodec + PartialEq> std::cmp::PartialEq<E> for RpcError<E> {
46 #[inline]
47 fn eq(&self, other: &E) -> bool {
48 if let Self::User(r) = self {
49 return r == other;
50 }
51 false
52 }
53}
54
55impl<E: RpcErrCodec + PartialEq> std::cmp::PartialEq<RpcError<E>> for RpcError<E> {
56 #[inline]
57 fn eq(&self, other: &Self) -> bool {
58 match self {
59 Self::Rpc(r) => {
60 if let Self::Rpc(o) = other {
61 return r == o;
62 }
63 }
64 Self::User(r) => {
65 if let Self::User(o) = other {
66 return r == o;
67 }
68 }
69 }
70 false
71 }
72}
73
74impl<E: RpcErrCodec> From<E> for RpcError<E> {
75 #[inline]
76 fn from(e: E) -> Self {
77 Self::User(e)
78 }
79}
80
81impl From<&str> for RpcError<String> {
82 #[inline]
83 fn from(e: &str) -> Self {
84 Self::User(e.to_string())
85 }
86}
87
88impl<E: RpcErrCodec> From<RpcIntErr> for RpcError<E> {
89 #[inline]
90 fn from(e: RpcIntErr) -> Self {
91 Self::Rpc(e)
92 }
93}
94
95pub trait RpcErrCodec: Send + Sized + 'static + Unpin {
187 fn encode<C: Codec>(&self, codec: &C) -> EncodedErr;
188
189 fn decode<C: Codec>(codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()>;
190
191 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
195}
196
197macro_rules! impl_rpc_error_for_num {
198 ($t: tt) => {
199 impl RpcErrCodec for $t {
200 #[inline(always)]
201 fn encode<C: Codec>(&self, _codec: &C) -> EncodedErr {
202 EncodedErr::Num(*self as u32)
203 }
204
205 #[inline(always)]
206 fn decode<C: Codec>(_codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()> {
207 if let Ok(i) = buf {
208 if i <= $t::max as u32 {
209 return Ok(i as Self);
210 }
211 }
212 Err(())
213 }
214
215 #[inline(always)]
216 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
217 write!(f, "errno {}", self)
218 }
219 }
220 };
221}
222
223impl_rpc_error_for_num!(i8);
224impl_rpc_error_for_num!(u8);
225impl_rpc_error_for_num!(i16);
226impl_rpc_error_for_num!(u16);
227impl_rpc_error_for_num!(i32);
228impl_rpc_error_for_num!(u32);
229
230impl RpcErrCodec for nix::errno::Errno {
231 #[inline(always)]
232 fn encode<C: Codec>(&self, _codec: &C) -> EncodedErr {
233 EncodedErr::Num(*self as u32)
234 }
235
236 #[inline(always)]
237 fn decode<C: Codec>(_codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()> {
238 if let Ok(i) = buf {
239 if i <= i32::max as u32 {
240 return Ok(Self::from_raw(i as i32));
241 }
242 }
243 Err(())
244 }
245
246 #[inline(always)]
247 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
248 write!(f, "{:?}", self)
249 }
250}
251
252impl RpcErrCodec for () {
253 #[inline(always)]
254 fn encode<C: Codec>(&self, _codec: &C) -> EncodedErr {
255 EncodedErr::Num(0u32)
256 }
257
258 #[inline(always)]
259 fn decode<C: Codec>(_codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()> {
260 if let Ok(i) = buf {
261 if i == 0 {
262 return Ok(());
263 }
264 }
265 Err(())
266 }
267
268 #[inline(always)]
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
270 write!(f, "err")
271 }
272}
273
274impl RpcErrCodec for String {
275 #[inline(always)]
276 fn encode<C: Codec>(&self, _codec: &C) -> EncodedErr {
277 EncodedErr::Buf(Vec::from(self.as_bytes()))
278 }
279 #[inline(always)]
280 fn decode<C: Codec>(_codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()> {
281 if let Err(s) = buf {
282 if let Ok(s) = str::from_utf8(s) {
283 return Ok(s.to_string());
284 }
285 }
286 Err(())
287 }
288
289 #[inline(always)]
290 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
291 write!(f, "{}", self)
292 }
293}
294
295#[derive(
302 strum::Display,
303 strum::EnumString,
304 strum::AsRefStr,
305 PartialEq,
306 PartialOrd,
307 Clone,
308 thiserror::Error,
309)]
310#[repr(u8)]
311pub enum RpcIntErr {
312 #[strum(serialize = "rpc_unreachable")]
314 Unreachable = 0,
315 #[strum(serialize = "rpc_io_err")]
317 IO = 1,
318 #[strum(serialize = "rpc_timeout")]
320 Timeout = 2,
321 #[strum(serialize = "rpc_method_notfound")]
323 Method = 3,
324 #[strum(serialize = "rpc_service_notfound")]
326 Service = 4,
327 #[strum(serialize = "rpc_encode")]
329 Encode = 5,
330 #[strum(serialize = "rpc_decode")]
332 Decode = 6,
333 #[strum(serialize = "rpc_internal_err")]
335 Internal = 7,
336 #[strum(serialize = "rpc_invalid_ver")]
338 Version = 8,
339}
340
341impl fmt::Debug for RpcIntErr {
343 #[inline]
344 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
345 fmt::Display::fmt(self, f)
346 }
347}
348
349impl RpcIntErr {
350 #[inline]
351 pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
352 self.as_ref().as_bytes()
353 }
354}
355
356impl From<std::io::Error> for RpcIntErr {
357 #[inline(always)]
358 fn from(_e: std::io::Error) -> Self {
359 Self::IO
360 }
361}
362
363#[derive(Debug, thiserror::Error)]
365pub enum EncodedErr {
366 Rpc(RpcIntErr),
368 Num(u32),
370 Static(&'static str),
372 Buf(Vec<u8>),
374}
375
376impl EncodedErr {
377 #[inline]
378 pub fn try_as_str<'a>(&'a self) -> Result<&'a str, ()> {
379 match self {
380 Self::Static(s) => return Ok(s),
381 Self::Buf(b) => {
382 if let Ok(s) = str::from_utf8(b) {
383 return Ok(s);
384 }
385 }
386 _ => {}
387 }
388 Err(())
389 }
390}
391
392impl std::cmp::PartialEq<EncodedErr> for EncodedErr {
394 fn eq(&self, other: &EncodedErr) -> bool {
395 match self {
396 Self::Rpc(e) => {
397 if let Self::Rpc(o) = other {
398 return e == o;
399 }
400 }
401 Self::Num(e) => {
402 if let Self::Num(o) = other {
403 return e == o;
404 }
405 }
406 Self::Static(s) => {
407 if let Ok(o) = other.try_as_str() {
408 return *s == o;
409 }
410 }
411 Self::Buf(s) => {
412 if let Self::Buf(o) = other {
413 return s == o;
414 } else if let Ok(o) = other.try_as_str() {
415 if let Ok(_s) = str::from_utf8(s) {
417 return _s == o;
418 }
419 }
420 }
421 }
422 false
423 }
424}
425
426impl fmt::Display for EncodedErr {
427 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428 match self {
429 Self::Rpc(e) => e.fmt(f),
430 Self::Num(no) => write!(f, "errno {}", no),
431 Self::Static(s) => write!(f, "{}", s),
432 Self::Buf(b) => match str::from_utf8(b) {
433 Ok(s) => {
434 write!(f, "{}", s)
435 }
436 Err(_) => {
437 write!(f, "err blob {} length", b.len())
438 }
439 },
440 }
441 }
442}
443
444impl From<RpcIntErr> for EncodedErr {
445 #[inline(always)]
446 fn from(e: RpcIntErr) -> Self {
447 Self::Rpc(e)
448 }
449}
450
451#[cfg(test)]
452mod tests {
453 use super::*;
454 use nix::errno::Errno;
455 use std::str::FromStr;
456
457 #[test]
458 fn test_internal_error() {
459 println!("{}", RpcIntErr::Internal);
460 println!("{:?}", RpcIntErr::Internal);
461 let s = RpcIntErr::Timeout.as_ref();
462 println!("RpcIntErr::Timeout as {}", s);
463 let e = RpcIntErr::from_str(s).expect("parse");
464 assert_eq!(e, RpcIntErr::Timeout);
465 assert!(RpcIntErr::from_str("timeoutss").is_err());
466 assert!(RpcIntErr::Timeout < RpcIntErr::Method);
467 assert!(RpcIntErr::IO < RpcIntErr::Method);
468 assert!(RpcIntErr::Unreachable < RpcIntErr::Method);
469 }
470
471 #[test]
472 fn test_rpc_error_default() {
473 let e = RpcError::<i32>::from(1i32);
474 println!("err {:?} {}", e, e);
475
476 let e = RpcError::<Errno>::from(Errno::EIO);
477 println!("err {:?} {}", e, e);
478
479 let e = RpcError::<String>::from("err_str");
480 println!("err {:?} {}", e, e);
481 let e2 = RpcError::<String>::from("err_str".to_string());
482 assert_eq!(e, e2);
483
484 let e = RpcError::<String>::from(RpcIntErr::IO);
485 println!("err {:?} {}", e, e);
486
487 let _e: Result<(), RpcIntErr> = Err(RpcIntErr::IO);
488
489 let e: Result<(), RpcError<String>> = _e.map_err(|e| e.into());
495 println!("err {:?}", e);
496 }
497
498 }