diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs
index 11050648..142502b7 100644
--- a/serde/src/de/mod.rs
+++ b/serde/src/de/mod.rs
@@ -32,10 +32,19 @@ pub trait Error: Sized + error::Error {
fn end_of_stream() -> Self;
/// Raised when a `Deserialize` struct type received an unexpected struct field.
- fn unknown_field(field: &str) -> Self;
+ fn unknown_field(field: &str) -> Self {
+ Error::syntax(&format!("Unknown field `{}`", field))
+ }
- /// Raised when a `Deserialize` struct type did not receive a field.
- fn missing_field(field: &'static str) -> Self;
+ /// Raised when a `Deserialize` enum type received an unexpected variant.
+ fn unknown_variant(field: &str) -> Self {
+ Error::syntax(&format!("Unknown variant `{}`", field))
+ }
+
+ /// raised when a `deserialize` struct type did not receive a field.
+ fn missing_field(field: &'static str) -> Self {
+ Error::syntax(&format!("Missing field `{}`", field))
+ }
}
/// `Type` represents all the primitive types that can be deserialized. This is used by
diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs
index bc53153e..a94fd02b 100644
--- a/serde_codegen/src/de.rs
+++ b/serde_codegen/src/de.rs
@@ -566,6 +566,7 @@ fn deserialize_item_enum(
.collect()
),
container_attrs,
+ true,
);
let variants_expr = builder.expr().ref_().slice()
@@ -807,6 +808,7 @@ fn deserialize_field_visitor(
builder: &aster::AstBuilder,
field_names: Vec
>,
container_attrs: &attr::ContainerAttrs,
+ is_variant: bool,
) -> Vec
> {
// Create the field names for the fields.
let field_idents: Vec = (0 .. field_names.len())
@@ -838,10 +840,16 @@ fn deserialize_field_visitor(
})
.collect();
+ let (index_error_msg, unknown_ident) = if is_variant {
+ (builder.expr().str("expected a variant"), builder.id("unknown_variant"))
+ } else {
+ (builder.expr().str("expected a field"), builder.id("unknown_field"))
+ };
+
let index_body = quote_expr!(cx,
match value {
$index_field_arms
- _ => { Err(::serde::de::Error::syntax("expected a field")) }
+ _ => { Err(::serde::de::Error::syntax($index_error_msg)) }
}
);
@@ -853,10 +861,10 @@ fn deserialize_field_visitor(
})
.collect();
- let fallthrough_arm_expr = if !container_attrs.deny_unknown_fields() {
+ let fallthrough_arm_expr = if !is_variant && !container_attrs.deny_unknown_fields() {
quote_expr!(cx, Ok(__Field::__ignore))
} else {
- quote_expr!(cx, Err(::serde::de::Error::unknown_field(value)))
+ quote_expr!(cx, Err(::serde::de::Error::$unknown_ident(value)))
};
let str_body = quote_expr!(cx,
@@ -947,7 +955,8 @@ fn deserialize_struct_visitor(
cx,
builder,
try!(field_exprs),
- container_attrs
+ container_attrs,
+ false,
);
let visit_map_expr = try!(deserialize_map(
diff --git a/serde_tests/tests/test_de.rs b/serde_tests/tests/test_de.rs
index dcc6e8f0..568bfaea 100644
--- a/serde_tests/tests/test_de.rs
+++ b/serde_tests/tests/test_de.rs
@@ -8,7 +8,13 @@ use num::rational::Ratio;
use serde::de::{Deserializer, Visitor};
-use token::{Token, assert_de_tokens, assert_de_tokens_ignore};
+use token::{
+ Error,
+ Token,
+ assert_de_tokens,
+ assert_de_tokens_ignore,
+ assert_de_tokens_error,
+};
//////////////////////////////////////////////////////////////////////////
@@ -600,3 +606,13 @@ declare_tests! {
],
}
}
+
+#[test]
+fn test_enum_error() {
+ assert_de_tokens_error::(
+ vec![
+ Token::EnumUnit("Enum", "Foo"),
+ ],
+ Error::UnknownVariantError("Foo".to_owned()),
+ )
+}
diff --git a/serde_tests/tests/token.rs b/serde_tests/tests/token.rs
index 40810d47..30d623be 100644
--- a/serde_tests/tests/token.rs
+++ b/serde_tests/tests/token.rs
@@ -371,6 +371,7 @@ pub enum Error {
SyntaxError,
EndOfStreamError,
UnknownFieldError(String),
+ UnknownVariantError(String),
MissingFieldError(&'static str),
InvalidName(&'static str),
InvalidValue(String),
@@ -395,6 +396,10 @@ impl de::Error for Error {
Error::UnknownFieldError(field.to_owned())
}
+ fn unknown_variant(variant: &str) -> Error {
+ Error::UnknownVariantError(variant.to_owned())
+ }
+
fn missing_field(field: &'static str) -> Error {
Error::MissingFieldError(field)
}