From 2dddc7796d436b2bfa0d1016d252250a3f7c4d18 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 17 Aug 2024 11:58:28 +0500 Subject: [PATCH] Cover ContentRefDeserializer::deserialize_option --- serde/src/private/de.rs | 7 +++ test_suite/tests/test_enum_untagged.rs | 74 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 6c81b720..5b5d9b6a 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -1898,10 +1898,17 @@ mod content { where V: Visitor<'de>, { + // Covered by tests/test_enum_untagged.rs + // with_optional_field::* match *self.content { Content::None => visitor.visit_none(), Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), Content::Unit => visitor.visit_unit(), + // This case is necessary for formats which does not store marker of optionality of value, + // for example, JSON. When `deserialize_any` is requested from such formats, they will + // report value without using `Visitor::visit_some`, because they do not known in which + // contexts this value will be used. + // RON is example of format which preserve markers. _ => visitor.visit_some(self), } } diff --git a/test_suite/tests/test_enum_untagged.rs b/test_suite/tests/test_enum_untagged.rs index d06002ce..60c62bac 100644 --- a/test_suite/tests/test_enum_untagged.rs +++ b/test_suite/tests/test_enum_untagged.rs @@ -191,6 +191,80 @@ fn newtype_enum() { ); } +// Reaches crate::private::de::content::ContentRefDeserializer::deserialize_option +mod with_optional_field { + use super::*; + + #[derive(Debug, PartialEq, Serialize, Deserialize)] + #[serde(untagged)] + enum Enum { + Struct { optional: Option }, + Null, + } + + #[test] + fn some() { + assert_tokens( + &Enum::Struct { optional: Some(42) }, + &[ + Token::Struct { + name: "Enum", + len: 1, + }, + Token::Str("optional"), + Token::Some, + Token::U32(42), + Token::StructEnd, + ], + ); + } + + #[test] + fn some_without_marker() { + assert_de_tokens( + &Enum::Struct { optional: Some(42) }, + &[ + Token::Struct { + name: "Enum", + len: 1, + }, + Token::Str("optional"), + Token::U32(42), + Token::StructEnd, + ], + ); + } + + #[test] + fn none() { + assert_tokens( + &Enum::Struct { optional: None }, + &[ + Token::Struct { + name: "Enum", + len: 1, + }, + Token::Str("optional"), + Token::None, + Token::StructEnd, + ], + ); + } + + #[test] + fn unit() { + assert_de_tokens( + &Enum::Struct { optional: None }, + &[ + Token::Map { len: None }, + Token::Str("optional"), + Token::Unit, + Token::MapEnd, + ], + ); + } +} + #[test] fn string_and_bytes() { #[derive(Debug, PartialEq, Deserialize)]