From 56bd3694227fa9d02e85ee1493f9709f241995e8 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 1 Jan 2022 12:36:58 -0800 Subject: [PATCH] Optimize deserialization of recursive buffered types --- serde/src/de/mod.rs | 14 ++++++++++++++ serde/src/lib.rs | 5 +++++ serde/src/private/de.rs | 29 +++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 54e2fd646..12e5b7eae 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -1213,6 +1213,20 @@ pub trait Deserializer<'de>: Sized { fn is_human_readable(&self) -> bool { true } + + // Not public API. + #[cfg(all(serde_derive, any(feature = "std", feature = "alloc")))] + #[doc(hidden)] + fn __deserialize_content( + self, + _: ::actually_private::T, + visitor: V, + ) -> Result<::private::de::Content<'de>, Self::Error> + where + V: Visitor<'de, Value = ::private::de::Content<'de>>, + { + self.deserialize_any(visitor) + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/serde/src/lib.rs b/serde/src/lib.rs index f6a8ac000..f5b24bc43 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -295,3 +295,8 @@ extern crate serde_derive; #[cfg(feature = "serde_derive")] #[doc(hidden)] pub use serde_derive::*; + +#[cfg(all(serde_derive, any(feature = "std", feature = "alloc")))] +mod actually_private { + pub struct T; +} diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index a387d404e..f0697d64f 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -206,6 +206,7 @@ mod content { use lib::*; use __private::size_hint; + use actually_private; use de::{ self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, @@ -215,7 +216,7 @@ mod content { /// deserializing untagged enums and internally tagged enums. /// /// Not public API. Use serde-value instead. - #[derive(Debug)] + #[derive(Debug, Clone)] pub enum Content<'de> { Bool(bool), @@ -294,7 +295,7 @@ mod content { // Untagged and internally tagged enums are only supported in // self-describing formats. let visitor = ContentVisitor { value: PhantomData }; - deserializer.deserialize_any(visitor) + deserializer.__deserialize_content(actually_private::T, visitor) } } @@ -1427,6 +1428,18 @@ mod content { drop(self); visitor.visit_unit() } + + fn __deserialize_content( + self, + _: actually_private::T, + visitor: V, + ) -> Result, Self::Error> + where + V: Visitor<'de, Value = Content<'de>>, + { + let _ = visitor; + Ok(self.content) + } } impl<'de, E> ContentDeserializer<'de, E> { @@ -2138,6 +2151,18 @@ mod content { { visitor.visit_unit() } + + fn __deserialize_content( + self, + _: actually_private::T, + visitor: V, + ) -> Result, Self::Error> + where + V: Visitor<'de, Value = Content<'de>>, + { + let _ = visitor; + Ok(self.content.clone()) + } } impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> {