1use rmpv::decode;
2use std::{error, fmt, io};
3
4#[derive(Debug)]
6pub enum DecodeError {
7 Truncated(io::Error),
9 Invalid,
12 DepthLimitExceeded,
14 UnknownIo(io::Error),
16}
17
18impl DecodeError {
19 fn description(&self) -> &str {
20 match *self {
21 DecodeError::Truncated(_) => "could not read enough bytes to decode a complete message",
22 DecodeError::UnknownIo(_) => "Unknown IO error while decoding a message",
23 DecodeError::Invalid => "the byte sequence is not a valid msgpack-rpc message",
24 DecodeError::DepthLimitExceeded => {
25 "The depth limit [`MAX_DEPTH`] of 1024 bytes were exceeded."
26 }
27 }
28 }
29}
30
31impl fmt::Display for DecodeError {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
33 self.description().fmt(f)
34 }
35}
36
37impl error::Error for DecodeError {
38 fn description(&self) -> &str {
39 self.description()
40 }
41
42 fn cause(&self) -> Option<&dyn error::Error> {
43 match *self {
44 DecodeError::UnknownIo(ref e) => Some(e),
45 DecodeError::Truncated(ref e) => Some(e),
46 _ => None,
47 }
48 }
49}
50
51impl From<io::Error> for DecodeError {
52 fn from(err: io::Error) -> DecodeError {
53 log::error!("Got I/O error {err}");
54 match err.kind() {
55 io::ErrorKind::UnexpectedEof => DecodeError::Truncated(err),
56 io::ErrorKind::Other => {
57 if let Some(cause) = err.get_ref().unwrap().source() {
58 if cause.to_string() == "type mismatch" {
62 return DecodeError::Invalid;
63 }
64 }
65 DecodeError::UnknownIo(err)
66 }
67 _ => DecodeError::UnknownIo(err),
68 }
69 }
70}
71
72impl From<decode::Error> for DecodeError {
73 fn from(err: decode::Error) -> DecodeError {
74 match err {
75 decode::Error::InvalidMarkerRead(io_err) | decode::Error::InvalidDataRead(io_err) => {
76 From::from(io_err)
77 }
78 decode::Error::DepthLimitExceeded => DecodeError::DepthLimitExceeded,
79 }
80 }
81}