From 0081cc961d0a14dd89cc68931f225b59e6d2931e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 14 Apr 2018 21:24:44 -0700 Subject: [PATCH] Implement all Content deserializer hints --- serde/src/private/de.rs | 365 +++++++++++++++++++++++++++++++++++----- 1 file changed, 323 insertions(+), 42 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index c9c0cba8..2b68e7a6 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -229,8 +229,8 @@ mod content { use lib::*; use super::size_hint; - use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, MapAccess, SeqAccess, - Unexpected, Visitor}; + use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, MapAccess, + SeqAccess, Unexpected, Visitor}; /// Used from generated code to buffer the contents of the Deserializer when /// deserializing untagged enums and internally tagged enums. @@ -1013,6 +1013,45 @@ mod content { err: PhantomData, } + impl<'de, E> ContentDeserializer<'de, E> + where + E: de::Error, + { + #[cold] + fn invalid_type(self, exp: &Expected) -> E { + de::Error::invalid_type(self.content.unexpected(), exp) + } + } + + fn visit_content_seq<'de, V, E>(content: Vec>, visitor: V) -> Result + where + V: Visitor<'de>, + E: de::Error, + { + let seq = content.into_iter().map(ContentDeserializer::new); + let mut seq_visitor = de::value::SeqDeserializer::new(seq); + let value = try!(visitor.visit_seq(&mut seq_visitor)); + try!(seq_visitor.end()); + Ok(value) + } + + fn visit_content_map<'de, V, E>( + content: Vec<(Content<'de>, Content<'de>)>, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + E: de::Error, + { + let map = content + .into_iter() + .map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v))); + let mut map_visitor = de::value::MapDeserializer::new(map); + let value = try!(visitor.visit_map(&mut map_visitor)); + try!(map_visitor.end()); + Ok(value) + } + /// Used when deserializing an internally tagged enum because the content will /// be used exactly once. impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E> @@ -1046,21 +1085,185 @@ mod content { Content::None => visitor.visit_none(), Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)), - Content::Seq(v) => { - let seq = v.into_iter().map(ContentDeserializer::new); - let mut seq_visitor = de::value::SeqDeserializer::new(seq); - let value = try!(visitor.visit_seq(&mut seq_visitor)); - try!(seq_visitor.end()); - Ok(value) - } - Content::Map(v) => { - let map = v.into_iter() - .map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v))); - let mut map_visitor = de::value::MapDeserializer::new(map); - let value = try!(visitor.visit_map(&mut map_visitor)); - try!(map_visitor.end()); - Ok(value) - } + Content::Seq(v) => visit_content_seq(v, visitor), + Content::Map(v) => visit_content_map(v, visitor), + } + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::Bool(v) => visitor.visit_bool(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::I8(v) => visitor.visit_i8(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::I16(v) => visitor.visit_i16(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::I32(v) => visitor.visit_i32(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_i64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::U8(v) => visitor.visit_u8(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::U16(v) => visitor.visit_u16(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::U32(v) => visitor.visit_u32(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_f32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::F32(v) => visitor.visit_f32(v), + Content::F64(v) => visitor.visit_f64(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_f64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::F64(v) => visitor.visit_f64(v), + Content::U64(v) => visitor.visit_u64(v), + Content::I64(v) => visitor.visit_i64(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::Char(v) => visitor.visit_char(v), + Content::String(v) => visitor.visit_string(v), + Content::Str(v) => visitor.visit_borrowed_str(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::String(v) => visitor.visit_string(v), + Content::Str(v) => visitor.visit_borrowed_str(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_byte_buf(visitor) + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::ByteBuf(v) => visitor.visit_byte_buf(v), + Content::Bytes(v) => visitor.visit_borrowed_bytes(v), + _ => Err(self.invalid_type(&visitor)), } } @@ -1076,6 +1279,44 @@ mod content { } } + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::Unit => visitor.visit_unit(), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match self.content { + // As a special case, allow deserializing untagged newtype + // variant containing unit struct. + // + // #[derive(Deserialize)] + // struct Info; + // + // #[derive(Deserialize)] + // #[serde(tag = "topic")] + // enum Message { + // Info(Info), + // } + // + // We want {"topic":"Info"} to deserialize even though + // ordinarily unit structs do not deserialize from empty map. + Content::Map(ref v) if v.is_empty() => visitor.visit_unit(), + _ => self.deserialize_any(visitor), + } + } + fn deserialize_newtype_struct( self, _name: &str, @@ -1087,6 +1328,61 @@ mod content { visitor.visit_newtype_struct(self) } + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::Seq(v) => visit_content_seq(v, visitor), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::Map(v) => visit_content_map(v, visitor), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match self.content { + Content::Seq(v) => visit_content_seq(v, visitor), + Content::Map(v) => visit_content_map(v, visitor), + _ => Err(self.invalid_type(&visitor)), + } + } + fn deserialize_enum( self, _name: &str, @@ -1129,38 +1425,23 @@ mod content { visitor.visit_enum(EnumDeserializer::new(variant, value)) } - fn deserialize_unit_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result + fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { - // As a special case, allow deserializing untagged newtype - // variant containing unit struct. - // - // #[derive(Deserialize)] - // struct Info; - // - // #[derive(Deserialize)] - // #[serde(tag = "topic")] - // enum Message { - // Info(Info), - // } - // - // We want {"topic":"Info"} to deserialize even though - // ordinarily unit structs do not deserialize from empty map. - Content::Map(ref v) if v.is_empty() => visitor.visit_unit(), - _ => self.deserialize_any(visitor), + Content::String(v) => visitor.visit_string(v), + Content::Str(v) => visitor.visit_borrowed_str(v), + _ => Err(self.invalid_type(&visitor)), } } - forward_to_deserialize_any! { - bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes - byte_buf unit seq tuple tuple_struct map struct identifier - ignored_any + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + drop(self); + visitor.visit_unit() } }