@@ -11,38 +11,149 @@ use serde::ser;
11
11
/// This type represents all possible errors that can occur when serializing or
12
12
/// deserializing JSON data.
13
13
pub struct Error {
14
+ /// This `Box` allows us to keep the size of `Error` as small as possible. A
15
+ /// larger `Error` type was substantially slower due to all the functions
16
+ /// that pass around `Result<T, Error>`.
14
17
err : Box < ErrorImpl > ,
15
18
}
16
19
17
20
/// Alias for a `Result` with the error type `serde_json::Error`.
18
21
pub type Result < T > = result:: Result < T , Error > ;
19
22
20
- enum ErrorImpl {
21
- /// The JSON value had some syntatic error.
22
- Syntax ( ErrorCode , usize , usize ) ,
23
+ impl Error {
24
+ /// One-based line number at which the error was detected.
25
+ ///
26
+ /// Characters in the first line of the input (before the first newline
27
+ /// character) are in line 1.
28
+ pub fn line ( & self ) -> usize {
29
+ self . err . line
30
+ }
23
31
24
- /// Some IO error occurred when serializing or deserializing a value.
25
- Io ( io:: Error ) ,
32
+ /// One-based column number at which the error was detected.
33
+ ///
34
+ /// The first character in the input and any characters immediately
35
+ /// following a newline character are in column 1.
36
+ ///
37
+ /// Note that errors may occur in column 0, for example if a read from an IO
38
+ /// stream fails immediately following a previously read newline character.
39
+ pub fn column ( & self ) -> usize {
40
+ self . err . column
41
+ }
42
+
43
+ /// Categorizes the cause of this error.
44
+ ///
45
+ /// - `Category::Io` - failure to read or write bytes on an IO stream
46
+ /// - `Category::Syntax` - input that is not syntactically valid JSON
47
+ /// - `Category::Data` - input data that is semantically incorrect
48
+ /// - `Category::Eof` - unexpected end of the input data
49
+ pub fn classify ( & self ) -> Category {
50
+ match self . err . code {
51
+ ErrorCode :: Message ( _) => Category :: Data ,
52
+ ErrorCode :: Io ( _) => Category :: Io ,
53
+ ErrorCode :: EofWhileParsingList |
54
+ ErrorCode :: EofWhileParsingObject |
55
+ ErrorCode :: EofWhileParsingString |
56
+ ErrorCode :: EofWhileParsingValue => Category :: Eof ,
57
+ ErrorCode :: ExpectedColon |
58
+ ErrorCode :: ExpectedListCommaOrEnd |
59
+ ErrorCode :: ExpectedObjectCommaOrEnd |
60
+ ErrorCode :: ExpectedSomeIdent |
61
+ ErrorCode :: ExpectedSomeValue |
62
+ ErrorCode :: ExpectedSomeString |
63
+ ErrorCode :: InvalidEscape |
64
+ ErrorCode :: InvalidNumber |
65
+ ErrorCode :: NumberOutOfRange |
66
+ ErrorCode :: InvalidUnicodeCodePoint |
67
+ ErrorCode :: KeyMustBeAString |
68
+ ErrorCode :: LoneLeadingSurrogateInHexEscape |
69
+ ErrorCode :: TrailingCharacters |
70
+ ErrorCode :: UnexpectedEndOfHexEscape |
71
+ ErrorCode :: RecursionLimitExceeded => Category :: Syntax ,
72
+ }
73
+ }
74
+
75
+ /// Returns true if this error was caused by a failure to read or write
76
+ /// bytes on an IO stream.
77
+ pub fn is_io ( & self ) -> bool {
78
+ self . classify ( ) == Category :: Io
79
+ }
80
+
81
+ /// Returns true if this error was caused by input that was not
82
+ /// syntactically valid JSON.
83
+ pub fn is_syntax ( & self ) -> bool {
84
+ self . classify ( ) == Category :: Syntax
85
+ }
86
+
87
+ /// Returns true if this error was caused by input data that was
88
+ /// semantically incorrect.
89
+ ///
90
+ /// For example, JSON containing a number is semantically incorrect when the
91
+ /// type being deserialized into holds a String.
92
+ pub fn is_data ( & self ) -> bool {
93
+ self . classify ( ) == Category :: Data
94
+ }
95
+
96
+ /// Returns true if this error was caused by prematurely reaching the end of
97
+ /// the input data.
98
+ ///
99
+ /// Callers that process streaming input may be interested in retrying the
100
+ /// deserialization once more data is available.
101
+ pub fn is_eof ( & self ) -> bool {
102
+ self . classify ( ) == Category :: Eof
103
+ }
104
+ }
105
+
106
+ /// Categorizes the cause of a `serde_json::Error`.
107
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
108
+ pub enum Category {
109
+ /// The error was caused by a failure to read or write bytes on an IO
110
+ /// stream.
111
+ Io ,
112
+
113
+ /// The error was caused by input that was not syntactically valid JSON.
114
+ Syntax ,
115
+
116
+ /// The error was caused by input data that was semantically incorrect.
117
+ ///
118
+ /// For example, JSON containing a number is semantically incorrect when the
119
+ /// type being deserialized into holds a String.
120
+ Data ,
121
+
122
+ /// The error was caused by prematurely reaching the end of the input data.
123
+ ///
124
+ /// Callers that process streaming input may be interested in retrying the
125
+ /// deserialization once more data is available.
126
+ Eof ,
127
+ }
128
+
129
+ #[ derive( Debug ) ]
130
+ struct ErrorImpl {
131
+ code : ErrorCode ,
132
+ line : usize ,
133
+ column : usize ,
26
134
}
27
135
28
136
// Not public API. Should be pub(crate).
29
137
#[ doc( hidden) ]
30
- #[ derive( Clone , PartialEq , Debug ) ]
138
+ #[ derive( Debug ) ]
31
139
pub enum ErrorCode {
32
140
/// Catchall for syntax error messages
33
141
Message ( String ) ,
34
142
143
+ /// Some IO error occurred while serializing or deserializing.
144
+ Io ( io:: Error ) ,
145
+
35
146
/// EOF while parsing a list.
36
- EOFWhileParsingList ,
147
+ EofWhileParsingList ,
37
148
38
149
/// EOF while parsing an object.
39
- EOFWhileParsingObject ,
150
+ EofWhileParsingObject ,
40
151
41
152
/// EOF while parsing a string.
42
- EOFWhileParsingString ,
153
+ EofWhileParsingString ,
43
154
44
155
/// EOF while parsing a JSON value.
45
- EOFWhileParsingValue ,
156
+ EofWhileParsingValue ,
46
157
47
158
/// Expected this character to be a `':'`.
48
159
ExpectedColon ,
@@ -93,9 +204,9 @@ pub enum ErrorCode {
93
204
impl Error {
94
205
// Not public API. Should be pub(crate).
95
206
#[ doc( hidden) ]
96
- pub fn syntax ( code : ErrorCode , line : usize , col : usize ) -> Self {
207
+ pub fn syntax ( code : ErrorCode , line : usize , column : usize ) -> Self {
97
208
Error {
98
- err : Box :: new ( ErrorImpl :: Syntax ( code, line, col ) ) ,
209
+ err : Box :: new ( ErrorImpl { code : code, line : line , column : column } ) ,
99
210
}
100
211
}
101
212
@@ -104,8 +215,8 @@ impl Error {
104
215
pub fn fix_position < F > ( self , f : F ) -> Self
105
216
where F : FnOnce ( ErrorCode ) -> Error
106
217
{
107
- if let ErrorImpl :: Syntax ( code , 0 , 0 ) = * self . err {
108
- f ( code)
218
+ if self . err . line == 0 {
219
+ f ( self . err . code )
109
220
} else {
110
221
self
111
222
}
@@ -115,17 +226,18 @@ impl Error {
115
226
impl Display for ErrorCode {
116
227
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
117
228
match * self {
118
- ErrorCode :: Message ( ref msg) => write ! ( f, "{}" , msg) ,
119
- ErrorCode :: EOFWhileParsingList => {
229
+ ErrorCode :: Message ( ref msg) => f. write_str ( msg) ,
230
+ ErrorCode :: Io ( ref err) => Display :: fmt ( err, f) ,
231
+ ErrorCode :: EofWhileParsingList => {
120
232
f. write_str ( "EOF while parsing a list" )
121
233
}
122
- ErrorCode :: EOFWhileParsingObject => {
234
+ ErrorCode :: EofWhileParsingObject => {
123
235
f. write_str ( "EOF while parsing an object" )
124
236
}
125
- ErrorCode :: EOFWhileParsingString => {
237
+ ErrorCode :: EofWhileParsingString => {
126
238
f. write_str ( "EOF while parsing a string" )
127
239
}
128
- ErrorCode :: EOFWhileParsingValue => {
240
+ ErrorCode :: EofWhileParsingValue => {
129
241
f. write_str ( "EOF while parsing a value" )
130
242
}
131
243
ErrorCode :: ExpectedColon => {
@@ -179,56 +291,44 @@ impl Display for ErrorCode {
179
291
180
292
impl error:: Error for Error {
181
293
fn description ( & self ) -> & str {
182
- match * self . err {
183
- ErrorImpl :: Syntax ( ..) => {
294
+ match self . err . code {
295
+ ErrorCode :: Io ( ref err) => error:: Error :: description ( err) ,
296
+ _ => {
184
297
// If you want a better message, use Display::fmt or to_string().
185
298
"JSON error"
186
299
}
187
- ErrorImpl :: Io ( ref error) => error:: Error :: description ( error) ,
188
300
}
189
301
}
190
302
191
303
fn cause ( & self ) -> Option < & error:: Error > {
192
- match * self . err {
193
- ErrorImpl :: Io ( ref error ) => Some ( error ) ,
304
+ match self . err . code {
305
+ ErrorCode :: Io ( ref err ) => Some ( err ) ,
194
306
_ => None ,
195
307
}
196
308
}
197
309
}
198
310
199
311
impl Display for Error {
200
- fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
201
- match * self . err {
202
- ErrorImpl :: Syntax ( ref code, line, col) => {
203
- if line == 0 && col == 0 {
204
- write ! ( fmt, "{}" , code)
205
- } else {
206
- write ! ( fmt, "{} at line {} column {}" , code, line, col)
207
- }
208
- }
209
- ErrorImpl :: Io ( ref error) => fmt:: Display :: fmt ( error, fmt) ,
312
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
313
+ Display :: fmt ( & * self . err , f)
314
+ }
315
+ }
316
+
317
+ impl Display for ErrorImpl {
318
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
319
+ if self . line == 0 {
320
+ Display :: fmt ( & self . code , f)
321
+ } else {
322
+ write ! ( f, "{} at line {} column {}" , self . code, self . line, self . column)
210
323
}
211
324
}
212
325
}
213
326
214
327
// Remove two layers of verbosity from the debug representation. Humans often
215
328
// end up seeing this representation because it is what unwrap() shows.
216
329
impl Debug for Error {
217
- fn fmt ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
218
- match * self . err {
219
- ErrorImpl :: Syntax ( ref code, ref line, ref col) => {
220
- formatter. debug_tuple ( "Syntax" )
221
- . field ( code)
222
- . field ( line)
223
- . field ( col)
224
- . finish ( )
225
- }
226
- ErrorImpl :: Io ( ref io) => {
227
- formatter. debug_tuple ( "Io" )
228
- . field ( io)
229
- . finish ( )
230
- }
231
- }
330
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
331
+ Debug :: fmt ( & * self . err , f)
232
332
}
233
333
}
234
334
@@ -243,31 +343,31 @@ impl From<ErrorImpl> for Error {
243
343
impl From < io:: Error > for Error {
244
344
fn from ( error : io:: Error ) -> Error {
245
345
Error {
246
- err : Box :: new ( ErrorImpl :: Io ( error) ) ,
346
+ err : Box :: new ( ErrorImpl { code : ErrorCode :: Io ( error) , line : 0 , column : 0 } ) ,
247
347
}
248
348
}
249
349
}
250
350
251
351
impl From < de:: value:: Error > for Error {
252
352
fn from ( error : de:: value:: Error ) -> Error {
253
353
Error {
254
- err : Box :: new ( ErrorImpl :: Syntax ( ErrorCode :: Message ( error. to_string ( ) ) , 0 , 0 ) ) ,
354
+ err : Box :: new ( ErrorImpl { code : ErrorCode :: Message ( error. to_string ( ) ) , line : 0 , column : 0 } ) ,
255
355
}
256
356
}
257
357
}
258
358
259
359
impl de:: Error for Error {
260
360
fn custom < T : Display > ( msg : T ) -> Error {
261
361
Error {
262
- err : Box :: new ( ErrorImpl :: Syntax ( ErrorCode :: Message ( msg. to_string ( ) ) , 0 , 0 ) ) ,
362
+ err : Box :: new ( ErrorImpl { code : ErrorCode :: Message ( msg. to_string ( ) ) , line : 0 , column : 0 } ) ,
263
363
}
264
364
}
265
365
}
266
366
267
367
impl ser:: Error for Error {
268
368
fn custom < T : Display > ( msg : T ) -> Error {
269
369
Error {
270
- err : Box :: new ( ErrorImpl :: Syntax ( ErrorCode :: Message ( msg. to_string ( ) ) , 0 , 0 ) ) ,
370
+ err : Box :: new ( ErrorImpl { code : ErrorCode :: Message ( msg. to_string ( ) ) , line : 0 , column : 0 } ) ,
271
371
}
272
372
}
273
373
}
0 commit comments