1use alloc::string::String;
4use alloc::vec::Vec;
5use core::fmt;
6
7#[non_exhaustive]
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum JsonLimitKind {
13 InputBytes,
15 Depth,
17 StringBytes,
19 KeyBytes,
21 NumberBytes,
23 ArrayItems,
25 ObjectMembers,
27 TotalNodes,
29 TotalDecodedStringBytes,
31}
32
33impl JsonLimitKind {
34 pub const fn as_str(self) -> &'static str {
36 match self {
37 Self::InputBytes => "input bytes",
38 Self::Depth => "nesting depth",
39 Self::StringBytes => "string bytes",
40 Self::KeyBytes => "key bytes",
41 Self::NumberBytes => "number bytes",
42 Self::ArrayItems => "array items",
43 Self::ObjectMembers => "object members",
44 Self::TotalNodes => "total nodes",
45 Self::TotalDecodedStringBytes => "total decoded string bytes",
46 }
47 }
48}
49
50#[non_exhaustive]
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub enum JsonErrorKind {
60 UnexpectedEof,
62 UnexpectedByte,
64 InvalidUtf8,
66 InvalidEscape,
68 InvalidUnicodeEscape,
70 LoneSurrogate,
72 UnescapedControlCharacter,
74 InvalidNumber,
76 DuplicateKey,
78 TrailingData,
80 LimitExceeded(JsonLimitKind),
82 WriteFailure,
84 NonFiniteNumber,
87}
88
89#[derive(Debug, Clone, PartialEq, Eq)]
91pub enum JsonPathSegment {
92 Key(String),
94 Index(usize),
96}
97
98#[derive(Debug, Clone, PartialEq, Eq, Default)]
101pub struct JsonPath {
102 segments: Vec<JsonPathSegment>,
103}
104
105impl JsonPath {
106 pub(crate) fn from_segments(segments: Vec<JsonPathSegment>) -> Self {
107 Self { segments }
108 }
109
110 pub fn segments(&self) -> &[JsonPathSegment] {
112 &self.segments
113 }
114}
115
116impl fmt::Display for JsonPath {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.write_str("$")?;
119 for segment in &self.segments {
120 match segment {
121 JsonPathSegment::Key(key) => write!(f, ".{key}")?,
122 JsonPathSegment::Index(index) => write!(f, "[{index}]")?,
123 }
124 }
125 Ok(())
126 }
127}
128
129#[derive(Debug, Clone, PartialEq, Eq)]
134pub struct JsonError {
135 kind: JsonErrorKind,
136 offset: usize,
137 line: usize,
138 column: usize,
139 path: Option<JsonPath>,
140}
141
142impl JsonError {
143 pub(crate) fn new(kind: JsonErrorKind, offset: usize, line: usize, column: usize) -> Self {
144 Self {
145 kind,
146 offset,
147 line,
148 column,
149 path: None,
150 }
151 }
152
153 pub(crate) fn with_path(mut self, path: JsonPath) -> Self {
154 self.path = Some(path);
155 self
156 }
157
158 #[cfg(feature = "canonical")]
161 pub(crate) fn serialization(kind: JsonErrorKind) -> Self {
162 Self {
163 kind,
164 offset: 0,
165 line: 0,
166 column: 0,
167 path: None,
168 }
169 }
170
171 pub fn kind(&self) -> &JsonErrorKind {
173 &self.kind
174 }
175
176 pub fn offset(&self) -> usize {
178 self.offset
179 }
180
181 pub fn line(&self) -> usize {
183 self.line
184 }
185
186 pub fn column(&self) -> usize {
188 self.column
189 }
190
191 pub fn path(&self) -> Option<&JsonPath> {
193 self.path.as_ref()
194 }
195}
196
197impl fmt::Display for JsonError {
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 let message = match &self.kind {
200 JsonErrorKind::UnexpectedEof => "unexpected end of input",
201 JsonErrorKind::UnexpectedByte => "unexpected byte",
202 JsonErrorKind::InvalidUtf8 => "invalid UTF-8",
203 JsonErrorKind::InvalidEscape => "invalid escape sequence",
204 JsonErrorKind::InvalidUnicodeEscape => "invalid unicode escape",
205 JsonErrorKind::LoneSurrogate => "unpaired UTF-16 surrogate",
206 JsonErrorKind::UnescapedControlCharacter => "unescaped control character in string",
207 JsonErrorKind::InvalidNumber => "invalid number",
208 JsonErrorKind::DuplicateKey => "duplicate object key",
209 JsonErrorKind::TrailingData => "trailing data after JSON value",
210 JsonErrorKind::LimitExceeded(limit) => {
211 write!(
212 f,
213 "limit exceeded: {} at byte {}, line {}, column {}",
214 limit.as_str(),
215 self.offset,
216 self.line,
217 self.column
218 )?;
219 if let Some(path) = &self.path {
220 write!(f, ", path: {path}")?;
221 }
222 return Ok(());
223 }
224 JsonErrorKind::WriteFailure => return f.write_str("failed to write output"),
226 JsonErrorKind::NonFiniteNumber => {
227 return f.write_str("number is not representable as a finite f64");
228 }
229 };
230 write!(
231 f,
232 "{message} at byte {}, line {}, column {}",
233 self.offset, self.line, self.column
234 )?;
235 if let Some(path) = &self.path {
236 write!(f, ", path: {path}")?;
237 }
238 Ok(())
239 }
240}
241
242#[cfg(feature = "std")]
243impl std::error::Error for JsonError {}
244
245#[non_exhaustive]
249#[derive(Debug, Clone, Copy, PartialEq, Eq)]
250pub enum JsonNumberError {
251 OutOfRange,
253 NotAnInteger,
255 NotFinite,
257 InvalidNumber,
259}
260
261impl fmt::Display for JsonNumberError {
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263 f.write_str(match self {
264 Self::OutOfRange => "number out of range for target type",
265 Self::NotAnInteger => "number is not an integer",
266 Self::NotFinite => "number is not finite",
267 Self::InvalidNumber => "not a valid JSON number",
268 })
269 }
270}
271
272#[cfg(feature = "std")]
273impl std::error::Error for JsonNumberError {}
274
275#[non_exhaustive]
279#[derive(Debug, Clone, Copy, PartialEq, Eq)]
280pub enum JsonDecodeErrorKind {
281 UnexpectedType,
283 MissingField,
285 Number,
287}
288
289#[derive(Debug, Clone, Copy, PartialEq, Eq)]
291pub struct JsonDecodeError {
292 kind: JsonDecodeErrorKind,
293 message: &'static str,
294}
295
296impl JsonDecodeError {
297 pub const fn new(kind: JsonDecodeErrorKind, message: &'static str) -> Self {
299 Self { kind, message }
300 }
301
302 pub const fn kind(&self) -> JsonDecodeErrorKind {
304 self.kind
305 }
306
307 pub const fn message(&self) -> &'static str {
309 self.message
310 }
311
312 pub const fn unexpected_type(message: &'static str) -> Self {
314 Self::new(JsonDecodeErrorKind::UnexpectedType, message)
315 }
316
317 pub const fn missing_field(message: &'static str) -> Self {
319 Self::new(JsonDecodeErrorKind::MissingField, message)
320 }
321
322 pub const fn number(message: &'static str) -> Self {
324 Self::new(JsonDecodeErrorKind::Number, message)
325 }
326}
327
328impl fmt::Display for JsonDecodeError {
329 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
330 f.write_str(self.message)
331 }
332}
333
334#[cfg(feature = "std")]
335impl std::error::Error for JsonDecodeError {}
336
337#[non_exhaustive]
342#[derive(Debug, Clone, PartialEq, Eq)]
343pub enum JsonFromStrError {
344 Parse(JsonError),
346 Decode(JsonDecodeError),
348}
349
350impl fmt::Display for JsonFromStrError {
351 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352 match self {
353 Self::Parse(error) => write!(f, "invalid JSON: {error}"),
354 Self::Decode(error) => write!(f, "JSON did not match the target type: {error}"),
355 }
356 }
357}
358
359impl From<JsonError> for JsonFromStrError {
360 fn from(error: JsonError) -> Self {
361 Self::Parse(error)
362 }
363}
364
365impl From<JsonDecodeError> for JsonFromStrError {
366 fn from(error: JsonDecodeError) -> Self {
367 Self::Decode(error)
368 }
369}
370
371#[cfg(feature = "std")]
372impl std::error::Error for JsonFromStrError {}