/// Deserialization module. use alloc::{ borrow::ToOwned, string::{String, ToString}, vec::Vec, }; use core::str; use serde::{ de::{self, DeserializeSeed, Deserializer as _, Visitor}, Deserialize, }; pub use crate::error::{Error, Position, Span, SpannedError}; use crate::{ error::{Result, SpannedResult}, extensions::Extensions, options::Options, parse::{NewtypeMode, ParsedByteStr, ParsedStr, Parser, StructType, TupleMode}, }; #[cfg(feature = "std")] use std::io; mod id; mod tag; #[cfg(test)] mod tests; mod value; /// The RON deserializer. /// /// If you just want to simply deserialize a value, /// you can use the [`from_str`] convenience function. pub struct Deserializer<'de> { pub(crate) parser: Parser<'de>, newtype_variant: bool, serde_content_newtype: bool, last_identifier: Option<&'de str>, recursion_limit: Option, } impl<'de> Deserializer<'de> { // Cannot implement trait here since output is tied to input lifetime 'de. #[allow(clippy::should_implement_trait)] pub fn from_str(input: &'de str) -> SpannedResult { Self::from_str_with_options(input, &Options::default()) } pub fn from_bytes(input: &'de [u8]) -> SpannedResult { Self::from_bytes_with_options(input, &Options::default()) } pub fn from_str_with_options(input: &'de str, options: &Options) -> SpannedResult { let mut deserializer = Deserializer { parser: Parser::new(input)?, newtype_variant: false, serde_content_newtype: false, last_identifier: None, recursion_limit: options.recursion_limit, }; deserializer.parser.exts |= options.default_extensions; Ok(deserializer) } // FIXME: panic is not actually possible, remove once utf8_chunks is stabilized #[allow(clippy::missing_panics_doc)] pub fn from_bytes_with_options(input: &'de [u8], options: &Options) -> SpannedResult { let err = match str::from_utf8(input) { Ok(input) => return Self::from_str_with_options(input, options), Err(err) => err, }; // FIXME: use [`utf8_chunks`](https://github.com/rust-lang/rust/issues/99543) once stabilised #[allow(clippy::expect_used)] let valid_input = str::from_utf8(&input[..err.valid_up_to()]).expect("source is valid up to error"); Err(SpannedError { code: err.into(), span: Span { start: Position { line: 1, col: 1 }, end: Position::from_src_end(valid_input), }, }) } #[must_use] pub fn remainder(&self) -> &'de str { self.parser.src() } #[must_use] pub fn span_error(&self, code: Error) -> SpannedError { self.parser.span_error(code) } #[must_use] pub fn extensions(&self) -> Extensions { self.parser.exts } } /// A convenience function for building a deserializer /// and deserializing a value of type `T` from a reader. #[cfg(feature = "std")] pub fn from_reader(rdr: R) -> SpannedResult where R: io::Read, T: de::DeserializeOwned, { Options::default().from_reader(rdr) } /// A convenience function for building a deserializer /// and deserializing a value of type `T` from a string. pub fn from_str<'a, T>(s: &'a str) -> SpannedResult where T: de::Deserialize<'a>, { Options::default().from_str(s) } /// A convenience function for building a deserializer /// and deserializing a value of type `T` from bytes. pub fn from_bytes<'a, T>(s: &'a [u8]) -> SpannedResult where T: de::Deserialize<'a>, { Options::default().from_bytes(s) } macro_rules! guard_recursion { ($self:expr => $expr:expr) => {{ if let Some(limit) = &mut $self.recursion_limit { if let Some(new_limit) = limit.checked_sub(1) { *limit = new_limit; } else { return Err(Error::ExceededRecursionLimit); } } let result = $expr; if let Some(limit) = &mut $self.recursion_limit { *limit = limit.saturating_add(1); } result }}; } impl<'de> Deserializer<'de> { /// Check if the remaining bytes are whitespace only, /// otherwise return an error. pub fn end(&mut self) -> Result<()> { self.parser.skip_ws()?; if self.parser.src().is_empty() { Ok(()) } else { Err(Error::TrailingCharacters) } } /// Called from [`deserialize_any`][serde::Deserializer::deserialize_any] /// when a struct was detected. Decides if there is a unit, tuple or usual /// struct and deserializes it accordingly. /// /// This method assumes there is no identifier left. fn handle_any_struct(&mut self, visitor: V, ident: Option<&str>) -> Result where V: Visitor<'de>, { // HACK: switch to JSON enum semantics for JSON content // Robust impl blocked on https://github.com/serde-rs/serde/issues/1183 let is_serde_content = is_serde_content::() || is_serde_tag_or_content::(); let old_serde_content_newtype = self.serde_content_newtype; self.serde_content_newtype = false; match ( self.parser.check_struct_type( NewtypeMode::NoParensMeanUnit, if old_serde_content_newtype { TupleMode::DifferentiateNewtype // separate match on NewtypeOrTuple below } else { TupleMode::ImpreciseTupleOrNewtype // Tuple and NewtypeOrTuple match equally }, )?, ident, ) { (StructType::Unit, Some(ident)) if is_serde_content => { // serde's Content type needs the ident for unit variants visitor.visit_str(ident) } (StructType::Unit, _) => visitor.visit_unit(), (_, Some(ident)) if is_serde_content => { // serde's Content type uses a singleton map encoding for enums visitor.visit_map(SerdeEnumContent { de: self, ident: Some(ident), }) } (StructType::Named, _) => { // giving no name results in worse errors but is necessary here self.handle_struct_after_name("", visitor) } (StructType::NewtypeTuple, _) if old_serde_content_newtype => { // deserialize a newtype struct or variant self.parser.consume_char('('); self.parser.skip_ws()?; let result = self.deserialize_any(visitor); self.parser.skip_ws()?; self.parser.consume_char(')'); result } ( StructType::AnyTuple | StructType::EmptyTuple | StructType::NewtypeTuple | StructType::NonNewtypeTuple, _, ) => { // first argument is technically incorrect, but ignored anyway self.deserialize_tuple(0, visitor) } } } /// Called from /// [`deserialize_struct`][serde::Deserializer::deserialize_struct], /// [`struct_variant`][serde::de::VariantAccess::struct_variant], and /// [`handle_any_struct`][Self::handle_any_struct]. Handles /// deserialising the enclosing parentheses and everything in between. /// /// This method assumes there is no struct name identifier left. fn handle_struct_after_name( &mut self, name_for_pretty_errors_only: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { if self.newtype_variant || self.parser.consume_char('(') { let old_newtype_variant = self.newtype_variant; self.newtype_variant = false; let value = guard_recursion! { self => visitor .visit_map(CommaSeparated::new(Terminator::Struct, self)) .map_err(|err| { struct_error_name( err, if !old_newtype_variant && !name_for_pretty_errors_only.is_empty() { Some(name_for_pretty_errors_only) } else { None }, ) })? }; self.parser.skip_ws()?; if old_newtype_variant || self.parser.consume_char(')') { Ok(value) } else { Err(Error::ExpectedStructLikeEnd) } } else if name_for_pretty_errors_only.is_empty() { Err(Error::ExpectedStructLike) } else { Err(Error::ExpectedNamedStructLike(name_for_pretty_errors_only)) } } } impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { if self.newtype_variant { if self.parser.check_char(')') { // newtype variant wraps the unit type / a unit struct without name return self.deserialize_unit(visitor); } #[allow(clippy::wildcard_in_or_patterns)] match self .parser .check_struct_type(NewtypeMode::InsideNewtype, TupleMode::DifferentiateNewtype)? { StructType::Named => { // newtype variant wraps a named struct // giving no name results in worse errors but is necessary here return self.handle_struct_after_name("", visitor); } StructType::EmptyTuple | StructType::NonNewtypeTuple => { // newtype variant wraps a tuple (struct) // first argument is technically incorrect, but ignored anyway return self.deserialize_tuple(0, visitor); } // StructType::Unit is impossible with NewtypeMode::InsideNewtype // StructType::AnyTuple is impossible with TupleMode::DifferentiateNewtype StructType::NewtypeTuple | _ => { // continue as usual with the inner content of the newtype variant self.newtype_variant = false; } } } if self.parser.consume_ident("true") { return visitor.visit_bool(true); } else if self.parser.consume_ident("false") { return visitor.visit_bool(false); } else if self.parser.check_ident("Some") { return self.deserialize_option(visitor); } else if self.parser.consume_ident("None") { return visitor.visit_none(); } else if self.parser.consume_str("()") { return visitor.visit_unit(); } else if self.parser.consume_ident("inf") || self.parser.consume_ident("inff32") { return visitor.visit_f32(core::f32::INFINITY); } else if self.parser.consume_ident("inff64") { return visitor.visit_f64(core::f64::INFINITY); } else if self.parser.consume_ident("NaN") || self.parser.consume_ident("NaNf32") { return visitor.visit_f32(core::f32::NAN); } else if self.parser.consume_ident("NaNf64") { return visitor.visit_f64(core::f64::NAN); } // `skip_identifier` does not change state if it fails if let Some(ident) = self.parser.skip_identifier() { self.parser.skip_ws()?; return self.handle_any_struct(visitor, Some(ident)); } match self.parser.peek_char_or_eof()? { '(' => self.handle_any_struct(visitor, None), '[' => self.deserialize_seq(visitor), '{' => self.deserialize_map(visitor), '0'..='9' | '+' | '-' | '.' => self.parser.any_number()?.visit(visitor), '"' | 'r' => self.deserialize_string(visitor), 'b' if self.parser.src().starts_with("b'") => self.parser.any_number()?.visit(visitor), 'b' => self.deserialize_byte_buf(visitor), '\'' => self.deserialize_char(visitor), other => Err(Error::UnexpectedChar(other)), } } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_bool(self.parser.bool()?) } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i8(self.parser.integer()?) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i16(self.parser.integer()?) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i32(self.parser.integer()?) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i64(self.parser.integer()?) } #[cfg(feature = "integer128")] fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_i128(self.parser.integer()?) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u8(self.parser.integer()?) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u16(self.parser.integer()?) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u32(self.parser.integer()?) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u64(self.parser.integer()?) } #[cfg(feature = "integer128")] fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_u128(self.parser.integer()?) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_f32(self.parser.float()?) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_f64(self.parser.float()?) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_char(self.parser.char()?) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { match self.parser.string()? { ParsedStr::Allocated(s) => visitor.visit_string(s), ParsedStr::Slice(s) => visitor.visit_borrowed_str(s), } } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_byte_buf(visitor) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { if self.parser.check_char('[') { let bytes = Vec::::deserialize(self)?; return visitor.visit_byte_buf(bytes); } match self.parser.byte_string()? { ParsedByteStr::Allocated(byte_buf) => visitor.visit_byte_buf(byte_buf), ParsedByteStr::Slice(bytes) => visitor.visit_borrowed_bytes(bytes), } } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { if self.parser.consume_ident("None") { visitor.visit_none() } else if self.parser.consume_ident("Some") && { self.parser.skip_ws()?; self.parser.consume_char('(') } { self.parser.skip_ws()?; self.newtype_variant = self .parser .exts .contains(Extensions::UNWRAP_VARIANT_NEWTYPES); let v = guard_recursion! { self => visitor.visit_some(&mut *self)? }; self.newtype_variant = false; self.parser.comma()?; if self.parser.consume_char(')') { Ok(v) } else { Err(Error::ExpectedOptionEnd) } } else if self.parser.exts.contains(Extensions::IMPLICIT_SOME) { guard_recursion! { self => visitor.visit_some(&mut *self) } } else { Err(Error::ExpectedOption) } } // In Serde, unit means an anonymous value containing no data. fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { if self.newtype_variant || self.parser.consume_str("()") { self.newtype_variant = false; visitor.visit_unit() } else { Err(Error::ExpectedUnit) } } fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { if self.newtype_variant || self.parser.consume_struct_name(name)? { self.newtype_variant = false; visitor.visit_unit() } else { self.deserialize_unit(visitor) } } fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { if name == crate::value::raw::RAW_VALUE_TOKEN { let src_before = self.parser.pre_ws_src(); self.parser.skip_ws()?; let _ignored = self.deserialize_ignored_any(de::IgnoredAny)?; self.parser.skip_ws()?; let src_after = self.parser.src(); if self.parser.has_unclosed_line_comment() { return Err(Error::UnclosedLineComment); } let ron_str = &src_before[..src_before.len() - src_after.len()]; return visitor .visit_borrowed_str::(ron_str) .map_err(|_| Error::ExpectedRawValue); } if self.parser.exts.contains(Extensions::UNWRAP_NEWTYPES) || self.newtype_variant { self.newtype_variant = false; return guard_recursion! { self => visitor.visit_newtype_struct(&mut *self) }; } self.parser.consume_struct_name(name)?; self.parser.skip_ws()?; if self.parser.consume_char('(') { self.parser.skip_ws()?; let value = guard_recursion! { self => visitor.visit_newtype_struct(&mut *self)? }; self.parser.comma()?; if self.parser.consume_char(')') { Ok(value) } else { Err(Error::ExpectedStructLikeEnd) } } else if name.is_empty() { Err(Error::ExpectedStructLike) } else { Err(Error::ExpectedNamedStructLike(name)) } } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { self.newtype_variant = false; if self.parser.consume_char('[') { let value = guard_recursion! { self => visitor.visit_seq(CommaSeparated::new(Terminator::Seq, self))? }; self.parser.skip_ws()?; if self.parser.consume_char(']') { Ok(value) } else { Err(Error::ExpectedArrayEnd) } } else { Err(Error::ExpectedArray) } } fn deserialize_tuple(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { if self.newtype_variant || self.parser.consume_char('(') { let old_newtype_variant = self.newtype_variant; self.newtype_variant = false; let value = guard_recursion! { self => visitor.visit_seq(CommaSeparated::new(Terminator::Tuple, self))? }; self.parser.skip_ws()?; if old_newtype_variant || self.parser.consume_char(')') { Ok(value) } else { Err(Error::ExpectedStructLikeEnd) } } else { Err(Error::ExpectedStructLike) } } fn deserialize_tuple_struct( self, name: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { if !self.newtype_variant { self.parser.consume_struct_name(name)?; } self.deserialize_tuple(len, visitor).map_err(|e| match e { Error::ExpectedStructLike if !name.is_empty() => Error::ExpectedNamedStructLike(name), e => e, }) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { struct VisitorExpecting(V); impl<'de, V: Visitor<'de>> core::fmt::Display for VisitorExpecting<&'_ V> { fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { self.0.expecting(fmt) } } self.newtype_variant = false; // TODO: Avoid allocating to perform this check. let serde_flatten_canary = VisitorExpecting(&visitor) .to_string() .starts_with("struct "); let terminator = if serde_flatten_canary { Terminator::MapAsStruct } else { Terminator::Map }; if self.parser.consume_char('{') { let value = guard_recursion! { self => visitor.visit_map(CommaSeparated::new(terminator, self))? }; self.parser.skip_ws()?; if self.parser.consume_char('}') { Ok(value) } else { Err(Error::ExpectedMapEnd) } } else { Err(Error::ExpectedMap) } } fn deserialize_struct( self, name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { if !self.newtype_variant { self.parser.consume_struct_name(name)?; } self.parser.skip_ws()?; self.handle_struct_after_name(name, visitor) } fn deserialize_enum( self, name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.newtype_variant = false; match guard_recursion! { self => visitor.visit_enum(Enum::new(self)) } { Ok(value) => Ok(value), Err(Error::NoSuchEnumVariant { expected, found, outer: None, }) if !name.is_empty() => Err(Error::NoSuchEnumVariant { expected, found, outer: Some(String::from(name)), }), Err(e) => Err(e), } } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { let identifier = self.parser.identifier()?; self.last_identifier = Some(identifier); visitor.visit_borrowed_str(identifier) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_any(visitor) } } enum Terminator { Map, MapAsStruct, Tuple, Struct, Seq, } impl Terminator { fn as_char(&self) -> char { match self { Terminator::Map | Terminator::MapAsStruct => '}', Terminator::Tuple | Terminator::Struct => ')', Terminator::Seq => ']', } } } struct CommaSeparated<'a, 'de: 'a> { de: &'a mut Deserializer<'de>, terminator: Terminator, had_comma: bool, inside_internally_tagged_enum: bool, } impl<'a, 'de> CommaSeparated<'a, 'de> { fn new(terminator: Terminator, de: &'a mut Deserializer<'de>) -> Self { CommaSeparated { de, terminator, had_comma: true, inside_internally_tagged_enum: false, } } fn has_element(&mut self) -> Result { self.de.parser.skip_ws()?; match ( self.had_comma, !self.de.parser.check_char(self.terminator.as_char()), ) { // Trailing comma, maybe has a next element (true, has_element) => Ok(has_element), // No trailing comma but terminator (false, false) => Ok(false), // No trailing comma or terminator (false, true) => Err(Error::ExpectedComma), } } } impl<'de, 'a> de::SeqAccess<'de> for CommaSeparated<'a, 'de> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> where T: DeserializeSeed<'de>, { if self.has_element()? { let res = guard_recursion! { self.de => seed.deserialize(&mut *self.de)? }; self.had_comma = self.de.parser.comma()?; Ok(Some(res)) } else { Ok(None) } } } impl<'de, 'a> de::MapAccess<'de> for CommaSeparated<'a, 'de> { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> where K: DeserializeSeed<'de>, { if self.has_element()? { self.inside_internally_tagged_enum = is_serde_tag_or_content::(); match self.terminator { Terminator::Struct => guard_recursion! { self.de => seed.deserialize(&mut id::Deserializer::new(&mut *self.de, false)).map(Some) }, Terminator::MapAsStruct => guard_recursion! { self.de => seed.deserialize(&mut id::Deserializer::new(&mut *self.de, true)).map(Some) }, _ => guard_recursion! { self.de => seed.deserialize(&mut *self.de).map(Some) }, } } else { Ok(None) } } fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, { self.de.parser.skip_ws()?; if self.de.parser.consume_char(':') { self.de.parser.skip_ws()?; let res = if self.inside_internally_tagged_enum && !is_serde_content::() { guard_recursion! { self.de => seed.deserialize(&mut tag::Deserializer::new(&mut *self.de))? } } else { guard_recursion! { self.de => seed.deserialize(&mut *self.de)? } }; self.had_comma = self.de.parser.comma()?; Ok(res) } else { Err(Error::ExpectedMapColon) } } } struct Enum<'a, 'de: 'a> { de: &'a mut Deserializer<'de>, } impl<'a, 'de> Enum<'a, 'de> { fn new(de: &'a mut Deserializer<'de>) -> Self { Enum { de } } } impl<'de, 'a> de::EnumAccess<'de> for Enum<'a, 'de> { type Error = Error; type Variant = Self; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>, { self.de.parser.skip_ws()?; let value = guard_recursion! { self.de => seed.deserialize(&mut *self.de)? }; Ok((value, self)) } } impl<'de, 'a> de::VariantAccess<'de> for Enum<'a, 'de> { type Error = Error; fn unit_variant(self) -> Result<()> { Ok(()) } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { let newtype_variant = self.de.last_identifier; self.de.parser.skip_ws()?; if self.de.parser.consume_char('(') { self.de.parser.skip_ws()?; self.de.newtype_variant = self .de .parser .exts .contains(Extensions::UNWRAP_VARIANT_NEWTYPES); let val = guard_recursion! { self.de => seed .deserialize(&mut *self.de) .map_err(|err| struct_error_name(err, newtype_variant))? }; self.de.newtype_variant = false; self.de.parser.comma()?; if self.de.parser.consume_char(')') { Ok(val) } else { Err(Error::ExpectedStructLikeEnd) } } else { Err(Error::ExpectedStructLike) } } fn tuple_variant(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.de.parser.skip_ws()?; self.de.deserialize_tuple(len, visitor) } fn struct_variant(self, _fields: &'static [&'static str], visitor: V) -> Result where V: Visitor<'de>, { let struct_variant = self.de.last_identifier; self.de.parser.skip_ws()?; self.de .handle_struct_after_name("", visitor) .map_err(|err| struct_error_name(err, struct_variant)) } } fn struct_error_name(error: Error, name: Option<&str>) -> Error { match error { Error::NoSuchStructField { expected, found, outer: None, } => Error::NoSuchStructField { expected, found, outer: name.map(ToOwned::to_owned), }, Error::MissingStructField { field, outer: None } => Error::MissingStructField { field, outer: name.map(ToOwned::to_owned), }, Error::DuplicateStructField { field, outer: None } => Error::DuplicateStructField { field, outer: name.map(ToOwned::to_owned), }, e => e, } } struct SerdeEnumContent<'a, 'de: 'a> { de: &'a mut Deserializer<'de>, ident: Option<&'a str>, } impl<'de, 'a> de::MapAccess<'de> for SerdeEnumContent<'a, 'de> { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> where K: DeserializeSeed<'de>, { self.ident .take() .map(|ident| seed.deserialize(de::value::StrDeserializer::new(ident))) .transpose() } fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, { self.de.parser.skip_ws()?; let old_serde_content_newtype = self.de.serde_content_newtype; self.de.serde_content_newtype = true; let result = seed.deserialize(&mut *self.de); self.de.serde_content_newtype = old_serde_content_newtype; result } } fn is_serde_content() -> bool { #[derive(serde_derive::Deserialize)] enum A {} type B = A; #[derive(serde_derive::Deserialize)] #[serde(untagged)] enum UntaggedEnum { A(A), B(B), } struct TypeIdDeserializer; impl<'de> de::Deserializer<'de> for TypeIdDeserializer { type Error = TypeIdError; fn deserialize_any>(self, _visitor: V) -> Result { Err(TypeIdError(typeid::of::())) } serde::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 } } #[derive(Debug)] struct TypeIdError(core::any::TypeId); impl core::fmt::Display for TypeIdError { fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result { Ok(()) } } impl de::Error for TypeIdError { #[allow(clippy::unreachable)] fn custom(_msg: T) -> Self { unreachable!() } } impl de::StdError for TypeIdError {} fn type_id_of_untagged_enum_default_buffer() -> core::any::TypeId { static TYPE_ID: once_cell::race::OnceBox = once_cell::race::OnceBox::new(); *TYPE_ID.get_or_init(|| match Deserialize::deserialize(TypeIdDeserializer) { Ok(UntaggedEnum::A(void) | UntaggedEnum::B(void)) => match void {}, Err(TypeIdError(typeid)) => alloc::boxed::Box::new(typeid), }) } typeid::of::() == type_id_of_untagged_enum_default_buffer() } fn is_serde_tag_or_content() -> bool { #[derive(serde_derive::Deserialize)] enum A {} #[derive(serde_derive::Deserialize)] #[serde(tag = "tag")] enum InternallyTaggedEnum { A { a: A }, } struct TypeIdDeserializer; impl<'de> de::Deserializer<'de> for TypeIdDeserializer { type Error = TypeIdError; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_map(self) } serde::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> de::MapAccess<'de> for TypeIdDeserializer { type Error = TypeIdError; fn next_key_seed>( &mut self, _seed: K, ) -> Result, Self::Error> { Err(TypeIdError(typeid::of::())) } #[allow(clippy::unreachable)] fn next_value_seed>( &mut self, _seed: V, ) -> Result { unreachable!() } } #[derive(Debug)] struct TypeIdError(core::any::TypeId); impl core::fmt::Display for TypeIdError { fn fmt(&self, _fmt: &mut core::fmt::Formatter) -> core::fmt::Result { Ok(()) } } impl de::Error for TypeIdError { #[allow(clippy::unreachable)] fn custom(_msg: T) -> Self { unreachable!() } } impl de::StdError for TypeIdError {} fn type_id_of_internally_tagged_enum_default_tag_or_buffer() -> core::any::TypeId { static TYPE_ID: once_cell::race::OnceBox = once_cell::race::OnceBox::new(); *TYPE_ID.get_or_init(|| match Deserialize::deserialize(TypeIdDeserializer) { Ok(InternallyTaggedEnum::A { a: void }) => match void {}, Err(TypeIdError(typeid)) => alloc::boxed::Box::new(typeid), }) } typeid::of::() == type_id_of_internally_tagged_enum_default_tag_or_buffer() }