Compare commits

...

14 Commits

Author SHA1 Message Date
Simon Persson a5d0703e44 Bump clippy dependency to compile on 1.8. 2016-01-23 16:15:31 -08:00
Erick Tryzelaar 0a32cea26e feat(impls): Allow options to be deserialized from units 2016-01-23 16:07:50 -08:00
Erick Tryzelaar da4e37d3f5 docs(tradeoffs): Add section that describes tradeoffs for option types 2016-01-20 11:15:43 -08:00
Erick Tryzelaar 3f9cbc157a fix(cargo): serde_codegen shouldn't depend on '*' serde dependencies 2016-01-18 13:15:09 -08:00
Erick Tryzelaar a51f930101 feat(cargo): Version bump 2016-01-18 13:11:16 -08:00
Erick Tryzelaar 77edd8e544 fix(clippy): Switch to using or_else when we get a str parse error 2016-01-18 13:07:30 -08:00
Erick Tryzelaar 8087b7cec6 fix(cargo): Bump clippy version 2016-01-18 13:00:21 -08:00
Erick Tryzelaar 8df841f048 fix(errors): Report errors on unknown #[serde(...)] attributes
Closes #51, #175, and #187
2016-01-18 12:39:46 -08:00
Erick Tryzelaar bfa2b69193 feat(clippy): Use clippy for it's extra lints 2016-01-18 12:24:03 -08:00
Erick Tryzelaar fbcf905c9f Merge pull request #210 from erickt/v0.6.x
feat(errors): Don't panic if annotating a non-struct/enum
2016-01-16 15:06:07 -08:00
Erick Tryzelaar 979a4bcd88 feat(errors): Don't panic if annotating a non-struct/enum
This also improves the error spans when there's an internal
error.

Closes #206.
2016-01-16 14:51:11 -08:00
Erick Tryzelaar 342ea25290 feat(cargo): Version bump 2016-01-13 07:05:32 -08:00
Erick Tryzelaar 8d8f17982a feat(cargo): Version bump 2016-01-13 06:59:30 -08:00
Erick Tryzelaar dd3233ac85 fix(cargo): Fix typos 2016-01-10 11:50:35 -08:00
26 changed files with 550 additions and 266 deletions
+63
View File
@@ -579,6 +579,69 @@ impl serde::de::Visitor for PointVisitor {
}
```
Design Considerations and tradeoffs for Serializers and Deserializers
=====================================================================
Serde serialization and deserialization implementations are written in such a
way that they err on being able to represent more values, and also provide
better error messages when they are passed an incorrect type to deserialize
from. For example, by default, it is a syntax error to deserialize a `String`
into an `Option<String>`. This is implemented such that it is possible to
distinguish between the values `None` and `Some(())`, if the serialization
format supports option types.
However, many formats do not have option types, and represents optional values
as either a `null`, or some other value. Serde `Serializer`s and
`Deserializer`s can opt-in support for this. For serialization, this is pretty
easy. Simply implement these methods:
```rust
...
fn visit_none(&mut self) -> Result<(), Self::Error> {
self.visit_unit()
}
fn visit_some<T>(&mut self, value: T) -> Result<(), Self::Error> {
value.serialize(self)
}
...
```
For deserialization, this can be implemented by way of the
`Deserializer::visit_option` hook, which presumes that there is some ability to peek at what is the
next value in the serialized token stream. This following example is from
[serde_tests::TokenDeserializer](https://github.com/serde-rs/serde/blob/master/serde_tests/tests/token.rs#L435-L454),
where it checks to see if the next value is an `Option`, a `()`, or some other
value:
```rust
...
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.tokens.peek() {
Some(&Token::Option(false)) => {
self.tokens.next();
visitor.visit_none()
}
Some(&Token::Option(true)) => {
self.tokens.next();
visitor.visit_some(self)
}
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_none()
}
Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfStreamError),
}
}
...
```
Annotations
===========
+7 -6
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "0.6.7"
version = "0.6.11"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -9,12 +9,13 @@ documentation = "https://serde-rs.github.io/serde/serde/serde/index.html"
readme = "../README.md"
keywords = ["serde", "serialization"]
[dependencies]
num = "^0.1.27"
[features]
nightly = []
num-impls = ["num-bigint", "num-complex", "num-rational"]
nightly = ["clippy"]
num-bigint = ["num/bigint"]
num-complex = ["num/complex"]
num-impls = ["num-bigint", "num-complex", "num-rational"]
num-rational = ["num/rational"]
[dependencies]
clippy = { version = "^0.0.37", optional = true }
num = { version = "^0.1.27", default-features = false }
+13 -4
View File
@@ -154,7 +154,9 @@ impl<
fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
where E: Error,
{
str::FromStr::from_str(v.trim()).or(Err(Error::type_mismatch(Type::Str)))
str::FromStr::from_str(v.trim()).or_else(|_| {
Err(Error::type_mismatch(Type::Str))
})
}
}
@@ -234,7 +236,7 @@ impl Visitor for StringVisitor {
fn visit_str<E>(&mut self, v: &str) -> Result<String, E>
where E: Error,
{
Ok(v.to_string())
Ok(v.to_owned())
}
fn visit_string<E>(&mut self, v: String) -> Result<String, E>
@@ -247,12 +249,12 @@ impl Visitor for StringVisitor {
where E: Error,
{
match str::from_utf8(v) {
Ok(s) => Ok(s.to_string()),
Ok(s) => Ok(s.to_owned()),
Err(_) => Err(Error::type_mismatch(Type::String)),
}
}
fn visit_byte_buf<'a, E>(&mut self, v: Vec<u8>) -> Result<String, E>
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<String, E>
where E: Error,
{
match String::from_utf8(v) {
@@ -281,6 +283,13 @@ impl<
> Visitor for OptionVisitor<T> {
type Value = Option<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
{
Ok(None)
}
#[inline]
fn visit_none<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
+4 -1
View File
@@ -10,7 +10,10 @@
//! [github repository](https://github.com/serde-rs/serde)
#![doc(html_root_url="https://serde-rs.github.io/serde/serde")]
#![cfg_attr(feature = "nightly", feature(collections, enumset, nonzero, step_trait, zero_one))]
#![cfg_attr(feature = "nightly", feature(collections, enumset, nonzero, plugin, step_trait,
zero_one))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
#![cfg_attr(feature = "nightly", allow(linkedlist))]
#![deny(missing_docs)]
+2 -2
View File
@@ -566,8 +566,8 @@ impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
{
match self.iter.next() {
Some((key, value)) => {
let value = try!(serializer.visit_map_elt(key, value));
Ok(Some(value))
try!(serializer.visit_map_elt(key, value));
Ok(Some(()))
}
None => Ok(None)
}
+2
View File
@@ -322,6 +322,7 @@ pub trait Serializer {
}
/// A trait that is used by a `Serialize` to iterate through a sequence.
#[cfg_attr(feature = "nightly", allow(len_without_is_empty))]
pub trait SeqVisitor {
/// Serializes a sequence item in the serializer.
///
@@ -338,6 +339,7 @@ pub trait SeqVisitor {
}
/// A trait that is used by a `Serialize` to iterate through a map.
#[cfg_attr(feature = "nightly", allow(len_without_is_empty))]
pub trait MapVisitor {
/// Serializes a map item in the serializer.
///
+10 -9
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_codegen"
version = "0.6.8"
version = "0.6.11"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
@@ -11,16 +11,17 @@ keywords = ["serde", "serialization"]
[features]
default = ["with-syntex"]
nightly = ["quasi_macros"]
nightly = ["clippy", "quasi_macros"]
with-syntex = ["quasi/with-syntex", "quasi_codegen", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"]
[build-dependencies]
quasi_codegen = { verision = "^0.3.12", optional = true }
syntex = { version = "^0.25.0", optional = true }
quasi_codegen = { version = "^0.4.0", optional = true }
syntex = { version = "^0.26.0", optional = true }
[dependencies]
aster = { version = "^0.9.3", default-features = false }
quasi = { verision = "^0.3.12", default-features = false }
quasi_macros = { version = "^0.3.12", optional = true }
syntex = { version = "^0.25.0", optional = true }
syntex_syntax = { version = "^0.25.0", optional = true }
aster = { version = "^0.10.0", default-features = false }
clippy = { version = "^0.0.37", optional = true }
quasi = { version = "^0.4.0", default-features = false }
quasi_macros = { version = "^0.4.0", optional = true }
syntex = { version = "^0.26.0", optional = true }
syntex_syntax = { version = "^0.26.0", optional = true }
+90 -18
View File
@@ -4,6 +4,7 @@ use std::collections::HashSet;
use syntax::ast;
use syntax::attr;
use syntax::ext::base::ExtCtxt;
use syntax::print::pprust::meta_item_to_string;
use syntax::ptr::P;
use aster;
@@ -32,7 +33,7 @@ impl FieldAttrs {
/// Return a set of formats that the field has attributes for.
pub fn formats(&self) -> HashSet<P<ast::Expr>> {
match self.names {
FieldNames::Format{ref formats, default: _} => {
FieldNames::Format { ref formats, .. } => {
let mut set = HashSet::new();
for (fmt, _) in formats.iter() {
set.insert(fmt.clone());
@@ -70,7 +71,7 @@ impl FieldAttrs {
pub fn default_key_expr(&self) -> &P<ast::Expr> {
match self.names {
FieldNames::Global(ref expr) => expr,
FieldNames::Format{formats: _, ref default} => default,
FieldNames::Format { ref default, .. } => default,
}
}
@@ -104,6 +105,7 @@ impl FieldAttrs {
}
pub struct FieldAttrsBuilder<'a> {
cx: &'a ExtCtxt<'a>,
builder: &'a aster::AstBuilder,
skip_serializing_field: bool,
skip_serializing_field_if_empty: bool,
@@ -114,8 +116,10 @@ pub struct FieldAttrsBuilder<'a> {
}
impl<'a> FieldAttrsBuilder<'a> {
pub fn new(builder: &'a aster::AstBuilder) -> FieldAttrsBuilder<'a> {
pub fn new(cx: &'a ExtCtxt<'a>,
builder: &'a aster::AstBuilder) -> FieldAttrsBuilder<'a> {
FieldAttrsBuilder {
cx: cx,
builder: builder,
skip_serializing_field: false,
skip_serializing_field_if_empty: false,
@@ -126,7 +130,7 @@ impl<'a> FieldAttrsBuilder<'a> {
}
}
pub fn field(mut self, field: &ast::StructField) -> FieldAttrsBuilder<'a> {
pub fn field(mut self, field: &ast::StructField) -> Result<FieldAttrsBuilder<'a>, ()> {
match field.node.kind {
ast::NamedField(name, _) => {
self.name = Some(self.builder.expr().str(name));
@@ -137,28 +141,36 @@ impl<'a> FieldAttrsBuilder<'a> {
self.attrs(&field.node.attrs)
}
pub fn attrs(self, attrs: &[ast::Attribute]) -> FieldAttrsBuilder<'a> {
attrs.iter().fold(self, FieldAttrsBuilder::attr)
pub fn attrs(mut self, attrs: &[ast::Attribute]) -> Result<FieldAttrsBuilder<'a>, ()> {
for attr in attrs {
self = try!(self.attr(attr));
}
Ok(self)
}
pub fn attr(self, attr: &ast::Attribute) -> FieldAttrsBuilder<'a> {
pub fn attr(mut self, attr: &ast::Attribute) -> Result<FieldAttrsBuilder<'a>, ()> {
match attr.node.value.node {
ast::MetaList(ref name, ref items) if name == &"serde" => {
attr::mark_used(&attr);
items.iter().fold(self, FieldAttrsBuilder::meta_item)
for item in items {
self = try!(self.meta_item(item));
}
Ok(self)
}
_ => {
self
Ok(self)
}
}
}
pub fn meta_item(mut self, meta_item: &P<ast::MetaItem>) -> FieldAttrsBuilder<'a> {
pub fn meta_item(mut self, meta_item: &P<ast::MetaItem>) -> Result<FieldAttrsBuilder<'a>, ()> {
match meta_item.node {
ast::MetaNameValue(ref name, ref lit) if name == &"rename" => {
let expr = self.builder.expr().build_lit(P(lit.clone()));
self.name(expr)
Ok(self.name(expr))
}
ast::MetaList(ref name, ref items) if name == &"rename" => {
for item in items {
@@ -172,23 +184,27 @@ impl<'a> FieldAttrsBuilder<'a> {
_ => { }
}
}
self
Ok(self)
}
ast::MetaWord(ref name) if name == &"default" => {
self.default()
Ok(self.default())
}
ast::MetaWord(ref name) if name == &"skip_serializing" => {
self.skip_serializing_field()
Ok(self.skip_serializing_field())
}
ast::MetaWord(ref name) if name == &"skip_serializing_if_empty" => {
self.skip_serializing_field_if_empty()
Ok(self.skip_serializing_field_if_empty())
}
ast::MetaWord(ref name) if name == &"skip_serializing_if_none" => {
self.skip_serializing_field_if_none()
Ok(self.skip_serializing_field_if_none())
}
_ => {
// Ignore unknown meta variables for now.
self
self.cx.span_err(
meta_item.span,
&format!("unknown serde field attribute `{}`",
meta_item_to_string(meta_item)));
Err(())
}
}
}
@@ -243,3 +259,59 @@ impl<'a> FieldAttrsBuilder<'a> {
}
}
}
/// Represents container (e.g. struct) attribute information
#[derive(Debug)]
pub struct ContainerAttrs;
pub struct ContainerAttrsBuilder<'a> {
cx: &'a ExtCtxt<'a>,
}
impl<'a> ContainerAttrsBuilder<'a> {
pub fn new(cx: &'a ExtCtxt) -> Self {
ContainerAttrsBuilder {
cx: cx,
}
}
pub fn attrs(mut self, attrs: &[ast::Attribute]) -> Result<Self, ()> {
for attr in attrs {
self = try!(self.attr(attr));
}
Ok(self)
}
pub fn attr(mut self, attr: &ast::Attribute) -> Result<Self, ()> {
match attr.node.value.node {
ast::MetaList(ref name, ref items) if name == &"serde" => {
attr::mark_used(&attr);
for item in items {
self = try!(self.meta_item(item));
}
Ok(self)
}
_ => {
Ok(self)
}
}
}
pub fn meta_item(self, meta_item: &P<ast::MetaItem>) -> Result<Self, ()> {
match meta_item.node {
_ => {
self.cx.span_err(
meta_item.span,
&format!("unknown serde container attribute `{}`",
meta_item_to_string(meta_item)));
Err(())
}
}
}
pub fn build(self) -> ContainerAttrs {
ContainerAttrs
}
}
+139 -123
View File
@@ -29,7 +29,7 @@ pub fn expand_derive_deserialize(
_ => {
cx.span_err(
meta_item.span,
"`derive` may only be applied to structs and enums");
"`#[derive(Deserialize)]` may only be applied to structs and enums");
return;
}
};
@@ -39,7 +39,12 @@ pub fn expand_derive_deserialize(
let generics = match item.node {
ast::ItemStruct(_, ref generics) => generics,
ast::ItemEnum(_, ref generics) => generics,
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Deserialize)]")
_ => {
cx.span_err(
meta_item.span,
"`#[derive(Deserialize)]` may only be applied to structs and enums");
return;
}
};
let impl_generics = builder.from_generics(generics.clone())
@@ -52,13 +57,13 @@ pub fn expand_derive_deserialize(
.segment(item.ident).with_generics(impl_generics.clone()).build()
.build();
let body = deserialize_body(
cx,
&builder,
&item,
&impl_generics,
ty.clone(),
);
let body = match deserialize_body(cx, &builder, &item, &impl_generics, ty.clone()) {
Ok(body) => body,
Err(()) => {
// An error occured, but it should have been reported already.
return;
}
};
let where_clause = &impl_generics.where_clause;
@@ -81,7 +86,11 @@ fn deserialize_body(
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
// Note: While we don't have any container attributes, we still want to try to
// parse them so we can report a proper error if we get passed an unknown attribute.
let _ = try!(field::container_attrs(cx, item));
match item.node {
ast::ItemStruct(ref variant_data, _) => {
deserialize_item_struct(
@@ -90,6 +99,7 @@ fn deserialize_body(
item,
impl_generics,
ty,
item.span,
variant_data,
)
}
@@ -103,7 +113,10 @@ fn deserialize_body(
enum_def,
)
}
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Deserialize)]")
_ => {
cx.span_bug(item.span,
"expected ItemStruct or ItemEnum in #[derive(Deserialize)]")
}
}
}
@@ -113,8 +126,9 @@ fn deserialize_item_struct(
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
span: Span,
variant_data: &ast::VariantData,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
match *variant_data {
ast::VariantData::Unit(_) => {
deserialize_unit_struct(
@@ -134,7 +148,7 @@ fn deserialize_item_struct(
}
ast::VariantData::Tuple(ref fields, _) => {
if fields.iter().any(|field| !field.node.kind.is_unnamed()) {
cx.bug("tuple struct has named fields")
cx.span_bug(span, "tuple struct has named fields")
}
deserialize_tuple_struct(
@@ -148,7 +162,7 @@ fn deserialize_item_struct(
}
ast::VariantData::Struct(ref fields, _) => {
if fields.iter().any(|field| field.node.kind.is_unnamed()) {
cx.bug("struct has unnamed fields")
cx.span_bug(span, "struct has unnamed fields")
}
deserialize_struct(
@@ -170,14 +184,14 @@ fn deserialize_visitor(
trait_generics: &ast::Generics,
forward_ty_params: Vec<ast::TyParam>,
forward_tys: Vec<P<ast::Ty>>
) -> (P<ast::Item>, P<ast::Ty>, P<ast::Expr>, ast::Generics) {
) -> Result<(P<ast::Item>, P<ast::Ty>, P<ast::Expr>, ast::Generics), ()> {
if trait_generics.ty_params.is_empty() && forward_tys.is_empty() {
(
Ok((
builder.item().tuple_struct("__Visitor").build(),
builder.ty().id("__Visitor"),
builder.expr().id("__Visitor"),
trait_generics.clone(),
)
))
} else {
let placeholders : Vec<_> = trait_generics.ty_params.iter()
.map(|t| builder.ty().id(t.ident))
@@ -187,7 +201,7 @@ fn deserialize_visitor(
ty_params.extend(trait_generics.ty_params.into_vec());
trait_generics.ty_params = P::from_vec(ty_params);
(
Ok((
builder.item().tuple_struct("__Visitor")
.generics().with(trait_generics.clone()).build()
.with_tys({
@@ -225,7 +239,7 @@ fn deserialize_visitor(
})
.build(),
trait_generics,
)
))
}
}
@@ -249,10 +263,10 @@ fn deserialize_unit_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
Ok(quote_expr!(cx, {
struct __Visitor;
impl ::serde::de::Visitor for __Visitor {
@@ -275,7 +289,7 @@ fn deserialize_unit_struct(
}
deserializer.visit_unit_struct($type_name, __Visitor)
})
}))
}
fn deserialize_newtype_struct(
@@ -284,16 +298,15 @@ fn deserialize_newtype_struct(
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
deserialize_visitor(
builder,
impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor(
builder,
impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
));
let visit_seq_expr = deserialize_seq(
cx,
@@ -304,7 +317,7 @@ fn deserialize_newtype_struct(
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$visitor_item
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
@@ -327,7 +340,7 @@ fn deserialize_newtype_struct(
}
deserializer.visit_newtype_struct($type_name, $visitor_expr)
})
}))
}
fn deserialize_tuple_struct(
@@ -337,16 +350,15 @@ fn deserialize_tuple_struct(
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
deserialize_visitor(
builder,
impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor(
builder,
impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
));
let visit_seq_expr = deserialize_seq(
cx,
@@ -357,7 +369,7 @@ fn deserialize_tuple_struct(
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$visitor_item
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
@@ -372,7 +384,7 @@ fn deserialize_tuple_struct(
}
deserializer.visit_tuple_struct($type_name, $fields, $visitor_expr)
})
}))
}
fn deserialize_seq(
@@ -414,7 +426,7 @@ fn deserialize_struct_as_seq(
builder: &aster::AstBuilder,
struct_path: ast::Path,
fields: &[ast::StructField],
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let let_values: Vec<P<ast::Stmt>> = (0 .. fields.len())
.map(|i| {
let name = builder.id(format!("__field{}", i));
@@ -437,7 +449,9 @@ fn deserialize_struct_as_seq(
(
match field.node.kind {
ast::NamedField(name, _) => name.clone(),
ast::UnnamedField(_) => cx.bug("struct contains unnamed fields"),
ast::UnnamedField(_) => {
cx.span_bug(field.span, "struct contains unnamed fields")
}
},
builder.expr().id(format!("__field{}", i)),
)
@@ -445,13 +459,13 @@ fn deserialize_struct_as_seq(
)
.build();
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$let_values
try!(visitor.end());
Ok($result)
})
}))
}
fn deserialize_struct(
@@ -461,35 +475,35 @@ fn deserialize_struct(
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[ast::StructField],
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = deserialize_visitor(
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor(
builder,
&impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
));
let type_path = builder.path().id(type_ident).build();
let visit_seq_expr = deserialize_struct_as_seq(
let visit_seq_expr = try!(deserialize_struct_as_seq(
cx,
builder,
type_path.clone(),
fields,
);
));
let (field_visitor, fields_stmt, visit_map_expr) = deserialize_struct_visitor(
let (field_visitor, fields_stmt, visit_map_expr) = try!(deserialize_struct_visitor(
cx,
builder,
type_path.clone(),
fields,
);
));
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$field_visitor
$visitor_item
@@ -515,7 +529,7 @@ fn deserialize_struct(
$fields_stmt
deserializer.visit_struct($type_name, FIELDS, $visitor_expr)
})
}))
}
fn deserialize_item_enum(
@@ -525,7 +539,7 @@ fn deserialize_item_enum(
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
enum_def: &EnumDef,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let where_clause = &impl_generics.where_clause;
let type_name = builder.expr().str(type_ident);
@@ -536,7 +550,7 @@ fn deserialize_item_enum(
enum_def.variants.iter()
.map(|variant| {
let expr = builder.expr().str(variant.node.name);
attr::FieldAttrsBuilder::new(builder)
attr::FieldAttrsBuilder::new(cx, builder)
.name(expr)
.default()
.build()
@@ -558,35 +572,33 @@ fn deserialize_item_enum(
).unwrap();
// Match arms to extract a variant from a string
let variant_arms: Vec<_> = enum_def.variants.iter()
.enumerate()
.map(|(i, variant)| {
let variant_name = builder.pat().enum_()
.id("__Field").id(format!("__field{}", i)).build()
.build();
let mut variant_arms = vec![];
for (i, variant) in enum_def.variants.iter().enumerate() {
let variant_name = builder.pat().enum_()
.id("__Field").id(format!("__field{}", i)).build()
.build();
let expr = deserialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
);
quote_arm!(cx, $variant_name => { $expr })
})
.collect();
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
deserialize_visitor(
let expr = try!(deserialize_variant(
cx,
builder,
type_ident,
impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
ty.clone(),
variant,
));
quote_expr!(cx, {
let arm = quote_arm!(cx, $variant_name => { $expr });
variant_arms.push(arm);
}
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor(
builder,
impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
));
Ok(quote_expr!(cx, {
$variant_visitor
$visitor_item
@@ -606,7 +618,7 @@ fn deserialize_item_enum(
$variants_stmt
deserializer.visit_enum($type_name, VARIANTS, $visitor_expr)
})
}))
}
fn deserialize_variant(
@@ -616,21 +628,21 @@ fn deserialize_variant(
generics: &ast::Generics,
ty: P<ast::Ty>,
variant: &ast::Variant,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let variant_ident = variant.node.name;
match variant.node.data {
ast::VariantData::Unit(_) => {
quote_expr!(cx, {
Ok(quote_expr!(cx, {
try!(visitor.visit_unit());
Ok($type_ident::$variant_ident)
})
}))
}
ast::VariantData::Tuple(ref args, _) if args.len() == 1 => {
quote_expr!(cx, {
Ok(quote_expr!(cx, {
let val = try!(visitor.visit_newtype());
Ok($type_ident::$variant_ident(val))
})
}))
}
ast::VariantData::Tuple(ref fields, _) => {
deserialize_tuple_variant(
@@ -665,16 +677,15 @@ fn deserialize_tuple_variant(
generics: &ast::Generics,
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let where_clause = &generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
deserialize_visitor(
builder,
generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor(
builder,
generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
));
let visit_seq_expr = deserialize_seq(
cx,
@@ -683,7 +694,7 @@ fn deserialize_tuple_variant(
fields,
);
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$visitor_item
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
@@ -697,7 +708,7 @@ fn deserialize_tuple_variant(
}
visitor.visit_tuple($fields, $visitor_expr)
})
}))
}
fn deserialize_struct_variant(
@@ -708,7 +719,7 @@ fn deserialize_struct_variant(
generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[ast::StructField],
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let where_clause = &generics.where_clause;
let type_path = builder.path()
@@ -716,29 +727,28 @@ fn deserialize_struct_variant(
.id(variant_ident)
.build();
let visit_seq_expr = deserialize_struct_as_seq(
let visit_seq_expr = try!(deserialize_struct_as_seq(
cx,
builder,
type_path.clone(),
fields,
);
));
let (field_visitor, fields_stmt, field_expr) = deserialize_struct_visitor(
let (field_visitor, fields_stmt, field_expr) = try!(deserialize_struct_visitor(
cx,
builder,
type_path,
fields,
);
));
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
deserialize_visitor(
builder,
generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = try!(deserialize_visitor(
builder,
generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
));
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$field_visitor
$visitor_item
@@ -764,7 +774,7 @@ fn deserialize_struct_variant(
$fields_stmt
visitor.visit_struct(FIELDS, $visitor_expr)
})
}))
}
fn deserialize_field_visitor(
@@ -920,19 +930,19 @@ fn deserialize_struct_visitor(
builder: &aster::AstBuilder,
struct_path: ast::Path,
fields: &[ast::StructField],
) -> (Vec<P<ast::Item>>, P<ast::Stmt>, P<ast::Expr>) {
) -> Result<(Vec<P<ast::Item>>, P<ast::Stmt>, P<ast::Expr>), ()> {
let field_visitor = deserialize_field_visitor(
cx,
builder,
field::struct_field_attrs(cx, builder, fields),
try!(field::struct_field_attrs(cx, builder, fields)),
);
let visit_map_expr = deserialize_map(
let visit_map_expr = try!(deserialize_map(
cx,
builder,
struct_path,
fields,
);
));
let fields_expr = builder.expr().addr_of().slice()
.with_exprs(
@@ -940,7 +950,9 @@ fn deserialize_struct_visitor(
.map(|field| {
match field.node.kind {
ast::NamedField(name, _) => builder.expr().str(name),
ast::UnnamedField(_) => panic!("struct contains unnamed fields"),
ast::UnnamedField(_) => {
cx.span_bug(field.span, "struct contains unnamed fields")
}
}
})
)
@@ -950,7 +962,7 @@ fn deserialize_struct_visitor(
const FIELDS: &'static [&'static str] = $fields_expr;
).unwrap();
(field_visitor, fields_stmt, visit_map_expr)
Ok((field_visitor, fields_stmt, visit_map_expr))
}
fn deserialize_map(
@@ -958,7 +970,7 @@ fn deserialize_map(
builder: &aster::AstBuilder,
struct_path: ast::Path,
fields: &[ast::StructField],
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
// Create the field names for the fields.
let field_names: Vec<ast::Ident> = (0 .. fields.len())
.map(|i| builder.id(format!("__field{}", i)))
@@ -980,8 +992,10 @@ fn deserialize_map(
})
.collect();
let field_attrs = try!(field::struct_field_attrs(cx, builder, fields));
let extract_values: Vec<P<ast::Stmt>> = field_names.iter()
.zip(field::struct_field_attrs(cx, builder, fields).iter())
.zip(field_attrs.iter())
.map(|(field_name, field_attr)| {
let missing_expr = if field_attr.use_default() {
quote_expr!(cx, ::std::default::Default::default())
@@ -1024,7 +1038,9 @@ fn deserialize_map(
(
match field.node.kind {
ast::NamedField(name, _) => name.clone(),
ast::UnnamedField(_) => panic!("struct contains unnamed fields"),
ast::UnnamedField(_) => {
cx.span_bug(field.span, "struct contains unnamed fields")
}
},
builder.expr().id(field_name),
)
@@ -1032,7 +1048,7 @@ fn deserialize_map(
)
.build();
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$let_values
while let Some(key) = try!(visitor.visit_key()) {
@@ -1046,5 +1062,5 @@ fn deserialize_map(
try!(visitor.end());
Ok($result)
})
}))
}
+21 -8
View File
@@ -2,16 +2,29 @@ use syntax::ast;
use syntax::ext::base::ExtCtxt;
use aster;
use attr::{FieldAttrs, FieldAttrsBuilder};
use attr;
pub fn struct_field_attrs(
_cx: &ExtCtxt,
cx: &ExtCtxt,
builder: &aster::AstBuilder,
fields: &[ast::StructField],
) -> Vec<FieldAttrs> {
fields.iter()
.map(|field| {
FieldAttrsBuilder::new(builder).field(field).build()
})
.collect()
) -> Result<Vec<attr::FieldAttrs>, ()> {
let mut attrs = vec![];
for field in fields {
let builder = attr::FieldAttrsBuilder::new(cx, builder);
let builder = try!(builder.field(field));
let attr = builder.build();
attrs.push(attr);
}
Ok(attrs)
}
pub fn container_attrs(
cx: &ExtCtxt,
container: &ast::Item,
) -> Result<attr::ContainerAttrs, ()> {
let builder = attr::ContainerAttrsBuilder::new(cx);
let builder = try!(builder.attrs(container.attrs()));
Ok(builder.build())
}
+7
View File
@@ -1,3 +1,5 @@
#![cfg_attr(feature = "nightly", plugin(clippy))]
#![cfg_attr(feature = "nightly", allow(used_underscore_binding))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(quasi_macros))]
@@ -16,6 +18,9 @@ extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc_plugin;
#[cfg(not(feature = "with-syntex"))]
use syntax::feature_gate::AttributeType;
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
@@ -70,4 +75,6 @@ pub fn register(reg: &mut rustc_plugin::Registry) {
syntax::parse::token::intern("derive_Deserialize"),
syntax::ext::base::MultiDecorator(
Box::new(de::expand_derive_deserialize)));
reg.register_attribute("serde".to_owned(), AttributeType::Normal);
}
+93 -67
View File
@@ -11,7 +11,7 @@ use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use field::struct_field_attrs;
use field;
pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
@@ -25,7 +25,7 @@ pub fn expand_derive_serialize(
_ => {
cx.span_err(
meta_item.span,
"`derive` may only be applied to structs and enums");
"`#[derive(Serialize)]` may only be applied to structs and enums");
return;
}
};
@@ -35,7 +35,12 @@ pub fn expand_derive_serialize(
let generics = match item.node {
ast::ItemStruct(_, ref generics) => generics,
ast::ItemEnum(_, ref generics) => generics,
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Serialize)]")
_ => {
cx.span_err(
meta_item.span,
"`#[derive(Serialize)]` may only be applied to structs and enums");
return;
}
};
let impl_generics = builder.from_generics(generics.clone())
@@ -48,13 +53,13 @@ pub fn expand_derive_serialize(
.segment(item.ident).with_generics(impl_generics.clone()).build()
.build();
let body = serialize_body(
cx,
&builder,
&item,
&impl_generics,
ty.clone(),
);
let body = match serialize_body(cx, &builder, &item, &impl_generics, ty.clone()) {
Ok(body) => body,
Err(()) => {
// An error occured, but it should have been reported already.
return;
}
};
let where_clause = &impl_generics.where_clause;
@@ -77,7 +82,11 @@ fn serialize_body(
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
// Note: While we don't have any container attributes, we still want to try to
// parse them so we can report a proper error if we get passed an unknown attribute.
let _ = try!(field::container_attrs(cx, item));
match item.node {
ast::ItemStruct(ref variant_data, _) => {
serialize_item_struct(
@@ -86,6 +95,7 @@ fn serialize_body(
item,
impl_generics,
ty,
item.span,
variant_data,
)
}
@@ -99,7 +109,10 @@ fn serialize_body(
enum_def,
)
}
_ => cx.bug("expected ItemStruct or ItemEnum in #[derive(Serialize)]")
_ => {
cx.span_bug(item.span,
"expected ItemStruct or ItemEnum in #[derive(Serialize)]");
}
}
}
@@ -109,8 +122,9 @@ fn serialize_item_struct(
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
span: Span,
variant_data: &ast::VariantData,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
match *variant_data {
ast::VariantData::Unit(_) => {
serialize_unit_struct(
@@ -128,7 +142,7 @@ fn serialize_item_struct(
}
ast::VariantData::Tuple(ref fields, _) => {
if fields.iter().any(|field| !field.node.kind.is_unnamed()) {
cx.bug("tuple struct has named fields")
cx.span_bug(span, "tuple struct has named fields")
}
serialize_tuple_struct(
@@ -142,7 +156,7 @@ fn serialize_item_struct(
}
ast::VariantData::Struct(ref fields, _) => {
if fields.iter().any(|field| field.node.kind.is_unnamed()) {
cx.bug("struct has unnamed fields")
cx.span_bug(span, "struct has unnamed fields")
}
serialize_struct(
@@ -161,20 +175,24 @@ fn serialize_unit_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, serializer.visit_unit_struct($type_name))
Ok(quote_expr!(cx,
serializer.visit_unit_struct($type_name)
))
}
fn serialize_newtype_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
type_ident: Ident
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, serializer.visit_newtype_struct($type_name, &self.0))
Ok(quote_expr!(cx,
serializer.visit_newtype_struct($type_name, &self.0)
))
}
fn serialize_tuple_struct(
@@ -184,7 +202,7 @@ fn serialize_tuple_struct(
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
@@ -199,7 +217,7 @@ fn serialize_tuple_struct(
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_tuple_struct($type_name, Visitor {
@@ -207,7 +225,7 @@ fn serialize_tuple_struct(
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$ty>,
})
})
}))
}
fn serialize_struct(
@@ -217,8 +235,13 @@ fn serialize_struct(
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[ast::StructField],
) -> P<ast::Expr> {
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
) -> Result<P<ast::Expr>, ()> {
let value_exprs = fields.iter().map(|field| {
let name = field.node.ident().expect("struct has unnamed field");
quote_expr!(cx, &self.value.$name)
});
let (visitor_struct, visitor_impl) = try!(serialize_struct_visitor(
cx,
builder,
ty.clone(),
@@ -228,15 +251,12 @@ fn serialize_struct(
.build_ty(ty.clone()),
fields,
impl_generics,
fields.iter().map(|field| {
let name = field.node.ident().expect("struct has unnamed field");
quote_expr!(cx, &self.value.$name)
})
);
value_exprs,
));
let type_name = builder.expr().str(type_ident);
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_struct($type_name, Visitor {
@@ -244,7 +264,7 @@ fn serialize_struct(
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$ty>,
})
})
}))
}
fn serialize_item_enum(
@@ -254,27 +274,28 @@ fn serialize_item_enum(
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
enum_def: &ast::EnumDef,
) -> P<ast::Expr> {
let arms: Vec<ast::Arm> = enum_def.variants.iter()
.enumerate()
.map(|(variant_index, variant)| {
serialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
variant_index,
)
})
.collect();
) -> Result<P<ast::Expr>, ()> {
let mut arms = vec![];
quote_expr!(cx,
for (variant_index, variant) in enum_def.variants.iter().enumerate() {
let arm = try!(serialize_variant(
cx,
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
variant_index,
));
arms.push(arm);
}
Ok(quote_expr!(cx,
match *self {
$arms
}
)
))
}
fn serialize_variant(
@@ -285,7 +306,7 @@ fn serialize_variant(
ty: P<ast::Ty>,
variant: &ast::Variant,
variant_index: usize,
) -> ast::Arm {
) -> Result<ast::Arm, ()> {
let type_name = builder.expr().str(type_ident);
let variant_ident = variant.node.name;
let variant_name = builder.expr().str(variant_ident);
@@ -296,7 +317,7 @@ fn serialize_variant(
.id(type_ident).id(variant_ident).build()
.build();
quote_arm!(cx,
Ok(quote_arm!(cx,
$pat => {
::serde::ser::Serializer::visit_unit_variant(
serializer,
@@ -305,7 +326,7 @@ fn serialize_variant(
$variant_name,
)
}
)
))
},
ast::VariantData::Tuple(ref fields, _) if fields.len() == 1 => {
let field = builder.id("__simple_value");
@@ -314,7 +335,8 @@ fn serialize_variant(
.id(type_ident).id(variant_ident).build()
.with_pats(Some(field).into_iter())
.build();
quote_arm!(cx,
Ok(quote_arm!(cx,
$pat => {
::serde::ser::Serializer::visit_newtype_variant(
serializer,
@@ -324,7 +346,7 @@ fn serialize_variant(
__simple_value,
)
}
)
))
},
ast::VariantData::Tuple(ref fields, _) => {
let field_names: Vec<ast::Ident> = (0 .. fields.len())
@@ -351,7 +373,9 @@ fn serialize_variant(
field_names,
);
quote_arm!(cx, $pat => { $expr })
Ok(quote_arm!(cx,
$pat => { $expr }
))
}
ast::VariantData::Struct(ref fields, _) => {
let field_names: Vec<_> = (0 .. fields.len())
@@ -367,7 +391,7 @@ fn serialize_variant(
let name = match field.node.kind {
ast::NamedField(name, _) => name,
ast::UnnamedField(_) => {
cx.bug("struct variant has unnamed fields")
cx.span_bug(field.span, "struct variant has unnamed fields")
}
};
@@ -376,7 +400,7 @@ fn serialize_variant(
)
.build();
let expr = serialize_struct_variant(
let expr = try!(serialize_struct_variant(
cx,
builder,
type_name,
@@ -386,9 +410,11 @@ fn serialize_variant(
ty,
fields,
field_names,
);
));
quote_arm!(cx, $pat => { $expr })
Ok(quote_arm!(cx,
$pat => { $expr }
))
}
}
}
@@ -453,7 +479,7 @@ fn serialize_struct_variant(
structure_ty: P<ast::Ty>,
fields: &[ast::StructField],
field_names: Vec<Ident>,
) -> P<ast::Expr> {
) -> Result<P<ast::Expr>, ()> {
let value_ty = builder.ty().tuple()
.with_tys(
fields.iter().map(|field| {
@@ -473,7 +499,7 @@ fn serialize_struct_variant(
)
.build();
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
let (visitor_struct, visitor_impl) = try!(serialize_struct_visitor(
cx,
builder,
structure_ty.clone(),
@@ -485,9 +511,9 @@ fn serialize_struct_variant(
.tup_field(i)
.field("value").self_()
})
);
));
quote_expr!(cx, {
Ok(quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_struct_variant($type_name, $variant_index, $variant_name, Visitor {
@@ -495,7 +521,7 @@ fn serialize_struct_variant(
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
})
})
}))
}
fn serialize_tuple_struct_visitor(
@@ -573,12 +599,12 @@ fn serialize_struct_visitor<I>(
fields: &[ast::StructField],
generics: &ast::Generics,
value_exprs: I,
) -> (P<ast::Item>, P<ast::Item>)
) -> Result<(P<ast::Item>, P<ast::Item>), ()>
where I: Iterator<Item=P<ast::Expr>>,
{
let value_exprs = value_exprs.collect::<Vec<_>>();
let field_attrs = struct_field_attrs(cx, builder, fields);
let field_attrs = try!(field::struct_field_attrs(cx, builder, fields));
let arms: Vec<ast::Arm> = field_attrs.iter()
.zip(value_exprs.iter())
@@ -641,7 +667,7 @@ fn serialize_struct_visitor<I>(
})
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
(
Ok((
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
@@ -673,5 +699,5 @@ fn serialize_struct_visitor<I>(
}
}
).unwrap(),
)
))
}
+5 -3
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_macros"
version = "0.6.6"
version = "0.6.11"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
@@ -13,9 +13,11 @@ name = "serde_macros"
plugin = true
[dependencies]
serde_codegen = { version = "*", path = "../serde_codegen", default-features = false, features = ["nightly"] }
clippy = "^0.0.37"
serde_codegen = { version = "^0.6.10", path = "../serde_codegen", default-features = false, features = ["nightly"] }
[dev-dependencies]
compiletest_rs = "^0.0.11"
num = "^0.1.27"
rustc-serialize = "^0.3.16"
serde = { version = "*", path = "../serde", features = ["nightly", "num-impls"] }
serde = { version = "^0.6.10", path = "../serde", features = ["nightly", "num-impls"] }
+1
View File
@@ -1,4 +1,5 @@
#![feature(custom_attribute, custom_derive, plugin, test)]
#![plugin(clippy)]
#![plugin(serde_macros)]
extern crate num;
+2 -1
View File
@@ -1,4 +1,5 @@
#![feature(plugin_registrar, rustc_private)]
#![feature(plugin, plugin_registrar, rustc_private)]
#![plugin(clippy)]
extern crate serde_codegen;
extern crate rustc_plugin;
@@ -0,0 +1,30 @@
#![feature(custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
#[derive(Serialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct Foo {
x: u32,
}
#[derive(Deserialize)]
#[serde(abc="xyz")] //~ unknown serde container attribute `abc = "xyz"`
struct Foo {
x: u32,
}
#[derive(Serialize)]
struct Foo {
#[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
x: u32,
}
#[derive(Deserialize)]
struct Foo {
#[serde(abc="xyz")] //~ unknown serde field attribute `abc = "xyz"`
x: u32,
}
fn main() { }
+25
View File
@@ -0,0 +1,25 @@
extern crate compiletest_rs as compiletest;
use std::path::PathBuf;
use std::env::var;
fn run_mode(mode: &'static str) {
let mut config = compiletest::default_config();
let cfg_mode = mode.parse().ok().expect("Invalid mode");
config.target_rustcflags = Some("-L target/debug/ -L target/debug/deps/".to_owned());
if let Ok(name) = var::<&str>("TESTNAME") {
let s : String = name.to_owned();
config.filter = Some(s)
}
config.mode = cfg_mode;
config.src_base = PathBuf::from(format!("tests/{}", mode));
compiletest::run_tests(&config);
}
#[test]
fn compile_test() {
run_mode("compile-fail");
}
+2
View File
@@ -6,3 +6,5 @@ extern crate serde;
extern crate test;
include!("../../serde_tests/tests/test.rs.in");
mod compile_tests;
+10 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_tests"
version = "0.6.2"
version = "0.6.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -10,16 +10,22 @@ readme = "README.md"
keywords = ["serialization"]
build = "build.rs"
[features]
nightly = ["clippy", "serde/nightly"]
[build-dependencies]
syntex = { version = "^0.25.0" }
syntex_syntax = { version = "^0.25.0" }
syntex = { version = "^0.26.0" }
syntex_syntax = { version = "^0.26.0" }
serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-syntex"] }
[dev-dependencies]
num = "^0.1.27"
rustc-serialize = "^0.3.16"
serde = { version = "*", path = "../serde", features = ["num-impls"] }
syntex = "^0.25.0"
syntex = "^0.26.0"
[dependencies]
clippy = { version = "^0.0.37", optional = true }
[[test]]
name = "test"
+2
View File
@@ -1,4 +1,6 @@
#![feature(test)]
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
extern crate num;
extern crate rustc_serialize;
+2 -2
View File
@@ -415,7 +415,7 @@ fn bench_decoder_dog(b: &mut Bencher) {
#[bench]
fn bench_decoder_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Frog("Henry".to_string(), 349);
let animal = Animal::Frog("Henry".to_owned(), 349);
let mut d = decoder::AnimalDecoder::new(animal.clone());
let value: Animal = Decodable::decode(&mut d).unwrap();
@@ -439,7 +439,7 @@ fn bench_deserializer_dog(b: &mut Bencher) {
#[bench]
fn bench_deserializer_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Animal::Frog("Henry".to_string(), 349);
let animal = Animal::Frog("Henry".to_owned(), 349);
let mut d = deserializer::AnimalDeserializer::new(animal.clone());
let value: Animal = Deserialize::deserialize(&mut d).unwrap();
+11 -11
View File
@@ -614,7 +614,7 @@ mod deserializer {
fn bench_decoder_0_0(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
map.insert("abc".to_string(), Some('c'));
map.insert("abc".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(),
@@ -653,11 +653,11 @@ fn bench_decoder_1_0(b: &mut Bencher) {
fn bench_decoder_1_5(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
map.insert("1".to_string(), Some('a'));
map.insert("2".to_string(), None);
map.insert("3".to_string(), Some('b'));
map.insert("4".to_string(), None);
map.insert("5".to_string(), Some('c'));
map.insert("1".to_owned(), Some('a'));
map.insert("2".to_owned(), None);
map.insert("3".to_owned(), Some('b'));
map.insert("4".to_owned(), None);
map.insert("5".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(
@@ -716,11 +716,11 @@ fn bench_deserializer_1_0(b: &mut Bencher) {
fn bench_deserializer_1_5(b: &mut Bencher) {
b.iter(|| {
let mut map = HashMap::new();
map.insert("1".to_string(), Some('a'));
map.insert("2".to_string(), None);
map.insert("3".to_string(), Some('b'));
map.insert("4".to_string(), None);
map.insert("5".to_string(), Some('c'));
map.insert("1".to_owned(), Some('a'));
map.insert("2".to_owned(), None);
map.insert("3".to_owned(), Some('b'));
map.insert("4".to_owned(), None);
map.insert("5".to_owned(), Some('c'));
let outer = Outer {
inner: vec!(
+3
View File
@@ -1,3 +1,6 @@
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
extern crate num;
extern crate serde;
+4 -4
View File
@@ -95,12 +95,12 @@ declare_tests! {
test_char {
'a' => vec![Token::Char('a')],
'a' => vec![Token::Str("a")],
'a' => vec![Token::String("a".to_string())],
'a' => vec![Token::String("a".to_owned())],
}
test_string {
"abc".to_string() => vec![Token::Str("abc")],
"abc".to_string() => vec![Token::String("abc".to_string())],
"a".to_string() => vec![Token::Char('a')],
"abc".to_owned() => vec![Token::Str("abc")],
"abc".to_owned() => vec![Token::String("abc".to_owned())],
"a".to_owned() => vec![Token::Char('a')],
}
test_option {
None::<i32> => vec![Token::Unit],
+1 -1
View File
@@ -63,7 +63,7 @@ declare_ser_tests! {
}
test_str {
"abc" => &[Token::Str("abc")],
"abc".to_string() => &[Token::Str("abc")],
"abc".to_owned() => &[Token::Str("abc")],
}
test_option {
None::<i32> => &[Token::Option(false)],
+1 -2
View File
@@ -325,7 +325,7 @@ impl de::Error for Error {
fn end_of_stream() -> Error { Error::EndOfStreamError }
fn unknown_field(field: &str) -> Error {
Error::UnknownFieldError(field.to_string())
Error::UnknownFieldError(field.to_owned())
}
fn missing_field(field: &'static str) -> Error {
@@ -379,7 +379,6 @@ impl<I> de::Deserializer for Deserializer<I>
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
println!("visit {:?}", self.tokens.peek());
match self.tokens.next() {
Some(Token::Bool(v)) => visitor.visit_bool(v),
Some(Token::Isize(v)) => visitor.visit_isize(v),