Compare commits

...

51 Commits

Author SHA1 Message Date
David Tolnay 7cc36a9cd3 Release 0.8.8 2016-09-08 08:34:20 -07:00
Homu d343017f47 Auto merge of #546 - serde-rs:qual, r=oli-obk
Result needs to be fully qualified

Without this:

```
error[E0244]: wrong number of type arguments
  --> src/api/accounts.rs:19:10
   |
19 | #[derive(Serialize, Deserialize, Debug)]
   |          ^^^^^^^^^^ expected 1 type arguments, found 2
```
2016-09-08 18:05:36 +09:00
David Tolnay 2212bfbf2c Result needs to be fully qualified
Without this:

```
error[E0244]: wrong number of type arguments
  --> src/api/accounts.rs:19:10
   |
19 | #[derive(Serialize, Deserialize, Debug)]
   |          ^^^^^^^^^^ expected 1 type arguments, found 2
```
2016-09-07 16:37:26 -07:00
David Tolnay e85ca8411e Release 0.8.7 2016-09-05 09:39:27 -07:00
Homu 1ff2053262 Auto merge of #536 - serde-rs:mutempty, r=oli-obk
Fix "variable does not need to be mutable" warning

Fixes #534.

cc @EliDupree
2016-09-06 01:10:43 +09:00
Homu bf779ea343 Auto merge of #525 - serde-rs:forward, r=oli-obk
Expose forward_to_deserialize macro

Fixes #522.

```rust
impl Deserializer for MyDeserializer {
    fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
        where V: Visitor
    {
        /* ... */
    }

    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
    }
}
```

cc @nox
2016-09-06 00:37:18 +09:00
David Tolnay 8fe66c7f2a Merge pull request #520 from serde-rs/bytes
Add constructors for Bytes and ByteBuf
2016-09-05 08:37:10 -07:00
David Tolnay e03dedabe4 Use peekable iterator to check for nonzero serialized fields 2016-09-05 08:22:17 -07:00
David Tolnay 08bc2d2e76 Use constructors to create Bytes and ByteBuf 2016-09-05 08:09:23 -07:00
David Tolnay 35be61d85f Resolve merge conflict 2016-09-05 08:02:35 -07:00
David Tolnay 3692edfd08 Merge branch serde-rs/master into serde-rs/forward 2016-09-05 07:59:42 -07:00
Homu 5a258ade27 Auto merge of #527 - serde-rs:seqvisitor, r=oli-obk
Impl SeqVisitor for MapDeserializer

@nox is this what you were trying to implement?
2016-09-05 20:09:44 +09:00
Homu f3052c392e Auto merge of #538 - serde-rs:notfalse, r=oli-obk
Remove `if !false { ... }` from generated serialization code

I don't think this negatively affects maintainability of the code in serde_codegen and I think there is some value in keeping our generated code relatively clear so that people can use it as a template when implementing Serialize manually with minor modifications.
2016-09-05 19:52:43 +09:00
David Tolnay d1ce4d62c9 Change to expression so that syntex keeps the semicolon 2016-09-02 18:07:26 -07:00
David Tolnay 869ebd9e4e Remove if !false { ... } from generated serialization code 2016-09-02 17:22:58 -07:00
David Tolnay 14446af537 Fix "variable does not need to be mutable" warning 2016-09-02 11:42:33 -07:00
David Tolnay 248d937f9a Release 0.8.6 2016-09-01 22:06:27 -07:00
David Tolnay ffa2f80186 Merge pull request #530 from serde-rs/derive
Macros 1.1
2016-09-01 21:59:32 -07:00
David Tolnay ac1128a647 Update serde_derive to 0.8.5 2016-09-01 21:28:58 -07:00
David Tolnay 88d845c4d1 Include! test suite for serde_derive 2016-09-01 21:28:40 -07:00
David Tolnay 87a402a751 Remove rustc_macro test crate 2016-09-01 11:17:35 -07:00
David Tolnay cdb0e6c899 Remove build script in favor of rust-lang/cargo#3064 2016-08-31 21:05:40 -07:00
David Tolnay 54cee86fd3 Bump to 0.8.5 2016-08-31 20:14:44 -07:00
David Tolnay 178edd1abc Merge branch origin/master into origin/derive 2016-08-31 20:12:46 -07:00
David Tolnay 4bb9279074 Bump syntex to 0.43 2016-08-31 12:53:27 -07:00
David Tolnay 3c45e5c7a5 Next iteration 2016-08-30 23:55:08 -07:00
David Tolnay d36f28971c Support no_std in forward_to_deserialize macro 2016-08-29 00:27:11 -07:00
David Tolnay d914fdf67b Macros 1.1 2016-08-28 22:21:25 -07:00
David Tolnay 7014c105b4 Remove coverage shield 2016-08-28 08:39:53 -07:00
David Tolnay f3d566af09 Remove clippy shield 2016-08-28 08:37:55 -07:00
David Tolnay 278e8eb720 Add deserialize_seq methods to MapDeserializer 2016-08-25 10:45:25 -04:00
David Tolnay e9b04de9a5 Impl SeqVisitor for MapDeserializer 2016-08-25 10:12:23 -04:00
David Tolnay 2a2891d54b Expose forward_to_deserialize macro 2016-08-24 00:16:22 -04:00
David Tolnay 123e040189 Merge pull request #524 from serde-rs/skeptic
Remove skeptic
2016-08-23 22:17:13 -04:00
David Tolnay 6f0f273d9c Remove skeptic 2016-08-23 22:04:50 -04:00
David Tolnay fb7ba225d1 Add constructors for Bytes and ByteBuf
This commit adds `Bytes::new(&[u8])` and `ByteBuf::from<T: Into<Vec<u8>>>(T)`.
2016-08-23 16:24:00 -04:00
David Tolnay d690ffda8d Release 0.8.4 2016-08-22 11:37:53 -04:00
David Tolnay 18a775277f Merge pull request #514 from nox/maps
Introduce MapDeserializer::unbounded (fixes #512)
2016-08-22 09:05:50 -04:00
Anthony Ramine fbb250766d Introduce MapDeserializer::unbounded (fixes #512) 2016-08-22 09:11:10 +02:00
David Tolnay 71116b860a Merge pull request #513 from nox/cow
Implement ValueDeserializer for Cow<str>
2016-08-21 14:07:56 -04:00
Anthony Ramine ce3f134145 Implement ValueDeserializer for Cow<str> 2016-08-21 19:52:13 +02:00
David Tolnay 80507d650c Merge pull request #511 from serde-rs/extra
Switch to syntex::with_extra_stack
2016-08-19 21:27:17 -04:00
David Tolnay 0ae61a3dd1 Switch to syntex::with_extra_stack 2016-08-19 21:09:55 -04:00
David Tolnay 5fb73073bd Release 0.8.3 2016-08-19 13:11:59 -04:00
David Tolnay 63d484d50c Merge pull request #510 from serde-rs/clippy
Re-enable clippy
2016-08-19 13:01:24 -04:00
David Tolnay f3f29f81bc Fix new lints 2016-08-19 12:46:45 -04:00
David Tolnay 621588b258 Revert "Disable clippy until Manishearth/rust-clippy#1174 is fixed"
This reverts commit 2bc1d62e50.
2016-08-19 11:47:31 -04:00
Homu 7aba920dec Auto merge of #509 - serde-rs:cow, r=oli-obk
Fix codegen with lifetimes but no type parameters

Fixes #507.
2016-08-20 00:16:54 +09:00
David Tolnay a732b9bad3 Fix codegen with lifetimes but no type parameters 2016-08-19 11:12:38 -04:00
Oliver Schneider 6723da67b3 Merge pull request #506 from serde-rs/https
HTTPS for serde.rs
2016-08-19 10:57:52 +02:00
David Tolnay 2d99a50c27 HTTPS for serde.rs 2016-08-18 17:08:05 -04:00
25 changed files with 785 additions and 451 deletions
+6 -6
View File
@@ -1,4 +1,4 @@
# Serde &emsp; [![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 &emsp; [![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.** **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
@@ -6,11 +6,11 @@
You may be looking for: You may be looking for:
- [An overview of Serde](http://serde.rs/) - [An overview of Serde](https://serde.rs/)
- [Data formats supported by Serde](http://serde.rs/#data-formats) - [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](http://serde.rs/codegen.html) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html)
- [Examples](http://serde.rs/examples.html) - [Examples](https://serde.rs/examples.html)
- [API documentation](http://docs.serde.rs/serde/) - [API documentation](https://docs.serde.rs/serde/)
## Serde in action ## Serde in action
+4 -3
View File
@@ -1,11 +1,12 @@
[package] [package]
name = "serde" name = "serde"
version = "0.8.2" version = "0.8.8"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "http://docs.serde.rs/serde/" documentation = "https://docs.serde.rs/serde/"
readme = "../README.md" readme = "../README.md"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
@@ -17,7 +18,7 @@ std = []
unstable = [] unstable = []
alloc = ["unstable"] alloc = ["unstable"]
collections = ["alloc"] collections = ["alloc"]
unstable-testing = ["unstable", "std"] unstable-testing = ["clippy", "unstable", "std"]
[dependencies] [dependencies]
clippy = { version = "^0.*", optional = true } clippy = { version = "^0.*", optional = true }
+22 -22
View File
@@ -19,6 +19,15 @@ pub struct Bytes<'a> {
bytes: &'a [u8], bytes: &'a [u8],
} }
impl<'a> Bytes<'a> {
/// Wrap an existing `&[u8]`.
pub fn new(bytes: &'a [u8]) -> Self {
Bytes {
bytes: bytes,
}
}
}
impl<'a> fmt::Debug for Bytes<'a> { impl<'a> fmt::Debug for Bytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\"")); try!(f.write_str("b\""));
@@ -31,18 +40,14 @@ impl<'a> fmt::Debug for Bytes<'a> {
impl<'a> From<&'a [u8]> for Bytes<'a> { impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self { fn from(bytes: &'a [u8]) -> Self {
Bytes { Bytes::new(bytes)
bytes: bytes,
}
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
impl<'a> From<&'a Vec<u8>> for Bytes<'a> { impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
fn from(bytes: &'a Vec<u8>) -> Self { fn from(bytes: &'a Vec<u8>) -> Self {
Bytes { Bytes::new(bytes)
bytes: bytes,
}
} }
} }
@@ -90,15 +95,18 @@ mod bytebuf {
impl ByteBuf { impl ByteBuf {
/// Construct a new, empty `ByteBuf`. /// Construct a new, empty `ByteBuf`.
pub fn new() -> Self { pub fn new() -> Self {
ByteBuf { ByteBuf::from(Vec::new())
bytes: Vec::new(),
}
} }
/// Construct a new, empty `ByteBuf` with the specified capacity. /// Construct a new, empty `ByteBuf` with the specified capacity.
pub fn with_capacity(cap: usize) -> Self { pub fn with_capacity(cap: usize) -> Self {
ByteBuf::from(Vec::with_capacity(cap))
}
/// Wrap existing bytes in a `ByteBuf`.
pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
ByteBuf { ByteBuf {
bytes: Vec::with_capacity(cap) bytes: bytes.into(),
} }
} }
} }
@@ -121,9 +129,7 @@ mod bytebuf {
impl From<Vec<u8>> for ByteBuf { impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self { fn from(bytes: Vec<u8>) -> Self {
ByteBuf { ByteBuf::from(bytes)
bytes: bytes,
}
} }
} }
@@ -179,9 +185,7 @@ mod bytebuf {
fn visit_unit<E>(&mut self) -> Result<ByteBuf, E> fn visit_unit<E>(&mut self) -> Result<ByteBuf, E>
where E: de::Error, where E: de::Error,
{ {
Ok(ByteBuf { Ok(ByteBuf::new())
bytes: Vec::new(),
})
} }
#[inline] #[inline]
@@ -197,9 +201,7 @@ mod bytebuf {
try!(visitor.end()); try!(visitor.end());
Ok(ByteBuf { Ok(ByteBuf::from(values))
bytes: values,
})
} }
#[inline] #[inline]
@@ -213,9 +215,7 @@ mod bytebuf {
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E> fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error, where E: de::Error,
{ {
Ok(ByteBuf { Ok(ByteBuf::from(v))
bytes: v,
})
} }
} }
-65
View File
@@ -11,71 +11,6 @@ use collections::{String, Vec};
use core::fmt; use core::fmt;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// Macro helper to not have to re-implement all the defaulted methods.
/// Every given method ignores all arguments and forwards to `deserialize`.
/// Note that `deserialize_enum` simply returns an `Error::invalid_type`.
macro_rules! de_forward_to_deserialize {
($($func:ident),*) => {
$(de_forward_to_deserialize!{func: $func})*
};
(func: deserialize_unit_struct) => {
de_forward_to_deserialize!{named: deserialize_unit_struct}
};
(func: deserialize_newtype_struct) => {
de_forward_to_deserialize!{named: deserialize_newtype_struct}
};
(func: deserialize_tuple) => {
de_forward_to_deserialize!{tup_fn: deserialize_tuple}
};
(func: deserialize_seq_fixed_size) => {
de_forward_to_deserialize!{tup_fn: deserialize_seq_fixed_size}
};
(func: deserialize_tuple_struct) => {
#[inline]
fn deserialize_tuple_struct<__V>(&mut self, _: &str, _: usize, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
(func: deserialize_struct) => {
#[inline]
fn deserialize_struct<__V>(&mut self, _: &str, _: &[&str], visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
(func: deserialize_enum) => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor {
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
(named: $func:ident) => {
#[inline]
fn $func<__V>(&mut self, _: &str, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
(tup_fn: $func: ident) => {
#[inline]
fn $func<__V>(&mut self, _: usize, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
(func: $func:ident) => {
#[inline]
fn $func<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
}
///////////////////////////////////////////////////////////////////////////////
// modules come after macros
pub mod impls; pub mod impls;
pub mod value; pub mod value;
+299 -160
View File
@@ -12,6 +12,8 @@ use std::collections::{
hash_set, hash_set,
}; };
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use std::vec; use std::vec;
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "collections", not(feature = "std")))]
@@ -24,6 +26,8 @@ use collections::{
btree_set, btree_set,
vec, vec,
}; };
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(all(feature = "unstable", feature = "collections"))]
use collections::borrow::ToOwned; use collections::borrow::ToOwned;
@@ -128,7 +132,7 @@ impl fmt::Display for Error {
write!(formatter, "Unknown variant: {}", variant) write!(formatter, "Unknown variant: {}", variant)
} }
Error::UnknownField(ref field) => write!(formatter, "Unknown field: {}", field), Error::UnknownField(ref field) => write!(formatter, "Unknown field: {}", field),
Error::MissingField(ref field) => write!(formatter, "Missing field: {}", field), Error::MissingField(field) => write!(formatter, "Missing field: {}", field),
} }
} }
} }
@@ -174,20 +178,10 @@ impl<E> de::Deserializer for UnitDeserializer<E>
{ {
type Error = E; type Error = E;
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
deserialize_f64, deserialize_f32, unit seq seq_fixed_size bytes map unit_struct newtype_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, tuple_struct struct struct_field tuple enum ignored_any
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
} }
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
@@ -225,21 +219,11 @@ macro_rules! primitive_deserializer {
{ {
type Error = E; type Error = E;
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str
deserialize_f64, deserialize_f32, string unit option seq seq_fixed_size bytes map unit_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, newtype_struct tuple_struct struct struct_field tuple enum
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, ignored_any
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<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
@@ -307,20 +291,10 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
visitor.visit(self) visitor.visit(self)
} }
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
deserialize_f64, deserialize_f32, unit option seq seq_fixed_size bytes map unit_struct newtype_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, tuple_struct struct struct_field tuple ignored_any
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_struct, deserialize_tuple_struct,
deserialize_option
} }
} }
@@ -404,20 +378,10 @@ impl<E> de::Deserializer for StringDeserializer<E>
visitor.visit(self) visitor.visit(self)
} }
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
deserialize_f64, deserialize_f32, unit option seq seq_fixed_size bytes map unit_struct newtype_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, tuple_struct struct struct_field tuple ignored_any
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_struct, deserialize_tuple_struct,
deserialize_option
} }
} }
@@ -463,6 +427,95 @@ impl<'a, E> de::VariantVisitor for StringDeserializer<E>
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `String`.
#[cfg(any(feature = "std", feature = "collections"))]
pub struct CowStrDeserializer<'a, E>(Option<Cow<'a, str>>, PhantomData<E>);
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
where E: de::Error,
{
type Deserializer = CowStrDeserializer<'a, E>;
fn into_deserializer(self) -> CowStrDeserializer<'a, E> {
CowStrDeserializer(Some(self), PhantomData)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
where E: de::Error,
{
type Error = E;
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
match self.0.take() {
Some(Cow::Borrowed(string)) => visitor.visit_str(string),
Some(Cow::Owned(string)) => visitor.visit_string(string),
None => Err(de::Error::end_of_stream()),
}
}
fn deserialize_enum<V>(&mut self,
_name: &str,
_variants: &'static [&'static str],
mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::EnumVisitor,
{
visitor.visit(self)
}
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 ignored_any
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> de::VariantVisitor for CowStrDeserializer<'a, E>
where E: de::Error,
{
type Error = E;
fn visit_variant<T>(&mut self) -> Result<T, Self::Error>
where T: de::Deserialize,
{
de::Deserialize::deserialize(self)
}
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize,
{
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new()));
Ok(value)
}
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::TupleVariant))
}
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::StructVariant))
}
}
///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a sequence. /// A helper deserializer that deserializes a sequence.
pub struct SeqDeserializer<I, E> { pub struct SeqDeserializer<I, E> {
iter: I, iter: I,
@@ -496,21 +549,10 @@ impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
visitor.visit_seq(self) visitor.visit_seq(self)
} }
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
deserialize_f64, deserialize_f32, unit option seq seq_fixed_size bytes map unit_struct newtype_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, tuple_struct struct struct_field tuple enum ignored_any
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
} }
} }
@@ -619,21 +661,10 @@ impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
visitor.visit_seq(&mut self.visitor) visitor.visit_seq(&mut self.visitor)
} }
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
deserialize_f64, deserialize_f32, unit option seq seq_fixed_size bytes map unit_struct newtype_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, tuple_struct struct struct_field tuple enum ignored_any
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
} }
} }
@@ -648,7 +679,7 @@ pub struct MapDeserializer<I, K, V, E>
{ {
iter: I, iter: I,
value: Option<V>, value: Option<V>,
len: usize, len: Option<usize>,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
@@ -658,15 +689,35 @@ impl<I, K, V, E> MapDeserializer<I, K, V, E>
V: ValueDeserializer<E>, V: ValueDeserializer<E>,
E: de::Error, E: de::Error,
{ {
/// Construct a new `MapDeserializer<I, K, V>`. /// Construct a new `MapDeserializer<I, K, V, E>` with a specific length.
pub fn new(iter: I, len: usize) -> Self { pub fn new(iter: I, len: usize) -> Self {
MapDeserializer { MapDeserializer {
iter: iter, iter: iter,
value: None, value: None,
len: len, len: Some(len),
marker: PhantomData, marker: PhantomData,
} }
} }
/// Construct a new `MapDeserializer<I, K, V, E>` that is not bounded
/// by a specific length and that delegates to `iter` for its size hint.
pub fn unbounded(iter: I) -> Self {
MapDeserializer {
iter: iter,
value: None,
len: None,
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> impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
@@ -683,21 +734,26 @@ impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
visitor.visit_map(self) visitor.visit_map(self)
} }
de_forward_to_deserialize!{ fn deserialize_seq<V_>(&mut self, mut visitor: V_) -> Result<V_::Value, Self::Error>
deserialize_bool, where V_: de::Visitor,
deserialize_f64, deserialize_f32, {
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, visitor.visit_seq(self)
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize, }
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any, fn deserialize_seq_fixed_size<V_>(&mut self, len: usize, mut visitor: V_) -> Result<V_::Value, Self::Error>
deserialize_bytes, where V_: de::Visitor,
deserialize_unit_struct, deserialize_unit, {
deserialize_seq, deserialize_seq_fixed_size, match self.len {
deserialize_map, deserialize_newtype_struct, deserialize_struct_field, Some(map_len) if map_len == len => visitor.visit_seq(self),
deserialize_tuple, Some(_) => Err(de::Error::invalid_length(len)),
deserialize_enum, None => visitor.visit_seq(self),
deserialize_struct, deserialize_tuple_struct, }
deserialize_option }
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option bytes map unit_struct newtype_struct tuple_struct struct
struct_field tuple enum ignored_any
} }
} }
@@ -712,12 +768,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> fn visit_key<T>(&mut self) -> Result<Option<T>, Self::Error>
where T: de::Deserialize, where T: de::Deserialize,
{ {
match self.iter.next() { match self.next() {
Some((key, value)) => { Some((key, value)) => {
self.len -= 1;
self.value = Some(value); self.value = Some(value);
let mut de = key.into_deserializer(); let mut de = key.into_deserializer();
Ok(Some(try!(de::Deserialize::deserialize(&mut de)))) de::Deserialize::deserialize(&mut de).map(Some)
} }
None => Ok(None), None => Ok(None),
} }
@@ -738,15 +793,133 @@ impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
} }
fn end(&mut self) -> Result<(), Self::Error> { fn end(&mut self) -> Result<(), Self::Error> {
if self.len == 0 { match self.len {
Ok(()) Some(len) if len > 0 => Err(de::Error::invalid_length(len)),
} else { _ => Ok(())
Err(de::Error::invalid_length(self.len))
} }
} }
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len)) self.len.map_or_else(
|| self.iter.size_hint(),
|len| (len, Some(len)))
}
}
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;
forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
unit option bytes map unit_struct newtype_struct tuple_struct struct
struct_field tuple enum ignored_any
}
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))
} }
} }
@@ -811,21 +984,10 @@ impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
visitor.visit_map(&mut self.visitor) visitor.visit_map(&mut self.visitor)
} }
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
deserialize_f64, deserialize_f32, unit option seq seq_fixed_size bytes map unit_struct newtype_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, tuple_struct struct struct_field tuple enum ignored_any
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
} }
} }
@@ -858,25 +1020,13 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
} }
} }
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
deserialize_f64, deserialize_f32, unit option seq seq_fixed_size bytes map unit_struct newtype_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, tuple_struct struct struct_field tuple enum ignored_any
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
} }
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
@@ -909,20 +1059,9 @@ impl<E> de::Deserializer for ByteBufDeserializer<E>
} }
} }
de_forward_to_deserialize!{ forward_to_deserialize! {
deserialize_bool, bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string
deserialize_f64, deserialize_f32, unit option seq seq_fixed_size bytes map unit_struct newtype_struct
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize, tuple_struct struct struct_field tuple enum ignored_any
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
} }
} }
+4 -1
View File
@@ -9,7 +9,7 @@
//! For a detailed tutorial on the different ways to use serde please check out the //! For a detailed tutorial on the different ways to use serde please check out the
//! [github repository](https://github.com/serde-rs/serde) //! [github repository](https://github.com/serde-rs/serde)
#![doc(html_root_url="http://docs.serde.rs")] #![doc(html_root_url="https://docs.serde.rs")]
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))] #![cfg_attr(feature = "unstable", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "alloc", feature(alloc))]
@@ -45,6 +45,9 @@ macro_rules! format {
($s:expr, $($rest:tt)*) => ($s) ($s:expr, $($rest:tt)*) => ($s)
} }
#[macro_use]
mod macros;
pub mod bytes; pub mod bytes;
pub mod de; pub mod de;
#[cfg(feature = "std")] #[cfg(feature = "std")]
+179
View File
@@ -0,0 +1,179 @@
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_method {
($func:ident($($arg:ty),*)) => {
#[inline]
fn $func<__V>(&mut self, $(_: $arg,)* visitor: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor
{
self.deserialize(visitor)
}
};
}
#[cfg(feature = "std")]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_enum {
() => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::std::result::Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor
{
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
}
#[cfg(not(feature = "std"))]
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_enum {
() => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> ::core::result::Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor
{
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
(bool) => {
forward_to_deserialize_method!{deserialize_bool()}
};
(usize) => {
forward_to_deserialize_method!{deserialize_usize()}
};
(u8) => {
forward_to_deserialize_method!{deserialize_u8()}
};
(u16) => {
forward_to_deserialize_method!{deserialize_u16()}
};
(u32) => {
forward_to_deserialize_method!{deserialize_u32()}
};
(u64) => {
forward_to_deserialize_method!{deserialize_u64()}
};
(isize) => {
forward_to_deserialize_method!{deserialize_isize()}
};
(i8) => {
forward_to_deserialize_method!{deserialize_i8()}
};
(i16) => {
forward_to_deserialize_method!{deserialize_i16()}
};
(i32) => {
forward_to_deserialize_method!{deserialize_i32()}
};
(i64) => {
forward_to_deserialize_method!{deserialize_i64()}
};
(f32) => {
forward_to_deserialize_method!{deserialize_f32()}
};
(f64) => {
forward_to_deserialize_method!{deserialize_f64()}
};
(char) => {
forward_to_deserialize_method!{deserialize_char()}
};
(str) => {
forward_to_deserialize_method!{deserialize_str()}
};
(string) => {
forward_to_deserialize_method!{deserialize_string()}
};
(unit) => {
forward_to_deserialize_method!{deserialize_unit()}
};
(option) => {
forward_to_deserialize_method!{deserialize_option()}
};
(seq) => {
forward_to_deserialize_method!{deserialize_seq()}
};
(seq_fixed_size) => {
forward_to_deserialize_method!{deserialize_seq_fixed_size(usize)}
};
(bytes) => {
forward_to_deserialize_method!{deserialize_bytes()}
};
(map) => {
forward_to_deserialize_method!{deserialize_map()}
};
(unit_struct) => {
forward_to_deserialize_method!{deserialize_unit_struct(&'static str)}
};
(newtype_struct) => {
forward_to_deserialize_method!{deserialize_newtype_struct(&'static str)}
};
(tuple_struct) => {
forward_to_deserialize_method!{deserialize_tuple_struct(&'static str, usize)}
};
(struct) => {
forward_to_deserialize_method!{deserialize_struct(&'static str, &'static [&'static str])}
};
(struct_field) => {
forward_to_deserialize_method!{deserialize_struct_field()}
};
(tuple) => {
forward_to_deserialize_method!{deserialize_tuple(usize)}
};
(ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()}
};
(enum) => {
forward_to_deserialize_enum!();
};
}
/// Helper to forward `Deserializer` methods to `Deserializer::deserialize`.
/// Every given method ignores all arguments and forwards to `deserialize`.
/// Note that `deserialize_enum` simply returns an `Error::invalid_type`; a
/// better approach is tracked in [serde-rs/serde#521][1].
///
/// ```rust,ignore
/// impl Deserializer for MyDeserializer {
/// fn deserialize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// {
/// /* ... */
/// }
///
/// 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
/// }
/// }
/// ```
///
/// [1]: https://github.com/serde-rs/serde/issues/521
#[macro_export]
macro_rules! forward_to_deserialize {
($($func:ident)*) => {
$(forward_to_deserialize_helper!{$func})*
};
}
+12 -11
View File
@@ -1,11 +1,12 @@
[package] [package]
name = "serde_codegen" name = "serde_codegen"
version = "0.8.2" version = "0.8.8"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework" description = "Macros to auto-generate implementations for the serde framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde" documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
build = "build.rs" build = "build.rs"
include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/lib.rs.in"] include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/lib.rs.in"]
@@ -13,7 +14,7 @@ include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/lib.rs.in"]
[features] [features]
default = ["with-syntex"] default = ["with-syntex"]
unstable = ["quasi_macros"] unstable = ["quasi_macros"]
unstable-testing = [] unstable-testing = ["clippy"]
with-syntex = [ with-syntex = [
"quasi/with-syntex", "quasi/with-syntex",
"quasi_codegen", "quasi_codegen",
@@ -24,14 +25,14 @@ with-syntex = [
] ]
[build-dependencies] [build-dependencies]
quasi_codegen = { version = "^0.17.0", optional = true } quasi_codegen = { version = "^0.19.0", optional = true }
syntex = { version = "^0.41.0", optional = true } syntex = { version = "^0.43.0", optional = true }
[dependencies] [dependencies]
aster = { version = "^0.24.0", default-features = false } aster = { version = "^0.26.0", default-features = false }
clippy = { version = "^0.*", optional = true } clippy = { version = "^0.*", optional = true }
quasi = { version = "^0.17.0", default-features = false } quasi = { version = "^0.19.0", default-features = false }
quasi_macros = { version = "^0.17.0", optional = true } quasi_macros = { version = "^0.19.0", optional = true }
serde_codegen_internals = { version = "=0.6.0", default-features = false, path = "../serde_codegen_internals" } serde_codegen_internals = { version = "=0.8.0", default-features = false, path = "../serde_codegen_internals" }
syntex = { version = "^0.41.0", optional = true } syntex = { version = "^0.43.0", optional = true }
syntex_syntax = { version = "^0.41.0", optional = true } syntex_syntax = { version = "^0.43.0", optional = true }
+1 -1
View File
@@ -192,7 +192,7 @@ fn deserialize_visitor(
builder: &aster::AstBuilder, builder: &aster::AstBuilder,
generics: &ast::Generics, generics: &ast::Generics,
) -> (P<ast::Item>, P<ast::Ty>, P<ast::Expr>) { ) -> (P<ast::Item>, P<ast::Ty>, P<ast::Expr>) {
if generics.ty_params.is_empty() { if generics.lifetimes.is_empty() && generics.ty_params.is_empty() {
( (
builder.item().unit_struct("__Visitor"), builder.item().unit_struct("__Visitor"),
builder.ty().id("__Visitor"), builder.ty().id("__Visitor"),
-36
View File
@@ -1,36 +0,0 @@
use std::env;
use std::ffi::OsStr;
use std::ops::Drop;
pub fn set_if_unset<K, V>(k: K, v: V) -> TmpEnv<K>
where K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
match env::var(&k) {
Ok(_) => TmpEnv::WasAlreadySet,
Err(_) => {
env::set_var(&k, v);
TmpEnv::WasNotSet { k: k }
}
}
}
#[must_use]
pub enum TmpEnv<K>
where K: AsRef<OsStr>,
{
WasAlreadySet,
WasNotSet {
k: K,
}
}
impl<K> Drop for TmpEnv<K>
where K: AsRef<OsStr>,
{
fn drop(&mut self) {
if let TmpEnv::WasNotSet { ref k } = *self {
env::remove_var(k);
}
}
}
+52 -43
View File
@@ -36,7 +36,56 @@ include!(concat!(env!("OUT_DIR"), "/lib.rs"));
include!("lib.rs.in"); include!("lib.rs.in");
#[cfg(feature = "with-syntex")] #[cfg(feature = "with-syntex")]
mod env; 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")] #[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error> pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
@@ -47,50 +96,10 @@ pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
let dst = dst.as_ref().to_owned(); let dst = dst.as_ref().to_owned();
let expand_thread = move || { let expand_thread = move || {
use syntax::{ast, fold}; syntex_registry().expand("", src, dst)
/// 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)
}; };
// 16 MB stack unless otherwise specified syntex::with_extra_stack(expand_thread)
let _tmp_env = env::set_if_unset("RUST_MIN_STACK", "16777216");
use std::thread;
thread::spawn(expand_thread).join().unwrap()
} }
#[cfg(not(feature = "with-syntex"))] #[cfg(not(feature = "with-syntex"))]
+54 -21
View File
@@ -4,6 +4,7 @@ use syntax::ast::{self, Ident, MetaItem};
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ptr::P; use syntax::ptr::P;
use syntax::tokenstream::TokenTree;
use bound; use bound;
use span; use span;
@@ -226,9 +227,10 @@ fn serialize_tuple_struct(
let type_name = name_expr(builder, item_attrs.name()); let type_name = name_expr(builder, item_attrs.name());
let len = serialize_stmts.len(); let len = serialize_stmts.len();
let let_mut = mut_if(cx, len > 0);
quote_block!(cx, { quote_block!(cx, {
let mut state = try!(_serializer.serialize_tuple_struct($type_name, $len)); let $let_mut state = try!(_serializer.serialize_tuple_struct($type_name, $len));
$serialize_stmts $serialize_stmts
_serializer.serialize_tuple_struct_end(state) _serializer.serialize_tuple_struct_end(state)
}).unwrap() }).unwrap()
@@ -253,8 +255,14 @@ fn serialize_struct(
); );
let type_name = name_expr(builder, item_attrs.name()); let type_name = name_expr(builder, item_attrs.name());
let len = fields.iter()
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing()) .filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(cx, serialized_fields.peek().is_some());
let len = serialized_fields
.map(|field| { .map(|field| {
let ident = field.ident.expect("struct has unnamed fields"); let ident = field.ident.expect("struct has unnamed fields");
let field_expr = quote_expr!(cx, &self.$ident); let field_expr = quote_expr!(cx, &self.$ident);
@@ -267,7 +275,7 @@ fn serialize_struct(
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
quote_block!(cx, { quote_block!(cx, {
let mut state = try!(_serializer.serialize_struct($type_name, $len)); let $let_mut state = try!(_serializer.serialize_struct($type_name, $len));
$serialize_fields $serialize_fields
_serializer.serialize_struct_end(state) _serializer.serialize_struct_end(state)
}).unwrap() }).unwrap()
@@ -458,9 +466,10 @@ fn serialize_tuple_variant(
); );
let len = serialize_stmts.len(); let len = serialize_stmts.len();
let let_mut = mut_if(cx, len > 0);
quote_block!(cx, { quote_block!(cx, {
let mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len)); let $let_mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len));
$serialize_stmts $serialize_stmts
_serializer.serialize_tuple_variant_end(state) _serializer.serialize_tuple_variant_end(state)
}).unwrap() }).unwrap()
@@ -488,8 +497,14 @@ fn serialize_struct_variant(
); );
let item_name = name_expr(builder, item_attrs.name()); let item_name = name_expr(builder, item_attrs.name());
let len = fields.iter()
let mut serialized_fields = fields.iter()
.filter(|&field| !field.attrs.skip_serializing()) .filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(cx, serialized_fields.peek().is_some());
let len = serialized_fields
.map(|field| { .map(|field| {
let ident = field.ident.expect("struct has unnamed fields"); let ident = field.ident.expect("struct has unnamed fields");
let field_expr = quote_expr!(cx, $ident); let field_expr = quote_expr!(cx, $ident);
@@ -502,7 +517,7 @@ fn serialize_struct_variant(
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr)); .fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
quote_block!(cx, { quote_block!(cx, {
let mut state = try!(_serializer.serialize_struct_variant( let $let_mut state = try!(_serializer.serialize_struct_variant(
$item_name, $item_name,
$variant_index, $variant_index,
$variant_name, $variant_name,
@@ -532,19 +547,21 @@ fn serialize_tuple_struct_visitor(
}; };
let skip = field.attrs.skip_serializing_if() let skip = field.attrs.skip_serializing_if()
.map(|path| quote_expr!(cx, $path($field_expr))) .map(|path| quote_expr!(cx, $path($field_expr)));
.unwrap_or(quote_expr!(cx, false));
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder, field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr); &structure_ty, generics, &field.ty, path, field_expr);
} }
quote_stmt!(cx, let ser = quote_expr!(cx,
if !$skip { try!(_serializer.$func(&mut state, $field_expr));
try!(_serializer.$func(&mut state, $field_expr)); );
}
).unwrap() match skip {
None => quote_stmt!(cx, $ser).unwrap(),
Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(),
}
}) })
.collect() .collect()
} }
@@ -571,19 +588,21 @@ fn serialize_struct_visitor(
let key_expr = name_expr(builder, field.attrs.name()); let key_expr = name_expr(builder, field.attrs.name());
let skip = field.attrs.skip_serializing_if() let skip = field.attrs.skip_serializing_if()
.map(|path| quote_expr!(cx, $path($field_expr))) .map(|path| quote_expr!(cx, $path($field_expr)));
.unwrap_or(quote_expr!(cx, false));
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder, field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr) &structure_ty, generics, &field.ty, path, field_expr)
} }
quote_stmt!(cx, let ser = quote_expr!(cx,
if !$skip { try!(_serializer.$func(&mut state, $key_expr, $field_expr));
try!(_serializer.$func(&mut state, $key_expr, $field_expr)); );
}
).unwrap() match skip {
None => quote_stmt!(cx, $ser).unwrap(),
Some(skip) => quote_stmt!(cx, if !$skip { $ser }).unwrap(),
}
}) })
.collect() .collect()
} }
@@ -617,7 +636,7 @@ fn wrap_serialize_with(
} }
impl $wrapper_generics _serde::ser::Serialize for $wrapper_ty $where_clause { impl $wrapper_generics _serde::ser::Serialize for $wrapper_ty $where_clause {
fn serialize<__S>(&self, __s: &mut __S) -> Result<(), __S::Error> fn serialize<__S>(&self, __s: &mut __S) -> ::std::result::Result<(), __S::Error>
where __S: _serde::ser::Serializer where __S: _serde::ser::Serializer
{ {
$path(self.value, __s) $path(self.value, __s)
@@ -637,3 +656,17 @@ fn name_expr(
) -> P<ast::Expr> { ) -> P<ast::Expr> {
builder.expr().str(name.serialize_name()) builder.expr().str(name.serialize_name())
} }
// Serialization of an empty struct results in code like:
//
// let mut state = try!(serializer.serialize_struct("S", 0));
// serializer.serialize_struct_end(state)
//
// where we want to omit the `mut` to avoid a warning.
fn mut_if(cx: &ExtCtxt, is_mut: bool) -> Vec<TokenTree> {
if is_mut {
quote_tokens!(cx, mut)
} else {
Vec::new()
}
}
+6 -5
View File
@@ -1,20 +1,21 @@
[package] [package]
name = "serde_codegen_internals" name = "serde_codegen_internals"
version = "0.6.0" version = "0.8.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable." description = "AST representation used by Serde codegen. Unstable."
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde" documentation = "https://docs.serde.rs/serde_codegen_internals/"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
[features] [features]
default = ["with-syntex"] default = ["with-syntex"]
unstable-testing = [] unstable-testing = ["clippy"]
with-syntex = ["syntex_syntax", "syntex_errors"] with-syntex = ["syntex_syntax", "syntex_errors"]
[dependencies] [dependencies]
clippy = { version = "^0.*", optional = true } clippy = { version = "^0.*", optional = true }
syntex_syntax = { version = "^0.41.0", optional = true } syntex_syntax = { version = "^0.43.0", optional = true }
syntex_errors = { version = "^0.41.0", optional = true } syntex_errors = { version = "^0.43.0", optional = true }
+46 -24
View File
@@ -8,8 +8,7 @@ use syntax::fold::Folder;
use syntax::parse::parser::{Parser, PathStyle}; use syntax::parse::parser::{Parser, PathStyle};
use syntax::parse::token::{self, InternedString}; use syntax::parse::token::{self, InternedString};
use syntax::parse; use syntax::parse;
use syntax::print::pprust::{lit_to_string, meta_item_to_string}; use syntax::print::pprust::{lit_to_string, meta_item_to_string, meta_list_item_to_string};
use syntax::ptr::P;
use syntax::tokenstream::{self, TokenTree}; use syntax::tokenstream::{self, TokenTree};
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints // This module handles parsing of `#[serde(...)]` attributes. The entrypoints
@@ -165,7 +164,7 @@ impl Item {
cx.span_err( cx.span_err(
meta_item.span, meta_item.span,
&format!("unknown serde container attribute `{}`", &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( cx.span_err(
meta_item.span, meta_item.span,
&format!("unknown serde variant attribute `{}`", &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( cx.span_err(
meta_item.span, meta_item.span,
&format!("unknown serde field attribute `{}`", &format!("unknown serde field attribute `{}`",
meta_item_to_string(meta_item))); meta_item_to_string(&meta_item)));
} }
} }
} }
@@ -449,12 +448,14 @@ impl Field {
} }
} }
type SerAndDe<T> = (Option<Spanned<T>>, Option<Spanned<T>>);
fn get_ser_and_de<T, F>( fn get_ser_and_de<T, F>(
cx: &ExtCtxt, cx: &ExtCtxt,
attribute: &'static str, attribute: &'static str,
items: &[P<ast::MetaItem>], items: &[ast::NestedMetaItem],
f: F f: F
) -> Result<(Option<Spanned<T>>, Option<Spanned<T>>), ()> ) -> Result<SerAndDe<T>, ()>
where F: Fn(&ExtCtxt, &str, &ast::Lit) -> Result<T, ()>, where F: Fn(&ExtCtxt, &str, &ast::Lit) -> Result<T, ()>,
{ {
let mut ser_item = Attr::none(cx, attribute); let mut ser_item = Attr::none(cx, attribute);
@@ -462,15 +463,29 @@ fn get_ser_and_de<T, F>(
for item in items { for item in items {
match item.node { match item.node {
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"serialize" => { ast::NestedMetaItemKind::MetaItem(ref meta_item) => {
if let Ok(v) = f(cx, name, lit) { match meta_item.node {
ser_item.set(item.span, v); 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" => { ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"deserialize" => {
if let Ok(v) = f(cx, name, lit) { if let Ok(v) = f(cx, name, lit) {
de_item.set(item.span, v); de_item.set(item.span, v);
}
}
_ => {
cx.span_err(
item.span,
&format!("unknown {} attribute `{}`",
attribute,
meta_item_to_string(meta_item)));
return Err(());
}
} }
} }
@@ -479,7 +494,7 @@ fn get_ser_and_de<T, F>(
item.span, item.span,
&format!("unknown {} attribute `{}`", &format!("unknown {} attribute `{}`",
attribute, attribute,
meta_item_to_string(item))); meta_list_item_to_string(item)));
return Err(()); return Err(());
} }
@@ -491,23 +506,30 @@ fn get_ser_and_de<T, F>(
fn get_renames( fn get_renames(
cx: &ExtCtxt, cx: &ExtCtxt,
items: &[P<ast::MetaItem>], items: &[ast::NestedMetaItem],
) -> Result<(Option<Spanned<InternedString>>, Option<Spanned<InternedString>>), ()> { ) -> Result<SerAndDe<InternedString>, ()> {
get_ser_and_de(cx, "rename", items, get_str_from_lit) get_ser_and_de(cx, "rename", items, get_str_from_lit)
} }
fn get_where_predicates( fn get_where_predicates(
cx: &ExtCtxt, cx: &ExtCtxt,
items: &[P<ast::MetaItem>], items: &[ast::NestedMetaItem],
) -> Result<(Option<Spanned<Vec<ast::WherePredicate>>>, Option<Spanned<Vec<ast::WherePredicate>>>), ()> { ) -> Result<SerAndDe<Vec<ast::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where) 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 { match attr.node.value.node {
ast::MetaItemKind::List(ref name, ref items) if name == &"serde" => { ast::MetaItemKind::List(ref name, ref items) if name == &"serde" => {
attr::mark_used(&attr); 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 _ => None
} }
@@ -570,7 +592,7 @@ fn get_str_from_lit(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result<Interned
name, name,
lit_to_string(lit))); lit_to_string(lit)));
return Err(()); Err(())
} }
} }
} }
+23
View File
@@ -0,0 +1,23 @@
[package]
name = "serde_derive"
version = "0.8.8"
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.8", path = "../serde_codegen" }
[dev-dependencies]
fnv = "1.0"
serde = { version = "0.8.8", path = "../serde" }
serde_test = { version = "0.8.8", path = "../serde_test" }
+21
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()
}
+8
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");
+8 -18
View File
@@ -1,14 +1,14 @@
[package] [package]
name = "serde_macros" name = "serde_macros"
version = "0.8.2" version = "0.8.8"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework" description = "Macros to auto-generate implementations for the serde framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://github.com/serde-rs/serde" documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs", "build.rs"] include = ["Cargo.toml", "src/**/*.rs"]
build = "build.rs"
[lib] [lib]
name = "serde_macros" name = "serde_macros"
@@ -16,36 +16,26 @@ plugin = true
[features] [features]
unstable-testing = [ unstable-testing = [
"skeptic", "clippy",
"serde_json",
"serde/unstable-testing", "serde/unstable-testing",
"serde_codegen/unstable-testing" "serde_codegen/unstable-testing"
] ]
[build-dependencies]
skeptic = { version = "^0.6.0", optional = true }
[dependencies] [dependencies]
clippy = { version = "^0.*", optional = true } clippy = { version = "^0.*", optional = true }
serde_codegen = { version = "=0.8.2", default-features = false, features = ["unstable"], path = "../serde_codegen" } serde_codegen = { version = "=0.8.8", default-features = false, features = ["unstable"], path = "../serde_codegen" }
skeptic = { version = "^0.6.0", optional = true }
serde_json = { version = "0.8.0", optional = true }
[dev-dependencies] [dev-dependencies]
compiletest_rs = "^0.2.0" compiletest_rs = "^0.2.0"
fnv = "1.0" fnv = "1.0"
rustc-serialize = "^0.3.16" rustc-serialize = "^0.3.16"
serde = { version = "0.8.2", path = "../serde" } serde = { version = "0.8.8", path = "../serde" }
serde_test = { version = "0.8.2", path = "../serde_test" } serde_test = { version = "0.8.8", path = "../serde_test" }
[[test]] [[test]]
name = "test" name = "test"
path = "tests/test.rs" path = "tests/test.rs"
[[test]]
name = "skeptic"
path = "tests/skeptic.rs"
[[bench]] [[bench]]
name = "bench" name = "bench"
path = "benches/bench.rs" path = "benches/bench.rs"
-18
View File
@@ -1,18 +0,0 @@
#[cfg(feature = "unstable-testing")]
mod inner {
extern crate skeptic;
pub fn main() {
println!("cargo:rerun-if-changed=../README.md");
skeptic::generate_doc_tests(&["../README.md"]);
}
}
#[cfg(not(feature = "unstable-testing"))]
mod inner {
pub fn main() {}
}
fn main() {
inner::main()
}
+1 -1
View File
@@ -1,5 +1,5 @@
#![feature(custom_derive, plugin)] #![feature(custom_derive, plugin)]
#![plugin(serde_macros)] #![plugin(serde_macros, clippy)]
#![deny(identity_op)] #![deny(identity_op)]
-3
View File
@@ -1,3 +0,0 @@
#![cfg(feature = "unstable-testing")]
include!(concat!(env!("OUT_DIR"), "/skeptic-tests.rs"));
-1
View File
@@ -6,4 +6,3 @@ extern crate test;
include!("../../testing/tests/test.rs.in"); include!("../../testing/tests/test.rs.in");
mod compile_tests; mod compile_tests;
mod skeptic;
+4 -3
View File
@@ -1,14 +1,15 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "0.8.2" version = "0.8.8"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "http://docs.serde.rs/serde/" documentation = "https://docs.serde.rs/serde_test/"
readme = "../README.md" readme = "../README.md"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
[dependencies] [dependencies]
serde = { version = "0.8.2", path = "../serde" } serde = { version = "0.8.8", path = "../serde" }
+4 -3
View File
@@ -1,17 +1,18 @@
[package] [package]
name = "serde_testing" name = "serde_testing"
version = "0.8.2" version = "0.8.8"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "http://docs.serde.rs/serde/" documentation = "https://docs.serde.rs/serde/"
readme = "README.md" readme = "README.md"
keywords = ["serialization"] keywords = ["serialization"]
build = "build.rs" build = "build.rs"
[features] [features]
unstable-testing = ["serde/unstable-testing", "serde_codegen/unstable-testing"] unstable-testing = ["clippy", "serde/unstable-testing", "serde_codegen/unstable-testing"]
[build-dependencies] [build-dependencies]
serde_codegen = { path = "../serde_codegen", features = ["with-syntex"] } serde_codegen = { path = "../serde_codegen", features = ["with-syntex"] }
+31 -6
View File
@@ -6,8 +6,14 @@ extern crate serde;
use self::serde::ser::{Serialize, Serializer}; use self::serde::ser::{Serialize, Serializer};
use self::serde::de::{Deserialize, Deserializer}; use self::serde::de::{Deserialize, Deserializer};
use std::borrow::Cow;
use std::marker::PhantomData; use std::marker::PhantomData;
// Try to trip up the generated code if it fails to use fully qualified paths.
#[allow(dead_code)]
struct Result;
use std::result::Result as StdResult;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
#[test] #[test]
@@ -177,6 +183,25 @@ fn test_gen() {
e: E, e: E,
} }
assert::<WithTraits2<X, X>>(); assert::<WithTraits2<X, X>>();
#[derive(Serialize, Deserialize)]
struct CowStr<'a>(Cow<'a, str>);
assert::<CowStr>();
#[derive(Serialize, Deserialize)]
#[serde(bound(deserialize = "T::Owned: Deserialize"))]
struct CowT<'a, T: ?Sized + 'a + ToOwned>(Cow<'a, T>);
assert::<CowT<str>>();
#[derive(Serialize, Deserialize)]
struct EmptyStruct {}
assert::<EmptyStruct>();
#[derive(Serialize, Deserialize)]
enum EmptyEnumVariant {
EmptyStruct {},
}
assert::<EmptyEnumVariant>();
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@@ -185,32 +210,32 @@ fn assert<T: Serialize + Deserialize>() {}
fn assert_ser<T: Serialize>() {} fn assert_ser<T: Serialize>() {}
trait SerializeWith { trait SerializeWith {
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> Result<(), S::Error>; fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> StdResult<(), S::Error>;
} }
trait DeserializeWith: Sized { trait DeserializeWith: Sized {
fn deserialize_with<D: Deserializer>(_: &mut D) -> Result<Self, D::Error>; fn deserialize_with<D: Deserializer>(_: &mut D) -> StdResult<Self, D::Error>;
} }
// Implements neither Serialize nor Deserialize // Implements neither Serialize nor Deserialize
struct X; struct X;
fn ser_x<S: Serializer>(_: &X, _: &mut S) -> Result<(), S::Error> { fn ser_x<S: Serializer>(_: &X, _: &mut S) -> StdResult<(), S::Error> {
unimplemented!() unimplemented!()
} }
fn de_x<D: Deserializer>(_: &mut D) -> Result<X, D::Error> { fn de_x<D: Deserializer>(_: &mut D) -> StdResult<X, D::Error> {
unimplemented!() unimplemented!()
} }
impl SerializeWith for X { impl SerializeWith for X {
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> Result<(), S::Error> { fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> StdResult<(), S::Error> {
unimplemented!() unimplemented!()
} }
} }
impl DeserializeWith for X { impl DeserializeWith for X {
fn deserialize_with<D: Deserializer>(_: &mut D) -> Result<Self, D::Error> { fn deserialize_with<D: Deserializer>(_: &mut D) -> StdResult<Self, D::Error> {
unimplemented!() unimplemented!()
} }
} }