titanic/
err.rs

1//! All errors that can happen while parsing can be found here.
2
3use arrayvec::{ArrayVec, CapacityError};
4use chrono;
5use std::{io, num, str};
6
7use lexer::STRING_LENGTH;
8
9quick_error! {
10    /// Errors that can happen while parsing.
11    #[derive(Debug)]
12    pub enum ParseError {
13        /// Encountered an error while lexing.
14        Lexer(err: LexError) {
15            from()
16            description(err.description())
17            display("Could not parse due to an error in the lexer: {}", err)
18            cause(err)
19        }
20        /// Found an unexpected token.
21        UnexpectedToken {
22            description("Unexpected token")
23            display("Encountered unexpected token")
24        }
25        /// Found an unexptected sentence type.
26        UnexpectedSentenceType {
27            description("Unexpected sentence type")
28            display("Encountered unexpected sentence type")
29        }
30        /// Failed to parse a `FloatLiteral` to a `NaiveTime`.
31        Time(err: chrono::format::ParseError) {
32            from()
33            description("Time parsing error")
34            display("Failed to parse FloatLiteral as time: {}", err)
35            cause(err)
36        }
37        /// Failed to parse a `StringLiteral` to a `CardDir`.
38        UnexpectedDir(dir: ArrayVec<[u8; STRING_LENGTH]>) {
39            description("Unexpected direction")
40            display("Could not parse {:?} as direction", dir)
41        }
42        /// Failed to convert to `str`.
43        /// This should not happen if the lexer only returns ascii bytes.
44        Utf8(err: str::Utf8Error) {
45            from()
46            description(err.description())
47            display("{}", err)
48            cause(err)
49        }
50        /// Found an invalid value.
51        /// E.g. a station id not between 0 and 1023, a float with the wrong
52        /// format for a coordinate, ...
53        InvalidValue(msg: &'static str) {
54            description("Invalid value")
55            display("Invalid value, {}", msg)
56        }
57        /// Failed to parse an integer.
58        Int(err: num::ParseIntError) {
59            from()
60            description(err.description())
61            display("{}", err)
62            cause(err)
63        }
64        /// Failed to parse a float.
65        Float(err: num::ParseFloatError) {
66            from()
67            description(err.description())
68            display("{}", err)
69            cause(err)
70        }
71        /// Found an invalid coordinate, e.g. latitude outside of the range -90° to +90°.
72        InvalidCoord(val: f64, max: f64) {
73            description("Invalid coordinate")
74            display("Invalid coordinate: {} should be between {:.0} and {:.0}", val, max*-1.0, max)
75        }
76        /// Found an unexpected unit.
77        InvalidUnit {
78            description("Unexpected unit")
79            display("Found an unexpected unit")
80        }
81    }
82}
83
84quick_error!{
85    /// Errors that can happen while lexing the raw input.
86    #[derive(Debug)]
87    pub enum LexError {
88        /// An invalid character.
89        InvalidCharacter(c: u8) {
90            description("Invalid character")
91            display("Encountered invalid character \"{}\"", *c as char)
92        }
93        /// The checksum is invalid.
94        /// The two values are the expected and the actual checksum.
95        /// `InvalidChecksum(expected: u8, actual: u8)`
96        InvalidChecksum(expected: u8, actual: u8) {
97            description("Invalid checksum")
98            display("Expected checksum \"{:X}\" , found checksum \"{}\"", expected, actual)
99        }
100        /// I/O Error
101        Io(err: io::Error) {
102            from()
103            description(err.description())
104            display("Encountered I/O error while lexing: {}", err)
105            cause(err)
106        }
107        /// The EOF was found in an unexpected location.
108        /// This can happen in the header and the checksum, when there aren't
109        /// enough bytes after the starting sign.
110        UnexpectedEof(token: &'static str) {
111            description("Unexpected EOF")
112            display("Encountered unexpected EOF in {}", token)
113        }
114        /// A token could not be completed.
115        /// Some reasons for that are a `'-'` without a following digit and
116        /// a non hex-digit in the two chars following `'*'`.
117        IncompleteToken(token: &'static str) {
118            description("Incomplete token")
119            display("Could not complete token of type {}", token)
120        }
121        /// An array overflowed while trying to push values into it.
122        ArrayOverflow(err: CapacityError<u8>) {
123            from()
124            description(err.description())
125            display("Array buffer overflow: {}", err)
126            cause(err)
127        }
128        /// Failed to parse an integer.
129        Int(err: num::ParseIntError) {
130            from()
131            description(err.description())
132            display("{}", err)
133            cause(err)
134        }
135        /// Failed to parse some bytes to a `str` because they are not even utf8
136        /// even though only ascii is expected.
137        NotEvenUtf8(err: str::Utf8Error) {
138            from()
139            description(err.description())
140            display("Expected ascii but did not even get valid utf8: {}", err)
141            cause(err)
142        }
143    }
144}
145
146impl From<(u8, u8)> for LexError {
147    fn from((expected, actual): (u8, u8)) -> Self {
148        LexError::InvalidChecksum(expected, actual)
149    }
150}