Merge pull request #1022 from sfackler/skip-field

Inform serializers about skipped fields.
This commit is contained in:
David Tolnay 2017-09-08 09:47:43 -07:00 committed by GitHub
commit 800620e2aa
4 changed files with 66 additions and 24 deletions

View File

@ -1727,6 +1727,13 @@ pub trait SerializeStruct {
where
T: Serialize;
/// Indicate that a struct field has been skipped.
#[inline]
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
let _ = key;
Ok(())
}
/// Finish serializing a struct.
fn end(self) -> Result<Self::Ok, Self::Error>;
}
@ -1772,6 +1779,13 @@ pub trait SerializeStructVariant {
where
T: Serialize;
/// Indicate that a struct variant field has been skipped.
#[inline]
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
let _ = key;
Ok(())
}
/// Finish serializing a struct variant.
fn end(self) -> Result<Self::Ok, Self::Error>;
}

View File

@ -1384,26 +1384,27 @@ fn deserialize_identifier(
"field identifier"
};
let visit_index = if is_variant {
let variant_indices = 0u32..;
let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len());
let visit_index = quote! {
fn visit_u32<__E>(self, __value: u32) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
{
match __value {
#(
#variant_indices => _serde::export::Ok(#constructors),
)*
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value as u64),
&#fallthrough_msg))
}
}
};
Some(visit_index)
let index_expecting = if is_variant {
"variant"
} else {
None
"field"
};
let variant_indices = 0u32..;
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
let visit_index = quote! {
fn visit_u32<__E>(self, __value: u32) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
{
match __value {
#(
#variant_indices => _serde::export::Ok(#constructors),
)*
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value as u64),
&#fallthrough_msg))
}
}
};
let bytes_to_str = if fallthrough.is_some() {

View File

@ -242,6 +242,7 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
params,
false,
quote!(_serde::ser::SerializeStruct::serialize_field),
quote!(_serde::ser::SerializeStruct::skip_field),
);
let type_name = cattrs.name().serialize_name();
@ -707,15 +708,23 @@ fn serialize_struct_variant<'a>(
fields: &[Field],
name: &str,
) -> Fragment {
let method = match context {
let (method, skip_method) = match context {
StructVariant::ExternallyTagged { .. } => {
quote!(_serde::ser::SerializeStructVariant::serialize_field)
(
quote!(_serde::ser::SerializeStructVariant::serialize_field),
quote!(_serde::ser::SerializeStructVariant::skip_field),
)
}
StructVariant::InternallyTagged { .. } |
StructVariant::Untagged => quote!(_serde::ser::SerializeStruct::serialize_field),
StructVariant::Untagged => {
(
quote!(_serde::ser::SerializeStruct::serialize_field),
quote!(_serde::ser::SerializeStruct::skip_field),
)
}
};
let serialize_fields = serialize_struct_visitor(fields, params, true, method);
let serialize_fields = serialize_struct_visitor(fields, params, true, method, skip_method);
let mut serialized_fields = fields
.iter()
@ -829,6 +838,7 @@ fn serialize_struct_visitor(
params: &Parameters,
is_enum: bool,
func: Tokens,
skip_func: Tokens,
) -> Vec<Tokens> {
fields
.iter()
@ -859,7 +869,15 @@ fn serialize_struct_visitor(
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
Some(skip) => {
quote! {
if !#skip {
#ser
} else {
try!(#skip_func(&mut __serde_state, #key_expr));
}
}
}
}
},
)

View File

@ -521,6 +521,15 @@ declare_tests! {
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Map { len: Some(3) },
Token::U32(0),
Token::I32(1),
Token::U32(1),
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 3 },
Token::Str("a"),