From 518ffa4ae6add6d02543366ac257ee3ac2c9ac85 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 22 Mar 2025 14:52:46 -0700 Subject: [PATCH] Customizable buffer type (proof of concept) --- serde/src/de/mod.rs | 37 +++++++++++++++++++++++++++++++++++++ serde/src/lib.rs | 1 + serde/src/private/de.rs | 28 +++++++++++++++++++++++++++- serde_derive/src/de.rs | 8 ++++---- 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index b2cc64c86..79012641b 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1223,6 +1223,12 @@ pub trait Deserializer<'de>: Sized { true } + /// + fn deserialize_buffer(self) -> Result, Self::Error> { + let content = crate::__private::de::Content::deserialize(self)?; + Ok(crate::__private::de::ContentDeserializer::new(content)) + } + // Not public API. #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] #[doc(hidden)] @@ -1238,6 +1244,29 @@ pub trait Deserializer<'de>: Sized { } } +/// +pub trait Buffer<'de> { + /// + type Error: Error; + + /// + type OwnedDeserializer: Deserializer<'de, Error = Self::Error>; + + /// + type RefDeserializer<'a>: Deserializer<'de, Error = Self::Error> + Copy + where + 'de: 'a, + Self: 'a; + + /// + fn owned_deserializer(self) -> Self::OwnedDeserializer; + + /// + fn ref_deserializer<'a>(&'a self) -> Self::RefDeserializer<'a> + where + 'de: 'a; +} + //////////////////////////////////////////////////////////////////////////////// /// This trait represents a visitor that walks through a deserializer. @@ -1892,6 +1921,14 @@ pub trait MapAccess<'de> { fn size_hint(&self) -> Option { None } + + /// + fn next_value_buffer( + &mut self, + ) -> Result + use<'de, Self>, Self::Error> { + let content = self.next_value::()?; + Ok(crate::__private::de::ContentDeserializer::new(content)) + } } impl<'de, A> MapAccess<'de> for &mut A diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 84b5cd7e8..1dd25a28d 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -94,6 +94,7 @@ //////////////////////////////////////////////////////////////////////////////// +#![feature(precise_capturing_in_traits)] // Serde types in rustdoc of other crates get linked to here. #![doc(html_root_url = "https://docs.rs/serde/1.0.219")] // Support using Serde without the standard library! diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index af5878bbb..3c426b075 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -211,7 +211,7 @@ mod content { use crate::actually_private; use crate::de::value::{MapDeserializer, SeqDeserializer}; use crate::de::{ - self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, + self, size_hint, Buffer, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, }; @@ -324,6 +324,32 @@ mod content { } } + impl<'de, E> Buffer<'de> for ContentDeserializer<'de, E> + where + E: de::Error, + { + type Error = E; + + type OwnedDeserializer = Self; + + type RefDeserializer<'a> + = ContentRefDeserializer<'a, 'de, E> + where + 'de: 'a, + E: 'a; + + fn owned_deserializer(self) -> Self::OwnedDeserializer { + self + } + + fn ref_deserializer<'a>(&'a self) -> Self::RefDeserializer<'a> + where + 'de: 'a, + { + ContentRefDeserializer::new(&self.content) + } + } + /// Used to capture data in [`Content`] from other deserializers. /// Cannot capture externally tagged enums, `i128` and `u128`. struct ContentVisitor<'de> { diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 4967e35d1..c47e63377 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1669,12 +1669,12 @@ 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_buffer(&mut __map)?; // Visit the second key. match #next_relevant_key { // Second key is the tag. _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => { - let __deserializer = _serde::__private::de::ContentDeserializer::<__A::Error>::new(__content); + let __deserializer = _serde::de::Buffer::owned_deserializer(__content); #finish_content_then_tag } // Second key is a duplicate of the content. @@ -1789,8 +1789,8 @@ fn deserialize_untagged_enum_after( }); quote_block! { - let __content = <_serde::__private::de::Content as _serde::Deserialize>::deserialize(__deserializer)?; - let __deserializer = _serde::__private::de::ContentRefDeserializer::<__D::Error>::new(&__content); + let __content = _serde::Deserializer::deserialize_buffer(__deserializer)?; + let __deserializer = _serde::de::Buffer::ref_deserializer(&__content); #first_attempt