mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-09 20:11:01 +00:00
feat(codegen): Detect repeated struct field when deserializing
This commit is contained in:
@@ -46,6 +46,12 @@ pub trait Error: Sized + error::Error {
|
|||||||
fn missing_field(field: &'static str) -> Self {
|
fn missing_field(field: &'static str) -> Self {
|
||||||
Error::custom(format!("Missing field `{}`", field))
|
Error::custom(format!("Missing field `{}`", field))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Raised when a `Deserialize` struct type received more than one of the
|
||||||
|
/// same struct field.
|
||||||
|
fn duplicate_field(field: &'static str) -> Self {
|
||||||
|
Error::custom(format!("Duplicate field `{}`", field))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Type` represents all the primitive types that can be deserialized. This is used by
|
/// `Type` represents all the primitive types that can be deserialized. This is used by
|
||||||
|
|||||||
@@ -1156,6 +1156,9 @@ fn deserialize_map(
|
|||||||
let value_arms = fields_attrs_names.iter()
|
let value_arms = fields_attrs_names.iter()
|
||||||
.filter(|&&(_, ref attrs, _)| !attrs.skip_deserializing_field())
|
.filter(|&&(_, ref attrs, _)| !attrs.skip_deserializing_field())
|
||||||
.map(|&(field, ref attrs, name)| {
|
.map(|&(field, ref attrs, name)| {
|
||||||
|
let deser_name = attrs.name().deserialize_name();
|
||||||
|
let name_str = builder.expr().lit().str(deser_name);
|
||||||
|
|
||||||
let visit = match attrs.deserialize_with() {
|
let visit = match attrs.deserialize_with() {
|
||||||
None => {
|
None => {
|
||||||
let field_ty = &field.ty;
|
let field_ty = &field.ty;
|
||||||
@@ -1173,6 +1176,9 @@ fn deserialize_map(
|
|||||||
};
|
};
|
||||||
quote_arm!(cx,
|
quote_arm!(cx,
|
||||||
__Field::$name => {
|
__Field::$name => {
|
||||||
|
if $name.is_some() {
|
||||||
|
return Err(<__V::Error as _serde::de::Error>::duplicate_field($name_str));
|
||||||
|
}
|
||||||
$name = Some($visit);
|
$name = Some($visit);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -725,4 +725,32 @@ declare_error_tests! {
|
|||||||
],
|
],
|
||||||
Error::UnexpectedToken(Token::SeqSep),
|
Error::UnexpectedToken(Token::SeqSep),
|
||||||
}
|
}
|
||||||
|
test_duplicate_field_struct<Struct> {
|
||||||
|
vec![
|
||||||
|
Token::MapStart(Some(3)),
|
||||||
|
Token::MapSep,
|
||||||
|
Token::Str("a"),
|
||||||
|
Token::I32(1),
|
||||||
|
|
||||||
|
Token::MapSep,
|
||||||
|
Token::Str("a"),
|
||||||
|
Token::I32(3),
|
||||||
|
Token::MapEnd,
|
||||||
|
],
|
||||||
|
Error::DuplicateFieldError("a"),
|
||||||
|
}
|
||||||
|
test_duplicate_field_enum<Enum> {
|
||||||
|
vec![
|
||||||
|
Token::EnumMapStart("Enum", "Map", Some(3)),
|
||||||
|
Token::EnumMapSep,
|
||||||
|
Token::Str("a"),
|
||||||
|
Token::I32(1),
|
||||||
|
|
||||||
|
Token::EnumMapSep,
|
||||||
|
Token::Str("a"),
|
||||||
|
Token::I32(3),
|
||||||
|
Token::EnumMapEnd,
|
||||||
|
],
|
||||||
|
Error::DuplicateFieldError("a"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -410,6 +410,7 @@ pub enum Error {
|
|||||||
UnknownFieldError(String),
|
UnknownFieldError(String),
|
||||||
UnknownVariantError(String),
|
UnknownVariantError(String),
|
||||||
MissingFieldError(&'static str),
|
MissingFieldError(&'static str),
|
||||||
|
DuplicateFieldError(&'static str),
|
||||||
InvalidName(&'static str),
|
InvalidName(&'static str),
|
||||||
InvalidValue(String),
|
InvalidValue(String),
|
||||||
UnexpectedToken(Token<'static>),
|
UnexpectedToken(Token<'static>),
|
||||||
@@ -429,6 +430,10 @@ impl de::Error for Error {
|
|||||||
|
|
||||||
fn end_of_stream() -> Error { Error::EndOfStreamError }
|
fn end_of_stream() -> Error { Error::EndOfStreamError }
|
||||||
|
|
||||||
|
fn invalid_value(msg: &str) -> Error {
|
||||||
|
Error::InvalidValue(msg.to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
fn unknown_field(field: &str) -> Error {
|
fn unknown_field(field: &str) -> Error {
|
||||||
Error::UnknownFieldError(field.to_owned())
|
Error::UnknownFieldError(field.to_owned())
|
||||||
}
|
}
|
||||||
@@ -440,6 +445,10 @@ impl de::Error for Error {
|
|||||||
fn missing_field(field: &'static str) -> Error {
|
fn missing_field(field: &'static str) -> Error {
|
||||||
Error::MissingFieldError(field)
|
Error::MissingFieldError(field)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn duplicate_field(field: &'static str) -> Error {
|
||||||
|
Error::DuplicateFieldError(field)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
|
|||||||
Reference in New Issue
Block a user