Skip to content

Commit

Permalink
Improve error messages when deserializing enums
Browse files Browse the repository at this point in the history
  • Loading branch information
avandecreme committed Nov 20, 2024
1 parent 0903de4 commit 0f23dc5
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 6 deletions.
14 changes: 10 additions & 4 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1873,7 +1873,14 @@ impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer<R> {
Some(b'{') => {
check_recursion! {
self.eat_char();
let ret = visitor.visit_enum(VariantAccess::new(self));
let ret = match tri!(self.parse_whitespace()) {
Some(b'}') => Err(self.fix_position(de::Error::invalid_value(
Unexpected::Other("empty map"),
&"enum variant",
))),
Some(_) => visitor.visit_enum(VariantAccess::new(self)),
None => Err(self.error(ErrorCode::EofWhileParsingObject)),
};
}
let value = tri!(ret);

Expand All @@ -1882,12 +1889,11 @@ impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer<R> {
self.eat_char();
Ok(value)
}
Some(_) => Err(self.error(ErrorCode::ExpectedSomeValue)),
Some(_) => Err(self.error(ErrorCode::ExpectedObjectCommaOrEnd)),
None => Err(self.error(ErrorCode::EofWhileParsingObject)),
}
}
Some(b'"') => visitor.visit_enum(UnitVariantAccess::new(self)),
Some(_) => Err(self.peek_error(ErrorCode::ExpectedSomeValue)),
Some(_) => visitor.visit_enum(UnitVariantAccess::new(self)),
None => Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
}
}
Expand Down
44 changes: 42 additions & 2 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ enum Animal {
AntHive(Vec<String>),
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
enum BoardGame {
Chess,
Checkers,
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
struct Inner {
a: (),
Expand Down Expand Up @@ -1304,12 +1310,15 @@ fn test_parse_option() {
fn test_parse_enum_errors() {
test_parse_err::<Animal>(
&[
("{}", "expected value at line 1 column 2"),
("[]", "expected value at line 1 column 1"),
("{}", "invalid value: empty map, expected enum variant at line 1 column 1"),
("[]", "invalid type: sequence, expected variant identifier at line 1 column 0"),
("true", "invalid type: boolean `true`, expected variant identifier at line 1 column 4"),
("\"unknown\"",
"unknown variant `unknown`, expected one of `Dog`, `Frog`, `Cat`, `AntHive` at line 1 column 9"),
("{\"unknown\":null}",
"unknown variant `unknown`, expected one of `Dog`, `Frog`, `Cat`, `AntHive` at line 1 column 10"),
("{\"AntHive\": []", "EOF while parsing an object at line 1 column 14"),
("{\"AntHive\": []\"", "expected `,` or `}` at line 1 column 14"),
("{\"Dog\":", "EOF while parsing a value at line 1 column 7"),
("{\"Dog\":}", "expected value at line 1 column 8"),
("{\"Dog\":{}}", "invalid type: map, expected unit at line 1 column 7"),
Expand All @@ -1331,6 +1340,37 @@ fn test_parse_enum_errors() {
);
}

#[test]
fn test_parse_value_less_enum_errors() {
test_parse_err::<BoardGame>(&[
(
"1",
"invalid type: integer `1`, expected variant identifier at line 1 column 1",
),
(
"null",
"invalid type: null, expected variant identifier at line 1 column 4",
),
(
"true",
"invalid type: boolean `true`, expected variant identifier at line 1 column 4",
),
(
"[]",
"invalid type: sequence, expected variant identifier at line 1 column 0",
),
("{}", "invalid value: empty map, expected enum variant"),
(
"{\"unknown\": \"unknown\"}",
"unknown variant `unknown`, expected `Chess` or `Checkers` at line 1 column 10",
),
(
"{\"Chess\": \"unknown\"}",
"invalid type: string \"unknown\", expected unit at line 1 column 19",
),
]);
}

#[test]
fn test_parse_enum() {
test_parse_ok(vec![
Expand Down

0 comments on commit 0f23dc5

Please sign in to comment.