From b2377d4c0b012573f54772990bcb0a653e3a8688 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 5 Apr 2017 08:54:30 -0700 Subject: [PATCH 1/2] Allow enums in ignored map value in serde_test --- serde_test/src/de.rs | 64 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs index 7a0918f6..5437ffa2 100644 --- a/serde_test/src/de.rs +++ b/serde_test/src/de.rs @@ -132,12 +132,35 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { Some(Token::StructStart(_, len)) => { self.visit_map(Some(len), Token::StructSep, Token::StructEnd, visitor) } + Some(Token::EnumStart(_)) => { + let variant = self.next_token().ok_or(Error::EndOfTokens)?; + let next = *self.tokens.first().ok_or(Error::EndOfTokens)?; + match (variant, next) { + (Token::Str(variant), Token::Unit) => { + self.next_token(); + visitor.visit_str(variant) + } + (Token::Bytes(variant), Token::Unit) => { + self.next_token(); + visitor.visit_bytes(variant) + } + (Token::U32(variant), Token::Unit) => { + self.next_token(); + visitor.visit_u32(variant) + } + (variant, Token::Unit) => { + Err(Error::UnexpectedToken(variant)) + } + (variant, _) => { + visitor.visit_map(EnumMapVisitor::new(self, variant)) + } + } + } Some(Token::EnumUnit(_, variant)) => visitor.visit_str(variant), - Some(Token::EnumStart(variant)) | Some(Token::EnumNewType(_, variant)) | Some(Token::EnumSeqStart(_, variant, _)) | Some(Token::EnumMapStart(_, variant, _)) => { - visitor.visit_map(EnumMapVisitor::new(self, variant)) + visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant))) } Some(token) => Err(Error::UnexpectedToken(token)), None => Err(Error::EndOfTokens), @@ -542,11 +565,11 @@ impl<'de, 'a> VariantVisitor<'de> for DeserializerEnumVisitor<'a, 'de> { struct EnumMapVisitor<'a, 'de: 'a> { de: &'a mut Deserializer<'de>, - variant: Option<&'a str>, + variant: Option, } impl<'a, 'de> EnumMapVisitor<'a, 'de> { - fn new(de: &'a mut Deserializer<'de>, variant: &'a str) -> Self { + fn new(de: &'a mut Deserializer<'de>, variant: Token) -> Self { EnumMapVisitor { de: de, variant: Some(variant), @@ -561,7 +584,18 @@ impl<'de, 'a> MapVisitor<'de> for EnumMapVisitor<'a, 'de> { where K: DeserializeSeed<'de> { match self.variant.take() { - Some(variant) => seed.deserialize(variant.into_deserializer()).map(Some), + Some(Token::Str(variant)) => { + seed.deserialize(variant.into_deserializer()).map(Some) + } + Some(Token::Bytes(variant)) => { + seed.deserialize(BytesDeserializer { value: variant }).map(Some) + } + Some(Token::U32(variant)) => { + seed.deserialize(variant.into_deserializer()).map(Some) + } + Some(other) => { + Err(Error::UnexpectedToken(other)) + } None => Ok(None), } } @@ -600,3 +634,23 @@ impl<'de, 'a> MapVisitor<'de> for EnumMapVisitor<'a, 'de> { } } } + +struct BytesDeserializer { + value: &'static [u8], +} + +impl<'de> de::Deserializer<'de> for BytesDeserializer { + type Error = Error; + + fn deserialize(self, visitor: V) -> Result + where V: de::Visitor<'de> + { + visitor.visit_bytes(self.value) + } + + forward_to_deserialize! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option + seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct + struct struct_field tuple enum ignored_any byte_buf + } +} From c3d9b42cdf402bf249a1b3f272451694cdf21182 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 5 Apr 2017 09:19:22 -0700 Subject: [PATCH 2/2] Fix handling of option and newtype in IgnoredAny --- serde/src/de/ignored_any.rs | 8 ++++---- serde_test/src/de.rs | 3 ++- test_suite/tests/test_de.rs | 17 +++++++++-------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/serde/src/de/ignored_any.rs b/serde/src/de/ignored_any.rs index d51f7386..3ee68433 100644 --- a/serde/src/de/ignored_any.rs +++ b/serde/src/de/ignored_any.rs @@ -53,17 +53,17 @@ impl<'de> Deserialize<'de> for IgnoredAny { } #[inline] - fn visit_some(self, _: D) -> Result + fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de> { - Ok(IgnoredAny) + IgnoredAny::deserialize(deserializer) } #[inline] - fn visit_newtype_struct(self, _: D) -> Result + fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer<'de> { - Ok(IgnoredAny) + IgnoredAny::deserialize(deserializer) } #[inline] diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs index 5437ffa2..28989187 100644 --- a/serde_test/src/de.rs +++ b/serde_test/src/de.rs @@ -111,6 +111,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { Some(Token::Option(true)) => visitor.visit_some(self), Some(Token::Unit) => visitor.visit_unit(), Some(Token::UnitStruct(_name)) => visitor.visit_unit(), + Some(Token::StructNewType(_name)) => visitor.visit_newtype_struct(self), Some(Token::SeqStart(len)) => { self.visit_seq(len, Token::SeqSep, Token::SeqEnd, visitor) } @@ -182,7 +183,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { self.next_token(); visitor.visit_some(self) } - Some(_) => visitor.visit_some(self), + Some(_) => self.deserialize(visitor), None => Err(Error::EndOfTokens), } } diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index f5817f2b..2d012259 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -35,6 +35,9 @@ mod macros; #[derive(Copy, Clone, PartialEq, Debug, Deserialize)] struct UnitStruct; +#[derive(PartialEq, Debug, Deserialize)] +struct NewtypeStruct(i32); + #[derive(PartialEq, Debug, Deserialize)] struct TupleStruct(i32, i32, i32); @@ -166,13 +169,6 @@ fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) { let mut de = serde_test::Deserializer::new(&concated_tokens); let v: Result = Deserialize::deserialize(&mut de); - // We run this test on every token stream for convenience, but - // some token streams don't make sense embedded as a map value, - // so we ignore those. SyntaxError is the real sign of trouble. - if let Err(Error::UnexpectedToken(_)) = v { - return; - } - assert_eq!(v.as_ref(), Ok(&expected)); assert_eq!(de.next_token(), None); } @@ -225,7 +221,6 @@ declare_tests! { test_option { None:: => &[Token::Unit], None:: => &[Token::Option(false)], - Some(1) => &[Token::I32(1)], Some(1) => &[ Token::Option(true), Token::I32(1), @@ -260,6 +255,12 @@ declare_tests! { Token::SeqEnd, ], } + test_newtype_struct { + NewtypeStruct(1) => &[ + Token::StructNewType("NewtypeStruct"), + Token::I32(1), + ], + } test_tuple_struct { TupleStruct(1, 2, 3) => &[ Token::SeqStart(Some(3)),