From 00b1b6b2b5e6154eba81e2ad8c6a43b945583ad0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 14 Sep 2025 08:35:53 -0700 Subject: [PATCH] Move Content's Deserialize impl from serde_core to serde --- Cargo.toml | 1 + serde/src/private/de.rs | 235 +++++++++++++++++++++++++++++- serde_core/src/private/content.rs | 224 ---------------------------- serde_core/src/private/mod.rs | 2 +- serde_derive/src/de.rs | 6 +- 5 files changed, 234 insertions(+), 234 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f5944a36..a139b97d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ resolver = "2" [patch.crates-io] serde = { path = "serde" } serde_core = { path = "serde_core" } +serde_derive = { path = "serde_derive" } [workspace.dependencies] proc-macro2 = { version = "1.0.74", default-features = false } diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 747a2da6..9d5f485d 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -11,9 +11,10 @@ use crate::de::{MapAccess, Unexpected}; #[cfg(any(feature = "std", feature = "alloc"))] pub use self::content::{ - content_as_str, Content, ContentDeserializer, ContentRefDeserializer, EnumDeserializer, - InternallyTaggedUnitVisitor, TagContentOtherField, TagContentOtherFieldVisitor, - TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor, + content_as_str, Content, ContentDeserializer, ContentRefDeserializer, ContentVisitor, + EnumDeserializer, InternallyTaggedUnitVisitor, TagContentOtherField, + TagContentOtherFieldVisitor, TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, + UntaggedUnitVisitor, }; pub use serde_core::__private::InPlaceSeed; @@ -212,8 +213,8 @@ mod content { self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, }; + use serde_core::__private::size_hint; pub use serde_core::__private::Content; - use serde_core::__private::{size_hint, ContentVisitor}; pub fn content_as_str<'a, 'de>(content: &'a Content<'de>) -> Option<&'a str> { match *content { @@ -283,6 +284,228 @@ mod content { } } + pub struct ContentVisitor<'de> { + value: PhantomData>, + } + + impl<'de> ContentVisitor<'de> { + pub fn new() -> Self { + ContentVisitor { value: PhantomData } + } + } + + impl<'de> DeserializeSeed<'de> for ContentVisitor<'de> { + type Value = Content<'de>; + + fn deserialize(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.__deserialize_content_v1(self) + } + } + + impl<'de> Visitor<'de> for ContentVisitor<'de> { + type Value = Content<'de>; + + fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str("any value") + } + + fn visit_bool(self, value: bool) -> Result + where + F: de::Error, + { + Ok(Content::Bool(value)) + } + + fn visit_i8(self, value: i8) -> Result + where + F: de::Error, + { + Ok(Content::I8(value)) + } + + fn visit_i16(self, value: i16) -> Result + where + F: de::Error, + { + Ok(Content::I16(value)) + } + + fn visit_i32(self, value: i32) -> Result + where + F: de::Error, + { + Ok(Content::I32(value)) + } + + fn visit_i64(self, value: i64) -> Result + where + F: de::Error, + { + Ok(Content::I64(value)) + } + + fn visit_u8(self, value: u8) -> Result + where + F: de::Error, + { + Ok(Content::U8(value)) + } + + fn visit_u16(self, value: u16) -> Result + where + F: de::Error, + { + Ok(Content::U16(value)) + } + + fn visit_u32(self, value: u32) -> Result + where + F: de::Error, + { + Ok(Content::U32(value)) + } + + fn visit_u64(self, value: u64) -> Result + where + F: de::Error, + { + Ok(Content::U64(value)) + } + + fn visit_f32(self, value: f32) -> Result + where + F: de::Error, + { + Ok(Content::F32(value)) + } + + fn visit_f64(self, value: f64) -> Result + where + F: de::Error, + { + Ok(Content::F64(value)) + } + + fn visit_char(self, value: char) -> Result + where + F: de::Error, + { + Ok(Content::Char(value)) + } + + fn visit_str(self, value: &str) -> Result + where + F: de::Error, + { + Ok(Content::String(value.into())) + } + + fn visit_borrowed_str(self, value: &'de str) -> Result + where + F: de::Error, + { + Ok(Content::Str(value)) + } + + fn visit_string(self, value: String) -> Result + where + F: de::Error, + { + Ok(Content::String(value)) + } + + fn visit_bytes(self, value: &[u8]) -> Result + where + F: de::Error, + { + Ok(Content::ByteBuf(value.into())) + } + + fn visit_borrowed_bytes(self, value: &'de [u8]) -> Result + where + F: de::Error, + { + Ok(Content::Bytes(value)) + } + + fn visit_byte_buf(self, value: Vec) -> Result + where + F: de::Error, + { + Ok(Content::ByteBuf(value)) + } + + fn visit_unit(self) -> Result + where + F: de::Error, + { + Ok(Content::Unit) + } + + fn visit_none(self) -> Result + where + F: de::Error, + { + Ok(Content::None) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let v = tri!(ContentVisitor::new().deserialize(deserializer)); + Ok(Content::Some(Box::new(v))) + } + + fn visit_newtype_struct(self, deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let v = tri!(ContentVisitor::new().deserialize(deserializer)); + Ok(Content::Newtype(Box::new(v))) + } + + fn visit_seq(self, mut visitor: V) -> Result + where + V: SeqAccess<'de>, + { + let mut vec = + Vec::::with_capacity(size_hint::cautious::(visitor.size_hint())); + while let Some(e) = tri!(visitor.next_element_seed(ContentVisitor::new())) { + vec.push(e); + } + Ok(Content::Seq(vec)) + } + + fn visit_map(self, mut visitor: V) -> Result + where + V: MapAccess<'de>, + { + let mut vec = + Vec::<(Content, Content)>::with_capacity( + size_hint::cautious::<(Content, Content)>(visitor.size_hint()), + ); + while let Some(kv) = + tri!(visitor.next_entry_seed(ContentVisitor::new(), ContentVisitor::new())) + { + vec.push(kv); + } + Ok(Content::Map(vec)) + } + + fn visit_enum(self, _visitor: V) -> Result + where + V: EnumAccess<'de>, + { + Err(de::Error::custom( + "untagged and internally tagged enums do not support enum input", + )) + } + } + /// This is the type of the map keys in an internally tagged enum. /// /// Not public API. @@ -622,7 +845,7 @@ mod content { } }; let rest = de::value::SeqAccessDeserializer::new(seq); - Ok((tag, tri!(Content::deserialize(rest)))) + Ok((tag, tri!(ContentVisitor::new().deserialize(rest)))) } fn visit_map(self, mut map: M) -> Result @@ -643,7 +866,7 @@ mod content { tag = Some(tri!(map.next_value())); } TagOrContent::Content(k) => { - let v = tri!(map.next_value()); + let v = tri!(map.next_value_seed(ContentVisitor::new())); vec.push((k, v)); } } diff --git a/serde_core/src/private/content.rs b/serde_core/src/private/content.rs index d082e5df..f29a9b52 100644 --- a/serde_core/src/private/content.rs +++ b/serde_core/src/private/content.rs @@ -1,6 +1,4 @@ -use crate::de::{self, Deserialize, Deserializer, EnumAccess, MapAccess, SeqAccess, Visitor}; use crate::lib::*; -use crate::private::size_hint; // Used from generated code to buffer the contents of the Deserializer when // deserializing untagged enums and internally tagged enums. @@ -39,225 +37,3 @@ pub enum Content<'de> { Seq(Vec>), Map(Vec<(Content<'de>, Content<'de>)>), } - -impl<'de> Deserialize<'de> for Content<'de> { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - // Untagged and internally tagged enums are only supported in - // self-describing formats. - let visitor = ContentVisitor { value: PhantomData }; - deserializer.__deserialize_content_v1(visitor) - } -} - -#[doc(hidden)] -pub struct ContentVisitor<'de> { - value: PhantomData>, -} - -impl<'de> ContentVisitor<'de> { - pub fn new() -> Self { - ContentVisitor { value: PhantomData } - } -} - -impl<'de> Visitor<'de> for ContentVisitor<'de> { - type Value = Content<'de>; - - fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str("any value") - } - - fn visit_bool(self, value: bool) -> Result - where - F: de::Error, - { - Ok(Content::Bool(value)) - } - - fn visit_i8(self, value: i8) -> Result - where - F: de::Error, - { - Ok(Content::I8(value)) - } - - fn visit_i16(self, value: i16) -> Result - where - F: de::Error, - { - Ok(Content::I16(value)) - } - - fn visit_i32(self, value: i32) -> Result - where - F: de::Error, - { - Ok(Content::I32(value)) - } - - fn visit_i64(self, value: i64) -> Result - where - F: de::Error, - { - Ok(Content::I64(value)) - } - - fn visit_u8(self, value: u8) -> Result - where - F: de::Error, - { - Ok(Content::U8(value)) - } - - fn visit_u16(self, value: u16) -> Result - where - F: de::Error, - { - Ok(Content::U16(value)) - } - - fn visit_u32(self, value: u32) -> Result - where - F: de::Error, - { - Ok(Content::U32(value)) - } - - fn visit_u64(self, value: u64) -> Result - where - F: de::Error, - { - Ok(Content::U64(value)) - } - - fn visit_f32(self, value: f32) -> Result - where - F: de::Error, - { - Ok(Content::F32(value)) - } - - fn visit_f64(self, value: f64) -> Result - where - F: de::Error, - { - Ok(Content::F64(value)) - } - - fn visit_char(self, value: char) -> Result - where - F: de::Error, - { - Ok(Content::Char(value)) - } - - fn visit_str(self, value: &str) -> Result - where - F: de::Error, - { - Ok(Content::String(value.into())) - } - - fn visit_borrowed_str(self, value: &'de str) -> Result - where - F: de::Error, - { - Ok(Content::Str(value)) - } - - fn visit_string(self, value: String) -> Result - where - F: de::Error, - { - Ok(Content::String(value)) - } - - fn visit_bytes(self, value: &[u8]) -> Result - where - F: de::Error, - { - Ok(Content::ByteBuf(value.into())) - } - - fn visit_borrowed_bytes(self, value: &'de [u8]) -> Result - where - F: de::Error, - { - Ok(Content::Bytes(value)) - } - - fn visit_byte_buf(self, value: Vec) -> Result - where - F: de::Error, - { - Ok(Content::ByteBuf(value)) - } - - fn visit_unit(self) -> Result - where - F: de::Error, - { - Ok(Content::Unit) - } - - fn visit_none(self) -> Result - where - F: de::Error, - { - Ok(Content::None) - } - - fn visit_some(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let v = tri!(Deserialize::deserialize(deserializer)); - Ok(Content::Some(Box::new(v))) - } - - fn visit_newtype_struct(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let v = tri!(Deserialize::deserialize(deserializer)); - Ok(Content::Newtype(Box::new(v))) - } - - fn visit_seq(self, mut visitor: V) -> Result - where - V: SeqAccess<'de>, - { - let mut vec = - Vec::::with_capacity(size_hint::cautious::(visitor.size_hint())); - while let Some(e) = tri!(visitor.next_element()) { - vec.push(e); - } - Ok(Content::Seq(vec)) - } - - fn visit_map(self, mut visitor: V) -> Result - where - V: MapAccess<'de>, - { - let mut vec = Vec::<(Content, Content)>::with_capacity(size_hint::cautious::<( - Content, - Content, - )>(visitor.size_hint())); - while let Some(kv) = tri!(visitor.next_entry()) { - vec.push(kv); - } - Ok(Content::Map(vec)) - } - - fn visit_enum(self, _visitor: V) -> Result - where - V: EnumAccess<'de>, - { - Err(de::Error::custom( - "untagged and internally tagged enums do not support enum input", - )) - } -} diff --git a/serde_core/src/private/mod.rs b/serde_core/src/private/mod.rs index 77753786..dd5f93fe 100644 --- a/serde_core/src/private/mod.rs +++ b/serde_core/src/private/mod.rs @@ -14,7 +14,7 @@ pub mod string; #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] #[doc(hidden)] -pub use self::content::{Content, ContentVisitor}; +pub use self::content::Content; #[doc(hidden)] pub use self::seed::InPlaceSeed; #[doc(hidden)] diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index bbf97b41..13f60462 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1669,7 +1669,7 @@ fn deserialize_adjacently_tagged_enum( // First key is the content. _serde::__private::Some(_serde::__private::de::TagOrContentField::Content) => { // Buffer up the content. - let __content = _serde::de::MapAccess::next_value::<_serde::__private::de::Content>(&mut __map)?; + let __content = _serde::de::MapAccess::next_value_seed(&mut __map, _serde::__private::de::ContentVisitor::new())?; // Visit the second key. match #next_relevant_key { // Second key is the tag. @@ -1789,7 +1789,7 @@ fn deserialize_untagged_enum_after( }); quote_block! { - let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?; + let __content = _serde::de::DeserializeSeed::deserialize(_serde::__private::de::ContentVisitor::new(), __deserializer)?; let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content); #first_attempt @@ -2592,7 +2592,7 @@ fn deserialize_map( __Field::__other(__name) => { __collect.push(_serde::__private::Some(( __name, - _serde::de::MapAccess::next_value(&mut __map)?))); + _serde::de::MapAccess::next_value_seed(&mut __map, _serde::__private::de::ContentVisitor::new())?))); } }) } else if cattrs.deny_unknown_fields() {