diff --git a/src/de.rs b/src/de.rs index 4080c54ac..62f968952 100644 --- a/src/de.rs +++ b/src/de.rs @@ -1879,7 +1879,14 @@ impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer { 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); @@ -1888,12 +1895,11 @@ impl<'de, R: Read<'de>> de::Deserializer<'de> for &mut Deserializer { self.eat_char(); Ok(value) } - Some(_) => Err(self.error(ErrorCode::ExpectedSomeValue)), + Some(_) => Err(self.error(ErrorCode::ExpectedObjectEnd)), 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)), } } diff --git a/src/error.rs b/src/error.rs index fbf9eb14e..57f2f2902 100644 --- a/src/error.rs +++ b/src/error.rs @@ -62,6 +62,7 @@ impl Error { ErrorCode::ExpectedColon | ErrorCode::ExpectedListCommaOrEnd | ErrorCode::ExpectedObjectCommaOrEnd + | ErrorCode::ExpectedObjectEnd | ErrorCode::ExpectedSomeIdent | ErrorCode::ExpectedSomeValue | ErrorCode::ExpectedDoubleQuote @@ -261,6 +262,9 @@ pub(crate) enum ErrorCode { /// Expected this character to be either a `','` or a `'}'`. ExpectedObjectCommaOrEnd, + /// Expected this character to be `'}'`. + ExpectedObjectEnd, + /// Expected to parse either a `true`, `false`, or a `null`. ExpectedSomeIdent, @@ -358,6 +362,7 @@ impl Display for ErrorCode { ErrorCode::ExpectedColon => f.write_str("expected `:`"), ErrorCode::ExpectedListCommaOrEnd => f.write_str("expected `,` or `]`"), ErrorCode::ExpectedObjectCommaOrEnd => f.write_str("expected `,` or `}`"), + ErrorCode::ExpectedObjectEnd => f.write_str("expected `}`"), ErrorCode::ExpectedSomeIdent => f.write_str("expected ident"), ErrorCode::ExpectedSomeValue => f.write_str("expected value"), ErrorCode::ExpectedDoubleQuote => f.write_str("expected `\"`"), diff --git a/tests/test.rs b/tests/test.rs index d41a2336a..9031a3aff 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -70,6 +70,12 @@ enum Animal { AntHive(Vec), } +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +enum BoardGame { + Chess, + Checkers, +} + #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] struct Inner { a: (), @@ -1304,12 +1310,15 @@ fn test_parse_option() { fn test_parse_enum_errors() { test_parse_err::( &[ - ("{}", "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 `}` 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"), @@ -1331,6 +1340,40 @@ fn test_parse_enum_errors() { ); } +#[test] +fn test_parse_value_less_enum_errors() { + test_parse_err::(&[ + ( + "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 at line 1 column 1", + ), + ( + "{\"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![