mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 09:28:04 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 89278996c5 | |||
| ecef937e26 | |||
| bceda5fb18 | |||
| f46a08b04e | |||
| f3cb7c7a32 | |||
| af795e2e54 | |||
| 6aa07fe0d6 | |||
| c455720f81 | |||
| b07a208716 | |||
| df93fab5fa | |||
| 1a972d2105 | |||
| 6d1807bb4a | |||
| b37cf858ce | |||
| 5f8fa33756 | |||
| f3f006f411 | |||
| 607966dcf7 | |||
| 6a8c39b2aa |
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.41" # remember to update html_root_url
|
||||
version = "1.0.43" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
|
||||
@@ -196,6 +196,7 @@ macro_rules! declare_error_trait {
|
||||
/// For example if we try to deserialize a String out of a JSON file
|
||||
/// containing an integer, the unexpected type is the integer and the
|
||||
/// expected type is the string.
|
||||
#[cold]
|
||||
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
|
||||
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
|
||||
}
|
||||
@@ -213,6 +214,7 @@ macro_rules! declare_error_trait {
|
||||
/// For example if we try to deserialize a String out of some binary data
|
||||
/// that is not valid UTF-8, the unexpected value is the bytes and the
|
||||
/// expected value is a string.
|
||||
#[cold]
|
||||
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
|
||||
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
|
||||
}
|
||||
@@ -226,12 +228,14 @@ macro_rules! declare_error_trait {
|
||||
/// The `exp` argument provides information about what data was being
|
||||
/// expected. For example `exp` might say that a tuple of size 6 was
|
||||
/// expected.
|
||||
#[cold]
|
||||
fn invalid_length(len: usize, exp: &Expected) -> Self {
|
||||
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
|
||||
}
|
||||
|
||||
/// Raised when a `Deserialize` enum type received a variant with an
|
||||
/// unrecognized name.
|
||||
#[cold]
|
||||
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
|
||||
if expected.is_empty() {
|
||||
Error::custom(format_args!("unknown variant `{}`, there are no variants",
|
||||
@@ -245,6 +249,7 @@ macro_rules! declare_error_trait {
|
||||
|
||||
/// Raised when a `Deserialize` struct type received a field with an
|
||||
/// unrecognized name.
|
||||
#[cold]
|
||||
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
|
||||
if expected.is_empty() {
|
||||
Error::custom(format_args!("unknown field `{}`, there are no fields",
|
||||
@@ -259,12 +264,14 @@ macro_rules! declare_error_trait {
|
||||
/// Raised when a `Deserialize` struct type expected to receive a required
|
||||
/// field with a particular name but that field was not present in the
|
||||
/// input.
|
||||
#[cold]
|
||||
fn missing_field(field: &'static str) -> Self {
|
||||
Error::custom(format_args!("missing field `{}`", field))
|
||||
}
|
||||
|
||||
/// Raised when a `Deserialize` struct type received more than one of the
|
||||
/// same field.
|
||||
#[cold]
|
||||
fn duplicate_field(field: &'static str) -> Self {
|
||||
Error::custom(format_args!("duplicate field `{}`", field))
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ type ErrorImpl = ();
|
||||
|
||||
impl de::Error for Error {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cold]
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
T: Display,
|
||||
@@ -68,6 +69,7 @@ impl de::Error for Error {
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
#[cold]
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
T: Display,
|
||||
@@ -78,6 +80,7 @@ impl de::Error for Error {
|
||||
}
|
||||
|
||||
impl ser::Error for Error {
|
||||
#[cold]
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
T: Display,
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.41")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.43")]
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Unstable functionality only if the user asks for it. For tracking and
|
||||
|
||||
+13
-2
@@ -277,6 +277,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn unexpected(&self) -> Unexpected {
|
||||
match *self {
|
||||
Content::Bool(b) => Unexpected::Bool(b),
|
||||
@@ -1309,7 +1310,12 @@ mod content {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_newtype_struct(self)
|
||||
match self.content {
|
||||
Content::Newtype(v) => {
|
||||
visitor.visit_newtype_struct(ContentDeserializer::new(*v))
|
||||
}
|
||||
_ => visitor.visit_newtype_struct(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
@@ -2000,7 +2006,12 @@ mod content {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_newtype_struct(self)
|
||||
match *self.content {
|
||||
Content::Newtype(ref v) => {
|
||||
visitor.visit_newtype_struct(ContentRefDeserializer::new(v))
|
||||
}
|
||||
_ => visitor.visit_newtype_struct(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.41" # remember to update html_root_url
|
||||
version = "1.0.43" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
@@ -24,7 +24,7 @@ proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "0.3"
|
||||
quote = "0.5"
|
||||
quote = "0.5.2"
|
||||
serde_derive_internals = { version = "=0.23.1", default-features = false, path = "../serde_derive_internals" }
|
||||
syn = { version = "0.13", features = ["visit"] }
|
||||
|
||||
|
||||
+22
-20
@@ -16,6 +16,7 @@ use bound;
|
||||
use fragment::{Expr, Fragment, Match, Stmts};
|
||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use internals::{self, attr};
|
||||
use try;
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
@@ -36,10 +37,9 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
|
||||
|
||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||
let vis = &input.vis;
|
||||
let fun = quote_spanned!(Span::call_site()=> deserialize);
|
||||
quote! {
|
||||
impl #de_impl_generics #ident #ty_generics #where_clause {
|
||||
#vis fn #fun<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
|
||||
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
|
||||
where __D: _serde::Deserializer<#delife>
|
||||
{
|
||||
#body
|
||||
@@ -63,10 +63,12 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
|
||||
}
|
||||
};
|
||||
|
||||
let try_replacement = try::replacement();
|
||||
let generated = quote! {
|
||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||
const #dummy_const: () = {
|
||||
extern crate serde as _serde;
|
||||
#try_replacement
|
||||
#impl_block
|
||||
};
|
||||
};
|
||||
@@ -583,11 +585,11 @@ fn deserialize_seq(
|
||||
|
||||
let mut result = if is_struct {
|
||||
let names = fields.iter().map(|f| &f.ident);
|
||||
quote_spanned! {Span::call_site()=>
|
||||
quote! {
|
||||
#type_path { #( #names: #vars ),* }
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {Span::call_site()=>
|
||||
quote! {
|
||||
#type_path ( #(#vars),* )
|
||||
}
|
||||
};
|
||||
@@ -649,11 +651,10 @@ fn deserialize_seq_in_place(
|
||||
})
|
||||
});
|
||||
|
||||
let dot = quote_spanned!(Span::call_site()=> .);
|
||||
if field.attrs.skip_deserializing() {
|
||||
let default = Expr(expr_is_missing(field, cattrs));
|
||||
quote! {
|
||||
self.place #dot #field_name = #default;
|
||||
self.place.#field_name = #default;
|
||||
}
|
||||
} else {
|
||||
let return_invalid_length = quote! {
|
||||
@@ -663,7 +664,7 @@ fn deserialize_seq_in_place(
|
||||
None => {
|
||||
quote! {
|
||||
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
|
||||
_serde::private::de::InPlaceSeed(&mut self.place #dot #field_name)))
|
||||
_serde::private::de::InPlaceSeed(&mut self.place.#field_name)))
|
||||
{
|
||||
#return_invalid_length
|
||||
}
|
||||
@@ -676,7 +677,7 @@ fn deserialize_seq_in_place(
|
||||
#wrapper
|
||||
match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) {
|
||||
_serde::export::Some(__wrap) => {
|
||||
self.place #dot #field_name = __wrap.value;
|
||||
self.place.#field_name = __wrap.value;
|
||||
}
|
||||
_serde::export::None => {
|
||||
#return_invalid_length
|
||||
@@ -732,7 +733,7 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
|
||||
}
|
||||
};
|
||||
|
||||
let mut result = quote_spanned!(Span::call_site()=> #type_path(#value));
|
||||
let mut result = quote!(#type_path(__field0));
|
||||
if params.has_getter {
|
||||
let this = ¶ms.this;
|
||||
result = quote! {
|
||||
@@ -745,6 +746,7 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
|
||||
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
||||
where __E: _serde::Deserializer<#delife>
|
||||
{
|
||||
let __field0 = #value;
|
||||
_serde::export::Ok(#result)
|
||||
}
|
||||
}
|
||||
@@ -757,13 +759,12 @@ fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> To
|
||||
|
||||
let delife = params.borrowed.de_lifetime();
|
||||
|
||||
let elem = quote_spanned!(Span::call_site()=> .0);
|
||||
quote! {
|
||||
#[inline]
|
||||
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
||||
where __E: _serde::Deserializer<#delife>
|
||||
{
|
||||
_serde::Deserialize::deserialize_in_place(__e, &mut self.place #elem)
|
||||
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1625,12 +1626,13 @@ fn deserialize_untagged_variant(
|
||||
let type_name = params.type_name();
|
||||
let variant_name = variant.ident.as_ref();
|
||||
quote_expr! {
|
||||
_serde::export::Result::map(
|
||||
_serde::Deserializer::deserialize_any(
|
||||
#deserializer,
|
||||
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
|
||||
),
|
||||
|()| #this::#variant_ident)
|
||||
match _serde::Deserializer::deserialize_any(
|
||||
#deserializer,
|
||||
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
|
||||
) {
|
||||
_serde::export::Ok(()) => _serde::export::Ok(#this::#variant_ident),
|
||||
_serde::export::Err(__err) => _serde::export::Err(__err),
|
||||
}
|
||||
}
|
||||
}
|
||||
Style::Newtype => deserialize_untagged_newtype_variant(
|
||||
@@ -2305,9 +2307,9 @@ fn deserialize_map(
|
||||
let ident = field.ident.expect("struct contains unnamed fields");
|
||||
if field.attrs.skip_deserializing() {
|
||||
let value = Expr(expr_is_missing(field, cattrs));
|
||||
quote_spanned!(Span::call_site()=> #ident: #value)
|
||||
quote!(#ident: #value)
|
||||
} else {
|
||||
quote_spanned!(Span::call_site()=> #ident: #name)
|
||||
quote!(#ident: #name)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2325,7 +2327,7 @@ fn deserialize_map(
|
||||
}
|
||||
};
|
||||
|
||||
let mut result = quote_spanned!(Span::call_site()=> #struct_path { #(#result),* });
|
||||
let mut result = quote!(#struct_path { #(#result),* });
|
||||
if params.has_getter {
|
||||
let this = ¶ms.this;
|
||||
result = quote! {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.41")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.43")]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding)
|
||||
@@ -43,14 +43,6 @@ extern crate proc_macro2;
|
||||
use proc_macro::TokenStream;
|
||||
use syn::DeriveInput;
|
||||
|
||||
// Quote's default is def_site but it appears call_site is likely to stabilize
|
||||
// before def_site. Thus we try to use only call_site.
|
||||
macro_rules! quote {
|
||||
($($tt:tt)*) => {
|
||||
quote_spanned!($crate::proc_macro2::Span::call_site()=> $($tt)*)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
mod bound;
|
||||
#[macro_use]
|
||||
@@ -58,6 +50,7 @@ mod fragment;
|
||||
|
||||
mod de;
|
||||
mod ser;
|
||||
mod try;
|
||||
|
||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
|
||||
+15
-7
@@ -15,6 +15,7 @@ use bound;
|
||||
use fragment::{Fragment, Match, Stmts};
|
||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use internals::{attr, Ctxt};
|
||||
use try;
|
||||
|
||||
use std::u32;
|
||||
|
||||
@@ -32,10 +33,9 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
||||
|
||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||
let vis = &input.vis;
|
||||
let fun = quote_spanned!(Span::call_site()=> serialize);
|
||||
quote! {
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
#vis fn #fun<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
where __S: _serde::Serializer
|
||||
{
|
||||
#body
|
||||
@@ -55,10 +55,12 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
||||
}
|
||||
};
|
||||
|
||||
let try_replacement = try::replacement();
|
||||
let generated = quote! {
|
||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||
const #dummy_const: () = {
|
||||
extern crate serde as _serde;
|
||||
#try_replacement
|
||||
#impl_block
|
||||
};
|
||||
};
|
||||
@@ -594,9 +596,15 @@ fn serialize_adjacently_tagged_variant(
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
|
||||
quote_expr! {
|
||||
_serde::Serialize::serialize(#field_expr, __serializer)
|
||||
}
|
||||
return quote_block! {
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 2));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #content, #field_expr));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
};
|
||||
}
|
||||
Style::Tuple => {
|
||||
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
|
||||
@@ -1056,9 +1064,9 @@ fn mut_if(is_mut: bool) -> Option<Tokens> {
|
||||
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
|
||||
let self_var = ¶ms.self_var;
|
||||
match (params.is_remote, field.attrs.getter()) {
|
||||
(false, None) => quote_spanned!(Span::call_site()=> &#self_var.#member),
|
||||
(false, None) => quote!(&#self_var.#member),
|
||||
(true, None) => {
|
||||
let inner = quote_spanned!(Span::call_site()=> &#self_var.#member);
|
||||
let inner = quote!(&#self_var.#member);
|
||||
let ty = field.ty;
|
||||
quote!(_serde::private::ser::constrain::<#ty>(#inner))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use quote::Tokens;
|
||||
use proc_macro2::{Op, Spacing};
|
||||
|
||||
// None of our generated code requires the `From::from` error conversion
|
||||
// performed by the standard library's `try!` macro. With this simplified macro
|
||||
// we see a significant improvement in type checking and borrow checking time of
|
||||
// the generated code and a slight improvement in binary size.
|
||||
pub fn replacement() -> Tokens {
|
||||
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
|
||||
let dollar = Op::new('$', Spacing::Alone);
|
||||
|
||||
quote! {
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! try {
|
||||
(#dollar __expr:expr) => {
|
||||
match #dollar __expr {
|
||||
_serde::export::Ok(__val) => __val,
|
||||
_serde::export::Err(__err) => {
|
||||
return _serde::export::Err(__err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.41" # remember to update html_root_url
|
||||
version = "1.0.43" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.41")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.43")]
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// Whitelisted clippy lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
||||
|
||||
@@ -446,6 +446,54 @@ fn test_generic_newtype_struct() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_untagged_newtype_struct() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum E {
|
||||
Newtype(GenericNewTypeStruct<u32>),
|
||||
Null,
|
||||
}
|
||||
|
||||
assert_tokens(
|
||||
&E::Newtype(GenericNewTypeStruct(5u32)),
|
||||
&[
|
||||
Token::NewtypeStruct {
|
||||
name: "GenericNewTypeStruct",
|
||||
},
|
||||
Token::U32(5),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_adjacently_tagged_newtype_struct() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum E {
|
||||
Newtype(GenericNewTypeStruct<u32>),
|
||||
Null,
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&E::Newtype(GenericNewTypeStruct(5u32)),
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "E",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("c"),
|
||||
Token::NewtypeStruct {
|
||||
name: "GenericNewTypeStruct",
|
||||
},
|
||||
Token::U32(5),
|
||||
Token::Str("t"),
|
||||
Token::Str("Newtype"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generic_tuple_struct() {
|
||||
assert_tokens(
|
||||
|
||||
Reference in New Issue
Block a user