Skip to content

Commit ca8a81a

Browse files
committed
Improve error messages when deserializing enums
1 parent efa66e3 commit ca8a81a

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

src/de.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,7 +1879,14 @@ impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer<R> {
18791879
Some(b'{') => {
18801880
check_recursion! {
18811881
self.eat_char();
1882-
let ret = visitor.visit_enum(VariantAccess::new(self));
1882+
let ret = match tri!(self.parse_whitespace()) {
1883+
Some(b'}') => Err(self.fix_position(de::Error::invalid_value(
1884+
Unexpected::Other("empty map"),
1885+
&"enum variant",
1886+
))),
1887+
Some(_) => visitor.visit_enum(VariantAccess::new(self)),
1888+
None => Err(self.error(ErrorCode::EofWhileParsingObject)),
1889+
};
18831890
}
18841891
let value = tri!(ret);
18851892

@@ -1888,12 +1895,11 @@ impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer<R> {
18881895
self.eat_char();
18891896
Ok(value)
18901897
}
1891-
Some(_) => Err(self.error(ErrorCode::ExpectedSomeValue)),
1898+
Some(_) => Err(self.error(ErrorCode::ExpectedObjectEnd)),
18921899
None => Err(self.error(ErrorCode::EofWhileParsingObject)),
18931900
}
18941901
}
1895-
Some(b'"') => visitor.visit_enum(UnitVariantAccess::new(self)),
1896-
Some(_) => Err(self.peek_error(ErrorCode::ExpectedSomeValue)),
1902+
Some(_) => visitor.visit_enum(UnitVariantAccess::new(self)),
18971903
None => Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
18981904
}
18991905
}

src/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl Error {
6262
ErrorCode::ExpectedColon
6363
| ErrorCode::ExpectedListCommaOrEnd
6464
| ErrorCode::ExpectedObjectCommaOrEnd
65+
| ErrorCode::ExpectedObjectEnd
6566
| ErrorCode::ExpectedSomeIdent
6667
| ErrorCode::ExpectedSomeValue
6768
| ErrorCode::ExpectedDoubleQuote
@@ -261,6 +262,9 @@ pub(crate) enum ErrorCode {
261262
/// Expected this character to be either a `','` or a `'}'`.
262263
ExpectedObjectCommaOrEnd,
263264

265+
/// Expected this character to be `'}'`.
266+
ExpectedObjectEnd,
267+
264268
/// Expected to parse either a `true`, `false`, or a `null`.
265269
ExpectedSomeIdent,
266270

@@ -358,6 +362,7 @@ impl Display for ErrorCode {
358362
ErrorCode::ExpectedColon => f.write_str("expected `:`"),
359363
ErrorCode::ExpectedListCommaOrEnd => f.write_str("expected `,` or `]`"),
360364
ErrorCode::ExpectedObjectCommaOrEnd => f.write_str("expected `,` or `}`"),
365+
ErrorCode::ExpectedObjectEnd => f.write_str("expected `}`"),
361366
ErrorCode::ExpectedSomeIdent => f.write_str("expected ident"),
362367
ErrorCode::ExpectedSomeValue => f.write_str("expected value"),
363368
ErrorCode::ExpectedDoubleQuote => f.write_str("expected `\"`"),

tests/test.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ enum Animal {
7171
AntHive(Vec<String>),
7272
}
7373

74+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
75+
enum BoardGame {
76+
Chess,
77+
Checkers,
78+
}
79+
7480
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
7581
struct Inner {
7682
a: (),
@@ -1305,12 +1311,15 @@ fn test_parse_option() {
13051311
fn test_parse_enum_errors() {
13061312
test_parse_err::<Animal>(
13071313
&[
1308-
("{}", "expected value at line 1 column 2"),
1309-
("[]", "expected value at line 1 column 1"),
1314+
("{}", "invalid value: empty map, expected enum variant at line 1 column 1"),
1315+
("[]", "invalid type: sequence, expected variant identifier at line 1 column 0"),
1316+
("true", "invalid type: boolean `true`, expected variant identifier at line 1 column 4"),
13101317
("\"unknown\"",
13111318
"unknown variant `unknown`, expected one of `Dog`, `Frog`, `Cat`, `AntHive` at line 1 column 9"),
13121319
("{\"unknown\":null}",
13131320
"unknown variant `unknown`, expected one of `Dog`, `Frog`, `Cat`, `AntHive` at line 1 column 10"),
1321+
("{\"AntHive\": []", "EOF while parsing an object at line 1 column 14"),
1322+
("{\"AntHive\": [],", "expected `}` at line 1 column 14"),
13141323
("{\"Dog\":", "EOF while parsing a value at line 1 column 7"),
13151324
("{\"Dog\":}", "expected value at line 1 column 8"),
13161325
("{\"Dog\":{}}", "invalid type: map, expected unit at line 1 column 7"),
@@ -1332,6 +1341,40 @@ fn test_parse_enum_errors() {
13321341
);
13331342
}
13341343

1344+
#[test]
1345+
fn test_parse_value_less_enum_errors() {
1346+
test_parse_err::<BoardGame>(&[
1347+
(
1348+
"1",
1349+
"invalid type: integer `1`, expected variant identifier at line 1 column 1",
1350+
),
1351+
(
1352+
"null",
1353+
"invalid type: null, expected variant identifier at line 1 column 4",
1354+
),
1355+
(
1356+
"true",
1357+
"invalid type: boolean `true`, expected variant identifier at line 1 column 4",
1358+
),
1359+
(
1360+
"[]",
1361+
"invalid type: sequence, expected variant identifier at line 1 column 0",
1362+
),
1363+
(
1364+
"{}",
1365+
"invalid value: empty map, expected enum variant at line 1 column 1",
1366+
),
1367+
(
1368+
"{\"unknown\": \"unknown\"}",
1369+
"unknown variant `unknown`, expected `Chess` or `Checkers` at line 1 column 10",
1370+
),
1371+
(
1372+
"{\"Chess\": \"unknown\"}",
1373+
"invalid type: string \"unknown\", expected unit at line 1 column 19",
1374+
),
1375+
]);
1376+
}
1377+
13351378
#[test]
13361379
fn test_parse_enum() {
13371380
test_parse_ok(vec![

0 commit comments

Comments
 (0)