1use std::fmt;
2
3use value_trait::ValueType;
4
5#[derive(Debug)]
7pub enum ErrorType {
8 Unexpected(Option<ValueType>, Option<ValueType>),
10 InputTooLarge,
13 BadKeyType,
15 ExpectedArray,
17 ExpectedArrayComma,
19 ExpectedBoolean,
21 ExpectedEnum,
23 ExpectedFloat,
25 ExpectedInteger,
27 ExpectedMap,
29 ExpectedObjectColon,
31 ExpectedMapComma,
33 ExpectedMapEnd,
35 ExpectedNull,
37 ExpectedTrue,
39 ExpectedFalse,
41 ExpectedNumber,
43 ExpectedSigned,
45 ExpectedString,
47 ExpectedUnsigned,
49 InternalError(InternalError),
51 InvalidEscape,
53 InvalidExponent,
55 InvalidNumber,
57 InvalidUtf8,
59 InvalidUnicodeEscape,
61 InvalidUnicodeCodepoint,
63 KeyMustBeAString,
65 NoStructure,
67 Parser,
69 Eof,
71 Serde(String),
73 Syntax,
75 TrailingData,
77 UnexpectedCharacter,
79 UnterminatedString,
81 ExpectedArrayContent,
83 ExpectedObjectContent,
85 ExpectedObjectKey,
87 Overflow,
89 DepthLimitExceeded,
91 SimdUnsupported,
93 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#[derive(Debug, PartialEq)]
160pub struct Error {
161 index: usize,
163 character: Option<char>,
165 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 #[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 #[must_use]
199 pub fn index(&self) -> usize {
200 self.index
201 }
202
203 #[must_use]
205 pub fn character(&self) -> Option<char> {
206 self.character
207 }
208
209 #[must_use]
211 pub fn error(&self) -> &ErrorType {
212 &self.err_type
213 }
214
215 #[must_use]
221 pub fn is_io(&self) -> bool {
222 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 #[must_use]
232 pub fn is_eof(&self) -> bool {
233 matches!(self.err_type, ErrorType::Eof)
234 }
235
236 #[must_use]
238 pub fn is_data(&self) -> bool {
239 !(self.is_syntax() || self.is_eof() || self.is_io())
241 }
242
243 #[must_use]
245 pub fn is_syntax(&self) -> bool {
246 matches!(
248 self.err_type,
249 ErrorType::InternalError(crate::InternalError::TapeError) | 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}