Skip to main content

serde_fressian/
error.rs

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    //// serialization errors
21    UnsupportedTAType,
22    UnsupportedCacheType, //temporary
23    IntTooLargeFori64,
24    //// deserialization errors
25    UnmatchedCode(u8),
26    Expectedi64, //rawinput read_int got bad int
27    ExpectedNonZeroReadLength, //gave length 0 to ByteReader::read_bytes
28    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    //rename
139    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    // pub fn fix_position<F>(self, f: F) -> Self
175    // where
176    //     F: FnOnce(ErrorCode) -> Error,
177    // {
178    //     if self.err.line == 0 {
179    //         f(self.err.code)
180    //     } else {
181    //         self
182    //     }
183    // }
184}
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(), // is what unwrap() shows.
241            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            // should use Display::fmt or to_string().
266            _ => "fressian error!",
267        }
268    }
269}
270