Compare commits

...

104 Commits

Author SHA1 Message Date
David Tolnay 964a2dd4d1 Release 0.9.7 2017-02-09 17:52:11 -08:00
David Tolnay 8a21bbc720 Merge pull request #755 from serde-rs/playground
Playground feature to get serde_derive picked up by integer32 playground
2017-02-09 17:50:39 -08:00
Oliver Schneider 4dba260ad7 Merge pull request #756 from shepmaster/patch-2
Add missing close backtick
2017-02-09 18:01:35 +01:00
Jake Goulding 1d3044fa28 Add missing close backtick 2017-02-09 11:53:12 -05:00
David Tolnay d1f0112bfb Playground feature to get serde_derive picked up by integer32 playground 2017-02-08 12:37:40 -08:00
David Tolnay 3f25cd9a7e No longer need ser::Error import 2017-02-08 08:17:43 -08:00
David Tolnay 45a36f1219 Fix proc macro panic message in tests 2017-02-08 08:12:32 -08:00
David Tolnay 529a1cfedb Keyword no_std for serde and serde_derive 2017-02-08 07:40:02 -08:00
David Tolnay 219abd2e00 The performance is identical 2017-02-04 19:04:29 -08:00
David Tolnay 4bd10528a0 Merge pull request #736 from nox/serialize-iter
Introduce collect_seq and collect_map
2017-02-04 11:18:36 -08:00
David Tolnay b82bba2d0a Merge pull request #747 from serde-rs/phantom_tags
Content clean-up
2017-02-04 08:53:04 -08:00
Anthony Ramine 17c175a1a6 Use specialisation to optimise collect_seq and collect_map 2017-02-04 12:22:58 +01:00
Anthony Ramine 763ab9c2a1 Use serialize_seq! to implement Serialize for [T] 2017-02-04 12:21:45 +01:00
Anthony Ramine 30b8036efa Remove ser::Iterator 2017-02-04 12:17:25 +01:00
Anthony Ramine 89bb16da6b Introduce Serializer::collect_map 2017-02-04 11:49:53 +01:00
Anthony Ramine d00a895902 Introduce Serializer::collect_seq
This function serializes the given iterator as a sequence. Its iter parameter
has type I: IntoIterator, <I as IntoIterator>::Item: Serialize, which means it
will work both for iterators passed by value, therefore consuming them, and as
the value for a #[serde(serialize_with)] attribute, where it will be called as
Serializer::collect_seq(&self.field, serializer), relying on the common practice
of implementing IntoIterator for &C where C is a data type representing some
kind of collection.
2017-02-04 11:49:34 +01:00
Oliver Schneider 393b19ee8a update codegen to the content changes 2017-02-04 10:37:50 +01:00
Oliver Schneider e68888d475 remove possible sublte ambiguity with .into_deserializer 2017-02-04 10:00:04 +01:00
David Tolnay d1306a78ec Release 0.9.6 2017-02-03 08:02:47 -08:00
David Tolnay ce230adf12 Merge pull request #739 from serde-rs/tag
Untagged and internally tagged enums
2017-02-03 07:50:26 -08:00
David Tolnay 066c9a15cf Explain status of content module 2017-02-03 07:43:04 -08:00
Oliver Schneider 6277079152 move the PhantomData usage to the Deserializer 2017-02-03 15:02:40 +01:00
Oliver Schneider d60fd84b7e Merge pull request #740 from serde-rs/enumset
Remove the EnumSet impls
2017-02-03 13:38:39 +01:00
David Tolnay 02e6c04e9f Check for sequence end 2017-02-02 22:13:32 -08:00
David Tolnay 9f04b9d6e7 Remove the EnumSet impls 2017-02-02 19:13:55 -08:00
David Tolnay d298da0b4f Require std for deserializing untagged enums 2017-02-02 19:09:38 -08:00
David Tolnay ff21d557c7 Untagged and internally tagged enums 2017-02-02 18:48:30 -08:00
Oliver Schneider faaa494579 Merge pull request #738 from serde-rs/absolute
Use absolute paths to Ok, Err, and other types and methods
2017-02-02 08:16:51 +01:00
David Tolnay 661cdf4e00 Inline the trait docs at the top level 2017-02-01 12:58:24 -08:00
David Tolnay a55d812441 Even more absolute paths 2017-02-01 12:12:39 -08:00
David Tolnay b7ca574bb3 Use absolute paths to Ok and Err 2017-02-01 09:42:12 -08:00
David Tolnay d960571439 Release 0.9.5 2017-02-01 01:01:06 -08:00
David Tolnay 1ccc58e2aa Merge pull request #735 from serde-rs/travis
Allow running travis build locally
2017-02-01 00:43:27 -08:00
David Tolnay 34b39083bc No error if clippy install fails 2017-02-01 00:38:02 -08:00
David Tolnay 48f4deac55 No more travis-cargo 2017-01-31 12:18:57 -08:00
David Tolnay 9a0f05d00d Speed up the travis clippy installation 2017-01-31 12:09:44 -08:00
David Tolnay b47e1a6dc3 Allow clippy failure in travis 2017-01-31 12:07:35 -08:00
David Tolnay 39c7797633 Allow running travis build locally 2017-01-31 12:07:31 -08:00
Oliver Schneider 368784949e move to cargo clippy instead of using the clippy plugin (#733)
* move to cargo clippy instead of using the clippy plugin

fixes #729

* non-exectable scripts must be run with `sh`

* don't build serde in the clippy travis job

* only run clippy tests if installing clippy succeeds

* why is travis so picky?

* no more serde_codegen

* serde_test_suite_deps has no features

* don't use empty loops, llvm optimizes them to undefined behaviour

* abort the clippy job when clippy lints are triggered

* use caches on travis to speed up builds

* why are we even using `travis-cargo`?

* need to reinstall clippy frequently due to nightly updates

* command line tools are hard
2017-01-31 09:09:37 -08:00
Oliver Schneider 74cf80989d Merge pull request #731 from serde-rs/pubtuple
No tuple structs with private fields in public API
2017-01-31 08:56:46 +01:00
David Tolnay f0b4735781 No tuple structs with private fields in public API 2017-01-30 18:10:50 -08:00
David Tolnay 297f373548 Release 0.9.4 2017-01-30 17:42:11 -08:00
David Tolnay 81f28da8e1 Clarify the role of Impossible serializer 2017-01-30 17:41:33 -08:00
David Tolnay d4bb687032 Merge pull request #728 from nox/impossibru
Introduce ser::Impossible (fixes #694)
2017-01-30 17:26:21 -08:00
Anthony Ramine f9bc5037f5 Introduce ser::Impossible (fixes #694) 2017-01-31 02:20:04 +01:00
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
72 changed files with 4338 additions and 1830 deletions
+14 -23
View File
@@ -1,26 +1,17 @@
sudo: false sudo: false
language: rust language: rust
cache: cargo
# run builds for all the trains (and more)
rust: rust:
- 1.13.0 - 1.13.0
- stable - stable
- beta - beta
- nightly - nightly
before_script:
- pip install 'travis-cargo<0.2' --user matrix:
- export PATH=$HOME/.local/bin:$PATH include:
script: - rust: nightly
- (cd serde && travis-cargo build) env: CLIPPY=true
- (cd serde && travis-cargo --skip nightly test)
- (cd serde && travis-cargo --only nightly test -- --features unstable-testing) script: ./travis.sh
- (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 collections)
- (cd testing && travis-cargo --skip nightly test)
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde_derive && travis-cargo --only nightly test)
#- (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:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
+9
View File
@@ -0,0 +1,9 @@
[workspace]
members = [
"serde",
"serde_codegen_internals",
"serde_derive",
"serde_test",
"test_suite",
"test_suite/no_std",
]
-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);
}
+13 -4
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "0.9.0-rc2" version = "0.9.7"
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"
@@ -8,10 +8,13 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" 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 = ["serde", "serialization"] keywords = ["serde", "serialization", "no_std"]
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"]
@@ -19,7 +22,13 @@ std = []
unstable = [] unstable = []
alloc = ["unstable"] alloc = ["unstable"]
collections = ["alloc"] collections = ["alloc"]
unstable-testing = ["clippy", "unstable", "std"] unstable-testing = ["unstable", "std"]
# to get serde_derive picked up by play.integer32.com
playground = ["serde_derive"]
[dependencies] [dependencies]
clippy = { version = "^0.*", optional = true } serde_derive = { version = "0.9", 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>,
+761
View File
@@ -0,0 +1,761 @@
// This module is doc(hidden) and nothing here should be used outside of
// generated code.
//
// We will iterate on the implementation for a few releases and only have to
// worry about backward compatibility for the `untagged` and `tag` attributes
// rather than for this entire mechanism.
//
// This issue is tracking making some of this stuff public:
// https://github.com/serde-rs/serde/issues/741
#![doc(hidden)]
use core::fmt;
use core::marker::PhantomData;
#[cfg(all(not(feature = "std"), feature = "collections"))]
use collections::{String, Vec};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
use de::{
self,
Deserialize,
DeserializeSeed,
Deserializer,
Visitor,
SeqVisitor,
MapVisitor,
EnumVisitor,
};
/// Used from generated code to buffer the contents of the Deserializer when
/// deserializing untagged enums and internally tagged enums.
///
/// Not public API. Use serde-value instead.
#[derive(Debug)]
pub enum Content {
// Don't mind the PhantomData, just need to use E somewhere.
Bool(bool),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
F32(f32),
F64(f64),
Char(char),
String(String),
Bytes(Vec<u8>),
None,
Some(Box<Content>),
Unit,
Newtype(Box<Content>),
Seq(Vec<Content>),
Map(Vec<(Content, Content)>),
}
impl Deserialize for Content {
fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
// Untagged and internally tagged enums are only supported in
// self-describing formats.
deserializer.deserialize(ContentVisitor)
}
}
struct ContentVisitor;
impl Visitor for ContentVisitor {
type Value = Content;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("any value")
}
fn visit_bool<F>(self, value: bool) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Bool(value))
}
fn visit_i8<F>(self, value: i8) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::I8(value))
}
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::I16(value))
}
fn visit_i32<F>(self, value: i32) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::I32(value))
}
fn visit_i64<F>(self, value: i64) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::I64(value))
}
fn visit_u8<F>(self, value: u8) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::U8(value))
}
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::U16(value))
}
fn visit_u32<F>(self, value: u32) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::U32(value))
}
fn visit_u64<F>(self, value: u64) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::U64(value))
}
fn visit_f32<F>(self, value: f32) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::F32(value))
}
fn visit_f64<F>(self, value: f64) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::F64(value))
}
fn visit_char<F>(self, value: char) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Char(value))
}
fn visit_str<F>(self, value: &str) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::String(value.into()))
}
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::String(value))
}
fn visit_bytes<F>(self, value: &[u8]) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Bytes(value.into()))
}
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Bytes(value))
}
fn visit_unit<F>(self) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::Unit)
}
fn visit_none<F>(self) -> Result<Self::Value, F>
where F: de::Error
{
Ok(Content::None)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
Deserialize::deserialize(deserializer).map(|v| Content::Some(Box::new(v)))
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
Deserialize::deserialize(deserializer).map(|v| Content::Newtype(Box::new(v)))
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor
{
let mut vec = Vec::with_capacity(visitor.size_hint().0);
while let Some(e) = try!(visitor.visit()) {
vec.push(e);
}
Ok(Content::Seq(vec))
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor
{
let mut vec = Vec::with_capacity(visitor.size_hint().0);
while let Some(kv) = try!(visitor.visit()) {
vec.push(kv);
}
Ok(Content::Map(vec))
}
fn visit_enum<V>(self, _visitor: V) -> Result<Self::Value, V::Error>
where V: EnumVisitor
{
Err(de::Error::custom("untagged and internally tagged enums do not support enum input"))
}
}
/// This is the type of the map keys in an internally tagged enum.
///
/// Not public API.
pub enum TagOrContent {
Tag,
Content(Content),
}
struct TagOrContentVisitor {
name: &'static str,
}
impl TagOrContentVisitor {
fn new(name: &'static str) -> Self {
TagOrContentVisitor {
name: name,
}
}
}
impl DeserializeSeed for TagOrContentVisitor {
type Value = TagOrContent;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
// Internally tagged enums are only supported in self-describing
// formats.
deserializer.deserialize(self)
}
}
impl Visitor for TagOrContentVisitor {
type Value = TagOrContent;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "a type tag `{}` or any other value", self.name)
}
fn visit_bool<F>(self, value: bool) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_bool(value).map(TagOrContent::Content)
}
fn visit_i8<F>(self, value: i8) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_i8(value).map(TagOrContent::Content)
}
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_i16(value).map(TagOrContent::Content)
}
fn visit_i32<F>(self, value: i32) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_i32(value).map(TagOrContent::Content)
}
fn visit_i64<F>(self, value: i64) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_i64(value).map(TagOrContent::Content)
}
fn visit_u8<F>(self, value: u8) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_u8(value).map(TagOrContent::Content)
}
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_u16(value).map(TagOrContent::Content)
}
fn visit_u32<F>(self, value: u32) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_u32(value).map(TagOrContent::Content)
}
fn visit_u64<F>(self, value: u64) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_u64(value).map(TagOrContent::Content)
}
fn visit_f32<F>(self, value: f32) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_f32(value).map(TagOrContent::Content)
}
fn visit_f64<F>(self, value: f64) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_f64(value).map(TagOrContent::Content)
}
fn visit_char<F>(self, value: char) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_char(value).map(TagOrContent::Content)
}
fn visit_str<F>(self, value: &str) -> Result<Self::Value, F>
where F: de::Error
{
if value == self.name {
Ok(TagOrContent::Tag)
} else {
ContentVisitor.visit_str(value).map(TagOrContent::Content)
}
}
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
where F: de::Error
{
if value == self.name {
Ok(TagOrContent::Tag)
} else {
ContentVisitor.visit_string(value).map(TagOrContent::Content)
}
}
fn visit_bytes<F>(self, value: &[u8]) -> Result<Self::Value, F>
where F: de::Error
{
if value == self.name.as_bytes() {
Ok(TagOrContent::Tag)
} else {
ContentVisitor.visit_bytes(value).map(TagOrContent::Content)
}
}
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
where F: de::Error
{
if value == self.name.as_bytes() {
Ok(TagOrContent::Tag)
} else {
ContentVisitor.visit_byte_buf(value).map(TagOrContent::Content)
}
}
fn visit_unit<F>(self) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_unit().map(TagOrContent::Content)
}
fn visit_none<F>(self) -> Result<Self::Value, F>
where F: de::Error
{
ContentVisitor.visit_none().map(TagOrContent::Content)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
ContentVisitor.visit_some(deserializer).map(TagOrContent::Content)
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
ContentVisitor.visit_newtype_struct(deserializer).map(TagOrContent::Content)
}
fn visit_seq<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor
{
ContentVisitor.visit_seq(visitor).map(TagOrContent::Content)
}
fn visit_map<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor
{
ContentVisitor.visit_map(visitor).map(TagOrContent::Content)
}
fn visit_enum<V>(self, visitor: V) -> Result<Self::Value, V::Error>
where V: EnumVisitor
{
ContentVisitor.visit_enum(visitor).map(TagOrContent::Content)
}
}
/// Used by generated code to deserialize an internally tagged enum.
///
/// Not public API.
pub struct TaggedContent<T> {
pub tag: T,
pub content: Content,
}
/// Not public API.
pub struct TaggedContentVisitor<T> {
tag_name: &'static str,
tag: PhantomData<T>,
}
impl<T> TaggedContentVisitor<T> {
/// Visitor for the content of an internally tagged enum with the given tag
/// name.
pub fn new(name: &'static str) -> Self {
TaggedContentVisitor {
tag_name: name,
tag: PhantomData,
}
}
}
impl<T> DeserializeSeed for TaggedContentVisitor<T>
where T: Deserialize
{
type Value = TaggedContent<T>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where D: Deserializer
{
// Internally tagged enums are only supported in self-describing
// formats.
deserializer.deserialize(self)
}
}
impl<T> Visitor for TaggedContentVisitor<T>
where T: Deserialize
{
type Value = TaggedContent<T>;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("any value")
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor
{
let mut tag = None;
let mut vec = Vec::with_capacity(visitor.size_hint().0);
while let Some(k) = try!(visitor.visit_key_seed(TagOrContentVisitor::new(self.tag_name))) {
match k {
TagOrContent::Tag => {
if tag.is_some() {
return Err(de::Error::duplicate_field(self.tag_name));
}
tag = Some(try!(visitor.visit_value()));
}
TagOrContent::Content(k) => {
let v = try!(visitor.visit_value());
vec.push((k, v));
}
}
}
match tag {
None => {
Err(de::Error::missing_field(self.tag_name))
}
Some(tag) => {
Ok(TaggedContent {
tag: tag,
content: Content::Map(vec),
})
}
}
}
}
/// Not public API
pub struct ContentDeserializer<E> {
content: Content,
err: PhantomData<E>,
}
/// Used when deserializing an internally tagged enum because the content will
/// be used exactly once.
impl<E> Deserializer for ContentDeserializer<E>
where E: de::Error
{
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
match self.content {
Content::Bool(v) => visitor.visit_bool(v),
Content::U8(v) => visitor.visit_u8(v),
Content::U16(v) => visitor.visit_u16(v),
Content::U32(v) => visitor.visit_u32(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I8(v) => visitor.visit_i8(v),
Content::I16(v) => visitor.visit_i16(v),
Content::I32(v) => visitor.visit_i32(v),
Content::I64(v) => visitor.visit_i64(v),
Content::F32(v) => visitor.visit_f32(v),
Content::F64(v) => visitor.visit_f64(v),
Content::Char(v) => visitor.visit_char(v),
Content::String(v) => visitor.visit_string(v),
Content::Unit => visitor.visit_unit(),
Content::None => visitor.visit_none(),
Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)),
Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)),
Content::Seq(v) => {
let seq = v.into_iter().map(ContentDeserializer::new);
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
let value = try!(visitor.visit_seq(&mut seq_visitor));
try!(seq_visitor.end());
Ok(value)
},
Content::Map(v) => {
let map = v.into_iter().map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
Ok(value)
},
Content::Bytes(v) => visitor.visit_byte_buf(v),
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
match self.content {
Content::None => visitor.visit_none(),
Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)),
Content::Unit => visitor.visit_unit(),
_ => visitor.visit_some(self)
}
}
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
visitor.visit_newtype_struct(self)
}
forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
struct_field tuple enum ignored_any
}
}
impl<E> ContentDeserializer<E> {
/// private API, don't use
pub fn new(content: Content) -> Self {
ContentDeserializer {
content: content,
err: PhantomData,
}
}
}
/// Not public API.
pub struct ContentRefDeserializer<'a, E> {
content: &'a Content,
err: PhantomData<E>,
}
/// Used when deserializing an untagged enum because the content may need to be
/// used more than once.
impl<'a, E> Deserializer for ContentRefDeserializer<'a, E>
where E: de::Error
{
type Error = E;
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
match *self.content {
Content::Bool(v) => visitor.visit_bool(v),
Content::U8(v) => visitor.visit_u8(v),
Content::U16(v) => visitor.visit_u16(v),
Content::U32(v) => visitor.visit_u32(v),
Content::U64(v) => visitor.visit_u64(v),
Content::I8(v) => visitor.visit_i8(v),
Content::I16(v) => visitor.visit_i16(v),
Content::I32(v) => visitor.visit_i32(v),
Content::I64(v) => visitor.visit_i64(v),
Content::F32(v) => visitor.visit_f32(v),
Content::F64(v) => visitor.visit_f64(v),
Content::Char(v) => visitor.visit_char(v),
Content::String(ref v) => visitor.visit_str(v),
Content::Unit => visitor.visit_unit(),
Content::None => visitor.visit_none(),
Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)),
Content::Newtype(ref v) => visitor.visit_newtype_struct(ContentRefDeserializer::new(v)),
Content::Seq(ref v) => {
let seq = v.into_iter().map(ContentRefDeserializer::new);
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
let value = try!(visitor.visit_seq(&mut seq_visitor));
try!(seq_visitor.end());
Ok(value)
},
Content::Map(ref v) => {
let map = v.into_iter().map(|&(ref k, ref v)| (ContentRefDeserializer::new(k), ContentRefDeserializer::new(v)));
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
Ok(value)
},
Content::Bytes(ref v) => visitor.visit_bytes(v),
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
match *self.content {
Content::None => visitor.visit_none(),
Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)),
Content::Unit => visitor.visit_unit(),
_ => visitor.visit_some(self)
}
}
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
visitor.visit_newtype_struct(self)
}
forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct tuple_struct struct
struct_field tuple enum ignored_any
}
}
impl<'a, E> ContentRefDeserializer<'a, E> {
/// private API, don't use
pub fn new(content: &'a Content) -> Self {
ContentRefDeserializer {
content: content,
err: PhantomData,
}
}
}
impl<E> de::value::ValueDeserializer<E> for ContentDeserializer<E>
where E: de::Error
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
impl<'a, E> de::value::ValueDeserializer<E> for ContentRefDeserializer<'a, E>
where E: de::Error
{
type Deserializer = Self;
fn into_deserializer(self) -> Self {
self
}
}
/// Visitor for deserializing an internally tagged unit variant.
///
/// Not public API.
pub struct InternallyTaggedUnitVisitor<'a> {
type_name: &'a str,
variant_name: &'a str,
}
impl<'a> InternallyTaggedUnitVisitor<'a> {
/// Not public API.
pub fn new(type_name: &'a str, variant_name: &'a str) -> Self {
InternallyTaggedUnitVisitor {
type_name: type_name,
variant_name: variant_name,
}
}
}
impl<'a> Visitor for InternallyTaggedUnitVisitor<'a> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name)
}
fn visit_map<V>(self, _: V) -> Result<(), V::Error>
where V: MapVisitor
{
Ok(())
}
}
/// Visitor for deserializing an untagged unit variant.
///
/// Not public API.
pub struct UntaggedUnitVisitor<'a> {
type_name: &'a str,
variant_name: &'a str,
}
impl<'a> UntaggedUnitVisitor<'a> {
/// Not public API.
pub fn new(type_name: &'a str, variant_name: &'a str) -> Self {
UntaggedUnitVisitor {
type_name: type_name,
variant_name: variant_name,
}
}
}
impl<'a> Visitor for UntaggedUnitVisitor<'a> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name)
}
fn visit_unit<E>(self) -> Result<(), E>
where E: de::Error
{
Ok(())
}
}
+66 -86
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,11 @@ use std::collections::{
VecDeque, VecDeque,
}; };
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "unstable", 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 +42,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 +60,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 +178,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 +205,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 +293,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 +302,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,15 +479,6 @@ seq_impl!(
BTreeSet::new(), BTreeSet::new(),
BTreeSet::insert); BTreeSet::insert);
#[cfg(all(feature = "unstable", feature = "collections"))]
seq_impl!(
EnumSet<T>,
EnumSetVisitor<T: Deserialize + CLike>,
visitor,
EnumSet::new(),
EnumSet::new(),
EnumSet::insert);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
seq_impl!( seq_impl!(
LinkedList<T>, LinkedList<T>,
@@ -574,7 +563,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 +579,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 +601,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 +667,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 +688,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 +1003,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 +1099,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 +1137,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 +1160,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)),
} }
} }
} }
+509 -179
View File
File diff suppressed because it is too large Load Diff
+13 -4
View File
@@ -2,6 +2,16 @@ use core::marker::PhantomData;
use de::{Deserialize, Deserializer, Error, Visitor}; use de::{Deserialize, Deserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))]
pub use de::content::{
Content,
ContentRefDeserializer,
ContentDeserializer,
TaggedContentVisitor,
InternallyTaggedUnitVisitor,
UntaggedUnitVisitor,
};
/// If the missing field is of type `Option<T>` then treat is as `None`, /// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error. /// otherwise it is an error.
pub fn missing_field<V, E>(field: &'static str) -> Result<V, E> pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
@@ -28,10 +38,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
} }
} }
+141 -92
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;
@@ -53,7 +51,9 @@ use bytes;
/// This represents all the possible errors that can occur using the `ValueDeserializer`. /// This represents all the possible errors that can occur using the `ValueDeserializer`.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct Error(ErrorImpl); pub struct Error {
err: ErrorImpl,
}
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
type ErrorImpl = Box<str>; type ErrorImpl = Box<str>;
@@ -63,19 +63,23 @@ type ErrorImpl = ();
impl de::Error for Error { impl de::Error for Error {
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
fn custom<T: Display>(msg: T) -> Self { fn custom<T: Display>(msg: T) -> Self {
Error(msg.to_string().into_boxed_str()) Error {
err: msg.to_string().into_boxed_str(),
}
} }
#[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 {
err: (),
}
} }
} }
impl Display for Error { impl Display for Error {
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(&self.0) formatter.write_str(&self.err)
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "collections")))]
@@ -87,7 +91,7 @@ impl Display for Error {
impl error::Error for Error { impl error::Error for Error {
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
fn description(&self) -> &str { fn description(&self) -> &str {
&self.0 &self.err
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "collections")))]
@@ -115,12 +119,16 @@ impl<E> ValueDeserializer<E> for ()
type Deserializer = UnitDeserializer<E>; type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer<E> { fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer(PhantomData) UnitDeserializer {
marker: PhantomData,
}
} }
} }
/// A helper deserializer that deserializes a `()`. /// A helper deserializer that deserializes a `()`.
pub struct UnitDeserializer<E>(PhantomData<E>); pub struct UnitDeserializer<E> {
marker: PhantomData<E>,
}
impl<E> de::Deserializer for UnitDeserializer<E> impl<E> de::Deserializer for UnitDeserializer<E>
where E: de::Error where E: de::Error
@@ -128,9 +136,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,9 +157,12 @@ 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> {
value: $ty,
marker: PhantomData<E>
}
impl<E> ValueDeserializer<E> for $ty impl<E> ValueDeserializer<E> for $ty
where E: de::Error, where E: de::Error,
@@ -159,7 +170,10 @@ macro_rules! primitive_deserializer {
type Deserializer = $name<E>; type Deserializer = $name<E>;
fn into_deserializer(self) -> $name<E> { fn into_deserializer(self) -> $name<E> {
$name(self, PhantomData) $name {
value: self,
marker: PhantomData,
}
} }
} }
@@ -169,16 +183,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.value $($cast)*)
} }
} }
} }
@@ -189,12 +202,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);
@@ -202,7 +215,10 @@ primitive_deserializer!(char, CharDeserializer, visit_char);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// A helper deserializer that deserializes a `&str`. /// A helper deserializer that deserializes a `&str`.
pub struct StrDeserializer<'a, E>(&'a str, PhantomData<E>); pub struct StrDeserializer<'a, E> {
value: &'a str,
marker: PhantomData<E>,
}
impl<'a, E> ValueDeserializer<E> for &'a str impl<'a, E> ValueDeserializer<E> for &'a str
where E: de::Error, where E: de::Error,
@@ -210,7 +226,10 @@ impl<'a, E> ValueDeserializer<E> for &'a str
type Deserializer = StrDeserializer<'a, E>; type Deserializer = StrDeserializer<'a, E>;
fn into_deserializer(self) -> StrDeserializer<'a, E> { fn into_deserializer(self) -> StrDeserializer<'a, E> {
StrDeserializer(self, PhantomData) StrDeserializer {
value: self,
marker: PhantomData,
}
} }
} }
@@ -222,7 +241,7 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
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.visit_str(self.0) visitor.visit_str(self.value)
} }
fn deserialize_enum<V>(self, fn deserialize_enum<V>(self,
@@ -235,9 +254,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
} }
} }
@@ -258,7 +277,10 @@ impl<'a, E> de::EnumVisitor for StrDeserializer<'a, E>
/// A helper deserializer that deserializes a `String`. /// A helper deserializer that deserializes a `String`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
pub struct StringDeserializer<E>(String, PhantomData<E>); pub struct StringDeserializer<E> {
value: String,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
impl<E> ValueDeserializer<E> for String impl<E> ValueDeserializer<E> for String
@@ -267,7 +289,10 @@ impl<E> ValueDeserializer<E> for String
type Deserializer = StringDeserializer<E>; type Deserializer = StringDeserializer<E>;
fn into_deserializer(self) -> StringDeserializer<E> { fn into_deserializer(self) -> StringDeserializer<E> {
StringDeserializer(self, PhantomData) StringDeserializer {
value: self,
marker: PhantomData,
}
} }
} }
@@ -280,7 +305,7 @@ impl<E> de::Deserializer for StringDeserializer<E>
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.visit_string(self.0) visitor.visit_string(self.value)
} }
fn deserialize_enum<V>(self, fn deserialize_enum<V>(self,
@@ -293,9 +318,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
} }
} }
@@ -317,7 +342,10 @@ impl<'a, E> de::EnumVisitor for StringDeserializer<E>
/// A helper deserializer that deserializes a `String`. /// A helper deserializer that deserializes a `String`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
pub struct CowStrDeserializer<'a, E>(Cow<'a, str>, PhantomData<E>); pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
impl<'a, E> ValueDeserializer<E> for Cow<'a, str> impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
@@ -326,7 +354,10 @@ impl<'a, E> ValueDeserializer<E> for Cow<'a, str>
type Deserializer = CowStrDeserializer<'a, E>; type Deserializer = CowStrDeserializer<'a, E>;
fn into_deserializer(self) -> CowStrDeserializer<'a, E> { fn into_deserializer(self) -> CowStrDeserializer<'a, E> {
CowStrDeserializer(self, PhantomData) CowStrDeserializer {
value: self,
marker: PhantomData,
}
} }
} }
@@ -339,7 +370,7 @@ impl<'a, E> de::Deserializer for CowStrDeserializer<'a, E>
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,
{ {
match self.0 { match self.value {
Cow::Borrowed(string) => visitor.visit_str(string), Cow::Borrowed(string) => visitor.visit_str(string),
Cow::Owned(string) => visitor.visit_string(string), Cow::Owned(string) => visitor.visit_string(string),
} }
@@ -355,9 +386,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
} }
} }
@@ -397,7 +428,9 @@ impl<I, E> SeqDeserializer<I, E>
} }
} }
fn end(&mut self) -> Result<(), E> { /// Check for remaining elements after passing a `SeqDeserializer` to
/// `Visitor::visit_seq`.
pub fn end(mut self) -> Result<(), E> {
let mut remaining = 0; let mut remaining = 0;
while self.iter.next().is_some() { while self.iter.next().is_some() {
remaining += 1; remaining += 1;
@@ -428,9 +461,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 +573,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,17 +612,9 @@ impl<I, E> MapDeserializer<I, E>
} }
} }
fn next(&mut self) -> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> { /// Check for remaining elements after passing a `MapDeserializer` to
match self.iter.next() { /// `Visitor::visit_map`.
Some(kv) => { pub fn end(mut self) -> Result<(), E> {
self.count += 1;
Some(private::Pair::split(kv))
}
None => None,
}
}
fn end(&mut self) -> Result<(), E> {
let mut remaining = 0; let mut remaining = 0;
while self.iter.next().is_some() { while self.iter.next().is_some() {
remaining += 1; remaining += 1;
@@ -602,6 +627,16 @@ impl<I, E> MapDeserializer<I, E>
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count))) Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count)))
} }
} }
fn next_pair(&mut self) -> Option<(<I::Item as private::Pair>::First, <I::Item as private::Pair>::Second)> {
match self.iter.next() {
Some(kv) => {
self.count += 1;
Some(private::Pair::split(kv))
}
None => None,
}
}
} }
impl<I, E> de::Deserializer for MapDeserializer<I, E> impl<I, E> de::Deserializer for MapDeserializer<I, E>
@@ -636,9 +671,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 +689,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 +712,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 +739,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 +765,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 +909,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
} }
} }
@@ -888,12 +923,18 @@ impl<'a, E> ValueDeserializer<E> for bytes::Bytes<'a>
type Deserializer = BytesDeserializer<'a, E>; type Deserializer = BytesDeserializer<'a, E>;
fn into_deserializer(self) -> BytesDeserializer<'a, E> { fn into_deserializer(self) -> BytesDeserializer<'a, E> {
BytesDeserializer(self.into(), PhantomData) BytesDeserializer {
value: self.into(),
marker: PhantomData,
}
} }
} }
/// A helper deserializer that deserializes a `&[u8]`. /// A helper deserializer that deserializes a `&[u8]`.
pub struct BytesDeserializer<'a, E>(&'a [u8], PhantomData<E>); pub struct BytesDeserializer<'a, E> {
value: &'a [u8],
marker: PhantomData<E>,
}
impl<'a, E> de::Deserializer for BytesDeserializer<'a, E> impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
where E: de::Error where E: de::Error
@@ -903,13 +944,13 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
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.visit_bytes(self.0) visitor.visit_bytes(self.value)
} }
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
} }
} }
@@ -922,13 +963,19 @@ impl<E> ValueDeserializer<E> for bytes::ByteBuf
type Deserializer = ByteBufDeserializer<E>; type Deserializer = ByteBufDeserializer<E>;
fn into_deserializer(self) -> Self::Deserializer { fn into_deserializer(self) -> Self::Deserializer {
ByteBufDeserializer(self.into(), PhantomData) ByteBufDeserializer {
value: self.into(),
marker: PhantomData,
}
} }
} }
/// A helper deserializer that deserializes a `Vec<u8>`. /// A helper deserializer that deserializes a `Vec<u8>`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
pub struct ByteBufDeserializer<E>(Vec<u8>, PhantomData<E>); pub struct ByteBufDeserializer<E> {
value: Vec<u8>,
marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
impl<E> de::Deserializer for ByteBufDeserializer<E> impl<E> de::Deserializer for ByteBufDeserializer<E>
@@ -939,13 +986,13 @@ impl<E> de::Deserializer for ByteBufDeserializer<E>
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.visit_byte_buf(self.0) visitor.visit_byte_buf(self.value)
} }
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
} }
} }
@@ -955,10 +1002,12 @@ mod private {
use de::{self, Unexpected}; use de::{self, Unexpected};
use core::marker::PhantomData; use core::marker::PhantomData;
pub struct UnitOnly<E>(PhantomData<E>); pub struct UnitOnly<E> {
marker: PhantomData<E>,
}
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) { pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
(t, UnitOnly(PhantomData)) (t, UnitOnly { marker: PhantomData })
} }
impl<E> de::VariantVisitor for UnitOnly<E> impl<E> de::VariantVisitor for UnitOnly<E>
@@ -977,24 +1026,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;
+34
View File
@@ -0,0 +1,34 @@
#[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::option::Option::{self, None, Some};
pub use core::result::Result::{self, Ok, Err};
#[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}")
}
+76 -22
View File
@@ -1,43 +1,92 @@
//! 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(inclusive_range, nonzero, specialization, 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))]
#![cfg_attr(feature = "clippy", plugin(clippy))] #![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
#![cfg_attr(feature = "clippy", allow(linkedlist))]
#![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, option};
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
extern crate core; pub use actual_core::nonzero;
#[cfg(feature = "unstable")]
pub use self::core::nonzero;
} }
#[doc(inline)]
pub use ser::{Serialize, Serializer}; pub use ser::{Serialize, Serializer};
#[doc(inline)]
pub use de::{Deserialize, Deserializer}; pub use de::{Deserialize, Deserializer};
#[macro_use] #[macro_use]
@@ -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)*) => {
+22 -89
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,16 @@ use collections::{
Vec, Vec,
}; };
#[cfg(all(feature = "unstable", feature = "collections"))] #[cfg(feature = "collections")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "unstable", 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,40 +58,36 @@ 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(feature = "std")]
#[cfg(feature = "unstable")] use super::Error;
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);
@@ -157,24 +144,6 @@ impl<T> Serialize for PhantomData<T> {
} }
} }
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for [T]
where T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
let mut seq = try!(serializer.serialize_seq(Some(self.len())));
for e in self {
try!(seq.serialize_element(e));
}
seq.end()
}
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
macro_rules! array_impls { macro_rules! array_impls {
@@ -230,48 +199,23 @@ array_impls!(32);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
impl<'a, I> Serialize for Iterator<I>
where I: IntoIterator, <I as IntoIterator>::Item: Serialize
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
// FIXME: use specialization to prevent invalidating the object in case of clonable iterators?
let iter = match self.0.borrow_mut().take() {
Some(iter) => iter.into_iter(),
None => return Err(S::Error::custom("Iterator used twice")),
};
let size = match iter.size_hint() {
(lo, Some(hi)) if lo == hi => Some(lo),
_ => None,
};
let mut seq = try!(serializer.serialize_seq(size));
for e in iter {
try!(seq.serialize_element(e));
}
seq.end()
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! serialize_seq { macro_rules! serialize_seq {
() => { () => {
#[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,
{ {
let mut seq = try!(serializer.serialize_seq(Some(self.len()))); serializer.collect_seq(self)
for e in self {
try!(seq.serialize_element(e));
}
seq.end()
} }
} }
} }
impl<T> Serialize for [T]
where T: Serialize,
{
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BinaryHeap<T> impl<T> Serialize for BinaryHeap<T>
where T: Serialize + Ord where T: Serialize + Ord
@@ -286,13 +230,6 @@ impl<T> Serialize for BTreeSet<T>
serialize_seq!(); serialize_seq!();
} }
#[cfg(all(feature = "unstable", feature = "collections"))]
impl<T> Serialize for EnumSet<T>
where T: Serialize + CLike
{
serialize_seq!();
}
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<T, H> Serialize for HashSet<T, H> impl<T, H> Serialize for HashSet<T, H>
where T: Serialize + Eq + Hash, where T: Serialize + Eq + Hash,
@@ -333,7 +270,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 +287,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,12 +510,7 @@ 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,
{ {
let mut map = try!(serializer.serialize_map(Some(self.len()))); serializer.collect_map(self)
for (k, v) in self {
try!(map.serialize_key(k));
try!(map.serialize_value(v));
}
map.end()
} }
} }
} }
@@ -695,9 +627,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 +705,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")),
} }
} }
} }
+177
View File
@@ -0,0 +1,177 @@
//! This module contains `Impossible` serializer and its implementations.
use core::marker::PhantomData;
use ser::{
self,
Serialize,
SerializeSeq,
SerializeTuple,
SerializeTupleStruct,
SerializeTupleVariant,
SerializeMap,
SerializeStruct,
SerializeStructVariant,
};
/// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types.
///
/// This type cannot be instantiated, but implements every one of the traits
/// corresponding to the `Serializer` compound types: `SerializeSeq`,
/// `SerializeTuple`, `SerializeTupleStruct`, `SerializeTupleVariant`,
/// `SerializeMap`, `SerializeStruct`, and `SerializeStructVariant`.
///
/// ```rust,ignore
/// impl Serializer for MySerializer {
/// type Ok = ();
/// type Error = Error;
///
/// type SerializeSeq = Impossible<(), Error>;
/// /* other associated types */
///
/// /// This data format does not support serializing sequences.
/// fn serialize_seq(self,
/// len: Option<usize>)
/// -> Result<Self::SerializeSeq, Error> {
/// // Given Impossible cannot be instantiated, the only
/// // thing we can do here is to return an error.
/// Err(...)
/// }
///
/// /* other Serializer methods */
/// }
/// ```
pub struct Impossible<Ok, E> {
void: Void,
_marker: PhantomData<(Ok, E)>,
}
enum Void {}
impl<Ok, E> SerializeSeq for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTuple for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeMap for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_key<T: ?Sized + Serialize>(&mut self,
_key: &T)
-> Result<(), E> {
match self.void {}
}
fn serialize_value<T: ?Sized + Serialize>(&mut self,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeStruct for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
where E: ser::Error,
{
type Ok = Ok;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
_key: &'static str,
_value: &T)
-> Result<(), E> {
match self.void {}
}
fn end(self) -> Result<Ok, E> {
match self.void {}
}
}
+622 -195
View File
File diff suppressed because it is too large Load Diff
+235
View File
@@ -0,0 +1,235 @@
use core::fmt::{self, Display};
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct};
/// Not public API.
pub fn serialize_tagged_newtype<S, T>(
serializer: S,
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
value: T,
) -> Result<S::Ok, S::Error>
where S: Serializer,
T: Serialize
{
value.serialize(TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
})
}
struct TaggedSerializer<S> {
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
delegate: S,
}
enum Unsupported {
Boolean,
Integer,
Float,
Char,
String,
ByteArray,
Optional,
Unit,
UnitStruct,
Sequence,
Tuple,
TupleStruct,
Enum,
}
impl Display for Unsupported {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Unsupported::Boolean => formatter.write_str("a boolean"),
Unsupported::Integer => formatter.write_str("an integer"),
Unsupported::Float => formatter.write_str("a float"),
Unsupported::Char => formatter.write_str("a char"),
Unsupported::String => formatter.write_str("a string"),
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"),
Unsupported::UnitStruct => formatter.write_str("a unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
Unsupported::Enum => formatter.write_str("an enum"),
}
}
}
struct Error {
type_ident: &'static str,
variant_ident: &'static str,
ty: Unsupported,
}
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter,
"cannot serialize tagged newtype variant {}::{} containing {}",
self.type_ident, self.variant_ident, self.ty)
}
}
impl<S> TaggedSerializer<S>
where S: Serializer
{
fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom(Error {
type_ident: self.type_ident,
variant_ident: self.variant_ident,
ty: what,
})
}
}
impl<S> Serializer for TaggedSerializer<S>
where S: Serializer
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = S::SerializeSeq;
type SerializeTuple = S::SerializeTuple;
type SerializeTupleStruct = S::SerializeTupleStruct;
type SerializeTupleVariant = S::SerializeTupleVariant;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
type SerializeStructVariant = S::SerializeStructVariant;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(self, _: &'static str, _: usize, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
}
fn serialize_newtype_struct<T: ?Sized>(self, _: &'static str, value: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self, _: &'static str, _: usize, _: &'static str, _: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
Err(self.bad_type(Unsupported::Enum))
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_seq_fixed_size(self, _: usize) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
}
fn serialize_tuple_variant(self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
try!(map.serialize_entry(self.tag, self.variant_name));
Ok(map)
}
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, Self::Error> {
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
try!(state.serialize_field(self.tag, self.variant_name));
Ok(state)
}
fn serialize_struct_variant(self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
}
}
-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)
}
+5 -6
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_codegen_internals" name = "serde_codegen_internals"
version = "0.11.3" version = "0.13.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."
@@ -10,9 +10,8 @@ documentation = "https://docs.serde.rs/serde_codegen_internals/"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable-testing = ["clippy"]
[dependencies] [dependencies]
clippy = { version = "^0.*", optional = true } syn = "0.11"
syn = "0.10"
[badges]
travis-ci = { repository = "serde-rs/serde" }
+89 -4
View File
@@ -92,6 +92,32 @@ pub struct Item {
deny_unknown_fields: bool, deny_unknown_fields: bool,
ser_bound: Option<Vec<syn::WherePredicate>>, ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>, de_bound: Option<Vec<syn::WherePredicate>>,
tag: EnumTag,
}
/// Styles of representing an enum.
#[derive(Debug)]
pub enum EnumTag {
/// The default.
///
/// ```json
/// {"variant1": {"key1": "value1", "key2": "value2"}}
/// ```
External,
/// `#[serde(tag = "type")]`
///
/// ```json
/// {"type": "variant1", "key1": "value1", "key2": "value2"}
/// ```
Internal(String),
/// `#[serde(untagged)]`
///
/// ```json
/// {"key1": "value1", "key2": "value2"}
/// ```
None,
} }
impl Item { impl Item {
@@ -102,6 +128,8 @@ impl Item {
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields"); let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut ser_bound = Attr::none(cx, "bound"); let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound"); let mut de_bound = Attr::none(cx, "bound");
let mut untagged = BoolAttr::none(cx, "untagged");
let mut internal_tag = Attr::none(cx, "tag");
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) { for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items { for meta_item in meta_items {
@@ -143,18 +171,70 @@ impl Item {
} }
} }
// Parse `#[serde(untagged)]`
MetaItem(Word(ref name)) if name == "untagged" => {
match item.body {
syn::Body::Enum(_) => {
untagged.set_true();
}
syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
}
}
// Parse `#[serde(tag = "type")]`
MetaItem(NameValue(ref name, ref lit)) if name == "tag" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match item.body {
syn::Body::Enum(_) => {
internal_tag.set(s);
}
syn::Body::Struct(_) => {
cx.error("#[serde(tag = \"...\")] can only be used on enums")
}
}
}
}
MetaItem(ref meta_item) => { MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`", cx.error(format!("unknown serde container attribute `{}`",
meta_item.name())); meta_item.name()));
} }
Literal(_) => { Literal(_) => {
cx.error(format!("unexpected literal in serde container attribute")); cx.error("unexpected literal in serde container attribute");
} }
} }
} }
} }
let tag = match (untagged.get(), internal_tag.get()) {
(false, None) => EnumTag::External,
(true, None) => EnumTag::None,
(false, Some(tag)) => {
// Check that there are no tuple variants.
if let syn::Body::Enum(ref variants) = item.body {
for variant in variants {
match variant.data {
syn::VariantData::Struct(_) | syn::VariantData::Unit => {}
syn::VariantData::Tuple(ref fields) => {
if fields.len() != 1 {
cx.error("#[serde(tag = \"...\")] cannot be used with tuple variants");
break;
}
}
}
}
}
EnumTag::Internal(tag)
}
(true, Some(_)) => {
cx.error("enum cannot be both untagged and internally tagged");
EnumTag::External // doesn't matter, will error
}
};
Item { Item {
name: Name { name: Name {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()), serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
@@ -163,6 +243,7 @@ impl Item {
deny_unknown_fields: deny_unknown_fields.get(), deny_unknown_fields: deny_unknown_fields.get(),
ser_bound: ser_bound.get(), ser_bound: ser_bound.get(),
de_bound: de_bound.get(), de_bound: de_bound.get(),
tag: tag,
} }
} }
@@ -181,6 +262,10 @@ impl Item {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..]) self.de_bound.as_ref().map(|vec| &vec[..])
} }
pub fn tag(&self) -> &EnumTag {
&self.tag
}
} }
/// Represents variant attribute information /// Represents variant attribute information
@@ -231,7 +316,7 @@ impl Variant {
} }
Literal(_) => { Literal(_) => {
cx.error(format!("unexpected literal in serde variant attribute")); cx.error("unexpected literal in serde variant attribute");
} }
} }
} }
@@ -390,7 +475,7 @@ impl Field {
} }
Literal(_) => { Literal(_) => {
cx.error(format!("unexpected literal in serde field attribute")); cx.error("unexpected literal in serde field attribute");
} }
} }
} }
@@ -404,7 +489,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(),
-3
View File
@@ -1,6 +1,3 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
extern crate syn; extern crate syn;
pub mod ast; pub mod ast;
+12 -13
View File
@@ -1,27 +1,26 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "0.9.0-rc2" version = "0.9.7"
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)]"
homepage = "https://serde.rs" homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html" documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization", "no_std"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
[features]
unstable = []
[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" quote = "0.3.8"
path = "../serde_codegen" serde_codegen_internals = { version = "=0.13.0", default-features = false, path = "../serde_codegen_internals" }
default-features = false syn = { version = "0.11", features = ["aster", "visit"] }
features = ["with-syn"]
[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
} }
@@ -110,7 +110,8 @@ fn deserialize_body(
impl_generics, impl_generics,
ty, ty,
fields, fields,
&item.attrs) &item.attrs,
None)
} }
Body::Struct(Style::Tuple, ref fields) | Body::Struct(Style::Tuple, ref fields) |
Body::Struct(Style::Newtype, ref fields) => { Body::Struct(Style::Newtype, ref fields) => {
@@ -124,7 +125,8 @@ fn deserialize_body(
impl_generics, impl_generics,
ty, ty,
fields, fields,
&item.attrs) &item.attrs,
None)
} }
Body::Struct(Style::Unit, _) => { Body::Struct(Style::Unit, _) => {
deserialize_unit_struct( deserialize_unit_struct(
@@ -158,11 +160,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 +184,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,22 +210,22 @@ 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) _serde::export::fmt::Formatter::write_str(formatter, #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) _serde::export::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) _serde::export::Ok(#type_ident)
} }
} }
@@ -238,6 +240,7 @@ fn deserialize_tuple(
ty: syn::Ty, ty: syn::Ty,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item, item_attrs: &attr::Item,
deserializer: Option<Tokens>,
) -> Tokens { ) -> Tokens {
let where_clause = &impl_generics.where_clause; let where_clause = &impl_generics.where_clause;
@@ -274,14 +277,16 @@ fn deserialize_tuple(
false, false,
); );
let dispatch = if is_enum { let dispatch = if let Some(deserializer) = deserializer {
quote!(_serde::Deserializer::deserialize(#deserializer, #visitor_expr))
} else if is_enum {
quote!(_serde::de::VariantVisitor::visit_tuple(visitor, #nfields, #visitor_expr)) quote!(_serde::de::VariantVisitor::visit_tuple(visitor, #nfields, #visitor_expr))
} else if nfields == 1 { } else if nfields == 1 {
let type_name = item_attrs.name().deserialize_name(); let type_name = item_attrs.name().deserialize_name();
quote!(deserializer.deserialize_newtype_struct(#type_name, #visitor_expr)) quote!(_serde::Deserializer::deserialize_newtype_struct(deserializer, #type_name, #visitor_expr))
} else { } else {
let type_name = item_attrs.name().deserialize_name(); let type_name = item_attrs.name().deserialize_name();
quote!(deserializer.deserialize_tuple_struct(#type_name, #nfields, #visitor_expr)) quote!(_serde::Deserializer::deserialize_tuple_struct(deserializer, #type_name, #nfields, #visitor_expr))
}; };
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
@@ -297,14 +302,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) _serde::export::fmt::Formatter::write_str(formatter, #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
@@ -341,7 +346,7 @@ fn deserialize_seq(
let visit = match field.attrs.deserialize_with() { let visit = match field.attrs.deserialize_with() {
None => { None => {
let field_ty = &field.ty; let field_ty = &field.ty;
quote!(try!(visitor.visit::<#field_ty>())) quote!(try!(_serde::de::SeqVisitor::visit::<#field_ty>(&mut visitor)))
} }
Some(path) => { Some(path) => {
let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with( let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with(
@@ -349,7 +354,8 @@ fn deserialize_seq(
quote!({ quote!({
#wrapper #wrapper
#wrapper_impl #wrapper_impl
try!(visitor.visit::<#wrapper_ty>()).map(|wrap| wrap.value) try!(_serde::de::SeqVisitor::visit::<#wrapper_ty>(&mut visitor))
.map(|wrap| wrap.value)
}) })
} }
}; };
@@ -357,7 +363,7 @@ fn deserialize_seq(
let #var = match #visit { let #var = match #visit {
Some(value) => { value }, Some(value) => { value },
None => { None => {
return Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting)); return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
} }
}; };
}; };
@@ -379,7 +385,7 @@ fn deserialize_seq(
quote! { quote! {
#(#let_values)* #(#let_values)*
Ok(#result) _serde::export::Ok(#result)
} }
} }
@@ -408,10 +414,10 @@ 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)) _serde::export::Ok(#type_path(#value))
} }
} }
} }
@@ -423,7 +429,11 @@ fn deserialize_struct(
ty: syn::Ty, ty: syn::Ty,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item, item_attrs: &attr::Item,
deserializer: Option<Tokens>,
) -> Tokens { ) -> Tokens {
let is_enum = variant_ident.is_some();
let is_untagged = deserializer.is_some();
let where_clause = &impl_generics.where_clause; let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(impl_generics); let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(impl_generics);
@@ -453,15 +463,18 @@ fn deserialize_struct(
item_attrs, item_attrs,
); );
let is_enum = variant_ident.is_some(); let dispatch = if let Some(deserializer) = deserializer {
let dispatch = if is_enum { quote! {
_serde::Deserializer::deserialize(#deserializer, #visitor_expr)
}
} else if is_enum {
quote! { quote! {
_serde::de::VariantVisitor::visit_struct(visitor, FIELDS, #visitor_expr) _serde::de::VariantVisitor::visit_struct(visitor, FIELDS, #visitor_expr)
} }
} else { } else {
let type_name = item_attrs.name().deserialize_name(); let type_name = item_attrs.name().deserialize_name();
quote! { quote! {
deserializer.deserialize_struct(#type_name, FIELDS, #visitor_expr) _serde::Deserializer::deserialize_struct(deserializer, #type_name, FIELDS, #visitor_expr)
} }
}; };
@@ -472,6 +485,20 @@ fn deserialize_struct(
quote!(mut visitor) quote!(mut visitor)
}; };
let visit_seq = if is_untagged {
// untagged struct variants do not get a visit_seq method
None
} else {
Some(quote! {
#[inline]
fn visit_seq<__V>(self, #visitor_var: __V) -> _serde::export::Result<#ty, __V::Error>
where __V: _serde::de::SeqVisitor
{
#visit_seq
}
})
};
quote!({ quote!({
#field_visitor #field_visitor
@@ -480,19 +507,14 @@ 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) _serde::export::fmt::Formatter::write_str(formatter, #expecting)
} }
#[inline] #visit_seq
fn visit_seq<__V>(self, #visitor_var: __V) -> ::std::result::Result<#ty, __V::Error>
where __V: _serde::de::SeqVisitor
{
#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
@@ -511,6 +533,45 @@ fn deserialize_item_enum(
ty: syn::Ty, ty: syn::Ty,
variants: &[Variant], variants: &[Variant],
item_attrs: &attr::Item item_attrs: &attr::Item
) -> Tokens {
match *item_attrs.tag() {
attr::EnumTag::External => {
deserialize_externally_tagged_enum(
type_ident,
impl_generics,
ty,
variants,
item_attrs,
)
}
attr::EnumTag::Internal(ref tag) => {
deserialize_internally_tagged_enum(
type_ident,
impl_generics,
ty,
variants,
item_attrs,
tag,
)
}
attr::EnumTag::None => {
deserialize_untagged_enum(
type_ident,
impl_generics,
ty,
variants,
item_attrs,
)
}
}
}
fn deserialize_externally_tagged_enum(
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
) -> Tokens { ) -> Tokens {
let where_clause = &impl_generics.where_clause; let where_clause = &impl_generics.where_clause;
@@ -544,7 +605,7 @@ fn deserialize_item_enum(
.map(|(i, variant)| { .map(|(i, variant)| {
let variant_name = field_i(i); let variant_name = field_i(i);
let block = deserialize_variant( let block = deserialize_externally_tagged_variant(
type_ident, type_ident,
impl_generics, impl_generics,
ty.clone(), ty.clone(),
@@ -563,13 +624,14 @@ fn deserialize_item_enum(
// all variants have `#[serde(skip_deserializing)]`. // all variants have `#[serde(skip_deserializing)]`.
quote! { quote! {
// FIXME: Once we drop support for Rust 1.15: // FIXME: Once we drop support for Rust 1.15:
// let Err(err) = visitor.visit_variant::<__Field>(); // let _serde::export::Err(err) = _serde::de::EnumVisitor::visit_variant::<__Field>(visitor);
// Err(err) // _serde::export::Err(err)
visitor.visit_variant::<__Field>().map(|(impossible, _)| match impossible {}) _serde::de::EnumVisitor::visit_variant::<__Field>(visitor)
.map(|(impossible, _)| match impossible {})
} }
} else { } else {
quote! { quote! {
match try!(visitor.visit_variant()) { match try!(_serde::de::EnumVisitor::visit_variant(visitor)) {
#(#variant_arms)* #(#variant_arms)*
} }
} }
@@ -585,11 +647,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) _serde::export::fmt::Formatter::write_str(formatter, #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
@@ -598,11 +660,115 @@ fn deserialize_item_enum(
#variants_stmt #variants_stmt
deserializer.deserialize_enum(#type_name, VARIANTS, #visitor_expr) _serde::Deserializer::deserialize_enum(deserializer, #type_name, VARIANTS, #visitor_expr)
}) })
} }
fn deserialize_variant( fn deserialize_internally_tagged_enum(
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
tag: &str,
) -> Tokens {
let variant_names_idents: Vec<_> = variants.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
.collect();
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
let variant_visitor = deserialize_field_visitor(
variant_names_idents,
item_attrs,
true,
);
// Match arms to extract a variant from a string
let variant_arms = variants.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| {
let variant_name = field_i(i);
let block = deserialize_internally_tagged_variant(
type_ident,
impl_generics,
ty.clone(),
variant,
item_attrs,
quote!(_serde::de::private::ContentDeserializer::<__D::Error>::new(_tagged.content)),
);
quote! {
__Field::#variant_name => #block
}
});
quote!({
#variant_visitor
#variants_stmt
let _tagged = try!(_serde::Deserializer::deserialize(
deserializer,
_serde::de::private::TaggedContentVisitor::<__Field>::new(#tag)));
match _tagged.tag {
#(#variant_arms)*
}
})
}
fn deserialize_untagged_enum(
type_ident: &syn::Ident,
impl_generics: &syn::Generics,
ty: syn::Ty,
variants: &[Variant],
item_attrs: &attr::Item,
) -> Tokens {
let attempts = variants.iter()
.filter(|variant| !variant.attrs.skip_deserializing())
.map(|variant| {
deserialize_untagged_variant(
type_ident,
impl_generics,
ty.clone(),
variant,
item_attrs,
quote!(_serde::de::private::ContentRefDeserializer::<__D::Error>::new(&_content)),
)
});
// TODO this message could be better by saving the errors from the failed
// attempts. The heuristic used by TOML was to count the number of fields
// processed before an error, and use the error that happened after the
// largest number of fields. I'm not sure I like that. Maybe it would be
// better to save all the errors and combine them into one message that
// explains why none of the variants matched.
let fallthrough_msg = format!("data did not match any variant of untagged enum {}", type_ident);
quote!({
let _content = try!(<_serde::de::private::Content as _serde::Deserialize>::deserialize(deserializer));
#(
if let _serde::export::Ok(ok) = #attempts {
return _serde::export::Ok(ok);
}
)*
_serde::export::Err(_serde::de::Error::custom(#fallthrough_msg))
})
}
fn deserialize_externally_tagged_variant(
type_ident: &syn::Ident, type_ident: &syn::Ident,
generics: &syn::Generics, generics: &syn::Generics,
ty: syn::Ty, ty: syn::Ty,
@@ -615,11 +781,11 @@ fn deserialize_variant(
Style::Unit => { Style::Unit => {
quote!({ quote!({
try!(_serde::de::VariantVisitor::visit_unit(visitor)); try!(_serde::de::VariantVisitor::visit_unit(visitor));
Ok(#type_ident::#variant_ident) _serde::export::Ok(#type_ident::#variant_ident)
}) })
} }
Style::Newtype => { Style::Newtype => {
deserialize_newtype_variant( deserialize_externally_tagged_newtype_variant(
type_ident, type_ident,
variant_ident, variant_ident,
generics, generics,
@@ -634,6 +800,7 @@ fn deserialize_variant(
ty, ty,
&variant.fields, &variant.fields,
item_attrs, item_attrs,
None,
) )
} }
Style::Struct => { Style::Struct => {
@@ -644,22 +811,115 @@ fn deserialize_variant(
ty, ty,
&variant.fields, &variant.fields,
item_attrs, item_attrs,
None,
) )
} }
} }
} }
fn deserialize_newtype_variant( fn deserialize_internally_tagged_variant(
type_ident: &syn::Ident,
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
item_attrs: &attr::Item,
deserializer: Tokens,
) -> Tokens {
let variant_ident = &variant.ident;
match variant.style {
Style::Unit => {
let type_name = type_ident.as_ref();
let variant_name = variant.ident.as_ref();
quote!({
try!(_serde::Deserializer::deserialize(#deserializer, _serde::de::private::InternallyTaggedUnitVisitor::new(#type_name, #variant_name)));
_serde::export::Ok(#type_ident::#variant_ident)
})
}
Style::Newtype | Style::Struct => {
deserialize_untagged_variant(
type_ident,
generics,
ty,
variant,
item_attrs,
deserializer,
)
}
Style::Tuple => unreachable!("checked in serde_codegen_internals"),
}
}
fn deserialize_untagged_variant(
type_ident: &syn::Ident,
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
item_attrs: &attr::Item,
deserializer: Tokens,
) -> Tokens {
let variant_ident = &variant.ident;
match variant.style {
Style::Unit => {
let type_name = type_ident.as_ref();
let variant_name = variant.ident.as_ref();
quote! {
_serde::export::Result::map(
_serde::Deserializer::deserialize(
#deserializer,
_serde::de::private::UntaggedUnitVisitor::new(#type_name, #variant_name)
),
|()| #type_ident::#variant_ident)
}
}
Style::Newtype => {
deserialize_untagged_newtype_variant(
type_ident,
variant_ident,
generics,
&variant.fields[0],
deserializer,
)
}
Style::Tuple => {
deserialize_tuple(
type_ident,
Some(variant_ident),
generics,
ty,
&variant.fields,
item_attrs,
Some(deserializer),
)
}
Style::Struct => {
deserialize_struct(
type_ident,
Some(variant_ident),
generics,
ty,
&variant.fields,
item_attrs,
Some(deserializer),
)
}
}
}
fn deserialize_externally_tagged_newtype_variant(
type_ident: &syn::Ident, type_ident: &syn::Ident,
variant_ident: &syn::Ident, variant_ident: &syn::Ident,
impl_generics: &syn::Generics, impl_generics: &syn::Generics,
field: &Field, field: &Field,
) -> Tokens { ) -> Tokens {
let visit = match field.attrs.deserialize_with() { match field.attrs.deserialize_with() {
None => { None => {
let field_ty = &field.ty; let field_ty = &field.ty;
quote! { quote! {
try!(_serde::de::VariantVisitor::visit_newtype::<#field_ty>(visitor)) _serde::export::Result::map(
_serde::de::VariantVisitor::visit_newtype::<#field_ty>(visitor),
#type_ident::#variant_ident),
} }
} }
Some(path) => { Some(path) => {
@@ -668,12 +928,41 @@ fn deserialize_newtype_variant(
quote!({ quote!({
#wrapper #wrapper
#wrapper_impl #wrapper_impl
try!(_serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(visitor)).value _serde::export::Result::map(
_serde::de::VariantVisitor::visit_newtype::<#wrapper_ty>(visitor),
|_wrapper| #type_ident::#variant_ident(_wrapper.value))
})
}
}
}
fn deserialize_untagged_newtype_variant(
type_ident: &syn::Ident,
variant_ident: &syn::Ident,
impl_generics: &syn::Generics,
field: &Field,
deserializer: Tokens,
) -> Tokens {
match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
quote!({
_serde::export::Result::map(
<#field_ty as _serde::Deserialize>::deserialize(#deserializer),
#type_ident::#variant_ident)
})
}
Some(path) => {
let (wrapper, wrapper_impl, wrapper_ty) = wrap_deserialize_with(
type_ident, impl_generics, field.ty, path);
quote!({
#wrapper
#wrapper_impl
_serde::export::Result::map(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer),
|_wrapper| #type_ident::#variant_ident(_wrapper.value))
}) })
} }
};
quote! {
Ok(#type_ident::#variant_ident(#visit)),
} }
} }
@@ -682,7 +971,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,20 +981,51 @@ 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 => _serde::export::Ok(__Field::#field_idents),
)*
_ => _serde::export::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)) _serde::export::Err(_serde::de::Error::unknown_variant(value, VARIANTS))
} }
} else if item_attrs.deny_unknown_fields() { } else if item_attrs.deny_unknown_fields() {
quote! { quote! {
Err(_serde::de::Error::unknown_field(value, FIELDS)) _serde::export::Err(_serde::de::Error::unknown_field(value, FIELDS))
} }
} else { } else {
quote! { quote! {
Ok(__Field::__ignore) _serde::export::Ok(__Field::__ignore)
} }
}; };
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 +1035,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,23 +1043,39 @@ 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") _serde::export::fmt::Formatter::write_str(formatter, "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 => _serde::export::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 => _serde::export::Ok(__Field::#field_idents),
)*
_ => {
#bytes_to_str
#fallthrough_arm
}
}
}
} }
deserializer.deserialize_struct_field(__FieldVisitor) _serde::Deserializer::deserialize_struct_field(deserializer, __FieldVisitor)
} }
} }
} }
@@ -800,7 +1137,7 @@ fn deserialize_map(
.map(|&(field, ref name)| { .map(|&(field, ref name)| {
let field_ty = &field.ty; let field_ty = &field.ty;
quote! { quote! {
let mut #name: Option<#field_ty> = None; let mut #name: _serde::export::Option<#field_ty> = _serde::export::None;
} }
}); });
@@ -814,7 +1151,7 @@ fn deserialize_map(
None => { None => {
let field_ty = &field.ty; let field_ty = &field.ty;
quote! { quote! {
try!(visitor.visit_value::<#field_ty>()) try!(_serde::de::MapVisitor::visit_value::<#field_ty>(&mut visitor))
} }
} }
Some(path) => { Some(path) => {
@@ -823,16 +1160,16 @@ fn deserialize_map(
quote!({ quote!({
#wrapper #wrapper
#wrapper_impl #wrapper_impl
try!(visitor.visit_value::<#wrapper_ty>()).value try!(_serde::de::MapVisitor::visit_value::<#wrapper_ty>(&mut visitor)).value
}) })
} }
}; };
quote! { quote! {
__Field::#name => { __Field::#name => {
if #name.is_some() { if _serde::export::Option::is_some(&#name) {
return Err(<__V::Error as _serde::de::Error>::duplicate_field(#deser_name)); return _serde::export::Err(<__V::Error as _serde::de::Error>::duplicate_field(#deser_name));
} }
#name = Some(#visit); #name = _serde::export::Some(#visit);
} }
} }
}); });
@@ -842,7 +1179,7 @@ fn deserialize_map(
None None
} else { } else {
Some(quote! { Some(quote! {
_ => { let _ = try!(visitor.visit_value::<_serde::de::impls::IgnoredAny>()); } _ => { let _ = try!(_serde::de::MapVisitor::visit_value::<_serde::de::impls::IgnoredAny>(&mut visitor)); }
}) })
}; };
@@ -850,12 +1187,13 @@ fn deserialize_map(
let match_keys = if item_attrs.deny_unknown_fields() && all_skipped { let match_keys = if item_attrs.deny_unknown_fields() && all_skipped {
quote! { quote! {
// FIXME: Once we drop support for Rust 1.15: // FIXME: Once we drop support for Rust 1.15:
// let None::<__Field> = try!(visitor.visit_key()); // let _serde::export::None::<__Field> = try!(_serde::de::MapVisitor::visit_key(&mut visitor));
try!(visitor.visit_key::<__Field>()).map(|impossible| match impossible {}); try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut visitor))
.map(|impossible| match impossible {});
} }
} else { } else {
quote! { quote! {
while let Some(key) = try!(visitor.visit_key::<__Field>()) { while let _serde::export::Some(key) = try!(_serde::de::MapVisitor::visit_key::<__Field>(&mut visitor)) {
match key { match key {
#(#value_arms)* #(#value_arms)*
#ignored_arm #ignored_arm
@@ -871,8 +1209,8 @@ fn deserialize_map(
quote! { quote! {
let #name = match #name { let #name = match #name {
Some(#name) => #name, _serde::export::Some(#name) => #name,
None => #missing_expr _serde::export::None => #missing_expr
}; };
} }
}); });
@@ -895,7 +1233,7 @@ fn deserialize_map(
#(#extract_values)* #(#extract_values)*
Ok(#struct_path { #(#result),* }) _serde::export::Ok(#struct_path { #(#result),* })
} }
} }
@@ -933,18 +1271,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 { _serde::export::Ok(__SerdeDeserializeWithStruct {
value: value, value: value,
phantom: ::std::marker::PhantomData, phantom: _serde::export::PhantomData,
}) })
} }
} }
@@ -956,7 +1294,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());
@@ -973,7 +1311,7 @@ fn expr_is_missing(attrs: &attr::Field) -> Tokens {
} }
Some(_) => { Some(_) => {
quote! { quote! {
return Err(<__V::Error as _serde::de::Error>::missing_field(#name)) return _serde::export::Err(<__V::Error as _serde::de::Error>::missing_field(#name))
} }
} }
} }
+20 -4
View File
@@ -1,11 +1,26 @@
extern crate proc_macro; #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
extern crate serde_codegen; #![cfg_attr(feature = "cargo-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 +28,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
@@ -125,7 +125,7 @@ fn serialize_unit_struct(item_attrs: &attr::Item) -> Tokens {
let type_name = item_attrs.name().serialize_name(); let type_name = item_attrs.name().serialize_name();
quote! { quote! {
_serializer.serialize_unit_struct(#type_name) _serde::Serializer::serialize_unit_struct(_serializer, #type_name)
} }
} }
@@ -144,7 +144,7 @@ fn serialize_newtype_struct(
} }
quote! { quote! {
_serializer.serialize_newtype_struct(#type_name, #field_expr) _serde::Serializer::serialize_newtype_struct(_serializer, #type_name, #field_expr)
} }
} }
@@ -167,7 +167,7 @@ fn serialize_tuple_struct(
let let_mut = mut_if(len > 0); let let_mut = mut_if(len > 0);
quote! { quote! {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_struct(#type_name, #len)); let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(_serializer, #type_name, #len));
#(#serialize_stmts)* #(#serialize_stmts)*
_serde::ser::SerializeTupleStruct::end(__serde_state) _serde::ser::SerializeTupleStruct::end(__serde_state)
} }
@@ -208,7 +208,7 @@ fn serialize_struct(
.fold(quote!(0), |sum, expr| quote!(#sum + #expr)); .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote! { quote! {
let #let_mut __serde_state = try!(_serializer.serialize_struct(#type_name, #len)); let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(_serializer, #type_name, #len));
#(#serialize_fields)* #(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state) _serde::ser::SerializeStruct::end(__serde_state)
} }
@@ -251,16 +251,13 @@ fn serialize_variant(
variant_index: usize, variant_index: usize,
item_attrs: &attr::Item, item_attrs: &attr::Item,
) -> Tokens { ) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let variant_ident = variant.ident.clone(); let variant_ident = variant.ident.clone();
let variant_name = variant.attrs.name().serialize_name();
if variant.attrs.skip_serializing() { if variant.attrs.skip_serializing() {
let skipped_msg = format!("the enum variant {}::{} cannot be serialized", let skipped_msg = format!("the enum variant {}::{} cannot be serialized",
type_ident, variant_ident); type_ident, variant_ident);
let skipped_err = quote! { let skipped_err = quote! {
Err(_serde::ser::Error::custom(#skipped_msg)) _serde::export::Err(_serde::ser::Error::custom(#skipped_msg))
}; };
let fields_pat = match variant.style { let fields_pat = match variant.style {
Style::Unit => quote!(), Style::Unit => quote!(),
@@ -271,139 +268,351 @@ fn serialize_variant(
#type_ident::#variant_ident #fields_pat => #skipped_err, #type_ident::#variant_ident #fields_pat => #skipped_err,
} }
} else { // variant wasn't skipped } else { // variant wasn't skipped
match variant.style { let case = match variant.style {
Style::Unit => { Style::Unit => {
quote! { quote! {
#type_ident::#variant_ident => #type_ident::#variant_ident
_serde::Serializer::serialize_unit_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
),
} }
}, }
Style::Newtype => { Style::Newtype => {
let block = serialize_newtype_variant(
type_name,
variant_index,
variant_name,
ty,
generics,
&variant.fields[0],
);
quote! { quote! {
#type_ident::#variant_ident(ref __simple_value) => #block, #type_ident::#variant_ident(ref __simple_value)
} }
}, }
Style::Tuple => { Style::Tuple => {
let field_names = (0 .. variant.fields.len()) let field_names = (0 .. variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i))); .map(|i| Ident::new(format!("__field{}", i)));
let block = serialize_tuple_variant(
type_name,
variant_index,
variant_name,
generics,
ty,
&variant.fields,
);
quote! { quote! {
#type_ident::#variant_ident(#(ref #field_names),*) => { #block } #type_ident::#variant_ident(#(ref #field_names),*)
} }
} }
Style::Struct => { Style::Struct => {
let fields = variant.fields.iter() let fields = variant.fields.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields")); .map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
quote! {
#type_ident::#variant_ident { #(ref #fields),* }
}
}
};
let block = serialize_struct_variant( let body = match *item_attrs.tag() {
variant_index, attr::EnumTag::External => {
variant_name, serialize_externally_tagged_variant(
generics, generics,
ty, ty,
&variant.fields, variant,
variant_index,
item_attrs, item_attrs,
); )
}
attr::EnumTag::Internal(ref tag) => {
serialize_internally_tagged_variant(
type_ident.as_ref(),
variant_ident.as_ref(),
generics,
ty,
variant,
item_attrs,
tag,
)
}
attr::EnumTag::None => {
serialize_untagged_variant(
generics,
ty,
variant,
item_attrs,
)
}
};
quote! { quote! {
#type_ident::#variant_ident { #(ref #fields),* } => { #block } #case => #body
} }
}
}
fn serialize_externally_tagged_variant(
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item,
) -> Tokens {
let type_name = item_attrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
match variant.style {
Style::Unit => {
quote! {
_serde::Serializer::serialize_unit_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
),
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&ty, generics, field.ty, path, field_expr);
}
quote! {
_serde::Serializer::serialize_newtype_variant(
_serializer,
#type_name,
#variant_index,
#variant_name,
#field_expr,
),
}
}
Style::Tuple => {
let block = serialize_tuple_variant(
TupleVariant::ExternallyTagged {
type_name: type_name,
variant_index: variant_index,
variant_name: variant_name,
},
generics,
ty,
&variant.fields,
);
quote! {
{ #block }
}
}
Style::Struct => {
let block = serialize_struct_variant(
StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
},
generics,
ty,
&variant.fields,
item_attrs,
);
quote! {
{ #block }
} }
} }
} }
} }
fn serialize_newtype_variant( fn serialize_internally_tagged_variant(
type_name: String, type_ident: &str,
variant_index: usize, variant_ident: &str,
variant_name: String,
item_ty: syn::Ty,
generics: &syn::Generics, generics: &syn::Generics,
field: &Field, ty: syn::Ty,
variant: &Variant,
item_attrs: &attr::Item,
tag: &str,
) -> Tokens { ) -> Tokens {
let mut field_expr = quote!(__simple_value); let type_name = item_attrs.name().serialize_name();
if let Some(path) = field.attrs.serialize_with() { let variant_name = variant.attrs.name().serialize_name();
field_expr = wrap_serialize_with(
&item_ty, generics, field.ty, path, field_expr);
}
quote! { match variant.style {
_serde::Serializer::serialize_newtype_variant( Style::Unit => {
_serializer, quote!({
#type_name, let mut __struct = try!(_serde::Serializer::serialize_struct(
#variant_index, _serializer, #type_name, 1));
#variant_name, try!(_serde::ser::SerializeStruct::serialize_field(
#field_expr, &mut __struct, #tag, #variant_name));
) _serde::ser::SerializeStruct::end(__struct)
})
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&ty, generics, field.ty, path, field_expr);
}
quote! {
_serde::ser::private::serialize_tagged_newtype(
_serializer,
#type_ident,
#variant_ident,
#tag,
#variant_name,
#field_expr,
),
}
}
Style::Struct => {
let block = serialize_struct_variant(
StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
},
generics,
ty,
&variant.fields,
item_attrs,
);
quote! {
{ #block }
}
}
Style::Tuple => unreachable!("checked in serde_codegen_internals"),
} }
} }
fn serialize_untagged_variant(
generics: &syn::Generics,
ty: syn::Ty,
variant: &Variant,
item_attrs: &attr::Item,
) -> Tokens {
match variant.style {
Style::Unit => {
quote! {
_serde::Serializer::serialize_unit(_serializer),
}
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__simple_value);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(
&ty, generics, field.ty, path, field_expr);
}
quote! {
_serde::Serialize::serialize(#field_expr, _serializer),
}
}
Style::Tuple => {
let block = serialize_tuple_variant(
TupleVariant::Untagged,
generics,
ty,
&variant.fields,
);
quote! {
{ #block }
}
}
Style::Struct => {
let block = serialize_struct_variant(
StructVariant::Untagged,
generics,
ty,
&variant.fields,
item_attrs,
);
quote! {
{ #block }
}
}
}
}
enum TupleVariant {
ExternallyTagged {
type_name: String,
variant_index: usize,
variant_name: String,
},
Untagged,
}
fn serialize_tuple_variant( fn serialize_tuple_variant(
type_name: String, context: TupleVariant,
variant_index: usize,
variant_name: String,
generics: &syn::Generics, generics: &syn::Generics,
structure_ty: syn::Ty, structure_ty: syn::Ty,
fields: &[Field], fields: &[Field],
) -> Tokens { ) -> Tokens {
let method = match context {
TupleVariant::ExternallyTagged{..} => {
quote!(_serde::ser::SerializeTupleVariant::serialize_field)
}
TupleVariant::Untagged => {
quote!(_serde::ser::SerializeTuple::serialize_element)
}
};
let serialize_stmts = serialize_tuple_struct_visitor( let serialize_stmts = serialize_tuple_struct_visitor(
structure_ty, structure_ty,
fields, fields,
generics, generics,
true, true,
quote!(_serde::ser::SerializeTupleVariant::serialize_field), method,
); );
let len = serialize_stmts.len(); let len = serialize_stmts.len();
let let_mut = mut_if(len > 0); let let_mut = mut_if(len > 0);
quote! { match context {
let #let_mut __serde_state = try!(_serializer.serialize_tuple_variant( TupleVariant::ExternallyTagged { type_name, variant_index, variant_name } => {
#type_name, quote! {
#variant_index, let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_variant(
#variant_name, _serializer,
#len)); #type_name,
#(#serialize_stmts)* #variant_index,
_serde::ser::SerializeTupleVariant::end(__serde_state) #variant_name,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
}
TupleVariant::Untagged => {
quote! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple(
_serializer,
#len));
#(#serialize_stmts)*
_serde::ser::SerializeTuple::end(__serde_state)
}
}
} }
} }
fn serialize_struct_variant( enum StructVariant<'a> {
variant_index: usize, ExternallyTagged {
variant_name: String, variant_index: usize,
variant_name: String,
},
InternallyTagged {
tag: &'a str,
variant_name: String,
},
Untagged,
}
fn serialize_struct_variant<'a>(
context: StructVariant<'a>,
generics: &syn::Generics, generics: &syn::Generics,
ty: syn::Ty, ty: syn::Ty,
fields: &[Field], fields: &[Field],
item_attrs: &attr::Item, item_attrs: &attr::Item,
) -> Tokens { ) -> Tokens {
let method = match context {
StructVariant::ExternallyTagged{..} => {
quote!(_serde::ser::SerializeStructVariant::serialize_field)
}
StructVariant::InternallyTagged{..} | StructVariant::Untagged => {
quote!(_serde::ser::SerializeStruct::serialize_field)
}
};
let serialize_fields = serialize_struct_visitor( let serialize_fields = serialize_struct_visitor(
ty.clone(), ty.clone(),
fields, fields,
generics, generics,
true, true,
quote!(_serde::ser::SerializeStructVariant::serialize_field), method,
); );
let item_name = item_attrs.name().serialize_name(); let item_name = item_attrs.name().serialize_name();
@@ -425,15 +634,47 @@ fn serialize_struct_variant(
}) })
.fold(quote!(0), |sum, expr| quote!(#sum + #expr)); .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote! { match context {
let #let_mut __serde_state = try!(_serializer.serialize_struct_variant( StructVariant::ExternallyTagged { variant_index, variant_name } => {
#item_name, quote! {
#variant_index, let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct_variant(
#variant_name, _serializer,
#len, #item_name,
)); #variant_index,
#(#serialize_fields)* #variant_name,
_serde::ser::SerializeStructVariant::end(__serde_state) #len,
));
#(#serialize_fields)*
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote! {
let mut __serde_state = try!(_serde::Serializer::serialize_struct(
_serializer,
#item_name,
#len + 1,
));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
#tag,
#variant_name,
));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
StructVariant::Untagged => {
quote! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(
_serializer,
#item_name,
#len,
));
#(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state)
}
}
} }
} }
@@ -537,20 +778,20 @@ fn wrap_serialize_with(
quote!({ quote!({
struct __SerializeWith #wrapper_generics #where_clause { struct __SerializeWith #wrapper_generics #where_clause {
value: &'__a #field_ty, value: &'__a #field_ty,
phantom: ::std::marker::PhantomData<#item_ty>, phantom: _serde::export::PhantomData<#item_ty>,
} }
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: _serde::export::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;
+5 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "0.9.0-rc2" version = "0.9.7"
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"
@@ -12,4 +12,7 @@ keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"] include = ["Cargo.toml", "src/**/*.rs"]
[dependencies] [dependencies]
serde = { version = "0.9.0-rc2", path = "../serde" } serde = { version = "0.9", path = "../serde" }
[badges]
travis-ci = { repository = "serde-rs/serde" }
+57 -435
View File
@@ -47,91 +47,29 @@ impl<I> Deserializer<I>
} }
} }
fn visit_seq<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error> fn visit_seq<V>(&mut self, len: Option<usize>, sep: Token<'static>, end: Token<'static>, visitor: V) -> Result<V::Value, Error>
where V: Visitor, where V: Visitor,
{ {
let value = try!(visitor.visit_seq(DeserializerSeqVisitor { let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
de: self, de: self,
len: len, len: len,
sep: sep,
end: end.clone(),
})); }));
try!(self.expect_token(Token::SeqEnd)); try!(self.expect_token(end));
Ok(value) Ok(value)
} }
fn visit_array<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error> fn visit_map<V>(&mut self, len: Option<usize>, sep: Token<'static>, end: Token<'static>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerArrayVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::SeqEnd));
Ok(value)
}
fn visit_tuple<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerTupleVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::TupleEnd));
Ok(value)
}
fn visit_tuple_struct<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerTupleStructVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::TupleStructEnd));
Ok(value)
}
fn visit_variant_seq<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_seq(DeserializerVariantSeqVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::EnumSeqEnd));
Ok(value)
}
fn visit_map<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor, where V: Visitor,
{ {
let value = try!(visitor.visit_map(DeserializerMapVisitor { let value = try!(visitor.visit_map(DeserializerMapVisitor {
de: self, de: self,
len: len, len: len,
sep: sep,
end: end.clone(),
})); }));
try!(self.expect_token(Token::MapEnd)); try!(self.expect_token(end));
Ok(value)
}
fn visit_struct<V>(&mut self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_map(DeserializerStructVisitor {
de: self,
len: fields.len(),
}));
try!(self.expect_token(Token::StructEnd));
Ok(value)
}
fn visit_variant_map<V>(&mut self, len: Option<usize>, visitor: V) -> Result<V::Value, Error>
where V: Visitor,
{
let value = try!(visitor.visit_map(DeserializerVariantMapVisitor {
de: self,
len: len,
}));
try!(self.expect_token(Token::EnumMapEnd));
Ok(value) Ok(value)
} }
} }
@@ -141,97 +79,9 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
{ {
type Error = Error; type Error = Error;
fn deserialize_seq<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error> forward_to_deserialize! {
where __V: de::Visitor { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit
self.deserialize(visitor) seq bytes byte_buf map struct_field ignored_any
}
fn deserialize_struct_field<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_map<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_unit<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bytes<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_byte_buf<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_ignored_any<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_string<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_str<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_char<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i16<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i8<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u16<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u8<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f32<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f64<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bool<__V>(self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::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>
@@ -239,12 +89,10 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
{ {
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),
@@ -261,16 +109,22 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
Some(Token::Unit) => visitor.visit_unit(), Some(Token::Unit) => visitor.visit_unit(),
Some(Token::UnitStruct(_name)) => visitor.visit_unit(), Some(Token::UnitStruct(_name)) => visitor.visit_unit(),
Some(Token::SeqStart(len)) => { Some(Token::SeqStart(len)) => {
self.visit_seq(len, visitor) self.visit_seq(len, Token::SeqSep, Token::SeqEnd, visitor)
} }
Some(Token::SeqArrayStart(len))| Some(Token::TupleStructStart(_, len)) => { Some(Token::SeqArrayStart(len)) => {
self.visit_seq(Some(len), visitor) self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(Token::TupleStart(len)) => {
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
}
Some(Token::TupleStructStart(_, len)) => {
self.visit_seq(Some(len), Token::TupleStructSep, Token::TupleStructEnd, visitor)
} }
Some(Token::MapStart(len)) => { Some(Token::MapStart(len)) => {
self.visit_map(len, visitor) self.visit_map(len, Token::MapSep, Token::MapEnd, visitor)
} }
Some(Token::StructStart(_, len)) => { Some(Token::StructStart(_, len)) => {
self.visit_map(Some(len), visitor) self.visit_map(Some(len), Token::StructSep, Token::StructEnd, visitor)
} }
Some(token) => Err(Error::UnexpectedToken(token)), Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
@@ -283,7 +137,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 +145,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 +176,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),
} }
} }
@@ -374,7 +224,7 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
match self.tokens.peek() { match self.tokens.peek() {
Some(&Token::SeqArrayStart(_)) => { Some(&Token::SeqArrayStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_array(len, visitor) self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
} }
Some(_) => self.deserialize(visitor), Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
@@ -387,29 +237,25 @@ 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()
} }
Some(&Token::SeqStart(_)) => { Some(&Token::SeqStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_seq(Some(len), visitor) self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
} }
Some(&Token::SeqArrayStart(_)) => { Some(&Token::SeqArrayStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_array(len, visitor) self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
} }
Some(&Token::TupleStart(_)) => { Some(&Token::TupleStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_tuple(len, visitor) self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
} }
Some(&Token::TupleStructStart(_, _)) => { Some(&Token::TupleStructStart(_, _)) => {
self.tokens.next(); self.tokens.next();
self.visit_tuple_struct(len, visitor) self.visit_seq(Some(len), Token::TupleStructSep, Token::TupleStructEnd, visitor)
} }
Some(_) => self.deserialize(visitor), Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
@@ -437,20 +283,20 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
} }
Some(&Token::SeqStart(_)) => { Some(&Token::SeqStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_seq(Some(len), visitor) self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
} }
Some(&Token::SeqArrayStart(_)) => { Some(&Token::SeqArrayStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_array(len, visitor) self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
} }
Some(&Token::TupleStart(_)) => { Some(&Token::TupleStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_tuple(len, visitor) self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
} }
Some(&Token::TupleStructStart(n, _)) => { Some(&Token::TupleStructStart(n, _)) => {
self.tokens.next(); self.tokens.next();
if name == n { if name == n {
self.visit_tuple_struct(len, visitor) self.visit_seq(Some(len), Token::TupleStructSep, Token::TupleStructEnd, visitor)
} else { } else {
Err(Error::InvalidName(n)) Err(Error::InvalidName(n))
} }
@@ -470,14 +316,14 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
Some(&Token::StructStart(n, _)) => { Some(&Token::StructStart(n, _)) => {
self.tokens.next(); self.tokens.next();
if name == n { if name == n {
self.visit_struct(fields, visitor) self.visit_map(Some(fields.len()), Token::StructSep, Token::StructEnd, visitor)
} else { } else {
Err(Error::InvalidName(n)) Err(Error::InvalidName(n))
} }
} }
Some(&Token::MapStart(_)) => { Some(&Token::MapStart(_)) => {
self.tokens.next(); self.tokens.next();
self.visit_map(Some(fields.len()), visitor) self.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor)
} }
Some(_) => self.deserialize(visitor), Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
@@ -490,6 +336,8 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
struct DeserializerSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> { struct DeserializerSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>, de: &'a mut Deserializer<I>,
len: Option<usize>, len: Option<usize>,
sep: Token<'static>,
end: Token<'static>,
} }
impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I> impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I>
@@ -500,158 +348,15 @@ impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I>
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error> fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed, where T: DeserializeSeed,
{ {
match self.de.tokens.peek() { if self.de.tokens.peek() == Some(&self.end) {
Some(&Token::SeqSep) => { return Ok(None);
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::SeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
} }
} match self.de.tokens.next() {
Some(ref token) if *token == self.sep => {
fn size_hint(&self) -> (usize, Option<usize>) { self.len = self.len.map(|len| len.saturating_sub(1));
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerArrayVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerArrayVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::SeqSep) => {
self.de.tokens.next();
self.len -= 1;
seed.deserialize(&mut *self.de).map(Some) seed.deserialize(&mut *self.de).map(Some)
} }
Some(&Token::SeqEnd) => Ok(None), Some(other) => Err(Error::UnexpectedToken(other)),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerTupleVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerTupleVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::TupleSep) => {
self.de.tokens.next();
self.len -= 1;
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::TupleEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerTupleStructVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> SeqVisitor for DeserializerTupleStructVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::TupleStructSep) => {
self.de.tokens.next();
self.len -= 1;
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::TupleStructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantSeqVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> SeqVisitor for DeserializerVariantSeqVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::EnumSeqSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| len - 1);
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::EnumSeqEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
@@ -667,6 +372,8 @@ impl<'a, I> SeqVisitor for DeserializerVariantSeqVisitor<'a, I>
struct DeserializerMapVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> { struct DeserializerMapVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>, de: &'a mut Deserializer<I>,
len: Option<usize>, len: Option<usize>,
sep: Token<'static>,
end: Token<'static>,
} }
impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I> impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
@@ -677,17 +384,15 @@ impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error> fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed, where K: DeserializeSeed,
{ {
match self.de.tokens.peek() { if self.de.tokens.peek() == Some(&self.end) {
Some(&Token::MapSep) => { return Ok(None);
self.de.tokens.next(); }
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 }); match self.de.tokens.next() {
Some(ref token) if *token == self.sep => {
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some) seed.deserialize(&mut *self.de).map(Some)
} }
Some(&Token::MapEnd) => Ok(None), Some(other) => Err(Error::UnexpectedToken(other)),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
@@ -706,47 +411,6 @@ impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct DeserializerStructVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: usize,
}
impl<'a, I> MapVisitor for DeserializerStructVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::StructSep) => {
self.de.tokens.next();
self.len = self.len.saturating_sub(1);
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::StructEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed,
{
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
//////////////////////////////////////////////////////////////////////////
struct DeserializerEnumVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> { struct DeserializerEnumVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>, de: &'a mut Deserializer<I>,
} }
@@ -821,7 +485,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
let token = self.de.tokens.next().unwrap(); let token = self.de.tokens.next().unwrap();
if len == enum_len { if len == enum_len {
self.de.visit_variant_seq(Some(len), visitor) self.de.visit_seq(Some(len), Token::EnumSeqSep, Token::EnumSeqEnd, visitor)
} else { } else {
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
@@ -830,7 +494,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
let token = self.de.tokens.next().unwrap(); let token = self.de.tokens.next().unwrap();
if len == enum_len { if len == enum_len {
self.de.visit_seq(Some(len), visitor) self.de.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
} else { } else {
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
@@ -852,7 +516,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
let token = self.de.tokens.next().unwrap(); let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len { if fields.len() == enum_len {
self.de.visit_variant_map(Some(fields.len()), visitor) self.de.visit_map(Some(fields.len()), Token::EnumMapSep, Token::EnumMapEnd, visitor)
} else { } else {
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
@@ -861,7 +525,7 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
let token = self.de.tokens.next().unwrap(); let token = self.de.tokens.next().unwrap();
if fields.len() == enum_len { if fields.len() == enum_len {
self.de.visit_map(Some(fields.len()), visitor) self.de.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor)
} else { } else {
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
@@ -873,45 +537,3 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
} }
} }
} }
//////////////////////////////////////////////////////////////////////////
struct DeserializerVariantMapVisitor<'a, I: 'a> where I: Iterator<Item=Token<'static>> {
de: &'a mut Deserializer<I>,
len: Option<usize>,
}
impl<'a, I> MapVisitor for DeserializerVariantMapVisitor<'a, I>
where I: Iterator<Item=Token<'static>>,
{
type Error = Error;
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed,
{
match self.de.tokens.peek() {
Some(&Token::EnumMapSep) => {
self.de.tokens.next();
self.len = self.len.map(|len| if len > 0 { len - 1} else { 0 });
seed.deserialize(&mut *self.de).map(Some)
}
Some(&Token::EnumMapEnd) => Ok(None),
Some(_) => {
let token = self.de.tokens.next().unwrap();
Err(Error::UnexpectedToken(token))
}
None => Err(Error::EndOfTokens),
}
}
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed,
{
seed.deserialize(&mut *self.de)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len.unwrap_or(0);
(len, self.len)
}
}
+1
View File
@@ -1,3 +1,4 @@
#[macro_use]
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),
+9 -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,23 @@ 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 = [
"compiletest_rs",
[build-dependencies] "serde/unstable-testing",
serde_codegen = { path = "../serde_codegen", features = ["with-syntex"] } ]
[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 } compiletest_rs = { version = "0.2", optional = true }
[[test]] [[test]]
name = "test" name = "test"
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "serde_test_suite_deps"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[workspace]
[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" }
+52
View File
@@ -0,0 +1,52 @@
#![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) -> ! {
unsafe {
libc::abort()
}
}
//////////////////////////////////////////////////////////////////////////////
#[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 },
}
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S { struct S {
#[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize` #[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize`
x: (), x: (),
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S { struct S {
#[serde(rename="x")] #[serde(rename="x")]
#[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename` #[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S { struct S {
#[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename` #[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (), x: (),
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S { struct S {
#[serde(rename(serialize="x"))] #[serde(rename(serialize="x"))]
#[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename` #[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename`
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S { struct S {
#[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename` #[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename`
x: (), x: (),
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S { struct S {
#[serde(rename(serialize="x"))] #[serde(rename(serialize="x"))]
#[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename` #[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename`
@@ -0,0 +1,10 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] cannot be used with tuple variants
enum E {
Tuple(u8, u8),
}
fn main() {}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] can only be used on enums
struct S;
fn main() {}
@@ -0,0 +1,12 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(untagged)]
#[serde(tag = "type")] //~^^ HELP: enum cannot be both untagged and internally tagged
enum E {
A(u8),
B(String),
}
fn main() {}
@@ -0,0 +1,8 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(untagged)] //~^ HELP: #[serde(untagged)] can only be used on enums
struct S;
fn main() {}
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize, Deserialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize, Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> { struct Test<'a> {
s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str
} }
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(abc="xyz")] //~^ HELP: unknown serde container attribute `abc` #[serde(abc="xyz")] //~^ HELP: unknown serde container attribute `abc`
struct A { struct A {
x: u32, x: u32,
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct C { struct C {
#[serde(abc="xyz")] //~^^ HELP: unknown serde field attribute `abc` #[serde(abc="xyz")] //~^^ HELP: unknown serde field attribute `abc`
x: u32, x: u32,
@@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: custom derive attribute panicked #[derive(Serialize)] //~ ERROR: proc-macro derive panicked
enum E { enum E {
#[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc` #[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc`
V, V,
+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()
+23
View File
@@ -0,0 +1,23 @@
#![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)],
@@ -229,7 +225,7 @@ declare_tests! {
], ],
() => &[ () => &[
Token::TupleStructStart("Anything", 0), Token::TupleStructStart("Anything", 0),
Token::SeqEnd, Token::TupleStructEnd,
], ],
} }
test_unit_struct { test_unit_struct {
@@ -334,7 +330,7 @@ declare_tests! {
], ],
BTreeSet::<isize>::new() => &[ BTreeSet::<isize>::new() => &[
Token::TupleStructStart("Anything", 0), Token::TupleStructStart("Anything", 0),
Token::SeqEnd, Token::TupleStructEnd,
], ],
} }
test_hashset { test_hashset {
@@ -362,7 +358,7 @@ declare_tests! {
], ],
HashSet::<isize>::new() => &[ HashSet::<isize>::new() => &[
Token::TupleStructStart("Anything", 0), Token::TupleStructStart("Anything", 0),
Token::SeqEnd, Token::TupleStructEnd,
], ],
hashset![FnvHasher @ 1, 2, 3] => &[ hashset![FnvHasher @ 1, 2, 3] => &[
Token::SeqStart(Some(3)), Token::SeqStart(Some(3)),
@@ -412,7 +408,7 @@ declare_tests! {
], ],
Vec::<isize>::new() => &[ Vec::<isize>::new() => &[
Token::TupleStructStart("Anything", 0), Token::TupleStructStart("Anything", 0),
Token::SeqEnd, Token::TupleStructEnd,
], ],
} }
test_array { test_array {
@@ -476,7 +472,7 @@ declare_tests! {
], ],
[0; 0] => &[ [0; 0] => &[
Token::TupleStructStart("Anything", 0), Token::TupleStructStart("Anything", 0),
Token::SeqEnd, Token::TupleStructEnd,
], ],
} }
test_tuple { test_tuple {
@@ -568,7 +564,7 @@ declare_tests! {
], ],
BTreeMap::<isize, isize>::new() => &[ BTreeMap::<isize, isize>::new() => &[
Token::StructStart("Anything", 0), Token::StructStart("Anything", 0),
Token::MapEnd, Token::StructEnd,
], ],
} }
test_hashmap { test_hashmap {
@@ -622,7 +618,7 @@ declare_tests! {
], ],
HashMap::<isize, isize>::new() => &[ HashMap::<isize, isize>::new() => &[
Token::StructStart("Anything", 0), Token::StructStart("Anything", 0),
Token::MapEnd, Token::StructEnd,
], ],
hashmap![FnvHasher @ 1 => 2, 3 => 4] => &[ hashmap![FnvHasher @ 1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)), Token::MapStart(Some(2)),
@@ -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()),
} }
} }
@@ -8,11 +8,15 @@ use self::serde::de::{Deserialize, Deserializer};
use std::borrow::Cow; use std::borrow::Cow;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::result::Result as StdResult;
// Try to trip up the generated code if it fails to use fully qualified paths. // Try to trip up the generated code if it fails to use fully qualified paths.
#[allow(dead_code)] #[allow(dead_code)]
struct Result; struct Result;
use std::result::Result as StdResult; #[allow(dead_code)]
struct Ok;
#[allow(dead_code)]
struct Err;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@@ -1,11 +1,14 @@
extern crate serde_test; extern crate serde_test;
use self::serde_test::{ use self::serde_test::{
Error,
Token, Token,
assert_tokens, assert_tokens,
assert_ser_tokens, assert_ser_tokens,
assert_de_tokens, assert_de_tokens,
assert_de_tokens_error,
}; };
use std::collections::BTreeMap;
use std::marker::PhantomData; use std::marker::PhantomData;
// That tests that the derived Serialize implementation doesn't trigger // That tests that the derived Serialize implementation doesn't trigger
@@ -625,3 +628,256 @@ fn test_enum_state_field() {
] ]
); );
} }
#[test]
fn test_untagged_enum() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum Untagged {
A {
a: u8,
},
B {
b: u8,
},
C,
D(u8),
E(String),
F(u8, u8),
}
assert_tokens(
&Untagged::A { a: 1 },
&[
Token::StructStart("Untagged", 1),
Token::StructSep,
Token::Str("a"),
Token::U8(1),
Token::StructEnd,
]
);
assert_tokens(
&Untagged::B { b: 2 },
&[
Token::StructStart("Untagged", 1),
Token::StructSep,
Token::Str("b"),
Token::U8(2),
Token::StructEnd,
]
);
assert_tokens(
&Untagged::C,
&[
Token::Unit,
]
);
assert_tokens(
&Untagged::D(4),
&[
Token::U8(4),
]
);
assert_tokens(
&Untagged::E("e".to_owned()),
&[
Token::Str("e"),
]
);
assert_tokens(
&Untagged::F(1, 2),
&[
Token::TupleStart(2),
Token::TupleSep,
Token::U8(1),
Token::TupleSep,
Token::U8(2),
Token::TupleEnd,
]
);
assert_de_tokens_error::<Untagged>(
&[
Token::Option(false),
],
Error::Message("data did not match any variant of untagged enum Untagged".to_owned()),
);
assert_de_tokens_error::<Untagged>(
&[
Token::TupleStart(1),
Token::TupleSep,
Token::U8(1),
Token::TupleEnd,
],
Error::Message("data did not match any variant of untagged enum Untagged".to_owned()),
);
assert_de_tokens_error::<Untagged>(
&[
Token::TupleStart(3),
Token::TupleSep,
Token::U8(1),
Token::TupleSep,
Token::U8(2),
Token::TupleSep,
Token::U8(3),
Token::TupleEnd,
],
Error::Message("data did not match any variant of untagged enum Untagged".to_owned()),
);
}
#[test]
fn test_internally_tagged_enum() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Newtype(BTreeMap<String, String>);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Struct {
f: u8,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type")]
enum InternallyTagged {
A {
a: u8,
},
B {
b: u8,
},
C,
D(BTreeMap<String, String>),
E(Newtype),
F(Struct),
}
assert_tokens(
&InternallyTagged::A { a: 1 },
&[
Token::StructStart("InternallyTagged", 2),
Token::StructSep,
Token::Str("type"),
Token::Str("A"),
Token::StructSep,
Token::Str("a"),
Token::U8(1),
Token::StructEnd,
]
);
assert_tokens(
&InternallyTagged::B { b: 2 },
&[
Token::StructStart("InternallyTagged", 2),
Token::StructSep,
Token::Str("type"),
Token::Str("B"),
Token::StructSep,
Token::Str("b"),
Token::U8(2),
Token::StructEnd,
]
);
assert_tokens(
&InternallyTagged::C,
&[
Token::StructStart("InternallyTagged", 1),
Token::StructSep,
Token::Str("type"),
Token::Str("C"),
Token::StructEnd,
]
);
assert_tokens(
&InternallyTagged::D(BTreeMap::new()),
&[
Token::MapStart(Some(1)),
Token::MapSep,
Token::Str("type"),
Token::Str("D"),
Token::MapEnd,
]
);
assert_tokens(
&InternallyTagged::E(Newtype(BTreeMap::new())),
&[
Token::MapStart(Some(1)),
Token::MapSep,
Token::Str("type"),
Token::Str("E"),
Token::MapEnd,
]
);
assert_tokens(
&InternallyTagged::F(Struct { f: 6 }),
&[
Token::StructStart("Struct", 2),
Token::StructSep,
Token::Str("type"),
Token::Str("F"),
Token::StructSep,
Token::Str("f"),
Token::U8(6),
Token::StructEnd,
]
);
assert_de_tokens_error::<InternallyTagged>(
&[
Token::MapStart(Some(0)),
Token::MapEnd,
],
Error::Message("missing field `type`".to_owned()),
);
assert_de_tokens_error::<InternallyTagged>(
&[
Token::MapStart(Some(1)),
Token::MapSep,
Token::Str("type"),
Token::Str("Z"),
Token::MapEnd,
],
Error::Message("unknown variant `Z`, expected one of `A`, `B`, `C`, `D`, `E`, `F`".to_owned()),
);
}
@@ -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;
Executable
+71
View File
@@ -0,0 +1,71 @@
#!/bin/bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
channel() {
if [ -n "${TRAVIS}" ]; then
if [ "${TRAVIS_RUST_VERSION}" = "${CHANNEL}" ]; then
pwd
(set -x; cargo "$@")
fi
else
pwd
(set -x; cargo "+${CHANNEL}" "$@")
fi
}
if [ -n "${CLIPPY}" ]; then
# cached installation will not work on a later nightly
if [ -n "${TRAVIS}" ] && ! cargo install clippy --debug --force; then
echo "COULD NOT COMPILE CLIPPY, IGNORING CLIPPY TESTS"
exit
fi
cd "$DIR/serde"
cargo clippy --features unstable-testing -- -Dclippy
cd "$DIR/serde_derive"
cargo clippy --features unstable-testing -- -Dclippy
cd "$DIR/test_suite"
cargo clippy --features unstable-testing -- -Dclippy
cd "$DIR/test_suite/no_std"
cargo clippy -- -Dclippy
else
CHANNEL=nightly
cargo clean
cd "$DIR/serde"
channel build
channel build --no-default-features
channel build --no-default-features --features alloc
channel build --no-default-features --features collections
channel test --features unstable-testing
cd "$DIR/test_suite/deps"
channel build
cd "$DIR/test_suite"
channel test --features unstable-testing
cd "$DIR/test_suite/no_std"
channel build
CHANNEL=beta
cargo clean
cd "$DIR/serde"
channel build
cd "$DIR/test_suite"
channel test
CHANNEL=stable
cargo clean
cd "$DIR/serde"
channel build
channel build --no-default-features
CHANNEL=1.13.0
cargo clean
cd "$DIR/serde"
channel build
channel build --no-default-features
fi