Merge branch serde-rs/master into Gankro/deserialize_from
This commit is contained in:
commit
0c2e91f28a
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.23" # remember to update html_root_url
|
||||
version = "1.0.24" # 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"
|
||||
|
@ -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.23")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.24")]
|
||||
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.23" # remember to update html_root_url
|
||||
version = "1.0.24" # 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]
|
||||
quote = "0.3.8"
|
||||
serde_derive_internals = { version = "=0.17.0", default-features = false, path = "../serde_derive_internals" }
|
||||
serde_derive_internals = { version = "=0.18.0", default-features = false, path = "../serde_derive_internals" }
|
||||
syn = { version = "0.11", features = ["visit"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -583,7 +583,30 @@ fn deserialize_seq(
|
||||
};
|
||||
}
|
||||
|
||||
let let_default = match *cattrs.default() {
|
||||
attr::Default::Default => {
|
||||
Some(
|
||||
quote!(
|
||||
let __default: Self::Value = _serde::export::Default::default();
|
||||
),
|
||||
)
|
||||
}
|
||||
attr::Default::Path(ref path) => {
|
||||
Some(
|
||||
quote!(
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
quote_block! {
|
||||
#let_default
|
||||
#(#let_values)*
|
||||
_serde::export::Ok(#result)
|
||||
}
|
||||
@ -2034,15 +2057,15 @@ fn deserialize_map(
|
||||
attr::Default::Default => {
|
||||
Some(
|
||||
quote!(
|
||||
let __default: Self::Value = _serde::export::Default::default();
|
||||
),
|
||||
let __default: Self::Value = _serde::export::Default::default();
|
||||
),
|
||||
)
|
||||
}
|
||||
attr::Default::Path(ref path) => {
|
||||
Some(
|
||||
quote!(
|
||||
let __default: Self::Value = #path();
|
||||
),
|
||||
let __default: Self::Value = #path();
|
||||
),
|
||||
)
|
||||
}
|
||||
attr::Default::None => {
|
||||
|
@ -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.23")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.24")]
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.17.0" # remember to update html_root_url
|
||||
version = "0.18.0" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "AST representation used by Serde derive macros. Unstable."
|
||||
|
@ -49,9 +49,11 @@ impl<'a> Container<'a> {
|
||||
let attrs = attr::Container::from_ast(cx, item);
|
||||
|
||||
let mut body = match item.body {
|
||||
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
|
||||
syn::Body::Enum(ref variants) => {
|
||||
Body::Enum(enum_from_ast(cx, variants, &attrs.default()))
|
||||
}
|
||||
syn::Body::Struct(ref variant_data) => {
|
||||
let (style, fields) = struct_from_ast(cx, variant_data, None);
|
||||
let (style, fields) = struct_from_ast(cx, variant_data, None, &attrs.default());
|
||||
Body::Struct(style, fields)
|
||||
}
|
||||
};
|
||||
@ -98,36 +100,54 @@ impl<'a> Body<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
|
||||
fn enum_from_ast<'a>(
|
||||
cx: &Ctxt,
|
||||
variants: &'a [syn::Variant],
|
||||
container_default: &attr::Default,
|
||||
) -> Vec<Variant<'a>> {
|
||||
variants
|
||||
.iter()
|
||||
.map(
|
||||
|variant| {
|
||||
let attrs = attr::Variant::from_ast(cx, variant);
|
||||
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
|
||||
Variant {
|
||||
ident: variant.ident.clone(),
|
||||
attrs: attrs,
|
||||
style: style,
|
||||
fields: fields,
|
||||
}
|
||||
},
|
||||
)
|
||||
.map(|variant| {
|
||||
let attrs = attr::Variant::from_ast(cx, variant);
|
||||
let (style, fields) =
|
||||
struct_from_ast(cx, &variant.data, Some(&attrs), container_default);
|
||||
Variant {
|
||||
ident: variant.ident.clone(),
|
||||
attrs: attrs,
|
||||
style: style,
|
||||
fields: fields,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
|
||||
fn struct_from_ast<'a>(
|
||||
cx: &Ctxt,
|
||||
data: &'a syn::VariantData,
|
||||
attrs: Option<&attr::Variant>,
|
||||
container_default: &attr::Default,
|
||||
) -> (Style, Vec<Field<'a>>) {
|
||||
match *data {
|
||||
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
|
||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
||||
(Style::Newtype, fields_from_ast(cx, fields, attrs))
|
||||
syn::VariantData::Struct(ref fields) => {
|
||||
(Style::Struct, fields_from_ast(cx, fields, attrs, container_default))
|
||||
}
|
||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => (
|
||||
Style::Newtype,
|
||||
fields_from_ast(cx, fields, attrs, container_default),
|
||||
),
|
||||
syn::VariantData::Tuple(ref fields) => {
|
||||
(Style::Tuple, fields_from_ast(cx, fields, attrs, container_default))
|
||||
}
|
||||
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
|
||||
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr::Variant>) -> Vec<Field<'a>> {
|
||||
fn fields_from_ast<'a>(
|
||||
cx: &Ctxt,
|
||||
fields: &'a [syn::Field],
|
||||
attrs: Option<&attr::Variant>,
|
||||
container_default: &attr::Default,
|
||||
) -> Vec<Field<'a>> {
|
||||
fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
@ -135,7 +155,7 @@ fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr:
|
||||
|(i, field)| {
|
||||
Field {
|
||||
ident: field.ident.clone(),
|
||||
attrs: attr::Field::from_ast(cx, i, field, attrs),
|
||||
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
|
||||
ty: &field.ty,
|
||||
}
|
||||
},
|
||||
|
@ -723,7 +723,13 @@ pub enum Default {
|
||||
|
||||
impl Field {
|
||||
/// Extract out the `#[serde(...)]` attributes from a struct field.
|
||||
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field, attrs: Option<&Variant>) -> Self {
|
||||
pub fn from_ast(
|
||||
cx: &Ctxt,
|
||||
index: usize,
|
||||
field: &syn::Field,
|
||||
attrs: Option<&Variant>,
|
||||
container_default: &Default,
|
||||
) -> Self {
|
||||
let mut ser_name = Attr::none(cx, "rename");
|
||||
let mut de_name = Attr::none(cx, "rename");
|
||||
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
|
||||
@ -890,9 +896,10 @@ impl Field {
|
||||
}
|
||||
}
|
||||
|
||||
// Is skip_deserializing, initialize the field to Default::default()
|
||||
// unless a different default is specified by `#[serde(default = "...")]`
|
||||
if skip_deserializing.0.value.is_some() {
|
||||
// Is skip_deserializing, initialize the field to Default::default() unless a different
|
||||
// default is specified by `#[serde(default = "...")]` on ourselves or our container (e.g.
|
||||
// the struct we are in).
|
||||
if container_default == &Default::None && skip_deserializing.0.value.is_some() {
|
||||
default.set_if_none(Default::Default);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.17.0")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.18.0")]
|
||||
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.23" # remember to update html_root_url
|
||||
version = "1.0.24" # 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"
|
||||
|
@ -11,17 +11,17 @@ pub struct Compact<T: ?Sized>(T);
|
||||
|
||||
/// Trait to determine whether a value is represented in human-readable or
|
||||
/// compact form.
|
||||
///
|
||||
///
|
||||
/// ```
|
||||
/// extern crate serde;
|
||||
/// extern crate serde_test;
|
||||
///
|
||||
///
|
||||
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
/// use serde_test::{Configure, Token, assert_tokens};
|
||||
///
|
||||
///
|
||||
/// #[derive(Debug, PartialEq)]
|
||||
/// struct Example(u8, u8);
|
||||
///
|
||||
///
|
||||
/// impl Serialize for Example {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer,
|
||||
@ -33,7 +33,7 @@ pub struct Compact<T: ?Sized>(T);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// impl<'de> Deserialize<'de> for Example {
|
||||
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
/// where D: Deserializer<'de>,
|
||||
@ -52,7 +52,7 @@ pub struct Compact<T: ?Sized>(T);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// fn main() {
|
||||
/// assert_tokens(
|
||||
/// &Example(1, 0).compact(),
|
||||
|
@ -155,7 +155,7 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.23")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.24")]
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// Whitelisted clippy lints
|
||||
|
@ -80,6 +80,20 @@ struct StructSkipAll {
|
||||
#[serde(skip_deserializing)] a: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(default)]
|
||||
struct StructSkipDefault {
|
||||
#[serde(skip_deserializing)] a: i32,
|
||||
}
|
||||
|
||||
impl Default for StructSkipDefault {
|
||||
fn default() -> Self {
|
||||
StructSkipDefault {
|
||||
a: 16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct StructSkipAllDenyUnknown {
|
||||
@ -600,6 +614,12 @@ declare_tests! {
|
||||
Token::StructEnd,
|
||||
],
|
||||
}
|
||||
test_struct_skip_default {
|
||||
StructSkipDefault { a: 16 } => &[
|
||||
Token::Struct { name: "StructSkipDefault", len: 0 },
|
||||
Token::StructEnd,
|
||||
],
|
||||
}
|
||||
test_struct_skip_all_deny_unknown {
|
||||
StructSkipAllDenyUnknown { a: 0 } => &[
|
||||
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user