Skip to main content

simd_json/
error.rs

1use std::fmt;
2
3use value_trait::ValueType;
4
5/// Error types encountered while parsing
6#[derive(Debug)]
7pub enum ErrorType {
8    /// A specific type was expected but another one encountered.
9    Unexpected(Option<ValueType>, Option<ValueType>),
10    /// Simd-json only supports inputs of up to
11    /// 4GB in size.
12    InputTooLarge,
13    /// The key of a map isn't a string
14    BadKeyType,
15    /// Expected an array
16    ExpectedArray,
17    /// Expected a `,` in an array
18    ExpectedArrayComma,
19    /// expected an boolean
20    ExpectedBoolean,
21    /// Expected an enum
22    ExpectedEnum,
23    /// Expected a float
24    ExpectedFloat,
25    /// Expected an integer
26    ExpectedInteger,
27    /// Expected a map
28    ExpectedMap,
29    /// Expected an `:` to separate key and value in an object
30    ExpectedObjectColon,
31    /// Expected a `,` in an object
32    ExpectedMapComma,
33    /// Expected the object to end
34    ExpectedMapEnd,
35    /// Expected a null
36    ExpectedNull,
37    /// Expected a true
38    ExpectedTrue,
39    /// Expected a false
40    ExpectedFalse,
41    /// Expected a number
42    ExpectedNumber,
43    /// Expected a signed number
44    ExpectedSigned,
45    /// Expected a string
46    ExpectedString,
47    /// Expected an unsigned number
48    ExpectedUnsigned,
49    /// Internal error
50    InternalError(InternalError),
51    /// Invalid escape sequence
52    InvalidEscape,
53    /// Invalid exponent in a floating point number
54    InvalidExponent,
55    /// Invalid number
56    InvalidNumber,
57    /// Invalid UTF8 codepoint
58    InvalidUtf8,
59    /// Invalid Unicode escape sequence
60    InvalidUnicodeEscape,
61    /// Invalid Unicode codepoint
62    InvalidUnicodeCodepoint,
63    /// Object Key isn't a string
64    KeyMustBeAString,
65    /// Non structural character
66    NoStructure,
67    /// Parser Error
68    Parser,
69    /// Early End Of File
70    Eof,
71    /// Generic serde error
72    Serde(String),
73    /// Generic syntax error
74    Syntax,
75    /// Trailing data
76    TrailingData,
77    /// Unexpected character
78    UnexpectedCharacter,
79    /// Unterminated string
80    UnterminatedString,
81    /// Expected Array elements
82    ExpectedArrayContent,
83    /// Expected Object elements
84    ExpectedObjectContent,
85    /// Expected Object Key
86    ExpectedObjectKey,
87    /// Overflow of a limited buffer
88    Overflow,
89    /// The structure depth exceeds the limit (`1024` by default).
90    DepthLimitExceeded,
91    /// No SIMD support detected during runtime
92    SimdUnsupported,
93    /// IO error
94    Io(std::io::Error),
95}
96
97#[derive(Clone, Debug, PartialEq)]
98pub enum InternalError {
99    TapeError,
100}
101
102impl From<std::io::Error> for Error {
103    fn from(e: std::io::Error) -> Self {
104        Self::generic(ErrorType::Io(e))
105    }
106}
107
108#[cfg(not(tarpaulin_include))]
109impl PartialEq for ErrorType {
110    fn eq(&self, other: &Self) -> bool {
111        match (self, other) {
112            (Self::Io(_), Self::Io(_))
113            | (Self::BadKeyType, Self::BadKeyType)
114            | (Self::ExpectedArray, Self::ExpectedArray)
115            | (Self::ExpectedArrayComma, Self::ExpectedArrayComma)
116            | (Self::ExpectedBoolean, Self::ExpectedBoolean)
117            | (Self::ExpectedTrue, Self::ExpectedTrue)
118            | (Self::ExpectedFalse, Self::ExpectedFalse)
119            | (Self::ExpectedEnum, Self::ExpectedEnum)
120            | (Self::ExpectedFloat, Self::ExpectedFloat)
121            | (Self::ExpectedInteger, Self::ExpectedInteger)
122            | (Self::ExpectedMap, Self::ExpectedMap)
123            | (Self::ExpectedObjectColon, Self::ExpectedObjectColon)
124            | (Self::ExpectedMapComma, Self::ExpectedMapComma)
125            | (Self::ExpectedMapEnd, Self::ExpectedMapEnd)
126            | (Self::ExpectedNull, Self::ExpectedNull)
127            | (Self::ExpectedNumber, Self::ExpectedNumber)
128            | (Self::ExpectedSigned, Self::ExpectedSigned)
129            | (Self::ExpectedString, Self::ExpectedString)
130            | (Self::ExpectedUnsigned, Self::ExpectedUnsigned)
131            | (Self::InvalidEscape, Self::InvalidEscape)
132            | (Self::InvalidExponent, Self::InvalidExponent)
133            | (Self::InvalidNumber, Self::InvalidNumber)
134            | (Self::InvalidUtf8, Self::InvalidUtf8)
135            | (Self::InvalidUnicodeEscape, Self::InvalidUnicodeEscape)
136            | (Self::InvalidUnicodeCodepoint, Self::InvalidUnicodeCodepoint)
137            | (Self::KeyMustBeAString, Self::KeyMustBeAString)
138            | (Self::NoStructure, Self::NoStructure)
139            | (Self::Parser, Self::Parser)
140            | (Self::Eof, Self::Eof)
141            | (Self::Syntax, Self::Syntax)
142            | (Self::TrailingData, Self::TrailingData)
143            | (Self::UnexpectedCharacter, Self::UnexpectedCharacter)
144            | (Self::UnterminatedString, Self::UnterminatedString)
145            | (Self::ExpectedArrayContent, Self::ExpectedArrayContent)
146            | (Self::ExpectedObjectContent, Self::ExpectedObjectContent)
147            | (Self::ExpectedObjectKey, Self::ExpectedObjectKey)
148            | (Self::Overflow, Self::Overflow)
149            | (Self::DepthLimitExceeded, Self::DepthLimitExceeded)
150            | (Self::InputTooLarge, Self::InputTooLarge)
151            | (Self::SimdUnsupported, Self::SimdUnsupported) => true,
152            (Self::Serde(s1), Self::Serde(s2)) => s1 == s2,
153            (Self::InternalError(e1), Self::InternalError(e2)) => e1 == e2,
154            _ => false,
155        }
156    }
157}
158/// Parser error
159#[derive(Debug, PartialEq)]
160pub struct Error {
161    /// Byte index it was encountered at
162    index: usize,
163    /// Current character
164    character: Option<char>,
165    /// Type of error
166    err_type: ErrorType,
167}
168
169impl Error {
170    #[cold]
171    #[inline(never)]
172    pub(crate) fn new(index: usize, character: Option<char>, err_type: ErrorType) -> Self {
173        Self {
174            index,
175            character,
176            err_type,
177        }
178    }
179    #[cold]
180    #[inline(never)]
181    pub(crate) fn new_c(index: usize, character: char, error: ErrorType) -> Self {
182        Self::new(index, Some(character), error)
183    }
184
185    /// Create a generic error
186    #[must_use = "Error creation"]
187    #[cold]
188    #[inline(never)]
189    pub fn generic(t: ErrorType) -> Self {
190        Self {
191            index: 0,
192            character: None,
193            err_type: t,
194        }
195    }
196
197    /// Returns the byte index the error occurred at.
198    #[must_use]
199    pub fn index(&self) -> usize {
200        self.index
201    }
202
203    /// Returns the current character the error occurred at.
204    #[must_use]
205    pub fn character(&self) -> Option<char> {
206        self.character
207    }
208
209    /// Returns the type of error that occurred.
210    #[must_use]
211    pub fn error(&self) -> &ErrorType {
212        &self.err_type
213    }
214
215    // These make it a bit easier to fit into a serde_json context
216    // The classification is based on that of serde_json - so if maybe
217    // you disagree with that classification, please leave as is anyway.
218
219    /// Indicates if the error that occurred was an IO error
220    #[must_use]
221    pub fn is_io(&self) -> bool {
222        // We have to include InternalError _somewhere_
223        match &self.err_type {
224            ErrorType::Io(_) | ErrorType::InputTooLarge => true,
225            ErrorType::InternalError(e) if !matches!(e, crate::InternalError::TapeError) => true,
226            _ => false,
227        }
228    }
229
230    /// Indicates if the error that occurred was an early EOF
231    #[must_use]
232    pub fn is_eof(&self) -> bool {
233        matches!(self.err_type, ErrorType::Eof)
234    }
235
236    /// Indicates if the error that occurred was due to a data shape error
237    #[must_use]
238    pub fn is_data(&self) -> bool {
239        // Lazy? maybe but if it aint something else...
240        !(self.is_syntax() || self.is_eof() || self.is_io())
241    }
242
243    /// Indicates if the error that occurred was due a JSON syntax error
244    #[must_use]
245    pub fn is_syntax(&self) -> bool {
246        // Lazy? maybe but if it aint something else...
247        matches!(
248            self.err_type,
249            ErrorType::InternalError(crate::InternalError::TapeError) | //This seems to get thrown on some syntax errors
250            ErrorType::BadKeyType |
251            ErrorType::ExpectedArrayComma |
252            ErrorType::ExpectedObjectColon |
253            ErrorType::ExpectedMapComma |
254            ErrorType::ExpectedMapEnd |
255            ErrorType::InvalidEscape |
256            ErrorType::InvalidExponent |
257            ErrorType::InvalidNumber |
258            ErrorType::InvalidUtf8 |
259            ErrorType::InvalidUnicodeEscape |
260            ErrorType::InvalidUnicodeCodepoint |
261            ErrorType::KeyMustBeAString |
262            ErrorType::NoStructure |
263            ErrorType::Parser |
264            ErrorType::Syntax |
265            ErrorType::TrailingData |
266            ErrorType::UnexpectedCharacter |
267            ErrorType::UnterminatedString |
268            ErrorType::ExpectedArrayContent |
269            ErrorType::ExpectedObjectContent |
270            ErrorType::ExpectedObjectKey |
271            ErrorType::Overflow |
272            ErrorType::SimdUnsupported
273        )
274    }
275}
276impl std::error::Error for Error {}
277
278#[cfg(not(tarpaulin_include))]
279impl fmt::Display for Error {
280    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281        if let Some(c) = self.character {
282            write!(f, "{:?} at character {} ('{c}')", self.err_type, self.index)
283        } else {
284            write!(f, "{:?} at character {}", self.err_type, self.index)
285        }
286    }
287}
288
289#[cfg(not(tarpaulin_include))]
290impl From<Error> for std::io::Error {
291    fn from(e: Error) -> Self {
292        std::io::Error::new(std::io::ErrorKind::InvalidData, e)
293    }
294}