mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-20 05:41:04 +00:00
+31
-16
@@ -6,7 +6,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use syn::{self, Ident, Member};
|
use syn::{self, Ident, Index, Member};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use quote::{ToTokens, Tokens};
|
use quote::{ToTokens, Tokens};
|
||||||
use proc_macro2::{Literal, Span, Term};
|
use proc_macro2::{Literal, Span, Term};
|
||||||
@@ -32,9 +32,10 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
|
|||||||
|
|
||||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||||
let vis = &input.vis;
|
let vis = &input.vis;
|
||||||
|
let fun = quote_spanned!(Span::call_site()=> deserialize);
|
||||||
quote! {
|
quote! {
|
||||||
impl #de_impl_generics #ident #ty_generics #where_clause {
|
impl #de_impl_generics #ident #ty_generics #where_clause {
|
||||||
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
|
#vis fn #fun<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
|
||||||
where __D: _serde::Deserializer<#delife>
|
where __D: _serde::Deserializer<#delife>
|
||||||
{
|
{
|
||||||
#body
|
#body
|
||||||
@@ -562,14 +563,16 @@ fn deserialize_seq(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// FIXME: parentheses around field values are because of
|
||||||
|
// https://github.com/rust-lang/rust/issues/47311
|
||||||
let mut result = if is_struct {
|
let mut result = if is_struct {
|
||||||
let names = fields.iter().map(|f| &f.ident);
|
let names = fields.iter().map(|f| &f.ident);
|
||||||
quote! {
|
quote_spanned! {Span::call_site()=>
|
||||||
#type_path { #( #names: #vars ),* }
|
#type_path { #( #names: (#vars) ),* }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote_spanned! {Span::call_site()=>
|
||||||
#type_path ( #(#vars),* )
|
#type_path ( #((#vars)),* )
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -624,12 +627,16 @@ fn deserialize_seq_in_place(
|
|||||||
let field_name = field
|
let field_name = field
|
||||||
.ident
|
.ident
|
||||||
.map(Member::Named)
|
.map(Member::Named)
|
||||||
.unwrap_or_else(|| Member::Unnamed(field_index.into()));
|
.unwrap_or_else(|| Member::Unnamed(Index {
|
||||||
|
index: field_index as u32,
|
||||||
|
span: Span::call_site(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
let dot = quote_spanned!(Span::call_site()=> .);
|
||||||
if field.attrs.skip_deserializing() {
|
if field.attrs.skip_deserializing() {
|
||||||
let default = Expr(expr_is_missing(field, cattrs));
|
let default = Expr(expr_is_missing(field, cattrs));
|
||||||
quote! {
|
quote! {
|
||||||
self.place.#field_name = #default;
|
self.place #dot #field_name = #default;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let return_invalid_length = quote! {
|
let return_invalid_length = quote! {
|
||||||
@@ -639,7 +646,7 @@ fn deserialize_seq_in_place(
|
|||||||
None => {
|
None => {
|
||||||
quote! {
|
quote! {
|
||||||
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
|
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
|
||||||
_serde::private::de::InPlaceSeed(&mut self.place.#field_name)))
|
_serde::private::de::InPlaceSeed(&mut self.place #dot #field_name)))
|
||||||
{
|
{
|
||||||
#return_invalid_length
|
#return_invalid_length
|
||||||
}
|
}
|
||||||
@@ -652,7 +659,7 @@ fn deserialize_seq_in_place(
|
|||||||
#wrapper
|
#wrapper
|
||||||
match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) {
|
match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) {
|
||||||
_serde::export::Some(__wrap) => {
|
_serde::export::Some(__wrap) => {
|
||||||
self.place.#field_name = __wrap.value;
|
self.place #dot #field_name = __wrap.value;
|
||||||
}
|
}
|
||||||
_serde::export::None => {
|
_serde::export::None => {
|
||||||
#return_invalid_length
|
#return_invalid_length
|
||||||
@@ -708,7 +715,9 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = quote!(#type_path(#value));
|
// FIXME: parentheses around field values are because of
|
||||||
|
// https://github.com/rust-lang/rust/issues/47311
|
||||||
|
let mut result = quote_spanned!(Span::call_site()=> #type_path((#value)));
|
||||||
if params.has_getter {
|
if params.has_getter {
|
||||||
let this = ¶ms.this;
|
let this = ¶ms.this;
|
||||||
result = quote! {
|
result = quote! {
|
||||||
@@ -733,12 +742,13 @@ fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> To
|
|||||||
|
|
||||||
let delife = params.borrowed.de_lifetime();
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
|
let elem = quote_spanned!(Span::call_site()=> .0);
|
||||||
quote! {
|
quote! {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
||||||
where __E: _serde::Deserializer<#delife>
|
where __E: _serde::Deserializer<#delife>
|
||||||
{
|
{
|
||||||
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
|
_serde::Deserialize::deserialize_in_place(__e, &mut self.place #elem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2039,13 +2049,15 @@ fn deserialize_map(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// FIXME: parentheses around field values are because of
|
||||||
|
// https://github.com/rust-lang/rust/issues/47311
|
||||||
let result = fields_names.iter().map(|&(field, ref name)| {
|
let result = fields_names.iter().map(|&(field, ref name)| {
|
||||||
let ident = field.ident.expect("struct contains unnamed fields");
|
let ident = field.ident.expect("struct contains unnamed fields");
|
||||||
if field.attrs.skip_deserializing() {
|
if field.attrs.skip_deserializing() {
|
||||||
let value = Expr(expr_is_missing(field, cattrs));
|
let value = Expr(expr_is_missing(field, cattrs));
|
||||||
quote!(#ident: #value)
|
quote_spanned!(Span::call_site()=> #ident: (#value))
|
||||||
} else {
|
} else {
|
||||||
quote!(#ident: #name)
|
quote_spanned!(Span::call_site()=> #ident: (#name))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2063,7 +2075,7 @@ fn deserialize_map(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = quote!(#struct_path { #(#result),* });
|
let mut result = quote_spanned!(Span::call_site()=> #struct_path { #(#result),* });
|
||||||
if params.has_getter {
|
if params.has_getter {
|
||||||
let this = ¶ms.this;
|
let this = ¶ms.this;
|
||||||
result = quote! {
|
result = quote! {
|
||||||
@@ -2314,7 +2326,10 @@ fn wrap_deserialize_variant_with(
|
|||||||
let (wrapper, wrapper_ty) =
|
let (wrapper, wrapper_ty) =
|
||||||
wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with);
|
wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with);
|
||||||
|
|
||||||
let field_access = (0..variant.fields.len()).map(|n| Member::Unnamed(n.into()));
|
let field_access = (0..variant.fields.len()).map(|n| Member::Unnamed(Index {
|
||||||
|
index: n as u32,
|
||||||
|
span: Span::call_site(),
|
||||||
|
}));
|
||||||
let unwrap_fn = match variant.style {
|
let unwrap_fn = match variant.style {
|
||||||
Style::Struct => {
|
Style::Struct => {
|
||||||
let field_idents = variant
|
let field_idents = variant
|
||||||
|
|||||||
+18
-7
@@ -6,7 +6,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use syn::{self, Ident, Member};
|
use syn::{self, Ident, Index, Member};
|
||||||
use quote::Tokens;
|
use quote::Tokens;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
|
|
||||||
@@ -31,9 +31,10 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
|||||||
|
|
||||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||||
let vis = &input.vis;
|
let vis = &input.vis;
|
||||||
|
let fun = quote_spanned!(Span::call_site()=> serialize);
|
||||||
quote! {
|
quote! {
|
||||||
impl #impl_generics #ident #ty_generics #where_clause {
|
impl #impl_generics #ident #ty_generics #where_clause {
|
||||||
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
#vis fn #fun<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||||
where __S: _serde::Serializer
|
where __S: _serde::Serializer
|
||||||
{
|
{
|
||||||
#body
|
#body
|
||||||
@@ -202,7 +203,10 @@ fn serialize_newtype_struct(
|
|||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let type_name = cattrs.name().serialize_name();
|
let type_name = cattrs.name().serialize_name();
|
||||||
|
|
||||||
let mut field_expr = get_member(params, field, &Member::Unnamed(0.into()));
|
let mut field_expr = get_member(params, field, &Member::Unnamed(Index {
|
||||||
|
index: 0,
|
||||||
|
span: Span::call_site(),
|
||||||
|
}));
|
||||||
if let Some(path) = field.attrs.serialize_with() {
|
if let Some(path) = field.attrs.serialize_with() {
|
||||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||||
}
|
}
|
||||||
@@ -817,7 +821,10 @@ fn serialize_tuple_struct_visitor(
|
|||||||
let id = Ident::new(&format!("__field{}", i), Span::def_site());
|
let id = Ident::new(&format!("__field{}", i), Span::def_site());
|
||||||
quote!(#id)
|
quote!(#id)
|
||||||
} else {
|
} else {
|
||||||
get_member(params, field, &Member::Unnamed(i.into()))
|
get_member(params, field, &Member::Unnamed(Index {
|
||||||
|
index: i as u32,
|
||||||
|
span: Span::call_site(),
|
||||||
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
let skip = field
|
let skip = field
|
||||||
@@ -940,7 +947,10 @@ fn wrap_serialize_with(
|
|||||||
};
|
};
|
||||||
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
||||||
|
|
||||||
let field_access = (0..field_exprs.len()).map(|n| Member::Unnamed(n.into()));
|
let field_access = (0..field_exprs.len()).map(|n| Member::Unnamed(Index {
|
||||||
|
index: n as u32,
|
||||||
|
span: Span::call_site(),
|
||||||
|
}));
|
||||||
|
|
||||||
quote!({
|
quote!({
|
||||||
struct __SerializeWith #wrapper_impl_generics #where_clause {
|
struct __SerializeWith #wrapper_impl_generics #where_clause {
|
||||||
@@ -981,11 +991,12 @@ fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
|
|||||||
let self_var = ¶ms.self_var;
|
let self_var = ¶ms.self_var;
|
||||||
match (params.is_remote, field.attrs.getter()) {
|
match (params.is_remote, field.attrs.getter()) {
|
||||||
(false, None) => {
|
(false, None) => {
|
||||||
quote!(&#self_var.#member)
|
quote_spanned!(Span::call_site()=> &#self_var.#member)
|
||||||
}
|
}
|
||||||
(true, None) => {
|
(true, None) => {
|
||||||
|
let inner = quote_spanned!(Span::call_site()=> &#self_var.#member);
|
||||||
let ty = field.ty;
|
let ty = field.ty;
|
||||||
quote!(_serde::private::ser::constrain::<#ty>(&#self_var.#member))
|
quote!(_serde::private::ser::constrain::<#ty>(#inner))
|
||||||
}
|
}
|
||||||
(true, Some(getter)) => {
|
(true, Some(getter)) => {
|
||||||
let ty = field.ty;
|
let ty = field.ty;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ readme = "README.md"
|
|||||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
proc-macro2 = "0.2"
|
||||||
syn = { version = "0.12", default-features = false, features = ["derive", "parsing", "clone-impls"] }
|
syn = { version = "0.12", default-features = false, features = ["derive", "parsing", "clone-impls"] }
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
|
|||||||
@@ -8,12 +8,14 @@
|
|||||||
|
|
||||||
use Ctxt;
|
use Ctxt;
|
||||||
use syn;
|
use syn;
|
||||||
|
use syn::Ident;
|
||||||
use syn::Meta::{List, NameValue, Word};
|
use syn::Meta::{List, NameValue, Word};
|
||||||
use syn::NestedMeta::{Literal, Meta};
|
use syn::NestedMeta::{Literal, Meta};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::synom::Synom;
|
use syn::synom::Synom;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use proc_macro2::Span;
|
||||||
|
|
||||||
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
|
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
|
||||||
// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
|
// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
|
||||||
@@ -577,10 +579,10 @@ impl Variant {
|
|||||||
Meta(NameValue(ref m)) if m.ident == "with" => {
|
Meta(NameValue(ref m)) if m.ident == "with" => {
|
||||||
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) {
|
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) {
|
||||||
let mut ser_path = path.clone();
|
let mut ser_path = path.clone();
|
||||||
ser_path.segments.push("serialize".into());
|
ser_path.segments.push(Ident::new("serialize", Span::call_site()).into());
|
||||||
serialize_with.set(ser_path);
|
serialize_with.set(ser_path);
|
||||||
let mut de_path = path;
|
let mut de_path = path;
|
||||||
de_path.segments.push("deserialize".into());
|
de_path.segments.push(Ident::new("deserialize", Span::call_site()).into());
|
||||||
deserialize_with.set(de_path);
|
deserialize_with.set(de_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -819,10 +821,10 @@ impl Field {
|
|||||||
Meta(NameValue(ref m)) if m.ident == "with" => {
|
Meta(NameValue(ref m)) if m.ident == "with" => {
|
||||||
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) {
|
if let Ok(path) = parse_lit_into_path(cx, m.ident.as_ref(), &m.lit) {
|
||||||
let mut ser_path = path.clone();
|
let mut ser_path = path.clone();
|
||||||
ser_path.segments.push("serialize".into());
|
ser_path.segments.push(Ident::new("serialize", Span::call_site()).into());
|
||||||
serialize_with.set(ser_path);
|
serialize_with.set(ser_path);
|
||||||
let mut de_path = path;
|
let mut de_path = path;
|
||||||
de_path.segments.push("deserialize".into());
|
de_path.segments.push(Ident::new("deserialize", Span::call_site()).into());
|
||||||
deserialize_with.set(de_path);
|
deserialize_with.set(de_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -911,10 +913,24 @@ impl Field {
|
|||||||
// impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str>
|
// impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str>
|
||||||
// impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]>
|
// impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]>
|
||||||
if is_cow(&field.ty, is_str) {
|
if is_cow(&field.ty, is_str) {
|
||||||
let path = syn::parse_str("_serde::private::de::borrow_cow_str").unwrap();
|
let mut path = syn::Path {
|
||||||
|
leading_colon: None,
|
||||||
|
segments: Punctuated::new(),
|
||||||
|
};
|
||||||
|
path.segments.push(Ident::new("_serde", Span::def_site()).into());
|
||||||
|
path.segments.push(Ident::new("private", Span::def_site()).into());
|
||||||
|
path.segments.push(Ident::new("de", Span::def_site()).into());
|
||||||
|
path.segments.push(Ident::new("borrow_cow_str", Span::def_site()).into());
|
||||||
deserialize_with.set_if_none(path);
|
deserialize_with.set_if_none(path);
|
||||||
} else if is_cow(&field.ty, is_slice_u8) {
|
} else if is_cow(&field.ty, is_slice_u8) {
|
||||||
let path = syn::parse_str("_serde::private::de::borrow_cow_bytes").unwrap();
|
let mut path = syn::Path {
|
||||||
|
leading_colon: None,
|
||||||
|
segments: Punctuated::new(),
|
||||||
|
};
|
||||||
|
path.segments.push(Ident::new("_serde", Span::def_site()).into());
|
||||||
|
path.segments.push(Ident::new("private", Span::def_site()).into());
|
||||||
|
path.segments.push(Ident::new("de", Span::def_site()).into());
|
||||||
|
path.segments.push(Ident::new("borrow_cow_bytes", Span::def_site()).into());
|
||||||
deserialize_with.set_if_none(path);
|
deserialize_with.set_if_none(path);
|
||||||
}
|
}
|
||||||
} else if is_rptr(&field.ty, is_str) || is_rptr(&field.ty, is_slice_u8) {
|
} else if is_rptr(&field.ty, is_str) || is_rptr(&field.ty, is_slice_u8) {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate syn;
|
extern crate syn;
|
||||||
|
|
||||||
|
extern crate proc_macro2;
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ unstable = ["serde/unstable", "compiletest_rs"]
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
|
proc-macro2 = "0.2"
|
||||||
rustc-serialize = "0.3.16"
|
rustc-serialize = "0.3.16"
|
||||||
serde = { path = "../serde", features = ["rc"] }
|
serde = { path = "../serde", features = ["rc"] }
|
||||||
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ else
|
|||||||
channel build
|
channel build
|
||||||
cd "$DIR/test_suite"
|
cd "$DIR/test_suite"
|
||||||
channel test --features unstable
|
channel test --features unstable
|
||||||
|
channel build --tests --features proc-macro2/nightly
|
||||||
if [ -z "${APPVEYOR}" ]; then
|
if [ -z "${APPVEYOR}" ]; then
|
||||||
cd "$DIR/test_suite/no_std"
|
cd "$DIR/test_suite/no_std"
|
||||||
channel build
|
channel build
|
||||||
|
|||||||
Reference in New Issue
Block a user