diff --git a/serde/src/de/content.rs b/serde/src/de/content.rs index fa8875c8..59c3f8ae 100644 --- a/serde/src/de/content.rs +++ b/serde/src/de/content.rs @@ -35,9 +35,9 @@ use de::{ /// /// Not public API. Use serde-value instead. #[derive(Debug)] -pub enum Content { +pub enum Content { // Don't mind the PhantomData, just need to use E somewhere. - Bool(bool, PhantomData), + Bool(bool), U8(u8), U16(u16), @@ -57,36 +57,26 @@ pub enum Content { Bytes(Vec), None, - Some(Box>), + Some(Box), Unit, - Newtype(Box>), - Seq(Vec>), - Map(Vec<(Content, Content)>), + Newtype(Box), + Seq(Vec), + Map(Vec<(Content, Content)>), } -impl Deserialize for Content { +impl Deserialize for Content { fn deserialize(deserializer: D) -> Result { // Untagged and internally tagged enums are only supported in // self-describing formats. - deserializer.deserialize(ContentVisitor::new()) + deserializer.deserialize(ContentVisitor) } } -struct ContentVisitor { - err: PhantomData, -} +struct ContentVisitor; -impl ContentVisitor { - fn new() -> Self { - ContentVisitor { - err: PhantomData, - } - } -} - -impl Visitor for ContentVisitor { - type Value = Content; +impl Visitor for ContentVisitor { + type Value = Content; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str("any value") @@ -95,7 +85,7 @@ impl Visitor for ContentVisitor { fn visit_bool(self, value: bool) -> Result where F: de::Error { - Ok(Content::Bool(value, PhantomData)) + Ok(Content::Bool(value)) } fn visit_i8(self, value: i8) -> Result @@ -242,27 +232,25 @@ impl Visitor for ContentVisitor { /// This is the type of the map keys in an internally tagged enum. /// /// Not public API. -pub enum TagOrContent { +pub enum TagOrContent { Tag, - Content(Content), + Content(Content), } -struct TagOrContentVisitor { +struct TagOrContentVisitor { name: &'static str, - err: PhantomData, } -impl TagOrContentVisitor { +impl TagOrContentVisitor { fn new(name: &'static str) -> Self { TagOrContentVisitor { name: name, - err: PhantomData, } } } -impl DeserializeSeed for TagOrContentVisitor { - type Value = TagOrContent; +impl DeserializeSeed for TagOrContentVisitor { + type Value = TagOrContent; fn deserialize(self, deserializer: D) -> Result where D: Deserializer @@ -273,8 +261,8 @@ impl DeserializeSeed for TagOrContentVisitor { } } -impl Visitor for TagOrContentVisitor { - type Value = TagOrContent; +impl Visitor for TagOrContentVisitor { + type Value = TagOrContent; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "a type tag `{}` or any other value", self.name) @@ -283,73 +271,73 @@ impl Visitor for TagOrContentVisitor { fn visit_bool(self, value: bool) -> Result where F: de::Error { - ContentVisitor::new().visit_bool(value).map(TagOrContent::Content) + ContentVisitor.visit_bool(value).map(TagOrContent::Content) } fn visit_i8(self, value: i8) -> Result where F: de::Error { - ContentVisitor::new().visit_i8(value).map(TagOrContent::Content) + ContentVisitor.visit_i8(value).map(TagOrContent::Content) } fn visit_i16(self, value: i16) -> Result where F: de::Error { - ContentVisitor::new().visit_i16(value).map(TagOrContent::Content) + ContentVisitor.visit_i16(value).map(TagOrContent::Content) } fn visit_i32(self, value: i32) -> Result where F: de::Error { - ContentVisitor::new().visit_i32(value).map(TagOrContent::Content) + ContentVisitor.visit_i32(value).map(TagOrContent::Content) } fn visit_i64(self, value: i64) -> Result where F: de::Error { - ContentVisitor::new().visit_i64(value).map(TagOrContent::Content) + ContentVisitor.visit_i64(value).map(TagOrContent::Content) } fn visit_u8(self, value: u8) -> Result where F: de::Error { - ContentVisitor::new().visit_u8(value).map(TagOrContent::Content) + ContentVisitor.visit_u8(value).map(TagOrContent::Content) } fn visit_u16(self, value: u16) -> Result where F: de::Error { - ContentVisitor::new().visit_u16(value).map(TagOrContent::Content) + ContentVisitor.visit_u16(value).map(TagOrContent::Content) } fn visit_u32(self, value: u32) -> Result where F: de::Error { - ContentVisitor::new().visit_u32(value).map(TagOrContent::Content) + ContentVisitor.visit_u32(value).map(TagOrContent::Content) } fn visit_u64(self, value: u64) -> Result where F: de::Error { - ContentVisitor::new().visit_u64(value).map(TagOrContent::Content) + ContentVisitor.visit_u64(value).map(TagOrContent::Content) } fn visit_f32(self, value: f32) -> Result where F: de::Error { - ContentVisitor::new().visit_f32(value).map(TagOrContent::Content) + ContentVisitor.visit_f32(value).map(TagOrContent::Content) } fn visit_f64(self, value: f64) -> Result where F: de::Error { - ContentVisitor::new().visit_f64(value).map(TagOrContent::Content) + ContentVisitor.visit_f64(value).map(TagOrContent::Content) } fn visit_char(self, value: char) -> Result where F: de::Error { - ContentVisitor::new().visit_char(value).map(TagOrContent::Content) + ContentVisitor.visit_char(value).map(TagOrContent::Content) } fn visit_str(self, value: &str) -> Result @@ -358,7 +346,7 @@ impl Visitor for TagOrContentVisitor { if value == self.name { Ok(TagOrContent::Tag) } else { - ContentVisitor::new().visit_str(value).map(TagOrContent::Content) + ContentVisitor.visit_str(value).map(TagOrContent::Content) } } @@ -368,7 +356,7 @@ impl Visitor for TagOrContentVisitor { if value == self.name { Ok(TagOrContent::Tag) } else { - ContentVisitor::new().visit_string(value).map(TagOrContent::Content) + ContentVisitor.visit_string(value).map(TagOrContent::Content) } } @@ -378,7 +366,7 @@ impl Visitor for TagOrContentVisitor { if value == self.name.as_bytes() { Ok(TagOrContent::Tag) } else { - ContentVisitor::new().visit_bytes(value).map(TagOrContent::Content) + ContentVisitor.visit_bytes(value).map(TagOrContent::Content) } } @@ -388,84 +376,82 @@ impl Visitor for TagOrContentVisitor { if value == self.name.as_bytes() { Ok(TagOrContent::Tag) } else { - ContentVisitor::new().visit_byte_buf(value).map(TagOrContent::Content) + ContentVisitor.visit_byte_buf(value).map(TagOrContent::Content) } } fn visit_unit(self) -> Result where F: de::Error { - ContentVisitor::new().visit_unit().map(TagOrContent::Content) + ContentVisitor.visit_unit().map(TagOrContent::Content) } fn visit_none(self) -> Result where F: de::Error { - ContentVisitor::new().visit_none().map(TagOrContent::Content) + ContentVisitor.visit_none().map(TagOrContent::Content) } fn visit_some(self, deserializer: D) -> Result where D: Deserializer { - ContentVisitor::new().visit_some(deserializer).map(TagOrContent::Content) + ContentVisitor.visit_some(deserializer).map(TagOrContent::Content) } fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer { - ContentVisitor::new().visit_newtype_struct(deserializer).map(TagOrContent::Content) + ContentVisitor.visit_newtype_struct(deserializer).map(TagOrContent::Content) } fn visit_seq(self, visitor: V) -> Result where V: SeqVisitor { - ContentVisitor::new().visit_seq(visitor).map(TagOrContent::Content) + ContentVisitor.visit_seq(visitor).map(TagOrContent::Content) } fn visit_map(self, visitor: V) -> Result where V: MapVisitor { - ContentVisitor::new().visit_map(visitor).map(TagOrContent::Content) + ContentVisitor.visit_map(visitor).map(TagOrContent::Content) } fn visit_enum(self, visitor: V) -> Result where V: EnumVisitor { - ContentVisitor::new().visit_enum(visitor).map(TagOrContent::Content) + ContentVisitor.visit_enum(visitor).map(TagOrContent::Content) } } /// Used by generated code to deserialize an internally tagged enum. /// /// Not public API. -pub struct TaggedContent { +pub struct TaggedContent { pub tag: T, - pub content: Content, + pub content: Content, } /// Not public API. -pub struct TaggedContentVisitor { +pub struct TaggedContentVisitor { tag_name: &'static str, tag: PhantomData, - err: PhantomData, } -impl TaggedContentVisitor { +impl TaggedContentVisitor { /// Visitor for the content of an internally tagged enum with the given tag /// name. pub fn new(name: &'static str) -> Self { TaggedContentVisitor { tag_name: name, tag: PhantomData, - err: PhantomData, } } } -impl DeserializeSeed for TaggedContentVisitor +impl DeserializeSeed for TaggedContentVisitor where T: Deserialize { - type Value = TaggedContent; + type Value = TaggedContent; fn deserialize(self, deserializer: D) -> Result where D: Deserializer @@ -476,10 +462,10 @@ impl DeserializeSeed for TaggedContentVisitor } } -impl Visitor for TaggedContentVisitor +impl Visitor for TaggedContentVisitor where T: Deserialize { - type Value = TaggedContent; + type Value = TaggedContent; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str("any value") @@ -518,9 +504,15 @@ impl Visitor for TaggedContentVisitor } } +/// Not public API +pub struct ContentDeserializer { + content: Content, + err: PhantomData, +} + /// Used when deserializing an internally tagged enum because the content will /// be used exactly once. -impl Deserializer for Content +impl Deserializer for ContentDeserializer where E: de::Error { type Error = E; @@ -528,8 +520,8 @@ impl Deserializer for Content fn deserialize(self, visitor: V) -> Result where V: Visitor { - match self { - Content::Bool(v, _) => visitor.visit_bool(v), + match self.content { + Content::Bool(v) => visitor.visit_bool(v), Content::U8(v) => visitor.visit_u8(v), Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), @@ -544,17 +536,17 @@ impl Deserializer for Content Content::String(v) => visitor.visit_string(v), Content::Unit => visitor.visit_unit(), Content::None => visitor.visit_none(), - Content::Some(v) => visitor.visit_some(*v), - Content::Newtype(v) => visitor.visit_newtype_struct(*v), + 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(); + 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(); + 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()); @@ -567,9 +559,9 @@ impl Deserializer for Content fn deserialize_option(self, visitor: V) -> Result where V: Visitor { - match self { + match self.content { Content::None => visitor.visit_none(), - Content::Some(v) => visitor.visit_some(*v), + Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), Content::Unit => visitor.visit_unit(), _ => visitor.visit_some(self) } @@ -588,19 +580,25 @@ impl Deserializer for Content } } -impl de::value::ValueDeserializer for Content - where E: de::Error -{ - type Deserializer = Self; - - fn into_deserializer(self) -> Self { - self +impl ContentDeserializer { + /// private API, don't use + pub fn new(content: Content) -> Self { + ContentDeserializer { + content: content, + err: PhantomData, + } } } +/// Not public API. +pub struct ContentRefDeserializer<'a, E> { + content: &'a Content, + err: PhantomData, +} + /// Used when deserializing an untagged enum because the content may need to be /// used more than once. -impl<'a, E> Deserializer for &'a Content +impl<'a, E> Deserializer for ContentRefDeserializer<'a, E> where E: de::Error { type Error = E; @@ -608,8 +606,8 @@ impl<'a, E> Deserializer for &'a Content fn deserialize(self, visitor: V) -> Result where V: Visitor { - match *self { - Content::Bool(v, _) => visitor.visit_bool(v), + match *self.content { + Content::Bool(v) => visitor.visit_bool(v), Content::U8(v) => visitor.visit_u8(v), Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), @@ -624,17 +622,17 @@ impl<'a, E> Deserializer for &'a Content Content::String(ref v) => visitor.visit_str(v), Content::Unit => visitor.visit_unit(), Content::None => visitor.visit_none(), - Content::Some(ref v) => visitor.visit_some(&**v), - Content::Newtype(ref v) => visitor.visit_newtype_struct(&**v), + Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), + Content::Newtype(ref v) => visitor.visit_newtype_struct(ContentRefDeserializer::new(v)), Content::Seq(ref v) => { - let seq = v.into_iter(); + let seq = v.into_iter().map(ContentRefDeserializer::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(ref v) => { - let map = v.into_iter().map(|&(ref k, ref v)| (k, v)); + let map = v.into_iter().map(|&(ref k, ref v)| (ContentRefDeserializer::new(k), ContentRefDeserializer::new(v))); let mut map_visitor = de::value::MapDeserializer::new(map); let value = try!(visitor.visit_map(&mut map_visitor)); try!(map_visitor.end()); @@ -647,9 +645,9 @@ impl<'a, E> Deserializer for &'a Content fn deserialize_option(self, visitor: V) -> Result where V: Visitor { - match *self { + match *self.content { Content::None => visitor.visit_none(), - Content::Some(ref v) => visitor.visit_some(&**v), + Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), Content::Unit => visitor.visit_unit(), _ => visitor.visit_some(self) } @@ -668,7 +666,27 @@ impl<'a, E> Deserializer for &'a Content } } -impl<'a, E> de::value::ValueDeserializer for &'a Content +impl<'a, E> ContentRefDeserializer<'a, E> { + /// private API, don't use + pub fn new(content: &'a Content) -> Self { + ContentRefDeserializer { + content: content, + err: PhantomData, + } + } +} + +impl de::value::ValueDeserializer for ContentDeserializer + where E: de::Error +{ + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + +impl<'a, E> de::value::ValueDeserializer for ContentRefDeserializer<'a, E> where E: de::Error { type Deserializer = Self; diff --git a/serde/src/de/private.rs b/serde/src/de/private.rs index 750eecdc..566c4b11 100644 --- a/serde/src/de/private.rs +++ b/serde/src/de/private.rs @@ -5,6 +5,8 @@ use de::{Deserialize, Deserializer, Error, Visitor}; #[cfg(any(feature = "std", feature = "collections"))] pub use de::content::{ Content, + ContentRefDeserializer, + ContentDeserializer, TaggedContentVisitor, InternallyTaggedUnitVisitor, UntaggedUnitVisitor, diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index b72d78ad..95abd5f0 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -704,7 +704,7 @@ fn deserialize_internally_tagged_enum( ty.clone(), variant, item_attrs, - quote!(_tagged.content), + quote!(_serde::de::private::ContentDeserializer::<__D::Error>::new(_tagged.content)), ); quote! { @@ -719,7 +719,7 @@ fn deserialize_internally_tagged_enum( let _tagged = try!(_serde::Deserializer::deserialize( deserializer, - _serde::de::private::TaggedContentVisitor::<__Field, __D::Error>::new(#tag))); + _serde::de::private::TaggedContentVisitor::<__Field>::new(#tag))); match _tagged.tag { #(#variant_arms)* @@ -743,7 +743,7 @@ fn deserialize_untagged_enum( ty.clone(), variant, item_attrs, - quote!(&_content), + quote!(_serde::de::private::ContentRefDeserializer::<__D::Error>::new(&_content)), ) }); @@ -756,7 +756,7 @@ fn deserialize_untagged_enum( let fallthrough_msg = format!("data did not match any variant of untagged enum {}", type_ident); quote!({ - let _content = try!(<_serde::de::private::Content<__D::Error> as _serde::Deserialize>::deserialize(deserializer)); + let _content = try!(<_serde::de::private::Content as _serde::Deserialize>::deserialize(deserializer)); #( if let _serde::export::Ok(ok) = #attempts {