mirror of
https://github.com/serde-rs/serde.git
synced 2025-10-02 15:25:38 +00:00
Correctly calculate has_flatten
attribute in all cases for deserialization
Consequence: `FlattenSkipDeserializing[DenyUnknown]` - does not collect data in Field, because do not read them anyway - gets `deserialize_in_place` method - gets ability to deserialize from sequence (visit_seq method) - uses `deserialize_struct` instead of `deserialize_map`
This commit is contained in:
parent
0647a7c1fe
commit
fd5b5e9aa5
@ -285,13 +285,7 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
|||||||
deserialize_struct(params, fields, &cont.attrs, StructForm::Struct)
|
deserialize_struct(params, fields, &cont.attrs, StructForm::Struct)
|
||||||
}
|
}
|
||||||
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
|
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
|
||||||
deserialize_tuple(
|
deserialize_tuple(params, fields, &cont.attrs, TupleForm::Tuple)
|
||||||
params,
|
|
||||||
fields,
|
|
||||||
&cont.attrs,
|
|
||||||
cont.attrs.has_flatten(),
|
|
||||||
TupleForm::Tuple,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
|
Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
|
||||||
}
|
}
|
||||||
@ -465,11 +459,10 @@ fn deserialize_tuple(
|
|||||||
params: &Parameters,
|
params: &Parameters,
|
||||||
fields: &[Field],
|
fields: &[Field],
|
||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
has_flatten: bool,
|
|
||||||
form: TupleForm,
|
form: TupleForm,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
assert!(
|
assert!(
|
||||||
!has_flatten,
|
!has_flatten(fields),
|
||||||
"tuples and tuple variants cannot have flatten fields"
|
"tuples and tuple variants cannot have flatten fields"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -590,7 +583,7 @@ fn deserialize_tuple_in_place(
|
|||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
assert!(
|
assert!(
|
||||||
!cattrs.has_flatten(),
|
!has_flatten(fields),
|
||||||
"tuples and tuple variants cannot have flatten fields"
|
"tuples and tuple variants cannot have flatten fields"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -972,9 +965,7 @@ fn deserialize_struct(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let has_flatten = fields
|
let has_flatten = has_flatten(fields);
|
||||||
.iter()
|
|
||||||
.any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing());
|
|
||||||
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten);
|
let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs, has_flatten);
|
||||||
|
|
||||||
// untagged struct variants do not get a visit_seq method. The same applies to
|
// untagged struct variants do not get a visit_seq method. The same applies to
|
||||||
@ -1114,7 +1105,7 @@ fn deserialize_struct_in_place(
|
|||||||
) -> Option<Fragment> {
|
) -> Option<Fragment> {
|
||||||
// for now we do not support in_place deserialization for structs that
|
// for now we do not support in_place deserialization for structs that
|
||||||
// are represented as map.
|
// are represented as map.
|
||||||
if cattrs.has_flatten() {
|
if has_flatten(fields) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1830,7 +1821,6 @@ fn deserialize_externally_tagged_variant(
|
|||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
cattrs,
|
cattrs,
|
||||||
variant.attrs.has_flatten(),
|
|
||||||
TupleForm::ExternallyTagged(variant_ident),
|
TupleForm::ExternallyTagged(variant_ident),
|
||||||
),
|
),
|
||||||
Style::Struct => deserialize_struct(
|
Style::Struct => deserialize_struct(
|
||||||
@ -1930,7 +1920,6 @@ fn deserialize_untagged_variant(
|
|||||||
params,
|
params,
|
||||||
&variant.fields,
|
&variant.fields,
|
||||||
cattrs,
|
cattrs,
|
||||||
variant.attrs.has_flatten(),
|
|
||||||
TupleForm::Untagged(variant_ident, deserializer),
|
TupleForm::Untagged(variant_ident, deserializer),
|
||||||
),
|
),
|
||||||
Style::Struct => deserialize_struct(
|
Style::Struct => deserialize_struct(
|
||||||
@ -2703,7 +2692,7 @@ fn deserialize_map_in_place(
|
|||||||
cattrs: &attr::Container,
|
cattrs: &attr::Container,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
assert!(
|
assert!(
|
||||||
!cattrs.has_flatten(),
|
!has_flatten(fields),
|
||||||
"inplace deserialization of maps does not support flatten fields"
|
"inplace deserialization of maps does not support flatten fields"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -3038,6 +3027,13 @@ fn effective_style(variant: &Variant) -> Style {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True if there are fields that is not skipped and has a `#[serde(flatten)]` attribute.
|
||||||
|
fn has_flatten(fields: &[Field]) -> bool {
|
||||||
|
fields
|
||||||
|
.iter()
|
||||||
|
.any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing())
|
||||||
|
}
|
||||||
|
|
||||||
struct DeImplGenerics<'a>(&'a Parameters);
|
struct DeImplGenerics<'a>(&'a Parameters);
|
||||||
#[cfg(feature = "deserialize_in_place")]
|
#[cfg(feature = "deserialize_in_place")]
|
||||||
struct InPlaceImplGenerics<'a>(&'a Parameters);
|
struct InPlaceImplGenerics<'a>(&'a Parameters);
|
||||||
|
@ -85,7 +85,6 @@ impl<'a> Container<'a> {
|
|||||||
for field in &mut variant.fields {
|
for field in &mut variant.fields {
|
||||||
if field.attrs.flatten() {
|
if field.attrs.flatten() {
|
||||||
has_flatten = true;
|
has_flatten = true;
|
||||||
variant.attrs.mark_has_flatten();
|
|
||||||
}
|
}
|
||||||
field.attrs.rename_by_rules(
|
field.attrs.rename_by_rules(
|
||||||
variant
|
variant
|
||||||
|
@ -810,18 +810,6 @@ pub struct Variant {
|
|||||||
rename_all_rules: RenameAllRules,
|
rename_all_rules: RenameAllRules,
|
||||||
ser_bound: Option<Vec<syn::WherePredicate>>,
|
ser_bound: Option<Vec<syn::WherePredicate>>,
|
||||||
de_bound: Option<Vec<syn::WherePredicate>>,
|
de_bound: Option<Vec<syn::WherePredicate>>,
|
||||||
/// True if variant is a struct variant which contains a field with
|
|
||||||
/// `#[serde(flatten)]`.
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// enum Enum {
|
|
||||||
/// Variant {
|
|
||||||
/// #[serde(flatten)]
|
|
||||||
/// some_field: (),
|
|
||||||
/// },
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
has_flatten: bool,
|
|
||||||
skip_deserializing: bool,
|
skip_deserializing: bool,
|
||||||
skip_serializing: bool,
|
skip_serializing: bool,
|
||||||
other: bool,
|
other: bool,
|
||||||
@ -991,7 +979,6 @@ impl Variant {
|
|||||||
},
|
},
|
||||||
ser_bound: ser_bound.get(),
|
ser_bound: ser_bound.get(),
|
||||||
de_bound: de_bound.get(),
|
de_bound: de_bound.get(),
|
||||||
has_flatten: false,
|
|
||||||
skip_deserializing: skip_deserializing.get(),
|
skip_deserializing: skip_deserializing.get(),
|
||||||
skip_serializing: skip_serializing.get(),
|
skip_serializing: skip_serializing.get(),
|
||||||
other: other.get(),
|
other: other.get(),
|
||||||
@ -1034,14 +1021,6 @@ impl Variant {
|
|||||||
self.de_bound.as_ref().map(|vec| &vec[..])
|
self.de_bound.as_ref().map(|vec| &vec[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_flatten(&self) -> bool {
|
|
||||||
self.has_flatten
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mark_has_flatten(&mut self) {
|
|
||||||
self.has_flatten = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn skip_deserializing(&self) -> bool {
|
pub fn skip_deserializing(&self) -> bool {
|
||||||
self.skip_deserializing
|
self.skip_deserializing
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user