From 6ce6ad6f3850ec513ed93d9503753f738be295a7 Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Sat, 3 Feb 2024 14:47:21 -0500 Subject: [PATCH 1/2] Add FlatMapDeserializerError --- serde/src/private/de.rs | 79 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/serde/src/private/de.rs b/serde/src/private/de.rs index 883e6909c..2f3275428 100644 --- a/serde/src/private/de.rs +++ b/serde/src/private/de.rs @@ -7,7 +7,7 @@ use crate::de::{ }; #[cfg(any(feature = "std", feature = "alloc"))] -use crate::de::{MapAccess, Unexpected}; +use crate::de::{Expected, MapAccess, StdError, Unexpected}; #[cfg(any(feature = "std", feature = "alloc"))] pub use self::content::{ @@ -2586,6 +2586,72 @@ where } } +#[cfg(any(feature = "std", feature = "alloc"))] +#[derive(Debug)] +pub enum FlatMapDeserializerError { + Inner(E), + NoVariantFoundInFlattenedData(&'static str), +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl Display for FlatMapDeserializerError +where + E: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + FlatMapDeserializerError::Inner(e) => write!(f, "{}", e), + FlatMapDeserializerError::NoVariantFoundInFlattenedData(name) => { + write!(f, "no variant of enum {} found in flattened data", name) + } + } + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl StdError for FlatMapDeserializerError where E: StdError {} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl Error for FlatMapDeserializerError +where + E: Error, +{ + fn custom(msg: T) -> Self + where + T: Display, + { + FlatMapDeserializerError::Inner(Error::custom(msg)) + } + + fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self { + FlatMapDeserializerError::Inner(Error::invalid_type(unexp, exp)) + } + + fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self { + FlatMapDeserializerError::Inner(Error::invalid_value(unexp, exp)) + } + + fn invalid_length(len: usize, exp: &Expected) -> Self { + FlatMapDeserializerError::Inner(Error::invalid_length(len, exp)) + } + + fn unknown_variant(variant: &str, exp: &'static [&'static str]) -> Self { + FlatMapDeserializerError::Inner(Error::unknown_variant(variant, exp)) + } + + fn unknown_field(field: &str, exp: &'static [&'static str]) -> Self { + FlatMapDeserializerError::Inner(Error::unknown_field(field, exp)) + } + + fn missing_field(field: &'static str) -> Self { + FlatMapDeserializerError::Inner(Error::missing_field(field)) + } + + fn duplicate_field(field: &'static str) -> Self { + FlatMapDeserializerError::Inner(Error::duplicate_field(field)) + } +} + #[cfg(any(feature = "std", feature = "alloc"))] pub struct FlatMapDeserializer<'a, 'de: 'a, E>( pub &'a mut Vec, Content<'de>)>>, @@ -2597,7 +2663,7 @@ impl<'a, 'de, E> FlatMapDeserializer<'a, 'de, E> where E: Error, { - fn deserialize_other() -> Result { + fn deserialize_other() -> Result> { Err(Error::custom("can only flatten structs and maps")) } } @@ -2621,7 +2687,7 @@ impl<'a, 'de, E> Deserializer<'de> for FlatMapDeserializer<'a, 'de, E> where E: Error, { - type Error = E; + type Error = FlatMapDeserializerError; fn deserialize_any(self, visitor: V) -> Result where @@ -2645,10 +2711,9 @@ where } } - Err(Error::custom(format_args!( - "no variant of enum {} found in flattened data", - name - ))) + Err(FlatMapDeserializerError::NoVariantFoundInFlattenedData( + name, + )) } fn deserialize_map(self, visitor: V) -> Result From 0c1b047834da51d5527822b2174af550418e977a Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Sat, 3 Feb 2024 14:47:30 -0500 Subject: [PATCH 2/2] Support flattened enum with default attributes --- serde_derive/src/de.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index e3b737c61..b48e9fed7 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -2594,11 +2594,36 @@ fn deserialize_map( } Some(path) => quote!(#path), }; + + let no_variant_expr = if field.attrs.default().is_none() && cattrs.default().is_none() { + let span = field.original.span(); + quote_spanned!(span=> + return _serde::__private::Err( + _serde::de::Error::custom(_e) + ); + ) + } else { + let is_missing = Expr(expr_is_missing(field, cattrs)); + quote!(#is_missing) + }; + quote! { - let #name: #field_ty = #func( + let #name: #field_ty = match #func( _serde::__private::de::FlatMapDeserializer( &mut __collect, - _serde::__private::PhantomData))?; + _serde::__private::PhantomData)) { + _serde::__private::Ok(#name) => #name, + _serde::__private::Err( + _e @ _serde::__private::de::FlatMapDeserializerError::NoVariantFoundInFlattenedData(..) + ) => { + #no_variant_expr + } + _serde::__private::Err( + _serde::__private::de::FlatMapDeserializerError::Inner(e) + ) => { + return _serde::__private::Err(e); + } + }; } });