Compare commits

...

59 Commits

Author SHA1 Message Date
David Tolnay 8624ca6f1d Release 0.9.3 2017-01-28 15:01:58 -08:00
David Tolnay a9b5cc4830 Fix invalid_length message for tuples and arrays 2017-01-28 15:00:54 -08:00
David Tolnay c31f76321c Release 0.9.2 2017-01-28 09:10:39 -08:00
David Tolnay f2402dcf52 Merge pull request #724 from serde-rs/entry
SerializeMap::serialize_entry
2017-01-28 09:08:51 -08:00
David Tolnay 361402ac4d SerializeMap::serialize_entry 2017-01-28 09:03:32 -08:00
David Tolnay c52e131a03 Replace deprecated MacroInput 2017-01-27 15:42:43 -08:00
David Tolnay c0a06bdc96 Update to syn 0.11 2017-01-27 15:25:42 -08:00
David Tolnay dd13fd3a34 Isolate the compiletest dependencies 2017-01-27 14:53:30 -08:00
David Tolnay 91f628727b Clean up the compile_tests script 2017-01-27 14:37:28 -08:00
David Tolnay 571a2e4e2d Indent the travis config to look like serde_json's 2017-01-27 14:17:07 -08:00
David Tolnay 7edcf6ec3b Simplify Error::custom example 2017-01-27 14:03:40 -08:00
David Tolnay e4f7d8513c Clean up clippy lints in codegen_internals 2017-01-25 21:22:15 -08:00
David Tolnay 09c69da909 Move test macro to where it is used 2017-01-25 20:55:55 -08:00
David Tolnay 7ee175f448 Remove duplicate btreemap macro 2017-01-25 20:54:31 -08:00
David Tolnay 70ab3cdd61 Docs are built in a different repo 2017-01-25 20:51:10 -08:00
David Tolnay 8fb554e593 Rename no_std tests to underscores 2017-01-25 20:50:23 -08:00
David Tolnay 7a2bfdc1dd Consistent underscores in root directory 2017-01-25 20:45:33 -08:00
David Tolnay 9046e9d7a1 Test suite requires beta for now 2017-01-25 20:45:08 -08:00
David Tolnay 87040b4bc4 Fix clippy lints in serde_test 2017-01-25 20:42:44 -08:00
David Tolnay 68aab2424f Rename test suite crate 2017-01-25 20:40:13 -08:00
David Tolnay 9b9b697eb1 Make compiletest an optional dependency of the test suite 2017-01-25 20:39:27 -08:00
David Tolnay db449c4bf2 Set up clippy for serde_test 2017-01-25 20:38:21 -08:00
David Tolnay 948aa47687 Clean up clippy lints 2017-01-25 20:34:01 -08:00
David Tolnay 3e1e42ef9b Combine the test suites 2017-01-25 20:29:09 -08:00
David Tolnay dbdfe4f306 Remove serde_codegen from the test suite 2017-01-25 20:19:16 -08:00
David Tolnay e0d6b9d010 Merge serde_codegen into serde_derive crate 2017-01-25 20:07:55 -08:00
David Tolnay a5b8e806f8 Remove with-syntex feature of serde_codegen 2017-01-25 20:02:24 -08:00
David Tolnay d7dadd83b6 Remove the syntex example 2017-01-25 19:54:24 -08:00
David Tolnay 7612fd8e82 Release 0.9.1 2017-01-25 14:58:22 -08:00
David Tolnay 4c77af53e5 Clean up dependency declarations 2017-01-25 14:54:32 -08:00
David Tolnay 5d9c1aeb06 Release 0.9.0 2017-01-25 12:57:45 -08:00
David Tolnay 59e48997dd Release 0.9.0-rc4 2017-01-25 10:14:43 -08:00
Oliver Schneider ffcd97834f Merge pull request #721 from serde-rs/size
Remove usize and isize from data model
2017-01-25 19:08:02 +01:00
David Tolnay e0c049dbf2 Remove usize and isize from data model 2017-01-25 09:08:06 -08:00
David Tolnay 8cb6607e82 Merge pull request #719 from serde-rs/rustdoc
Serde rustdoc
2017-01-24 20:59:26 -08:00
David Tolnay 1ffb0570b6 Do not require rustdoc tests to run on stable 2017-01-24 20:47:31 -08:00
David Tolnay 2c1dd60575 Serde rustdoc 2017-01-24 20:37:11 -08:00
David Tolnay 24f849da2d Remove unused #[macro_use]
I think this was for the quasi-quoting macros back in the day.
2017-01-24 09:28:00 -08:00
David Tolnay a5024a4238 Merge pull request #717 from serde-rs/badger
add travis badge to crates.io
2017-01-24 05:35:55 -08:00
Oliver Schneider b105423e5e add travis badge to crates.io 2017-01-24 10:30:10 +01:00
Oliver Schneider 42c1bc2907 Merge pull request #716 from serde-rs/ref
Serialize T by ref
2017-01-24 08:31:24 +01:00
David Tolnay c334c1c7b5 Release 0.9.0-rc3 2017-01-23 19:14:02 -08:00
David Tolnay 92668d7061 Serialize T by ref 2017-01-23 17:11:18 -08:00
David Tolnay b9d865d8e7 Merge pull request #715 from serde-rs/nostd
Support serde_derive on no_std
2017-01-23 16:13:25 -08:00
David Tolnay fc4e370ba9 Support serde_derive on no_std 2017-01-23 16:03:06 -08:00
Oliver Schneider a982d27536 Merge pull request #700 from serde-rs/usize
Restore visit_usize and visit_bytes for identifying variants
2017-01-23 11:27:06 +01:00
Oliver Schneider dc87826298 Merge pull request #699 from serde-rs/fields
Remove visit_usize from Duration impl
2017-01-23 11:26:18 +01:00
David Tolnay a09a8a039a All combinations of features compile without warnings 2017-01-23 01:45:54 -08:00
David Tolnay ea702755a2 Merge branch master into origin/usize
Conflicts:
    serde_codegen/src/de.rs
    testing/tests/test_de.rs
2017-01-23 01:36:49 -08:00
David Tolnay d161911c63 Merge branch master into origin/fields
Conflicts:
    serde/src/de/impls.rs
2017-01-23 01:28:01 -08:00
Oliver Schneider e27553d3df Merge pull request #710 from serde-rs/errors
Errors redesign
2017-01-23 10:25:48 +01:00
David Tolnay 48eaf988bc Add free-form option for Unexpected 2017-01-22 05:02:24 -08:00
David Tolnay 73a364d4fd Capture byte value for error message 2017-01-22 04:57:12 -08:00
David Tolnay 6dfdcb6ba1 Merge pull request #713 from serde-rs/zero
Suppress warning about using num::Zero
2017-01-21 19:20:57 -08:00
David Tolnay 089c7eb1d7 Suppress warning about using num::Zero 2017-01-21 19:14:56 -08:00
David Tolnay e40fbe0767 Restore visit_bytes for Duration impl 2017-01-18 21:13:51 -08:00
David Tolnay 0a10116bf5 Restore visit_bytes for identifying variants and fields 2017-01-18 21:11:51 -08:00
David Tolnay b1fbbfd3ce Restore visit_usize for identifying variants 2017-01-17 23:52:06 -08:00
David Tolnay 984ebcead0 Remove visit_usize and visit_bytes for Duration impl 2017-01-17 23:32:28 -08:00
62 changed files with 1792 additions and 1107 deletions
+21 -19
View File
@@ -1,26 +1,28 @@
sudo: false sudo: false
language: rust language: rust
# run builds for all the trains (and more)
rust: rust:
- 1.13.0 - 1.13.0
- stable - stable
- beta - beta
- nightly - nightly
before_script: before_script:
- pip install 'travis-cargo<0.2' --user - pip install 'travis-cargo<0.2' --user
- export PATH=$HOME/.local/bin:$PATH - export PATH=$HOME/.local/bin:$PATH
script: script:
- (cd serde && travis-cargo build) - (cd serde && travis-cargo build)
- (cd serde && travis-cargo --skip nightly test) - (cd serde && travis-cargo --only beta test)
- (cd serde && travis-cargo --only nightly test -- --features unstable-testing) - (cd serde && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde && travis-cargo build -- --no-default-features) - (cd serde && travis-cargo build -- --no-default-features)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features alloc) - (cd serde && travis-cargo --only nightly build -- --no-default-features --features alloc)
- (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections) - (cd serde && travis-cargo --only nightly build -- --no-default-features --features collections)
- (cd testing && travis-cargo --skip nightly test) - (cd test_suite && travis-cargo --only beta test)
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing) - (cd test_suite/deps && travis-cargo --only nightly build && cd .. && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde_derive && travis-cargo --only nightly test) - (cd test_suite/no_std && travis-cargo --only nightly build)
#- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
#- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features unstable)
- (cd serde && travis-cargo --only stable doc)
env: env:
global: global:
- TRAVIS_CARGO_NIGHTLY_FEATURE="" - TRAVIS_CARGO_NIGHTLY_FEATURE=""
-2
View File
@@ -1,2 +0,0 @@
target
Cargo.lock
-18
View File
@@ -1,18 +0,0 @@
[package]
name = "serde-syntex-example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
build = "build.rs"
publish = false
[features]
default = ["serde_codegen"]
unstable = ["serde_derive"]
[build-dependencies]
serde_codegen = { version = "^0.8", optional = true, path = "../../serde_codegen" }
[dependencies]
serde = "^0.8"
serde_derive = { version = "^0.8", optional = true, path = "../../serde_derive" }
serde_json = "^0.8"
-20
View File
@@ -1,20 +0,0 @@
This example demonstrates how to use Serde with Syntex. On stable or nightly
with Syntex, it can be built with:
```
% rustup run stable cargo run
Running `target/debug/serde-syntex-example`
{"x":1,"y":2}
Point { x: 1, y: 2 }
% rustup run nightly cargo run
Running `target/debug/serde-syntex-example`
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
On nightly, it can use a plugin with:
```
% rustup run nightly cargo run --features unstable --no-default-features
```
-25
View File
@@ -1,25 +0,0 @@
#[cfg(not(feature = "serde_derive"))]
mod inner {
extern crate serde_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("src/main.rs.in");
let dst = Path::new(&out_dir).join("main.rs");
serde_codegen::expand(&src, &dst).unwrap();
}
}
#[cfg(feature = "serde_derive")]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
-12
View File
@@ -1,12 +0,0 @@
#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[cfg(feature = "serde_derive")]
include!("main.rs.in");
#[cfg(not(feature = "serde_derive"))]
include!(concat!(env!("OUT_DIR"), "/main.rs"));
@@ -1,16 +0,0 @@
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
+8 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "0.9.0-rc2" version = "0.9.3"
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"
@@ -12,6 +12,9 @@ keywords = ["serde", "serialization"]
categories = ["encoding"] categories = ["encoding"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
[features] [features]
default = ["std"] default = ["std"]
@@ -22,4 +25,7 @@ collections = ["alloc"]
unstable-testing = ["clippy", "unstable", "std"] unstable-testing = ["clippy", "unstable", "std"]
[dependencies] [dependencies]
clippy = { version = "^0.*", optional = true } clippy = { version = "0.*", optional = true }
[dev-dependencies]
serde_derive = "0.9"
+60 -4
View File
@@ -1,4 +1,20 @@
//! Helper module to enable serializing bytes more efficiently //! Wrapper types to enable optimized handling of `&[u8]` and `Vec<u8>`.
//!
//! Without specialization, Rust forces us to treat `&[u8]` just like any other
//! slice and `Vec<u8>` just like any other vector. In reality this particular
//! slice and vector can often be serialized and deserialized in a more
//! efficient, compact representation in many formats.
//!
//! When working with such a format, you can opt into specialized handling of
//! `&[u8]` by wrapping it in `bytes::Bytes` and `Vec<u8>` by wrapping it in
//! `bytes::ByteBuf`.
//!
//! Rust support for specialization is being tracked in
//! [rust-lang/rust#31844][specialization]. Once it lands in the stable compiler
//! we will be deprecating these wrapper types in favor of optimizing `&[u8]`
//! and `Vec<u8>` out of the box.
//!
//! [specialization]: https://github.com/rust-lang/rust/issues/31844
use core::{ops, fmt, char, iter, slice}; use core::{ops, fmt, char, iter, slice};
use core::fmt::Write; use core::fmt::Write;
@@ -6,14 +22,36 @@ use core::fmt::Write;
use ser; use ser;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
pub use self::bytebuf::{ByteBuf, ByteBufVisitor}; pub use self::bytebuf::ByteBuf;
#[cfg(any(feature = "std", feature = "collections"))]
#[doc(hidden)] // does anybody need this?
pub use self::bytebuf::ByteBufVisitor;
#[cfg(feature = "collections")] #[cfg(feature = "collections")]
use collections::Vec; use collections::Vec;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// `Bytes` wraps a `&[u8]` in order to serialize into a byte array. /// Wraps a `&[u8]` in order to serialize in an efficient way. Does not support
/// deserialization.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::Bytes;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize)]
/// struct Packet<'a> {
/// destination: IpAddr,
/// payload: Bytes<'a>,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)] #[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Bytes<'a> { pub struct Bytes<'a> {
bytes: &'a [u8], bytes: &'a [u8],
@@ -86,7 +124,25 @@ mod bytebuf {
#[cfg(feature = "collections")] #[cfg(feature = "collections")]
use collections::{String, Vec}; use collections::{String, Vec};
/// `ByteBuf` wraps a `Vec<u8>` and serializes as a byte array. /// Wraps a `Vec<u8>` in order to serialize and deserialize in an efficient
/// way.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::ByteBuf;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize, Deserialize)]
/// struct Packet {
/// destination: IpAddr,
/// payload: ByteBuf,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)] #[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf { pub struct ByteBuf {
bytes: Vec<u8>, bytes: Vec<u8>,
+68 -77
View File
@@ -2,7 +2,7 @@
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::borrow::Cow; use std::borrow::Cow;
#[cfg(all(feature = "unstable", feature = "collections", not(feature = "std")))] #[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow; use collections::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "collections", not(feature = "std")))]
@@ -27,12 +27,13 @@ use std::collections::{
VecDeque, VecDeque,
}; };
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet}; use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
use collections::borrow::ToOwned; use collections::borrow::ToOwned;
use core::fmt; use core::fmt;
#[cfg(feature = "std")]
use core::hash::{Hash, BuildHasher}; use core::hash::{Hash, BuildHasher};
use core::marker::PhantomData; use core::marker::PhantomData;
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -43,15 +44,15 @@ use core::str;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::rc::Rc; use std::rc::Rc;
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc; use alloc::rc::Rc;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::sync::Arc; use std::sync::Arc;
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::arc::Arc; use alloc::arc::Arc;
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box; use alloc::boxed::Box;
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -61,6 +62,7 @@ use std::time::Duration;
use core::nonzero::{NonZero, Zeroable}; use core::nonzero::{NonZero, Zeroable};
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
#[allow(deprecated)] // required for impl Deserialize for NonZero<T>
use core::num::Zero; use core::num::Zero;
use de::{ use de::{
@@ -178,12 +180,10 @@ macro_rules! impl_deserialize_num {
formatter.write_str(stringify!($ty)) formatter.write_str(stringify!($ty))
} }
impl_deserialize_num_method!($ty, isize, visit_isize, from_isize, Signed, i64);
impl_deserialize_num_method!($ty, i8, visit_i8, from_i8, Signed, i64); impl_deserialize_num_method!($ty, i8, visit_i8, from_i8, Signed, i64);
impl_deserialize_num_method!($ty, i16, visit_i16, from_i16, Signed, i64); impl_deserialize_num_method!($ty, i16, visit_i16, from_i16, Signed, i64);
impl_deserialize_num_method!($ty, i32, visit_i32, from_i32, Signed, i64); impl_deserialize_num_method!($ty, i32, visit_i32, from_i32, Signed, i64);
impl_deserialize_num_method!($ty, i64, visit_i64, from_i64, Signed, i64); impl_deserialize_num_method!($ty, i64, visit_i64, from_i64, Signed, i64);
impl_deserialize_num_method!($ty, usize, visit_usize, from_usize, Unsigned, u64);
impl_deserialize_num_method!($ty, u8, visit_u8, from_u8, Unsigned, u64); impl_deserialize_num_method!($ty, u8, visit_u8, from_u8, Unsigned, u64);
impl_deserialize_num_method!($ty, u16, visit_u16, from_u16, Unsigned, u64); impl_deserialize_num_method!($ty, u16, visit_u16, from_u16, Unsigned, u64);
impl_deserialize_num_method!($ty, u32, visit_u32, from_u32, Unsigned, u64); impl_deserialize_num_method!($ty, u32, visit_u32, from_u32, Unsigned, u64);
@@ -207,12 +207,12 @@ macro_rules! impl_deserialize_num {
} }
} }
impl_deserialize_num!(isize, deserialize_isize); impl_deserialize_num!(isize, deserialize_i64);
impl_deserialize_num!(i8, deserialize_i8); impl_deserialize_num!(i8, deserialize_i8);
impl_deserialize_num!(i16, deserialize_i16); impl_deserialize_num!(i16, deserialize_i16);
impl_deserialize_num!(i32, deserialize_i32); impl_deserialize_num!(i32, deserialize_i32);
impl_deserialize_num!(i64, deserialize_i64); impl_deserialize_num!(i64, deserialize_i64);
impl_deserialize_num!(usize, deserialize_usize); impl_deserialize_num!(usize, deserialize_u64);
impl_deserialize_num!(u8, deserialize_u8); impl_deserialize_num!(u8, deserialize_u8);
impl_deserialize_num!(u16, deserialize_u16); impl_deserialize_num!(u16, deserialize_u16);
impl_deserialize_num!(u32, deserialize_u32); impl_deserialize_num!(u32, deserialize_u32);
@@ -295,7 +295,7 @@ impl Visitor for StringVisitor {
{ {
match str::from_utf8(v) { match str::from_utf8(v) {
Ok(s) => Ok(s.to_owned()), Ok(s) => Ok(s.to_owned()),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes, &self)), Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
} }
} }
@@ -304,7 +304,7 @@ impl Visitor for StringVisitor {
{ {
match String::from_utf8(v) { match String::from_utf8(v) {
Ok(s) => Ok(s), Ok(s) => Ok(s),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes, &self)), Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)),
} }
} }
} }
@@ -481,7 +481,7 @@ seq_impl!(
BTreeSet::new(), BTreeSet::new(),
BTreeSet::insert); BTreeSet::insert);
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
seq_impl!( seq_impl!(
EnumSet<T>, EnumSet<T>,
EnumSetVisitor<T: Deserialize + CLike>, EnumSetVisitor<T: Deserialize + CLike>,
@@ -574,7 +574,7 @@ impl<T> Deserialize for [T; 0]
} }
macro_rules! array_impls { macro_rules! array_impls {
($($len:expr => ($($name:ident)+))+) => { ($($len:expr => ($($n:tt $name:ident)+))+) => {
$( $(
impl<T> Visitor for ArrayVisitor<[T; $len]> where T: Deserialize { impl<T> Visitor for ArrayVisitor<[T; $len]> where T: Deserialize {
type Value = [T; $len]; type Value = [T; $len];
@@ -590,7 +590,7 @@ macro_rules! array_impls {
$( $(
let $name = match try!(visitor.visit()) { let $name = match try!(visitor.visit()) {
Some(val) => val, Some(val) => val,
None => return Err(Error::invalid_length(0, &self)), None => return Err(Error::invalid_length($n, &self)),
}; };
)+ )+
@@ -612,44 +612,44 @@ macro_rules! array_impls {
} }
array_impls! { array_impls! {
1 => (a) 1 => (0 a)
2 => (a b) 2 => (0 a 1 b)
3 => (a b c) 3 => (0 a 1 b 2 c)
4 => (a b c d) 4 => (0 a 1 b 2 c 3 d)
5 => (a b c d e) 5 => (0 a 1 b 2 c 3 d 4 e)
6 => (a b c d e f) 6 => (0 a 1 b 2 c 3 d 4 e 5 f)
7 => (a b c d e f g) 7 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g)
8 => (a b c d e f g h) 8 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h)
9 => (a b c d e f g h i) 9 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i)
10 => (a b c d e f g h i j) 10 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j)
11 => (a b c d e f g h i j k) 11 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k)
12 => (a b c d e f g h i j k l) 12 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l)
13 => (a b c d e f g h i j k l m) 13 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m)
14 => (a b c d e f g h i j k l m n) 14 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n)
15 => (a b c d e f g h i j k l m n o) 15 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o)
16 => (a b c d e f g h i j k l m n o p) 16 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p)
17 => (a b c d e f g h i j k l m n o p q) 17 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q)
18 => (a b c d e f g h i j k l m n o p q r) 18 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r)
19 => (a b c d e f g h i j k l m n o p q r s) 19 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s)
20 => (a b c d e f g h i j k l m n o p q r s t) 20 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t)
21 => (a b c d e f g h i j k l m n o p q r s t u) 21 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u)
22 => (a b c d e f g h i j k l m n o p q r s t u v) 22 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v)
23 => (a b c d e f g h i j k l m n o p q r s t u v w) 23 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w)
24 => (a b c d e f g h i j k l m n o p q r s t u v w x) 24 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x)
25 => (a b c d e f g h i j k l m n o p q r s t u v w x y) 25 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y)
26 => (a b c d e f g h i j k l m n o p q r s t u v w x y z) 26 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z)
27 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa) 27 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa)
28 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab) 28 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab)
29 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac) 29 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac)
30 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad) 30 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad)
31 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae) 31 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae)
32 => (a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af) 32 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae 31 af)
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls { macro_rules! tuple_impls {
($($len:expr => $visitor:ident => ($($name:ident)+))+) => { ($($len:expr => $visitor:ident => ($($n:tt $name:ident)+))+) => {
$( $(
/// Construct a tuple visitor. /// Construct a tuple visitor.
pub struct $visitor<$($name,)+> { pub struct $visitor<$($name,)+> {
@@ -678,7 +678,7 @@ macro_rules! tuple_impls {
$( $(
let $name = match try!(visitor.visit()) { let $name = match try!(visitor.visit()) {
Some(value) => value, Some(value) => value,
None => return Err(Error::invalid_length(0, &self)), None => return Err(Error::invalid_length($n, &self)),
}; };
)+ )+
@@ -699,22 +699,22 @@ macro_rules! tuple_impls {
} }
tuple_impls! { tuple_impls! {
1 => TupleVisitor1 => (T0) 1 => TupleVisitor1 => (0 T0)
2 => TupleVisitor2 => (T0 T1) 2 => TupleVisitor2 => (0 T0 1 T1)
3 => TupleVisitor3 => (T0 T1 T2) 3 => TupleVisitor3 => (0 T0 1 T1 2 T2)
4 => TupleVisitor4 => (T0 T1 T2 T3) 4 => TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3)
5 => TupleVisitor5 => (T0 T1 T2 T3 T4) 5 => TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 => TupleVisitor6 => (T0 T1 T2 T3 T4 T5) 6 => TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 => TupleVisitor7 => (T0 T1 T2 T3 T4 T5 T6) 7 => TupleVisitor7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 => TupleVisitor8 => (T0 T1 T2 T3 T4 T5 T6 T7) 8 => TupleVisitor8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 => TupleVisitor9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8) 9 => TupleVisitor9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 => TupleVisitor10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9) 10 => TupleVisitor10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 => TupleVisitor11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10) 11 => TupleVisitor11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
12 => TupleVisitor12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11) 12 => TupleVisitor12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
13 => TupleVisitor13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12) 13 => TupleVisitor13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
14 => TupleVisitor14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13) 14 => TupleVisitor14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
15 => TupleVisitor15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14) 15 => TupleVisitor15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
16 => TupleVisitor16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15) 16 => TupleVisitor16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -1014,16 +1014,6 @@ impl Deserialize for Duration {
formatter.write_str("`secs` or `nanos`") formatter.write_str("`secs` or `nanos`")
} }
fn visit_usize<E>(self, value: usize) -> Result<Field, E>
where E: Error,
{
match value {
0usize => Ok(Field::Secs),
1usize => Ok(Field::Nanos),
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self)),
}
}
fn visit_str<E>(self, value: &str) -> Result<Field, E> fn visit_str<E>(self, value: &str) -> Result<Field, E>
where E: Error, where E: Error,
{ {
@@ -1120,6 +1110,7 @@ impl Deserialize for Duration {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
#[allow(deprecated)] // num::Zero is deprecated but there is no replacement
impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero { impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero {
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error> where D: Deserializer { fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
let value = try!(Deserialize::deserialize(deserializer)); let value = try!(Deserialize::deserialize(deserializer));
@@ -1157,7 +1148,7 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
formatter.write_str("`Ok` or `Err`") formatter.write_str("`Ok` or `Err`")
} }
fn visit_usize<E>(self, value: usize) -> Result<Field, E> where E: Error { fn visit_u32<E>(self, value: u32) -> Result<Field, E> where E: Error {
match value { match value {
0 => Ok(Field::Ok), 0 => Ok(Field::Ok),
1 => Ok(Field::Err), 1 => Ok(Field::Err),
@@ -1180,7 +1171,7 @@ impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
_ => { _ => {
match str::from_utf8(value) { match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)), Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes, &self)), Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)),
} }
} }
} }
+507 -179
View File
File diff suppressed because it is too large Load Diff
+3 -4
View File
@@ -28,10 +28,9 @@ pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
string unit seq seq_fixed_size bytes byte_buf map unit_struct seq_fixed_size bytes byte_buf map unit_struct newtype_struct
newtype_struct tuple_struct struct struct_field tuple enum tuple_struct struct struct_field tuple enum ignored_any
ignored_any
} }
} }
+52 -55
View File
@@ -33,9 +33,7 @@ use collections::boxed::Box;
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "collections", not(feature = "std")))]
use collections::string::ToString; use collections::string::ToString;
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "std")]
use collections::borrow::ToOwned;
use core::hash::Hash; use core::hash::Hash;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::error; use std::error;
@@ -67,7 +65,7 @@ impl de::Error for Error {
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "collections")))]
fn custom<T: Display>(msg: T) -> Self { fn custom<T: Display>(_msg: T) -> Self {
Error(()) Error(())
} }
} }
@@ -128,9 +126,9 @@ impl<E> de::Deserializer for UnitDeserializer<E>
type Error = E; type Error = E;
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
unit seq seq_fixed_size bytes map unit_struct newtype_struct seq_fixed_size bytes map unit_struct newtype_struct tuple_struct struct
tuple_struct struct struct_field tuple enum ignored_any byte_buf struct_field tuple enum ignored_any byte_buf
} }
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -149,7 +147,7 @@ impl<E> de::Deserializer for UnitDeserializer<E>
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
macro_rules! primitive_deserializer { macro_rules! primitive_deserializer {
($ty:ty, $name:ident, $method:ident) => { ($ty:ty, $name:ident, $method:ident $($cast:tt)*) => {
/// A helper deserializer that deserializes a number. /// A helper deserializer that deserializes a number.
pub struct $name<E>($ty, PhantomData<E>); pub struct $name<E>($ty, PhantomData<E>);
@@ -169,16 +167,15 @@ macro_rules! primitive_deserializer {
type Error = E; type Error = E;
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit
string unit option seq seq_fixed_size bytes map unit_struct option seq seq_fixed_size bytes map unit_struct newtype_struct
newtype_struct tuple_struct struct struct_field tuple enum tuple_struct struct struct_field tuple enum ignored_any byte_buf
ignored_any byte_buf
} }
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor, where V: de::Visitor,
{ {
visitor.$method(self.0) visitor.$method(self.0 $($cast)*)
} }
} }
} }
@@ -189,12 +186,12 @@ primitive_deserializer!(i8, I8Deserializer, visit_i8);
primitive_deserializer!(i16, I16Deserializer, visit_i16); primitive_deserializer!(i16, I16Deserializer, visit_i16);
primitive_deserializer!(i32, I32Deserializer, visit_i32); primitive_deserializer!(i32, I32Deserializer, visit_i32);
primitive_deserializer!(i64, I64Deserializer, visit_i64); primitive_deserializer!(i64, I64Deserializer, visit_i64);
primitive_deserializer!(isize, IsizeDeserializer, visit_isize); primitive_deserializer!(isize, IsizeDeserializer, visit_i64 as i64);
primitive_deserializer!(u8, U8Deserializer, visit_u8); primitive_deserializer!(u8, U8Deserializer, visit_u8);
primitive_deserializer!(u16, U16Deserializer, visit_u16); primitive_deserializer!(u16, U16Deserializer, visit_u16);
primitive_deserializer!(u32, U32Deserializer, visit_u32); primitive_deserializer!(u32, U32Deserializer, visit_u32);
primitive_deserializer!(u64, U64Deserializer, visit_u64); primitive_deserializer!(u64, U64Deserializer, visit_u64);
primitive_deserializer!(usize, UsizeDeserializer, visit_usize); primitive_deserializer!(usize, UsizeDeserializer, visit_u64 as u64);
primitive_deserializer!(f32, F32Deserializer, visit_f32); primitive_deserializer!(f32, F32Deserializer, visit_f32);
primitive_deserializer!(f64, F64Deserializer, visit_f64); primitive_deserializer!(f64, F64Deserializer, visit_f64);
primitive_deserializer!(char, CharDeserializer, visit_char); primitive_deserializer!(char, CharDeserializer, visit_char);
@@ -235,9 +232,9 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option seq seq_fixed_size bytes map unit_struct newtype_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
tuple_struct struct struct_field tuple ignored_any byte_buf struct struct_field tuple ignored_any byte_buf
} }
} }
@@ -293,9 +290,9 @@ impl<E> de::Deserializer for StringDeserializer<E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option seq seq_fixed_size bytes map unit_struct newtype_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
tuple_struct struct struct_field tuple ignored_any byte_buf struct struct_field tuple ignored_any byte_buf
} }
} }
@@ -355,9 +352,9 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option seq seq_fixed_size bytes map unit_struct newtype_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
tuple_struct struct struct_field tuple ignored_any byte_buf struct struct_field tuple ignored_any byte_buf
} }
} }
@@ -428,9 +425,9 @@ impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option seq seq_fixed_size bytes map unit_struct newtype_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
tuple_struct struct struct_field tuple enum ignored_any byte_buf struct struct_field tuple enum ignored_any byte_buf
} }
} }
@@ -540,9 +537,9 @@ impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option seq seq_fixed_size bytes map unit_struct newtype_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
tuple_struct struct struct_field tuple enum ignored_any byte_buf struct struct_field tuple enum ignored_any byte_buf
} }
} }
@@ -579,7 +576,7 @@ impl<I, E> MapDeserializer<I, E>
} }
} }
fn next(&mut self) -> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> { fn next_pair(&mut self) -> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> {
match self.iter.next() { match self.iter.next() {
Some(kv) => { Some(kv) => {
self.count += 1; self.count += 1;
@@ -636,9 +633,9 @@ impl<I, E> de::Deserializer for MapDeserializer<I, E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option bytes map unit_struct newtype_struct tuple_struct struct bytes map unit_struct newtype_struct tuple_struct struct struct_field
struct_field tuple enum ignored_any byte_buf tuple enum ignored_any byte_buf
} }
} }
@@ -654,7 +651,7 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
fn visit_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> fn visit_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where T: de::DeserializeSeed, where T: de::DeserializeSeed,
{ {
match self.next() { match self.next_pair() {
Some((key, value)) => { Some((key, value)) => {
self.value = Some(value); self.value = Some(value);
seed.deserialize(key.into_deserializer()).map(Some) seed.deserialize(key.into_deserializer()).map(Some)
@@ -677,7 +674,7 @@ impl<I, E> de::MapVisitor for MapDeserializer<I, E>
where TK: de::DeserializeSeed, where TK: de::DeserializeSeed,
TV: de::DeserializeSeed TV: de::DeserializeSeed
{ {
match self.next() { match self.next_pair() {
Some((key, value)) => { Some((key, value)) => {
let key = try!(kseed.deserialize(key.into_deserializer())); let key = try!(kseed.deserialize(key.into_deserializer()));
let value = try!(vseed.deserialize(value.into_deserializer())); let value = try!(vseed.deserialize(value.into_deserializer()));
@@ -704,7 +701,7 @@ impl<I, E> de::SeqVisitor for MapDeserializer<I, E>
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where T: de::DeserializeSeed, where T: de::DeserializeSeed,
{ {
match self.next() { match self.next_pair() {
Some((k, v)) => { Some((k, v)) => {
let de = PairDeserializer(k, v, PhantomData); let de = PairDeserializer(k, v, PhantomData);
seed.deserialize(de).map(Some) seed.deserialize(de).map(Some)
@@ -730,9 +727,9 @@ impl<A, B, E> de::Deserializer for PairDeserializer<A, B, E>
type Error = E; type Error = E;
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option bytes map unit_struct newtype_struct tuple_struct struct bytes map unit_struct newtype_struct tuple_struct struct struct_field
struct_field tuple enum ignored_any byte_buf tuple enum ignored_any byte_buf
} }
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
@@ -874,9 +871,9 @@ impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option seq seq_fixed_size bytes map unit_struct newtype_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
tuple_struct struct struct_field tuple enum ignored_any byte_buf struct struct_field tuple enum ignored_any byte_buf
} }
} }
@@ -907,9 +904,9 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option seq seq_fixed_size bytes map unit_struct newtype_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
tuple_struct struct struct_field tuple enum ignored_any byte_buf struct struct_field tuple enum ignored_any byte_buf
} }
} }
@@ -943,9 +940,9 @@ impl<E> de::Deserializer for ByteBufDeserializer<E>
} }
forward_to_deserialize! { forward_to_deserialize! {
bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
unit option seq seq_fixed_size bytes map unit_struct newtype_struct seq seq_fixed_size bytes map unit_struct newtype_struct tuple_struct
tuple_struct struct struct_field tuple enum ignored_any byte_buf struct struct_field tuple enum ignored_any byte_buf
} }
} }
@@ -977,24 +974,24 @@ mod private {
} }
fn visit_tuple<V>(self, fn visit_tuple<V>(self,
_len: usize, _len: usize,
_visitor: V) -> Result<V::Value, Self::Error> _visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor where V: de::Visitor
{ {
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant")) Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"))
} }
fn visit_struct<V>(self, fn visit_struct<V>(self,
_fields: &'static [&'static str], _fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error> _visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor where V: de::Visitor
{ {
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant")) Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"))
} }
} }
/// Avoid having to restate the generic types on MapDeserializer. The /// Avoid having to restate the generic types on `MapDeserializer`. The
/// Iterator::Item contains enough information to figure out K and V. /// `Iterator::Item` contains enough information to figure out K and V.
pub trait Pair { pub trait Pair {
type First; type First;
type Second; type Second;
+33
View File
@@ -0,0 +1,33 @@
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::String;
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
pub use core::default::Default;
pub use core::fmt;
pub use core::marker::PhantomData;
pub use core::result::Result;
#[cfg(any(feature = "collections", feature = "std"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
//
// let value = &_serde::export::from_utf8_lossy(bytes);
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
//
// so it is okay for the return type to be different from the std case as long
// as the above works.
#[cfg(not(any(feature = "collections", feature = "std")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
use core::str;
// Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid
// UTF-8.
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
}
+74 -20
View File
@@ -1,40 +1,89 @@
//! Serde Serialization Framework //! # Serde
//! //!
//! Serde is a powerful framework that enables serialization libraries to generically serialize //! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! Rust data structures without the overhead of runtime type information. In many situations, the //! structures efficiently and generically.
//! handshake protocol between serializers and serializees can be completely optimized away,
//! leaving serde to perform roughly the same speed as a hand written serializer for a specific
//! type.
//! //!
//! For a detailed tutorial on the different ways to use serde please check out the //! The Serde ecosystem consists of data structures that know how to serialize
//! [github repository](https://github.com/serde-rs/serde) //! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website https://serde.rs/ for additional documentation and
//! usage examples.
//!
//! ### Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's code
//! generation to automatically derive implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform roughly the same speed as a handwritten serializer
//! for the specific selection of data structure and data format.
//!
//! ### Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON](https://github.com/serde-rs/json), the ubiquitous JavaScript Object
//! Notation used by many HTTP APIs.
//! - [Bincode](https://github.com/TyOverby/bincode), a compact binary format
//! used for IPC within the Servo rendering engine.
//! - [CBOR](https://github.com/pyfisch/cbor), a Concise Binary Object
//! Representation designed for small message size without the need for
//! version negotiation.
//! - [YAML](https://github.com/dtolnay/serde-yaml), a popular human-friendly
//! configuration language that ain't markup language.
//! - [MessagePack](https://github.com/3Hren/msgpack-rust), an efficient binary
//! format that resembles a compact JSON.
//! - [TOML](https://github.com/alexcrichton/toml-rs), a minimal configuration
//! format used by [Cargo](http://doc.crates.io/manifest.html).
//! - [Pickle](https://github.com/birkenfeld/serde-pickle), a format common in
//! the Python world.
//! - [Hjson](https://github.com/laktak/hjson-rust), a variant of JSON designed
//! to be readable and writable by humans.
//! - [BSON](https://github.com/zonyitoo/bson-rs), the data storage and network
//! transfer format used by MongoDB.
//! - [URL](https://github.com/nox/serde_urlencoded), the x-www-form-urlencoded
//! format.
//! - [XML](https://github.com/serde-rs/xml), the flexible machine-friendly W3C
//! standard. *(deserialization only)*
//! - [Envy](https://github.com/softprops/envy), a way to deserialize
//! environment variables into Rust structs. *(deserialization only)*
//! - [Redis](https://github.com/OneSignal/serde-redis), deserialize values from
//! Redis when using [redis-rs](https://crates.io/crates/redis).
//! *(deserialization only)*
#![doc(html_root_url="https://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, inclusive_range))] #![cfg_attr(feature = "unstable", feature(nonzero, inclusive_range, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections, enumset))] #![cfg_attr(feature = "collections", feature(collections, enumset))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))] #![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(linkedlist))] #![cfg_attr(feature = "clippy", allow(linkedlist, type_complexity, doc_markdown))]
#![cfg_attr(any(not(feature = "std"), feature = "unstable"), allow(unused_variables, unused_imports, unused_features, dead_code))]
#![deny(missing_docs)] #![deny(missing_docs)]
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
extern crate collections; extern crate collections;
#[cfg(all(feature = "unstable", feature = "alloc"))] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
#[cfg(feature = "unstable")]
extern crate core as actual_core;
#[cfg(feature = "std")] #[cfg(feature = "std")]
mod core { mod core {
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize, pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
usize, f32, f64, char, str, num, slice, iter, cell}; usize, f32, f64, char, str, num, slice, iter, cell, default, result};
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
extern crate core; pub use actual_core::nonzero;
#[cfg(feature = "unstable")]
pub use self::core::nonzero;
} }
pub use ser::{Serialize, Serializer}; pub use ser::{Serialize, Serializer};
@@ -46,8 +95,13 @@ mod macros;
pub mod bytes; pub mod bytes;
pub mod de; pub mod de;
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[doc(hidden)]
pub mod iter; pub mod iter;
pub mod ser; pub mod ser;
#[cfg(not(feature = "std"))] #[cfg_attr(feature = "std", doc(hidden))]
pub mod error; pub mod error;
mod utils; mod utils;
// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;
+51 -15
View File
@@ -32,9 +32,6 @@ macro_rules! forward_to_deserialize_helper {
(bool) => { (bool) => {
forward_to_deserialize_method!{deserialize_bool()} forward_to_deserialize_method!{deserialize_bool()}
}; };
(usize) => {
forward_to_deserialize_method!{deserialize_usize()}
};
(u8) => { (u8) => {
forward_to_deserialize_method!{deserialize_u8()} forward_to_deserialize_method!{deserialize_u8()}
}; };
@@ -47,9 +44,6 @@ macro_rules! forward_to_deserialize_helper {
(u64) => { (u64) => {
forward_to_deserialize_method!{deserialize_u64()} forward_to_deserialize_method!{deserialize_u64()}
}; };
(isize) => {
forward_to_deserialize_method!{deserialize_isize()}
};
(i8) => { (i8) => {
forward_to_deserialize_method!{deserialize_i8()} forward_to_deserialize_method!{deserialize_i8()}
}; };
@@ -124,28 +118,70 @@ macro_rules! forward_to_deserialize_helper {
}; };
} }
/// Helper to forward `Deserializer` methods to `Deserializer::deserialize`. // Super explicit first paragraph because this shows up at the top level and
/// Every given method ignores all arguments and forwards to `deserialize`. // trips up people who are just looking for basic Serialize / Deserialize
/// Note that `deserialize_enum` simply returns an `Error::invalid_type`; a // documentation.
/// better approach is tracked in [serde-rs/serde#521][1]. //
/// Helper macro when implementing the `Deserializer` part of a new data format
/// for Serde.
/// ///
/// ```rust,ignore /// Some `Deserializer` implementations for self-describing formats do not care
/// what hint the `Visitor` gives them, they just want to blindly call the
/// `Visitor` method corresponding to the data they can tell is in the input.
/// This requires repetitive implementations of all the `Deserializer` trait
/// methods.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// # impl Deserializer for MyDeserializer {
/// # type Error = value::Error;
/// # fn deserialize<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor
/// # { unimplemented!() }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor
/// {
/// self.deserialize(visitor)
/// }
/// # forward_to_deserialize! {
/// # u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// # tuple_struct struct struct_field tuple enum ignored_any
/// # }
/// # }
/// # fn main() {}
/// ```
///
/// The `forward_to_deserialize!` macro implements these simple forwarding
/// methods so that they forward directly to `Deserializer::deserialize`. You
/// can choose which methods to forward.
///
/// ```rust
/// # #[macro_use] extern crate serde;
/// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer;
/// impl Deserializer for MyDeserializer { /// impl Deserializer for MyDeserializer {
/// # type Error = value::Error;
/// fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> /// fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor /// where V: Visitor
/// { /// {
/// /* ... */ /// /* ... */
/// # let _ = visitor;
/// # unimplemented!()
/// } /// }
/// ///
/// forward_to_deserialize! { /// forward_to_deserialize! {
/// bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 char str string /// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
/// unit option seq seq_fixed_size bytes map unit_struct newtype_struct /// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
/// tuple_struct struct struct_field tuple enum ignored_any /// tuple_struct struct struct_field tuple enum ignored_any
/// } /// }
/// } /// }
/// # fn main() {}
/// ``` /// ```
///
/// [1]: https://github.com/serde-rs/serde/issues/521
#[macro_export] #[macro_export]
macro_rules! forward_to_deserialize { macro_rules! forward_to_deserialize {
($($func:ident)*) => { ($($func:ident)*) => {
+21 -28
View File
@@ -1,9 +1,3 @@
//! Implementations for all of Rust's builtin types. Tuples implement the `Serialize` trait if they
//! have at most 16 fields. Arrays implement the `Serialize` trait if their length is 32 or less.
//! You can always forward array serialization to slice serialization, which works for any length.
//! Long tuples are best replaced by tuple structs, for which you can use `derive(Serialize)`. In
//! that case the number of fields is irrelevant.
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::borrow::Cow; use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "collections", not(feature = "std")))]
@@ -30,19 +24,18 @@ use collections::{
Vec, Vec,
}; };
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet}; use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
use collections::borrow::ToOwned; use collections::borrow::ToOwned;
#[cfg(feature = "std")]
use core::hash::{Hash, BuildHasher}; use core::hash::{Hash, BuildHasher};
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
use core::iter; use core::iter;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::net; use std::net;
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
use core::num;
#[cfg(feature = "unstable")]
use core::ops; use core::ops;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::path; use std::path;
@@ -67,14 +60,13 @@ use core::marker::PhantomData;
use core::nonzero::{NonZero, Zeroable}; use core::nonzero::{NonZero, Zeroable};
use super::{ use super::{
Error,
Serialize, Serialize,
SerializeMap,
SerializeSeq, SerializeSeq,
SerializeStruct,
SerializeTuple, SerializeTuple,
Serializer, Serializer,
}; };
#[cfg(any(feature = "std", feature = "unstable"))]
use super::Error;
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
use super::Iterator; use super::Iterator;
@@ -82,25 +74,25 @@ use super::Iterator;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_visit { macro_rules! impl_visit {
($ty:ty, $method:ident) => { ($ty:ty, $method:ident $($cast:tt)*) => {
impl Serialize for $ty { impl Serialize for $ty {
#[inline] #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, where S: Serializer,
{ {
serializer.$method(*self) serializer.$method(*self $($cast)*)
} }
} }
} }
} }
impl_visit!(bool, serialize_bool); impl_visit!(bool, serialize_bool);
impl_visit!(isize, serialize_isize); impl_visit!(isize, serialize_i64 as i64);
impl_visit!(i8, serialize_i8); impl_visit!(i8, serialize_i8);
impl_visit!(i16, serialize_i16); impl_visit!(i16, serialize_i16);
impl_visit!(i32, serialize_i32); impl_visit!(i32, serialize_i32);
impl_visit!(i64, serialize_i64); impl_visit!(i64, serialize_i64);
impl_visit!(usize, serialize_usize); impl_visit!(usize, serialize_u64 as u64);
impl_visit!(u8, serialize_u8); impl_visit!(u8, serialize_u8);
impl_visit!(u16, serialize_u16); impl_visit!(u16, serialize_u16);
impl_visit!(u32, serialize_u32); impl_visit!(u32, serialize_u32);
@@ -241,7 +233,7 @@ impl<'a, I> Serialize for Iterator<I>
// FIXME: use specialization to prevent invalidating the object in case of clonable iterators? // FIXME: use specialization to prevent invalidating the object in case of clonable iterators?
let iter = match self.0.borrow_mut().take() { let iter = match self.0.borrow_mut().take() {
Some(iter) => iter.into_iter(), Some(iter) => iter.into_iter(),
None => return Err(S::Error::custom("Iterator used twice")), None => return Err(Error::custom("Iterator used twice")),
}; };
let size = match iter.size_hint() { let size = match iter.size_hint() {
(lo, Some(hi)) if lo == hi => Some(lo), (lo, Some(hi)) if lo == hi => Some(lo),
@@ -249,7 +241,7 @@ impl<'a, I> Serialize for Iterator<I>
}; };
let mut seq = try!(serializer.serialize_seq(size)); let mut seq = try!(serializer.serialize_seq(size));
for e in iter { for e in iter {
try!(seq.serialize_element(e)); try!(seq.serialize_element(&e));
} }
seq.end() seq.end()
} }
@@ -265,7 +257,7 @@ macro_rules! serialize_seq {
{ {
let mut seq = try!(serializer.serialize_seq(Some(self.len()))); let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self { for e in self {
try!(seq.serialize_element(e)); try!(seq.serialize_element(&e));
} }
seq.end() seq.end()
} }
@@ -286,7 +278,7 @@ impl<T> Serialize for BTreeSet<T>
serialize_seq!(); serialize_seq!();
} }
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
impl<T> Serialize for EnumSet<T> impl<T> Serialize for EnumSet<T>
where T: Serialize + CLike where T: Serialize + CLike
{ {
@@ -333,7 +325,7 @@ impl<A> Serialize for ops::Range<A>
{ {
let mut seq = try!(serializer.serialize_seq(Some(self.len()))); let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self.clone() { for e in self.clone() {
try!(seq.serialize_element(e)); try!(seq.serialize_element(&e));
} }
seq.end() seq.end()
} }
@@ -350,7 +342,7 @@ impl<A> Serialize for ops::RangeInclusive<A>
{ {
let mut seq = try!(serializer.serialize_seq(Some(self.len()))); let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self.clone() { for e in self.clone() {
try!(seq.serialize_element(e)); try!(seq.serialize_element(&e));
} }
seq.end() seq.end()
} }
@@ -573,10 +565,10 @@ macro_rules! serialize_map {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, where S: Serializer,
{ {
use super::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(self.len()))); let mut map = try!(serializer.serialize_map(Some(self.len())));
for (k, v) in self { for (k, v) in self {
try!(map.serialize_key(k)); try!(map.serialize_entry(k, v));
try!(map.serialize_value(v));
} }
map.end() map.end()
} }
@@ -695,9 +687,10 @@ impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer, where S: Serializer,
{ {
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Duration", 2)); let mut state = try!(serializer.serialize_struct("Duration", 2));
try!(state.serialize_field("secs", self.as_secs())); try!(state.serialize_field("secs", &self.as_secs()));
try!(state.serialize_field("nanos", self.subsec_nanos())); try!(state.serialize_field("nanos", &self.subsec_nanos()));
state.end() state.end()
} }
} }
@@ -772,7 +765,7 @@ impl Serialize for path::Path {
{ {
match self.to_str() { match self.to_str() {
Some(s) => s.serialize(serializer), Some(s) => s.serialize(serializer),
None => Err(Error::custom("Path contains invalid UTF-8 characters")), None => Err(Error::custom("path contains invalid UTF-8 characters")),
} }
} }
} }
+557 -180
View File
@@ -1,76 +1,248 @@
//! Generic serialization framework. //! Generic data structure serialization framework.
//! # For Developers who want to serialize objects
//! Implement the `Serialize` trait for the type of objects you want to serialize. Call methods of
//! the `serializer` object. For which methods to call and how to do so, look at the documentation
//! of the `Serializer` trait.
//! //!
//! # For Serialization Format Developers //! The two most important traits in this module are `Serialize` and
//! Implement the `Serializer` trait for a structure that contains fields that enable it to write //! `Serializer`.
//! the serialization result to your target. When a method's argument is an object of type //!
//! `Serialize`, you can either forward the serializer object (`self`) or create a new one, //! - **A type that implements `Serialize` is a data structure** that can be
//! depending on the quirks of your format. //! serialized to any data format supported by Serde, and conversely
//! - **A type that implements `Serializer` is a data format** that can
//! serialize any data structure supported by Serde.
//!
//! # The Serialize trait
//!
//! Serde provides `Serialize` implementations for many Rust primitive and
//! standard library types. The complete list is below. All of these can be
//! serialized using Serde out of the box.
//!
//! Additionally, Serde provides a procedural macro called `serde_derive` to
//! automatically generate `Serialize` implementations for structs and enums in
//! your program. See the [codegen section of the manual][codegen] for how to
//! use this.
//!
//! In rare cases it may be necessary to implement `Serialize` manually for some
//! type in your program. See the [Implementing `Serialize`][impl-serialize]
//! section of the manual for more about this.
//!
//! Third-party crates may provide `Serialize` implementations for types that
//! they expose. For example the `linked-hash-map` crate provides a
//! `LinkedHashMap<K, V>` type that is serializable by Serde because the crate
//! provides an implementation of `Serialize` for it.
//!
//! # The Serializer trait
//!
//! `Serializer` implementations are provided by third-party crates, for example
//! [`serde_json`][serde_json], [`serde_yaml`][serde_yaml] and
//! [`bincode`][bincode].
//!
//! A partial list of well-maintained formats is given on the [Serde
//! website][data-formats].
//!
//! # Implementations of Serialize provided by Serde
//!
//! - **Primitive types**:
//! - bool
//! - isize, i8, i16, i32, i64
//! - usize, u8, u16, u32, u64
//! - f32, f64
//! - char
//! - str
//! - &T and &mut T
//! - **Compound types**:
//! - [T]
//! - [T; 0] through [T; 32]
//! - tuples up to size 16
//! - **Common standard library types**:
//! - String
//! - Option\<T\>
//! - Result\<T, E\>
//! - PhantomData\<T\>
//! - **Wrapper types**:
//! - Box\<T\>
//! - Rc\<T\>
//! - Arc\<T\>
//! - Cow\<'a, T\>
//! - **Collection types**:
//! - BTreeMap\<K, V\>
//! - BTreeSet\<T\>
//! - BinaryHeap\<T\>
//! - HashMap\<K, V, H\>
//! - HashSet\<T, H\>
//! - LinkedList\<T\>
//! - VecDeque\<T\>
//! - Vec\<T\>
//! - EnumSet\<T\> (unstable)
//! - Range\<T\> (unstable)
//! - RangeInclusive\<T\> (unstable)
//! - **Miscellaneous standard library types**:
//! - Duration
//! - Path
//! - PathBuf
//! - NonZero\<T\> (unstable)
//! - **Net types**:
//! - IpAddr
//! - Ipv4Addr
//! - Ipv6Addr
//! - SocketAddr
//! - SocketAddrV4
//! - SocketAddrV6
//!
//! [codegen]: https://serde.rs/codegen.html
//! [impl-serialize]: https://serde.rs/impl-serialize.html
//! [serde_json]: https://github.com/serde-rs/json
//! [serde_yaml]: https://github.com/dtolnay/serde-yaml
//! [bincode]: https://github.com/TyOverby/bincode
//! [data-formats]: https://serde.rs/#data-formats
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::error; use std::error;
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
use error; use error;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::String;
#[cfg(feature = "unstable")]
use core::marker::PhantomData;
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
use core::cell::RefCell; use core::cell::RefCell;
use core::fmt::Display; use core::fmt::Display;
pub mod impls; mod impls;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// `Error` is a trait that allows a `Serialize` to generically create a /// Trait used by `Serialize` implementations to generically construct errors
/// `Serializer` error. /// belonging to the `Serializer` against which they are currently running.
pub trait Error: Sized + error::Error { pub trait Error: Sized + error::Error {
/// Raised when there is a general error when serializing a type. /// Raised when a `Serialize` implementation encounters a general error
/// while serializing a type.
///
/// The message should not be capitalized and should not end with a period.
///
/// For example, a filesystem `Path` may refuse to serialize itself if it
/// contains invalid UTF-8 data.
///
/// ```rust
/// # use serde::ser::{Serialize, Serializer, Error};
/// # struct Path;
/// # impl Path { fn to_str(&self) -> Option<&str> { unimplemented!() } }
/// impl Serialize for Path {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// {
/// match self.to_str() {
/// Some(s) => s.serialize(serializer),
/// None => Err(Error::custom("path contains invalid UTF-8 characters")),
/// }
/// }
/// }
/// ```
fn custom<T: Display>(msg: T) -> Self; fn custom<T: Display>(msg: T) -> Self;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// A trait that describes a type that can be serialized by a `Serializer`. /// An implementation of this trait is a **data structure** that can be
/// serialized into any data format supported by Serde.
///
/// Serde provides `Serialize` implementations for many Rust primitive and
/// standard library types. The complete list is [here][ser]. All of these can
/// be serialized using Serde out of the box.
///
/// Additionally, Serde provides a procedural macro called `serde_derive` to
/// automatically generate `Serialize` implementations for structs and enums in
/// your program. See the [codegen section of the manual][codegen] for how to
/// use this.
///
/// In rare cases it may be necessary to implement `Serialize` manually for some
/// type in your program. See the [Implementing `Serialize`][impl-serialize]
/// section of the manual for more about this.
///
/// Third-party crates may provide `Serialize` implementations for types that
/// they expose. For example the `linked-hash-map` crate provides a
/// `LinkedHashMap<K, V>` type that is serializable by Serde because the crate
/// provides an implementation of `Serialize` for it.
///
/// [ser]: https://docs.serde.rs/serde/ser/index.html
/// [codegen]: https://serde.rs/codegen.html
/// [impl-serialize]: https://serde.rs/impl-serialize.html
pub trait Serialize { pub trait Serialize {
/// Serializes this value into this serializer. /// Serialize this value into the given Serde serializer.
///
/// See the [Implementing `Serialize`][impl-serialize] section of the manual
/// for more information about how to implement this method.
///
/// [impl-serialize]: https://serde.rs/impl-serialize.html
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer; where S: Serializer;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// A trait that describes a type that can serialize a stream of values into the underlying format. /// An implementation of this trait is a **data format** that can serialize any
/// data structure supported by Serde.
/// ///
/// # For `Serialize` Developers /// The role of this trait is to define the serialization half of the Serde data
/// Non-aggregate types like integers and strings can be serialized directly by calling the /// model, which is a way to categorize every Rust data structure into one of 28
/// appropriate function. For Aggregate types there's an initial `serialize_T` method that yields /// possible types. Each method of the `Serializer` trait corresponds to one of
/// a State object that you should not interact with. For each part of the aggregate there's a /// the types of the data model.
/// `serialize_T_elt` method that allows you to pass values or key/value pairs. The types of the
/// values or the keys may change between calls, but the serialization format may not necessarily
/// accept it. The `serialize_T_elt` method also takes a mutable reference to the state object.
/// Make sure that you always use the same state object and only the state object that was returned
/// by the `serialize_T` method. Finally, when your object is done, call the `serialize_T_end`
/// method and pass the state object by value
/// ///
/// # For Serialization Format Developers /// Implementations of `Serialize` map themselves into this data model by
/// If your format has different situations where it accepts different types, create a /// invoking exactly one of the `Serializer` methods.
/// `Serializer` for each situation. You can create the sub-`Serializer` in one of the aggregate ///
/// `serialize_T` methods and return it as a state object. Remember to also set the corresponding /// The types that make up the Serde data model are:
/// associated type `TState`. In the `serialize_T_elt` methods you will be given a mutable ///
/// reference to that state. You do not need to do any additional checks for the correctness of the /// - 12 primitive types:
/// state object, as it is expected that the user will not modify it. Due to the generic nature /// - bool
/// of the `Serialize` impls, modifying the object is impossible on stable Rust. /// - i8, i16, i32, i64
/// - u8, u16, u32, u64
/// - f32, f64
/// - char
/// - string
/// - byte array - [u8]
/// - option
/// - either none or some value
/// - unit
/// - unit is the type of () in Rust
/// - unit_struct
/// - for example `struct Unit` or `PhantomData<T>`
/// - unit_variant
/// - the `E::A` and `E::B` in `enum E { A, B }`
/// - newtype_struct
/// - for example `struct Millimeters(u8)`
/// - newtype_variant
/// - the `E::N` in `enum E { N(u8) }`
/// - seq
/// - a dynamically sized sequence of values, for example `Vec<T>` or
/// `HashSet<T>`
/// - seq_fixed_size
/// - a statically sized sequence of values for which the size will be known
/// at deserialization time without looking at the serialized data, for
/// example `[u64; 10]`
/// - tuple
/// - for example `(u8,)` or `(String, u64, Vec<T>)`
/// - tuple_struct
/// - for example `struct Rgb(u8, u8, u8)`
/// - tuple_variant
/// - the `E::T` in `enum E { T(u8, u8) }`
/// - map
/// - for example `BTreeMap<K, V>`
/// - struct
/// - a key-value pairing in which the keys will be known at deserialization
/// time without looking at the serialized data, for example `struct S { r:
/// u8, g: u8, b: u8 }`
/// - struct_variant
/// - the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`
///
/// Many Serde serializers produce text or binary data as output, for example
/// JSON or Bincode. This is not a requirement of the `Serializer` trait, and
/// there are serializers that do not produce text or binary output. One example
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
/// serializer) that produces a `serde_json::Value` data structure in memory as
/// output.
pub trait Serializer { pub trait Serializer {
/// Trickery to enforce correct use of the `Serialize` trait. Every /// The output type produced by this `Serializer` during successful
/// `Serializer` should set `Ok = ()`. /// serialization. Most serializers that produce text or binary output
/// should set `Ok = ()` and serialize into an `io::Write` or buffer
/// contained within the `Serializer` instance. Serializers that build
/// in-memory data structures may be simplified by using `Ok` to propagate
/// the data structure around.
type Ok; type Ok;
/// The error type when some error occurs during serialization. /// The error type when some error occurs during serialization.
@@ -104,75 +276,85 @@ pub trait Serializer {
/// content of the struct variant. /// content of the struct variant.
type SerializeStructVariant: SerializeStructVariant<Ok=Self::Ok, Error=Self::Error>; type SerializeStructVariant: SerializeStructVariant<Ok=Self::Ok, Error=Self::Error>;
/// Serializes a `bool` value. /// Serialize a `bool` value.
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error>; fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error>;
/// Serializes an `isize` value. If the format does not differentiate /// Serialize an `i8` value.
/// between `isize` and `i64`, a reasonable implementation would be to cast ///
/// the value to `i64` and forward to `serialize_i64`. /// If the format does not differentiate between `i8` and `i64`, a
fn serialize_isize(self, v: isize) -> Result<Self::Ok, Self::Error>; /// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
/// Serializes an `i8` value. If the format does not differentiate between
/// `i8` and `i64`, a reasonable implementation would be to cast the value
/// to `i64` and forward to `serialize_i64`.
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error>; fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error>;
/// Serializes an `i16` value. If the format does not differentiate between /// Serialize an `i16` value.
/// `i16` and `i64`, a reasonable implementation would be to cast the value ///
/// to `i64` and forward to `serialize_i64`. /// If the format does not differentiate between `i16` and `i64`, a
/// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error>; fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error>;
/// Serializes an `i32` value. If the format does not differentiate between /// Serialize an `i32` value.
/// `i32` and `i64`, a reasonable implementation would be to cast the value ///
/// to `i64` and forward to `serialize_i64`. /// If the format does not differentiate between `i32` and `i64`, a
/// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`.
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error>; fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error>;
/// Serializes an `i64` value. /// Serialize an `i64` value.
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>; fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
/// Serializes a `usize` value. If the format does not differentiate between /// Serialize a `u8` value.
/// `usize` and `u64`, a reasonable implementation would be to cast the ///
/// value to `u64` and forward to `serialize_u64`. /// If the format does not differentiate between `u8` and `u64`, a
fn serialize_usize(self, v: usize) -> Result<Self::Ok, Self::Error>; /// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
/// Serializes a `u8` value. If the format does not differentiate between
/// `u8` and `u64`, a reasonable implementation would be to cast the value
/// to `u64` and forward to `serialize_u64`.
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error>; fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error>;
/// Serializes a `u16` value. If the format does not differentiate between /// Serialize a `u16` value.
/// `u16` and `u64`, a reasonable implementation would be to cast the value ///
/// to `u64` and forward to `serialize_u64`. /// If the format does not differentiate between `u16` and `u64`, a
/// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error>; fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error>;
/// Serializes a `u32` value. If the format does not differentiate between /// Serialize a `u32` value.
/// `u32` and `u64`, a reasonable implementation would be to cast the value ///
/// to `u64` and forward to `serialize_u64`. /// If the format does not differentiate between `u32` and `u64`, a
/// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`.
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error>; fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error>;
/// `Serializes a `u64` value. /// Serialize a `u64` value.
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>; fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
/// Serializes an `f32` value. If the format does not differentiate between /// Serialize an `f32` value.
/// `f32` and `f64`, a reasonable implementation would be to cast the value ///
/// to `f64` and forward to `serialize_f64`. /// If the format does not differentiate between `f32` and `f64`, a
/// reasonable implementation would be to cast the value to `f64` and
/// forward to `serialize_f64`.
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error>; fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error>;
/// Serializes an `f64` value. /// Serialize an `f64` value.
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error>; fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error>;
/// Serializes a character. If the format does not support characters, /// Serialize a character.
/// it is reasonable to serialize it as a single element `str` or a `u32`. ///
/// If the format does not support characters, it is reasonable to serialize
/// it as a single element `str` or a `u32`.
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error>; fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error>;
/// Serializes a `&str`. /// Serialize a `&str`.
fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error>; fn serialize_str(self, value: &str) -> Result<Self::Ok, Self::Error>;
/// Serialize a chunk of raw byte data.
///
/// Enables serializers to serialize byte slices more compactly or more /// Enables serializers to serialize byte slices more compactly or more
/// efficiently than other types of slices. If no efficient implementation /// efficiently than other types of slices. If no efficient implementation
/// is available, a reasonable implementation would be to forward to /// is available, a reasonable implementation would be to forward to
/// `serialize_seq`. If forwarded, the implementation looks usually just like this: /// `serialize_seq`. If forwarded, the implementation looks usually just
/// ```rust /// like this:
///
/// ```rust,ignore
/// let mut seq = self.serialize_seq(Some(value.len()))?; /// let mut seq = self.serialize_seq(Some(value.len()))?;
/// for b in value { /// for b in value {
/// seq.serialize_element(b)?; /// seq.serialize_element(b)?;
@@ -181,19 +363,40 @@ pub trait Serializer {
/// ``` /// ```
fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error>; fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error>;
/// Serializes a `()` value. It's reasonable to just not serialize anything. /// Serialize a `None` value.
fn serialize_none(self) -> Result<Self::Ok, Self::Error>;
/// Serialize a `Some(T)` value.
fn serialize_some<T: ?Sized + Serialize>(
self,
value: &T,
) -> Result<Self::Ok, Self::Error>;
/// Serialize a `()` value.
fn serialize_unit(self) -> Result<Self::Ok, Self::Error>; fn serialize_unit(self) -> Result<Self::Ok, Self::Error>;
/// Serializes a unit struct value. A reasonable implementation would be to /// Serialize a unit struct like `struct Unit` or `PhantomData<T>`.
/// forward to `serialize_unit`. ///
/// A reasonable implementation would be to forward to `serialize_unit`.
fn serialize_unit_struct( fn serialize_unit_struct(
self, self,
name: &'static str, name: &'static str,
) -> Result<Self::Ok, Self::Error>; ) -> Result<Self::Ok, Self::Error>;
/// Serializes a unit variant, otherwise known as a variant with no /// Serialize a unit variant like `E::A` in `enum E { A, B }`.
/// arguments. A reasonable implementation would be to forward to ///
/// `serialize_unit`. /// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, and the `variant` is the name of the
/// variant.
///
/// A reasonable implementation would be to forward to `serialize_unit`.
///
/// ```rust,ignore
/// match *self {
/// E::A => serializer.serialize_unit_variant("E", 0, "A"),
/// E::B => serializer.serialize_unit_variant("E", 1, "B"),
/// }
/// ```
fn serialize_unit_variant( fn serialize_unit_variant(
self, self,
name: &'static str, name: &'static str,
@@ -201,74 +404,130 @@ pub trait Serializer {
variant: &'static str, variant: &'static str,
) -> Result<Self::Ok, Self::Error>; ) -> Result<Self::Ok, Self::Error>;
/// Allows a tuple struct with a single element, also known as a newtype /// Serialize a newtype struct like `struct Millimeters(u8)`.
/// struct, to be more efficiently serialized than a tuple struct with ///
/// multiple items. A reasonable implementation would be to forward to /// Serializers are encouraged to treat newtype structs as insignificant
/// `serialize_tuple_struct` or to just serialize the inner value without wrapping. /// wrappers around the data they contain. A reasonable implementation would
fn serialize_newtype_struct<T: Serialize>( /// be to forward to `value.serialize(self)`.
///
/// ```rust,ignore
/// serializer.serialize_newtype_struct("Millimeters", &self.0)
/// ```
fn serialize_newtype_struct<T: ?Sized + Serialize>(
self, self,
name: &'static str, name: &'static str,
value: T, value: &T,
) -> Result<Self::Ok, Self::Error>; ) -> Result<Self::Ok, Self::Error>;
/// Allows a variant with a single item to be more efficiently serialized /// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`.
/// than a variant with multiple items. A reasonable implementation would be ///
/// to forward to `serialize_tuple_variant`. /// The `name` is the name of the enum, the `variant_index` is the index of
fn serialize_newtype_variant<T: Serialize>( /// this variant within the enum, and the `variant` is the name of the
/// variant. The `value` is the data contained within this newtype variant.
///
/// ```rust,ignore
/// match *self {
/// E::N(ref n) => serializer.serialize_newtype_variant("E", 0, "N", n),
/// }
/// ```
fn serialize_newtype_variant<T: ?Sized + Serialize>(
self, self,
name: &'static str, name: &'static str,
variant_index: usize, variant_index: usize,
variant: &'static str, variant: &'static str,
value: T, value: &T,
) -> Result<Self::Ok, Self::Error>; ) -> Result<Self::Ok, Self::Error>;
/// Serializes a `None` value. /// Begin to serialize a dynamically sized sequence. This call must be
fn serialize_none(self) -> Result<Self::Ok, Self::Error>; /// followed by zero or more calls to `serialize_element`, then a call to
/// `end`.
/// Serializes a `Some(...)` value. ///
fn serialize_some<T: Serialize>( /// The argument is the number of elements in the sequence, which may or may
self, /// not be computable before the sequence is iterated. Some serializers only
value: T, /// support sequences whose length is known up front.
) -> Result<Self::Ok, Self::Error>; ///
/// ```rust,ignore
/// Begins to serialize a sequence. This call must be followed by zero or /// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// more calls to `serialize_seq_elt`, then a call to `serialize_seq_end`. /// for element in self {
/// seq.serialize_element(element)?;
/// }
/// seq.end()
/// ```
fn serialize_seq( fn serialize_seq(
self, self,
len: Option<usize>, len: Option<usize>,
) -> Result<Self::SerializeSeq, Self::Error>; ) -> Result<Self::SerializeSeq, Self::Error>;
/// Begins to serialize a sequence whose length will be known at /// Begin to serialize a statically sized sequence whose length will be
/// deserialization time. This call must be followed by zero or more calls /// known at deserialization time without looking at the serialized data.
/// to `serialize_seq_elt`, then a call to `serialize_seq_end`. A reasonable /// This call must be followed by zero or more calls to `serialize_element`,
/// implementation would be to forward to `serialize_seq`. /// then a call to `end`.
///
/// ```rust,ignore
/// let mut seq = serializer.serialize_seq_fixed_size(self.len())?;
/// for element in self {
/// seq.serialize_element(element)?;
/// }
/// seq.end()
/// ```
fn serialize_seq_fixed_size( fn serialize_seq_fixed_size(
self, self,
size: usize, size: usize,
) -> Result<Self::SerializeSeq, Self::Error>; ) -> Result<Self::SerializeSeq, Self::Error>;
/// Begins to serialize a tuple. This call must be followed by zero or more /// Begin to serialize a tuple. This call must be followed by zero or more
/// calls to `serialize_tuple_elt`, then a call to `serialize_tuple_end`. A /// calls to `serialize_field`, then a call to `end`.
/// reasonable implementation would be to forward to `serialize_seq`. ///
/// ```rust,ignore
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_field(&self.0)?;
/// tup.serialize_field(&self.1)?;
/// tup.serialize_field(&self.2)?;
/// tup.end()
/// ```
fn serialize_tuple( fn serialize_tuple(
self, self,
len: usize, len: usize,
) -> Result<Self::SerializeTuple, Self::Error>; ) -> Result<Self::SerializeTuple, Self::Error>;
/// Begins to serialize a tuple struct. This call must be followed by zero /// Begin to serialize a tuple struct like `struct Rgb(u8, u8, u8)`. This
/// or more calls to `serialize_tuple_struct_elt`, then a call to /// call must be followed by zero or more calls to `serialize_field`, then a
/// `serialize_tuple_struct_end`. A reasonable implementation would be to /// call to `end`.
/// forward to `serialize_tuple`. ///
/// The `name` is the name of the tuple struct and the `len` is the number
/// of data fields that will be serialized.
///
/// ```rust,ignore
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?;
/// ts.serialize_field(&self.1)?;
/// ts.serialize_field(&self.2)?;
/// ts.end()
/// ```
fn serialize_tuple_struct( fn serialize_tuple_struct(
self, self,
name: &'static str, name: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error>; ) -> Result<Self::SerializeTupleStruct, Self::Error>;
/// Begins to serialize a tuple variant. This call must be followed by zero /// Begin to serialize a tuple variant like `E::T` in `enum E { T(u8, u8)
/// or more calls to `serialize_tuple_variant_elt`, then a call to /// }`. This call must be followed by zero or more calls to
/// `serialize_tuple_variant_end`. A reasonable implementation would be to /// `serialize_field`, then a call to `end`.
/// forward to `serialize_tuple_struct`. ///
/// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized.
///
/// ```rust,ignore
/// match *self {
/// E::T(ref a, ref b) => {
/// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?;
/// tv.serialize_field(a)?;
/// tv.serialize_field(b)?;
/// tv.end()
/// }
/// }
/// ```
fn serialize_tuple_variant( fn serialize_tuple_variant(
self, self,
name: &'static str, name: &'static str,
@@ -277,25 +536,64 @@ pub trait Serializer {
len: usize, len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error>; ) -> Result<Self::SerializeTupleVariant, Self::Error>;
/// Begins to serialize a map. This call must be followed by zero or more /// Begin to serialize a map. This call must be followed by zero or more
/// calls to `serialize_map_key` and `serialize_map_value`, then a call to /// calls to `serialize_key` and `serialize_value`, then a call to `end`.
/// `serialize_map_end`. ///
/// The argument is the number of elements in the map, which may or may not
/// be computable before the map is iterated. Some serializers only support
/// maps whose length is known up front.
///
/// ```rust,ignore
/// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self {
/// map.serialize_entry(k, v)?;
/// }
/// map.end()
/// ```
fn serialize_map( fn serialize_map(
self, self,
len: Option<usize>, len: Option<usize>,
) -> Result<Self::SerializeMap, Self::Error>; ) -> Result<Self::SerializeMap, Self::Error>;
/// Begins to serialize a struct. This call must be followed by zero or more /// Begin to serialize a struct like `struct Rgb { r: u8, g: u8, b: u8 }`.
/// calls to `serialize_struct_elt`, then a call to `serialize_struct_end`. /// This call must be followed by zero or more calls to `serialize_field`,
/// then a call to `end`.
///
/// The `name` is the name of the struct and the `len` is the number of
/// data fields that will be serialized.
///
/// ```rust,ignore
/// let mut struc = serializer.serialize_struct("Rgb", 3)?;
/// struc.serialize_field("r", &self.r)?;
/// struc.serialize_field("g", &self.g)?;
/// struc.serialize_field("b", &self.b)?;
/// struc.end()
/// ```
fn serialize_struct( fn serialize_struct(
self, self,
name: &'static str, name: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeStruct, Self::Error>; ) -> Result<Self::SerializeStruct, Self::Error>;
/// Begins to serialize a struct variant. This call must be followed by zero /// Begin to serialize a struct variant like `E::S` in `enum E { S { r: u8,
/// or more calls to `serialize_struct_variant_elt`, then a call to /// g: u8, b: u8 } }`. This call must be followed by zero or more calls to
/// `serialize_struct_variant_end`. /// `serialize_field`, then a call to `end`.
///
/// The `name` is the name of the enum, the `variant_index` is the index of
/// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized.
///
/// ```rust,ignore
/// match *self {
/// E::S { ref r, ref g, ref b } => {
/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?;
/// sv.serialize_field("r", r)?;
/// sv.serialize_field("g", g)?;
/// sv.serialize_field("b", b)?;
/// sv.end()
/// }
/// }
/// ```
fn serialize_struct_variant( fn serialize_struct_variant(
self, self,
name: &'static str, name: &'static str,
@@ -307,130 +605,209 @@ pub trait Serializer {
/// Returned from `Serializer::serialize_seq` and /// Returned from `Serializer::serialize_seq` and
/// `Serializer::serialize_seq_fixed_size`. /// `Serializer::serialize_seq_fixed_size`.
///
/// ```rust,ignore
/// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self {
/// seq.serialize_element(element)?;
/// }
/// seq.end()
/// ```
pub trait SerializeSeq { pub trait SerializeSeq {
/// Trickery to enforce correct use of the `Serialize` trait. Every /// Must match the `Ok` type of our `Serializer`.
/// `SerializeSeq` should set `Ok = ()`.
type Ok; type Ok;
/// The error type when some error occurs during serialization. /// Must match the `Error` type of our `Serializer`.
type Error: Error; type Error: Error;
/// Serializes a sequence element. /// Serialize a sequence element.
fn serialize_element<T: Serialize>(&mut self, value: T) -> Result<(), Self::Error>; fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finishes serializing a sequence. /// Finish serializing a sequence.
fn end(self) -> Result<Self::Ok, Self::Error>; fn end(self) -> Result<Self::Ok, Self::Error>;
} }
/// Returned from `Serializer::serialize_tuple`. /// Returned from `Serializer::serialize_tuple`.
///
/// ```rust,ignore
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_field(&self.0)?;
/// tup.serialize_field(&self.1)?;
/// tup.serialize_field(&self.2)?;
/// tup.end()
/// ```
pub trait SerializeTuple { pub trait SerializeTuple {
/// Trickery to enforce correct use of the `Serialize` trait. Every /// Must match the `Ok` type of our `Serializer`.
/// `SerializeTuple` should set `Ok = ()`.
type Ok; type Ok;
/// The error type when some error occurs during serialization. /// Must match the `Error` type of our `Serializer`.
type Error: Error; type Error: Error;
/// Serializes a tuple element. /// Serialize a tuple element.
fn serialize_element<T: Serialize>(&mut self, value: T) -> Result<(), Self::Error>; fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finishes serializing a tuple. /// Finish serializing a tuple.
fn end(self) -> Result<Self::Ok, Self::Error>; fn end(self) -> Result<Self::Ok, Self::Error>;
} }
/// Returned from `Serializer::serialize_tuple_struct`. /// Returned from `Serializer::serialize_tuple_struct`.
///
/// ```rust,ignore
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?;
/// ts.serialize_field(&self.1)?;
/// ts.serialize_field(&self.2)?;
/// ts.end()
/// ```
pub trait SerializeTupleStruct { pub trait SerializeTupleStruct {
/// Trickery to enforce correct use of the `Serialize` trait. Every /// Must match the `Ok` type of our `Serializer`.
/// `SerializeTupleStruct` should set `Ok = ()`.
type Ok; type Ok;
/// The error type when some error occurs during serialization. /// Must match the `Error` type of our `Serializer`.
type Error: Error; type Error: Error;
/// Serializes a tuple struct element. /// Serialize a tuple struct field.
fn serialize_field<T: Serialize>(&mut self, value: T) -> Result<(), Self::Error>; fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finishes serializing a tuple struct. /// Finish serializing a tuple struct.
fn end(self) -> Result<Self::Ok, Self::Error>; fn end(self) -> Result<Self::Ok, Self::Error>;
} }
/// Returned from `Serializer::serialize_tuple_variant`. /// Returned from `Serializer::serialize_tuple_variant`.
///
/// ```rust,ignore
/// match *self {
/// E::T(ref a, ref b) => {
/// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?;
/// tv.serialize_field(a)?;
/// tv.serialize_field(b)?;
/// tv.end()
/// }
/// }
/// ```
pub trait SerializeTupleVariant { pub trait SerializeTupleVariant {
/// Trickery to enforce correct use of the `Serialize` trait. Every /// Must match the `Ok` type of our `Serializer`.
/// `SerializeTupleVariant` should set `Ok = ()`.
type Ok; type Ok;
/// The error type when some error occurs during serialization. /// Must match the `Error` type of our `Serializer`.
type Error: Error; type Error: Error;
/// Serializes a tuple variant element. /// Serialize a tuple variant field.
fn serialize_field<T: Serialize>(&mut self, value: T) -> Result<(), Self::Error>; fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finishes serializing a tuple variant. /// Finish serializing a tuple variant.
fn end(self) -> Result<Self::Ok, Self::Error>; fn end(self) -> Result<Self::Ok, Self::Error>;
} }
/// Returned from `Serializer::serialize_map`. /// Returned from `Serializer::serialize_map`.
///
/// ```rust,ignore
/// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self {
/// map.serialize_entry(k, v)?;
/// }
/// map.end()
/// ```
pub trait SerializeMap { pub trait SerializeMap {
/// Trickery to enforce correct use of the `Serialize` trait. Every /// Must match the `Ok` type of our `Serializer`.
/// `SerializeMap` should set `Ok = ()`.
type Ok; type Ok;
/// The error type when some error occurs during serialization. /// Must match the `Error` type of our `Serializer`.
type Error: Error; type Error: Error;
/// Serialize a map key. /// Serialize a map key.
fn serialize_key<T: Serialize>(&mut self, key: T) -> Result<(), Self::Error>; fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), Self::Error>;
/// Serialize a map value. /// Serialize a map value.
fn serialize_value<T: Serialize>(&mut self, value: T) -> Result<(), Self::Error>; fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), Self::Error>;
/// Finishes serializing a map. /// Serialize a map entry consisting of a key and a value.
///
/// Some `Serialize` types are not able to hold a key and value in memory at
/// the same time so `SerializeMap` implementations are required to support
/// `serialize_key` and `serialize_value` individually. The
/// `serialize_entry` method allows serializers to optimize for the case
/// where key and value are both available. `Serialize` implementations are
/// encouraged to use `serialize_entry` if possible.
///
/// The default implementation delegates to `serialize_key` and
/// `serialize_value`. This is appropriate for serializers that do not care
/// about performance or are not able to optimize `serialize_entry` any
/// better than this.
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(
&mut self,
key: &K,
value: &V,
) -> Result<(), Self::Error> {
try!(self.serialize_key(key));
self.serialize_value(value)
}
/// Finish serializing a map.
fn end(self) -> Result<Self::Ok, Self::Error>; fn end(self) -> Result<Self::Ok, Self::Error>;
} }
/// Returned from `Serializer::serialize_struct`. /// Returned from `Serializer::serialize_struct`.
///
/// ```rust,ignore
/// let mut struc = serializer.serialize_struct("Rgb", 3)?;
/// struc.serialize_field("r", &self.r)?;
/// struc.serialize_field("g", &self.g)?;
/// struc.serialize_field("b", &self.b)?;
/// struc.end()
/// ```
pub trait SerializeStruct { pub trait SerializeStruct {
/// Trickery to enforce correct use of the `Serialize` trait. Every /// Must match the `Ok` type of our `Serializer`.
/// `SerializeStruct` should set `Ok = ()`.
type Ok; type Ok;
/// The error type when some error occurs during serialization. /// Must match the `Error` type of our `Serializer`.
type Error: Error; type Error: Error;
/// Serializes a struct field. /// Serialize a struct field.
fn serialize_field<V: Serialize>(&mut self, key: &'static str, value: V) -> Result<(), Self::Error>; fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>;
/// Finishes serializing a struct. /// Finish serializing a struct.
fn end(self) -> Result<Self::Ok, Self::Error>; fn end(self) -> Result<Self::Ok, Self::Error>;
} }
/// Returned from `Serializer::serialize_struct_variant`. /// Returned from `Serializer::serialize_struct_variant`.
///
/// ```rust,ignore
/// match *self {
/// E::S { ref r, ref g, ref b } => {
/// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?;
/// sv.serialize_field("r", r)?;
/// sv.serialize_field("g", g)?;
/// sv.serialize_field("b", b)?;
/// sv.end()
/// }
/// }
/// ```
pub trait SerializeStructVariant { pub trait SerializeStructVariant {
/// Trickery to enforce correct use of the `Serialize` trait. Every /// Must match the `Ok` type of our `Serializer`.
/// `SerializeStructVariant` should set `Ok = ()`.
type Ok; type Ok;
/// The error type when some error occurs during serialization. /// Must match the `Error` type of our `Serializer`.
type Error: Error; type Error: Error;
/// Serialize a struct variant element. /// Serialize a struct variant field.
fn serialize_field<V: Serialize>(&mut self, key: &'static str, value: V) -> Result<(), Self::Error>; fn serialize_field<T: ?Sized + Serialize>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>;
/// Finishes serializing a struct variant. /// Finish serializing a struct variant.
fn end(self) -> Result<Self::Ok, Self::Error>; fn end(self) -> Result<Self::Ok, Self::Error>;
} }
/// A wrapper type for iterators that implements `Serialize` for iterators whose items implement /// A wrapper type for iterators that implements `Serialize` for iterators whose
/// `Serialize`. Don't use multiple times. Create new versions of this with the `iterator` function /// items implement `Serialize`. Don't use multiple times. Create new versions
/// every time you want to serialize an iterator. /// of this with the `serde::ser::iterator` function every time you want to
/// serialize an iterator.
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
pub struct Iterator<I>(RefCell<Option<I>>) pub struct Iterator<I>(RefCell<Option<I>>)
where <I as IntoIterator>::Item: Serialize, where <I as IntoIterator>::Item: Serialize,
I: IntoIterator; I: IntoIterator;
/// Creates a temporary type that can be passed to any function expecting a `Serialize` and will /// Create a wrapper type that can be passed to any function expecting a
/// serialize the given iterator as a sequence /// `Serialize` and will serialize the given iterator as a sequence.
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
pub fn iterator<I>(iter: I) -> Iterator<I> pub fn iterator<I>(iter: I) -> Iterator<I>
where <I as IntoIterator>::Item: Serialize, where <I as IntoIterator>::Item: Serialize,
-29
View File
@@ -1,29 +0,0 @@
[package]
name = "serde_codegen"
version = "0.9.0-rc2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
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"]
[features]
default = ["with-syntex"]
unstable = []
unstable-testing = ["clippy"]
with-syntex = [
"syntex",
"syntex_syntax",
]
with-syn = []
[dependencies]
clippy = { version = "^0.*", optional = true }
quote = "0.3.8"
serde_codegen_internals = { version = "=0.11.3", default-features = false, path = "../serde_codegen_internals" }
syn = { version = "0.10", features = ["aster", "visit"] }
syntex = { version = "^0.54.0", optional = true }
syntex_syntax = { version = "^0.54.0", optional = true }
-172
View File
@@ -1,172 +0,0 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate serde_codegen_internals as internals;
#[cfg(feature = "with-syntex")]
extern crate syntex;
#[cfg(feature = "with-syntex")]
#[macro_use]
extern crate syntex_syntax as syntax;
extern crate syn;
#[macro_use]
extern crate quote;
#[cfg(feature = "with-syntex")]
use std::path::Path;
mod bound;
mod de;
mod ser;
#[cfg(feature = "with-syntex")]
fn syntex_registry() -> syntex::Registry {
use syntax::{ast, fold};
/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
/// Helper folder that strips the serde attributes after the extensions have been expanded.
struct StripAttributeFolder;
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
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", shim::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg
}
#[cfg(feature = "with-syntex")]
pub fn expand_str(src: &str) -> Result<String, syntex::Error> {
let src = src.to_owned();
let expand_thread = move || {
syntex_registry().expand_str("", "", &src)
};
syntex::with_extra_stack(expand_thread)
}
#[cfg(feature = "with-syntex")]
pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let src = src.as_ref().to_owned();
let dst = dst.as_ref().to_owned();
let expand_thread = move || {
syntex_registry().expand("", src, dst)
};
syntex::with_extra_stack(expand_thread)
}
macro_rules! shim {
($name:ident $pkg:ident :: $func:ident) => {
pub fn $func(
cx: &mut ::syntax::ext::base::ExtCtxt,
span: ::syntax::codemap::Span,
meta_item: &::syntax::ast::MetaItem,
annotatable: &::syntax::ext::base::Annotatable,
push: &mut FnMut(::syntax::ext::base::Annotatable)
) {
let item = match *annotatable {
::syntax::ext::base::Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
concat!("`#[derive(",
stringify!($name),
")]` may only be applied to structs and enums"));
return;
}
};
use syntax::{attr, ast, visit};
struct MarkSerdeAttributesUsed;
impl<'a> visit::Visitor<'a> for MarkSerdeAttributesUsed {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
if attr.value.name == "serde" {
if let ast::MetaItemKind::List(..) = attr.value.node {
attr::mark_used(attr);
}
}
}
}
visit::walk_item(&mut MarkSerdeAttributesUsed, item);
use syntax::print::pprust;
let s = pprust::item_to_string(item);
use {syn, $pkg};
let syn_item = syn::parse_macro_input(&s).unwrap();
let expanded = match $pkg::$func(&syn_item) {
Ok(expanded) => expanded.to_string(),
Err(msg) => {
cx.span_err(span, &msg);
return;
}
};
use syntax::parse;
let name = stringify!($name).to_string();
let sess = cx.parse_sess;
let impl_item = parse::parse_item_from_source_str(name, expanded, sess);
push(::syntax::ext::base::Annotatable::Item(impl_item.unwrap().unwrap()));
}
};
}
#[cfg(feature = "with-syntex")]
mod shim {
shim!(Serialize ser::expand_derive_serialize);
shim!(Deserialize de::expand_derive_deserialize);
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_serialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
ser::expand_derive_serialize(&syn_item)
}
#[cfg(feature = "with-syn")]
#[doc(hidden)]
/// Not public API. Use the serde_derive crate.
pub fn expand_derive_deserialize(item: &str) -> Result<quote::Tokens, String> {
let syn_item = syn::parse_macro_input(item).unwrap();
de::expand_derive_deserialize(&syn_item)
}
+6 -3
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_codegen_internals" name = "serde_codegen_internals"
version = "0.11.3" version = "0.12.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."
@@ -14,5 +14,8 @@ include = ["Cargo.toml", "src/**/*.rs"]
unstable-testing = ["clippy"] unstable-testing = ["clippy"]
[dependencies] [dependencies]
clippy = { version = "^0.*", optional = true } clippy = { version = "0.*", optional = true }
syn = "0.10" syn = "0.11"
[badges]
travis-ci = { repository = "serde-rs/serde" }
+4 -4
View File
@@ -149,7 +149,7 @@ impl Item {
} }
Literal(_) => { Literal(_) => {
cx.error(format!("unexpected literal in serde container attribute")); cx.error("unexpected literal in serde container attribute");
} }
} }
} }
@@ -231,7 +231,7 @@ impl Variant {
} }
Literal(_) => { Literal(_) => {
cx.error(format!("unexpected literal in serde variant attribute")); cx.error("unexpected literal in serde variant attribute");
} }
} }
} }
@@ -390,7 +390,7 @@ impl Field {
} }
Literal(_) => { Literal(_) => {
cx.error(format!("unexpected literal in serde field attribute")); cx.error("unexpected literal in serde field attribute");
} }
} }
} }
@@ -404,7 +404,7 @@ impl Field {
Field { Field {
name: Name { name: Name {
serialize: ser_name.get().unwrap_or(ident.clone()), serialize: ser_name.get().unwrap_or_else(|| ident.clone()),
deserialize: de_name.get().unwrap_or(ident), deserialize: de_name.get().unwrap_or(ident),
}, },
skip_serializing: skip_serializing.get(), skip_serializing: skip_serializing.get(),
+13 -12
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "0.9.0-rc2" version = "0.9.3"
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 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -10,18 +10,19 @@ documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable = []
unstable-testing = ["clippy", "serde_codegen_internals/unstable-testing"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
[lib] [lib]
name = "serde_derive" name = "serde_derive"
proc-macro = true proc-macro = true
[dependencies.serde_codegen] [dependencies]
version = "=0.9.0-rc2" clippy = { version = "0.*", optional = true }
path = "../serde_codegen" quote = "0.3.8"
default-features = false serde_codegen_internals = { version = "=0.12.0", default-features = false, path = "../serde_codegen_internals" }
features = ["with-syn"] syn = { version = "0.11", features = ["aster", "visit"] }
[dev-dependencies]
compiletest_rs = "^0.2.0"
fnv = "1.0"
serde = { version = "0.9.0-rc2", path = "../serde" }
serde_test = { version = "0.9.0-rc2", path = "../serde_test" }
@@ -1,5 +1,5 @@
use syn::{self, aster, Ident}; use syn::{self, aster, Ident};
use quote::Tokens; use quote::{self, Tokens};
use bound; use bound;
use internals::ast::{Body, Field, Item, Style, Variant}; use internals::ast::{Body, Field, Item, Style, Variant};
@@ -7,7 +7,7 @@ use internals::{self, attr};
use std::iter; use std::iter;
pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Result<Tokens, String> { pub fn expand_derive_deserialize(item: &syn::DeriveInput) -> Result<Tokens, String> {
let item = { let item = {
let ctxt = internals::Ctxt::new(); let ctxt = internals::Ctxt::new();
let item = Item::from_ast(&ctxt, item); let item = Item::from_ast(&ctxt, item);
@@ -36,7 +36,7 @@ pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Result<Tokens, Strin
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl #impl_generics _serde::Deserialize for #ty #where_clause { impl #impl_generics _serde::Deserialize for #ty #where_clause {
fn deserialize<__D>(deserializer: __D) -> ::std::result::Result<#ty, __D::Error> fn deserialize<__D>(deserializer: __D) -> _serde::export::Result<#ty, __D::Error>
where __D: _serde::Deserializer where __D: _serde::Deserializer
#body #body
} }
@@ -158,11 +158,11 @@ fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) {
let phantom_types = generics.lifetimes.iter() let phantom_types = generics.lifetimes.iter()
.map(|lifetime_def| { .map(|lifetime_def| {
let lifetime = &lifetime_def.lifetime; let lifetime = &lifetime_def.lifetime;
quote!(::std::marker::PhantomData<& #lifetime ()>) quote!(_serde::export::PhantomData<& #lifetime ()>)
}).chain(generics.ty_params.iter() }).chain(generics.ty_params.iter()
.map(|ty_param| { .map(|ty_param| {
let ident = &ty_param.ident; let ident = &ty_param.ident;
quote!(::std::marker::PhantomData<#ident>) quote!(_serde::export::PhantomData<#ident>)
})); }));
let all_params = generics.lifetimes.iter() let all_params = generics.lifetimes.iter()
@@ -182,7 +182,7 @@ fn deserialize_visitor(generics: &syn::Generics) -> (Tokens, Tokens, Tokens) {
Some(quote!(::<#(#ty_param_idents),*>)) Some(quote!(::<#(#ty_param_idents),*>))
}; };
let phantom_exprs = iter::repeat(quote!(::std::marker::PhantomData)).take(num_phantoms); let phantom_exprs = iter::repeat(quote!(_serde::export::PhantomData)).take(num_phantoms);
( (
quote! { quote! {
@@ -208,19 +208,19 @@ fn deserialize_unit_struct(
impl _serde::de::Visitor for __Visitor { impl _serde::de::Visitor for __Visitor {
type Value = #type_ident; type Value = #type_ident;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str(#expecting) formatter.write_str(#expecting)
} }
#[inline] #[inline]
fn visit_unit<__E>(self) -> ::std::result::Result<#type_ident, __E> fn visit_unit<__E>(self) -> _serde::export::Result<#type_ident, __E>
where __E: _serde::de::Error, where __E: _serde::de::Error,
{ {
Ok(#type_ident) Ok(#type_ident)
} }
#[inline] #[inline]
fn visit_seq<__V>(self, _: __V) -> ::std::result::Result<#type_ident, __V::Error> fn visit_seq<__V>(self, _: __V) -> _serde::export::Result<#type_ident, __V::Error>
where __V: _serde::de::SeqVisitor, where __V: _serde::de::SeqVisitor,
{ {
Ok(#type_ident) Ok(#type_ident)
@@ -297,14 +297,14 @@ fn deserialize_tuple(
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause { impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
type Value = #ty; type Value = #ty;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str(#expecting) formatter.write_str(#expecting)
} }
#visit_newtype_struct #visit_newtype_struct
#[inline] #[inline]
fn visit_seq<__V>(self, #visitor_var: __V) -> ::std::result::Result<#ty, __V::Error> fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result<#ty, __V::Error>
where __V: _serde::de::SeqVisitor where __V: _serde::de::SeqVisitor
{ {
#visit_seq #visit_seq
@@ -408,7 +408,7 @@ fn deserialize_newtype_struct(
}; };
quote! { quote! {
#[inline] #[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> ::std::result::Result<Self::Value, __E::Error> fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer, where __E: _serde::Deserializer,
{ {
Ok(#type_path(#value)) Ok(#type_path(#value))
@@ -480,19 +480,19 @@ fn deserialize_struct(
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause { impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
type Value = #ty; type Value = #ty;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str(#expecting) formatter.write_str(#expecting)
} }
#[inline] #[inline]
fn visit_seq<__V>(self, #visitor_var: __V) -> ::std::result::Result<#ty, __V::Error> fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result<#ty, __V::Error>
where __V: _serde::de::SeqVisitor where __V: _serde::de::SeqVisitor
{ {
#visit_seq #visit_seq
} }
#[inline] #[inline]
fn visit_map<__V>(self, mut visitor: __V) -> ::std::result::Result<#ty, __V::Error> fn visit_map<__V>(self, mut visitor: __V) -> _serde::export::Result<#ty, __V::Error>
where __V: _serde::de::MapVisitor where __V: _serde::de::MapVisitor
{ {
#visit_map #visit_map
@@ -585,11 +585,11 @@ fn deserialize_item_enum(
impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause { impl #impl_generics _serde::de::Visitor for #visitor_ty #where_clause {
type Value = #ty; type Value = #ty;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str(#expecting) formatter.write_str(#expecting)
} }
fn visit_enum<__V>(self, visitor: __V) -> ::std::result::Result<#ty, __V::Error> fn visit_enum<__V>(self, visitor: __V) -> _serde::export::Result<#ty, __V::Error>
where __V: _serde::de::EnumVisitor, where __V: _serde::de::EnumVisitor,
{ {
#match_variant #match_variant
@@ -682,7 +682,8 @@ fn deserialize_field_visitor(
item_attrs: &attr::Item, item_attrs: &attr::Item,
is_variant: bool, is_variant: bool,
) -> Tokens { ) -> Tokens {
let field_names = fields.iter().map(|&(ref name, _)| name); let field_strs = fields.iter().map(|&(ref name, _)| name);
let field_bytes = fields.iter().map(|&(ref name, _)| quote::ByteStr(name));
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect(); let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect();
let ignore_variant = if is_variant || item_attrs.deny_unknown_fields() { let ignore_variant = if is_variant || item_attrs.deny_unknown_fields() {
@@ -691,6 +692,27 @@ fn deserialize_field_visitor(
Some(quote!(__ignore,)) Some(quote!(__ignore,))
}; };
let visit_index = if is_variant {
let variant_indices = 0u32..;
let fallthrough_msg = format!("variant index 0 <= i < {}", fields.len());
Some(quote! {
fn visit_u32<__E>(self, value: u32) -> _serde::export::Result<__Field, __E>
where __E: _serde::de::Error
{
match value {
#(
#variant_indices => Ok(__Field::#field_idents),
)*
_ => Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(value as u64),
&#fallthrough_msg))
}
}
})
} else {
None
};
let fallthrough_arm = if is_variant { let fallthrough_arm = if is_variant {
quote! { quote! {
Err(_serde::de::Error::unknown_variant(value, VARIANTS)) Err(_serde::de::Error::unknown_variant(value, VARIANTS))
@@ -705,6 +727,16 @@ fn deserialize_field_visitor(
} }
}; };
let bytes_to_str = if is_variant || item_attrs.deny_unknown_fields() {
Some(quote! {
// TODO https://github.com/serde-rs/serde/issues/666
// update this to use str::from_utf8(value).unwrap_or("") on no_std
let value = &_serde::export::from_utf8_lossy(value);
})
} else {
None
};
quote! { quote! {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
enum __Field { enum __Field {
@@ -714,7 +746,7 @@ fn deserialize_field_visitor(
impl _serde::Deserialize for __Field { impl _serde::Deserialize for __Field {
#[inline] #[inline]
fn deserialize<__D>(deserializer: __D) -> ::std::result::Result<__Field, __D::Error> fn deserialize<__D>(deserializer: __D) -> _serde::export::Result<__Field, __D::Error>
where __D: _serde::Deserializer, where __D: _serde::Deserializer,
{ {
struct __FieldVisitor; struct __FieldVisitor;
@@ -722,20 +754,36 @@ fn deserialize_field_visitor(
impl _serde::de::Visitor for __FieldVisitor { impl _serde::de::Visitor for __FieldVisitor {
type Value = __Field; type Value = __Field;
fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn expecting(&self, formatter: &mut _serde::export::fmt::Formatter) -> _serde::export::fmt::Result {
formatter.write_str("field name") formatter.write_str("field name")
} }
fn visit_str<__E>(self, value: &str) -> ::std::result::Result<__Field, __E> #visit_index
fn visit_str<__E>(self, value: &str) -> _serde::export::Result<__Field, __E>
where __E: _serde::de::Error where __E: _serde::de::Error
{ {
match value { match value {
#( #(
#field_names => Ok(__Field::#field_idents), #field_strs => Ok(__Field::#field_idents),
)* )*
_ => #fallthrough_arm _ => #fallthrough_arm
} }
} }
fn visit_bytes<__E>(self, value: &[u8]) -> _serde::export::Result<__Field, __E>
where __E: _serde::de::Error
{
match value {
#(
#field_bytes => Ok(__Field::#field_idents),
)*
_ => {
#bytes_to_str
#fallthrough_arm
}
}
}
} }
deserializer.deserialize_struct_field(__FieldVisitor) deserializer.deserialize_struct_field(__FieldVisitor)
@@ -933,18 +981,18 @@ fn wrap_deserialize_with(
quote! { quote! {
struct __SerdeDeserializeWithStruct #impl_generics #where_clause { struct __SerdeDeserializeWithStruct #impl_generics #where_clause {
value: #field_ty, value: #field_ty,
phantom: ::std::marker::PhantomData<#phantom_ty>, phantom: _serde::export::PhantomData<#phantom_ty>,
} }
}, },
quote! { quote! {
impl #impl_generics _serde::Deserialize for #wrapper_ty #where_clause { impl #impl_generics _serde::Deserialize for #wrapper_ty #where_clause {
fn deserialize<__D>(__d: __D) -> ::std::result::Result<Self, __D::Error> fn deserialize<__D>(__d: __D) -> _serde::export::Result<Self, __D::Error>
where __D: _serde::Deserializer where __D: _serde::Deserializer
{ {
let value = try!(#deserialize_with(__d)); let value = try!(#deserialize_with(__d));
Ok(__SerdeDeserializeWithStruct { Ok(__SerdeDeserializeWithStruct {
value: value, value: value,
phantom: ::std::marker::PhantomData, phantom: _serde::export::PhantomData,
}) })
} }
} }
@@ -956,7 +1004,7 @@ fn wrap_deserialize_with(
fn expr_is_missing(attrs: &attr::Field) -> Tokens { fn expr_is_missing(attrs: &attr::Field) -> Tokens {
match *attrs.default() { match *attrs.default() {
attr::FieldDefault::Default => { attr::FieldDefault::Default => {
return quote!(::std::default::Default::default()); return quote!(_serde::export::Default::default());
} }
attr::FieldDefault::Path(ref path) => { attr::FieldDefault::Path(ref path) => {
return quote!(#path()); return quote!(#path());
+22 -4
View File
@@ -1,11 +1,28 @@
extern crate proc_macro; #![cfg_attr(feature = "clippy", plugin(clippy))]
extern crate serde_codegen; #![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate serde_codegen_internals as internals;
extern crate proc_macro;
use proc_macro::TokenStream; use proc_macro::TokenStream;
mod bound;
mod de;
mod ser;
#[proc_macro_derive(Serialize, attributes(serde))] #[proc_macro_derive(Serialize, attributes(serde))]
pub fn derive_serialize(input: TokenStream) -> TokenStream { pub fn derive_serialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_serialize(&input.to_string()) { let input = syn::parse_derive_input(&input.to_string()).unwrap();
match ser::expand_derive_serialize(&input) {
Ok(expanded) => expanded.parse().unwrap(), Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg), Err(msg) => panic!(msg),
} }
@@ -13,7 +30,8 @@ pub fn derive_serialize(input: TokenStream) -> TokenStream {
#[proc_macro_derive(Deserialize, attributes(serde))] #[proc_macro_derive(Deserialize, attributes(serde))]
pub fn derive_deserialize(input: TokenStream) -> TokenStream { pub fn derive_deserialize(input: TokenStream) -> TokenStream {
match serde_codegen::expand_derive_deserialize(&input.to_string()) { let input = syn::parse_derive_input(&input.to_string()).unwrap();
match de::expand_derive_deserialize(&input) {
Ok(expanded) => expanded.parse().unwrap(), Ok(expanded) => expanded.parse().unwrap(),
Err(msg) => panic!(msg), Err(msg) => panic!(msg),
} }
@@ -5,7 +5,7 @@ use bound;
use internals::ast::{Body, Field, Item, Style, Variant}; use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{self, attr}; use internals::{self, attr};
pub fn expand_derive_serialize(item: &syn::MacroInput) -> Result<Tokens, String> { pub fn expand_derive_serialize(item: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new(); let ctxt = internals::Ctxt::new();
let item = Item::from_ast(&ctxt, item); let item = Item::from_ast(&ctxt, item);
try!(ctxt.check()); try!(ctxt.check());
@@ -30,7 +30,7 @@ pub fn expand_derive_serialize(item: &syn::MacroInput) -> Result<Tokens, String>
extern crate serde as _serde; extern crate serde as _serde;
#[automatically_derived] #[automatically_derived]
impl #impl_generics _serde::Serialize for #ty #where_clause { impl #impl_generics _serde::Serialize for #ty #where_clause {
fn serialize<__S>(&self, _serializer: __S) -> ::std::result::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, _serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where __S: _serde::Serializer
{ {
#body #body
@@ -541,14 +541,14 @@ fn wrap_serialize_with(
} }
impl #wrapper_generics _serde::Serialize for #wrapper_ty #where_clause { impl #wrapper_generics _serde::Serialize for #wrapper_ty #where_clause {
fn serialize<__S>(&self, __s: __S) -> ::std::result::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer where __S: _serde::Serializer
{ {
#path(self.value, __s) #path(self.value, __s)
} }
} }
__SerializeWith { &__SerializeWith {
value: #value, value: #value,
phantom: ::std::marker::PhantomData::<#item_ty>, phantom: ::std::marker::PhantomData::<#item_ty>,
} }
-30
View File
@@ -1,30 +0,0 @@
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_fail() {
run_mode("compile-fail");
}
#[test]
fn run_pass() {
run_mode("run-pass");
}
-10
View File
@@ -1,10 +0,0 @@
#![feature(test)]
#[macro_use]
extern crate serde_derive;
extern crate test;
include!("../../testing/tests/test.rs.in");
mod compile_tests;
+9 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "0.9.0-rc2" version = "0.9.3"
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"
@@ -11,5 +11,12 @@ readme = "../README.md"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable-testing = ["clippy"]
[dependencies] [dependencies]
serde = { version = "0.9.0-rc2", path = "../serde" } clippy = { version = "0.*", optional = true }
serde = { version = "0.9", path = "../serde" }
[badges]
travis-ci = { repository = "serde-rs/serde" }
+3 -21
View File
@@ -225,26 +225,16 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
where __V: de::Visitor { where __V: de::Visitor {
self.deserialize(visitor) self.deserialize(visitor)
} }
fn deserialize_usize<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_isize<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error> fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor, where V: Visitor,
{ {
match self.tokens.next() { match self.tokens.next() {
Some(Token::Bool(v)) => visitor.visit_bool(v), Some(Token::Bool(v)) => visitor.visit_bool(v),
Some(Token::Isize(v)) => visitor.visit_isize(v),
Some(Token::I8(v)) => visitor.visit_i8(v), Some(Token::I8(v)) => visitor.visit_i8(v),
Some(Token::I16(v)) => visitor.visit_i16(v), Some(Token::I16(v)) => visitor.visit_i16(v),
Some(Token::I32(v)) => visitor.visit_i32(v), Some(Token::I32(v)) => visitor.visit_i32(v),
Some(Token::I64(v)) => visitor.visit_i64(v), Some(Token::I64(v)) => visitor.visit_i64(v),
Some(Token::Usize(v)) => visitor.visit_usize(v),
Some(Token::U8(v)) => visitor.visit_u8(v), Some(Token::U8(v)) => visitor.visit_u8(v),
Some(Token::U16(v)) => visitor.visit_u16(v), Some(Token::U16(v)) => visitor.visit_u16(v),
Some(Token::U32(v)) => visitor.visit_u32(v), Some(Token::U32(v)) => visitor.visit_u32(v),
@@ -283,7 +273,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
where V: Visitor, where V: Visitor,
{ {
match self.tokens.peek() { match self.tokens.peek() {
Some(&Token::Option(false)) => { Some(&Token::Unit) | Some(&Token::Option(false)) => {
self.tokens.next(); self.tokens.next();
visitor.visit_none() visitor.visit_none()
} }
@@ -291,10 +281,6 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
self.tokens.next(); self.tokens.next();
visitor.visit_some(self) visitor.visit_some(self)
} }
Some(&Token::Unit) => {
self.tokens.next();
visitor.visit_none()
}
Some(_) => visitor.visit_some(self), Some(_) => visitor.visit_some(self),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
@@ -326,7 +312,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
let token = self.tokens.next().unwrap(); let token = self.tokens.next().unwrap();
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
None => { return Err(Error::EndOfTokens); } None => Err(Error::EndOfTokens),
} }
} }
@@ -387,11 +373,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
where V: Visitor, where V: Visitor,
{ {
match self.tokens.peek() { match self.tokens.peek() {
Some(&Token::Unit) => { Some(&Token::Unit) | Some(&Token::UnitStruct(_)) => {
self.tokens.next();
visitor.visit_unit()
}
Some(&Token::UnitStruct(_)) => {
self.tokens.next(); self.tokens.next();
visitor.visit_unit() visitor.visit_unit()
} }
+3
View File
@@ -1,3 +1,6 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
extern crate serde; extern crate serde;
mod assert; mod assert;
+18 -28
View File
@@ -46,11 +46,6 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
Ok(()) Ok(())
} }
fn serialize_isize(self, v: isize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Isize(v)));
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<(), Error> { fn serialize_i8(self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v))); assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
Ok(()) Ok(())
@@ -71,11 +66,6 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
Ok(()) Ok(())
} }
fn serialize_usize(self, v: usize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Usize(v)));
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<(), Error> { fn serialize_u8(self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v))); assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
Ok(()) Ok(())
@@ -139,20 +129,20 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
Ok(()) Ok(())
} }
fn serialize_newtype_struct<T>(self, fn serialize_newtype_struct<T: ?Sized>(self,
name: &'static str, name: &'static str,
value: T) -> Result<(), Error> value: &T) -> Result<(), Error>
where T: Serialize, where T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name))); assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
value.serialize(self) value.serialize(self)
} }
fn serialize_newtype_variant<T>(self, fn serialize_newtype_variant<T: ?Sized>(self,
name: &str, name: &str,
_variant_index: usize, _variant_index: usize,
variant: &str, variant: &str,
value: T) -> Result<(), Error> value: &T) -> Result<(), Error>
where T: Serialize, where T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant))); assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
@@ -164,8 +154,8 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
Ok(()) Ok(())
} }
fn serialize_some<V>(self, value: V) -> Result<(), Error> fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where V: Serialize, where T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::Option(true))); assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self) value.serialize(self)
@@ -228,7 +218,7 @@ impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I>
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_element<T>(&mut self, value: T) -> Result<(), Error> fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize where T: Serialize
{ {
assert_eq!(self.tokens.next(), Some(&Token::SeqSep)); assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
@@ -247,7 +237,7 @@ impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I>
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_element<T>(&mut self, value: T) -> Result<(), Error> fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize where T: Serialize
{ {
assert_eq!(self.tokens.next(), Some(&Token::TupleSep)); assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
@@ -266,7 +256,7 @@ impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I>
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_field<T>(&mut self, value: T) -> Result<(), Error> fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize where T: Serialize
{ {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep)); assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
@@ -285,7 +275,7 @@ impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I>
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_field<T>(&mut self, value: T) -> Result<(), Error> fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize where T: Serialize
{ {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep)); assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
@@ -304,12 +294,12 @@ impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I>
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_key<T>(&mut self, key: T) -> Result<(), Self::Error> where T: Serialize { fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::MapSep)); assert_eq!(self.tokens.next(), Some(&Token::MapSep));
key.serialize(&mut **self) key.serialize(&mut **self)
} }
fn serialize_value<T>(&mut self, value: T) -> Result<(), Self::Error> where T: Serialize { fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
value.serialize(&mut **self) value.serialize(&mut **self)
} }
@@ -325,7 +315,7 @@ impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I>
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_field<V>(&mut self, key: &'static str, value: V) -> Result<(), Self::Error> where V: Serialize { fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::StructSep)); assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(&mut **self)); try!(key.serialize(&mut **self));
value.serialize(&mut **self) value.serialize(&mut **self)
@@ -343,7 +333,7 @@ impl<'s, 'a, I> ser::SerializeStructVariant for &'s mut Serializer<'a, I>
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_field<V>(&mut self, key: &'static str, value: V) -> Result<(), Self::Error> where V: Serialize { fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep)); assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(&mut **self)); try!(key.serialize(&mut **self));
value.serialize(&mut **self) value.serialize(&mut **self)
-2
View File
@@ -1,12 +1,10 @@
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> { pub enum Token<'a> {
Bool(bool), Bool(bool),
Isize(isize),
I8(i8), I8(i8),
I16(i16), I16(i16),
I32(i32), I32(i32),
I64(i64), I64(i64),
Usize(usize),
U8(u8), U8(u8),
U16(u16), U16(u16),
U32(u32), U32(u32),
+13 -9
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_testing" name = "serde_test_suite"
version = "0.9.0-rc2" version = "0.0.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 = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
@@ -9,23 +9,27 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/" documentation = "https://docs.serde.rs/serde/"
readme = "README.md" readme = "README.md"
keywords = ["serialization"] keywords = ["serialization"]
build = "build.rs"
publish = false publish = false
[features] [features]
unstable-testing = ["clippy", "serde/unstable-testing", "serde_codegen/unstable-testing"] unstable-testing = [
"clippy",
[build-dependencies] "compiletest_rs",
serde_codegen = { path = "../serde_codegen", features = ["with-syntex"] } "serde/unstable-testing",
"serde_derive/unstable-testing",
"serde_test/unstable-testing",
]
[dev-dependencies] [dev-dependencies]
fnv = "1.0" fnv = "1.0"
rustc-serialize = "^0.3.16" rustc-serialize = "0.3.16"
serde = { path = "../serde" } serde = { path = "../serde" }
serde_derive = { path = "../serde_derive" }
serde_test = { path = "../serde_test" } serde_test = { path = "../serde_test" }
[dependencies] [dependencies]
clippy = { version = "^0.*", optional = true } clippy = { version = "0.*", optional = true }
compiletest_rs = { version = "0.2", optional = true }
[[test]] [[test]]
name = "test" name = "test"
+9
View File
@@ -0,0 +1,9 @@
[package]
name = "serde_test_suite_deps"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[dependencies]
serde = { path = "../../serde" }
serde_derive = { path = "../../serde_derive" }
View File
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "serde_derive_tests_no_std"
version = "0.0.0"
publish = false
[dependencies]
serde = { path = "../../serde", default-features = false }
serde_derive = { path = "../../serde_derive" }
+50
View File
@@ -0,0 +1,50 @@
#![feature(lang_items, start, libc)]
#![no_std]
extern crate libc;
#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
#[lang = "eh_personality"]
#[no_mangle]
pub extern fn rust_eh_personality() {}
#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {}
#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32) -> ! {
loop {}
}
//////////////////////////////////////////////////////////////////////////////
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)]
struct Unit;
#[derive(Serialize, Deserialize)]
struct Newtype(u8);
#[derive(Serialize, Deserialize)]
struct Tuple(u8, u8);
#[derive(Serialize, Deserialize)]
struct Struct { f: u8 }
#[derive(Serialize, Deserialize)]
enum Enum {
Unit,
Newtype(u8),
Tuple(u8, u8),
Struct { f: u8 },
}
+26
View File
@@ -0,0 +1,26 @@
extern crate compiletest_rs as compiletest;
use std::env;
fn run_mode(mode: &'static str) {
let mut config = compiletest::default_config();
config.mode = mode.parse().expect("invalid mode");
config.target_rustcflags = Some("-L deps/target/debug/deps".to_owned());
if let Ok(name) = env::var("TESTNAME") {
config.filter = Some(name);
}
config.src_base = format!("tests/{}", mode).into();
compiletest::run_tests(&config);
}
#[test]
fn compile_fail() {
run_mode("compile-fail");
}
#[test]
fn run_pass() {
run_mode("run-pass");
}
@@ -1,31 +1,3 @@
#[macro_export]
macro_rules! declare_ser_tests {
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
$(
#[test]
fn $name() {
$(
assert_ser_tokens(&$value, $tokens);
)+
}
)+
}
}
#[macro_export]
macro_rules! btreemap {
() => {
BTreeMap::new()
};
($($key:expr => $value:expr),+) => {
{
let mut map = BTreeMap::new();
$(map.insert($key, $value);)+
map
}
}
}
macro_rules! btreeset { macro_rules! btreeset {
() => { () => {
BTreeSet::new() BTreeSet::new()
+26
View File
@@ -0,0 +1,26 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "unstable-testing", feature(test, non_ascii_idents))]
#[cfg(feature = "unstable-testing")]
extern crate test;
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_test;
#[macro_use]
mod macros;
mod test_annotations;
mod test_bytes;
mod test_de;
mod test_gen;
mod test_macros;
mod test_ser;
#[cfg(feature = "unstable-testing")]
mod compiletest;
@@ -97,7 +97,7 @@ macro_rules! declare_tests {
} }
macro_rules! declare_error_tests { macro_rules! declare_error_tests {
($($name:ident<$target:ident> { $tokens:expr, $expected:expr, })+) => { ($($name:ident<$target:ty> { $tokens:expr, $expected:expr, })+) => {
$( $(
#[test] #[test]
fn $name() { fn $name() {
@@ -155,12 +155,10 @@ declare_tests! {
false => &[Token::Bool(false)], false => &[Token::Bool(false)],
} }
test_isize { test_isize {
0isize => &[Token::Isize(0)],
0isize => &[Token::I8(0)], 0isize => &[Token::I8(0)],
0isize => &[Token::I16(0)], 0isize => &[Token::I16(0)],
0isize => &[Token::I32(0)], 0isize => &[Token::I32(0)],
0isize => &[Token::I64(0)], 0isize => &[Token::I64(0)],
0isize => &[Token::Usize(0)],
0isize => &[Token::U8(0)], 0isize => &[Token::U8(0)],
0isize => &[Token::U16(0)], 0isize => &[Token::U16(0)],
0isize => &[Token::U32(0)], 0isize => &[Token::U32(0)],
@@ -169,14 +167,12 @@ declare_tests! {
0isize => &[Token::F64(0.)], 0isize => &[Token::F64(0.)],
} }
test_ints { test_ints {
0isize => &[Token::Isize(0)],
0i8 => &[Token::I8(0)], 0i8 => &[Token::I8(0)],
0i16 => &[Token::I16(0)], 0i16 => &[Token::I16(0)],
0i32 => &[Token::I32(0)], 0i32 => &[Token::I32(0)],
0i64 => &[Token::I64(0)], 0i64 => &[Token::I64(0)],
} }
test_uints { test_uints {
0usize => &[Token::Usize(0)],
0u8 => &[Token::U8(0)], 0u8 => &[Token::U8(0)],
0u16 => &[Token::U16(0)], 0u16 => &[Token::U16(0)],
0u32 => &[Token::U32(0)], 0u32 => &[Token::U32(0)],
@@ -774,6 +770,20 @@ declare_tests! {
Token::EnumMapEnd, Token::EnumMapEnd,
], ],
} }
test_enum_unit_usize {
Enum::Unit => &[
Token::EnumStart("Enum"),
Token::U32(0),
Token::Unit,
],
}
test_enum_unit_bytes {
Enum::Unit => &[
Token::EnumStart("Enum"),
Token::Bytes(b"Unit"),
Token::Unit,
],
}
test_box { test_box {
Box::new(0i32) => &[Token::I32(0)], Box::new(0i32) => &[Token::I32(0)],
} }
@@ -918,20 +928,30 @@ declare_error_tests! {
], ],
Error::Message("duplicate field `a`".to_owned()), Error::Message("duplicate field `a`".to_owned()),
} }
test_enum_unit_usize<Enum> { test_enum_out_of_range<Enum> {
&[ &[
Token::EnumStart("Enum"), Token::EnumStart("Enum"),
Token::Usize(0), Token::U32(4),
Token::Unit, Token::Unit,
], ],
Error::Message("invalid type: integer `0`, expected field name".into()), Error::Message("invalid value: integer `4`, expected variant index 0 <= i < 4".into()),
} }
test_enum_unit_bytes<Enum> { test_short_tuple<(u8, u8, u8)> {
&[ &[
Token::EnumStart("Enum"), Token::TupleStart(1),
Token::Bytes(b"Unit"), Token::TupleSep,
Token::Unit, Token::U8(1),
Token::TupleEnd,
], ],
Error::Message("invalid type: byte array, expected field name".into()), Error::Message("invalid length 1, expected a tuple of size 3".into()),
}
test_short_array<[u8; 3]> {
&[
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::U8(1),
Token::SeqEnd,
],
Error::Message("invalid length 1, expected an array of length 3".into()),
} }
} }
@@ -51,7 +51,20 @@ enum Enum {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
declare_ser_tests! { macro_rules! declare_tests {
($($name:ident { $($value:expr => $tokens:expr,)+ })+) => {
$(
#[test]
fn $name() {
$(
assert_ser_tokens(&$value, $tokens);
)+
}
)+
}
}
declare_tests! {
test_unit { test_unit {
() => &[Token::Unit], () => &[Token::Unit],
} }
@@ -60,14 +73,12 @@ declare_ser_tests! {
false => &[Token::Bool(false)], false => &[Token::Bool(false)],
} }
test_isizes { test_isizes {
0isize => &[Token::Isize(0)],
0i8 => &[Token::I8(0)], 0i8 => &[Token::I8(0)],
0i16 => &[Token::I16(0)], 0i16 => &[Token::I16(0)],
0i32 => &[Token::I32(0)], 0i32 => &[Token::I32(0)],
0i64 => &[Token::I64(0)], 0i64 => &[Token::I64(0)],
} }
test_usizes { test_usizes {
0usize => &[Token::Usize(0)],
0u8 => &[Token::U8(0)], 0u8 => &[Token::U8(0)],
0u16 => &[Token::U16(0)], 0u16 => &[Token::U16(0)],
0u32 => &[Token::U32(0)], 0u32 => &[Token::U32(0)],
@@ -432,7 +443,7 @@ fn test_cannot_serialize_paths() {
assert_ser_tokens_error( assert_ser_tokens_error(
&Path::new(path), &Path::new(path),
&[], &[],
Error::Message("Path contains invalid UTF-8 characters".to_owned())); Error::Message("path contains invalid UTF-8 characters".to_owned()));
let mut path_buf = PathBuf::new(); let mut path_buf = PathBuf::new();
path_buf.push(path); path_buf.push(path);
@@ -440,7 +451,7 @@ fn test_cannot_serialize_paths() {
assert_ser_tokens_error( assert_ser_tokens_error(
&path_buf, &path_buf,
&[], &[],
Error::Message("Path contains invalid UTF-8 characters".to_owned())); Error::Message("path contains invalid UTF-8 characters".to_owned()));
} }
#[test] #[test]
-11
View File
@@ -1,11 +0,0 @@
extern crate serde_codegen;
use std::env;
use std::path::Path;
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let src = Path::new("tests/test.rs.in");
let dst = Path::new(&out_dir).join("test.rs");
serde_codegen::expand(&src, &dst).unwrap();
}
-6
View File
@@ -1,6 +0,0 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "unstable-testing", feature(non_ascii_idents))]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
-12
View File
@@ -1,12 +0,0 @@
extern crate serde;
extern crate serde_test;
#[macro_use]
mod macros;
mod test_annotations;
mod test_bytes;
mod test_de;
mod test_gen;
mod test_macros;
mod test_ser;