Compare commits

...

5 Commits

Author SHA1 Message Date
David Tolnay b4076f4577 Release 1.0.51 2018-05-08 10:07:45 -07:00
David Tolnay c4181f46be Respect variant skip attribute in inferred bounds 2018-05-07 21:30:00 -07:00
David Tolnay 8c0efc3d77 Add a variant skip attribute 2018-05-07 21:27:34 -07:00
David Tolnay 7e3efaf6c5 Improve error when a 'de lifetime parameter already exists 2018-05-07 21:15:44 -07:00
David Tolnay 12fe42ed45 Support empty adjacently tagged enum 2018-05-07 21:02:42 -07:00
11 changed files with 89 additions and 23 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.50" # remember to update html_root_url
version = "1.0.51" # 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"
+1 -1
View File
@@ -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.50")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.51")]
// 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
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.50" # remember to update html_root_url
version = "1.0.51" # 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)]"
+41 -12
View File
@@ -82,6 +82,11 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
}
fn precondition(cx: &Ctxt, cont: &Container) {
precondition_sized(cx, cont);
precondition_no_de_lifetime(cx, cont);
}
fn precondition_sized(cx: &Ctxt, cont: &Container) {
if let Data::Struct(_, ref fields) = cont.data {
if let Some(last) = fields.last() {
if let syn::Type::Slice(_) = *last.ty {
@@ -91,6 +96,17 @@ fn precondition(cx: &Ctxt, cont: &Container) {
}
}
fn precondition_no_de_lifetime(cx: &Ctxt, cont: &Container) {
if let BorrowedLifetimes::Borrowed(_) = borrowed_lifetimes(cont) {
for param in cont.generics.lifetimes() {
if param.lifetime.to_string() == "'de" {
cx.error("cannot deserialize when there is a lifetime parameter called 'de");
return;
}
}
}
}
struct Parameters {
/// Name of the type the `derive` is on.
local: syn::Ident,
@@ -175,13 +191,17 @@ fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generi
}
}
// Fields with a `skip_deserializing` or `deserialize_with` attribute are not
// deserialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Deserialize` bound where T is the type of the field.
// Fields with a `skip_deserializing` or `deserialize_with` attribute, or which
// belong to a variant with a `skip_deserializing` or `deserialize_with`
// attribute, are not deserialized by us so we do not generate a bound. Fields
// with a `bound` attribute specify their own bound so we do not generate one.
// All other fields may need a `T: Deserialize` bound where T is the type of the
// field.
fn needs_deserialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_deserializing() && field.deserialize_with().is_none() && field.de_bound().is_none()
&& variant.map_or(true, |variant| variant.deserialize_with().is_none())
&& variant.map_or(true, |variant| {
!variant.skip_deserializing() && variant.deserialize_with().is_none()
})
}
// Fields with a `default` attribute (not `default=...`), and fields with a
@@ -1393,6 +1413,21 @@ fn deserialize_adjacently_tagged_enum(
}
};
let finish_content_then_tag = if variant_arms.is_empty() {
quote! {
match try!(_serde::de::MapAccess::next_value::<__Field>(&mut __map)) {}
}
} else {
quote! {
let __ret = try!(match try!(_serde::de::MapAccess::next_value(&mut __map)) {
// Deserialize the buffered content now that we know the variant.
#(#variant_arms)*
});
// Visit remaining keys, looking for duplicates.
#visit_remaining_keys
}
};
quote_block! {
#variant_visitor
@@ -1469,13 +1504,7 @@ fn deserialize_adjacently_tagged_enum(
// Second key is the tag.
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
let __deserializer = _serde::private::de::ContentDeserializer::<__A::Error>::new(__content);
// Parse the tag.
let __ret = try!(match try!(_serde::de::MapAccess::next_value(&mut __map)) {
// Deserialize the buffered content now that we know the variant.
#(#variant_arms)*
});
// Visit remaining keys, looking for duplicates.
#visit_remaining_keys
#finish_content_then_tag
}
// Second key is a duplicate of the content.
_serde::export::Some(_serde::private::de::TagOrContentField::Content) => {
+6
View File
@@ -580,6 +580,12 @@ impl Variant {
}
}
// Parse `#[serde(skip)]`
Meta(Word(word)) if word == "skip" => {
skip_serializing.set_true();
skip_deserializing.set_true();
}
// Parse `#[serde(skip_deserializing)]`
Meta(Word(word)) if word == "skip_deserializing" => {
skip_deserializing.set_true();
+1 -1
View File
@@ -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.50")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.51")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
+7 -5
View File
@@ -150,13 +150,15 @@ fn build_generics(cont: &Container) -> syn::Generics {
}
// Fields with a `skip_serializing` or `serialize_with` attribute, or which
// belong to a variant with a `serialize_with` attribute, are not serialized by
// us so we do not generate a bound. Fields with a `bound` attribute specify
// their own bound so we do not generate one. All other fields may need a `T:
// Serialize` bound where T is the type of the field.
// belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
// are not serialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
&& variant.map_or(true, |variant| variant.serialize_with().is_none())
&& variant.map_or(true, |variant| {
!variant.skip_serializing() && variant.serialize_with().is_none()
})
}
fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.50" # remember to update html_root_url
version = "1.0.51" # 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"
+1 -1
View File
@@ -161,7 +161,7 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.50")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.51")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
@@ -0,0 +1,15 @@
// Copyright 2018 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct S<'de> {
s: &'de str, //~^^ HELP: cannot deserialize when there is a lifetime parameter called 'de
}
+14
View File
@@ -588,6 +588,20 @@ fn test_gen() {
}
}
}
#[derive(Deserialize)]
#[serde(tag = "t", content = "c")]
enum AdjacentlyTaggedVoid {}
#[derive(Serialize, Deserialize)]
enum SkippedVariant<T> {
#[serde(skip)]
#[allow(dead_code)]
T(T),
Unit,
}
assert::<SkippedVariant<X>>();
}
//////////////////////////////////////////////////////////////////////////