1#[derive(Debug, PartialEq, Eq, Clone)]
6pub enum JsonErrorType {
7 FloatExpectingInt,
9
10 DuplicateKey(String),
12
13 InternalError(String),
15
16 EofWhileParsingList,
22
23 EofWhileParsingObject,
25
26 EofWhileParsingString,
28
29 EofWhileParsingValue,
31
32 ExpectedColon,
34
35 ExpectedListCommaOrEnd,
37
38 ExpectedObjectCommaOrEnd,
40
41 ExpectedSomeIdent,
43
44 ExpectedSomeValue,
46
47 InvalidEscape,
49
50 InvalidNumber,
52
53 NumberOutOfRange,
55
56 InvalidUnicodeCodePoint,
58
59 ControlCharacterWhileParsingString,
61
62 KeyMustBeAString,
64
65 LoneLeadingSurrogateInHexEscape,
67
68 TrailingComma,
70
71 TrailingCharacters,
73
74 UnexpectedEndOfHexEscape,
76
77 RecursionLimitExceeded,
79}
80
81impl std::fmt::Display for JsonErrorType {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 match self {
85 Self::FloatExpectingInt => f.write_str("float value was found where an int was expected"),
86 Self::DuplicateKey(s) => write!(f, "Detected duplicate key {s:?}"),
87 Self::InternalError(s) => write!(f, "Internal error: {s:?}"),
88 Self::EofWhileParsingList => f.write_str("EOF while parsing a list"),
89 Self::EofWhileParsingObject => f.write_str("EOF while parsing an object"),
90 Self::EofWhileParsingString => f.write_str("EOF while parsing a string"),
91 Self::EofWhileParsingValue => f.write_str("EOF while parsing a value"),
92 Self::ExpectedColon => f.write_str("expected `:`"),
93 Self::ExpectedListCommaOrEnd => f.write_str("expected `,` or `]`"),
94 Self::ExpectedObjectCommaOrEnd => f.write_str("expected `,` or `}`"),
95 Self::ExpectedSomeIdent => f.write_str("expected ident"),
96 Self::ExpectedSomeValue => f.write_str("expected value"),
97 Self::InvalidEscape => f.write_str("invalid escape"),
98 Self::InvalidNumber => f.write_str("invalid number"),
99 Self::NumberOutOfRange => f.write_str("number out of range"),
100 Self::InvalidUnicodeCodePoint => f.write_str("invalid unicode code point"),
101 Self::ControlCharacterWhileParsingString => {
102 f.write_str("control character (\\u0000-\\u001F) found while parsing a string")
103 }
104 Self::KeyMustBeAString => f.write_str("key must be a string"),
105 Self::LoneLeadingSurrogateInHexEscape => f.write_str("lone leading surrogate in hex escape"),
106 Self::TrailingComma => f.write_str("trailing comma"),
107 Self::TrailingCharacters => f.write_str("trailing characters"),
108 Self::UnexpectedEndOfHexEscape => f.write_str("unexpected end of hex escape"),
109 Self::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
110 }
111 }
112}
113
114pub type JsonResult<T> = Result<T, JsonError>;
115
116#[derive(Debug, Clone, Eq, PartialEq)]
118pub struct JsonError {
119 pub error_type: JsonErrorType,
121 pub index: usize,
123}
124
125impl JsonError {
126 pub(crate) fn new(error_type: JsonErrorType, index: usize) -> Self {
127 Self { error_type, index }
128 }
129
130 pub fn get_position(&self, json_data: &[u8]) -> LinePosition {
131 LinePosition::find(json_data, self.index)
132 }
133
134 pub fn description(&self, json_data: &[u8]) -> String {
135 let position = self.get_position(json_data);
136 format!("{} at {}", self.error_type, position)
137 }
138}
139
140impl std::fmt::Display for JsonError {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 write!(f, "{} at index {}", self.error_type, self.index)
143 }
144}
145
146macro_rules! json_error {
147 ($error_type:ident, $index:expr) => {
148 crate::errors::JsonError::new(crate::errors::JsonErrorType::$error_type, $index)
149 };
150}
151
152pub(crate) use json_error;
153
154macro_rules! json_err {
155 ($error_type:ident, $index:expr) => {
156 Err(crate::errors::json_error!($error_type, $index))
157 };
158}
159
160use crate::Jiter;
161pub(crate) use json_err;
162
163pub(crate) const DEFAULT_RECURSION_LIMIT: u8 = 200;
164
165#[derive(Debug, Clone, Eq, PartialEq)]
167pub enum JsonType {
168 Null,
169 Bool,
170 Int,
171 Float,
172 String,
173 Array,
174 Object,
175}
176
177impl std::fmt::Display for JsonType {
178 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179 match self {
180 Self::Null => f.write_str("null"),
181 Self::Bool => f.write_str("bool"),
182 Self::Int => f.write_str("int"),
183 Self::Float => f.write_str("float"),
184 Self::String => f.write_str("string"),
185 Self::Array => f.write_str("array"),
186 Self::Object => f.write_str("object"),
187 }
188 }
189}
190
191#[derive(Debug, Clone, Eq, PartialEq)]
193pub enum JiterErrorType {
194 JsonError(JsonErrorType),
195 WrongType { expected: JsonType, actual: JsonType },
196}
197
198impl std::fmt::Display for JiterErrorType {
199 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 match self {
201 Self::JsonError(error_type) => write!(f, "{error_type}"),
202 Self::WrongType { expected, actual } => {
203 write!(f, "expected {expected} but found {actual}")
204 }
205 }
206 }
207}
208
209#[derive(Debug, Clone, Eq, PartialEq)]
211pub struct JiterError {
212 pub error_type: JiterErrorType,
213 pub index: usize,
214}
215
216impl std::fmt::Display for JiterError {
217 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
218 write!(f, "{} at index {}", self.error_type, self.index)
219 }
220}
221
222impl JiterError {
223 pub(crate) fn new(error_type: JiterErrorType, index: usize) -> Self {
224 Self { error_type, index }
225 }
226
227 pub fn get_position(&self, jiter: &Jiter) -> LinePosition {
228 jiter.error_position(self.index)
229 }
230
231 pub fn description(&self, jiter: &Jiter) -> String {
232 let position = self.get_position(jiter);
233 format!("{} at {}", self.error_type, position)
234 }
235
236 pub(crate) fn wrong_type(expected: JsonType, actual: JsonType, index: usize) -> Self {
237 Self::new(JiterErrorType::WrongType { expected, actual }, index)
238 }
239}
240
241impl From<JsonError> for JiterError {
242 fn from(error: JsonError) -> Self {
243 Self {
244 error_type: JiterErrorType::JsonError(error.error_type),
245 index: error.index,
246 }
247 }
248}
249
250#[derive(Debug, Clone, PartialEq, Eq)]
252pub struct LinePosition {
253 pub line: usize,
255 pub column: usize,
257}
258
259impl std::fmt::Display for LinePosition {
260 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
261 write!(f, "line {} column {}", self.line, self.column)
262 }
263}
264
265impl LinePosition {
266 pub fn new(line: usize, column: usize) -> Self {
267 Self { line, column }
268 }
269
270 pub fn find(json_data: &[u8], find: usize) -> Self {
272 let mut line = 1;
273 let mut last_line_start = 0;
274 let mut index = 0;
275 while let Some(next) = json_data.get(index) {
276 if *next == b'\n' {
277 line += 1;
278 last_line_start = index + 1;
279 }
280 if index == find {
281 return Self {
282 line,
283 column: index + 1 - last_line_start,
284 };
285 }
286 index += 1;
287 }
288 Self {
289 line,
290 column: index.saturating_sub(last_line_start),
291 }
292 }
293
294 pub fn short(&self) -> String {
295 format!("{}:{}", self.line, self.column)
296 }
297}