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