From 9e8cda4c3773dd1a7878a7af82533c0f441d8511 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 15 Mar 2018 21:11:35 +0100 Subject: [PATCH] Added basic not fully working FlatMapSerializer --- serde/src/private/ser.rs | 245 ++++++++++++++++++++++++++++++++++++++- serde_derive/src/de.rs | 2 +- serde_derive/src/ser.rs | 2 +- 3 files changed, 245 insertions(+), 4 deletions(-) diff --git a/serde/src/private/ser.rs b/serde/src/private/ser.rs index 932ebf4a..5b277852 100644 --- a/serde/src/private/ser.rs +++ b/serde/src/private/ser.rs @@ -58,10 +58,11 @@ enum Unsupported { ByteArray, Optional, Unit, + UnitStruct, + NewtypeStruct, Sequence, Tuple, TupleStruct, - #[cfg(not(any(feature = "std", feature = "alloc")))] Enum, } @@ -76,10 +77,11 @@ impl Display for Unsupported { Unsupported::ByteArray => formatter.write_str("a byte array"), Unsupported::Optional => formatter.write_str("an optional"), Unsupported::Unit => formatter.write_str("unit"), + Unsupported::UnitStruct => formatter.write_str("unit struct"), + Unsupported::NewtypeStruct => formatter.write_str("newtype struct"), Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"), - #[cfg(not(any(feature = "std", feature = "alloc")))] Unsupported::Enum => formatter.write_str("an enum"), } } @@ -1028,3 +1030,242 @@ mod content { } } } + +#[cfg(any(feature = "std", feature = "alloc"))] +pub struct FlatMapSerializer(M); + +#[cfg(any(feature = "std", feature = "alloc"))] +impl FlatMapSerializer +where + M: SerializeMap +{ + fn bad_type(self, what: Unsupported) -> M::Error { + ser::Error::custom(format_args!( + "cannot flatten serialize {} values", what + )) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl Serializer for FlatMapSerializer + where M: SerializeMap +{ + type Ok = M::Ok; + type Error = M::Error; + + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeMap = FlatMapSerializeMap; + type SerializeStruct = FlatMapSerializeStruct; + type SerializeTupleVariant = Impossible; + type SerializeStructVariant = Impossible; + + fn serialize_bool(self, _: bool) -> Result { + Err(self.bad_type(Unsupported::Boolean)) + } + + fn serialize_i8(self, _: i8) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_i16(self, _: i16) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_i32(self, _: i32) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_i64(self, _: i64) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_u8(self, _: u8) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_u16(self, _: u16) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_u32(self, _: u32) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_u64(self, _: u64) -> Result { + Err(self.bad_type(Unsupported::Integer)) + } + + fn serialize_f32(self, _: f32) -> Result { + Err(self.bad_type(Unsupported::Float)) + } + + fn serialize_f64(self, _: f64) -> Result { + Err(self.bad_type(Unsupported::Float)) + } + + fn serialize_char(self, _: char) -> Result { + Err(self.bad_type(Unsupported::Char)) + } + + fn serialize_str(self, _: &str) -> Result { + Err(self.bad_type(Unsupported::String)) + } + + fn serialize_bytes(self, _: &[u8]) -> Result { + Err(self.bad_type(Unsupported::ByteArray)) + } + + fn serialize_none(self) -> Result { + Err(self.bad_type(Unsupported::Optional)) + } + + fn serialize_some(self, _: &T) -> Result + where + T: Serialize, + { + Err(self.bad_type(Unsupported::Optional)) + } + + fn serialize_unit(self) -> Result { + Err(self.bad_type(Unsupported::Unit)) + } + + fn serialize_unit_struct(self, _: &'static str) -> Result { + Err(self.bad_type(Unsupported::UnitStruct)) + } + + fn serialize_unit_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + ) -> Result { + Err(self.bad_type(Unsupported::Enum)) + } + + fn serialize_newtype_struct( + self, + _: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + // TODO: can we do better here? + Err(self.bad_type(Unsupported::NewtypeStruct)) + } + + fn serialize_newtype_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + _: &T, + ) -> Result + where + T: Serialize, + { + Err(self.bad_type(Unsupported::Enum)) + } + + fn serialize_seq(self, _: Option) -> Result { + Err(self.bad_type(Unsupported::Sequence)) + } + + fn serialize_tuple(self, _: usize) -> Result { + Err(self.bad_type(Unsupported::Tuple)) + } + + fn serialize_tuple_struct( + self, + _: &'static str, + _: usize, + ) -> Result { + Err(self.bad_type(Unsupported::TupleStruct)) + } + + fn serialize_tuple_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + _: usize, + ) -> Result { + Err(self.bad_type(Unsupported::Enum)) + } + + fn serialize_map(self, _: Option) -> Result { + Ok(FlatMapSerializeMap(self.0)) + } + + fn serialize_struct( + self, + _: &'static str, + _: usize, + ) -> Result { + Ok(FlatMapSerializeStruct(self.0)) + } + + fn serialize_struct_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + _: usize, + ) -> Result { + Err(self.bad_type(Unsupported::Enum)) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +pub struct FlatMapSerializeMap(M); + +#[cfg(any(feature = "std", feature = "alloc"))] +impl ser::SerializeMap for FlatMapSerializeMap + where M: SerializeMap +{ + type Ok = M::Ok; + type Error = M::Error; + + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + self.0.serialize_key(key) + } + + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + self.0.serialize_value(value) + } + + fn end(self) -> Result { + self.0.end() + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +pub struct FlatMapSerializeStruct(M); + +#[cfg(any(feature = "std", feature = "alloc"))] +impl ser::SerializeStruct for FlatMapSerializeStruct + where M: SerializeMap +{ + type Ok = M::Ok; + type Error = M::Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + self.0.serialize_entry(key, value) + } + + fn end(self) -> Result { + self.0.end() + } +} diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index ec2506d4..01ea6bfe 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -2122,7 +2122,7 @@ fn deserialize_map( let field_ty = field.ty; quote! { let #name: #field_ty = try!(_serde::de::Deserialize::deserialize( - _serde::private::de::FlatMapDeserializer::new( + _serde::private::de::FlatMapDeserializer( &mut __collect, _serde::export::PhantomData))); } diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 20d22ff6..9211b144 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -925,7 +925,7 @@ fn serialize_struct_visitor( let span = Span::def_site().located_at(field.original.span()); let ser = if field.attrs.flatten() { quote! { - try!((#field_expr).serialize(_serde::private::ser::FlatSerializer::new(&mut __serde_state))); + try!((#field_expr).serialize(_serde::private::ser::FlatMapSerializer(&mut __serde_state))); } } else { let func = struct_trait.serialize_field(span);