Merge branch serde-rs/master into serde-rs/forward

This commit is contained in:
David Tolnay 2016-09-05 07:59:42 -07:00
commit 3692edfd08
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
14 changed files with 369 additions and 96 deletions

View File

@ -1,4 +1,4 @@
# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Coverage Status](https://coveralls.io/repos/serde-rs/serde/badge.svg?branch=master&service=github)](https://coveralls.io/github/serde-rs/serde?branch=master) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde) [![Clippy Linting Result](https://clippy.bashy.io/github/serde-rs/serde/master/badge.svg)](https://clippy.bashy.io/github/serde-rs/serde/master/log)
# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde)
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**

View File

@ -1,6 +1,6 @@
[package]
name = "serde"
version = "0.8.4"
version = "0.8.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"

View File

@ -709,6 +709,15 @@ impl<I, K, V, E> MapDeserializer<I, K, V, E>
marker: PhantomData,
}
}
fn next(&mut self) -> Option<(K, V)> {
self.iter.next().map(|(k, v)| {
if let Some(len) = self.len.as_mut() {
*len -= 1;
}
(k, v)
})
}
}
impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
@ -725,10 +734,59 @@ impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
visitor.visit_map(self)
}
<<<<<<< HEAD
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option seq seq_fixed_size bytes map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
||||||| merged common ancestors
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
=======
fn deserialize_seq<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
{
visitor.visit_seq(self)
}
fn deserialize_seq_fixed_size<V_>(&mut self, len: usize, mut visitor: V_) -> Result<V_::Value, Self::Error>
where V_: de::Visitor,
{
match self.len {
Some(map_len) if map_len == len => visitor.visit_seq(self),
Some(_) => Err(de::Error::invalid_length(len)),
None => visitor.visit_seq(self),
}
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
>>>>>>> origin/master
}
}
@ -743,14 +801,11 @@ impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
fn visit_key<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize,
{
match self.iter.next() {
match self.next() {
Some((key, value)) => {
if let Some(len) = self.len.as_mut() {
*len -= 1;
}
self.value = Some(value);
let mut de = key.into_deserializer();
Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
de::Deserialize::deserialize(&mut de).map(Some)
}
None => Ok(None),
}
@ -784,6 +839,132 @@ impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
}
}
impl<I, K, V, E> de::SeqVisitor for MapDeserializer<I, K, V, E>
where I: Iterator<Item=(K, V)>,
K: ValueDeserializer<E>,
V: ValueDeserializer<E>,
E: de::Error,
{
type Error = E;
fn visit<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize,
{
match self.next() {
Some(kv) => {
let mut de = PairDeserializer(Some(kv), PhantomData);
de::Deserialize::deserialize(&mut de).map(Some)
}
None => Ok(None),
}
}
fn end(&mut self) -> Result<(), Self::Error> {
de::MapVisitor::end(self)
}
fn size_hint(&self) -> (usize, Option<usize>) {
de::MapVisitor::size_hint(self)
}
}
// Used in the `impl SeqVisitor for MapDeserializer` to visit the map as a
// sequence of pairs.
struct PairDeserializer<A, B, E>(Option<(A, B)>, PhantomData<E>);
impl<A, B, E> de::Deserializer for PairDeserializer<A, B, E>
where A: ValueDeserializer<E>,
B: ValueDeserializer<E>,
E: de::Error
{
type Error = E;
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit, deserialize_option,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct
}
fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
self.deserialize_seq(visitor)
}
fn deserialize_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some((k, v)) => {
visitor.visit_seq(PairVisitor(Some(k), Some(v), PhantomData))
}
None => Err(de::Error::end_of_stream()),
}
}
fn deserialize_seq_fixed_size<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
if len == 2 {
self.deserialize_seq(visitor)
} else {
Err(de::Error::invalid_length(len))
}
}
}
struct PairVisitor<A, B, E>(Option<A>, Option<B>, PhantomData<E>);
impl<A, B, E> de::SeqVisitor for PairVisitor<A, B, E>
where A: ValueDeserializer<E>,
B: ValueDeserializer<E>,
E: de::Error,
{
type Error = E;
fn visit<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize,
{
if let Some(k) = self.0.take() {
let mut de = k.into_deserializer();
de::Deserialize::deserialize(&mut de).map(Some)
} else if let Some(v) = self.1.take() {
let mut de = v.into_deserializer();
de::Deserialize::deserialize(&mut de).map(Some)
} else {
Ok(None)
}
}
fn end(&mut self) -> Result<(), Self::Error> {
if self.1.is_none() {
Ok(())
} else {
Err(de::Error::invalid_length(self.size_hint().0))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = if self.0.is_some() {
2
} else if self.1.is_some() {
1
} else {
0
};
(len, Some(len))
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]

View File

@ -1,6 +1,6 @@
[package]
name = "serde_codegen"
version = "0.8.4"
version = "0.8.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
@ -25,14 +25,14 @@ with-syntex = [
]
[build-dependencies]
quasi_codegen = { version = "^0.18.0", optional = true }
syntex = { version = "^0.42.2", optional = true }
quasi_codegen = { version = "^0.19.0", optional = true }
syntex = { version = "^0.43.0", optional = true }
[dependencies]
aster = { version = "^0.25.0", default-features = false }
aster = { version = "^0.26.0", default-features = false }
clippy = { version = "^0.*", optional = true }
quasi = { version = "^0.18.0", default-features = false }
quasi_macros = { version = "^0.18.0", optional = true }
serde_codegen_internals = { version = "=0.7.0", default-features = false, path = "../serde_codegen_internals" }
syntex = { version = "^0.42.2", optional = true }
syntex_syntax = { version = "^0.42.0", optional = true }
quasi = { version = "^0.19.0", default-features = false }
quasi_macros = { version = "^0.19.0", optional = true }
serde_codegen_internals = { version = "=0.8.0", default-features = false, path = "../serde_codegen_internals" }
syntex = { version = "^0.43.0", optional = true }
syntex_syntax = { version = "^0.43.0", optional = true }

View File

@ -35,6 +35,58 @@ include!(concat!(env!("OUT_DIR"), "/lib.rs"));
#[cfg(not(feature = "with-syntex"))]
include!("lib.rs.in");
#[cfg(feature = "with-syntex")]
fn syntex_registry() -> syntex::Registry {
use syntax::{ast, fold};
/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
/// Helper folder that strips the serde attributes after the extensions have been expanded.
struct StripAttributeFolder;
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; }
_ => {}
}
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}
let mut reg = syntex::Registry::new();
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg
}
#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
let src = src.to_owned();
let expand_thread = move || {
syntex_registry().expand_str("", "", &src)
};
syntex::with_extra_stack(expand_thread)
}
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
@ -44,43 +96,7 @@ pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
let dst = dst.as_ref().to_owned();
let expand_thread = move || {
use syntax::{ast, fold};
/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
/// Helper folder that strips the serde attributes after the extensions have been expanded.
struct StripAttributeFolder;
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; }
_ => {}
}
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}
let mut reg = syntex::Registry::new();
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg.expand("", src, dst)
syntex_registry().expand("", src, dst)
};
syntex::with_extra_stack(expand_thread)

View File

@ -532,19 +532,21 @@ fn serialize_tuple_struct_visitor(
};
let skip = field.attrs.skip_serializing_if()
.map(|path| quote_expr!(cx, $path($field_expr)))
.unwrap_or(quote_expr!(cx, false));
.map(|path| quote_expr!(cx, $path($field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr);
}
quote_stmt!(cx,
if !$skip {
try!(_serializer.$func(&mut state, $field_expr));
}
).unwrap()
let ser = quote_expr!(cx,
try!(_serializer.$func(&mut state, $field_expr));
);
match skip {
None => quote_stmt!(cx, $ser).unwrap(),
Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(),
}
})
.collect()
}
@ -571,19 +573,21 @@ fn serialize_struct_visitor(
let key_expr = name_expr(builder, field.attrs.name());
let skip = field.attrs.skip_serializing_if()
.map(|path| quote_expr!(cx, $path($field_expr)))
.unwrap_or(quote_expr!(cx, false));
.map(|path| quote_expr!(cx, $path($field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr)
}
quote_stmt!(cx,
if !$skip {
try!(_serializer.$func(&mut state, $key_expr, $field_expr));
}
).unwrap()
let ser = quote_expr!(cx,
try!(_serializer.$func(&mut state, $key_expr, $field_expr));
);
match skip {
None => quote_stmt!(cx, $ser).unwrap(),
Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(),
}
})
.collect()
}

View File

@ -1,6 +1,6 @@
[package]
name = "serde_codegen_internals"
version = "0.7.0"
version = "0.8.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
@ -17,5 +17,5 @@ with-syntex = ["syntex_syntax", "syntex_errors"]
[dependencies]
clippy = { version = "^0.*", optional = true }
syntex_syntax = { version = "^0.42.0", optional = true }
syntex_errors = { version = "^0.42.0", optional = true }
syntex_syntax = { version = "^0.43.0", optional = true }
syntex_errors = { version = "^0.43.0", optional = true }

View File

@ -8,8 +8,7 @@ use syntax::fold::Folder;
use syntax::parse::parser::{Parser, PathStyle};
use syntax::parse::token::{self, InternedString};
use syntax::parse;
use syntax::print::pprust::{lit_to_string, meta_item_to_string};
use syntax::ptr::P;
use syntax::print::pprust::{lit_to_string, meta_item_to_string, meta_list_item_to_string};
use syntax::tokenstream::{self, TokenTree};
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
@ -165,7 +164,7 @@ impl Item {
cx.span_err(
meta_item.span,
&format!("unknown serde container attribute `{}`",
meta_item_to_string(meta_item)));
meta_item_to_string(&meta_item)));
}
}
}
@ -236,7 +235,7 @@ impl Variant {
cx.span_err(
meta_item.span,
&format!("unknown serde variant attribute `{}`",
meta_item_to_string(meta_item)));
meta_item_to_string(&meta_item)));
}
}
}
@ -384,7 +383,7 @@ impl Field {
cx.span_err(
meta_item.span,
&format!("unknown serde field attribute `{}`",
meta_item_to_string(meta_item)));
meta_item_to_string(&meta_item)));
}
}
}
@ -454,7 +453,7 @@ type SerAndDe<T> = (Option<Spanned<T>>, Option<Spanned<T>>);
fn get_ser_and_de<T, F>(
cx: &ExtCtxt,
attribute: &'static str,
items: &[P<ast::MetaItem>],
items: &[ast::NestedMetaItem],
f: F
) -> Result<SerAndDe<T>, ()>
where F: Fn(&ExtCtxt, &str, &ast::Lit) -> Result<T, ()>,
@ -464,15 +463,29 @@ fn get_ser_and_de<T, F>(
for item in items {
match item.node {
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => {
if let Ok(v) = f(cx, name, lit) {
ser_item.set(item.span, v);
}
}
ast::NestedMetaItemKind::MetaItem(ref meta_item) => {
match meta_item.node {
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => {
if let Ok(v) = f(cx, name, lit) {
ser_item.set(item.span, v);
}
}
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => {
if let Ok(v) = f(cx, name, lit) {
de_item.set(item.span, v);
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => {
if let Ok(v) = f(cx, name, lit) {
de_item.set(item.span, v);
}
}
_ => {
cx.span_err(
item.span,
&format!("unknown {} attribute `{}`",
attribute,
meta_item_to_string(meta_item)));
return Err(());
}
}
}
@ -481,7 +494,7 @@ fn get_ser_and_de<T, F>(
item.span,
&format!("unknown {} attribute `{}`",
attribute,
meta_item_to_string(item)));
meta_list_item_to_string(item)));
return Err(());
}
@ -493,23 +506,30 @@ fn get_ser_and_de<T, F>(
fn get_renames(
cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
items: &[ast::NestedMetaItem],
) -> Result<SerAndDe<InternedString>, ()> {
get_ser_and_de(cx, "rename", items, get_str_from_lit)
}
fn get_where_predicates(
cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
items: &[ast::NestedMetaItem],
) -> Result<SerAndDe<Vec<ast::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
pub fn get_serde_meta_items(attr: &ast::Attribute) -> Option<&[P<ast::MetaItem>]> {
pub fn get_serde_meta_items(attr: &ast::Attribute) -> Option<Vec<ast::MetaItem>> {
match attr.node.value.node {
ast::MetaItemKind::List(ref name, ref items) if name == &"serde" => {
attr::mark_used(attr);
Some(items)
Some(items.iter().filter_map(|item| {
match item.node {
ast::NestedMetaItemKind::MetaItem(ref meta_item) => {
Some((*meta_item.clone()).clone())
}
_ => None,
}
}).collect())
}
_ => None
}

23
serde_derive/Cargo.toml Normal file
View File

@ -0,0 +1,23 @@
[package]
name = "serde_derive"
version = "0.8.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[lib]
name = "serde_derive"
rustc-macro = true
[dependencies]
serde_codegen = { version = "=0.8.6", path = "../serde_codegen" }
[dev-dependencies]
fnv = "1.0"
serde = { version = "0.8.6", path = "../serde" }
serde_test = { version = "0.8.6", path = "../serde_test" }

21
serde_derive/src/lib.rs Normal file
View File

@ -0,0 +1,21 @@
#![feature(rustc_macro, rustc_macro_lib)]
#![cfg(not(test))]
extern crate rustc_macro;
extern crate serde_codegen;
use rustc_macro::TokenStream;
#[rustc_macro_derive(Serialize)]
pub fn derive_serialize(input: TokenStream) -> TokenStream {
let item = format!("#[derive(Serialize)]\n{}", input);
let expanded = serde_codegen::expand_str(&item).unwrap();
expanded.parse().unwrap()
}
#[rustc_macro_derive(Deserialize)]
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
let item = format!("#[derive(Deserialize)]\n{}", input);
let expanded = serde_codegen::expand_str(&item).unwrap();
expanded.parse().unwrap()
}

View File

@ -0,0 +1,8 @@
#![feature(test, rustc_macro, rustc_attrs)]
#[macro_use]
extern crate serde_derive;
extern crate test;
include!("../../testing/tests/test.rs.in");

View File

@ -1,6 +1,6 @@
[package]
name = "serde_macros"
version = "0.8.4"
version = "0.8.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
@ -23,14 +23,14 @@ unstable-testing = [
[dependencies]
clippy = { version = "^0.*", optional = true }
serde_codegen = { version = "=0.8.4", default-features = false, features = ["unstable"], path = "../serde_codegen" }
serde_codegen = { version = "=0.8.6", default-features = false, features = ["unstable"], path = "../serde_codegen" }
[dev-dependencies]
compiletest_rs = "^0.2.0"
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = { version = "0.8.4", path = "../serde" }
serde_test = { version = "0.8.4", path = "../serde_test" }
serde = { version = "0.8.6", path = "../serde" }
serde_test = { version = "0.8.6", path = "../serde_test" }
[[test]]
name = "test"

View File

@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "0.8.4"
version = "0.8.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
@ -12,4 +12,4 @@ keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[dependencies]
serde = { version = "0.8.4", path = "../serde" }
serde = { version = "0.8.6", path = "../serde" }

View File

@ -1,6 +1,6 @@
[package]
name = "serde_testing"
version = "0.8.4"
version = "0.8.6"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"