mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-24 11:07:59 +00:00
478 lines
16 KiB
Rust
478 lines
16 KiB
Rust
//! Deserialization of struct field identifiers and enum variant identifiers by
|
|
//! way of a Rust enum.
|
|
|
|
use crate::de::{FieldWithAliases, Parameters};
|
|
use crate::fragment::{Fragment, Stmts};
|
|
use crate::internals::ast::{Style, Variant};
|
|
use crate::internals::attr;
|
|
use crate::private;
|
|
use proc_macro2::{Literal, TokenStream};
|
|
use quote::{quote, ToTokens};
|
|
|
|
// Generates `Deserialize::deserialize` body for an enum with
|
|
// `serde(field_identifier)` or `serde(variant_identifier)` attribute.
|
|
pub(super) fn deserialize_custom(
|
|
params: &Parameters,
|
|
variants: &[Variant],
|
|
cattrs: &attr::Container,
|
|
) -> Fragment {
|
|
let is_variant = match cattrs.identifier() {
|
|
attr::Identifier::Variant => true,
|
|
attr::Identifier::Field => false,
|
|
attr::Identifier::No => unreachable!(),
|
|
};
|
|
|
|
let this_type = params.this_type.to_token_stream();
|
|
let this_value = params.this_value.to_token_stream();
|
|
|
|
let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() {
|
|
let last_ident = &last.ident;
|
|
if last.attrs.other() {
|
|
// Process `serde(other)` attribute. It would always be found on the
|
|
// last variant (checked in `check_identifier`), so all preceding
|
|
// are ordinary variants.
|
|
let ordinary = &variants[..variants.len() - 1];
|
|
let fallthrough = quote!(_serde::#private::Ok(#this_value::#last_ident));
|
|
(ordinary, Some(fallthrough), None)
|
|
} else if let Style::Newtype = last.style {
|
|
let ordinary = &variants[..variants.len() - 1];
|
|
let fallthrough = |value| {
|
|
quote! {
|
|
_serde::#private::Result::map(
|
|
_serde::Deserialize::deserialize(
|
|
_serde::#private::de::IdentifierDeserializer::from(#value)
|
|
),
|
|
#this_value::#last_ident)
|
|
}
|
|
};
|
|
(
|
|
ordinary,
|
|
Some(fallthrough(quote!(__value))),
|
|
Some(fallthrough(quote!(_serde::#private::de::Borrowed(
|
|
__value
|
|
)))),
|
|
)
|
|
} else {
|
|
(variants, None, None)
|
|
}
|
|
} else {
|
|
(variants, None, None)
|
|
};
|
|
|
|
let idents_aliases: Vec<_> = ordinary
|
|
.iter()
|
|
.map(|variant| FieldWithAliases {
|
|
ident: variant.ident.clone(),
|
|
aliases: variant.attrs.aliases(),
|
|
})
|
|
.collect();
|
|
|
|
let names = idents_aliases.iter().flat_map(|variant| variant.aliases);
|
|
|
|
let names_const = if fallthrough.is_some() {
|
|
None
|
|
} else if is_variant {
|
|
let variants = quote! {
|
|
#[doc(hidden)]
|
|
const VARIANTS: &'static [&'static str] = &[ #(#names),* ];
|
|
};
|
|
Some(variants)
|
|
} else {
|
|
let fields = quote! {
|
|
#[doc(hidden)]
|
|
const FIELDS: &'static [&'static str] = &[ #(#names),* ];
|
|
};
|
|
Some(fields)
|
|
};
|
|
|
|
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
|
|
params.generics_with_de_lifetime();
|
|
let delife = params.borrowed.de_lifetime();
|
|
let visitor_impl = Stmts(deserialize_identifier(
|
|
&this_value,
|
|
&idents_aliases,
|
|
is_variant,
|
|
fallthrough,
|
|
fallthrough_borrowed,
|
|
false,
|
|
cattrs.expecting(),
|
|
));
|
|
|
|
quote_block! {
|
|
#names_const
|
|
|
|
#[doc(hidden)]
|
|
struct __FieldVisitor #de_impl_generics #where_clause {
|
|
marker: _serde::#private::PhantomData<#this_type #ty_generics>,
|
|
lifetime: _serde::#private::PhantomData<&#delife ()>,
|
|
}
|
|
|
|
#[automatically_derived]
|
|
impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause {
|
|
type Value = #this_type #ty_generics;
|
|
|
|
#visitor_impl
|
|
}
|
|
|
|
let __visitor = __FieldVisitor {
|
|
marker: _serde::#private::PhantomData::<#this_type #ty_generics>,
|
|
lifetime: _serde::#private::PhantomData,
|
|
};
|
|
_serde::Deserializer::deserialize_identifier(__deserializer, __visitor)
|
|
}
|
|
}
|
|
|
|
pub(super) fn deserialize_generated(
|
|
deserialized_fields: &[FieldWithAliases],
|
|
has_flatten: bool,
|
|
is_variant: bool,
|
|
ignore_variant: Option<TokenStream>,
|
|
fallthrough: Option<TokenStream>,
|
|
) -> Fragment {
|
|
let this_value = quote!(__Field);
|
|
let field_idents: &Vec<_> = &deserialized_fields
|
|
.iter()
|
|
.map(|field| &field.ident)
|
|
.collect();
|
|
|
|
let visitor_impl = Stmts(deserialize_identifier(
|
|
&this_value,
|
|
deserialized_fields,
|
|
is_variant,
|
|
fallthrough,
|
|
None,
|
|
!is_variant && has_flatten,
|
|
None,
|
|
));
|
|
|
|
let lifetime = if !is_variant && has_flatten {
|
|
Some(quote!(<'de>))
|
|
} else {
|
|
None
|
|
};
|
|
|
|
quote_block! {
|
|
#[allow(non_camel_case_types)]
|
|
#[doc(hidden)]
|
|
enum __Field #lifetime {
|
|
#(#field_idents,)*
|
|
#ignore_variant
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
struct __FieldVisitor;
|
|
|
|
#[automatically_derived]
|
|
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
|
|
type Value = __Field #lifetime;
|
|
|
|
#visitor_impl
|
|
}
|
|
|
|
#[automatically_derived]
|
|
impl<'de> _serde::Deserialize<'de> for __Field #lifetime {
|
|
#[inline]
|
|
fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result<Self, __D::Error>
|
|
where
|
|
__D: _serde::Deserializer<'de>,
|
|
{
|
|
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn deserialize_identifier(
|
|
this_value: &TokenStream,
|
|
deserialized_fields: &[FieldWithAliases],
|
|
is_variant: bool,
|
|
fallthrough: Option<TokenStream>,
|
|
fallthrough_borrowed: Option<TokenStream>,
|
|
collect_other_fields: bool,
|
|
expecting: Option<&str>,
|
|
) -> Fragment {
|
|
let str_mapping = deserialized_fields.iter().map(|field| {
|
|
let ident = &field.ident;
|
|
let aliases = field.aliases;
|
|
let private2 = private;
|
|
// `aliases` also contains a main name
|
|
quote! {
|
|
#(
|
|
#aliases => _serde::#private2::Ok(#this_value::#ident),
|
|
)*
|
|
}
|
|
});
|
|
let bytes_mapping = deserialized_fields.iter().map(|field| {
|
|
let ident = &field.ident;
|
|
// `aliases` also contains a main name
|
|
let aliases = field
|
|
.aliases
|
|
.iter()
|
|
.map(|alias| Literal::byte_string(alias.value.as_bytes()));
|
|
let private2 = private;
|
|
quote! {
|
|
#(
|
|
#aliases => _serde::#private2::Ok(#this_value::#ident),
|
|
)*
|
|
}
|
|
});
|
|
|
|
let expecting = expecting.unwrap_or(if is_variant {
|
|
"variant identifier"
|
|
} else {
|
|
"field identifier"
|
|
});
|
|
|
|
let bytes_to_str = if fallthrough.is_some() || collect_other_fields {
|
|
None
|
|
} else {
|
|
Some(quote! {
|
|
let __value = &_serde::#private::from_utf8_lossy(__value);
|
|
})
|
|
};
|
|
|
|
let (
|
|
value_as_str_content,
|
|
value_as_borrowed_str_content,
|
|
value_as_bytes_content,
|
|
value_as_borrowed_bytes_content,
|
|
) = if collect_other_fields {
|
|
(
|
|
Some(quote! {
|
|
let __value = _serde::#private::de::Content::String(_serde::#private::ToString::to_string(__value));
|
|
}),
|
|
Some(quote! {
|
|
let __value = _serde::#private::de::Content::Str(__value);
|
|
}),
|
|
Some(quote! {
|
|
let __value = _serde::#private::de::Content::ByteBuf(__value.to_vec());
|
|
}),
|
|
Some(quote! {
|
|
let __value = _serde::#private::de::Content::Bytes(__value);
|
|
}),
|
|
)
|
|
} else {
|
|
(None, None, None, None)
|
|
};
|
|
|
|
let fallthrough_arm_tokens;
|
|
let fallthrough_arm = if let Some(fallthrough) = &fallthrough {
|
|
fallthrough
|
|
} else if is_variant {
|
|
fallthrough_arm_tokens = quote! {
|
|
_serde::#private::Err(_serde::de::Error::unknown_variant(__value, VARIANTS))
|
|
};
|
|
&fallthrough_arm_tokens
|
|
} else {
|
|
fallthrough_arm_tokens = quote! {
|
|
_serde::#private::Err(_serde::de::Error::unknown_field(__value, FIELDS))
|
|
};
|
|
&fallthrough_arm_tokens
|
|
};
|
|
|
|
let visit_other = if collect_other_fields {
|
|
quote! {
|
|
fn visit_bool<__E>(self, __value: bool) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Bool(__value)))
|
|
}
|
|
|
|
fn visit_i8<__E>(self, __value: i8) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I8(__value)))
|
|
}
|
|
|
|
fn visit_i16<__E>(self, __value: i16) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I16(__value)))
|
|
}
|
|
|
|
fn visit_i32<__E>(self, __value: i32) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I32(__value)))
|
|
}
|
|
|
|
fn visit_i64<__E>(self, __value: i64) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I64(__value)))
|
|
}
|
|
|
|
fn visit_u8<__E>(self, __value: u8) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U8(__value)))
|
|
}
|
|
|
|
fn visit_u16<__E>(self, __value: u16) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U16(__value)))
|
|
}
|
|
|
|
fn visit_u32<__E>(self, __value: u32) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U32(__value)))
|
|
}
|
|
|
|
fn visit_u64<__E>(self, __value: u64) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U64(__value)))
|
|
}
|
|
|
|
fn visit_f32<__E>(self, __value: f32) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::F32(__value)))
|
|
}
|
|
|
|
fn visit_f64<__E>(self, __value: f64) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::F64(__value)))
|
|
}
|
|
|
|
fn visit_char<__E>(self, __value: char) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Char(__value)))
|
|
}
|
|
|
|
fn visit_unit<__E>(self) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
_serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Unit))
|
|
}
|
|
}
|
|
} else {
|
|
let u64_mapping = deserialized_fields.iter().enumerate().map(|(i, field)| {
|
|
let i = i as u64;
|
|
let ident = &field.ident;
|
|
quote!(#i => _serde::#private::Ok(#this_value::#ident))
|
|
});
|
|
|
|
let u64_fallthrough_arm_tokens;
|
|
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
|
|
fallthrough
|
|
} else {
|
|
let index_expecting = if is_variant { "variant" } else { "field" };
|
|
let fallthrough_msg = format!(
|
|
"{} index 0 <= i < {}",
|
|
index_expecting,
|
|
deserialized_fields.len(),
|
|
);
|
|
u64_fallthrough_arm_tokens = quote! {
|
|
_serde::#private::Err(_serde::de::Error::invalid_value(
|
|
_serde::de::Unexpected::Unsigned(__value),
|
|
&#fallthrough_msg,
|
|
))
|
|
};
|
|
&u64_fallthrough_arm_tokens
|
|
};
|
|
|
|
quote! {
|
|
fn visit_u64<__E>(self, __value: u64) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
match __value {
|
|
#(#u64_mapping,)*
|
|
_ => #u64_fallthrough_arm,
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
|
|
let str_mapping = str_mapping.clone();
|
|
let bytes_mapping = bytes_mapping.clone();
|
|
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
|
|
Some(quote! {
|
|
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
match __value {
|
|
#(#str_mapping)*
|
|
_ => {
|
|
#value_as_borrowed_str_content
|
|
#fallthrough_borrowed_arm
|
|
}
|
|
}
|
|
}
|
|
|
|
fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
match __value {
|
|
#(#bytes_mapping)*
|
|
_ => {
|
|
#bytes_to_str
|
|
#value_as_borrowed_bytes_content
|
|
#fallthrough_borrowed_arm
|
|
}
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
None
|
|
};
|
|
|
|
quote_block! {
|
|
fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result {
|
|
_serde::#private::Formatter::write_str(__formatter, #expecting)
|
|
}
|
|
|
|
#visit_other
|
|
|
|
fn visit_str<__E>(self, __value: &str) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
match __value {
|
|
#(#str_mapping)*
|
|
_ => {
|
|
#value_as_str_content
|
|
#fallthrough_arm
|
|
}
|
|
}
|
|
}
|
|
|
|
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::#private::Result<Self::Value, __E>
|
|
where
|
|
__E: _serde::de::Error,
|
|
{
|
|
match __value {
|
|
#(#bytes_mapping)*
|
|
_ => {
|
|
#bytes_to_str
|
|
#value_as_bytes_content
|
|
#fallthrough_arm
|
|
}
|
|
}
|
|
}
|
|
|
|
#visit_borrowed
|
|
}
|
|
}
|