From f669f161277f231299a0e5733fe68d320b1ee2e4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 13 Sep 2025 10:24:40 -0700 Subject: [PATCH 1/2] Restore __deserialize_content optimization --- serde/src/private/de.rs | 427 ++++++++------------------------------ serde_core/build.rs | 6 + serde_core/src/de/mod.rs | 10 + serde_core/src/lib.rs | 9 + serde_core/src/private.rs | 265 +++++++++++++++++++++++ serde_derive/src/de.rs | 2 +- 6 files changed, 381 insertions(+), 338 deletions(-) create mode 100644 serde_core/src/private.rs diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index cd75d1e9..c400fff8 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -11,7 +11,7 @@ use crate::de::{MapAccess, Unexpected}; #[cfg(any(feature = "std", feature = "alloc"))] pub use self::content::{ - Content, ContentDeserializer, ContentRefDeserializer, EnumDeserializer, + content_as_str, Content, ContentDeserializer, ContentRefDeserializer, EnumDeserializer, InternallyTaggedUnitVisitor, TagContentOtherField, TagContentOtherFieldVisitor, TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor, }; @@ -213,324 +213,43 @@ mod content { self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, }; + pub use serde_core::__private::Content; + use serde_core::__private::ContentVisitor; - /// Used from generated code to buffer the contents of the Deserializer when - /// deserializing untagged enums and internally tagged enums. - /// - /// Not public API. Use serde-value instead. - #[derive(Debug, Clone)] - pub enum Content<'de> { - Bool(bool), - - U8(u8), - U16(u16), - U32(u32), - U64(u64), - - I8(i8), - I16(i16), - I32(i32), - I64(i64), - - F32(f32), - F64(f64), - - Char(char), - String(String), - Str(&'de str), - ByteBuf(Vec), - Bytes(&'de [u8]), - - None, - Some(Box>), - - Unit, - Newtype(Box>), - Seq(Vec>), - Map(Vec<(Content<'de>, Content<'de>)>), - } - - impl<'de> Content<'de> { - pub fn as_str(&self) -> Option<&str> { - match *self { - Content::Str(x) => Some(x), - Content::String(ref x) => Some(x), - Content::Bytes(x) => str::from_utf8(x).ok(), - Content::ByteBuf(ref x) => str::from_utf8(x).ok(), - _ => None, - } - } - - #[cold] - fn unexpected(&self) -> Unexpected { - match *self { - Content::Bool(b) => Unexpected::Bool(b), - Content::U8(n) => Unexpected::Unsigned(n as u64), - Content::U16(n) => Unexpected::Unsigned(n as u64), - Content::U32(n) => Unexpected::Unsigned(n as u64), - Content::U64(n) => Unexpected::Unsigned(n), - Content::I8(n) => Unexpected::Signed(n as i64), - Content::I16(n) => Unexpected::Signed(n as i64), - Content::I32(n) => Unexpected::Signed(n as i64), - Content::I64(n) => Unexpected::Signed(n), - Content::F32(f) => Unexpected::Float(f as f64), - Content::F64(f) => Unexpected::Float(f), - Content::Char(c) => Unexpected::Char(c), - Content::String(ref s) => Unexpected::Str(s), - Content::Str(s) => Unexpected::Str(s), - Content::ByteBuf(ref b) => Unexpected::Bytes(b), - Content::Bytes(b) => Unexpected::Bytes(b), - Content::None | Content::Some(_) => Unexpected::Option, - Content::Unit => Unexpected::Unit, - Content::Newtype(_) => Unexpected::NewtypeStruct, - Content::Seq(_) => Unexpected::Seq, - Content::Map(_) => Unexpected::Map, - } + pub fn content_as_str<'a, 'de>(content: &'a Content<'de>) -> Option<&'a str> { + match *content { + Content::Str(x) => Some(x), + Content::String(ref x) => Some(x), + Content::Bytes(x) => str::from_utf8(x).ok(), + Content::ByteBuf(ref x) => str::from_utf8(x).ok(), + _ => None, } } - 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_any(visitor) - } - } - - impl<'de, E> de::IntoDeserializer<'de, E> for Content<'de> - where - E: de::Error, - { - type Deserializer = ContentDeserializer<'de, E>; - - fn into_deserializer(self) -> Self::Deserializer { - ContentDeserializer::new(self) - } - } - - impl<'a, 'de, E> de::IntoDeserializer<'de, E> for &'a Content<'de> - where - E: de::Error, - { - type Deserializer = ContentRefDeserializer<'a, 'de, E>; - - fn into_deserializer(self) -> Self::Deserializer { - ContentRefDeserializer::new(self) - } - } - - /// Used to capture data in [`Content`] from other deserializers. - /// Cannot capture externally tagged enums, `i128` and `u128`. - struct ContentVisitor<'de> { - value: PhantomData>, - } - - impl<'de> ContentVisitor<'de> { - 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", - )) + #[cold] + fn content_unexpected<'a, 'de>(content: &'a Content<'de>) -> Unexpected<'a> { + match *content { + Content::Bool(b) => Unexpected::Bool(b), + Content::U8(n) => Unexpected::Unsigned(n as u64), + Content::U16(n) => Unexpected::Unsigned(n as u64), + Content::U32(n) => Unexpected::Unsigned(n as u64), + Content::U64(n) => Unexpected::Unsigned(n), + Content::I8(n) => Unexpected::Signed(n as i64), + Content::I16(n) => Unexpected::Signed(n as i64), + Content::I32(n) => Unexpected::Signed(n as i64), + Content::I64(n) => Unexpected::Signed(n), + Content::F32(f) => Unexpected::Float(f as f64), + Content::F64(f) => Unexpected::Float(f), + Content::Char(c) => Unexpected::Char(c), + Content::String(ref s) => Unexpected::Str(s), + Content::Str(s) => Unexpected::Str(s), + Content::ByteBuf(ref b) => Unexpected::Bytes(b), + Content::Bytes(b) => Unexpected::Bytes(b), + Content::None | Content::Some(_) => Unexpected::Option, + Content::Unit => Unexpected::Unit, + Content::Newtype(_) => Unexpected::NewtypeStruct, + Content::Seq(_) => Unexpected::Seq, + Content::Map(_) => Unexpected::Map, } } @@ -1065,7 +784,7 @@ mod content { { #[cold] fn invalid_type(self, exp: &dyn Expected) -> E { - de::Error::invalid_type(self.content.unexpected(), exp) + de::Error::invalid_type(content_unexpected(&self.content), exp) } fn deserialize_integer(self, visitor: V) -> Result @@ -1110,7 +829,8 @@ mod content { V: Visitor<'de>, E: de::Error, { - let mut seq_visitor = SeqDeserializer::new(content.into_iter()); + let mut seq_visitor = + SeqDeserializer::new(content.into_iter().map(ContentDeserializer::new)); let value = tri!(visitor.visit_seq(&mut seq_visitor)); tri!(seq_visitor.end()); Ok(value) @@ -1124,7 +844,11 @@ mod content { V: Visitor<'de>, E: de::Error, { - let mut map_visitor = MapDeserializer::new(content.into_iter()); + let mut map_visitor = MapDeserializer::new( + content + .into_iter() + .map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v))), + ); let value = tri!(visitor.visit_map(&mut map_visitor)); tri!(map_visitor.end()); Ok(value) @@ -1465,7 +1189,7 @@ mod content { s @ Content::String(_) | s @ Content::Str(_) => (s, None), other => { return Err(de::Error::invalid_type( - other.unexpected(), + content_unexpected(&other), &"string or map", )); } @@ -1496,6 +1220,14 @@ mod content { drop(self); visitor.visit_unit() } + + fn __deserialize_content_v1(self, visitor: V) -> Result + where + V: Visitor<'de, Value = Content<'de>>, + { + let _ = visitor; + Ok(self.content) + } } impl<'de, E> ContentDeserializer<'de, E> { @@ -1589,11 +1321,12 @@ mod content { V: de::Visitor<'de>, { match self.value { - Some(Content::Seq(v)) => { - de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor) - } + Some(Content::Seq(v)) => de::Deserializer::deserialize_any( + SeqDeserializer::new(v.into_iter().map(ContentDeserializer::new)), + visitor, + ), Some(other) => Err(de::Error::invalid_type( - other.unexpected(), + content_unexpected(&other), &"tuple variant", )), None => Err(de::Error::invalid_type( @@ -1613,13 +1346,19 @@ mod content { { match self.value { Some(Content::Map(v)) => { - de::Deserializer::deserialize_any(MapDeserializer::new(v.into_iter()), visitor) - } - Some(Content::Seq(v)) => { - de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor) + de::Deserializer::deserialize_any( + MapDeserializer::new(v.into_iter().map(|(k, v)| { + (ContentDeserializer::new(k), ContentDeserializer::new(v)) + })), + visitor, + ) } + Some(Content::Seq(v)) => de::Deserializer::deserialize_any( + SeqDeserializer::new(v.into_iter().map(ContentDeserializer::new)), + visitor, + ), Some(other) => Err(de::Error::invalid_type( - other.unexpected(), + content_unexpected(&other), &"struct variant", )), None => Err(de::Error::invalid_type( @@ -1642,7 +1381,7 @@ mod content { { #[cold] fn invalid_type(self, exp: &dyn Expected) -> E { - de::Error::invalid_type(self.content.unexpected(), exp) + de::Error::invalid_type(content_unexpected(self.content), exp) } fn deserialize_integer(self, visitor: V) -> Result @@ -1690,7 +1429,7 @@ mod content { V: Visitor<'de>, E: de::Error, { - let mut seq_visitor = SeqDeserializer::new(content.iter()); + let mut seq_visitor = SeqDeserializer::new(content.iter().map(ContentRefDeserializer::new)); let value = tri!(visitor.visit_seq(&mut seq_visitor)); tri!(seq_visitor.end()); Ok(value) @@ -1704,10 +1443,16 @@ mod content { V: Visitor<'de>, E: de::Error, { - fn content_ref_deserializer_pair<'a, 'de>( + fn content_ref_deserializer_pair<'a, 'de, E>( (k, v): &'a (Content<'de>, Content<'de>), - ) -> (&'a Content<'de>, &'a Content<'de>) { - (k, v) + ) -> ( + ContentRefDeserializer<'a, 'de, E>, + ContentRefDeserializer<'a, 'de, E>, + ) { + ( + ContentRefDeserializer::new(k), + ContentRefDeserializer::new(v), + ) } let map = content.iter().map(content_ref_deserializer_pair); @@ -2043,7 +1788,7 @@ mod content { ref s @ Content::String(_) | ref s @ Content::Str(_) => (s, None), ref other => { return Err(de::Error::invalid_type( - other.unexpected(), + content_unexpected(other), &"string or map", )); } @@ -2077,6 +1822,14 @@ mod content { { visitor.visit_unit() } + + fn __deserialize_content_v1(self, visitor: V) -> Result + where + V: Visitor<'de, Value = Content<'de>>, + { + let _ = visitor; + Ok(self.content.clone()) + } } impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> { @@ -2182,7 +1935,7 @@ mod content { // newtype_enum::tuple2 Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor), Some(other) => Err(de::Error::invalid_type( - other.unexpected(), + content_unexpected(other), &"tuple variant", )), None => Err(de::Error::invalid_type( @@ -2209,7 +1962,7 @@ mod content { // newtype_enum::empty_struct_from_seq Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor), Some(other) => Err(de::Error::invalid_type( - other.unexpected(), + content_unexpected(other), &"struct variant", )), None => Err(de::Error::invalid_type( @@ -2716,7 +2469,7 @@ fn flat_map_take_entry<'de>( // and if the field is one recognized by the current data structure. let is_recognized = match entry { None => false, - Some((k, _v)) => k.as_str().map_or(false, |name| recognized.contains(&name)), + Some((k, _v)) => content_as_str(k).map_or(false, |name| recognized.contains(&name)), }; if is_recognized { diff --git a/serde_core/build.rs b/serde_core/build.rs index 16311b1d..fe9fd15c 100644 --- a/serde_core/build.rs +++ b/serde_core/build.rs @@ -19,6 +19,7 @@ fn main() { println!("cargo:rustc-check-cfg=cfg(no_core_net)"); println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); + println!("cargo:rustc-check-cfg=cfg(no_serde_derive)"); println!("cargo:rustc-check-cfg=cfg(no_std_atomic)"); println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)"); println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)"); @@ -48,6 +49,11 @@ fn main() { } } + // Current minimum supported version of serde_derive crate is Rust 1.61. + if minor < 61 { + println!("cargo:rustc-cfg=no_serde_derive"); + } + // Support for core::ffi::CStr and alloc::ffi::CString stabilized in Rust 1.64. // https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#c-compatible-ffi-types-in-core-and-alloc if minor < 64 { diff --git a/serde_core/src/de/mod.rs b/serde_core/src/de/mod.rs index c21480c9..fa1fecdf 100644 --- a/serde_core/src/de/mod.rs +++ b/serde_core/src/de/mod.rs @@ -1255,6 +1255,16 @@ pub trait Deserializer<'de>: Sized { fn is_human_readable(&self) -> bool { true } + + // Not public API. + #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] + #[doc(hidden)] + fn __deserialize_content_v1(self, visitor: V) -> Result + where + V: Visitor<'de, Value = crate::private::Content<'de>>, + { + self.deserialize_any(visitor) + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/serde_core/src/lib.rs b/serde_core/src/lib.rs index e566bb50..50fa971e 100644 --- a/serde_core/src/lib.rs +++ b/serde_core/src/lib.rs @@ -261,6 +261,15 @@ pub use crate::ser::{Serialize, Serializer}; #[doc(hidden)] pub use lib::from_utf8_lossy; + +// Used by generated code. Not public API. +#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] +#[doc(hidden)] +#[path = "private.rs"] +pub mod __private; +#[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] +use self::__private as private; + #[path = "de/seed.rs"] mod seed; diff --git a/serde_core/src/private.rs b/serde_core/src/private.rs new file mode 100644 index 00000000..7abdee7d --- /dev/null +++ b/serde_core/src/private.rs @@ -0,0 +1,265 @@ +use crate::de::{ + self, size_hint, Deserialize, Deserializer, EnumAccess, MapAccess, SeqAccess, Visitor, +}; +use crate::lib::*; + +// Used from generated code to buffer the contents of the Deserializer when +// deserializing untagged enums and internally tagged enums. +// +// Not public API. Use serde-value instead. +// +// Obsoleted by format-specific buffer types (https://github.com/serde-rs/serde/pull/2912). +#[derive(Clone)] +#[doc(hidden)] +pub enum Content<'de> { + Bool(bool), + + U8(u8), + U16(u16), + U32(u32), + U64(u64), + + I8(i8), + I16(i16), + I32(i32), + I64(i64), + + F32(f32), + F64(f64), + + Char(char), + String(String), + Str(&'de str), + ByteBuf(Vec), + Bytes(&'de [u8]), + + None, + Some(Box>), + + Unit, + Newtype(Box>), + 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_derive/src/de.rs b/serde_derive/src/de.rs index 4967e35d..bbf97b41 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -2662,7 +2662,7 @@ fn deserialize_map( if let _serde::__private::Some(_serde::__private::Some((__key, _))) = __collect.into_iter().filter(_serde::__private::Option::is_some).next() { - if let _serde::__private::Some(__key) = __key.as_str() { + if let _serde::__private::Some(__key) = _serde::__private::de::content_as_str(&__key) { return _serde::__private::Err( _serde::de::Error::custom(format_args!("unknown field `{}`", &__key))); } else { From 7659fb686d7950ac515a488020ed8f369b3c2c89 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 13 Sep 2025 11:32:56 -0700 Subject: [PATCH 2/2] Inline SeqDeserializer and MapDeserializer for Content Greatly shrinks symbol sizes: keep all those generic type parameters (and even closures) out of symbol names. A good change even independent of serde_core. --- serde/src/private/de.rs | 739 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 702 insertions(+), 37 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index c400fff8..804bed2e 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -208,7 +208,6 @@ mod content { use crate::lib::*; - use crate::de::value::{MapDeserializer, SeqDeserializer}; use crate::de::{ self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, @@ -829,8 +828,7 @@ mod content { V: Visitor<'de>, E: de::Error, { - let mut seq_visitor = - SeqDeserializer::new(content.into_iter().map(ContentDeserializer::new)); + let mut seq_visitor = SeqDeserializer::new(content); let value = tri!(visitor.visit_seq(&mut seq_visitor)); tri!(seq_visitor.end()); Ok(value) @@ -844,11 +842,7 @@ mod content { V: Visitor<'de>, E: de::Error, { - let mut map_visitor = MapDeserializer::new( - content - .into_iter() - .map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v))), - ); + let mut map_visitor = MapDeserializer::new(content); let value = tri!(visitor.visit_map(&mut map_visitor)); tri!(map_visitor.end()); Ok(value) @@ -1240,6 +1234,362 @@ mod content { } } + struct SeqDeserializer<'de, E> { + iter: > as IntoIterator>::IntoIter, + count: usize, + marker: PhantomData, + } + + impl<'de, E> SeqDeserializer<'de, E> { + fn new(content: Vec>) -> Self { + SeqDeserializer { + iter: content.into_iter(), + count: 0, + marker: PhantomData, + } + } + } + + impl<'de, E> SeqDeserializer<'de, E> + where + E: de::Error, + { + fn end(self) -> Result<(), E> { + let remaining = self.iter.count(); + if remaining == 0 { + Ok(()) + } else { + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length( + self.count + remaining, + &ExpectedInSeq(self.count), + )) + } + } + } + + impl<'de, E> Deserializer<'de> for SeqDeserializer<'de, E> + where + E: de::Error, + { + type Error = E; + + fn deserialize_any(mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let v = tri!(visitor.visit_seq(&mut self)); + tri!(self.end()); + Ok(v) + } + + serde_core::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, E> SeqAccess<'de> for SeqDeserializer<'de, E> + where + E: de::Error, + { + type Error = E; + + fn next_element_seed(&mut self, seed: V) -> Result, Self::Error> + where + V: DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => { + self.count += 1; + seed.deserialize(ContentDeserializer::new(value)).map(Some) + } + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + struct ExpectedInSeq(usize); + + impl Expected for ExpectedInSeq { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.0 == 1 { + formatter.write_str("1 element in sequence") + } else { + write!(formatter, "{} elements in sequence", self.0) + } + } + } + + struct MapDeserializer<'de, E> { + iter: , Content<'de>)> as IntoIterator>::IntoIter, + value: Option>, + count: usize, + lifetime: PhantomData<&'de ()>, + error: PhantomData, + } + + impl<'de, E> MapDeserializer<'de, E> { + fn new(content: Vec<(Content<'de>, Content<'de>)>) -> Self { + MapDeserializer { + iter: content.into_iter(), + value: None, + count: 0, + lifetime: PhantomData, + error: PhantomData, + } + } + } + + impl<'de, E> MapDeserializer<'de, E> + where + E: de::Error, + { + fn end(self) -> Result<(), E> { + let remaining = self.iter.count(); + if remaining == 0 { + Ok(()) + } else { + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length( + self.count + remaining, + &ExpectedInMap(self.count), + )) + } + } + } + + impl<'de, E> MapDeserializer<'de, E> { + fn next_pair(&mut self) -> Option<(Content<'de>, Content<'de>)> { + match self.iter.next() { + Some((k, v)) => { + self.count += 1; + Some((k, v)) + } + None => None, + } + } + } + + impl<'de, E> Deserializer<'de> for MapDeserializer<'de, E> + where + E: de::Error, + { + type Error = E; + + fn deserialize_any(mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let value = tri!(visitor.visit_map(&mut self)); + tri!(self.end()); + Ok(value) + } + + fn deserialize_seq(mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let value = tri!(visitor.visit_seq(&mut self)); + tri!(self.end()); + Ok(value) + } + + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + let _ = len; + self.deserialize_seq(visitor) + } + + serde_core::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 tuple_struct map + struct enum identifier ignored_any + } + } + + impl<'de, E> MapAccess<'de> for MapDeserializer<'de, E> + where + E: de::Error, + { + type Error = E; + + fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>, + { + match self.next_pair() { + Some((key, value)) => { + self.value = Some(value); + seed.deserialize(ContentDeserializer::new(key)).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + let value = self.value.take(); + // Panic because this indicates a bug in the program rather than an + // expected failure. + let value = value.expect("MapAccess::next_value called before next_key"); + seed.deserialize(ContentDeserializer::new(value)) + } + + fn next_entry_seed( + &mut self, + kseed: TK, + vseed: TV, + ) -> Result, Self::Error> + where + TK: DeserializeSeed<'de>, + TV: DeserializeSeed<'de>, + { + match self.next_pair() { + Some((key, value)) => { + let key = tri!(kseed.deserialize(ContentDeserializer::new(key))); + let value = tri!(vseed.deserialize(ContentDeserializer::new(value))); + Ok(Some((key, value))) + } + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + impl<'de, E> SeqAccess<'de> for MapDeserializer<'de, E> + where + E: de::Error, + { + type Error = E; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.next_pair() { + Some((k, v)) => { + let de = PairDeserializer(k, v, PhantomData); + seed.deserialize(de).map(Some) + } + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + struct PairDeserializer<'de, E>(Content<'de>, Content<'de>, PhantomData); + + impl<'de, E> Deserializer<'de> for PairDeserializer<'de, E> + where + E: de::Error, + { + type Error = E; + + serde_core::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 tuple_struct map + struct enum identifier ignored_any + } + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData); + let pair = tri!(visitor.visit_seq(&mut pair_visitor)); + if pair_visitor.1.is_none() { + Ok(pair) + } else { + let remaining = pair_visitor.size_hint().unwrap(); + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length(2, &ExpectedInSeq(2 - remaining))) + } + } + + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + if len == 2 { + self.deserialize_seq(visitor) + } else { + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length(2, &ExpectedInSeq(len))) + } + } + } + + struct PairVisitor<'de, E>(Option>, Option>, PhantomData); + + impl<'de, E> SeqAccess<'de> for PairVisitor<'de, E> + where + E: de::Error, + { + type Error = E; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>, + { + if let Some(k) = self.0.take() { + seed.deserialize(ContentDeserializer::new(k)).map(Some) + } else if let Some(v) = self.1.take() { + seed.deserialize(ContentDeserializer::new(v)).map(Some) + } else { + Ok(None) + } + } + + fn size_hint(&self) -> Option { + if self.0.is_some() { + Some(2) + } else if self.1.is_some() { + Some(1) + } else { + Some(0) + } + } + } + + struct ExpectedInMap(usize); + + impl Expected for ExpectedInMap { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.0 == 1 { + formatter.write_str("1 element in map") + } else { + write!(formatter, "{} elements in map", self.0) + } + } + } + pub struct EnumDeserializer<'de, E> where E: de::Error, @@ -1321,10 +1671,9 @@ mod content { V: de::Visitor<'de>, { match self.value { - Some(Content::Seq(v)) => de::Deserializer::deserialize_any( - SeqDeserializer::new(v.into_iter().map(ContentDeserializer::new)), - visitor, - ), + Some(Content::Seq(v)) => { + de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) + } Some(other) => Err(de::Error::invalid_type( content_unexpected(&other), &"tuple variant", @@ -1346,17 +1695,11 @@ mod content { { match self.value { Some(Content::Map(v)) => { - de::Deserializer::deserialize_any( - MapDeserializer::new(v.into_iter().map(|(k, v)| { - (ContentDeserializer::new(k), ContentDeserializer::new(v)) - })), - visitor, - ) + de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor) + } + Some(Content::Seq(v)) => { + de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) } - Some(Content::Seq(v)) => de::Deserializer::deserialize_any( - SeqDeserializer::new(v.into_iter().map(ContentDeserializer::new)), - visitor, - ), Some(other) => Err(de::Error::invalid_type( content_unexpected(&other), &"struct variant", @@ -1429,7 +1772,7 @@ mod content { V: Visitor<'de>, E: de::Error, { - let mut seq_visitor = SeqDeserializer::new(content.iter().map(ContentRefDeserializer::new)); + let mut seq_visitor = SeqRefDeserializer::new(content); let value = tri!(visitor.visit_seq(&mut seq_visitor)); tri!(seq_visitor.end()); Ok(value) @@ -1443,20 +1786,7 @@ mod content { V: Visitor<'de>, E: de::Error, { - fn content_ref_deserializer_pair<'a, 'de, E>( - (k, v): &'a (Content<'de>, Content<'de>), - ) -> ( - ContentRefDeserializer<'a, 'de, E>, - ContentRefDeserializer<'a, 'de, E>, - ) { - ( - ContentRefDeserializer::new(k), - ContentRefDeserializer::new(v), - ) - } - - let map = content.iter().map(content_ref_deserializer_pair); - let mut map_visitor = MapDeserializer::new(map); + let mut map_visitor = MapRefDeserializer::new(content); let value = tri!(visitor.visit_map(&mut map_visitor)); tri!(map_visitor.end()); Ok(value) @@ -1850,6 +2180,341 @@ mod content { } } + struct SeqRefDeserializer<'a, 'de, E> { + iter: <&'a [Content<'de>] as IntoIterator>::IntoIter, + count: usize, + marker: PhantomData, + } + + impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E> { + fn new(content: &'a [Content<'de>]) -> Self { + SeqRefDeserializer { + iter: content.iter(), + count: 0, + marker: PhantomData, + } + } + } + + impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E> + where + E: de::Error, + { + fn end(self) -> Result<(), E> { + let remaining = self.iter.count(); + if remaining == 0 { + Ok(()) + } else { + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length( + self.count + remaining, + &ExpectedInSeq(self.count), + )) + } + } + } + + impl<'a, 'de, E> Deserializer<'de> for SeqRefDeserializer<'a, 'de, E> + where + E: de::Error, + { + type Error = E; + + fn deserialize_any(mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let v = tri!(visitor.visit_seq(&mut self)); + tri!(self.end()); + Ok(v) + } + + serde_core::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<'a, 'de, E> SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E> + where + E: de::Error, + { + type Error = E; + + fn next_element_seed(&mut self, seed: V) -> Result, Self::Error> + where + V: DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => { + self.count += 1; + seed.deserialize(ContentRefDeserializer::new(value)) + .map(Some) + } + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + struct MapRefDeserializer<'a, 'de, E> { + iter: <&'a [(Content<'de>, Content<'de>)] as IntoIterator>::IntoIter, + value: Option<&'a Content<'de>>, + count: usize, + error: PhantomData, + } + + impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E> { + fn new(content: &'a [(Content<'de>, Content<'de>)]) -> Self { + MapRefDeserializer { + iter: content.iter(), + value: None, + count: 0, + error: PhantomData, + } + } + } + + impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E> + where + E: de::Error, + { + fn end(self) -> Result<(), E> { + let remaining = self.iter.count(); + if remaining == 0 { + Ok(()) + } else { + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length( + self.count + remaining, + &ExpectedInMap(self.count), + )) + } + } + } + + impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E> { + fn next_pair(&mut self) -> Option<(&'a Content<'de>, &'a Content<'de>)> { + match self.iter.next() { + Some((k, v)) => { + self.count += 1; + Some((k, v)) + } + None => None, + } + } + } + + impl<'a, 'de, E> Deserializer<'de> for MapRefDeserializer<'a, 'de, E> + where + E: de::Error, + { + type Error = E; + + fn deserialize_any(mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let value = tri!(visitor.visit_map(&mut self)); + tri!(self.end()); + Ok(value) + } + + fn deserialize_seq(mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let value = tri!(visitor.visit_seq(&mut self)); + tri!(self.end()); + Ok(value) + } + + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + let _ = len; + self.deserialize_seq(visitor) + } + + serde_core::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 tuple_struct map + struct enum identifier ignored_any + } + } + + impl<'a, 'de, E> MapAccess<'de> for MapRefDeserializer<'a, 'de, E> + where + E: de::Error, + { + type Error = E; + + fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>, + { + match self.next_pair() { + Some((key, value)) => { + self.value = Some(value); + seed.deserialize(ContentRefDeserializer::new(key)).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + let value = self.value.take(); + // Panic because this indicates a bug in the program rather than an + // expected failure. + let value = value.expect("MapAccess::next_value called before next_key"); + seed.deserialize(ContentRefDeserializer::new(value)) + } + + fn next_entry_seed( + &mut self, + kseed: TK, + vseed: TV, + ) -> Result, Self::Error> + where + TK: DeserializeSeed<'de>, + TV: DeserializeSeed<'de>, + { + match self.next_pair() { + Some((key, value)) => { + let key = tri!(kseed.deserialize(ContentRefDeserializer::new(key))); + let value = tri!(vseed.deserialize(ContentRefDeserializer::new(value))); + Ok(Some((key, value))) + } + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + impl<'a, 'de, E> SeqAccess<'de> for MapRefDeserializer<'a, 'de, E> + where + E: de::Error, + { + type Error = E; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.next_pair() { + Some((k, v)) => { + let de = PairRefDeserializer(k, v, PhantomData); + seed.deserialize(de).map(Some) + } + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + size_hint::from_bounds(&self.iter) + } + } + + struct PairRefDeserializer<'a, 'de, E>(&'a Content<'de>, &'a Content<'de>, PhantomData); + + impl<'a, 'de, E> Deserializer<'de> for PairRefDeserializer<'a, 'de, E> + where + E: de::Error, + { + type Error = E; + + serde_core::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 tuple_struct map + struct enum identifier ignored_any + } + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let mut pair_visitor = PairRefVisitor(Some(self.0), Some(self.1), PhantomData); + let pair = tri!(visitor.visit_seq(&mut pair_visitor)); + if pair_visitor.1.is_none() { + Ok(pair) + } else { + let remaining = pair_visitor.size_hint().unwrap(); + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length(2, &ExpectedInSeq(2 - remaining))) + } + } + + fn deserialize_tuple(self, len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + if len == 2 { + self.deserialize_seq(visitor) + } else { + // First argument is the number of elements in the data, second + // argument is the number of elements expected by the Deserialize. + Err(de::Error::invalid_length(2, &ExpectedInSeq(len))) + } + } + } + + struct PairRefVisitor<'a, 'de, E>( + Option<&'a Content<'de>>, + Option<&'a Content<'de>>, + PhantomData, + ); + + impl<'a, 'de, E> SeqAccess<'de> for PairRefVisitor<'a, 'de, E> + where + E: de::Error, + { + type Error = E; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>, + { + if let Some(k) = self.0.take() { + seed.deserialize(ContentRefDeserializer::new(k)).map(Some) + } else if let Some(v) = self.1.take() { + seed.deserialize(ContentRefDeserializer::new(v)).map(Some) + } else { + Ok(None) + } + } + + fn size_hint(&self) -> Option { + if self.0.is_some() { + Some(2) + } else if self.1.is_some() { + Some(1) + } else { + Some(0) + } + } + } + struct EnumRefDeserializer<'a, 'de: 'a, E> where E: de::Error,