1extern crate serde;
2
3use std;
4use std::fmt::{self, Debug, Display};
5use serde::{de};
6use serde::ser::{self,Serialize, Serializer, SerializeMap};
7use std::io;
8
9pub type Result<T> = ::std::result::Result<T, Error>;
10
11pub struct Error {
12 pub err: Box<ErrorImpl>,
13}
14
15pub enum ErrorCode {
16 Eof,
17 Io(io::Error),
18 Message(String),
19 UnsupportedType,
20 UnsupportedTAType,
22 UnsupportedCacheType, IntTooLargeFori64,
24 UnmatchedCode(u8),
26 Expectedi64, ExpectedNonZeroReadLength, ExpectedDoubleCode,
29 ExpectedFloatCode,
30 ExpectedBooleanCode,
31 ExpectedChunkBytesConclusion,
32 ExpectedBytesCode,
33 ExpectedStringCode,
34 MapExpectedListCode,
35 ExpectedListCode,
36 InvalidUTF8,
37 UnexpectedEof,
38 AttemptToReadPastEnd,
39}
40
41pub struct ErrorImpl {
42 pub code: ErrorCode,
43 pub position: usize,
44}
45
46#[derive(Copy, Clone, PartialEq, Eq, Debug, Serialize)]
47pub enum Category {
48 Io,
49 Eof,
50 De,
51 Ser,
52 Misc
53}
54
55impl ErrorImpl{
56 pub fn classify(&self) -> Category {
57 match self.code {
58 ErrorCode::Eof => Category::Eof,
59
60 ErrorCode::Io(_) => Category::Io,
61
62 ErrorCode::UnsupportedType
63 | ErrorCode::Message(_) => Category::Misc,
64
65 ErrorCode::UnsupportedTAType
66 | ErrorCode::UnsupportedCacheType
67 | ErrorCode::IntTooLargeFori64 => Category::Ser,
68
69 _ => Category::De
70 }
71 }
72}
73
74impl Serialize for ErrorImpl {
75 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
76 where
77 S: Serializer,
78 {
79 let mut map_state = serializer.serialize_map(None)?;
80
81 map_state.serialize_key("type")?;
82 map_state.serialize_value("serde-fressian")?;
83
84 map_state.serialize_key("category")?;
85 map_state.serialize_value(&self.classify())?;
86
87 map_state.serialize_key("position")?;
88 map_state.serialize_value(&self.position)?;
89
90 map_state.serialize_key("ErrorCode")?;
91
92 match &self.code {
93 ErrorCode::Io(_) => {
94 map_state.serialize_value("IO::Error")?;
95 }
96 ErrorCode::Message(msg) => {
97 map_state.serialize_value("Message")?;
98 map_state.serialize_key("value")?;
99 map_state.serialize_value(&msg)?;
100 }
101 ErrorCode::UnmatchedCode(code) => {
102 map_state.serialize_value("UnmatchedCode")?;
103 map_state.serialize_key("value")?;
104 map_state.serialize_value(&code)?;
105 }
106 _ => {
107 map_state.serialize_value(&self.code.to_string())?;
108 }
109 }
110
111 map_state.end()
112 }
113}
114
115impl Serialize for Error {
116 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
117 where
118 S: Serializer,
119 {
120 self.err.serialize(serializer)
121 }
122}
123
124impl Error {
125 pub fn is_eof(&self) -> bool { self.classify() == Category::Eof }
126
127 pub fn classify(&self) -> Category { self.err.classify() }
128
129 pub fn msg(msg: String) -> Self {
130 Error {
131 err: Box::new(ErrorImpl {
132 code: ErrorCode::Message(msg),
133 position: 0,
134 }),
135 }
136 }
137
138 pub fn syntax(code: ErrorCode, position: usize) -> Self {
140 Error {
141 err: Box::new(ErrorImpl {
142 code: code,
143 position: position,
144 }),
145 }
146 }
147
148 pub fn unmatched_code(code: u8, position: usize) -> Self {
149 Error {
150 err: Box::new(ErrorImpl {
151 code: ErrorCode::UnmatchedCode(code),
152 position: position,
153 }),
154 }
155 }
156
157 pub fn eof(position: usize) -> Self {
158 Error {
159 err: Box::new(ErrorImpl {
160 code: ErrorCode::Eof,
161 position: position,
162 }),
163 }
164 }
165 pub fn io(error: io::Error) -> Self {
166 Error {
167 err: Box::new(ErrorImpl {
168 code: ErrorCode::Io(error),
169 position: 0
170 }),
171 }
172 }
173
174 }
185
186impl Display for ErrorCode {
187 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
188 match *self {
189 ErrorCode::Eof => f.write_str("Eof"),
190 ErrorCode::Message(ref msg) => f.write_str(msg),
191 ErrorCode::Io(ref err) => Display::fmt(err, f),
192 ErrorCode::UnmatchedCode(_code) => f.write_str("UnmatchedCode"),
193 ErrorCode::UnsupportedType => f.write_str("UnsupportedType"),
194 ErrorCode::UnsupportedTAType => f.write_str("UnsupportedTAType"),
195 ErrorCode::UnsupportedCacheType => f.write_str("UnsupportedCacheType"),
196 ErrorCode::AttemptToReadPastEnd => f.write_str("AttemptToReadPastEnd"),
197 ErrorCode::UnexpectedEof => f.write_str("UnexpectedEof"),
198 ErrorCode::ExpectedListCode => f.write_str("ExpectedListCode"),
199 ErrorCode::MapExpectedListCode => f.write_str("MapExpectedListCode"),
200 ErrorCode::IntTooLargeFori64 => f.write_str("IntTooLargeFori64"),
201 ErrorCode::Expectedi64 => f.write_str("Expectedi64"),
202 ErrorCode::ExpectedDoubleCode => f.write_str("ExpectedDoubleCode"),
203 ErrorCode::ExpectedFloatCode => f.write_str("ExpectedFloatCode"),
204 ErrorCode::ExpectedBooleanCode => f.write_str("ExpectedBooleanCode"),
205 ErrorCode::ExpectedChunkBytesConclusion => f.write_str("ExpectedChunkBytesConclusion"),
206 ErrorCode::ExpectedBytesCode => f.write_str("ExpectedBytesCode"),
207 ErrorCode::InvalidUTF8 => f.write_str("InvalidUTF8"),
208 ErrorCode::ExpectedStringCode => f.write_str("ExpectedStringCode"),
209 ErrorCode::ExpectedNonZeroReadLength => f.write_str("ExpectedNonZeroReadLength")
210 }
211 }
212}
213
214
215impl Display for Error {
216 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
217 formatter.write_str(std::error::Error::description(self))
218 }
219}
220
221impl Display for ErrorImpl {
222 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
223 if self.position == 0 {
224 Display::fmt(&self.code, f)
225 } else {
226 write!(
227 f,
228 "{} at byte-position {}",
229 self.code, self.position
230 )
231 }
232 }
233}
234
235impl Debug for Error {
236 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
237 write!(
238 f,
239 "Error({:?}, byte-position: {})",
240 self.err.code.to_string(), self.err.position
242 )
243 }
244}
245
246
247impl ser::Error for Error {
248 fn custom<T: Display>(msg: T) -> Self {
249 Error::msg(msg.to_string())
250 }
251}
252
253impl de::Error for Error {
254 fn custom<T: Display>(msg: T) -> Self {
255 Error::msg(msg.to_string())
256 }
257}
258
259
260
261impl std::error::Error for Error {
262 fn description(&self) -> &str {
263 match self.err.code {
264 ErrorCode::Io(ref err) => std::error::Error::description(err),
265 _ => "fressian error!",
267 }
268 }
269}
270