1use serde::{de, ser};
10use std::error;
11use std::fmt;
12use std::io;
13use std::result;
14
15#[derive(Clone, PartialEq, Eq, Debug)]
16pub enum ErrorCode {
17 Unsupported(char),
19 EOFWhileParsing,
21 StackUnderflow,
23 NegativeLength,
25 StringNotUTF8,
27 InvalidStackTop(&'static str, String),
29 ValueNotHashable,
31 Recursive,
33 UnresolvedGlobal,
35 UnsupportedGlobal(Vec<u8>, Vec<u8>),
37 MissingMemo(u32),
39 InvalidLiteral(Vec<u8>),
41 TrailingBytes,
43 InvalidValue(String),
45 Structure(String),
47}
48
49impl fmt::Display for ErrorCode {
50 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
51 match *self {
52 ErrorCode::Unsupported(ch) => write!(fmt, "unsupported opcode {:?}", ch),
53 ErrorCode::EOFWhileParsing => write!(fmt, "EOF while parsing"),
54 ErrorCode::StackUnderflow => write!(fmt, "pickle stack underflow"),
55 ErrorCode::NegativeLength => write!(fmt, "negative length prefix"),
56 ErrorCode::StringNotUTF8 => write!(fmt, "string is not UTF-8 encoded"),
57 ErrorCode::InvalidStackTop(what, ref it) => {
58 write!(fmt, "invalid stack top, expected {}, got {}", what, it)
59 }
60 ErrorCode::ValueNotHashable => write!(fmt, "dict key or set item not hashable"),
61 ErrorCode::Recursive => write!(fmt, "recursive structure found"),
62 ErrorCode::UnresolvedGlobal => write!(fmt, "unresolved global reference"),
63 ErrorCode::UnsupportedGlobal(ref m, ref g) => write!(
64 fmt,
65 "unsupported global: {}.{}",
66 String::from_utf8_lossy(m),
67 String::from_utf8_lossy(g)
68 ),
69 ErrorCode::MissingMemo(n) => write!(fmt, "missing memo with id {}", n),
70 ErrorCode::InvalidLiteral(ref l) => {
71 write!(fmt, "literal is invalid: {}", String::from_utf8_lossy(l))
72 }
73 ErrorCode::TrailingBytes => write!(fmt, "trailing bytes found"),
74 ErrorCode::InvalidValue(ref s) => write!(fmt, "invalid value: {}", s),
75 ErrorCode::Structure(ref s) => fmt.write_str(s),
76 }
77 }
78}
79
80#[derive(Debug)]
83pub enum Error {
84 Io(io::Error),
86 Eval(ErrorCode, usize),
88 Syntax(ErrorCode),
90}
91
92impl From<io::Error> for Error {
93 fn from(error: io::Error) -> Error {
94 Error::Io(error)
95 }
96}
97
98pub type Result<T> = result::Result<T, Error>;
99
100impl fmt::Display for Error {
101 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
102 match *self {
103 Error::Io(ref error) => error.fmt(fmt),
104 Error::Eval(ref code, offset) => write!(fmt, "eval error at offset {}: {}", offset, code),
105 Error::Syntax(ref code) => write!(fmt, "decoding error: {}", code),
106 }
107 }
108}
109
110impl error::Error for Error {}
111
112impl de::Error for Error {
113 fn custom<T: fmt::Display>(msg: T) -> Error {
114 Error::Syntax(ErrorCode::Structure(msg.to_string()))
115 }
116}
117
118impl ser::Error for Error {
119 fn custom<T: fmt::Display>(msg: T) -> Error {
120 Error::Syntax(ErrorCode::Structure(msg.to_string()))
121 }
122}