diff --git a/serde/src/de/ignored_any.rs b/serde/src/de/ignored_any.rs index 855d68e1a..68a644e0d 100644 --- a/serde/src/de/ignored_any.rs +++ b/serde/src/de/ignored_any.rs @@ -1,6 +1,8 @@ use lib::*; -use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; +use de::{ + Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor, +}; /// An efficient way of discarding data from a deserializer. /// @@ -205,6 +207,13 @@ impl<'de> Visitor<'de> for IgnoredAny { let _ = bytes; Ok(IgnoredAny) } + + fn visit_enum(self, data: A) -> Result + where + A: EnumAccess<'de>, + { + data.variant::()?.1.newtype_variant() + } } impl<'de> Deserialize<'de> for IgnoredAny { diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index f1f7739d0..90e0f3951 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -124,6 +124,19 @@ enum EnumOther { Other, } +#[derive(PartialEq, Debug)] +struct IgnoredAny; + +impl<'de> Deserialize<'de> for IgnoredAny { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + serde::de::IgnoredAny::deserialize(deserializer)?; + Ok(IgnoredAny) + } +} + ////////////////////////////////////////////////////////////////////////// macro_rules! declare_tests { @@ -929,6 +942,21 @@ declare_tests! { Token::SeqEnd, ], } + test_ignored_any { + IgnoredAny => &[ + Token::Str("s"), + ], + IgnoredAny => &[ + Token::Seq { len: Some(1) }, + Token::Bool(true), + Token::SeqEnd, + ], + IgnoredAny => &[ + Token::Enum { name: "E" }, + Token::Str("Rust"), + Token::Unit, + ], + } } declare_tests! { diff --git a/test_suite/tests/test_ignored_any.rs b/test_suite/tests/test_ignored_any.rs new file mode 100644 index 000000000..921cdfc79 --- /dev/null +++ b/test_suite/tests/test_ignored_any.rs @@ -0,0 +1,104 @@ +use serde::de::value::{Error, MapDeserializer, SeqDeserializer}; +use serde::de::{ + DeserializeSeed, EnumAccess, IgnoredAny, IntoDeserializer, VariantAccess, Visitor, +}; +use serde::{forward_to_deserialize_any, Deserialize, Deserializer}; + +#[derive(PartialEq, Debug, Deserialize)] +enum Target { + Unit, + Newtype(i32), + Tuple(i32, i32), + Struct { a: i32 }, +} + +struct Enum(&'static str); + +impl<'de> Deserializer<'de> for Enum { + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_enum(self) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +impl<'de> EnumAccess<'de> for Enum { + type Error = Error; + type Variant = Self; + + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: DeserializeSeed<'de>, + { + let v = seed.deserialize(self.0.into_deserializer())?; + Ok((v, self)) + } +} + +impl<'de> VariantAccess<'de> for Enum { + type Error = Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + seed.deserialize(10i32.into_deserializer()) + } + + fn tuple_variant(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + let seq = SeqDeserializer::new(vec![1i32, 2].into_iter()); + visitor.visit_seq(seq) + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let map = MapDeserializer::new(vec![("a", 10i32)].into_iter()); + visitor.visit_map(map) + } +} + +#[test] +fn test_deserialize_enum() { + // First just make sure the Deserializer impl works + assert_eq!(Target::Unit, Target::deserialize(Enum("Unit")).unwrap()); + assert_eq!( + Target::Newtype(10), + Target::deserialize(Enum("Newtype")).unwrap() + ); + assert_eq!( + Target::Tuple(1, 2), + Target::deserialize(Enum("Tuple")).unwrap() + ); + assert_eq!( + Target::Struct { a: 10 }, + Target::deserialize(Enum("Struct")).unwrap() + ); + + // Now try IgnoredAny + IgnoredAny::deserialize(Enum("Unit")).unwrap(); + IgnoredAny::deserialize(Enum("Newtype")).unwrap(); + IgnoredAny::deserialize(Enum("Tuple")).unwrap(); + IgnoredAny::deserialize(Enum("Struct")).unwrap(); +}