From 44bd78d2cb1c0f26ba6e31bb070359ab8abe7eb6 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 25 Aug 2024 17:55:11 +0500 Subject: [PATCH 01/14] Generate final match inside DeserializeSeed implementation (review this commit with "ignore whitespace changes" option on) --- serde_derive/src/de.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 4967e35d1..686a9782a 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1406,19 +1406,47 @@ fn deserialize_internally_tagged_enum( let expecting = format!("internally tagged enum {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); + let this_type = ¶ms.this_type; + let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = + split_with_de_lifetime(params); + let delife = params.borrowed.de_lifetime(); + quote_block! { #variant_visitor #variants_stmt + struct __Seed #de_impl_generics #where_clause { + tag: __Field, + marker: _serde::__private::PhantomData<#this_type #ty_generics>, + lifetime: _serde::__private::PhantomData<&#delife ()>, + } + let (__tag, __content) = _serde::Deserializer::deserialize_any( __deserializer, _serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?; let __deserializer = _serde::__private::de::ContentDeserializer::<__D::Error>::new(__content); - match __tag { - #(#variant_arms)* + impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause { + type Value = #this_type #ty_generics; + + fn deserialize<__D>(self, __deserializer: __D) -> _serde::__private::Result + where + __D: _serde::de::Deserializer<#delife>, + { + match self.tag { + #(#variant_arms)* + } + } } + _serde::de::DeserializeSeed::deserialize( + __Seed { + tag: __tag, + marker: _serde::__private::PhantomData, + lifetime: _serde::__private::PhantomData, + }, + __deserializer + ) } } From aa8da3ef4af6df62753e7f67bef6caa7cadff2b4 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 25 Aug 2024 18:00:40 +0500 Subject: [PATCH 02/14] Move DeserializeSeed implementation above --- serde_derive/src/de.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 686a9782a..d347b9479 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1422,11 +1422,6 @@ fn deserialize_internally_tagged_enum( lifetime: _serde::__private::PhantomData<&#delife ()>, } - let (__tag, __content) = _serde::Deserializer::deserialize_any( - __deserializer, - _serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?; - let __deserializer = _serde::__private::de::ContentDeserializer::<__D::Error>::new(__content); - impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -1439,6 +1434,12 @@ fn deserialize_internally_tagged_enum( } } } + + let (__tag, __content) = _serde::Deserializer::deserialize_any( + __deserializer, + _serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?; + let __deserializer = _serde::__private::de::ContentDeserializer::<__D::Error>::new(__content); + _serde::de::DeserializeSeed::deserialize( __Seed { tag: __tag, From d7cec3b348159bd82ed269a826203d7a8c181f57 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 25 Aug 2024 18:36:32 +0500 Subject: [PATCH 03/14] Produce final result from TaggedContentVisitor --- serde/src/private/de.rs | 16 ++++++++++------ serde_derive/src/de.rs | 29 ++++++++++++++++++----------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 50ae6ed15..70f308480 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -855,9 +855,9 @@ mod content { impl<'de, T> Visitor<'de> for TaggedContentVisitor where - T: Deserialize<'de>, + T: Deserialize<'de> + DeserializeSeed<'de>, { - type Value = (T, Content<'de>); + type Value = T::Value; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str(self.expecting) @@ -867,21 +867,23 @@ mod content { where S: SeqAccess<'de>, { - let tag = match tri!(seq.next_element()) { + let tag: T = match tri!(seq.next_element()) { Some(tag) => tag, None => { return Err(de::Error::missing_field(self.tag_name)); } }; let rest = de::value::SeqAccessDeserializer::new(seq); - Ok((tag, tri!(Content::deserialize(rest)))) + let content = tri!(Content::deserialize(rest)); + + tag.deserialize(ContentDeserializer::::new(content)) } fn visit_map(self, mut map: M) -> Result where M: MapAccess<'de>, { - let mut tag = None; + let mut tag = None::; let mut vec = Vec::<(Content, Content)>::with_capacity(size_hint::cautious::<( Content, Content, @@ -902,7 +904,9 @@ mod content { } match tag { None => Err(de::Error::missing_field(self.tag_name)), - Some(tag) => Ok((tag, Content::Map(vec))), + Some(tag) => { + tag.deserialize(ContentDeserializer::::new(Content::Map(vec))) + } } } } diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index d347b9479..5a8bd3e65 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1422,6 +1422,22 @@ fn deserialize_internally_tagged_enum( lifetime: _serde::__private::PhantomData<&#delife ()>, } + impl #de_impl_generics _serde::de::Deserialize<#delife> for __Seed #de_ty_generics #where_clause { + fn deserialize<__D>(__deserializer: __D) -> _serde::__private::Result + where + __D: _serde::de::Deserializer<#delife>, + { + _serde::__private::Result::map( + __Field::deserialize(__deserializer), + |__tag| __Seed { + tag: __tag, + marker: _serde::__private::PhantomData, + lifetime: _serde::__private::PhantomData, + } + ) + } + } + impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause { type Value = #this_type #ty_generics; @@ -1435,18 +1451,9 @@ fn deserialize_internally_tagged_enum( } } - let (__tag, __content) = _serde::Deserializer::deserialize_any( + _serde::Deserializer::deserialize_any( __deserializer, - _serde::__private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?; - let __deserializer = _serde::__private::de::ContentDeserializer::<__D::Error>::new(__content); - - _serde::de::DeserializeSeed::deserialize( - __Seed { - tag: __tag, - marker: _serde::__private::PhantomData, - lifetime: _serde::__private::PhantomData, - }, - __deserializer + _serde::__private::de::TaggedContentVisitor::<__Seed>::new(#tag, #expecting) ) } } From b1fe66c7ba64cd5a7bb1dca38ec2bff3d77fb7c8 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 3 Oct 2022 21:47:31 +0500 Subject: [PATCH 04/14] Do not buffer content of the internally tagged enums when deserialize from sequence failures (2): newtype_unit_struct unit_variant_with_unknown_fields --- serde/src/private/de.rs | 5 +---- test_suite/tests/test_enum_internally_tagged.rs | 5 +++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 70f308480..61efa3bf6 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -873,10 +873,7 @@ mod content { return Err(de::Error::missing_field(self.tag_name)); } }; - let rest = de::value::SeqAccessDeserializer::new(seq); - let content = tri!(Content::deserialize(rest)); - - tag.deserialize(ContentDeserializer::::new(content)) + tag.deserialize(de::value::SeqAccessDeserializer::new(seq)) } fn visit_map(self, mut map: M) -> Result diff --git a/test_suite/tests/test_enum_internally_tagged.rs b/test_suite/tests/test_enum_internally_tagged.rs index b4d428c4d..c0f0ae105 100644 --- a/test_suite/tests/test_enum_internally_tagged.rs +++ b/test_suite/tests/test_enum_internally_tagged.rs @@ -320,8 +320,9 @@ fn newtype_map() { Token::Seq { len: Some(2) }, Token::Str("NewtypeMap"), // tag Token::Map { len: Some(0) }, - Token::MapEnd, - Token::SeqEnd, + // Tokens that could follow, but assert_de_tokens_error does not want them + // Token::MapEnd, + // Token::SeqEnd, ], "invalid type: sequence, expected a map", ); From f8967fb4de9f331f8d34030021602e669042e744 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 7 Aug 2023 20:11:39 +0500 Subject: [PATCH 05/14] Allow to deserialize unit and unit structs from SeqAccessDeserializer failures (1): unit_variant_with_unknown_fields Fixed (1): newtype_unit_struct --- serde/src/de/value.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 8f9c0b48e..9a979f9d8 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -1202,9 +1202,31 @@ where visitor.visit_seq(self.seq) } + fn deserialize_unit(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + // Covered by tests/test_enum_internally_tagged.rs + // newtype_unit + visitor.visit_unit() + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + // Covered by tests/test_enum_internally_tagged.rs + // newtype_unit_struct + self.deserialize_unit(visitor) + } + 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 + bytes byte_buf option newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } From 2c8ad9e29ca922fdcb9c6b362994ec05501a6181 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 24 Aug 2024 20:26:27 +0500 Subject: [PATCH 06/14] Ensure that sequence is empty in InternallyTaggedUnitVisitor::visit_seq When intermediate buffer is used, we can just ignore data, because it already was read from the original deserializer to the buffer and check for the emptiness was performed in another place. Now we reading directly from the original deserializer and should ensure empty sequence by self. Fixed (1): unit_variant_with_unknown_fields --- serde/src/de/value.rs | 6 +++++- serde/src/private/de.rs | 12 +++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 9a979f9d8..6e60530b4 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -1104,7 +1104,9 @@ where } } -struct ExpectedInSeq(usize); +/// Number of elements still expected in a sequence. Does not include already +/// read elements. +pub(crate) struct ExpectedInSeq(pub usize); impl Expected for ExpectedInSeq { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { @@ -1580,6 +1582,8 @@ where } } +/// Number of elements still expected in a map. Does not include already read +/// elements. struct ExpectedInMap(usize); impl Expected for ExpectedInMap { diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 61efa3bf6..7da5cadb2 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -209,7 +209,7 @@ mod content { use crate::lib::*; use crate::actually_private; - use crate::de::value::{MapDeserializer, SeqDeserializer}; + use crate::de::value::{ExpectedInSeq, MapDeserializer, SeqDeserializer}; use crate::de::{ self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, @@ -2297,11 +2297,17 @@ mod content { ) } - fn visit_seq(self, _: S) -> Result<(), S::Error> + fn visit_seq(self, mut seq: S) -> Result<(), S::Error> where S: SeqAccess<'de>, { - Ok(()) + match tri!(seq.next_element()) { + Some(IgnoredAny) => Err(de::Error::invalid_length( + 1 + seq.size_hint().unwrap_or(0), + &ExpectedInSeq(0), + )), + None => Ok(()), + } } fn visit_map(self, mut access: M) -> Result<(), M::Error> From 3c2b4cefa1626a1a1c6ead6a88c1f33194f88aef Mon Sep 17 00:00:00 2001 From: Mingun Date: Tue, 3 Nov 2020 22:27:36 +0500 Subject: [PATCH 07/14] Allow to deserialize newtype structs from SeqAccessDeserializer --- serde/src/de/value.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 6e60530b4..6aaba6ede 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -1226,9 +1226,16 @@ where self.deserialize_unit(visitor) } + fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_newtype_struct(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 newtype_struct seq tuple + bytes byte_buf option seq tuple tuple_struct map struct enum identifier ignored_any } } From 04de57580155ffff443d68b6a85a6fc48fa44682 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 20 Feb 2021 21:17:47 +0500 Subject: [PATCH 08/14] Extract first iteration - just copy body of loop --- serde/src/private/de.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 7da5cadb2..74a565500 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -885,6 +885,19 @@ mod content { Content, Content, )>(map.size_hint())); + + if let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { + match k { + TagOrContent::Tag => { + tag = Some(tri!(map.next_value())); + } + TagOrContent::Content(key) => { + let v = tri!(map.next_value()); + vec.push((key, v)); + } + } + } + while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { match k { TagOrContent::Tag => { From 712c3853ee464ca4c3acf0c30fd0ebaace0cc870 Mon Sep 17 00:00:00 2001 From: Mingun Date: Mon, 3 Oct 2022 00:31:39 +0500 Subject: [PATCH 09/14] Replace `if let` by `match` --- serde/src/private/de.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 74a565500..1a41e0014 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -886,16 +886,15 @@ mod content { Content, )>(map.size_hint())); - if let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { - match k { - TagOrContent::Tag => { - tag = Some(tri!(map.next_value())); - } - TagOrContent::Content(key) => { - let v = tri!(map.next_value()); - vec.push((key, v)); - } + match tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { + Some(TagOrContent::Tag) => { + tag = Some(tri!(map.next_value())); + } + Some(TagOrContent::Content(key)) => { + let v = tri!(map.next_value()); + vec.push((key, v)); } + None => {} } while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { From 141f2aa93d01b7d695ecc422abfe35050aa55c05 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 20 Feb 2021 21:50:00 +0500 Subject: [PATCH 10/14] Do not buffer content of the internally tagged enums if tag is the first field failures (3): newtype_newtype newtype_unit newtype_unit_struct --- serde/src/private/de.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 1a41e0014..2cfb02fd7 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -209,7 +209,9 @@ mod content { use crate::lib::*; use crate::actually_private; - use crate::de::value::{ExpectedInSeq, MapDeserializer, SeqDeserializer}; + use crate::de::value::{ + ExpectedInSeq, MapAccessDeserializer, MapDeserializer, SeqDeserializer, + }; use crate::de::{ self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, @@ -886,9 +888,13 @@ mod content { Content, )>(map.size_hint())); + // Read the first field. If it is a tag, immediately deserialize the typed data. + // Otherwise, we collect everything until we find the tag, and then deserialize + // using ContentDeserializer. match tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { Some(TagOrContent::Tag) => { - tag = Some(tri!(map.next_value())); + let tag: T = tri!(map.next_value()); + return tag.deserialize(MapAccessDeserializer::new(map)); } Some(TagOrContent::Content(key)) => { let v = tri!(map.next_value()); From 8fb8957e954a8cbd6cbc4b6a1531c69fd1ab2f40 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 24 Aug 2024 19:01:56 +0500 Subject: [PATCH 11/14] Allow to deserialize unit, unit structs and newtype structs from MapAccessDeserializer Fixed (3): newtype_newtype newtype_unit newtype_unit_struct --- serde/src/de/value.rs | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 6aaba6ede..d614d58b3 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -24,7 +24,9 @@ use crate::lib::*; use self::private::{First, Second}; -use crate::de::{self, size_hint, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor}; +use crate::de::{ + self, size_hint, Deserializer, Expected, IgnoredAny, IntoDeserializer, SeqAccess, Visitor, +}; use crate::ser; //////////////////////////////////////////////////////////////////////////////// @@ -1664,6 +1666,42 @@ where visitor.visit_map(self.map) } + fn deserialize_unit(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + // Covered by tests/test_enum_internally_tagged.rs + // newtype_unit + tri!(IgnoredAny.visit_map(self.map)); + visitor.visit_unit() + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + // Covered by tests/test_enum_internally_tagged.rs + // newtype_unit_struct + self.deserialize_unit(visitor) + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + // Covered by tests/test_enum_internally_tagged.rs + // newtype_newtype + visitor.visit_newtype_struct(self) + } + fn deserialize_enum( self, _name: &str, @@ -1678,7 +1716,7 @@ where 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 + bytes byte_buf option seq tuple tuple_struct map struct identifier ignored_any } } From d4d8c2414d22d3cb4ddc6ae8202f459f99065465 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 25 Aug 2024 19:40:41 +0500 Subject: [PATCH 12/14] Do not create vector when tag is the first field (review this commit with "ignore whitespace changes" option on) --- serde/src/private/de.rs | 52 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 2cfb02fd7..2d3cc7fc3 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -882,46 +882,50 @@ mod content { where M: MapAccess<'de>, { - let mut tag = None::; - let mut vec = Vec::<(Content, Content)>::with_capacity(size_hint::cautious::<( - Content, - Content, - )>(map.size_hint())); - // Read the first field. If it is a tag, immediately deserialize the typed data. // Otherwise, we collect everything until we find the tag, and then deserialize // using ContentDeserializer. match tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { Some(TagOrContent::Tag) => { let tag: T = tri!(map.next_value()); - return tag.deserialize(MapAccessDeserializer::new(map)); + tag.deserialize(MapAccessDeserializer::new(map)) } Some(TagOrContent::Content(key)) => { + let mut tag = None::; + let mut vec = Vec::<(Content, Content)>::with_capacity(size_hint::cautious::<( + Content, + Content, + )>( + map.size_hint() + )); + let v = tri!(map.next_value()); vec.push((key, v)); - } - None => {} - } - while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { - match k { - TagOrContent::Tag => { - if tag.is_some() { - return Err(de::Error::duplicate_field(self.tag_name)); + while let Some(k) = + tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) + { + match k { + TagOrContent::Tag => { + if tag.is_some() { + return Err(de::Error::duplicate_field(self.tag_name)); + } + tag = Some(tri!(map.next_value())); + } + TagOrContent::Content(k) => { + let v = tri!(map.next_value()); + vec.push((k, v)); + } } - tag = Some(tri!(map.next_value())); } - TagOrContent::Content(k) => { - let v = tri!(map.next_value()); - vec.push((k, v)); + match tag { + None => Err(de::Error::missing_field(self.tag_name)), + Some(tag) => { + tag.deserialize(ContentDeserializer::::new(Content::Map(vec))) + } } } - } - match tag { None => Err(de::Error::missing_field(self.tag_name)), - Some(tag) => { - tag.deserialize(ContentDeserializer::::new(Content::Map(vec))) - } } } } From 52f95213c4805a9b63876f9af987245099195c71 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sun, 25 Aug 2024 16:21:52 +0500 Subject: [PATCH 13/14] TagOrContent unnecessary public, remove `pub` --- serde/src/private/de.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 2d3cc7fc3..1e3b58a26 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -538,9 +538,7 @@ mod content { } /// This is the type of the map keys in an internally tagged enum. - /// - /// Not public API. - pub enum TagOrContent<'de> { + enum TagOrContent<'de> { Tag, Content(Content<'de>), } From cfe357b2a66dd9d0c9d3603f6b2bd05eb884f990 Mon Sep 17 00:00:00 2001 From: Mingun Date: Sat, 12 Aug 2023 15:33:04 +0500 Subject: [PATCH 14/14] Use deserialize_map when deserialize internally tagged enums Deserializer methods are only hints which deserializer is not obliged to follow. Both - TaggedContentVisitor - InternallyTaggedUnitVisitor accepts only visit_map and visit_seq and that is what derived implementation of Deserialize does for structs. Therefore it is fine to call deserialize_map here, as that already did in derived deserialize implementation. Because those structs officially not public, it is used only by derive macro --- serde_derive/src/de.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 5a8bd3e65..1de8f6146 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1073,7 +1073,7 @@ fn deserialize_struct( _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) }, StructForm::InternallyTagged(_, deserializer) => quote! { - _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) + _serde::Deserializer::deserialize_map(#deserializer, #visitor_expr) }, StructForm::Untagged(_, deserializer) => quote! { _serde::Deserializer::deserialize_any(#deserializer, #visitor_expr) @@ -1451,7 +1451,7 @@ fn deserialize_internally_tagged_enum( } } - _serde::Deserializer::deserialize_any( + _serde::Deserializer::deserialize_map( __deserializer, _serde::__private::de::TaggedContentVisitor::<__Seed>::new(#tag, #expecting) ) @@ -1909,7 +1909,7 @@ fn deserialize_internally_tagged_variant( quote!((#default)) }); quote_block! { - _serde::Deserializer::deserialize_any(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?; + _serde::Deserializer::deserialize_map(#deserializer, _serde::__private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?; _serde::__private::Ok(#this_value::#variant_ident #default) } }