Merge pull request #2968 from dtolnay/deserializecontent

Restore `__deserialize_content` optimization
This commit is contained in:
David Tolnay 2025-09-13 14:26:50 -07:00 committed by GitHub
commit 260511d149
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 1048 additions and 340 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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 {

View File

@ -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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de, Value = crate::private::Content<'de>>,
{
self.deserialize_any(visitor)
}
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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;

265
serde_core/src/private.rs Normal file
View File

@ -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<u8>),
Bytes(&'de [u8]),
None,
Some(Box<Content<'de>>),
Unit,
Newtype(Box<Content<'de>>),
Seq(Vec<Content<'de>>),
Map(Vec<(Content<'de>, Content<'de>)>),
}
impl<'de> Deserialize<'de> for Content<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<Content<'de>>,
}
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<F>(self, value: bool) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::Bool(value))
}
fn visit_i8<F>(self, value: i8) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::I8(value))
}
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::I16(value))
}
fn visit_i32<F>(self, value: i32) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::I32(value))
}
fn visit_i64<F>(self, value: i64) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::I64(value))
}
fn visit_u8<F>(self, value: u8) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::U8(value))
}
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::U16(value))
}
fn visit_u32<F>(self, value: u32) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::U32(value))
}
fn visit_u64<F>(self, value: u64) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::U64(value))
}
fn visit_f32<F>(self, value: f32) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::F32(value))
}
fn visit_f64<F>(self, value: f64) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::F64(value))
}
fn visit_char<F>(self, value: char) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::Char(value))
}
fn visit_str<F>(self, value: &str) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::String(value.into()))
}
fn visit_borrowed_str<F>(self, value: &'de str) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::Str(value))
}
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::String(value))
}
fn visit_bytes<F>(self, value: &[u8]) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::ByteBuf(value.into()))
}
fn visit_borrowed_bytes<F>(self, value: &'de [u8]) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::Bytes(value))
}
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::ByteBuf(value))
}
fn visit_unit<F>(self) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::Unit)
}
fn visit_none<F>(self) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::None)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
let v = tri!(Deserialize::deserialize(deserializer));
Ok(Content::Some(Box::new(v)))
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
let v = tri!(Deserialize::deserialize(deserializer));
Ok(Content::Newtype(Box::new(v)))
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: SeqAccess<'de>,
{
let mut vec =
Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint()));
while let Some(e) = tri!(visitor.next_element()) {
vec.push(e);
}
Ok(Content::Seq(vec))
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
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<V>(self, _visitor: V) -> Result<Self::Value, V::Error>
where
V: EnumAccess<'de>,
{
Err(de::Error::custom(
"untagged and internally tagged enums do not support enum input",
))
}
}

View File

@ -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 {