From 2fe9a860cd704dc29ec5d76ba7fa73cc4e4e669e Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 19 Aug 2017 10:29:54 -0700 Subject: [PATCH] Inform serializers about skipped fields. Closes #960. --- serde/src/ser/mod.rs | 12 ++++++++++++ serde_derive/src/ser.rs | 28 +++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index 4356f930..4a1fbfb7 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -1727,6 +1727,12 @@ pub trait SerializeStruct { where T: Serialize; + /// Indicate that a struct field has been skipped. + fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { + let _ = key; + Ok(()) + } + /// Finish serializing a struct. fn end(self) -> Result; } @@ -1772,6 +1778,12 @@ pub trait SerializeStructVariant { where T: Serialize; + /// Indicate that a struct variant field has been skipped. + fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { + let _ = key; + Ok(()) + } + /// Finish serializing a struct variant. fn end(self) -> Result; } diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 9be9bddc..9c3310be 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -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 { 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)); + } + } + } } }, )