use crate::de::identifier; use crate::de::{ deserialize_seq, expr_is_missing, field_i, has_flatten, wrap_deserialize_field_with, FieldWithAliases, Parameters, StructForm, }; #[cfg(feature = "deserialize_in_place")] use crate::de::{deserialize_seq_in_place, place_lifetime}; use crate::fragment::{Expr, Fragment, Match, Stmts}; use crate::internals::ast::Field; use crate::internals::attr; use crate::private; use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; /// Generates `Deserialize::deserialize` body for a `struct Struct {...}` pub(super) fn deserialize( params: &Parameters, fields: &[Field], cattrs: &attr::Container, form: StructForm, ) -> Fragment { let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); // If there are getters (implying private fields), construct the local type // and use an `Into` conversion to get the remote type. If there are no // getters then construct the target type directly. let construct = if params.has_getter { let local = ¶ms.local; quote!(#local) } else { quote!(#this_value) }; let type_path = match form { StructForm::Struct => construct, StructForm::ExternallyTagged(variant_ident) | StructForm::InternallyTagged(variant_ident) | StructForm::Untagged(variant_ident) => quote!(#construct::#variant_ident), }; let expecting = match form { StructForm::Struct => format!("struct {}", params.type_name()), StructForm::ExternallyTagged(variant_ident) | StructForm::InternallyTagged(variant_ident) | StructForm::Untagged(variant_ident) => { format!("struct variant {}::{}", params.type_name(), variant_ident) } }; let expecting = cattrs.expecting().unwrap_or(&expecting); let deserialized_fields: Vec<_> = fields .iter() .enumerate() // Skip fields that shouldn't be deserialized or that were flattened, // so they don't appear in the storage in their literal form .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(i, field)| FieldWithAliases { ident: field_i(i), aliases: field.attrs.aliases(), }) .collect(); let has_flatten = has_flatten(fields); let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, has_flatten); // untagged struct variants do not get a visit_seq method. The same applies to // structs that only have a map representation. let visit_seq = match form { StructForm::Untagged(_) => None, _ if has_flatten => None, _ => { let mut_seq = if deserialized_fields.is_empty() { quote!(_) } else { quote!(mut __seq) }; let visit_seq = Stmts(deserialize_seq( &type_path, params, fields, true, cattrs, expecting, )); Some(quote! { #[inline] fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } }) } }; let visit_map = Stmts(deserialize_map( &type_path, params, fields, cattrs, has_flatten, )); let visitor_seed = match form { StructForm::ExternallyTagged(..) if has_flatten => Some(quote! { #[automatically_derived] impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::#private::Result where __D: _serde::Deserializer<#delife>, { _serde::Deserializer::deserialize_map(__deserializer, self) } } }), _ => None, }; let fields_stmt = if has_flatten { None } else { let field_names = deserialized_fields.iter().flat_map(|field| field.aliases); Some(quote! { #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; }) }; let visitor_expr = quote! { __Visitor { marker: _serde::#private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData, } }; let dispatch = match form { StructForm::Struct if has_flatten => quote! { _serde::Deserializer::deserialize_map(__deserializer, #visitor_expr) }, StructForm::Struct => { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) } } StructForm::ExternallyTagged(_) if has_flatten => quote! { _serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr) }, StructForm::ExternallyTagged(_) => quote! { _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) }, StructForm::InternallyTagged(_) => quote! { _serde::Deserializer::deserialize_any(__deserializer, #visitor_expr) }, StructForm::Untagged(_) => quote! { _serde::Deserializer::deserialize_any(__deserializer, #visitor_expr) }, }; quote_block! { #field_visitor #[doc(hidden)] struct __Visitor #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 __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } #visit_seq #[inline] fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result where __A: _serde::de::MapAccess<#delife>, { #visit_map } } #visitor_seed #fields_stmt #dispatch } } fn deserialize_map( struct_path: &TokenStream, params: &Parameters, fields: &[Field], cattrs: &attr::Container, has_flatten: bool, ) -> Fragment { // Create the field names for the fields. let fields_names: Vec<_> = fields .iter() .enumerate() .map(|(i, field)| (field, field_i(i))) .collect(); // Declare each field that will be deserialized. let let_values = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let field_ty = field.ty; quote! { let mut #name: _serde::#private::Option<#field_ty> = _serde::#private::None; } }); // Collect contents for flatten fields into a buffer let let_collect = if has_flatten { Some(quote! { let mut __collect = _serde::#private::Vec::<_serde::#private::Option<( _serde::#private::de::Content, _serde::#private::de::Content )>>::new(); }) } else { None }; // Match arms to extract a value for a field. let value_arms = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let deser_name = field.attrs.name().deserialize_name(); let visit = match field.attrs.deserialize_with() { None => { let field_ty = field.ty; let span = field.original.span(); let func = quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>); quote! { #func(&mut __map)? } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) { _serde::#private::Ok(__wrapper) => __wrapper.value, _serde::#private::Err(__err) => { return _serde::#private::Err(__err); } } }) } }; quote! { __Field::#name => { if _serde::#private::Option::is_some(&#name) { return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name)); } #name = _serde::#private::Some(#visit); } } }); // Visit ignored values to consume them let ignored_arm = if has_flatten { Some(quote! { __Field::__other(__name) => { __collect.push(_serde::#private::Some(( __name, _serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::ContentVisitor::new())?))); } }) } else if cattrs.deny_unknown_fields() { None } else { Some(quote! { _ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; } }) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?; _serde::#private::Option::map( _serde::de::MapAccess::next_key::<__Field>(&mut __map)?, |__impossible| match __impossible {}); } } else { quote! { while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? { match __key { #(#value_arms)* #ignored_arm } } } }; let extract_values = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let missing_expr = Match(expr_is_missing(field, cattrs)); quote! { let #name = match #name { _serde::#private::Some(#name) => #name, _serde::#private::None => #missing_expr }; } }); let extract_collected = fields_names .iter() .filter(|&&(field, _)| field.attrs.flatten() && !field.attrs.skip_deserializing()) .map(|(field, name)| { let field_ty = field.ty; let func = match field.attrs.deserialize_with() { None => { let span = field.original.span(); quote_spanned!(span=> _serde::de::Deserialize::deserialize) } Some(path) => quote!(#path), }; quote! { let #name: #field_ty = #func( _serde::#private::de::FlatMapDeserializer( &mut __collect, _serde::#private::PhantomData))?; } }); let collected_deny_unknown_fields = if has_flatten && cattrs.deny_unknown_fields() { Some(quote! { if let _serde::#private::Some(_serde::#private::Some((__key, _))) = __collect.into_iter().filter(_serde::#private::Option::is_some).next() { if let _serde::#private::Some(__key) = _serde::#private::de::content_as_str(&__key) { return _serde::#private::Err( _serde::de::Error::custom(format_args!("unknown field `{}`", &__key))); } else { return _serde::#private::Err( _serde::de::Error::custom(format_args!("unexpected map key"))); } } }) } else { None }; let result = fields_names.iter().map(|(field, name)| { let member = &field.member; if field.attrs.skip_deserializing() { let value = Expr(expr_is_missing(field, cattrs)); quote!(#member: #value) } else { quote!(#member: #name) } }); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: Self::Value = _serde::#private::Default::default(); )), // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: Self::Value = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; let mut result = quote!(#struct_path { #(#result),* }); if params.has_getter { let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { _serde::#private::Into::<#this_type #ty_generics>::into(#result) }; } quote_block! { #(#let_values)* #let_collect #match_keys #let_default #(#extract_values)* #(#extract_collected)* #collected_deny_unknown_fields _serde::#private::Ok(#result) } } /// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}` #[cfg(feature = "deserialize_in_place")] pub(super) fn deserialize_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Option { // for now we do not support in_place deserialization for structs that // are represented as map. if has_flatten(fields) { return None; } let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); let expecting = format!("struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); let deserialized_fields: Vec<_> = fields .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) .map(|(i, field)| FieldWithAliases { ident: field_i(i), aliases: field.attrs.aliases(), }) .collect(); let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false); let mut_seq = if deserialized_fields.is_empty() { quote!(_) } else { quote!(mut __seq) }; let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs)); let field_names = deserialized_fields.iter().flat_map(|field| field.aliases); let type_name = cattrs.name().deserialize_name(); let in_place_impl_generics = de_impl_generics.in_place(); let in_place_ty_generics = de_ty_generics.in_place(); let place_life = place_lifetime(); Some(quote_block! { #field_visitor #[doc(hidden)] struct __Visitor #in_place_impl_generics #where_clause { place: &#place_life mut #this_type #ty_generics, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { type Value = (); fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } #[inline] fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } #[inline] fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result where __A: _serde::de::MapAccess<#delife>, { #visit_map } } #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor { place: __place, lifetime: _serde::#private::PhantomData, }) }) } #[cfg(feature = "deserialize_in_place")] fn deserialize_map_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { assert!( !has_flatten(fields), "inplace deserialization of maps does not support flatten fields" ); // Create the field names for the fields. let fields_names: Vec<_> = fields .iter() .enumerate() .map(|(i, field)| (field, field_i(i))) .collect(); // For deserialize_in_place, declare booleans for each field that will be // deserialized. let let_flags = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(_, name)| { quote! { let mut #name: bool = false; } }); // Match arms to extract a value for a field. let value_arms_from = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(field, name)| { let deser_name = field.attrs.name().deserialize_name(); let member = &field.member; let visit = match field.attrs.deserialize_with() { None => { quote! { _serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::InPlaceSeed(&mut self.place.#member))? } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper self.place.#member = match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) { _serde::#private::Ok(__wrapper) => __wrapper.value, _serde::#private::Err(__err) => { return _serde::#private::Err(__err); } }; }) } }; quote! { __Field::#name => { if #name { return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name)); } #visit; #name = true; } } }); // Visit ignored values to consume them let ignored_arm = if cattrs.deny_unknown_fields() { None } else { Some(quote! { _ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; } }) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?; _serde::#private::Option::map( _serde::de::MapAccess::next_key::<__Field>(&mut __map)?, |__impossible| match __impossible {}); } } else { quote! { while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? { match __key { #(#value_arms_from)* #ignored_arm } } } }; let check_flags = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(field, name)| { let missing_expr = expr_is_missing(field, cattrs); // If missing_expr unconditionally returns an error, don't try // to assign its value to self.place. if field.attrs.default().is_none() && cattrs.default().is_none() && field.attrs.deserialize_with().is_some() { let missing_expr = Stmts(missing_expr); quote! { if !#name { #missing_expr; } } } else { let member = &field.member; let missing_expr = Expr(missing_expr); quote! { if !#name { self.place.#member = #missing_expr; }; } } }); let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: #this_type #ty_generics = _serde::#private::Default::default(); )), // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; quote_block! { #(#let_flags)* #match_keys #let_default #(#check_flags)* _serde::#private::Ok(()) } } /// Generates enum and its `Deserialize` implementation that represents each /// non-skipped field of the struct fn deserialize_field_identifier( deserialized_fields: &[FieldWithAliases], cattrs: &attr::Container, has_flatten: bool, ) -> Stmts { let (ignore_variant, fallthrough) = if has_flatten { let ignore_variant = quote!(__other(_serde::#private::de::Content<'de>),); let fallthrough = quote!(_serde::#private::Ok(__Field::__other(__value))); (Some(ignore_variant), Some(fallthrough)) } else if cattrs.deny_unknown_fields() { (None, None) } else { let ignore_variant = quote!(__ignore,); let fallthrough = quote!(_serde::#private::Ok(__Field::__ignore)); (Some(ignore_variant), Some(fallthrough)) }; Stmts(identifier::deserialize_generated( deserialized_fields, has_flatten, false, ignore_variant, fallthrough, )) }