Skip to content

Commit 35bc6b9

Browse files
committed
Improve error messages when deserializing enums
1 parent 0903de4 commit 35bc6b9

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
@@ -1873,7 +1873,14 @@ impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer<R> {
18731873
Some(b'{') => {
18741874
check_recursion! {
18751875
self.eat_char();
1876-
let ret = visitor.visit_enum(VariantAccess::new(self));
1876+
let ret = match tri!(self.parse_whitespace()) {
1877+
Some(b'}') => Err(self.fix_position(de::Error::invalid_value(
1878+
Unexpected::Other("empty map"),
1879+
&"enum variant",
1880+
))),
1881+
Some(_) => visitor.visit_enum(VariantAccess::new(self)),
1882+
None => Err(self.error(ErrorCode::EofWhileParsingObject)),
1883+
};
18771884
}
18781885
let value = tri!(ret);
18791886

@@ -1882,12 +1889,11 @@ impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer<R> {
18821889
self.eat_char();
18831890
Ok(value)
18841891
}
1885-
Some(_) => Err(self.error(ErrorCode::ExpectedSomeValue)),
1892+
Some(_) => Err(self.error(ErrorCode::ExpectedObjectEnd)),
18861893
None => Err(self.error(ErrorCode::EofWhileParsingObject)),
18871894
}
18881895
}
1889-
Some(b'"') => visitor.visit_enum(UnitVariantAccess::new(self)),
1890-
Some(_) => Err(self.peek_error(ErrorCode::ExpectedSomeValue)),
1896+
Some(_) => visitor.visit_enum(UnitVariantAccess::new(self)),
18911897
None => Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
18921898
}
18931899
}

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
@@ -70,6 +70,12 @@ enum Animal {
7070
AntHive(Vec<String>),
7171
}
7272

73+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
74+
enum BoardGame {
75+
Chess,
76+
Checkers,
77+
}
78+
7379
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
7480
struct Inner {
7581
a: (),
@@ -1304,12 +1310,15 @@ fn test_parse_option() {
13041310
fn test_parse_enum_errors() {
13051311
test_parse_err::<Animal>(
13061312
&[
1307-
("{}", "expected value at line 1 column 2"),
1308-
("[]", "expected value at line 1 column 1"),
1313+
("{}", "invalid value: empty map, expected enum variant at line 1 column 1"),
1314+
("[]", "invalid type: sequence, expected variant identifier at line 1 column 0"),
1315+
("true", "invalid type: boolean `true`, expected variant identifier at line 1 column 4"),
13091316
("\"unknown\"",
13101317
"unknown variant `unknown`, expected one of `Dog`, `Frog`, `Cat`, `AntHive` at line 1 column 9"),
13111318
("{\"unknown\":null}",
13121319
"unknown variant `unknown`, expected one of `Dog`, `Frog`, `Cat`, `AntHive` at line 1 column 10"),
1320+
("{\"AntHive\": []", "EOF while parsing an object at line 1 column 14"),
1321+
("{\"AntHive\": [],", "expected `}` at line 1 column 14"),
13131322
("{\"Dog\":", "EOF while parsing a value at line 1 column 7"),
13141323
("{\"Dog\":}", "expected value at line 1 column 8"),
13151324
("{\"Dog\":{}}", "invalid type: map, expected unit at line 1 column 7"),
@@ -1331,6 +1340,40 @@ fn test_parse_enum_errors() {
13311340
);
13321341
}
13331342

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

0 commit comments

Comments
 (0)