Compare commits

...

111 Commits

Author SHA1 Message Date
David Tolnay f12f640590 Release 0.8.0 2016-07-27 22:07:57 -07:00
David Tolnay d02e959b3f Merge pull request #468 from sfackler/split-map
Split serialize_map_elt
2016-07-27 12:50:42 -07:00
Steven Fackler ea833d3427 Split serialize_map_elt
Like what's been done on the deserialization side with MapVisitor, this
allows some weirder uses of Serde to handle the key and value in
separate steps.
2016-07-27 12:12:07 -07:00
David Tolnay 78e74886be Update syntex to 0.39 2016-07-26 09:22:33 -07:00
Oliver Schneider 061a1d8a8c Merge pull request #465 from serde-rs/underscore
Remove underscore from parameter names in deserializer traits
2016-07-26 08:25:15 +02:00
David Tolnay de9fd3b04e Remove underscore from parameter names in deserializer traits
This makes the generated rustdoc easier to read.
2016-07-25 20:18:45 -07:00
David Tolnay e36f33589c Release 0.8.0-rc3 2016-07-23 15:13:19 -07:00
Homu a892a13473 Auto merge of #462 - jimmycuadra:ser-error-docstring, r=oli-obk
Fix typos in docstring of ser::Error.

Just a minor documentation fix for grammar and and a copy/paste error.
2016-07-23 17:07:46 +09:00
Jimmy Cuadra 556d5bdc27 Fix typos in docstring of ser::Error. 2016-07-23 00:56:55 -07:00
Homu c6acec29e5 Auto merge of #459 - serde-rs:phantom, r=oli-obk
PhantomData<T> does not require bounds on T
2016-07-23 01:43:45 +09:00
David Tolnay dce02c624b Merge pull request #460 from serde-rs/revert
Revert "Mention Empty Bounds for Recursion in Readme"
2016-07-22 09:13:53 -07:00
David Tolnay 77e56613a5 Revert "Mention Empty Bounds for Recursion in Readme"
This reverts commit 93968455f3.
2016-07-22 09:09:23 -07:00
David Tolnay 3b7fa47b2e PhantomData<T> does not require bounds on T 2016-07-22 09:05:43 -07:00
David Tolnay f5fd7f5950 Merge pull request #458 from serde-rs/testgen
Add tests for concrete instantiations in test_gen
2016-07-22 09:04:33 -07:00
David Tolnay fb6fc4e19f Add tests for concrete instantiations in test_gen 2016-07-22 08:49:51 -07:00
David Tolnay 85772726ee Merge pull request #456 from serde-rs/generic
Generate bounds on type parameters only
2016-07-22 07:58:56 -07:00
Oliver Schneider f05ba9fdf2 unhygienize the generic parameter comparison
include! completely messes up the identifiers' expansion info
2016-07-22 14:09:14 +02:00
Homu 2e829ae4e6 Auto merge of #457 - serde-rs:phantom, r=oli-obk
Impl Deserialize for PhantomData<T> for all T
2016-07-22 16:31:51 +09:00
David Tolnay 25a5dd1579 Impl Deserialize for PhantomData<T> for all T 2016-07-21 23:22:38 -07:00
David Tolnay 1831b471f9 Generate bounds on type parameters only 2016-07-21 23:06:18 -07:00
Oliver Schneider 49ff56aa15 Merge pull request #452 from oli-obk/pure_interface
Pure interface for Deserializer
2016-07-21 11:25:16 +02:00
Oliver Schneider 89549e2567 fix nightly 2016-07-21 10:49:02 +02:00
Oliver Schneider 124bacd871 fix for 1.8, 1.9 and stable 2016-07-21 10:11:04 +02:00
Oliver Schneider 4280dd466d rename deserialize_fixed_size_array to deserialize_seq_fixed_size 2016-07-20 19:20:31 +02:00
Oliver Schneider 65eb116a85 address comments 2016-07-20 19:18:45 +02:00
Homu e15940f355 Auto merge of #454 - nox:boxed, r=oli-obk
Implement Deserialize for Box<str>
2016-07-20 19:49:11 +09:00
Anthony Ramine 68440952ab Implement Deserialize for Box<str> 2016-07-20 12:47:08 +02:00
Oliver Schneider d751b4c39a Merge pull request #451 from killercup/doc/recursive-bounds
Mention Empty Bounds for Recursion in Readme
2016-07-20 10:43:54 +02:00
Oliver Schneider d10a69b243 document some hints for defaults 2016-07-20 10:42:14 +02:00
Pascal Hertleif 1a1b6fbf85 Fix Typo in Readme 2016-07-20 10:39:57 +02:00
Pascal Hertleif 93968455f3 Mention Empty Bounds for Recursion in Readme
Fixes #427
2016-07-20 10:39:57 +02:00
Oliver Schneider 4722571a4d make VariantVisitor pure 2016-07-20 10:33:28 +02:00
Oliver Schneider 36a7bf6244 make Deserializer pure 2016-07-20 10:26:31 +02:00
David Tolnay 89f0ad99a6 Merge pull request #449 from oli-obk/docs
add more extensive docs
2016-07-18 07:09:20 -07:00
Oliver Schneider 05ad8662e2 add more extensive docs 2016-07-18 16:08:07 +02:00
Oliver Schneider 15c09a8d2c Merge pull request #448 from laktak/hjson
add Hjson
2016-07-18 13:04:02 +02:00
Christian Zangl 80a27cbb4a add Hjson 2016-07-18 12:06:21 +02:00
David Tolnay 13e1a129dd Ignore unused struct in test_gen.rs 2016-07-17 21:10:05 -07:00
David Tolnay 334a6e788a Remove commented code in test_macros.rs 2016-07-17 21:09:44 -07:00
David Tolnay fa51083a12 Merge pull request #446 from serde-rs/unstable
Rename feature nightly-testing to unstable-testing
2016-07-17 18:26:20 -07:00
David Tolnay aaca4f06c6 Release 0.8.0-rc2 2016-07-17 18:07:40 -07:00
David Tolnay cc8a5a79ab See whether relative paths help cargo find the unstable-testing feature 2016-07-17 13:40:39 -07:00
David Tolnay 4f79829849 Rename feature nightly-testing to unstable-testing 2016-07-17 13:34:23 -07:00
David Tolnay 6c18896cf5 Unpin the clippy dependency 2016-07-17 13:32:40 -07:00
David Tolnay ac738632ef Merge pull request #445 from serde-rs/pubdep
Remove public dependency on Syntex
2016-07-17 13:15:42 -07:00
David Tolnay 8d06f36d71 Remove public dependency on Syntex 2016-07-17 13:00:39 -07:00
David Tolnay e404de85b2 Remove serde-syntex-example from travis until serde_json 0.8.0 2016-07-17 12:59:04 -07:00
David Tolnay 6fe01bc8e3 Release 0.8.0-rc1
This prerelease contains the Serializer API changes intended for 0.8.0. It
allows us to start merging PRs that use the new API.
2016-07-17 11:46:03 -07:00
David Tolnay 855f3d99bb Do not release any more 0.7 releases from master 2016-07-15 17:00:09 -07:00
David Tolnay 9d015a2942 Merge pull request #437 from oli-obk/map_seq_ser
Revamp Map/Seq serialization
2016-07-15 16:59:45 -07:00
Oliver Schneider 42c41922ce adjust tests for new interface 2016-07-15 12:59:30 +02:00
Oliver Schneider 984181c558 Merge remote-tracking branch 'serde/master' into map_seq_ser 2016-07-15 10:59:46 +02:00
David Tolnay ed603d4580 Merge pull request #442 from serde-rs/override
Use cargo override instead of relative paths
2016-07-15 01:56:14 -07:00
Oliver Schneider 70c83768b7 Merge pull request #1 from serde-rs/dtolnay/serializer
David's take on Serializer
2016-07-15 10:38:22 +02:00
David Tolnay 7220029055 Use cargo override instead of relative paths
This makes it possible to use `cargo clone` + `cargo build`.
2016-07-15 01:17:23 -07:00
David Tolnay 35676305da Merge pull request #401 from erickt/contributing
Add a contribution guide
2016-07-15 01:06:54 -07:00
David Tolnay fbad194042 Restore 'static requirement for names 2016-07-15 00:59:56 -07:00
David Tolnay 2e4cc0b443 Restore serialize_seq_fixed_size 2016-07-15 00:58:48 -07:00
David Tolnay 9217517532 Update impls 2016-07-15 00:55:38 -07:00
David Tolnay 0feeb7a341 David's take on Serializer 2016-07-15 00:01:31 -07:00
Oliver Schneider 2901344722 this time really fix ranges 2016-07-14 16:16:20 +02:00
Oliver Schneider 54c80ad677 fix range serialization 2016-07-14 15:37:05 +02:00
Oliver Schneider 16ba32dbe1 stateful map/seq serialization 2016-07-14 15:36:47 +02:00
Oliver Schneider 60938913b2 face -> palm 2016-07-13 19:18:01 +02:00
Oliver Schneider 26528fbbb4 silence lint about a: ref a patterns 2016-07-12 16:53:38 +02:00
Oliver Schneider 6adcaa55e5 json needs more info 2016-07-12 16:53:20 +02:00
Oliver Schneider fb575225bc simplify! 2016-07-12 16:16:48 +02:00
Oliver Schneider ee4e7413b0 whoops 2016-07-12 15:50:41 +02:00
Oliver Schneider a6f8bd5aac nightly 2016-07-12 15:49:41 +02:00
Oliver Schneider 3766633f4a adjust codegen to work with the revamped map/seq serializer 2016-07-12 15:44:19 +02:00
Dawid Ciężarkiewicz 99038b044e Eliminate Visitor pattern
Visitor is "pull", while `MapSerializer` and `SeqSerializer`
are "push" like the rest of the API.
2016-07-12 11:46:44 +02:00
David Tolnay 4ec0a7e672 Merge pull request #433 from softprops/add_envy
add envy
2016-07-10 20:59:50 -07:00
softprops a41dae45a5 add envy 2016-07-10 23:55:32 -04:00
David Tolnay cb9e1cfb54 Merge pull request #431 from serde-rs/version
Drop support for 1.7.0
2016-07-10 14:40:15 -07:00
David Tolnay 54ce7f2e90 Drop support for 1.7.0 2016-07-10 14:25:17 -07:00
David Tolnay ddbd139793 Merge pull request #430 from serde-rs/bump
Update syntex to 0.38
2016-07-09 11:51:38 -07:00
David Tolnay a070de28e2 Update syntex to 0.38 2016-07-09 11:37:01 -07:00
David Tolnay 57aeb26728 Merge pull request #428 from erickt/readme
Rewrite readme to front-load stable rust usage
2016-07-07 20:26:00 -07:00
Erick Tryzelaar a592828808 Rewrite readme to front-load stable rust usage 2016-07-07 14:31:24 -07:00
David Tolnay 67d86dcc4f Merge pull request #426 from serde-rs/display
impl Display for de::Type
2016-07-07 00:59:17 -07:00
David Tolnay 15764cb955 impl Display for de::Type 2016-07-06 23:33:59 -07:00
David Tolnay 97bc1e08e7 Release 0.7.13 2016-07-05 20:06:10 -07:00
Oliver Schneider 7ffb74f5bb Merge pull request #423 from dtolnay/seq
Close the seq before failing on invalid length
2016-07-05 22:44:52 +02:00
David Tolnay f25e6d3ea9 Close the seq before failing on invalid length
Equivalent to what 0f9a930 does for maps.
2016-07-05 10:08:36 -07:00
David Tolnay 431cbe48b7 Merge pull request #422 from serde-rs/missing
Close the map before checking for missing fields
2016-07-05 07:11:03 -07:00
Homu 5405ab319d Auto merge of #421 - serde-rs:length, r=oli-obk
Invalid-length when enum seq is too short

Fixes https://github.com/serde-rs/json/issues/96.
2016-07-05 18:27:33 +09:00
David Tolnay 0f9a930c4f Close the map before checking for missing fields 2016-07-05 01:42:38 -07:00
David Tolnay 1a449bb3d0 Invalid-length when enum seq is too short 2016-07-05 01:35:20 -07:00
David Tolnay c0e8164792 Merge pull request #418 from serde-rs/expninfo
Record expansion info
2016-07-04 15:22:09 -07:00
David Tolnay a3a7e4085f Add run-pass test for expansion info 2016-07-04 15:02:15 -07:00
David Tolnay 149c87d7c2 Record expansion info 2016-07-03 10:53:33 -07:00
David Tolnay 5deba439c3 Merge pull request #417 from serde-rs/bump
Update syntex to 0.37
2016-07-03 08:53:56 -07:00
David Tolnay d450de1482 Update syntex to 0.37 2016-07-02 20:20:44 -07:00
David Tolnay 47c7387279 Merge pull request #416 from dtolnay/filter
Remove filter no longer necessary for rustc >=1.7
2016-07-01 22:53:45 -07:00
David Tolnay dc8d209f29 Remove filter no longer necessary for rustc >=1.7 2016-07-01 22:34:15 -07:00
David Tolnay 831802adc8 Merge pull request #407 from dtolnay/internals
Rename serde_item to serde_codegen_internals
2016-06-30 20:06:12 -07:00
David Tolnay 2d5a26dfc0 Rename serde_internals to serde_codegen_internals 2016-06-30 19:53:57 -07:00
David Tolnay c6b6e2a5d9 Rename serde_item to serde_internals 2016-06-30 19:42:55 -07:00
Oliver Schneider d1be5ef187 Merge pull request #412 from dtolnay/test
Move Token De/Serializer to serde_test crate
2016-06-29 10:05:36 +02:00
David Tolnay f531be1524 Turn comments into doc comments 2016-06-29 00:58:33 -07:00
David Tolnay 10b1508d4a Sync serde_test version with the other crates 2016-06-29 00:17:50 -07:00
David Tolnay 041d5c0842 Make serde_test asserts more consistent 2016-06-28 23:50:19 -07:00
David Tolnay 7d09053bb8 Fix declare_ser_tests to work on old rustc 2016-06-28 23:09:37 -07:00
David Tolnay 8e87926bc2 Round out the Error variants 2016-06-28 22:57:53 -07:00
David Tolnay d6a462b862 Add serde_test to dev dependencies of serde_macros 2016-06-28 22:50:58 -07:00
David Tolnay cfc2f9adc0 Remove Error from name of Error variants 2016-06-28 22:49:13 -07:00
David Tolnay 00f94290a6 Add message to CustomError 2016-06-28 22:36:29 -07:00
David Tolnay 093201abfb Assert tokens are empty after reaching error 2016-06-28 22:23:38 -07:00
David Tolnay 6d64104375 Factor the Token De/Serializer into serde_test 2016-06-28 21:54:51 -07:00
David Tolnay fb0e62951f Rename serde_tests to testing 2016-06-28 20:43:59 -07:00
Erick Tryzelaar 18e077eda9 Add a contributing guide 2016-06-22 07:04:13 -07:00
59 changed files with 3219 additions and 2690 deletions
+7
View File
@@ -0,0 +1,7 @@
paths = [
"serde",
"serde_codegen",
"serde_codegen_internals",
"serde_macros",
"serde_test",
]
+9 -9
View File
@@ -2,10 +2,10 @@ sudo: false
language: rust
rust:
- stable
- beta
- nightly
- 1.7.0
- 1.8.0
- 1.9.0
- beta
addons:
apt:
packages:
@@ -18,19 +18,19 @@ before_script:
script:
- (cd serde && travis-cargo build)
- (cd serde && travis-cargo --skip nightly test)
- (cd serde && travis-cargo --only nightly test -- --features nightly-testing)
- (cd serde && travis-cargo --only nightly test -- --features unstable-testing)
- (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 serde_tests && travis-cargo --skip nightly test)
- (cd serde_tests && travis-cargo --only nightly test -- --features nightly-testing)
- (cd serde_macros && travis-cargo --only nightly test -- --features nightly-testing)
- (cd examples/serde-syntex-example && travis-cargo --skip nightly run)
- (cd examples/serde-syntex-example && travis-cargo --only nightly run -- --no-default-features --features nightly)
- (cd testing && travis-cargo --skip nightly test)
- (cd testing && travis-cargo --only nightly test -- --features unstable-testing)
- (cd serde_macros && travis-cargo --only nightly test -- --features unstable-testing)
#- (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)
after_success:
- (cd serde && travis-cargo --only stable doc-upload)
- (cd serde_tests && travis-cargo --only stable coveralls --no-sudo)
- (cd testing && travis-cargo --only stable coveralls --no-sudo)
env:
global:
- TRAVIS_CARGO_NIGHTLY_FEATURE=""
+45
View File
@@ -0,0 +1,45 @@
# Contributing to Serde
Serde welcomes contribution from everyone. Here are the guidelines if you are
thinking of helping us:
## Contributions
Contributions to Serde or its dependencies should be made in the form of GitHub
pull requests. Each pull request will be reviewed by a core contributor
(someone with permission to land patches) and either landed in the main tree or
given feedback for changes that would be required. All contributions should
follow this format, even those from core contributors.
Should you wish to work on an issue, please claim it first by commenting on
the GitHub issue that you want to work on it. This is to prevent duplicated
efforts from contributors on the same issue.
## Pull Request Checklist
- Branch from the master branch and, if needed, rebase to the current master
branch before submitting your pull request. If it doesn't merge cleanly with
master you may be asked to rebase your changes.
- Commits should be as small as possible, while ensuring that each commit is
correct independently (i.e., each commit should compile and pass tests).
- If your patch is not getting reviewed or you need a specific person to review
it, you can @-reply a reviewer asking for a review in the pull request or a
comment, or you can ask for a review in `#serde` on `irc.mozilla.org`.
- Add tests relevant to the fixed bug or new feature.
## Conduct
In all Serde-related forums, we follow the [Rust Code of
Conduct](https://www.rust-lang.org/conduct.html). For escalation or moderation
issues, please contact Erick (erick.tryzelaar@gmail.com) instead of the Rust
moderation team.
## Communication
Beyond opening tickets on the
[serde-rs/serde](https://github.com/serde-rs/serde) project, Serde contributors
frequent the `#serde` channel on
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC).
+146 -60
View File
@@ -12,74 +12,100 @@ information. In many situations, the 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.
Documentation is available at:
[Documentation](https://serde-rs.github.io/serde/serde/index.html)
* [serde](https://serde-rs.github.io/serde/serde/index.html)
Simple Serde Example
====================
Using Serde with Nightly Rust and serde\_macros
===============================================
Here is a simple example that demonstrates how to use Serde by serializing and
deserializing to JSON. Serde comes with some powerful code generation libraries
that work with Stable and Nightly Rust that eliminate much of the complexity of
hand rolling serialization and deserialization for a given type. First lets see
how we would use Nightly Rust, which is currently a bit simpler than Stable
Rust:
`Cargo.toml`:
Here is a simple example that uses
[serde_json](https://github.com/serde-rs/json), which uses Serde under the
covers, to generate and parse JSON. First, lets start off with the `Cargo.toml`
file:
```toml
[package]
name = "serde_example_nightly"
name = "serde_example"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
[dependencies]
serde = "*"
serde_json = "*"
serde_macros = "*"
```
`src/main.rs`
```rust
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
Next, the `src/main.rs` file itself:
```rust,ignore
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
use std::collections::HashMap;
use serde_json::Value;
use serde_json::builder::{ArrayBuilder, ObjectBuilder};
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
// Serde has support for many of the builtin Rust types, like arrays..:
let v = vec![1, 2];
let serialized = serde_json::to_string(&v).unwrap();
println!("serialized vec: {:?}", serialized);
println!("{}", serialized);
let deserialized: Vec<u32> = serde_json::from_str(&serialized).unwrap();
println!("deserialized vec: {:?}", deserialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
// ... and maps:
let mut map = HashMap::new();
map.insert("x".to_string(), 1);
map.insert("y".to_string(), 2);
println!("{:?}", deserialized);
let serialized = serde_json::to_string(&map).unwrap();
println!("serialized map: {:?}", serialized);
let deserialized: HashMap<String, u32> = serde_json::from_str(&serialized).unwrap();
println!("deserialized map: {:?}", deserialized);
// It also can handle complex objects:
let value = ObjectBuilder::new()
.insert("int", 1)
.insert("string", "a string")
.insert("array", ArrayBuilder::new()
.push(1)
.push(2)
.unwrap())
.unwrap();
let serialized = serde_json::to_string(&value).unwrap();
println!("serialized value: {:?}", serialized);
let deserialized: serde_json::Value = serde_json::from_str(&serialized).unwrap();
println!("deserialized value: {:?}", deserialized);
}
```
When run, it produces:
This produces the following output when run:
```
```sh
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
serialized vec: "[1,2]"
deserialized vec: [1, 2]
serialized map: "{\"y\":2,\"x\":1}"
deserialized map: {"y": 2, "x": 1}
serialized value: "{\"array\":[1,2],\"int\":1,\"string\":\"a string\"}"
deserialized value: {"array":[1,2],"int":1,"string":"a string"}
```
Using Serde with Stable Rust and serde\_codegen
===============================================
Stable Rust is a little more complicated because it does not yet support
compiler plugins. Instead we need to use `serde_codegen` which is based on the
code generation library [syntex](https://github.com/serde-rs/syntex):
The example before used `serde_json::Value` as the in-memory representation of
the JSON value, but it's also possible for Serde to serialize to and from
regular Rust types. However, the code to do this can be a bit complicated to
write. So instead, Serde also has some powerful code generation libraries that
work with Stable and Nightly Rust that eliminate much of the complexity of hand
rolling serialization and deserialization for a given type.
First lets see how we would use Stable Rust, which is currently a tad more
complicated than Nightly Rust due to having to work around compiler plugins
being unstable. We will use `serde_codegen` which is based on the code
generation library [syntex](https://github.com/serde-rs/syntex). First we need
to setup the `Cargo.toml` that builds the project:
```toml
[package]
@@ -96,16 +122,8 @@ serde = "*"
serde_json = "*"
```
`src/main.rs`:
```rust,ignore
extern crate serde;
extern crate serde_json;
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
`src/main.rs.in`:
Next, we define our source file, `src/main.rs.in`. Note this is a different
extension than usual because we need to do code generation:
```rust,ignore
#[derive(Serialize, Deserialize, Debug)]
@@ -116,17 +134,28 @@ struct Point {
fn main() {
let point = Point { x: 1, y: 2 };
let serialized = serde_json::to_string(&point).unwrap();
let serialized = serde_json::to_string(&point).unwrap();
println!("{}", serialized);
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
println!("{:?}", deserialized);
}
```
`build.rs`
To finish up the main source code, we define a very simple `src/main.rs` that
uses the generated code.
`src/main.rs`:
```rust,ignore
extern crate serde;
extern crate serde_json;
include!(concat!(env!("OUT_DIR"), "/main.rs"));
```
The last step is to actually drive the code generation, with the `build.rs` script:
```rust,ignore
extern crate serde_codegen;
@@ -144,17 +173,72 @@ pub fn main() {
}
```
This also produces:
All this produces this when run:
```
```sh
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
While this works well with Stable Rust, be aware that the error locations
currently are reported in the generated file instead of in the source file. You
may find it easier to develop with Nightly Rust and `serde\_macros`, then
currently are reported in the generated file instead of in the source file.
Using Serde with Nightly Rust and serde\_macros
===============================================
The prior example is a bit more complicated than it needs to be due to compiler
plugins being unstable. However, if you are already using Nightly Rust, you can
use `serde_macros`, which has a much simpler interface. First, here is the new
`Cargo.toml`:
```toml
[package]
name = "serde_example_nightly"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
[dependencies]
serde = "*"
serde_json = "*"
serde_macros = "*"
```
Note that it doesn't need a build script. Now the `src/main.rs`, which enables
the plugin feature, and registers the `serde_macros` plugin:
```rust
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde_json;
#[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);
}
```
This also produces the same output:
```sh
% cargo run
{"x":1,"y":2}
Point { x: 1, y: 2 }
```
You may find it easier to develop with Nightly Rust and `serde\_macros`, then
deploy with Stable Rust and `serde_codegen`. It's possible to combine both
approaches in one setup:
@@ -230,14 +314,14 @@ The `src/main.rs.in` is the same as before.
Then to run with stable:
```
```sh
% cargo build
...
```
Or with nightly:
```
```sh
% cargo build --features nightly --no-default-features
...
```
@@ -274,7 +358,7 @@ impl serde::Serialize for i32 {
As you can see it's pretty simple. More complex types like `BTreeMap` need to
pass a
[MapVisitor](http://serde-rs.github.io/serde/serde/serde/ser/trait.MapVisitor.html)
to the
to the
[Serializer](http://serde-rs.github.io/serde/serde/serde/ser/trait.Serializer.html)
in order to walk through the type:
@@ -435,7 +519,7 @@ impl serde::de::Visitor for I32Visitor {
Since it's possible for this type to get passed an unexpected type, we need a
way to error out. This is done by way of the
[Error](http://serde-rs.github.io/serde/serde/serde/de/trait.Error.html) trait,
which allows a
which allows a
[Deserialize](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserialize.html)
to generate an error for a few common error conditions. Here's how it could be used:
@@ -454,7 +538,7 @@ to generate an error for a few common error conditions. Here's how it could be u
Maps follow a similar pattern as before, and use a
[MapVisitor](http://serde-rs.github.io/serde/serde/serde/de/trait.MapVisitor.html)
to walk through the values generated by the
to walk through the values generated by the
[Deserializer](http://serde-rs.github.io/serde/serde/serde/de/trait.Deserializer.html).
```rust,ignore
@@ -740,6 +824,8 @@ Serialization Formats Using Serde
| Format | Name |
| ------ | ---- |
| Bincode | [bincode](https://crates.io/crates/bincode) |
| env vars | [envy](https://crates.io/crates/envy) |
| Hjson | [serde\_hjson](https://crates.io/crates/serde-hjson) |
| JSON | [serde\_json](https://crates.io/crates/serde_json) |
| MessagePack | [rmp](https://crates.io/crates/rmp) |
| XML | [serde\_xml](https://github.com/serde-rs/xml) |
-5
View File
@@ -1,5 +0,0 @@
paths = [
"../serde",
"../serde_codegen",
"../serde_macros",
]
+5 -5
View File
@@ -6,12 +6,12 @@ build = "build.rs"
[features]
default = ["serde_codegen"]
nightly = ["serde_macros"]
unstable = ["serde_macros"]
[build-dependencies]
serde_codegen = { version = "^0.7.11", optional = true }
serde_codegen = { version = "^0.7", optional = true }
[dependencies]
serde = "^0.7.11"
serde_json = "^0.7.0"
serde_macros = { version = "^0.7.11", optional = true }
serde = "^0.7"
serde_json = "^0.7"
serde_macros = { version = "^0.7", optional = true }
+4 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "0.7.11"
version = "0.8.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -14,10 +14,10 @@ include = ["Cargo.toml", "src/**/*.rs"]
default = ["std"]
std = []
nightly = []
alloc = ["nightly"]
unstable = []
alloc = ["unstable"]
collections = ["alloc"]
nightly-testing = ["clippy", "nightly", "std"]
unstable-testing = ["clippy", "unstable", "std"]
[dependencies]
clippy = { version = "^0.*", optional = true }
+24 -14
View File
@@ -2,7 +2,7 @@
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "nightly", feature = "collections", not(feature = "std")))]
#[cfg(all(feature = "unstable", feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
@@ -27,9 +27,9 @@ use std::collections::{
VecDeque,
};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::{Hash, BuildHasher};
@@ -42,21 +42,21 @@ use core::str;
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
#[cfg(feature = "std")]
use std::sync::Arc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
use alloc::arc::Arc;
#[cfg(all(feature = "nightly", feature = "alloc", not(feature = "std")))]
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::num::Zero;
use de::{
@@ -356,7 +356,7 @@ pub struct PhantomDataVisitor<T> {
marker: PhantomData<T>,
}
impl<T> Visitor for PhantomDataVisitor<T> where T: Deserialize {
impl<T> Visitor for PhantomDataVisitor<T> {
type Value = PhantomData<T>;
#[inline]
@@ -367,7 +367,7 @@ impl<T> Visitor for PhantomDataVisitor<T> where T: Deserialize {
}
}
impl<T> Deserialize for PhantomData<T> where T: Deserialize {
impl<T> Deserialize for PhantomData<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<PhantomData<T>, D::Error>
where D: Deserializer,
{
@@ -461,7 +461,7 @@ seq_impl!(
BTreeSet::new(),
BTreeSet::insert);
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
seq_impl!(
EnumSet<T>,
EnumSetVisitor<T: Deserialize + CLike>,
@@ -593,7 +593,7 @@ macro_rules! array_impls {
fn deserialize<D>(deserializer: &mut D) -> Result<[T; $len], D::Error>
where D: Deserializer,
{
deserializer.deserialize_fixed_size_array($len, $visitor::new())
deserializer.deserialize_seq_fixed_size($len, $visitor::new())
}
}
)+
@@ -806,7 +806,7 @@ map_impl!(
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "nightly", feature = "std"))]
#[cfg(all(feature = "unstable", feature = "std"))]
impl Deserialize for net::IpAddr {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer,
@@ -939,6 +939,16 @@ impl<T: Deserialize> Deserialize for Box<[T]> {
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl Deserialize for Box<str> {
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
where D: Deserializer
{
let s = try!(String::deserialize(deserializer));
Ok(s.into_boxed_str())
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Deserialize> Deserialize for Arc<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Arc<T>, D::Error>
@@ -972,7 +982,7 @@ impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deser
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero {
fn deserialize<D>(deserializer: &mut D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
let value = try!(Deserialize::deserialize(deserializer));
+195 -194
View File
@@ -8,6 +8,75 @@ use error;
#[cfg(all(not(feature = "std"), feature = "collections"))]
use collections::{String, Vec};
use core::fmt;
///////////////////////////////////////////////////////////////////////////////
/// Macro helper to not have to re-implement all the defaulted methods.
/// Every given method ignores all arguments and forwards to `deserialize`.
/// Note that `deserialize_enum` simply returns an `Error::invalid_type`.
macro_rules! de_forward_to_deserialize {
($($func:ident),*) => {
$(de_forward_to_deserialize!{func: $func})*
};
(func: deserialize_unit_struct) => {
de_forward_to_deserialize!{named: deserialize_unit_struct}
};
(func: deserialize_newtype_struct) => {
de_forward_to_deserialize!{named: deserialize_newtype_struct}
};
(func: deserialize_tuple) => {
de_forward_to_deserialize!{tup_fn: deserialize_tuple}
};
(func: deserialize_seq_fixed_size) => {
de_forward_to_deserialize!{tup_fn: deserialize_seq_fixed_size}
};
(func: deserialize_tuple_struct) => {
#[inline]
fn deserialize_tuple_struct<__V>(&mut self, _: &str, _: usize, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
(func: deserialize_struct) => {
#[inline]
fn deserialize_struct<__V>(&mut self, _: &str, _: &[&str], visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
(func: deserialize_enum) => {
#[inline]
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::EnumVisitor {
Err($crate::de::Error::invalid_type($crate::de::Type::Enum))
}
};
(named: $func:ident) => {
#[inline]
fn $func<__V>(&mut self, _: &str, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
(tup_fn: $func: ident) => {
#[inline]
fn $func<__V>(&mut self, _: usize, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
(func: $func:ident) => {
#[inline]
fn $func<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: $crate::de::Visitor {
self.deserialize(visitor)
}
};
}
///////////////////////////////////////////////////////////////////////////////
// modules come after macros
pub mod impls;
pub mod value;
mod from_primitive;
@@ -169,6 +238,46 @@ pub enum Type {
Bytes,
}
impl fmt::Display for Type {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let display = match *self {
Type::Bool => "bool",
Type::Usize => "usize",
Type::U8 => "u8",
Type::U16 => "u16",
Type::U32 => "u32",
Type::U64 => "u64",
Type::Isize => "isize",
Type::I8 => "i8",
Type::I16 => "i16",
Type::I32 => "i32",
Type::I64 => "i64",
Type::F32 => "f32",
Type::F64 => "f64",
Type::Char => "char",
Type::Str => "str",
Type::String => "string",
Type::Unit => "unit",
Type::Option => "option",
Type::Seq => "seq",
Type::Map => "map",
Type::UnitStruct => "unit struct",
Type::NewtypeStruct => "newtype struct",
Type::TupleStruct => "tuple struct",
Type::Struct => "struct",
Type::FieldName => "field name",
Type::Tuple => "tuple",
Type::Enum => "enum",
Type::VariantName => "variant name",
Type::StructVariant => "struct variant",
Type::TupleVariant => "tuple variant",
Type::UnitVariant => "unit variant",
Type::Bytes => "bytes",
};
display.fmt(formatter)
}
}
///////////////////////////////////////////////////////////////////////////////
/// `Deserialize` represents a type that can be deserialized.
@@ -201,278 +310,166 @@ pub trait Deserializer {
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `bool` value.
#[inline]
fn deserialize_bool<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `usize` value.
#[inline]
/// A reasonable default is to forward to `deserialize_u64`.
fn deserialize_usize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_u64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `u8` value.
#[inline]
/// A reasonable default is to forward to `deserialize_u64`.
fn deserialize_u8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_u64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `u16` value.
#[inline]
/// A reasonable default is to forward to `deserialize_u64`.
fn deserialize_u16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_u64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `u32` value.
#[inline]
/// A reasonable default is to forward to `deserialize_u64`.
fn deserialize_u32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_u64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `u64` value.
#[inline]
fn deserialize_u64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `isize` value.
#[inline]
/// A reasonable default is to forward to `deserialize_i64`.
fn deserialize_isize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_i64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `i8` value.
#[inline]
/// A reasonable default is to forward to `deserialize_i64`.
fn deserialize_i8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_i64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `i16` value.
#[inline]
/// A reasonable default is to forward to `deserialize_i64`.
fn deserialize_i16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_i64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `i32` value.
#[inline]
/// A reasonable default is to forward to `deserialize_i64`.
fn deserialize_i32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_i64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `i64` value.
#[inline]
fn deserialize_i64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `f32` value.
#[inline]
/// A reasonable default is to forward to `deserialize_f64`.
fn deserialize_f32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_f64(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `f64` value.
#[inline]
fn deserialize_f64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `char` value.
#[inline]
fn deserialize_char<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `&str` value.
#[inline]
fn deserialize_str<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `String` value.
#[inline]
fn deserialize_string<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_str(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `unit` value.
#[inline]
fn deserialize_unit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an `Option` value. This allows
/// deserializers that encode an optional value as a nullable value to convert the null value
/// into a `None`, and a regular value as `Some(value)`.
#[inline]
fn deserialize_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a sequence value. This allows
/// deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn deserialize_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a fixed size array. This allows
/// deserializers to parse arrays that aren't tagged as arrays.
///
/// By default, this deserializes arrays from a sequence.
#[inline]
fn deserialize_fixed_size_array<V>(&mut self,
_len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
fn deserialize_seq_fixed_size<V>(&mut self,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a `Vec<u8>`. This allows
/// deserializers that provide a custom byte vector serialization to properly deserialize the
/// type.
#[inline]
fn deserialize_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_seq(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a map of values. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn deserialize_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a unit struct. This allows
/// deserializers to a unit struct that aren't tagged as a unit struct.
#[inline]
fn deserialize_unit_struct<V>(&mut self,
_name: &'static str,
name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_unit(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a newtype struct. This allows
/// deserializers to a newtype struct that aren't tagged as a newtype struct.
#[inline]
/// A reasonable default is to simply deserialize the expected value directly.
fn deserialize_newtype_struct<V>(&mut self,
name: &'static str,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_tuple_struct(name, 1, visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a tuple struct. This allows
/// deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn deserialize_tuple_struct<V>(&mut self,
_name: &'static str,
name: &'static str,
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_tuple(len, visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a struct. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn deserialize_struct<V>(&mut self,
_name: &'static str,
_fields: &'static [&'static str],
name: &'static str,
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_map(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting some sort of struct field
/// name. This allows deserializers to choose between &str, usize, or &[u8] to properly
/// deserialize a struct field.
#[inline]
fn deserialize_struct_field<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize(visitor)
}
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting a tuple value. This allows
/// deserializers that provide a custom tuple serialization to properly deserialize the type.
#[inline]
fn deserialize_tuple<V>(&mut self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.deserialize_seq(visitor)
}
fn deserialize_tuple<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// This method hints that the `Deserialize` type is expecting an enum value. This allows
/// deserializers that provide a custom enumeration serialization to properly deserialize the
/// type.
#[inline]
fn deserialize_enum<V>(&mut self,
_enum: &'static str,
_variants: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor,
{
Err(Error::invalid_type(Type::Enum))
}
name: &'static str,
variants: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor;
/// This method hints that the `Deserialize` type needs to deserialize a value whose type
/// doesn't matter because it is ignored.
#[inline]
fn deserialize_ignored_any<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
self.deserialize(visitor)
}
where V: Visitor;
}
///////////////////////////////////////////////////////////////////////////////
@@ -483,9 +480,10 @@ pub trait Visitor {
type Value: Deserialize;
/// `visit_bool` deserializes a `bool` into a `Value`.
fn visit_bool<E>(&mut self, _v: bool) -> Result<Self::Value, E>
fn visit_bool<E>(&mut self, v: bool) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::Bool))
}
@@ -518,9 +516,10 @@ pub trait Visitor {
}
/// `visit_i64` deserializes a `i64` into a `Value`.
fn visit_i64<E>(&mut self, _v: i64) -> Result<Self::Value, E>
fn visit_i64<E>(&mut self, v: i64) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::I64))
}
@@ -553,9 +552,10 @@ pub trait Visitor {
}
/// `visit_u64` deserializes a `u64` into a `Value`.
fn visit_u64<E>(&mut self, _v: u64) -> Result<Self::Value, E>
fn visit_u64<E>(&mut self, v: u64) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::U64))
}
@@ -567,9 +567,10 @@ pub trait Visitor {
}
/// `visit_f64` deserializes a `f64` into a `Value`.
fn visit_f64<E>(&mut self, _v: f64) -> Result<Self::Value, E>
fn visit_f64<E>(&mut self, v: f64) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::F64))
}
@@ -582,9 +583,10 @@ pub trait Visitor {
}
/// `visit_str` deserializes a `&str` into a `Value`.
fn visit_str<E>(&mut self, _v: &str) -> Result<Self::Value, E>
fn visit_str<E>(&mut self, v: &str) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::Str))
}
@@ -608,9 +610,10 @@ pub trait Visitor {
/// `visit_unit_struct` deserializes a unit struct into a `Value`.
#[inline]
fn visit_unit_struct<E>(&mut self, _name: &'static str) -> Result<Self::Value, E>
fn visit_unit_struct<E>(&mut self, name: &'static str) -> Result<Self::Value, E>
where E: Error,
{
let _ = name;
self.visit_unit()
}
@@ -622,37 +625,42 @@ pub trait Visitor {
}
/// `visit_some` deserializes a value into a `Value`.
fn visit_some<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
fn visit_some<D>(&mut self, deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
let _ = deserializer;
Err(Error::invalid_type(Type::Option))
}
/// `visit_newtype_struct` deserializes a value into a `Value`.
fn visit_newtype_struct<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
fn visit_newtype_struct<D>(&mut self, deserializer: &mut D) -> Result<Self::Value, D::Error>
where D: Deserializer,
{
let _ = deserializer;
Err(Error::invalid_type(Type::NewtypeStruct))
}
/// `visit_seq` deserializes a `SeqVisitor` into a `Value`.
fn visit_seq<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
fn visit_seq<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: SeqVisitor,
{
let _ = visitor;
Err(Error::invalid_type(Type::Seq))
}
/// `visit_map` deserializes a `MapVisitor` into a `Value`.
fn visit_map<V>(&mut self, _visitor: V) -> Result<Self::Value, V::Error>
fn visit_map<V>(&mut self, visitor: V) -> Result<Self::Value, V::Error>
where V: MapVisitor,
{
let _ = visitor;
Err(Error::invalid_type(Type::Map))
}
/// `visit_bytes` deserializes a `&[u8]` into a `Value`.
fn visit_bytes<E>(&mut self, _v: &[u8]) -> Result<Self::Value, E>
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<Self::Value, E>
where E: Error,
{
let _ = v;
Err(Error::invalid_type(Type::Bytes))
}
@@ -828,33 +836,26 @@ pub trait VariantVisitor {
Err(Error::invalid_type(Type::UnitVariant))
}
/// `visit_newtype` is called when deserializing a variant with a single value. By default this
/// uses the `visit_tuple` method to deserialize the value.
#[inline]
/// `visit_newtype` is called when deserializing a variant with a single value.
/// A good default is often to use the `visit_tuple` method to deserialize a `(value,)`.
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: Deserialize,
{
let (value,) = try!(self.visit_tuple(1, impls::TupleVisitor1::new()));
Ok(value)
}
where T: Deserialize;
/// `visit_tuple` is called when deserializing a tuple-like variant.
/// If no tuple variants are expected, yield a
/// `Err(serde::de::Error::invalid_type(serde::de::Type::TupleVariant))`
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::invalid_type(Type::TupleVariant))
}
len: usize,
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// `visit_struct` is called when deserializing a struct-like variant.
/// If no struct variants are expected, yield a
/// `Err(serde::de::Error::invalid_type(serde::de::Type::StructVariant))`
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::invalid_type(Type::StructVariant))
}
fields: &'static [&'static str],
visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
}
impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
+214 -1
View File
@@ -25,7 +25,7 @@ use collections::{
vec,
};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::Hash;
@@ -174,6 +174,22 @@ impl<E> de::Deserializer for UnitDeserializer<E>
{
type Error = E;
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct
}
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
@@ -209,6 +225,23 @@ macro_rules! primitive_deserializer {
{
type Error = E;
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
fn deserialize<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error>
where V: de::Visitor,
{
@@ -273,6 +306,22 @@ impl<'a, E> de::Deserializer for StrDeserializer<'a, E>
{
visitor.visit(self)
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
}
impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
@@ -289,6 +338,29 @@ impl<'a, E> de::VariantVisitor for StrDeserializer<'a, E>
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize,
{
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new()));
Ok(value)
}
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::TupleVariant))
}
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::StructVariant))
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -331,6 +403,22 @@ impl<E> de::Deserializer for StringDeserializer<E>
{
visitor.visit(self)
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
}
#[cfg(any(feature = "std", feature = "collections"))]
@@ -348,6 +436,29 @@ impl<'a, E> de::VariantVisitor for StringDeserializer<E>
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Ok(())
}
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
where T: super::Deserialize,
{
let (value,) = try!(self.visit_tuple(1, super::impls::TupleVisitor1::new()));
Ok(value)
}
fn visit_tuple<V>(&mut self,
_len: usize,
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::TupleVariant))
}
fn visit_struct<V>(&mut self,
_fields: &'static [&'static str],
_visitor: V) -> Result<V::Value, Self::Error>
where V: super::Visitor
{
Err(super::Error::invalid_type(super::Type::StructVariant))
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -384,6 +495,23 @@ impl<I, T, E> de::Deserializer for SeqDeserializer<I, E>
{
visitor.visit_seq(self)
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
}
impl<I, T, E> de::SeqVisitor for SeqDeserializer<I, E>
@@ -490,6 +618,23 @@ impl<V_, E> de::Deserializer for SeqVisitorDeserializer<V_, E>
fn deserialize<V: de::Visitor>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_seq(&mut self.visitor)
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -537,6 +682,23 @@ impl<I, K, V, E> de::Deserializer for MapDeserializer<I, K, V, E>
{
visitor.visit_map(self)
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
}
impl<I, K, V, E> de::MapVisitor for MapDeserializer<I, K, V, E>
@@ -648,6 +810,23 @@ impl<V_, E> de::Deserializer for MapVisitorDeserializer<V_, E>
fn deserialize<V: de::Visitor>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> {
visitor.visit_map(&mut self.visitor)
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -678,6 +857,23 @@ impl<'a, E> de::Deserializer for BytesDeserializer<'a, E>
None => Err(de::Error::end_of_stream()),
}
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
}
@@ -712,4 +908,21 @@ impl<E> de::Deserializer for ByteBufDeserializer<E>
None => Err(de::Error::end_of_stream()),
}
}
de_forward_to_deserialize!{
deserialize_bool,
deserialize_f64, deserialize_f32,
deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_usize,
deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_isize,
deserialize_char, deserialize_str, deserialize_string,
deserialize_ignored_any,
deserialize_bytes,
deserialize_unit_struct, deserialize_unit,
deserialize_seq, deserialize_seq_fixed_size,
deserialize_map, deserialize_newtype_struct, deserialize_struct_field,
deserialize_tuple,
deserialize_enum,
deserialize_struct, deserialize_tuple_struct,
deserialize_option
}
}
+2 -2
View File
@@ -4,7 +4,7 @@ use core::fmt::{Debug, Display};
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
pub trait Error: Debug + Display + ::core::marker::Reflect {
/// A short description of the error.
///
@@ -24,7 +24,7 @@ pub trait Error: Debug + Display + ::core::marker::Reflect {
}
/// A stand-in for `std::error::Error`, which requires no allocation.
#[cfg(not(feature = "nightly"))]
#[cfg(not(feature = "unstable"))]
pub trait Error: Debug + Display {
/// A short description of the error.
///
+9 -9
View File
@@ -5,35 +5,35 @@
//! 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
//! [github repository](https://github.com/serde-rs/serde)
#![doc(html_root_url="https://serde-rs.github.io/serde/serde")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "nightly", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))]
#![cfg_attr(feature = "unstable", feature(reflect_marker, unicode, nonzero, plugin, step_trait, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections, enumset))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(linkedlist))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(linkedlist))]
#![cfg_attr(any(not(feature = "std"), feature = "nightly"), allow(unused_variables, unused_imports, unused_features, dead_code))]
#![cfg_attr(any(not(feature = "std"), feature = "unstable"), allow(unused_variables, unused_imports, unused_features, dead_code))]
#![deny(missing_docs)]
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
extern crate collections;
#[cfg(all(feature = "nightly", feature = "alloc"))]
#[cfg(all(feature = "unstable", feature = "alloc"))]
extern crate alloc;
#[cfg(feature = "std")]
mod core {
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};
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
extern crate core;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
pub use self::core::nonzero;
}
+81 -265
View File
@@ -1,4 +1,8 @@
//! Implementations for all of Rust's builtin types.
//! 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")]
use std::borrow::Cow;
@@ -26,19 +30,19 @@ use collections::{
Vec,
};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::enum_set::{CLike, EnumSet};
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
use collections::borrow::ToOwned;
use core::hash::{Hash, BuildHasher};
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::iter;
#[cfg(feature = "std")]
use std::net;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::num;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::ops;
#[cfg(feature = "std")]
use std::path;
@@ -57,15 +61,13 @@ use alloc::boxed::Box;
use core::marker::PhantomData;
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
use core::nonzero::{NonZero, Zeroable};
use super::{
Error,
Serialize,
Serializer,
SeqVisitor,
MapVisitor,
};
///////////////////////////////////////////////////////////////////////////////
@@ -133,26 +135,6 @@ impl<T> Serialize for Option<T> where T: Serialize {
}
}
impl<T> SeqVisitor for Option<T> where T: Serialize {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.take() {
Some(value) => {
try!(serializer.serialize_seq_elt(value));
Ok(Some(()))
}
None => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some(if self.is_some() { 1 } else { 0 })
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for PhantomData<T> {
@@ -164,69 +146,6 @@ impl<T> Serialize for PhantomData<T> {
}
}
///////////////////////////////////////////////////////////////////////////////
/// A `serde::Visitor` for sequence iterators.
///
/// # Examples
///
/// ```
/// use serde::{Serialize, Serializer};
/// use serde::ser::impls::SeqIteratorVisitor;
///
/// struct Seq(Vec<u32>);
///
/// impl Serialize for Seq {
/// fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
/// where S: Serializer,
/// {
/// ser.serialize_seq(SeqIteratorVisitor::new(
/// self.0.iter(),
/// Some(self.0.len()),
/// ))
/// }
/// }
/// ```
pub struct SeqIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
}
impl<T, Iter> SeqIteratorVisitor<Iter>
where Iter: Iterator<Item=T>
{
/// Construct a new `SeqIteratorVisitor<Iter>`.
#[inline]
pub fn new(iter: Iter, len: Option<usize>) -> SeqIteratorVisitor<Iter> {
SeqIteratorVisitor {
iter: iter,
len: len,
}
}
}
impl<T, Iter> SeqVisitor for SeqIteratorVisitor<Iter>
where T: Serialize,
Iter: Iterator<Item=T>,
{
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.iter.next() {
Some(value) => {
try!(serializer.serialize_seq_elt(value));
Ok(Some(()))
}
None => Ok(None),
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
///////////////////////////////////////////////////////////////////////////////
@@ -237,7 +156,11 @@ impl<T> Serialize for [T]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
let mut state = try!(serializer.serialize_seq(Some(self.len())));
for e in self.iter() {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
}
}
@@ -250,8 +173,11 @@ macro_rules! array_impls {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let visitor = SeqIteratorVisitor::new(self.iter(), Some($len));
serializer.serialize_fixed_size_array(visitor)
let mut state = try!(serializer.serialize_seq_fixed_size($len));
for e in self.iter() {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
}
}
}
@@ -293,40 +219,40 @@ array_impls!(32);
///////////////////////////////////////////////////////////////////////////////
macro_rules! serialize_seq {
() => {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let mut state = try!(serializer.serialize_seq(Some(self.len())));
for e in self {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BinaryHeap<T>
where T: Serialize + Ord
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for BTreeSet<T>
where T: Serialize + Ord,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(all(feature = "nightly", feature = "collections"))]
#[cfg(all(feature = "unstable", feature = "collections"))]
impl<T> Serialize for EnumSet<T>
where T: Serialize + CLike
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(feature = "std")]
@@ -334,27 +260,27 @@ impl<T, H> Serialize for HashSet<T, H>
where T: Serialize + Eq + Hash,
H: BuildHasher,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for LinkedList<T>
where T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_seq!();
}
#[cfg(feature = "nightly")]
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for Vec<T> where T: Serialize {
serialize_seq!();
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for VecDeque<T> where T: Serialize {
serialize_seq!();
}
#[cfg(feature = "unstable")]
impl<A> Serialize for ops::Range<A>
where A: Serialize + Clone + iter::Step + num::One,
for<'a> &'a A: ops::Add<&'a A, Output = A>,
@@ -364,27 +290,11 @@ impl<A> Serialize for ops::Range<A>
where S: Serializer,
{
let len = iter::Step::steps_between(&self.start, &self.end, &A::one());
serializer.serialize_seq(SeqIteratorVisitor::new(self.clone(), len))
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for Vec<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(&self[..]).serialize(serializer)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<T> Serialize for VecDeque<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
let mut state = try!(serializer.serialize_seq(len));
for e in self.clone() {
try!(serializer.serialize_seq_elt(&mut state, e));
}
serializer.serialize_seq_end(state)
}
}
@@ -413,52 +323,18 @@ macro_rules! tuple_impls {
}
)+) => {
$(
/// A tuple visitor.
pub struct $TupleVisitor<'a, $($T: 'a),+> {
tuple: &'a ($($T,)+),
state: u8,
}
impl<'a, $($T: 'a),+> $TupleVisitor<'a, $($T),+> {
/// Construct a new, empty `TupleVisitor`.
pub fn new(tuple: &'a ($($T,)+)) -> $TupleVisitor<'a, $($T),+> {
$TupleVisitor {
tuple: tuple,
state: 0,
}
}
}
impl<'a, $($T),+> SeqVisitor for $TupleVisitor<'a, $($T),+>
where $($T: Serialize),+
{
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.state {
$(
$state => {
self.state += 1;
Ok(Some(try!(serializer.serialize_tuple_elt(&e!(self.tuple.$idx)))))
}
)+
_ => {
Ok(None)
}
}
}
fn len(&self) -> Option<usize> {
Some($len)
}
}
impl<$($T),+> Serialize for ($($T,)+)
where $($T: Serialize),+
{
#[inline]
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.serialize_tuple($TupleVisitor::new(self))
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let mut state = try!(serializer.serialize_tuple($len));
$(
try!(serializer.serialize_tuple_elt(&mut state, &e!(self.$idx)));
)+
serializer.serialize_tuple_end(state)
}
}
)+
@@ -638,83 +514,28 @@ tuple_impls! {
///////////////////////////////////////////////////////////////////////////////
/// A `serde::Visitor` for (key, value) map iterators.
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
/// use serde::{Serialize, Serializer};
/// use serde::ser::impls::MapIteratorVisitor;
///
/// struct Map(HashMap<u32, u32>);
///
/// impl Serialize for Map {
/// fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
/// where S: Serializer,
/// {
/// ser.serialize_map(MapIteratorVisitor::new(
/// self.0.iter(),
/// Some(self.0.len()),
/// ))
/// }
/// }
/// ```
pub struct MapIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
}
impl<K, V, Iter> MapIteratorVisitor<Iter>
where Iter: Iterator<Item=(K, V)>
{
/// Construct a new `MapIteratorVisitor<Iter>`.
#[inline]
pub fn new(iter: Iter, len: Option<usize>) -> MapIteratorVisitor<Iter> {
MapIteratorVisitor {
iter: iter,
len: len,
}
}
}
impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
where K: Serialize,
V: Serialize,
I: Iterator<Item=(K, V)>,
{
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.iter.next() {
Some((key, value)) => {
try!(serializer.serialize_map_elt(key, value));
Ok(Some(()))
macro_rules! serialize_map {
() => {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let mut state = try!(serializer.serialize_map(Some(self.len())));
for (k, v) in self {
try!(serializer.serialize_map_key(&mut state, k));
try!(serializer.serialize_map_value(&mut state, v));
}
None => Ok(None)
serializer.serialize_map_end(state)
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_map!();
}
#[cfg(feature = "std")]
@@ -723,12 +544,7 @@ impl<K, V, H> Serialize for HashMap<K, V, H>
V: Serialize,
H: BuildHasher,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.serialize_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
serialize_map!();
}
///////////////////////////////////////////////////////////////////////////////
@@ -808,7 +624,7 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
///////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", feature = "nightly"))]
#[cfg(all(feature = "std", feature = "unstable"))]
impl Serialize for net::IpAddr {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
@@ -893,7 +709,7 @@ impl Serialize for path::PathBuf {
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
impl<T> Serialize for NonZero<T> where T: Serialize + Zeroable {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
(**self).serialize(serializer)
+318 -289
View File
@@ -1,4 +1,14 @@
//! Generic serialization framework.
//! # For Developers who want to serialize objects
//! Implement the `Serialize` trait for the type of objects you want to serialize. Call methods of
//! the `serializer` object. For which methods to call and how to do so, look at the documentation
//! of the `Serializer` trait.
//!
//! # For Serialization Format Developers
//! Implement the `Serializer` trait for a structure that contains fields that enable it to write
//! the serialization result to your target. When a method's argument is an object of type
//! `Serialize`, you can either forward the serializer object (`self`) or create a new one,
//! depending on the quirks of your format.
#[cfg(feature = "std")]
use std::error;
@@ -15,11 +25,11 @@ pub mod impls;
/// `Error` is a trait that allows a `Serialize` to generically create a
/// `Serializer` error.
pub trait Error: Sized + error::Error {
/// Raised when there is general error when deserializing a type.
/// Raised when there is a general error when serializing a type.
#[cfg(any(feature = "std", feature = "collections"))]
fn custom<T: Into<String>>(msg: T) -> Self;
/// Raised when there is general error when deserializing a type.
/// Raised when there is a general error when serializing a type.
#[cfg(all(not(feature = "std"), not(feature = "collections")))]
fn custom<T: Into<&'static str>>(msg: T) -> Self;
@@ -41,343 +51,362 @@ pub trait Serialize {
///////////////////////////////////////////////////////////////////////////////
/// A trait that describes a type that can serialize a stream of values into the underlying format.
///
/// # For `Serialize` Developers
/// Non-aggrergate types like integers and strings can be serialized directly by calling the
/// appropriate function. For Aggregate types there's an initial `serialize_T` method that yields
/// a State object that you should not interact with. For each part of the aggregate there's a
/// `serialize_T_elt` method that allows you to pass values or key/value pairs. The types of the
/// values or the keys may change between calls, but the serialization format may not necessarily
/// accept it. The `serialize_T_elt` method also takes a mutable reference to the state object.
/// Make sure that you always use the same state object and only the state object that was returned
/// by the `serialize_T` method. Finally, when your object is done, call the `serialize_T_end`
/// method and pass the state object by value
///
/// # For Serialization Format Developers
/// If your format has different situations where it accepts different types, create a
/// `Serializer` for each situation. You can create the sub-`Serializer` in one of the aggregate
/// `serialize_T` methods and return it as a state object. Remember to also set the corresponding
/// associated type `TState`. In the `serialize_T_elt` methods you will be given a mutable
/// reference to that state. You do not need to do any additional checks for the correctness of the
/// state object, as it is expected that the user will not modify it. Due to the generic nature
/// of the `Serialize` impls, modifying the object is impossible on stable Rust.
pub trait Serializer {
/// The error type that can be returned if some error occurs during serialization.
type Error: Error;
/// A state object that is initialized by `serialize_seq`, passed to
/// `serialize_seq_elt`, and consumed by `serialize_seq_end`. Use `()` if no
/// state is required.
type SeqState;
/// A state object that is initialized by `serialize_tuple`, passed to
/// `serialize_tuple_elt`, and consumed by `serialize_tuple_end`. Use `()`
/// if no state is required.
type TupleState;
/// A state object that is initialized by `serialize_tuple_struct`, passed
/// to `serialize_tuple_struct_elt`, and consumed by
/// `serialize_tuple_struct_end`. Use `()` if no state is required.
type TupleStructState;
/// A state object that is initialized by `serialize_tuple_variant`, passed
/// to `serialize_tuple_variant_elt`, and consumed by
/// `serialize_tuple_variant_end`. Use `()` if no state is required.
type TupleVariantState;
/// A state object that is initialized by `serialize_map`, passed to
/// `serialize_map_elt`, and consumed by `serialize_map_end`. Use `()` if no
/// state is required.
type MapState;
/// A state object that is initialized by `serialize_struct`, passed to
/// `serialize_struct_elt`, and consumed by `serialize_struct_end`. Use `()`
/// if no state is required.
type StructState;
/// A state object that is initialized by `serialize_struct_variant`, passed
/// to `serialize_struct_variant_elt`, and consumed by
/// `serialize_struct_variant_end`. Use `()` if no state is required.
type StructVariantState;
/// Serializes a `bool` value.
fn serialize_bool(&mut self, v: bool) -> Result<(), Self::Error>;
/// Serializes a `isize` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn serialize_isize(&mut self, v: isize) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// Serializes an `isize` value. If the format does not differentiate
/// between `isize` and `i64`, a reasonable implementation would be to cast
/// the value to `i64` and forward to `serialize_i64`.
fn serialize_isize(&mut self, v: isize) -> Result<(), Self::Error>;
/// Serializes a `i8` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn serialize_i8(&mut self, v: i8) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// Serializes an `i8` value. If the format does not differentiate between
/// `i8` and `i64`, a reasonable implementation would be to cast the value
/// to `i64` and forward to `serialize_i64`.
fn serialize_i8(&mut self, v: i8) -> Result<(), Self::Error>;
/// Serializes a `i16` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn serialize_i16(&mut self, v: i16) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// Serializes an `i16` value. If the format does not differentiate between
/// `i16` and `i64`, a reasonable implementation would be to cast the value
/// to `i64` and forward to `serialize_i64`.
fn serialize_i16(&mut self, v: i16) -> Result<(), Self::Error>;
/// Serializes a `i32` value. By default it casts the value to a `i64` and
/// passes it to the `serialize_i64` method.
#[inline]
fn serialize_i32(&mut self, v: i32) -> Result<(), Self::Error> {
self.serialize_i64(v as i64)
}
/// Serializes an `i32` value. If the format does not differentiate between
/// `i32` and `i64`, a reasonable implementation would be to cast the value
/// to `i64` and forward to `serialize_i64`.
fn serialize_i32(&mut self, v: i32) -> Result<(), Self::Error>;
/// Serializes a `i64` value.
#[inline]
/// Serializes an `i64` value.
fn serialize_i64(&mut self, v: i64) -> Result<(), Self::Error>;
/// Serializes a `usize` value. By default it casts the value to a `u64` and
/// passes it to the `serialize_u64` method.
#[inline]
fn serialize_usize(&mut self, v: usize) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// Serializes a `usize` value. If the format does not differentiate between
/// `usize` and `u64`, a reasonable implementation would be to cast the
/// value to `u64` and forward to `serialize_u64`.
fn serialize_usize(&mut self, v: usize) -> Result<(), Self::Error>;
/// Serializes a `u8` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn serialize_u8(&mut self, v: u8) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// Serializes a `u8` value. If the format does not differentiate between
/// `u8` and `u64`, a reasonable implementation would be to cast the value
/// to `u64` and forward to `serialize_u64`.
fn serialize_u8(&mut self, v: u8) -> Result<(), Self::Error>;
/// Serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn serialize_u16(&mut self, v: u16) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// Serializes a `u16` value. If the format does not differentiate between
/// `u16` and `u64`, a reasonable implementation would be to cast the value
/// to `u64` and forward to `serialize_u64`.
fn serialize_u16(&mut self, v: u16) -> Result<(), Self::Error>;
/// Serializes a `u32` value. By default it casts the value to a `u64` and passes
/// it to the `serialize_u64` method.
#[inline]
fn serialize_u32(&mut self, v: u32) -> Result<(), Self::Error> {
self.serialize_u64(v as u64)
}
/// Serializes a `u32` value. If the format does not differentiate between
/// `u32` and `u64`, a reasonable implementation would be to cast the value
/// to `u64` and forward to `serialize_u64`.
fn serialize_u32(&mut self, v: u32) -> Result<(), Self::Error>;
/// `Serializes a `u64` value.
#[inline]
fn serialize_u64(&mut self, v: u64) -> Result<(), Self::Error>;
/// Serializes a `f32` value. By default it casts the value to a `f64` and passes
/// it to the `serialize_f64` method.
#[inline]
fn serialize_f32(&mut self, v: f32) -> Result<(), Self::Error> {
self.serialize_f64(v as f64)
}
/// Serializes an `f32` value. If the format does not differentiate between
/// `f32` and `f64`, a reasonable implementation would be to cast the value
/// to `f64` and forward to `serialize_f64`.
fn serialize_f32(&mut self, v: f32) -> Result<(), Self::Error>;
/// Serializes a `f64` value.
/// Serializes an `f64` value.
fn serialize_f64(&mut self, v: f64) -> Result<(), Self::Error>;
/// Serializes a character. By default it serializes it as a `&str` containing a
/// single character.
#[inline]
fn serialize_char(&mut self, v: char) -> Result<(), Self::Error> {
self.serialize_str(::utils::encode_utf8(v).as_str())
}
/// Serializes a character. If the format does not support characters,
/// it is reasonable to serialize it as a single element `str` or a `u32`.
fn serialize_char(&mut self, v: char) -> Result<(), Self::Error>;
/// Serializes a `&str`.
fn serialize_str(&mut self, value: &str) -> Result<(), Self::Error>;
/// Enables those serialization formats that support serializing
/// byte slices separately from generic arrays. By default it serializes as a regular array.
#[inline]
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.serialize_seq(impls::SeqIteratorVisitor::new(value.iter(), Some(value.len())))
}
/// Enables serializers to serialize byte slices more compactly or more
/// efficiently than other types of slices. If no efficient implementation
/// is available, a reasonable implementation would be to forward to
/// `serialize_seq`. If forwarded, the implementation looks usually just like this:
/// ```rust
/// let mut state = try!(self.serialize_seq(value));
/// for b in value {
/// try!(self.serialize_seq_elt(&mut state, b));
/// }
/// self.serialize_seq_end(state)
/// ```
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error>;
/// Serializes a `()` value.
/// Serializes a `()` value. It's reasonable to just not serialize anything.
fn serialize_unit(&mut self) -> Result<(), Self::Error>;
/// Serializes a unit struct value.
///
/// By default, unit structs are serialized as a `()`.
#[inline]
fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Self::Error> {
self.serialize_unit()
}
/// Serializes a unit struct value. A reasonable implementation would be to
/// forward to `serialize_unit`.
fn serialize_unit_struct(
&mut self,
name: &'static str,
) -> Result<(), Self::Error>;
/// Serializes a unit variant, otherwise known as a variant with no arguments.
///
/// By default, unit variants are serialized as a `()`.
#[inline]
fn serialize_unit_variant(&mut self,
_name: &'static str,
_variant_index: usize,
_variant: &'static str) -> Result<(), Self::Error> {
self.serialize_unit()
}
/// Serializes a unit variant, otherwise known as a variant with no
/// arguments. A reasonable implementation would be to forward to
/// `serialize_unit`.
fn serialize_unit_variant(
&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
) -> Result<(), Self::Error>;
/// Allows a tuple struct with a single element, also known as a
/// newtyped value, to be more efficiently serialized than a tuple struct with multiple items.
/// By default it just serializes the value as a tuple struct sequence.
#[inline]
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Self::Error>
where T: Serialize,
{
self.serialize_tuple_struct(name, Some(value))
}
/// Allows a tuple struct with a single element, also known as a newtype
/// struct, to be more efficiently serialized than a tuple struct with
/// multiple items. A reasonable implementation would be to forward to
/// `serialize_tuple_struct` or to just serialize the inner value without wrapping.
fn serialize_newtype_struct<T: Serialize>(
&mut self,
name: &'static str,
value: T,
) -> Result<(), Self::Error>;
/// Allows a variant with a single item to be more efficiently
/// serialized than a variant with multiple items. By default it just serializes the value as a
/// tuple variant sequence.
#[inline]
fn serialize_newtype_variant<T>(&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: T) -> Result<(), Self::Error>
where T: Serialize,
{
self.serialize_tuple_variant(
name,
variant_index,
variant,
Some(value))
}
/// Allows a variant with a single item to be more efficiently serialized
/// than a variant with multiple items. A reasonable implementation would be
/// to forward to `serialize_tuple_variant`.
fn serialize_newtype_variant<T: Serialize>(
&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a `None` value..serialize
/// Serializes a `None` value.
fn serialize_none(&mut self) -> Result<(), Self::Error>;
/// Serializes a `Some(...)` value.
fn serialize_some<V>(&mut self, value: V) -> Result<(), Self::Error>
where V: Serialize;
fn serialize_some<T: Serialize>(
&mut self,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a sequence.
///
/// Callees of this method need to construct a `SeqVisitor`, which iterates through each item
/// in the sequence.
fn serialize_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor;
/// Begins to serialize a sequence. This call must be followed by zero or
/// more calls to `serialize_seq_elt`, then a call to `serialize_seq_end`.
fn serialize_seq(
&mut self,
len: Option<usize>,
) -> Result<Self::SeqState, Self::Error>;
/// Serializes a sequence element.
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize;
/// Serializes a sequence element. Must have previously called
/// `serialize_seq`.
fn serialize_seq_elt<T: Serialize>(
&mut self,
state: &mut Self::SeqState,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a tuple.
///
/// By default this serializes a tuple as a sequence.
#[inline]
fn serialize_tuple<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_seq(visitor)
}
/// Finishes serializing a sequence.
fn serialize_seq_end(
&mut self,
state: Self::SeqState,
) -> Result<(), Self::Error>;
/// Serializes a tuple element.
///
/// By default, tuples are serialized as a sequence.
#[inline]
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.serialize_seq_elt(value)
}
/// Begins to serialize a sequence whose length will be known at
/// deserialization time. This call must be followed by zero or more calls
/// to `serialize_seq_elt`, then a call to `serialize_seq_end`. A reasonable
/// implementation would be to forward to `serialize_seq`.
fn serialize_seq_fixed_size(
&mut self,
size: usize,
) -> Result<Self::SeqState, Self::Error>;
/// Serializes a fixed-size array.
///
/// By default this serializes an array as a sequence.
#[inline]
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_seq(visitor)
}
/// Begins to serialize a tuple. This call must be followed by zero or more
/// calls to `serialize_tuple_elt`, then a call to `serialize_tuple_end`. A
/// reasonable implementation would be to forward to `serialize_seq`.
fn serialize_tuple(
&mut self,
len: usize,
) -> Result<Self::TupleState, Self::Error>;
/// Serializes a tuple struct.
///
/// By default, tuple structs are serialized as a tuple.
#[inline]
fn serialize_tuple_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_tuple(visitor)
}
/// Serializes a tuple element. Must have previously called
/// `serialize_tuple`.
fn serialize_tuple_elt<T: Serialize>(
&mut self,
state: &mut Self::TupleState,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a tuple struct element.
///
/// By default, tuple struct elements are serialized as a tuple element.
#[inline]
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.serialize_tuple_elt(value)
}
/// Finishes serializing a tuple.
fn serialize_tuple_end(
&mut self,
state: Self::TupleState,
) -> Result<(), Self::Error>;
/// Serializes a tuple variant.
///
/// By default, tuple variants are serialized as a tuple struct.
#[inline]
fn serialize_tuple_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.serialize_tuple_struct(variant, visitor)
}
/// Begins to serialize a tuple struct. This call must be followed by zero
/// or more calls to `serialize_tuple_struct_elt`, then a call to
/// `serialize_tuple_struct_end`. A reasonable implementation would be to
/// forward to `serialize_tuple`.
fn serialize_tuple_struct(
&mut self,
name: &'static str,
len: usize,
) -> Result<Self::TupleStructState, Self::Error>;
/// Serializes a tuple element.
///
/// By default, tuples are serialized as a sequence.
#[inline]
fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.serialize_tuple_struct_elt(value)
}
/// Serializes a tuple struct element. Must have previously called
/// `serialize_tuple_struct`.
fn serialize_tuple_struct_elt<T: Serialize>(
&mut self,
state: &mut Self::TupleStructState,
value: T,
) -> Result<(), Self::Error>;
/// Serializes a map.
///
/// Callees of this method need to construct a `MapVisitor`, which iterates through each item
/// in the map.
fn serialize_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: MapVisitor;
/// Finishes serializing a tuple struct.
fn serialize_tuple_struct_end(
&mut self,
state: Self::TupleStructState,
) -> Result<(), Self::Error>;
/// Serializes a map element (key-value pair).
fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize;
/// Begins to serialize a tuple variant. This call must be followed by zero
/// or more calls to `serialize_tuple_variant_elt`, then a call to
/// `serialize_tuple_variant_end`. A reasonable implementation would be to
/// forward to `serialize_tuple_struct`.
fn serialize_tuple_variant(
&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize,
) -> Result<Self::TupleVariantState, Self::Error>;
/// Serializes a struct.
///
/// By default, structs are serialized as a map with the field name as the key.
#[inline]
fn serialize_struct<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.serialize_map(visitor)
}
/// Serializes a tuple variant element. Must have previously called
/// `serialize_tuple_variant`.
fn serialize_tuple_variant_elt<T: Serialize>(
&mut self,
state: &mut Self::TupleVariantState,
value: T,
) -> Result<(), Self::Error>;
/// Serializes an element of a struct.
///
/// By default, struct elements are serialized as a map element with the field name as the key.
#[inline]
fn serialize_struct_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
where V: Serialize,
{
self.serialize_map_elt(key, value)
}
/// Finishes serializing a tuple variant.
fn serialize_tuple_variant_end(
&mut self,
state: Self::TupleVariantState,
) -> Result<(), Self::Error>;
/// Serializes a struct variant.
///
/// By default, struct variants are serialized as a struct.
#[inline]
fn serialize_struct_variant<V>(&mut self,
_name: &'static str,
_variant_index: usize,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.serialize_struct(variant, visitor)
}
/// Begins to serialize a map. This call must be followed by zero or more
/// calls to `serialize_map_key` and `serialize_map_value`, then a call to
/// `serialize_map_end`.
fn serialize_map(
&mut self,
len: Option<usize>,
) -> Result<Self::MapState, Self::Error>;
/// Serializes an element of a struct variant.
///
/// By default, struct variant elements are serialized as a struct element.
#[inline]
fn serialize_struct_variant_elt<V>(&mut self,
key: &'static str,
value: V) -> Result<(), Self::Error>
where V: Serialize,
{
self.serialize_struct_elt(key, value)
}
}
/// A trait that is used by a `Serialize` to iterate through a sequence.
#[cfg_attr(feature = "nightly-testing", allow(len_without_is_empty))]
pub trait SeqVisitor {
/// Serializes a sequence item in the serializer.
///
/// This returns `Ok(Some(()))` when there are more items to serialize, or `Ok(None)` when
/// complete.
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer;
/// Return the length of the sequence if known.
#[inline]
fn len(&self) -> Option<usize> {
None
}
}
/// A trait that is used by a `Serialize` to iterate through a map.
#[cfg_attr(feature = "nightly-testing", allow(len_without_is_empty))]
pub trait MapVisitor {
/// Serializes a map item in the serializer.
///
/// This returns `Ok(Some(()))` when there are more items to serialize, or `Ok(None)` when
/// complete.
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer;
/// Return the length of the map if known.
#[inline]
fn len(&self) -> Option<usize> {
None
}
/// Serialize a map key. Must have previously called `serialize_map`.
fn serialize_map_key<T: Serialize>(
&mut self,
state: &mut Self::MapState,
key: T
) -> Result<(), Self::Error>;
/// Serialize a map value. Must have previously called `serialize_map`.
fn serialize_map_value<T: Serialize>(
&mut self,
state: &mut Self::MapState,
value: T
) -> Result<(), Self::Error>;
/// Finishes serializing a map.
fn serialize_map_end(
&mut self,
state: Self::MapState,
) -> Result<(), Self::Error>;
/// Begins to serialize a struct. This call must be followed by zero or more
/// calls to `serialize_struct_elt`, then a call to `serialize_struct_end`.
fn serialize_struct(
&mut self,
name: &'static str,
len: usize,
) -> Result<Self::StructState, Self::Error>;
/// Serializes a struct field. Must have previously called
/// `serialize_struct`.
fn serialize_struct_elt<V: Serialize>(
&mut self,
state: &mut Self::StructState,
key: &'static str,
value: V,
) -> Result<(), Self::Error>;
/// Finishes serializing a struct.
fn serialize_struct_end(
&mut self,
state: Self::StructState,
) -> Result<(), Self::Error>;
/// Begins to serialize a struct variant. This call must be followed by zero
/// or more calls to `serialize_struct_variant_elt`, then a call to
/// `serialize_struct_variant_end`.
fn serialize_struct_variant(
&mut self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize,
) -> Result<Self::StructVariantState, Self::Error>;
/// Serialize a struct variant element. Must have previously called
/// `serialize_struct_variant`.
fn serialize_struct_variant_elt<V: Serialize>(
&mut self,
state: &mut Self::StructVariantState,
key: &'static str,
value: V,
) -> Result<(), Self::Error>;
/// Finishes serializing a struct variant.
fn serialize_struct_variant_end(
&mut self,
state: Self::StructVariantState,
) -> Result<(), Self::Error>;
}
+12 -12
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_codegen"
version = "0.7.11"
version = "0.8.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
@@ -12,26 +12,26 @@ include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/lib.rs.in"]
[features]
default = ["with-syntex"]
nightly = ["quasi_macros"]
nightly-testing = ["clippy"]
unstable = ["quasi_macros"]
unstable-testing = ["clippy"]
with-syntex = [
"quasi/with-syntex",
"quasi_codegen",
"quasi_codegen/with-syntex",
"serde_item/with-syntex",
"serde_codegen_internals/with-syntex",
"syntex",
"syntex_syntax",
]
[build-dependencies]
quasi_codegen = { version = "^0.13.0", optional = true }
syntex = { version = "^0.36.0", optional = true }
quasi_codegen = { version = "^0.16.0", optional = true }
syntex = { version = "^0.39.0", optional = true }
[dependencies]
aster = { version = "^0.19.0", default-features = false }
aster = { version = "^0.22.0", default-features = false }
clippy = { version = "^0.*", optional = true }
quasi = { version = "^0.13.0", default-features = false }
quasi_macros = { version = "^0.13.0", optional = true }
serde_item = { version = "^0.2.0", path = "../serde_item", default-features = false }
syntex = { version = "^0.36.0", optional = true }
syntex_syntax = { version = "^0.36.0", optional = true }
quasi = { version = "^0.16.0", default-features = false }
quasi_macros = { version = "^0.16.0", optional = true }
serde_codegen_internals = { version = "0.5.0", default-features = false }
syntex = { version = "^0.39.0", optional = true }
syntex_syntax = { version = "^0.39.0", optional = true }
+63 -127
View File
@@ -3,10 +3,10 @@ use std::collections::HashSet;
use aster::AstBuilder;
use syntax::ast;
use syntax::ptr::P;
use syntax::visit;
use item::{attr, Item};
use internals::ast::Item;
use internals::attr;
// Remove the default from every type parameter because in the generated impls
// they look like associated types: "error: associated type bindings are not
@@ -48,6 +48,17 @@ pub fn with_where_predicates_from_fields<F>(
.build()
}
// Puts the given bound on any generic type parameters that are used in fields
// for which filter returns true.
//
// For example, the following struct needs the bound `A: Serialize, B: Serialize`.
//
// struct S<'b, A, B: 'b, C> {
// a: A,
// b: Option<&'b B>
// #[serde(skip_serializing)]
// c: C,
// }
pub fn with_bound<F>(
builder: &AstBuilder,
item: &Item,
@@ -57,135 +68,60 @@ pub fn with_bound<F>(
) -> ast::Generics
where F: Fn(&attr::Field) -> bool,
{
struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in
// the example). Initialized up front.
all_ty_params: HashSet<ast::Name>,
// Set of generic type parameters used in fields for which filter
// returns true (A and B in the example). Filled in as the visitor sees
// them.
relevant_ty_params: HashSet<ast::Name>,
}
impl visit::Visitor for FindTyParams {
fn visit_path(&mut self, path: &ast::Path, _id: ast::NodeId) {
if let Some(seg) = path.segments.last() {
if seg.identifier.name.as_str() == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
}
}
if !path.global && path.segments.len() == 1 {
let id = path.segments[0].identifier.name;
if self.all_ty_params.contains(&id) {
self.relevant_ty_params.insert(id);
}
}
visit::walk_path(self, path);
}
}
let all_ty_params: HashSet<_> = generics.ty_params.iter()
.map(|ty_param| ty_param.ident.name)
.collect();
let relevant_tys = item.body.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty);
let mut visitor = FindTyParams {
all_ty_params: all_ty_params,
relevant_ty_params: HashSet::new(),
};
for ty in relevant_tys {
visit::walk_ty(&mut visitor, ty);
}
builder.from_generics(generics.clone())
.with_predicates(
item.body.all_fields()
.filter(|&field| filter(&field.attrs))
.map(|field| &field.ty)
// TODO this filter can be removed later, see comment on function
.filter(|ty| contains_generic(ty, generics))
.filter(|ty| !contains_recursion(ty, item.ident))
.map(|ty| strip_reference(ty))
.map(|ty| builder.where_predicate()
// the type that is being bounded e.g. T
.bound().build(ty.clone())
generics.ty_params.iter()
.map(|ty_param| ty_param.ident.name)
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| builder.where_predicate()
// the type parameter that is being bounded e.g. T
.bound().build(builder.ty().id(id))
// the bound e.g. Serialize
.bound().trait_(bound.clone()).build()
.build()))
.build()
}
// Rust <1.7 enforces that `where` clauses involve generic type parameters. The
// corresponding compiler error is E0193. It is no longer enforced in Rust >=1.7
// so this filtering can be removed in the future when we stop supporting <1.7.
//
// E0193 means we must not generate a `where` clause like `i32: Serialize`
// because even though i32 implements Serialize, i32 is not a generic type
// parameter. Clauses like `T: Serialize` and `Option<T>: Serialize` are okay.
// This function decides whether a given type references any of the generic type
// parameters in the input `Generics`.
fn contains_generic(ty: &ast::Ty, generics: &ast::Generics) -> bool {
struct FindGeneric<'a> {
generic_names: &'a HashSet<ast::Name>,
found_generic: bool,
}
impl<'a, 'v> visit::Visitor<'v> for FindGeneric<'a> {
fn visit_path(&mut self, path: &'v ast::Path, _id: ast::NodeId) {
if !path.global
&& path.segments.len() == 1
&& self.generic_names.contains(&path.segments[0].identifier.name) {
self.found_generic = true;
} else {
visit::walk_path(self, path);
}
}
}
let generic_names: HashSet<_> = generics.ty_params.iter()
.map(|ty_param| ty_param.ident.name)
.collect();
let mut visitor = FindGeneric {
generic_names: &generic_names,
found_generic: false,
};
visit::walk_ty(&mut visitor, ty);
visitor.found_generic
}
// We do not attempt to generate any bounds based on field types that are
// directly recursive, as in:
//
// struct Test<D> {
// next: Box<Test<D>>,
// }
//
// This does not catch field types that are mutually recursive with some other
// type. For those, we require bounds to be specified by a `bound` attribute if
// the inferred ones are not correct.
//
// struct Test<D> {
// #[serde(bound="D: Serialize + Deserialize")]
// next: Box<Other<D>>,
// }
// struct Other<D> {
// #[serde(bound="D: Serialize + Deserialize")]
// next: Box<Test<D>>,
// }
fn contains_recursion(ty: &ast::Ty, ident: ast::Ident) -> bool {
struct FindRecursion {
ident: ast::Ident,
found_recursion: bool,
}
impl<'v> visit::Visitor<'v> for FindRecursion {
fn visit_path(&mut self, path: &'v ast::Path, _id: ast::NodeId) {
if !path.global
&& path.segments.len() == 1
&& path.segments[0].identifier == self.ident {
self.found_recursion = true;
} else {
visit::walk_path(self, path);
}
}
}
let mut visitor = FindRecursion {
ident: ident,
found_recursion: false,
};
visit::walk_ty(&mut visitor, ty);
visitor.found_recursion
}
// This is required to handle types that use both a reference and a value of
// the same type, as in:
//
// enum Test<'a, T> where T: 'a {
// Lifetime(&'a T),
// NoLifetime(T),
// }
//
// Preserving references, we would generate an impl like:
//
// impl<'a, T> Serialize for Test<'a, T>
// where &'a T: Serialize,
// T: Serialize { ... }
//
// And taking a reference to one of the elements would fail with:
//
// error: cannot infer an appropriate lifetime for pattern due
// to conflicting requirements [E0495]
// Test::NoLifetime(ref v) => { ... }
// ^~~~~
//
// Instead, we strip references before adding `T: Serialize` bounds in order to
// generate:
//
// impl<'a, T> Serialize for Test<'a, T>
// where T: Serialize { ... }
fn strip_reference(mut ty: &P<ast::Ty>) -> &P<ast::Ty> {
while let ast::TyKind::Rptr(_, ref mut_ty) = ty.node {
ty = &mut_ty.ty;
}
ty
}
+42 -36
View File
@@ -5,10 +5,12 @@ use syntax::codemap::Span;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::parse::token::InternedString;
use syntax::ptr::P;
use syntax::tokenstream::TokenTree;
use bound;
use error::Error;
use item::{self, attr};
use span;
use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{attr, Error};
pub fn expand_derive_deserialize(
cx: &mut ExtCtxt,
@@ -27,9 +29,9 @@ pub fn expand_derive_deserialize(
}
};
let item = match item::Item::from_ast(cx, item) {
let item = match Item::from_ast(cx, item) {
Ok(item) => item,
Err(item::Error::UnexpectedItemKind) => {
Err(Error::UnexpectedItemKind) => {
cx.span_err(item.span,
"`#[derive(Deserialize)]` may only be applied to structs and enums");
return;
@@ -43,13 +45,13 @@ pub fn expand_derive_deserialize(
let builder = aster::AstBuilder::new().span(span);
let impl_item = deserialize_item(cx, &builder, &item);
push(Annotatable::Item(impl_item))
push(span::record_expansion(cx, impl_item, "Deserialize"))
}
fn deserialize_item(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &item::Item,
item: &Item,
) -> P<ast::Item> {
let impl_generics = build_impl_generics(builder, &item);
@@ -88,7 +90,7 @@ fn deserialize_item(
// each generic field type that will be set to a default value.
fn build_impl_generics(
builder: &aster::AstBuilder,
item: &item::Item,
item: &Item,
) -> ast::Generics {
let generics = bound::without_defaults(item.generics);
@@ -131,12 +133,12 @@ fn requires_default(attrs: &attr::Field) -> bool {
fn deserialize_body(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &item::Item,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
match item.body {
item::Body::Enum(ref variants) => {
Body::Enum(ref variants) => {
deserialize_item_enum(
cx,
builder,
@@ -146,7 +148,7 @@ fn deserialize_body(
variants,
&item.attrs)
}
item::Body::Struct(item::Style::Struct, ref fields) => {
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
cx.span_bug(item.span, "struct has unnamed fields")
}
@@ -161,8 +163,8 @@ fn deserialize_body(
fields,
&item.attrs)
}
item::Body::Struct(item::Style::Tuple, ref fields) |
item::Body::Struct(item::Style::Newtype, ref fields) => {
Body::Struct(Style::Tuple, ref fields) |
Body::Struct(Style::Newtype, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
cx.span_bug(item.span, "tuple struct has named fields")
}
@@ -177,7 +179,7 @@ fn deserialize_body(
fields,
&item.attrs)
}
item::Body::Struct(item::Style::Unit, _) => {
Body::Struct(Style::Unit, _) => {
deserialize_unit_struct(
cx,
builder,
@@ -308,7 +310,7 @@ fn deserialize_tuple(
variant_ident: Option<Ident>,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[item::Field],
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause;
@@ -390,9 +392,10 @@ fn deserialize_seq(
type_ident: Ident,
type_path: ast::Path,
impl_generics: &ast::Generics,
fields: &[item::Field],
fields: &[Field],
is_struct: bool,
) -> P<ast::Expr> {
let mut index_in_seq = 0usize;
let let_values: Vec<_> = fields.iter()
.enumerate()
.map(|(i, field)| {
@@ -418,14 +421,17 @@ fn deserialize_seq(
})
}
};
quote_stmt!(cx,
let assign = quote_stmt!(cx,
let $name = match $visit {
Some(value) => { value },
None => {
return Err(_serde::de::Error::end_of_stream());
try!(visitor.end());
return Err(_serde::de::Error::invalid_length($index_in_seq));
}
};
).unwrap()
).unwrap();
index_in_seq += 1;
assign
}
})
.collect();
@@ -470,8 +476,8 @@ fn deserialize_newtype_struct(
type_ident: Ident,
type_path: &ast::Path,
impl_generics: &ast::Generics,
field: &item::Field,
) -> Vec<ast::TokenTree> {
field: &Field,
) -> Vec<TokenTree> {
let value = match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
@@ -505,7 +511,7 @@ fn deserialize_struct(
variant_ident: Option<Ident>,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[item::Field],
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause;
@@ -587,7 +593,7 @@ fn deserialize_item_enum(
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
variants: &[item::Variant],
variants: &[Variant],
item_attrs: &attr::Item
) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause;
@@ -678,19 +684,19 @@ fn deserialize_variant(
type_ident: Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
variant: &item::Variant,
variant: &Variant,
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let variant_ident = variant.ident;
match variant.style {
item::Style::Unit => {
Style::Unit => {
quote_expr!(cx, {
try!(visitor.visit_unit());
Ok($type_ident::$variant_ident)
})
}
item::Style::Newtype => {
Style::Newtype => {
deserialize_newtype_variant(
cx,
builder,
@@ -700,7 +706,7 @@ fn deserialize_variant(
&variant.fields[0],
)
}
item::Style::Tuple => {
Style::Tuple => {
deserialize_tuple(
cx,
builder,
@@ -712,7 +718,7 @@ fn deserialize_variant(
item_attrs,
)
}
item::Style::Struct => {
Style::Struct => {
deserialize_struct(
cx,
builder,
@@ -733,7 +739,7 @@ fn deserialize_newtype_variant(
type_ident: Ident,
variant_ident: Ident,
impl_generics: &ast::Generics,
field: &item::Field,
field: &Field,
) -> P<ast::Expr> {
let visit = match field.attrs.deserialize_with() {
None => {
@@ -919,7 +925,7 @@ fn deserialize_struct_visitor(
type_ident: Ident,
struct_path: ast::Path,
impl_generics: &ast::Generics,
fields: &[item::Field],
fields: &[Field],
item_attrs: &attr::Item,
) -> (Vec<P<ast::Item>>, ast::Stmt, P<ast::Expr>) {
let field_exprs = fields.iter()
@@ -971,7 +977,7 @@ fn deserialize_map(
type_ident: Ident,
struct_path: ast::Path,
impl_generics: &ast::Generics,
fields: &[item::Field],
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
// Create the field names for the fields.
@@ -1091,10 +1097,10 @@ fn deserialize_map(
}
}
$extract_values
try!(visitor.end());
$extract_values
Ok($result)
})
}
@@ -1187,14 +1193,14 @@ fn name_expr(
fn check_no_str(
cx: &ExtCtxt,
item: &item::Item,
) -> Result<(), Error> {
let fail = |field: &item::Field| {
item: &Item,
) -> Result<(), ()> {
let fail = |field: &Field| {
cx.span_err(
field.span,
"Serde does not support deserializing fields of type &str; \
consider using String instead");
Err(Error)
Err(())
};
for field in item.body.all_fields() {
-2
View File
@@ -1,2 +0,0 @@
/// Error returned if failed to parse attribute.
pub struct Error;
+9 -12
View File
@@ -1,13 +1,13 @@
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", allow(too_many_arguments))]
#![cfg_attr(feature = "nightly-testing", allow(used_underscore_binding))]
#![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))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(quasi_macros))]
extern crate aster;
extern crate quasi;
extern crate serde_item as item;
extern crate serde_codegen_internals as internals;
#[cfg(feature = "with-syntex")]
extern crate syntex;
@@ -40,13 +40,6 @@ pub fn expand<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
D: AsRef<Path>,
{
let mut registry = syntex::Registry::new();
register(&mut registry);
registry.expand("", src.as_ref(), dst.as_ref())
}
#[cfg(feature = "with-syntex")]
pub fn register(reg: &mut syntex::Registry) {
use syntax::{ast, fold};
/// Strip the serde attributes from the crate.
@@ -73,6 +66,8 @@ pub fn register(reg: &mut syntex::Registry) {
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)");
@@ -80,6 +75,8 @@ pub fn register(reg: &mut syntex::Registry) {
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
reg.expand("", src.as_ref(), dst.as_ref())
}
#[cfg(not(feature = "with-syntex"))]
+1 -1
View File
@@ -1,4 +1,4 @@
mod bound;
mod de;
mod error;
mod ser;
mod span;
+125 -312
View File
@@ -6,7 +6,9 @@ use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ptr::P;
use bound;
use item::{self, attr};
use span;
use internals::ast::{Body, Field, Item, Style, Variant};
use internals::{attr, Error};
pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
@@ -25,9 +27,9 @@ pub fn expand_derive_serialize(
}
};
let item = match item::Item::from_ast(cx, item) {
let item = match Item::from_ast(cx, item) {
Ok(item) => item,
Err(item::Error::UnexpectedItemKind) => {
Err(Error::UnexpectedItemKind) => {
cx.span_err(item.span,
"`#[derive(Serialize)]` may only be applied to structs and enums");
return;
@@ -37,13 +39,13 @@ pub fn expand_derive_serialize(
let builder = aster::AstBuilder::new().span(span);
let impl_item = serialize_item(cx, &builder, &item);
push(Annotatable::Item(impl_item))
push(span::record_expansion(cx, impl_item, "Serialize"))
}
fn serialize_item(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &item::Item,
item: &Item,
) -> P<ast::Item> {
let impl_generics = build_impl_generics(builder, &item);
@@ -81,7 +83,7 @@ fn serialize_item(
// field type that will be serialized by us.
fn build_impl_generics(
builder: &aster::AstBuilder,
item: &item::Item,
item: &Item,
) -> ast::Generics {
let generics = bound::without_defaults(item.generics);
@@ -114,12 +116,12 @@ fn needs_serialize_bound(attrs: &attr::Field) -> bool {
fn serialize_body(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
item: &item::Item,
item: &Item,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
) -> P<ast::Expr> {
match item.body {
item::Body::Enum(ref variants) => {
Body::Enum(ref variants) => {
serialize_item_enum(
cx,
builder,
@@ -129,7 +131,7 @@ fn serialize_body(
variants,
&item.attrs)
}
item::Body::Struct(item::Style::Struct, ref fields) => {
Body::Struct(Style::Struct, ref fields) => {
if fields.iter().any(|field| field.ident.is_none()) {
cx.span_bug(item.span, "struct has unnamed fields")
}
@@ -142,7 +144,7 @@ fn serialize_body(
fields,
&item.attrs)
}
item::Body::Struct(item::Style::Tuple, ref fields) => {
Body::Struct(Style::Tuple, ref fields) => {
if fields.iter().any(|field| field.ident.is_some()) {
cx.span_bug(item.span, "tuple struct has named fields")
}
@@ -155,7 +157,7 @@ fn serialize_body(
fields,
&item.attrs)
}
item::Body::Struct(item::Style::Newtype, ref fields) => {
Body::Struct(Style::Newtype, ref fields) => {
serialize_newtype_struct(
cx,
builder,
@@ -164,7 +166,7 @@ fn serialize_body(
&fields[0],
&item.attrs)
}
item::Body::Struct(item::Style::Unit, _) => {
Body::Struct(Style::Unit, _) => {
serialize_unit_struct(
cx,
builder,
@@ -190,7 +192,7 @@ fn serialize_newtype_struct(
builder: &aster::AstBuilder,
impl_generics: &ast::Generics,
item_ty: P<ast::Ty>,
field: &item::Field,
field: &Field,
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let type_name = name_expr(builder, item_attrs.name());
@@ -211,33 +213,26 @@ fn serialize_tuple_struct(
builder: &aster::AstBuilder,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[item::Field],
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
let serialize_stmts = serialize_tuple_struct_visitor(
cx,
builder,
ty.clone(),
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
builder.id("serialize_tuple_struct_elt"),
fields,
impl_generics,
false,
cx.ident_of("serialize_tuple_struct_elt"),
);
let type_name = name_expr(builder, item_attrs.name());
let len = serialize_stmts.len();
quote_expr!(cx, {
$visitor_struct
$visitor_impl
_serializer.serialize_tuple_struct($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$ty>,
})
let mut state = try!(_serializer.serialize_tuple_struct($type_name, $len));
$serialize_stmts
_serializer.serialize_tuple_struct_end(state)
})
}
@@ -246,33 +241,37 @@ fn serialize_struct(
builder: &aster::AstBuilder,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[item::Field],
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
let serialize_fields = serialize_struct_visitor(
cx,
builder,
ty.clone(),
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
builder.id("serialize_struct_elt"),
fields,
impl_generics,
false,
cx.ident_of("serialize_struct_elt"),
);
let type_name = name_expr(builder, item_attrs.name());
let len = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let ident = field.ident.expect("struct has unnamed fields");
let field_expr = quote_expr!(cx, &self.$ident);
match field.attrs.skip_serializing_if() {
Some(path) => quote_expr!(cx, if $path($field_expr) { 0 } else { 1 }),
None => quote_expr!(cx, 1),
}
})
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
quote_expr!(cx, {
$visitor_struct
$visitor_impl
_serializer.serialize_struct($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$ty>,
})
let mut state = try!(_serializer.serialize_struct($type_name, $len));
$serialize_fields
_serializer.serialize_struct_end(state)
})
}
@@ -282,7 +281,7 @@ fn serialize_item_enum(
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
variants: &[item::Variant],
variants: &[Variant],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let arms: Vec<_> =
@@ -315,7 +314,7 @@ fn serialize_variant(
type_ident: Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
variant: &item::Variant,
variant: &Variant,
variant_index: usize,
item_attrs: &attr::Item,
) -> ast::Arm {
@@ -325,7 +324,7 @@ fn serialize_variant(
let variant_name = name_expr(builder, variant.attrs.name());
match variant.style {
item::Style::Unit => {
Style::Unit => {
quote_arm!(cx,
$type_ident::$variant_ident => {
_serde::ser::Serializer::serialize_unit_variant(
@@ -337,7 +336,7 @@ fn serialize_variant(
}
)
},
item::Style::Newtype => {
Style::Newtype => {
let expr = serialize_newtype_variant(
cx,
builder,
@@ -353,7 +352,7 @@ fn serialize_variant(
$type_ident::$variant_ident(ref __simple_value) => { $expr }
)
},
item::Style::Tuple => {
Style::Tuple => {
let field_names: Vec<ast::Ident> = (0 .. variant.fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
@@ -375,35 +374,26 @@ fn serialize_variant(
generics,
ty,
&variant.fields,
field_names,
);
quote_arm!(cx,
$pat => { $expr }
)
}
item::Style::Struct => {
let field_names: Vec<_> = (0 .. variant.fields.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
let pat = builder.pat().struct_()
.id(type_ident).id(variant_ident).build()
.with_pats(
field_names.iter()
.zip(variant.fields.iter())
.map(|(id, field)| {
let name = match field.ident {
Some(name) => name,
None => {
cx.span_bug(field.span, "struct variant has unnamed fields")
}
};
(name, builder.pat().ref_id(id))
})
)
.build();
Style::Struct => {
let mut pat = builder.pat().struct_().id(type_ident).id(variant_ident).build();
for field in variant.fields.iter() {
let name = match field.ident {
Some(name) => name,
None => cx.span_bug(field.span, "struct variant has unnamed fields"),
};
pat = pat.with_field_pat(ast::FieldPat {
ident: name,
pat: builder.pat().ref_id(name),
is_shorthand: true,
});
}
let pat = pat.build();
let expr = serialize_struct_variant(
cx,
@@ -413,7 +403,6 @@ fn serialize_variant(
generics,
ty,
&variant.fields,
field_names,
item_attrs,
);
@@ -432,7 +421,7 @@ fn serialize_newtype_variant(
variant_name: P<ast::Expr>,
item_ty: P<ast::Ty>,
generics: &ast::Generics,
field: &item::Field,
field: &Field,
) -> P<ast::Expr> {
let mut field_expr = quote_expr!(cx, __simple_value);
if let Some(path) = field.attrs.serialize_with() {
@@ -459,47 +448,24 @@ fn serialize_tuple_variant(
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
fields: &[item::Field],
field_names: Vec<Ident>,
fields: &[Field],
) -> P<ast::Expr> {
let variant_ty = builder.ty().tuple()
.with_tys(
fields.iter().map(|field| {
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(field.ty.clone())
})
)
.build();
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
let serialize_stmts = serialize_tuple_struct_visitor(
cx,
builder,
structure_ty.clone(),
variant_ty,
builder.id("serialize_tuple_variant_elt"),
structure_ty,
fields,
generics,
true,
cx.ident_of("serialize_tuple_variant_elt"),
);
let value_expr = builder.expr().tuple()
.with_exprs(
field_names.iter().map(|field| {
builder.expr().id(field)
})
)
.build();
let len = serialize_stmts.len();
quote_expr!(cx, {
$visitor_struct
$visitor_impl
_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
})
let mut state = try!(_serializer.serialize_tuple_variant($type_name, $variant_index, $variant_name, $len));
$serialize_stmts
_serializer.serialize_tuple_variant_end(state)
})
}
@@ -510,84 +476,43 @@ fn serialize_struct_variant(
variant_name: P<ast::Expr>,
generics: &ast::Generics,
ty: P<ast::Ty>,
fields: &[item::Field],
field_names: Vec<Ident>,
fields: &[Field],
item_attrs: &attr::Item,
) -> P<ast::Expr> {
let variant_generics = builder.generics()
.with(generics.clone())
.add_lifetime_bound("'__serde_variant")
.lifetime_name("'__serde_variant")
.build();
let variant_struct = builder.item().struct_("__VariantStruct")
.with_generics(variant_generics.clone())
.with_fields(
fields.iter().map(|field| {
builder.struct_field(field.ident.expect("struct has unnamed fields"))
.ty()
.ref_()
.lifetime("'__serde_variant")
.build_ty(field.ty.clone())
})
)
.field("__serde_container_ty")
.ty().phantom_data().build(ty.clone())
.build();
let variant_expr = builder.expr().struct_id("__VariantStruct")
.with_id_exprs(
fields.iter()
.zip(field_names.iter())
.map(|(field, field_name)| {
(
field.ident.expect("struct has unnamed fields"),
builder.expr().id(field_name),
)
})
)
.field("__serde_container_ty").path()
.global()
.id("std").id("marker")
.segment("PhantomData")
.with_ty(ty.clone())
.build()
.build()
.build();
let variant_ty = builder.ty().path()
.segment("__VariantStruct")
.with_generics(variant_generics.clone())
.build()
.build();
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
let serialize_fields = serialize_struct_visitor(
cx,
builder,
variant_ty.clone(),
variant_ty.clone(),
builder.id("serialize_struct_variant_elt"),
ty.clone(),
fields,
&variant_generics,
&generics,
true,
cx.ident_of("serialize_struct_variant_elt"),
);
let item_name = name_expr(builder, item_attrs.name());
let len = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let ident = field.ident.expect("struct has unnamed fields");
let field_expr = quote_expr!(cx, $ident);
match field.attrs.skip_serializing_if() {
Some(path) => quote_expr!(cx, if $path($field_expr) { 0 } else { 1 }),
None => quote_expr!(cx, 1),
}
})
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
quote_expr!(cx, {
$variant_struct
$visitor_struct
$visitor_impl
_serializer.serialize_struct_variant(
let mut state = try!(_serializer.serialize_struct_variant(
$item_name,
$variant_index,
$variant_name,
Visitor {
value: $variant_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
},
)
$len,
));
$serialize_fields
_serializer.serialize_struct_variant_end(state)
})
}
@@ -595,187 +520,75 @@ fn serialize_tuple_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
serializer_method: ast::Ident,
fields: &[item::Field],
fields: &[Field],
generics: &ast::Generics,
is_enum: bool,
) -> (P<ast::Item>, P<ast::Item>) {
let arms: Vec<_> = fields.iter()
func: ast::Ident,
) -> Vec<ast::Stmt> {
fields.iter()
.enumerate()
.map(|(i, field)| {
let mut field_expr = builder.expr().tup_field(i).field("value").self_();
if !is_enum {
field_expr = quote_expr!(cx, &$field_expr);
}
let mut field_expr = if is_enum {
builder.expr().path().id(format!("__field{}", i)).build()
} else {
builder.expr().ref_().tup_field(i).self_()
};
let continue_if_skip = field.attrs.skip_serializing_if()
.map(|path| quote_stmt!(cx, if $path($field_expr) { continue }));
let skip = field.attrs.skip_serializing_if()
.map(|path| quote_expr!(cx, $path($field_expr)))
.unwrap_or(quote_expr!(cx, false));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr);
}
quote_arm!(cx,
$i => {
self.state += 1;
$continue_if_skip
Ok(Some(try!(_serializer.$serializer_method($field_expr))))
quote_stmt!(cx,
if !$skip {
try!(_serializer.$func(&mut state, $field_expr));
}
)
).unwrap()
})
.collect();
let visitor_impl_generics = builder.from_generics(generics.clone())
.add_lifetime_bound("'__a")
.lifetime_name("'__a")
.build();
let where_clause = &visitor_impl_generics.where_clause;
let visitor_generics = builder.from_generics(visitor_impl_generics.clone())
.strip_bounds()
.build();
let nfields = fields.len();
(
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $variant_ty,
_structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>,
}
).unwrap(),
quote_item!(cx,
impl $visitor_impl_generics _serde::ser::SeqVisitor
for Visitor $visitor_generics
$where_clause {
#[inline]
fn visit<__S>(&mut self, _serializer: &mut __S) -> ::std::result::Result<Option<()>, __S::Error>
where __S: _serde::ser::Serializer
{
match self.state {
$arms
_ => Ok(None)
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some($nfields)
}
}
).unwrap(),
)
.collect()
}
fn serialize_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
serializer_method: ast::Ident,
fields: &[item::Field],
fields: &[Field],
generics: &ast::Generics,
is_enum: bool,
) -> (P<ast::Item>, P<ast::Item>) {
let arms: Vec<ast::Arm> = fields.iter()
func: ast::Ident,
) -> Vec<ast::Stmt> {
fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.enumerate()
.map(|(i, field)| {
.map(|field| {
let ident = field.ident.expect("struct has unnamed field");
let mut field_expr = quote_expr!(cx, self.value.$ident);
if !is_enum {
field_expr = quote_expr!(cx, &$field_expr);
}
let mut field_expr = if is_enum {
quote_expr!(cx, $ident)
} else {
quote_expr!(cx, &self.$ident)
};
let key_expr = name_expr(builder, field.attrs.name());
let continue_if_skip = field.attrs.skip_serializing_if()
.map(|path| quote_stmt!(cx, if $path($field_expr) { continue }));
let skip = field.attrs.skip_serializing_if()
.map(|path| quote_expr!(cx, $path($field_expr)))
.unwrap_or(quote_expr!(cx, false));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_with(cx, builder,
&structure_ty, generics, &field.ty, path, field_expr)
}
let expr = quote_expr!(cx,
_serializer.$serializer_method($key_expr, $field_expr)
);
quote_arm!(cx,
$i => {
self.state += 1;
$continue_if_skip
return Ok(Some(try!($expr)));
quote_stmt!(cx,
if !$skip {
try!(_serializer.$func(&mut state, $key_expr, $field_expr));
}
)
).unwrap()
})
.collect();
let visitor_impl_generics = builder.from_generics(generics.clone())
.add_lifetime_bound("'__a")
.lifetime_name("'__a")
.build();
let where_clause = &visitor_impl_generics.where_clause;
let visitor_generics = builder.from_generics(visitor_impl_generics.clone())
.strip_bounds()
.build();
let len = fields.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(|field| {
let ident = field.ident.expect("struct has unnamed fields");
let mut field_expr = quote_expr!(cx, self.value.$ident);
if !is_enum {
field_expr = quote_expr!(cx, &$field_expr);
}
match field.attrs.skip_serializing_if() {
Some(path) => quote_expr!(cx, if $path($field_expr) { 0 } else { 1 }),
None => quote_expr!(cx, 1),
}
})
.fold(quote_expr!(cx, 0), |sum, expr| quote_expr!(cx, $sum + $expr));
(
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $variant_ty,
_structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>,
}
).unwrap(),
quote_item!(cx,
impl $visitor_impl_generics
_serde::ser::MapVisitor
for Visitor $visitor_generics
$where_clause {
#[inline]
fn visit<__S>(&mut self, _serializer: &mut __S) -> ::std::result::Result<Option<()>, __S::Error>
where __S: _serde::ser::Serializer,
{
loop {
match self.state {
$arms
_ => { return Ok(None); }
}
}
}
#[inline]
fn len(&self) -> Option<usize> {
Some($len)
}
}
).unwrap(),
)
.collect()
}
fn wrap_serialize_with(
+43
View File
@@ -0,0 +1,43 @@
use syntax::ast;
use syntax::codemap::{self, ExpnId, Span};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::fold::{self, Folder};
use syntax::parse::token::intern;
use syntax::ptr::P;
pub fn record_expansion(
cx: &ExtCtxt,
item: P<ast::Item>,
derive: &str,
) -> Annotatable {
let info = codemap::ExpnInfo {
call_site: codemap::DUMMY_SP,
callee: codemap::NameAndSpan {
format: codemap::MacroAttribute(intern(&format!("derive({})", derive))),
span: None,
allow_internal_unstable: false,
},
};
let expn_id = cx.codemap().record_expansion(info);
let mut respanner = Respanner { expn_id: expn_id };
let item = item.map(|item| respanner.fold_item_simple(item));
Annotatable::Item(item)
}
struct Respanner {
expn_id: ExpnId,
}
impl Folder for Respanner {
fn new_span(&mut self, span: Span) -> Span {
Span {
expn_id: self.expn_id,
.. span
}
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
@@ -1,6 +1,6 @@
[package]
name = "serde_item"
version = "0.2.0"
name = "serde_codegen_internals"
version = "0.5.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable."
@@ -11,9 +11,10 @@ include = ["Cargo.toml", "src/**/*.rs"]
[features]
default = ["with-syntex"]
nightly-testing = ["clippy"]
with-syntex = ["syntex_syntax"]
unstable-testing = ["clippy"]
with-syntex = ["syntex_syntax", "syntex_errors"]
[dependencies]
clippy = { version = "^0.*", optional = true }
syntex_syntax = { version = "^0.36.0", optional = true }
syntex_syntax = { version = "^0.39.0", optional = true }
syntex_errors = { version = "^0.39.0", optional = true }
@@ -1,24 +1,10 @@
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#[cfg(feature = "with-syntex")]
#[macro_use]
extern crate syntex_syntax as syntax;
#[cfg(not(feature = "with-syntex"))]
#[macro_use]
extern crate syntax;
use syntax::ast;
use syntax::codemap;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
pub mod attr;
mod error;
pub use error::Error;
use attr;
use Error;
pub struct Item<'a> {
pub ident: ast::Ident,
@@ -1,7 +1,7 @@
use std::rc::Rc;
use syntax::ast::{self, TokenTree};
use syntax::attr;
use syntax::ast;
use syntax::attr::{self, HasAttrs};
use syntax::codemap::{Span, Spanned, respan};
use syntax::ext::base::ExtCtxt;
use syntax::fold::Folder;
@@ -10,6 +10,7 @@ use syntax::parse::token::{self, InternedString};
use syntax::parse;
use syntax::print::pprust::{lit_to_string, meta_item_to_string};
use syntax::ptr::P;
use syntax::tokenstream::{self, TokenTree};
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
@@ -529,7 +530,7 @@ impl<'a, 'b> Folder for Respanner<'a, 'b> {
TokenTree::Delimited(span, ref delimed) => {
TokenTree::Delimited(
self.new_span(span),
Rc::new(ast::Delimited {
Rc::new(tokenstream::Delimited {
delim: delimed.delim,
open_span: delimed.open_span,
tts: self.fold_tts(&delimed.tts),
@@ -540,7 +541,7 @@ impl<'a, 'b> Folder for Respanner<'a, 'b> {
TokenTree::Sequence(span, ref seq) => {
TokenTree::Sequence(
self.new_span(span),
Rc::new(ast::SequenceRepetition {
Rc::new(tokenstream::SequenceRepetition {
tts: self.fold_tts(&seq.tts),
separator: seq.separator.clone().map(|tok| self.fold_token(tok)),
..**seq
+21
View File
@@ -0,0 +1,21 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#[cfg(feature = "with-syntex")]
#[macro_use]
extern crate syntex_syntax as syntax;
#[cfg(feature = "with-syntex")]
extern crate syntex_errors as errors;
#[cfg(not(feature = "with-syntex"))]
#[macro_use]
extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc_errors as errors;
pub mod ast;
pub mod attr;
mod error;
pub use error::Error;
+6 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_macros"
version = "0.7.11"
version = "0.8.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
@@ -14,17 +14,19 @@ name = "serde_macros"
plugin = true
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
unstable-testing = ["clippy", "serde/unstable-testing", "serde_codegen/unstable-testing"]
[dependencies]
clippy = { version = "^0.*", optional = true }
serde_codegen = { version = "^0.7.11", path = "../serde_codegen", default-features = false, features = ["nightly"] }
serde_codegen = { version = "0.8.0", default-features = false, features = ["unstable"] }
[dev-dependencies]
clippy = "^0.*"
compiletest_rs = "^0.2.0"
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = { version = "^0.7.11", path = "../serde" }
serde = "0.8.0"
serde_test = "0.8.0"
[[test]]
name = "test"
+1 -1
View File
@@ -6,4 +6,4 @@ extern crate rustc_serialize;
extern crate serde;
extern crate test;
include!("../../serde_tests/benches/bench.rs.in");
include!("../../testing/benches/bench.rs.in");
+6 -1
View File
@@ -20,6 +20,11 @@ fn run_mode(mode: &'static str) {
}
#[test]
fn compile_test() {
fn compile_fail() {
run_mode("compile-fail");
}
#[test]
fn run_pass() {
run_mode("run-pass");
}
@@ -0,0 +1,12 @@
#![feature(custom_derive, plugin)]
#![plugin(serde_macros, clippy)]
#![deny(identity_op)]
// The derived implementation uses 0+1 to add up the number of fields
// serialized, which Clippy warns about. If the expansion info is registered
// correctly, the Clippy lint is not triggered.
#[derive(Serialize)]
struct A { b: u8 }
fn main() {}
+1 -2
View File
@@ -1,9 +1,8 @@
#![feature(test, custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate test;
include!("../../serde_tests/tests/test.rs.in");
include!("../../testing/tests/test.rs.in");
mod compile_tests;
+14
View File
@@ -0,0 +1,14 @@
[package]
name = "serde_test"
version = "0.8.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[dependencies]
serde = "0.8.0"
+54
View File
@@ -0,0 +1,54 @@
use serde::{Serialize, Deserialize};
use de::Deserializer;
use error::Error;
use ser::Serializer;
use token::Token;
use std::fmt::Debug;
pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Serialize + Deserialize + PartialEq + Debug,
{
assert_ser_tokens(value, tokens);
assert_de_tokens(value, tokens);
}
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where T: Serialize,
{
let mut ser = Serializer::new(tokens.iter());
assert_eq!(Serialize::serialize(value, &mut ser), Ok(()));
assert_eq!(ser.next_token(), None);
}
/// Expect an error serializing `T`.
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error)
where T: Serialize + PartialEq + Debug,
{
let mut ser = Serializer::new(tokens.iter());
let v: Result<(), Error> = Serialize::serialize(value, &mut ser);
assert_eq!(v.as_ref(), Err(&error));
assert_eq!(ser.next_token(), None);
}
pub fn assert_de_tokens<T>(value: &T, tokens: &[Token<'static>])
where T: Deserialize + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v.as_ref(), Ok(value));
assert_eq!(de.next_token(), None);
}
/// Expect an error deserializing tokens into a `T`.
pub fn assert_de_tokens_error<T>(tokens: &[Token<'static>], error: Error)
where T: Deserialize + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens.to_vec().into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v, Err(error));
// There may be one token left if a peek caused the error
de.next_token();
assert_eq!(de.next_token(), None);
}
File diff suppressed because it is too large Load Diff
+87
View File
@@ -0,0 +1,87 @@
use std::{error, fmt};
use serde::{ser, de};
use token::Token;
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
// Shared
Custom(String),
InvalidValue(String),
// De
EndOfStream,
InvalidType(de::Type),
InvalidLength(usize),
UnknownVariant(String),
UnknownField(String),
MissingField(&'static str),
DuplicateField(&'static str),
InvalidName(&'static str),
UnexpectedToken(Token<'static>),
}
impl ser::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
}
}
impl de::Error for Error {
fn custom<T: Into<String>>(msg: T) -> Error {
Error::Custom(msg.into())
}
fn end_of_stream() -> Error {
Error::EndOfStream
}
fn invalid_type(ty: de::Type) -> Error {
Error::InvalidType(ty)
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
}
fn invalid_length(len: usize) -> Error {
Error::InvalidLength(len)
}
fn unknown_variant(variant: &str) -> Error {
Error::UnknownVariant(variant.to_owned())
}
fn unknown_field(field: &str) -> Error {
Error::UnknownField(field.to_owned())
}
fn missing_field(field: &'static str) -> Error {
Error::MissingField(field)
}
fn duplicate_field(field: &'static str) -> Error {
Error::DuplicateField(field)
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
+22
View File
@@ -0,0 +1,22 @@
extern crate serde;
mod assert;
pub use assert::{
assert_tokens,
assert_ser_tokens,
assert_ser_tokens_error,
assert_de_tokens,
assert_de_tokens_error,
};
mod ser;
pub use ser::Serializer;
mod de;
pub use de::Deserializer;
mod token;
pub use token::Token;
mod error;
pub use error::Error;
+323
View File
@@ -0,0 +1,323 @@
use std::marker::PhantomData;
use serde::ser::{
self,
Serialize,
};
use error::Error;
use token::Token;
pub struct Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
tokens: I,
phantom: PhantomData<&'a Token<'a>>,
}
impl<'a, I> Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
pub fn new(tokens: I) -> Serializer<'a, I> {
Serializer {
tokens: tokens,
phantom: PhantomData,
}
}
pub fn next_token(&mut self) -> Option<&'a Token<'a>> {
self.tokens.next()
}
}
impl<'a, I> ser::Serializer for Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Error = Error;
type MapState = ();
type SeqState = ();
type TupleState = ();
type TupleStructState = ();
type TupleVariantState = ();
type StructState = ();
type StructVariantState = ();
fn serialize_unit(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
Ok(())
}
fn serialize_newtype_variant<T>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
value.serialize(self)
}
fn serialize_unit_struct(&mut self, name: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
Ok(())
}
fn serialize_unit_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
Ok(())
}
fn serialize_bool(&mut self, v: bool) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
Ok(())
}
fn serialize_isize(&mut self, v: isize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Isize(v)));
Ok(())
}
fn serialize_i8(&mut self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
Ok(())
}
fn serialize_i16(&mut self, v: i16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
Ok(())
}
fn serialize_i32(&mut self, v: i32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
Ok(())
}
fn serialize_i64(&mut self, v: i64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
Ok(())
}
fn serialize_usize(&mut self, v: usize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Usize(v)));
Ok(())
}
fn serialize_u8(&mut self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
Ok(())
}
fn serialize_u16(&mut self, v: u16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
Ok(())
}
fn serialize_u32(&mut self, v: u32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
Ok(())
}
fn serialize_u64(&mut self, v: u64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
Ok(())
}
fn serialize_f32(&mut self, v: f32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
Ok(())
}
fn serialize_f64(&mut self, v: f64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
Ok(())
}
fn serialize_char(&mut self, v: char) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
Ok(())
}
fn serialize_str(&mut self, v: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
Ok(())
}
fn serialize_none(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
Ok(())
}
fn serialize_some<V>(&mut self, value: V) -> Result<(), Error>
where V: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
}
fn serialize_seq<'b>(&'b mut self, len: Option<usize>) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
Ok(())
}
fn serialize_seq_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(self)
}
fn serialize_seq_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
fn serialize_seq_fixed_size(&mut self, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
Ok(())
}
fn serialize_tuple(&mut self, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
Ok(())
}
fn serialize_tuple_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(self)
}
fn serialize_tuple_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
Ok(())
}
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
value.serialize(self)
}
fn serialize_tuple_struct(&mut self, name: &'static str, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructStart(name, len)));
Ok(())
}
fn serialize_tuple_struct_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(self)
}
fn serialize_tuple_struct_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(())
}
fn serialize_tuple_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len)));
Ok(())
}
fn serialize_tuple_variant_elt<T>(&mut self, _: &mut (), value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(self)
}
fn serialize_tuple_variant_end(&mut self, _: ()) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
}
fn serialize_map(&mut self, len: Option<usize>) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
Ok(())
}
fn serialize_map_key<T>(&mut self, _: &mut (), key: T) -> Result<(), Self::Error> where T: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
key.serialize(self)
}
fn serialize_map_value<T>(&mut self, _: &mut (), value: T) -> Result<(), Self::Error> where T: Serialize {
value.serialize(self)
}
fn serialize_map_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
fn serialize_struct(&mut self, name: &str, len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
Ok(())
}
fn serialize_struct_elt<V>(&mut self, _: &mut (), key: &'static str, value: V) -> Result<(), Self::Error> where V: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
Ok(())
}
fn serialize_struct_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
len: usize) -> Result<(), Error>
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len)));
Ok(())
}
fn serialize_struct_variant_elt<V>(&mut self, _: &mut (), key: &'static str, value: V) -> Result<(), Self::Error> where V: Serialize {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_variant_end(&mut self, _: ()) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
fn serialize_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
let mut state = try!(self.serialize_seq(Some(value.len())));
for c in value {
try!(self.serialize_seq_elt(&mut state, c));
}
self.serialize_seq_end(state)
}
}
+60
View File
@@ -0,0 +1,60 @@
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
Bool(bool),
Isize(isize),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
Usize(usize),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
Char(char),
Str(&'a str),
String(String),
Bytes(&'a [u8]),
Option(bool),
Unit,
UnitStruct(&'a str),
StructNewType(&'a str),
EnumStart(&'a str),
EnumUnit(&'a str, &'a str),
EnumNewType(&'a str, &'a str),
SeqStart(Option<usize>),
SeqArrayStart(usize),
SeqSep,
SeqEnd,
TupleStart(usize),
TupleSep,
TupleEnd,
TupleStructStart(&'a str, usize),
TupleStructSep,
TupleStructEnd,
MapStart(Option<usize>),
MapSep,
MapEnd,
StructStart(&'a str, usize),
StructSep,
StructEnd,
EnumSeqStart(&'a str, &'a str, usize),
EnumSeqSep,
EnumSeqEnd,
EnumMapStart(&'a str, &'a str, usize),
EnumMapSep,
EnumMapEnd,
}
-4
View File
@@ -1,4 +0,0 @@
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
-185
View File
@@ -1,185 +0,0 @@
use std::fmt;
use std::error;
extern crate serde;
use self::serde::Serialize;
use self::serde::bytes::{ByteBuf, Bytes};
///////////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq)]
struct Error;
impl serde::ser::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
}
impl serde::de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
fn end_of_stream() -> Error { Error }
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
///////////////////////////////////////////////////////////////////////////////
struct BytesSerializer {
bytes: Vec<u8>,
}
impl BytesSerializer {
fn new(bytes: Vec<u8>) -> Self {
BytesSerializer {
bytes: bytes,
}
}
}
impl serde::Serializer for BytesSerializer {
type Error = Error;
fn serialize_unit(&mut self) -> Result<(), Error> {
Err(Error)
}
fn serialize_bool(&mut self, _v: bool) -> Result<(), Error> {
Err(Error)
}
fn serialize_i64(&mut self, _v: i64) -> Result<(), Error> {
Err(Error)
}
fn serialize_u64(&mut self, _v: u64) -> Result<(), Error> {
Err(Error)
}
fn serialize_f32(&mut self, _v: f32) -> Result<(), Error> {
Err(Error)
}
fn serialize_f64(&mut self, _v: f64) -> Result<(), Error> {
Err(Error)
}
fn serialize_char(&mut self, _v: char) -> Result<(), Error> {
Err(Error)
}
fn serialize_str(&mut self, _v: &str) -> Result<(), Error> {
Err(Error)
}
fn serialize_none(&mut self) -> Result<(), Error> {
Err(Error)
}
fn serialize_some<V>(&mut self, _value: V) -> Result<(), Error>
where V: serde::Serialize,
{
Err(Error)
}
fn serialize_seq<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::SeqVisitor,
{
Err(Error)
}
fn serialize_seq_elt<T>(&mut self, _value: T) -> Result<(), Error>
where T: serde::Serialize
{
Err(Error)
}
fn serialize_map<V>(&mut self, _visitor: V) -> Result<(), Error>
where V: serde::ser::MapVisitor,
{
Err(Error)
}
fn serialize_map_elt<K, V>(&mut self, _key: K, _value: V) -> Result<(), Error>
where K: serde::Serialize,
V: serde::Serialize,
{
Err(Error)
}
fn serialize_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
assert_eq!(self.bytes, bytes);
Ok(())
}
}
///////////////////////////////////////////////////////////////////////////////
struct BytesDeserializer {
bytes: Option<Vec<u8>>,
}
impl BytesDeserializer {
fn new(bytes: Vec<u8>) -> Self {
BytesDeserializer {
bytes: Some(bytes),
}
}
}
impl serde::Deserializer for BytesDeserializer {
type Error = Error;
fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
{
Err(Error)
}
fn deserialize_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: serde::de::Visitor,
{
visitor.visit_byte_buf(self.bytes.take().unwrap())
}
}
///////////////////////////////////////////////////////////////////////////////
#[test]
fn test_bytes_ser_bytes() {
let buf = vec![];
let bytes = Bytes::from(&buf);
let mut ser = BytesSerializer::new(vec![]);
bytes.serialize(&mut ser).unwrap();
let buf = vec![1, 2, 3];
let bytes = Bytes::from(&buf);
let mut ser = BytesSerializer::new(vec![1, 2, 3]);
bytes.serialize(&mut ser).unwrap();
}
///////////////////////////////////////////////////////////////////////////////
#[test]
fn test_byte_buf_de_bytes() {
let mut de = BytesDeserializer::new(vec![]);
let bytes = serde::Deserialize::deserialize(&mut de);
assert_eq!(bytes, Ok(ByteBuf::new()));
let mut de = BytesDeserializer::new(vec![1, 2, 3]);
let bytes = serde::Deserialize::deserialize(&mut de);
assert_eq!(bytes, Ok(ByteBuf::from(vec![1, 2, 3])));
}
-134
View File
@@ -1,134 +0,0 @@
// These just test that serde_codegen is able to produce code that compiles
// successfully when there are a variety of generics and non-(de)serializable
// types involved.
extern crate serde;
use self::serde::ser::{Serialize, Serializer};
use self::serde::de::{Deserialize, Deserializer};
//////////////////////////////////////////////////////////////////////////
#[derive(Serialize, Deserialize)]
struct With<T> {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X,
}
#[derive(Serialize, Deserialize)]
struct WithRef<'a, T: 'a> {
#[serde(skip_deserializing)]
t: Option<&'a T>,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X,
}
#[derive(Serialize, Deserialize)]
struct Bounds<T: Serialize + Deserialize> {
t: T,
option: Option<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
}
#[derive(Serialize, Deserialize)]
struct NoBounds<T> {
t: T,
option: Option<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
}
#[derive(Serialize, Deserialize)]
enum EnumWith<T> {
Unit,
Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X),
Tuple(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X),
Struct {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X },
}
#[derive(Serialize)]
struct MultipleRef<'a, 'b, 'c, T> where T: 'c, 'c: 'b, 'b: 'a {
t: T,
rrrt: &'a &'b &'c T,
}
#[derive(Serialize, Deserialize)]
struct Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
);
#[derive(Serialize, Deserialize)]
struct Tuple<T>(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X,
);
#[derive(Serialize, Deserialize)]
enum TreeNode<D> {
Split {
left: Box<TreeNode<D>>,
right: Box<TreeNode<D>>,
},
Leaf {
data: D,
},
}
#[derive(Serialize, Deserialize)]
struct ListNode<D> {
data: D,
next: Box<ListNode<D>>,
}
#[derive(Serialize, Deserialize)]
#[serde(bound="D: SerializeWith + DeserializeWith")]
struct WithTraits1<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with",
bound="E: SerializeWith + DeserializeWith")]
e: E,
}
#[derive(Serialize, Deserialize)]
#[serde(bound(serialize="D: SerializeWith",
deserialize="D: DeserializeWith"))]
struct WithTraits2<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
bound(serialize="E: SerializeWith"))]
#[serde(deserialize_with="DeserializeWith::deserialize_with",
bound(deserialize="E: DeserializeWith"))]
e: E,
}
//////////////////////////////////////////////////////////////////////////
trait SerializeWith {
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> Result<(), S::Error>;
}
trait DeserializeWith: Sized {
fn deserialize_with<D: Deserializer>(_: &mut D) -> Result<Self, D::Error>;
}
// Implements neither Serialize nor Deserialize
struct X;
fn ser_x<S: Serializer>(_: &X, _: &mut S) -> Result<(), S::Error> { panic!() }
fn de_x<D: Deserializer>(_: &mut D) -> Result<X, D::Error> { panic!() }
@@ -1,6 +1,6 @@
[package]
name = "serde_tests"
version = "0.7.11"
name = "serde_testing"
version = "0.8.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -11,15 +11,16 @@ keywords = ["serialization"]
build = "build.rs"
[features]
nightly-testing = ["clippy", "serde/nightly-testing", "serde_codegen/nightly-testing"]
unstable-testing = ["clippy", "serde/unstable-testing", "serde_codegen/unstable-testing"]
[build-dependencies]
serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-syntex"] }
serde_codegen = { path = "../serde_codegen", features = ["with-syntex"] }
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = { version = "*", path = "../serde" }
serde = { path = "../serde" }
serde_test = { path = "../serde_test" }
[dependencies]
clippy = { version = "^0.*", optional = true }
@@ -1,6 +1,6 @@
#![feature(test)]
#![cfg_attr(feature = "nightly", feature(plugin))]
#![cfg_attr(feature = "nightly", plugin(clippy))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
extern crate rustc_serialize;
extern crate serde;
@@ -5,7 +5,7 @@ macro_rules! declare_ser_tests {
#[test]
fn $name() {
$(
::token::assert_ser_tokens(&$value, $tokens);
assert_ser_tokens(&$value, $tokens);
)+
}
)+
+4
View File
@@ -0,0 +1,4 @@
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
include!(concat!(env!("OUT_DIR"), "/test.rs"));
@@ -1,8 +1,8 @@
extern crate serde;
#[macro_use]
mod macros;
mod token;
mod test_annotations;
mod test_bytes;
mod test_de;
@@ -1,7 +1,8 @@
extern crate serde;
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
use token::{
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_tokens,
@@ -80,8 +81,8 @@ struct DefaultStruct<A, B, C, D, E>
fn test_default_struct() {
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
vec![
Token::StructStart("DefaultStruct", Some(3)),
&[
Token::StructStart("DefaultStruct", 3),
Token::StructSep,
Token::Str("a1"),
@@ -109,8 +110,8 @@ fn test_default_struct() {
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
vec![
Token::StructStart("DefaultStruct", Some(1)),
&[
Token::StructStart("DefaultStruct", 1),
Token::StructSep,
Token::Str("a1"),
@@ -143,8 +144,8 @@ enum DefaultEnum<A, B, C, D, E>
fn test_default_enum() {
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
vec![
Token::EnumMapStart("DefaultEnum", "Struct", Some(5)),
&[
Token::EnumMapStart("DefaultEnum", "Struct", 5),
Token::EnumMapSep,
Token::Str("a1"),
@@ -172,8 +173,8 @@ fn test_default_enum() {
assert_de_tokens(
&DefaultEnum::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123 },
vec![
Token::EnumMapStart("DefaultEnum", "Struct", Some(5)),
&[
Token::EnumMapStart("DefaultEnum", "Struct", 5),
Token::EnumMapSep,
Token::Str("a1"),
@@ -206,16 +207,16 @@ struct ContainsNoStdDefault<A: MyDefault> {
fn test_no_std_default() {
assert_de_tokens(
&ContainsNoStdDefault { a: NoStdDefault(123) },
vec![
Token::StructStart("ContainsNoStdDefault", Some(1)),
&[
Token::StructStart("ContainsNoStdDefault", 1),
Token::StructEnd,
]
);
assert_de_tokens(
&ContainsNoStdDefault { a: NoStdDefault(8) },
vec![
Token::StructStart("ContainsNoStdDefault", Some(1)),
&[
Token::StructStart("ContainsNoStdDefault", 1),
Token::StructSep,
Token::Str("a"),
@@ -279,8 +280,8 @@ fn test_elt_not_deserialize() {
c: NotDeserializeStruct(123),
e: NotDeserializeEnum::Trouble,
},
vec![
Token::StructStart("ContainsNotDeserialize", Some(3)),
&[
Token::StructStart("ContainsNotDeserialize", 3),
Token::StructEnd,
]
);
@@ -297,8 +298,8 @@ fn test_ignore_unknown() {
// 'Default' allows unknown. Basic smoke test of ignore...
assert_de_tokens(
&DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123 },
vec![
Token::StructStart("DefaultStruct", Some(5)),
&[
Token::StructStart("DefaultStruct", 5),
Token::StructSep,
Token::Str("whoops1"),
@@ -332,8 +333,8 @@ fn test_ignore_unknown() {
);
assert_de_tokens_error::<DenyUnknown>(
vec![
Token::StructStart("DenyUnknown", Some(2)),
&[
Token::StructStart("DenyUnknown", 2),
Token::StructSep,
Token::Str("a1"),
@@ -341,11 +342,8 @@ fn test_ignore_unknown() {
Token::StructSep,
Token::Str("whoops"),
Token::I32(2),
Token::StructEnd,
],
Error::UnknownFieldError("whoops".to_owned())
Error::UnknownField("whoops".to_owned())
);
}
@@ -369,8 +367,8 @@ struct RenameStructSerializeDeserialize {
fn test_rename_struct() {
assert_tokens(
&RenameStruct { a1: 1, a2: 2 },
vec![
Token::StructStart("Superhero", Some(2)),
&[
Token::StructStart("Superhero", 2),
Token::StructSep,
Token::Str("a1"),
@@ -387,7 +385,7 @@ fn test_rename_struct() {
assert_ser_tokens(
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
&[
Token::StructStart("SuperheroSer", Some(2)),
Token::StructStart("SuperheroSer", 2),
Token::StructSep,
Token::Str("a1"),
@@ -403,8 +401,8 @@ fn test_rename_struct() {
assert_de_tokens(
&RenameStructSerializeDeserialize { a1: 1, a2: 2 },
vec![
Token::StructStart("SuperheroDe", Some(2)),
&[
Token::StructStart("SuperheroDe", 2),
Token::StructSep,
Token::Str("a1"),
@@ -451,14 +449,14 @@ enum RenameEnumSerializeDeserialize<A> {
fn test_rename_enum() {
assert_tokens(
&RenameEnum::Batman,
vec![
&[
Token::EnumUnit("Superhero", "bruce_wayne"),
]
);
assert_tokens(
&RenameEnum::Superman(0),
vec![
&[
Token::EnumNewType("Superhero", "clark_kent"),
Token::I8(0),
]
@@ -466,8 +464,8 @@ fn test_rename_enum() {
assert_tokens(
&RenameEnum::WonderWoman(0, 1),
vec![
Token::EnumSeqStart("Superhero", "diana_prince", Some(2)),
&[
Token::EnumSeqStart("Superhero", "diana_prince", 2),
Token::EnumSeqSep,
Token::I8(0),
@@ -481,8 +479,8 @@ fn test_rename_enum() {
assert_tokens(
&RenameEnum::Flash { a: 1 },
vec![
Token::EnumMapStart("Superhero", "barry_allan", Some(1)),
&[
Token::EnumMapStart("Superhero", "barry_allan", 1),
Token::EnumMapSep,
Token::Str("b"),
@@ -498,7 +496,7 @@ fn test_rename_enum() {
b: String::new(),
},
&[
Token::EnumMapStart("SuperheroSer", "dick_grayson", Some(2)),
Token::EnumMapStart("SuperheroSer", "dick_grayson", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -517,8 +515,8 @@ fn test_rename_enum() {
a: 0,
b: String::new(),
},
vec![
Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)),
&[
Token::EnumMapStart("SuperheroDe", "jason_todd", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -552,7 +550,7 @@ fn test_skip_serializing_struct() {
c: 3,
},
&[
Token::StructStart("SkipSerializingStruct", Some(2)),
Token::StructStart("SkipSerializingStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -573,7 +571,7 @@ fn test_skip_serializing_struct() {
c: 123,
},
&[
Token::StructStart("SkipSerializingStruct", Some(1)),
Token::StructStart("SkipSerializingStruct", 1),
Token::StructSep,
Token::Str("a"),
@@ -605,7 +603,7 @@ fn test_skip_serializing_enum() {
c: 3,
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(2)),
Token::EnumMapStart("SkipSerializingEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -626,7 +624,7 @@ fn test_skip_serializing_enum() {
c: 123,
},
&[
Token::EnumMapStart("SkipSerializingEnum", "Struct", Some(1)),
Token::EnumMapStart("SkipSerializingEnum", "Struct", 1),
Token::EnumMapSep,
Token::Str("a"),
@@ -673,7 +671,7 @@ fn test_elt_not_serialize() {
d: NotSerializeEnum::Trouble,
},
&[
Token::StructStart("ContainsNotSerialize", Some(2)),
Token::StructStart("ContainsNotSerialize", 2),
Token::StructSep,
Token::Str("a"),
@@ -705,7 +703,7 @@ fn test_serialize_with_struct() {
b: 2,
},
&[
Token::StructStart("SerializeWithStruct", Some(2)),
Token::StructStart("SerializeWithStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -725,7 +723,7 @@ fn test_serialize_with_struct() {
b: 123,
},
&[
Token::StructStart("SerializeWithStruct", Some(2)),
Token::StructStart("SerializeWithStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -758,7 +756,7 @@ fn test_serialize_with_enum() {
b: 2,
},
&[
Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)),
Token::EnumMapStart("SerializeWithEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -778,7 +776,7 @@ fn test_serialize_with_enum() {
b: 123,
},
&[
Token::EnumMapStart("SerializeWithEnum", "Struct", Some(2)),
Token::EnumMapStart("SerializeWithEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -807,8 +805,8 @@ fn test_deserialize_with_struct() {
a: 1,
b: 2,
},
vec![
Token::StructStart("DeserializeWithStruct", Some(2)),
&[
Token::StructStart("DeserializeWithStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -827,8 +825,8 @@ fn test_deserialize_with_struct() {
a: 1,
b: 123,
},
vec![
Token::StructStart("DeserializeWithStruct", Some(2)),
&[
Token::StructStart("DeserializeWithStruct", 2),
Token::StructSep,
Token::Str("a"),
@@ -859,8 +857,8 @@ fn test_deserialize_with_enum() {
a: 1,
b: 2,
},
vec![
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
&[
Token::EnumMapStart("DeserializeWithEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -879,8 +877,8 @@ fn test_deserialize_with_enum() {
a: 1,
b: 123,
},
vec![
Token::EnumMapStart("DeserializeWithEnum", "Struct", Some(2)),
&[
Token::EnumMapStart("DeserializeWithEnum", "Struct", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -898,8 +896,8 @@ fn test_deserialize_with_enum() {
#[test]
fn test_missing_renamed_field_struct() {
assert_de_tokens_error::<RenameStruct>(
vec![
Token::StructStart("Superhero", Some(2)),
&[
Token::StructStart("Superhero", 2),
Token::StructSep,
Token::Str("a1"),
@@ -907,12 +905,12 @@ fn test_missing_renamed_field_struct() {
Token::StructEnd,
],
Error::MissingFieldError("a3"),
Error::MissingField("a3"),
);
assert_de_tokens_error::<RenameStructSerializeDeserialize>(
vec![
Token::StructStart("SuperheroDe", Some(2)),
&[
Token::StructStart("SuperheroDe", 2),
Token::StructSep,
Token::Str("a1"),
@@ -920,24 +918,24 @@ fn test_missing_renamed_field_struct() {
Token::StructEnd,
],
Error::MissingFieldError("a5"),
Error::MissingField("a5"),
);
}
#[test]
fn test_missing_renamed_field_enum() {
assert_de_tokens_error::<RenameEnum>(
vec![
Token::EnumMapStart("Superhero", "barry_allan", Some(1)),
&[
Token::EnumMapStart("Superhero", "barry_allan", 1),
Token::EnumMapEnd,
],
Error::MissingFieldError("b"),
Error::MissingField("b"),
);
assert_de_tokens_error::<RenameEnumSerializeDeserialize<i8>>(
vec![
Token::EnumMapStart("SuperheroDe", "jason_todd", Some(2)),
&[
Token::EnumMapStart("SuperheroDe", "jason_todd", 2),
Token::EnumMapSep,
Token::Str("a"),
@@ -945,6 +943,34 @@ fn test_missing_renamed_field_enum() {
Token::EnumMapEnd,
],
Error::MissingFieldError("d"),
Error::MissingField("d"),
);
}
#[derive(Debug, PartialEq, Deserialize)]
enum InvalidLengthEnum {
A(i32, i32, i32),
B(#[serde(skip_deserializing)] i32, i32, i32),
}
#[test]
fn test_invalid_length_enum() {
assert_de_tokens_error::<InvalidLengthEnum>(
&[
Token::EnumSeqStart("InvalidLengthEnum", "A", 3),
Token::EnumSeqSep,
Token::I32(1),
Token::EnumSeqEnd,
],
Error::InvalidLength(1),
);
assert_de_tokens_error::<InvalidLengthEnum>(
&[
Token::EnumSeqStart("InvalidLengthEnum", "B", 3),
Token::EnumSeqSep,
Token::I32(1),
Token::EnumSeqEnd,
],
Error::InvalidLength(1),
);
}
+460
View File
@@ -0,0 +1,460 @@
use std::fmt;
use std::error;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::bytes::{ByteBuf, Bytes};
use serde::ser;
use serde::de;
///////////////////////////////////////////////////////////////////////////////
#[derive(Debug, PartialEq)]
struct Error;
impl ser::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
}
impl de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error { Error }
fn end_of_stream() -> Error { Error }
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Deserialization Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}
///////////////////////////////////////////////////////////////////////////////
struct BytesSerializer {
bytes: Vec<u8>,
}
impl BytesSerializer {
fn new(bytes: Vec<u8>) -> Self {
BytesSerializer {
bytes: bytes,
}
}
}
impl Serializer for BytesSerializer {
type Error = Error;
type SeqState = ();
type MapState = ();
type TupleState = ();
type TupleStructState = ();
type TupleVariantState = ();
type StructState = ();
type StructVariantState = ();
fn serialize_unit(&mut self) -> Result<(), Error> {
Err(Error)
}
fn serialize_unit_struct(&mut self, _name: &'static str) -> Result<(), Error> {
Err(Error)
}
fn serialize_unit_variant(&mut self, _: &'static str, _: usize, _: &'static str) -> Result<(), Error> {
Err(Error)
}
fn serialize_bool(&mut self, _v: bool) -> Result<(), Error> {
Err(Error)
}
fn serialize_isize(&mut self, _v: isize) -> Result<(), Error> {
Err(Error)
}
fn serialize_usize(&mut self, _v: usize) -> Result<(), Error> {
Err(Error)
}
fn serialize_i8(&mut self, _v: i8) -> Result<(), Error> {
Err(Error)
}
fn serialize_u8(&mut self, _v: u8) -> Result<(), Error> {
Err(Error)
}
fn serialize_i16(&mut self, _v: i16) -> Result<(), Error> {
Err(Error)
}
fn serialize_u16(&mut self, _v: u16) -> Result<(), Error> {
Err(Error)
}
fn serialize_i32(&mut self, _v: i32) -> Result<(), Error> {
Err(Error)
}
fn serialize_u32(&mut self, _v: u32) -> Result<(), Error> {
Err(Error)
}
fn serialize_i64(&mut self, _v: i64) -> Result<(), Error> {
Err(Error)
}
fn serialize_u64(&mut self, _v: u64) -> Result<(), Error> {
Err(Error)
}
fn serialize_f32(&mut self, _v: f32) -> Result<(), Error> {
Err(Error)
}
fn serialize_f64(&mut self, _v: f64) -> Result<(), Error> {
Err(Error)
}
fn serialize_char(&mut self, _v: char) -> Result<(), Error> {
Err(Error)
}
fn serialize_str(&mut self, _v: &str) -> Result<(), Error> {
Err(Error)
}
fn serialize_none(&mut self) -> Result<(), Error> {
Err(Error)
}
fn serialize_some<V>(&mut self, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_newtype_struct<V>(&mut self, _: &'static str, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_newtype_variant<V>(&mut self, _: &'static str, _: usize, _: &'static str, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_seq(&mut self, _len: Option<usize>) -> Result<(), Error>
{
Err(Error)
}
fn serialize_seq_fixed_size(&mut self, _len: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_seq_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_seq_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple(&mut self, _len: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_tuple_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_struct(&mut self, _: &'static str, _len: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_struct_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_tuple_struct_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_variant(&mut self, _: &'static str, _: usize, _: &'static str, _len: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_tuple_variant_elt<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_tuple_variant_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_map(&mut self, _: Option<usize>) -> Result<(), Error>
{
Err(Error)
}
fn serialize_map_key<T>(&mut self, _: &mut (), _key: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_map_value<T>(&mut self, _: &mut (), _value: T) -> Result<(), Error>
where T: Serialize
{
Err(Error)
}
fn serialize_map_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_struct(&mut self, _: &'static str, _: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_struct_elt<V>(&mut self, _: &mut (), _key: &'static str, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_struct_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_struct_variant(&mut self, _: &'static str, _: usize, _: &'static str, _: usize) -> Result<(), Error>
{
Err(Error)
}
fn serialize_struct_variant_elt<V>(&mut self, _: &mut (), _key: &'static str, _value: V) -> Result<(), Error>
where V: Serialize,
{
Err(Error)
}
fn serialize_struct_variant_end(&mut self, _: ()) -> Result<(), Error>
{
Err(Error)
}
fn serialize_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
assert_eq!(self.bytes, bytes);
Ok(())
}
}
///////////////////////////////////////////////////////////////////////////////
struct BytesDeserializer {
bytes: Option<Vec<u8>>,
}
impl BytesDeserializer {
fn new(bytes: Vec<u8>) -> Self {
BytesDeserializer {
bytes: Some(bytes),
}
}
}
impl Deserializer for BytesDeserializer {
type Error = Error;
fn deserialize<V>(&mut self, _visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
Err(Error)
}
fn deserialize_bytes<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_byte_buf(self.bytes.take().unwrap())
}
fn deserialize_seq<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_struct_field<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_map<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_unit<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_ignored_any<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_string<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_str<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_char<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i16<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_i8<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u16<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_u8<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f32<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_f64<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_bool<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_usize<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_isize<__V>(&mut self, visitor: __V) -> Result<__V::Value, Self::Error>
where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_option<__V>(&mut self, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_seq_fixed_size<__V>(&mut self, _: usize, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_unit_struct<__V>(&mut self, _: &str, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_newtype_struct<__V>(&mut self, _: &str, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_tuple_struct<__V>(&mut self, _: &str, _: usize, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_struct<__V>(&mut self, _: &str, _: &[&str], visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_tuple<__V>(&mut self, _: usize, visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::Visitor {
self.deserialize(visitor)
}
fn deserialize_enum<__V>(&mut self, _: &str, _: &[&str], _visitor: __V)
-> Result<__V::Value, Self::Error> where __V: de::EnumVisitor {
Err(Error)
}
}
///////////////////////////////////////////////////////////////////////////////
#[test]
fn test_bytes_ser_bytes() {
let buf = vec![];
let bytes = Bytes::from(&buf);
let mut ser = BytesSerializer::new(vec![]);
bytes.serialize(&mut ser).unwrap();
let buf = vec![1, 2, 3];
let bytes = Bytes::from(&buf);
let mut ser = BytesSerializer::new(vec![1, 2, 3]);
bytes.serialize(&mut ser).unwrap();
}
///////////////////////////////////////////////////////////////////////////////
#[test]
fn test_byte_buf_de_bytes() {
let mut de = BytesDeserializer::new(vec![]);
let bytes = Deserialize::deserialize(&mut de);
assert_eq!(bytes, Ok(ByteBuf::new()));
let mut de = BytesDeserializer::new(vec![1, 2, 3]);
let bytes = Deserialize::deserialize(&mut de);
assert_eq!(bytes, Ok(ByteBuf::from(vec![1, 2, 3])));
}
@@ -2,14 +2,16 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::PathBuf;
use serde::Deserialize;
extern crate fnv;
use self::fnv::FnvHasher;
use token::{
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_de_tokens,
assert_de_tokens_ignore,
assert_de_tokens_error,
};
@@ -73,107 +75,147 @@ macro_rules! declare_error_tests {
}
}
fn assert_de_tokens_ignore(ignorable_tokens: &[Token<'static>]) {
#[derive(PartialEq, Debug, Deserialize)]
struct IgnoreBase {
a: i32,
}
let expected = IgnoreBase{a: 1};
// Embed the tokens to be ignored in the normal token
// stream for an IgnoreBase type
let concated_tokens : Vec<Token<'static>> = vec![
Token::MapStart(Some(2)),
Token::MapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::Str("ignored")
]
.into_iter()
.chain(ignorable_tokens.to_vec().into_iter())
.chain(vec![
Token::MapEnd,
].into_iter())
.collect();
let mut de = serde_test::Deserializer::new(concated_tokens.into_iter());
let v: Result<IgnoreBase, Error> = Deserialize::deserialize(&mut de);
// We run this test on every token stream for convenience, but
// some token streams don't make sense embedded as a map value,
// so we ignore those. SyntaxError is the real sign of trouble.
if let Err(Error::UnexpectedToken(_)) = v {
return;
}
assert_eq!(v.as_ref(), Ok(&expected));
assert_eq!(de.next_token(), None);
}
//////////////////////////////////////////////////////////////////////////
declare_tests! {
test_bool {
true => vec![Token::Bool(true)],
false => vec![Token::Bool(false)],
true => &[Token::Bool(true)],
false => &[Token::Bool(false)],
}
test_isize {
0isize => vec![Token::Isize(0)],
0isize => vec![Token::I8(0)],
0isize => vec![Token::I16(0)],
0isize => vec![Token::I32(0)],
0isize => vec![Token::I64(0)],
0isize => vec![Token::Usize(0)],
0isize => vec![Token::U8(0)],
0isize => vec![Token::U16(0)],
0isize => vec![Token::U32(0)],
0isize => vec![Token::U64(0)],
0isize => vec![Token::F32(0.)],
0isize => vec![Token::F64(0.)],
0isize => &[Token::Isize(0)],
0isize => &[Token::I8(0)],
0isize => &[Token::I16(0)],
0isize => &[Token::I32(0)],
0isize => &[Token::I64(0)],
0isize => &[Token::Usize(0)],
0isize => &[Token::U8(0)],
0isize => &[Token::U16(0)],
0isize => &[Token::U32(0)],
0isize => &[Token::U64(0)],
0isize => &[Token::F32(0.)],
0isize => &[Token::F64(0.)],
}
test_ints {
0isize => vec![Token::Isize(0)],
0i8 => vec![Token::I8(0)],
0i16 => vec![Token::I16(0)],
0i32 => vec![Token::I32(0)],
0i64 => vec![Token::I64(0)],
0isize => &[Token::Isize(0)],
0i8 => &[Token::I8(0)],
0i16 => &[Token::I16(0)],
0i32 => &[Token::I32(0)],
0i64 => &[Token::I64(0)],
}
test_uints {
0usize => vec![Token::Usize(0)],
0u8 => vec![Token::U8(0)],
0u16 => vec![Token::U16(0)],
0u32 => vec![Token::U32(0)],
0u64 => vec![Token::U64(0)],
0usize => &[Token::Usize(0)],
0u8 => &[Token::U8(0)],
0u16 => &[Token::U16(0)],
0u32 => &[Token::U32(0)],
0u64 => &[Token::U64(0)],
}
test_floats {
0f32 => vec![Token::F32(0.)],
0f64 => vec![Token::F64(0.)],
0f32 => &[Token::F32(0.)],
0f64 => &[Token::F64(0.)],
}
test_char {
'a' => vec![Token::Char('a')],
'a' => vec![Token::Str("a")],
'a' => vec![Token::String("a".to_owned())],
'a' => &[Token::Char('a')],
'a' => &[Token::Str("a")],
'a' => &[Token::String("a".to_owned())],
}
test_string {
"abc".to_owned() => vec![Token::Str("abc")],
"abc".to_owned() => vec![Token::String("abc".to_owned())],
"a".to_owned() => vec![Token::Char('a')],
"abc".to_owned() => &[Token::Str("abc")],
"abc".to_owned() => &[Token::String("abc".to_owned())],
"a".to_owned() => &[Token::Char('a')],
}
test_option {
None::<i32> => vec![Token::Unit],
None::<i32> => vec![Token::Option(false)],
Some(1) => vec![Token::I32(1)],
Some(1) => vec![
None::<i32> => &[Token::Unit],
None::<i32> => &[Token::Option(false)],
Some(1) => &[Token::I32(1)],
Some(1) => &[
Token::Option(true),
Token::I32(1),
],
}
test_result {
Ok::<i32, i32>(0) => vec![
Ok::<i32, i32>(0) => &[
Token::EnumStart("Result"),
Token::Str("Ok"),
Token::I32(0),
],
Err::<i32, i32>(1) => vec![
Err::<i32, i32>(1) => &[
Token::EnumStart("Result"),
Token::Str("Err"),
Token::I32(1),
],
}
test_unit {
() => vec![Token::Unit],
() => vec![
() => &[Token::Unit],
() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
() => vec![
() => &[
Token::SeqStart(None),
Token::SeqEnd,
],
() => vec![
Token::TupleStructStart("Anything", Some(0)),
() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
test_unit_struct {
UnitStruct => vec![Token::Unit],
UnitStruct => vec![
UnitStruct => &[Token::Unit],
UnitStruct => &[
Token::UnitStruct("UnitStruct"),
],
UnitStruct => vec![
UnitStruct => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
UnitStruct => vec![
UnitStruct => &[
Token::SeqStart(None),
Token::SeqEnd,
],
}
test_tuple_struct {
TupleStruct(1, 2, 3) => vec![
TupleStruct(1, 2, 3) => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -185,7 +227,7 @@ declare_tests! {
Token::I32(3),
Token::SeqEnd,
],
TupleStruct(1, 2, 3) => vec![
TupleStruct(1, 2, 3) => &[
Token::SeqStart(None),
Token::SeqSep,
Token::I32(1),
@@ -197,8 +239,8 @@ declare_tests! {
Token::I32(3),
Token::SeqEnd,
],
TupleStruct(1, 2, 3) => vec![
Token::TupleStructStart("TupleStruct", Some(3)),
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", 3),
Token::TupleStructSep,
Token::I32(1),
@@ -209,8 +251,8 @@ declare_tests! {
Token::I32(3),
Token::TupleStructEnd,
],
TupleStruct(1, 2, 3) => vec![
Token::TupleStructStart("TupleStruct", None),
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", 3),
Token::TupleStructSep,
Token::I32(1),
@@ -223,14 +265,14 @@ declare_tests! {
],
}
test_btreeset {
BTreeSet::<isize>::new() => vec![
BTreeSet::<isize>::new() => &[
Token::Unit,
],
BTreeSet::<isize>::new() => vec![
BTreeSet::<isize>::new() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
btreeset![btreeset![], btreeset![1], btreeset![2, 3]] => vec![
btreeset![btreeset![], btreeset![1], btreeset![2, 3]] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::SeqStart(Some(0)),
@@ -252,23 +294,23 @@ declare_tests! {
Token::SeqEnd,
Token::SeqEnd,
],
BTreeSet::<isize>::new() => vec![
BTreeSet::<isize>::new() => &[
Token::UnitStruct("Anything"),
],
BTreeSet::<isize>::new() => vec![
Token::TupleStructStart("Anything", Some(0)),
BTreeSet::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
test_hashset {
HashSet::<isize>::new() => vec![
HashSet::<isize>::new() => &[
Token::Unit,
],
HashSet::<isize>::new() => vec![
HashSet::<isize>::new() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
hashset![1, 2, 3] => vec![
hashset![1, 2, 3] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -280,14 +322,14 @@ declare_tests! {
Token::I32(3),
Token::SeqEnd,
],
HashSet::<isize>::new() => vec![
HashSet::<isize>::new() => &[
Token::UnitStruct("Anything"),
],
HashSet::<isize>::new() => vec![
Token::TupleStructStart("Anything", Some(0)),
HashSet::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
hashset![FnvHasher @ 1, 2, 3] => vec![
hashset![FnvHasher @ 1, 2, 3] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -301,14 +343,14 @@ declare_tests! {
],
}
test_vec {
Vec::<isize>::new() => vec![
Vec::<isize>::new() => &[
Token::Unit,
],
Vec::<isize>::new() => vec![
Vec::<isize>::new() => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
vec![vec![], vec![1], vec![2, 3]] => vec![
vec![vec![], vec![1], vec![2, 3]] => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::SeqStart(Some(0)),
@@ -330,27 +372,27 @@ declare_tests! {
Token::SeqEnd,
Token::SeqEnd,
],
Vec::<isize>::new() => vec![
Vec::<isize>::new() => &[
Token::UnitStruct("Anything"),
],
Vec::<isize>::new() => vec![
Token::TupleStructStart("Anything", Some(0)),
Vec::<isize>::new() => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
test_array {
[0; 0] => vec![
[0; 0] => &[
Token::Unit,
],
[0; 0] => vec![
[0; 0] => &[
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
[0; 0] => vec![
[0; 0] => &[
Token::SeqArrayStart(0),
Token::SeqEnd,
],
([0; 0], [1], [2, 3]) => vec![
([0; 0], [1], [2, 3]) => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::SeqStart(Some(0)),
@@ -372,7 +414,7 @@ declare_tests! {
Token::SeqEnd,
Token::SeqEnd,
],
([0; 0], [1], [2, 3]) => vec![
([0; 0], [1], [2, 3]) => &[
Token::SeqArrayStart(3),
Token::SeqSep,
Token::SeqArrayStart(0),
@@ -394,22 +436,22 @@ declare_tests! {
Token::SeqEnd,
Token::SeqEnd,
],
[0; 0] => vec![
[0; 0] => &[
Token::UnitStruct("Anything"),
],
[0; 0] => vec![
Token::TupleStructStart("Anything", Some(0)),
[0; 0] => &[
Token::TupleStructStart("Anything", 0),
Token::SeqEnd,
],
}
test_tuple {
(1,) => vec![
(1,) => &[
Token::SeqStart(Some(1)),
Token::SeqSep,
Token::I32(1),
Token::SeqEnd,
],
(1, 2, 3) => vec![
(1, 2, 3) => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -421,13 +463,13 @@ declare_tests! {
Token::I32(3),
Token::SeqEnd,
],
(1,) => vec![
(1,) => &[
Token::TupleStart(1),
Token::TupleSep,
Token::I32(1),
Token::TupleEnd,
],
(1, 2, 3) => vec![
(1, 2, 3) => &[
Token::TupleStart(3),
Token::TupleSep,
Token::I32(1),
@@ -441,21 +483,21 @@ declare_tests! {
],
}
test_btreemap {
BTreeMap::<isize, isize>::new() => vec![
BTreeMap::<isize, isize>::new() => &[
Token::Unit,
],
BTreeMap::<isize, isize>::new() => vec![
BTreeMap::<isize, isize>::new() => &[
Token::MapStart(Some(0)),
Token::MapEnd,
],
btreemap![1 => 2] => vec![
btreemap![1 => 2] => &[
Token::MapStart(Some(1)),
Token::MapSep,
Token::I32(1),
Token::I32(2),
Token::MapEnd,
],
btreemap![1 => 2, 3 => 4] => vec![
btreemap![1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -466,7 +508,7 @@ declare_tests! {
Token::I32(4),
Token::MapEnd,
],
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => vec![
btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -486,30 +528,30 @@ declare_tests! {
Token::MapEnd,
Token::MapEnd,
],
BTreeMap::<isize, isize>::new() => vec![
BTreeMap::<isize, isize>::new() => &[
Token::UnitStruct("Anything"),
],
BTreeMap::<isize, isize>::new() => vec![
Token::StructStart("Anything", Some(0)),
BTreeMap::<isize, isize>::new() => &[
Token::StructStart("Anything", 0),
Token::MapEnd,
],
}
test_hashmap {
HashMap::<isize, isize>::new() => vec![
HashMap::<isize, isize>::new() => &[
Token::Unit,
],
HashMap::<isize, isize>::new() => vec![
HashMap::<isize, isize>::new() => &[
Token::MapStart(Some(0)),
Token::MapEnd,
],
hashmap![1 => 2] => vec![
hashmap![1 => 2] => &[
Token::MapStart(Some(1)),
Token::MapSep,
Token::I32(1),
Token::I32(2),
Token::MapEnd,
],
hashmap![1 => 2, 3 => 4] => vec![
hashmap![1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -520,7 +562,7 @@ declare_tests! {
Token::I32(4),
Token::MapEnd,
],
hashmap![1 => hashmap![], 2 => hashmap![3 => 4, 5 => 6]] => vec![
hashmap![1 => hashmap![], 2 => hashmap![3 => 4, 5 => 6]] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -540,14 +582,14 @@ declare_tests! {
Token::MapEnd,
Token::MapEnd,
],
HashMap::<isize, isize>::new() => vec![
HashMap::<isize, isize>::new() => &[
Token::UnitStruct("Anything"),
],
HashMap::<isize, isize>::new() => vec![
Token::StructStart("Anything", Some(0)),
HashMap::<isize, isize>::new() => &[
Token::StructStart("Anything", 0),
Token::MapEnd,
],
hashmap![FnvHasher @ 1 => 2, 3 => 4] => vec![
hashmap![FnvHasher @ 1 => 2, 3 => 4] => &[
Token::MapStart(Some(2)),
Token::MapSep,
Token::I32(1),
@@ -560,7 +602,7 @@ declare_tests! {
],
}
test_struct {
Struct { a: 1, b: 2, c: 0 } => vec![
Struct { a: 1, b: 2, c: 0 } => &[
Token::MapStart(Some(3)),
Token::MapSep,
Token::Str("a"),
@@ -571,8 +613,8 @@ declare_tests! {
Token::I32(2),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => vec![
Token::StructStart("Struct", Some(3)),
Struct { a: 1, b: 2, c: 0 } => &[
Token::StructStart("Struct", 3),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
@@ -582,7 +624,7 @@ declare_tests! {
Token::I32(2),
Token::StructEnd,
],
Struct { a: 1, b: 2, c: 0 } => vec![
Struct { a: 1, b: 2, c: 0 } => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
@@ -593,7 +635,7 @@ declare_tests! {
],
}
test_struct_with_skip {
Struct { a: 1, b: 2, c: 0 } => vec![
Struct { a: 1, b: 2, c: 0 } => &[
Token::MapStart(Some(3)),
Token::MapSep,
Token::Str("a"),
@@ -612,8 +654,8 @@ declare_tests! {
Token::I32(4),
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => vec![
Token::StructStart("Struct", Some(3)),
Struct { a: 1, b: 2, c: 0 } => &[
Token::StructStart("Struct", 3),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
@@ -633,19 +675,19 @@ declare_tests! {
],
}
test_enum_unit {
Enum::Unit => vec![
Enum::Unit => &[
Token::EnumUnit("Enum", "Unit"),
],
}
test_enum_simple {
Enum::Simple(1) => vec![
Enum::Simple(1) => &[
Token::EnumNewType("Enum", "Simple"),
Token::I32(1),
],
}
test_enum_seq {
Enum::Seq(1, 2, 3) => vec![
Token::EnumSeqStart("Enum", "Seq", Some(3)),
Enum::Seq(1, 2, 3) => &[
Token::EnumSeqStart("Enum", "Seq", 3),
Token::EnumSeqSep,
Token::I32(1),
@@ -658,8 +700,8 @@ declare_tests! {
],
}
test_enum_map {
Enum::Map { a: 1, b: 2, c: 3 } => vec![
Token::EnumMapStart("Enum", "Map", Some(3)),
Enum::Map { a: 1, b: 2, c: 3 } => &[
Token::EnumMapStart("Enum", "Map", 3),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
@@ -675,24 +717,24 @@ declare_tests! {
],
}
test_enum_unit_usize {
Enum::Unit => vec![
Enum::Unit => &[
Token::EnumStart("Enum"),
Token::Usize(0),
Token::Unit,
],
}
test_enum_unit_bytes {
Enum::Unit => vec![
Enum::Unit => &[
Token::EnumStart("Enum"),
Token::Bytes(b"Unit"),
Token::Unit,
],
}
test_box {
Box::new(0i32) => vec![Token::I32(0)],
Box::new(0i32) => &[Token::I32(0)],
}
test_boxed_slice {
Box::new([0, 1, 2]) => vec![
Box::new([0, 1, 2]) => &[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(0),
@@ -704,52 +746,50 @@ declare_tests! {
],
}
test_net_ipv4addr {
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => vec![Token::Str("1.2.3.4")],
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
}
test_net_ipv6addr {
"::1".parse::<net::Ipv6Addr>().unwrap() => vec![Token::Str("::1")],
"::1".parse::<net::Ipv6Addr>().unwrap() => &[Token::Str("::1")],
}
test_net_socketaddr {
"1.2.3.4:1234".parse::<net::SocketAddr>().unwrap() => vec![Token::Str("1.2.3.4:1234")],
"1.2.3.4:1234".parse::<net::SocketAddrV4>().unwrap() => vec![Token::Str("1.2.3.4:1234")],
"[::1]:1234".parse::<net::SocketAddrV6>().unwrap() => vec![Token::Str("[::1]:1234")],
"1.2.3.4:1234".parse::<net::SocketAddr>().unwrap() => &[Token::Str("1.2.3.4:1234")],
"1.2.3.4:1234".parse::<net::SocketAddrV4>().unwrap() => &[Token::Str("1.2.3.4:1234")],
"[::1]:1234".parse::<net::SocketAddrV6>().unwrap() => &[Token::Str("[::1]:1234")],
}
test_path_buf {
PathBuf::from("/usr/local/lib") => vec![
PathBuf::from("/usr/local/lib") => &[
Token::String("/usr/local/lib".to_owned()),
],
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
#[test]
fn test_net_ipaddr() {
assert_de_tokens(
"1.2.3.4".parse::<net::IpAddr>().unwrap(),
vec![Token::Str("1.2.3.4")],
&[Token::Str("1.2.3.4")],
);
}
declare_error_tests! {
test_unknown_variant<Enum> {
vec![
&[
Token::EnumUnit("Enum", "Foo"),
],
Error::UnknownVariantError("Foo".to_owned()),
Error::UnknownVariant("Foo".to_owned()),
}
test_struct_seq_too_long<Struct> {
vec![
&[
Token::SeqStart(Some(4)),
Token::SeqSep, Token::I32(1),
Token::SeqSep, Token::I32(2),
Token::SeqSep, Token::I32(3),
Token::SeqSep, Token::I32(4),
Token::SeqEnd,
],
Error::UnexpectedToken(Token::SeqSep),
}
test_duplicate_field_struct<Struct> {
vec![
&[
Token::MapStart(Some(3)),
Token::MapSep,
Token::Str("a"),
@@ -757,23 +797,19 @@ declare_error_tests! {
Token::MapSep,
Token::Str("a"),
Token::I32(3),
Token::MapEnd,
],
Error::DuplicateFieldError("a"),
Error::DuplicateField("a"),
}
test_duplicate_field_enum<Enum> {
vec![
Token::EnumMapStart("Enum", "Map", Some(3)),
&[
Token::EnumMapStart("Enum", "Map", 3),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(3),
Token::EnumMapEnd,
],
Error::DuplicateFieldError("a"),
Error::DuplicateField("a"),
}
}
+216
View File
@@ -0,0 +1,216 @@
// These just test that serde_codegen is able to produce code that compiles
// successfully when there are a variety of generics and non-(de)serializable
// types involved.
extern crate serde;
use self::serde::ser::{Serialize, Serializer};
use self::serde::de::{Deserialize, Deserializer};
use std::marker::PhantomData;
//////////////////////////////////////////////////////////////////////////
#[test]
fn test_gen() {
#[derive(Serialize, Deserialize)]
struct With<T> {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X,
}
assert::<With<i32>>();
#[derive(Serialize, Deserialize)]
struct WithRef<'a, T: 'a> {
#[serde(skip_deserializing)]
t: Option<&'a T>,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X,
}
assert::<WithRef<i32>>();
#[derive(Serialize, Deserialize)]
struct PhantomX {
x: PhantomData<X>,
}
assert::<PhantomX>();
#[derive(Serialize, Deserialize)]
struct PhantomT<T> {
t: PhantomData<T>,
}
assert::<PhantomT<X>>();
#[derive(Serialize, Deserialize)]
struct Bounds<T: Serialize + Deserialize> {
t: T,
option: Option<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
}
assert::<Bounds<i32>>();
#[derive(Serialize, Deserialize)]
struct NoBounds<T> {
t: T,
option: Option<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
}
assert::<NoBounds<i32>>();
#[derive(Serialize, Deserialize)]
enum EnumWith<T> {
Unit,
Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X),
Tuple(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X),
Struct {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
x: X },
}
assert::<EnumWith<i32>>();
#[derive(Serialize)]
struct MultipleRef<'a, 'b, 'c, T> where T: 'c, 'c: 'b, 'b: 'a {
t: T,
rrrt: &'a &'b &'c T,
}
assert_ser::<MultipleRef<i32>>();
#[derive(Serialize, Deserialize)]
struct Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
);
assert::<Newtype>();
#[derive(Serialize, Deserialize)]
struct Tuple<T>(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X,
);
assert::<Tuple<i32>>();
#[derive(Serialize, Deserialize)]
enum TreeNode<D> {
Split {
left: Box<TreeNode<D>>,
right: Box<TreeNode<D>>,
},
Leaf {
data: D,
},
}
assert::<TreeNode<i32>>();
#[derive(Serialize, Deserialize)]
struct ListNode<D> {
data: D,
next: Box<ListNode<D>>,
}
assert::<ListNode<i32>>();
#[derive(Serialize, Deserialize)]
struct RecursiveA {
b: Box<RecursiveB>,
}
assert::<RecursiveA>();
#[derive(Serialize, Deserialize)]
enum RecursiveB {
A(RecursiveA),
}
assert::<RecursiveB>();
#[derive(Serialize, Deserialize)]
struct RecursiveGenericA<T> {
t: T,
b: Box<RecursiveGenericB<T>>,
}
assert::<RecursiveGenericA<i32>>();
#[derive(Serialize, Deserialize)]
enum RecursiveGenericB<T> {
T(T),
A(RecursiveGenericA<T>),
}
assert::<RecursiveGenericB<i32>>();
#[derive(Serialize)]
struct OptionStatic<'a> {
a: Option<&'a str>,
b: Option<&'static str>,
}
assert_ser::<OptionStatic>();
#[derive(Serialize, Deserialize)]
#[serde(bound="D: SerializeWith + DeserializeWith")]
struct WithTraits1<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with",
bound="E: SerializeWith + DeserializeWith")]
e: E,
}
assert::<WithTraits1<X, X>>();
#[derive(Serialize, Deserialize)]
#[serde(bound(serialize="D: SerializeWith",
deserialize="D: DeserializeWith"))]
struct WithTraits2<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
bound(serialize="E: SerializeWith"))]
#[serde(deserialize_with="DeserializeWith::deserialize_with",
bound(deserialize="E: DeserializeWith"))]
e: E,
}
assert::<WithTraits2<X, X>>();
}
//////////////////////////////////////////////////////////////////////////
fn assert<T: Serialize + Deserialize>() {}
fn assert_ser<T: Serialize>() {}
trait SerializeWith {
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> Result<(), S::Error>;
}
trait DeserializeWith: Sized {
fn deserialize_with<D: Deserializer>(_: &mut D) -> Result<Self, D::Error>;
}
// Implements neither Serialize nor Deserialize
struct X;
fn ser_x<S: Serializer>(_: &X, _: &mut S) -> Result<(), S::Error> {
unimplemented!()
}
fn de_x<D: Deserializer>(_: &mut D) -> Result<X, D::Error> {
unimplemented!()
}
impl SerializeWith for X {
fn serialize_with<S: Serializer>(_: &Self, _: &mut S) -> Result<(), S::Error> {
unimplemented!()
}
}
impl DeserializeWith for X {
fn deserialize_with<D: Deserializer>(_: &mut D) -> Result<Self, D::Error> {
unimplemented!()
}
}
@@ -1,11 +1,12 @@
use std::marker::PhantomData;
use token::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens};
extern crate serde_test;
use self::serde_test::{
Token,
assert_tokens,
assert_ser_tokens,
assert_de_tokens,
};
/*
trait Trait {
type Type;
}
*/
use std::marker::PhantomData;
// That tests that the derived Serialize implementation doesn't trigger
// any warning about `serializer` not being used, in case of empty enums.
@@ -38,23 +39,19 @@ struct DeNamedMap<A, B, C> {
}
#[derive(Debug, PartialEq, Serialize)]
enum SerEnum<'a, B: 'a, C: /* Trait + */ 'a, D> where D: /* Trait + */ 'a {
enum SerEnum<'a, B: 'a, C: 'a, D> where D: 'a {
Unit,
Seq(
i8,
B,
&'a C,
//C::Type,
&'a mut D,
//<D as Trait>::Type,
),
Map {
a: i8,
b: B,
c: &'a C,
//d: C::Type,
e: &'a mut D,
//f: <D as Trait>::Type,
d: &'a mut D,
},
// Make sure we can support more than one variant.
@@ -63,38 +60,30 @@ enum SerEnum<'a, B: 'a, C: /* Trait + */ 'a, D> where D: /* Trait + */ 'a {
i8,
B,
&'a C,
//C::Type,
&'a mut D,
//<D as Trait>::Type,
),
_Map2 {
a: i8,
b: B,
c: &'a C,
//d: C::Type,
e: &'a mut D,
//f: <D as Trait>::Type,
d: &'a mut D,
},
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DeEnum<B, C: /* Trait */, D> /* where D: Trait */ {
enum DeEnum<B, C, D> {
Unit,
Seq(
i8,
B,
C,
//C::Type,
D,
//<D as Trait>::Type,
),
Map {
a: i8,
b: B,
c: C,
//d: C::Type,
e: D,
//f: <D as Trait>::Type,
d: D,
},
// Make sure we can support more than one variant.
@@ -103,17 +92,13 @@ enum DeEnum<B, C: /* Trait */, D> /* where D: Trait */ {
i8,
B,
C,
//C::Type,
D,
//<D as Trait>::Type,
),
_Map2 {
a: i8,
b: B,
c: C,
//d: C::Type,
e: D,
//f: <D as Trait>::Type,
d: D,
},
}
@@ -161,7 +146,7 @@ struct DefaultTyParam<T: AssociatedType<X=i32> = i32> {
fn test_named_unit() {
assert_tokens(
&NamedUnit,
vec![Token::UnitStruct("NamedUnit")]
&[Token::UnitStruct("NamedUnit")]
);
}
@@ -173,7 +158,7 @@ fn test_ser_named_tuple() {
assert_ser_tokens(
&SerNamedTuple(&a, &mut b, c),
&[
Token::TupleStructStart("SerNamedTuple", Some(3)),
Token::TupleStructStart("SerNamedTuple", 3),
Token::TupleStructSep,
Token::I32(5),
@@ -192,7 +177,7 @@ fn test_ser_named_tuple() {
fn test_de_named_tuple() {
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
vec![
&[
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(5),
@@ -209,8 +194,8 @@ fn test_de_named_tuple() {
assert_de_tokens(
&DeNamedTuple(5, 6, 7),
vec![
Token::TupleStructStart("DeNamedTuple", Some(3)),
&[
Token::TupleStructStart("DeNamedTuple", 3),
Token::TupleStructSep,
Token::I32(5),
@@ -238,7 +223,7 @@ fn test_ser_named_map() {
c: c,
},
&[
Token::StructStart("SerNamedMap", Some(3)),
Token::StructStart("SerNamedMap", 3),
Token::StructSep,
Token::Str("a"),
@@ -265,8 +250,8 @@ fn test_de_named_map() {
b: 6,
c: 7,
},
vec![
Token::StructStart("DeNamedMap", Some(3)),
&[
Token::StructStart("DeNamedMap", 3),
Token::StructSep,
Token::Str("a"),
@@ -300,21 +285,17 @@ fn test_ser_enum_seq() {
let a = 1;
let b = 2;
let c = 3;
//let d = 4;
let mut e = 5;
//let f = 6;
let mut d = 4;
assert_ser_tokens(
&SerEnum::Seq(
a,
b,
&c,
//d,
&mut e,
//f,
&mut d,
),
&[
Token::EnumSeqStart("SerEnum", "Seq", Some(4)),
Token::EnumSeqStart("SerEnum", "Seq", 4),
Token::EnumSeqSep,
Token::I8(1),
@@ -326,7 +307,7 @@ fn test_ser_enum_seq() {
Token::I32(3),
Token::EnumSeqSep,
Token::I32(5),
Token::I32(4),
Token::EnumSeqEnd,
],
@@ -338,21 +319,17 @@ fn test_ser_enum_map() {
let a = 1;
let b = 2;
let c = 3;
//let d = 4;
let mut e = 5;
//let f = 6;
let mut d = 4;
assert_ser_tokens(
&SerEnum::Map {
a: a,
b: b,
c: &c,
//d: d,
e: &mut e,
//f: f,
d: &mut d,
},
&[
Token::EnumMapStart("SerEnum", "Map", Some(4)),
Token::EnumMapStart("SerEnum", "Map", 4),
Token::EnumMapSep,
Token::Str("a"),
@@ -367,8 +344,8 @@ fn test_ser_enum_map() {
Token::I32(3),
Token::EnumMapSep,
Token::Str("e"),
Token::I32(5),
Token::Str("d"),
Token::I32(4),
Token::EnumMapEnd,
],
@@ -379,7 +356,7 @@ fn test_ser_enum_map() {
fn test_de_enum_unit() {
assert_tokens(
&DeEnum::Unit::<u32, u32, u32>,
vec![
&[
Token::EnumUnit("DeEnum", "Unit"),
],
);
@@ -390,21 +367,17 @@ fn test_de_enum_seq() {
let a = 1;
let b = 2;
let c = 3;
//let d = 4;
let e = 5;
//let f = 6;
let d = 4;
assert_tokens(
&DeEnum::Seq(
a,
b,
c,
//d,
e,
//f,
d,
),
vec![
Token::EnumSeqStart("DeEnum", "Seq", Some(4)),
&[
Token::EnumSeqStart("DeEnum", "Seq", 4),
Token::EnumSeqSep,
Token::I8(1),
@@ -416,7 +389,7 @@ fn test_de_enum_seq() {
Token::I32(3),
Token::EnumSeqSep,
Token::I32(5),
Token::I32(4),
Token::EnumSeqEnd,
],
@@ -428,21 +401,17 @@ fn test_de_enum_map() {
let a = 1;
let b = 2;
let c = 3;
//let d = 4;
let e = 5;
//let f = 6;
let d = 4;
assert_tokens(
&DeEnum::Map {
a: a,
b: b,
c: c,
//d: d,
e: e,
//f: f,
d: d,
},
vec![
Token::EnumMapStart("DeEnum", "Map", Some(4)),
&[
Token::EnumMapStart("DeEnum", "Map", 4),
Token::EnumMapSep,
Token::Str("a"),
@@ -457,8 +426,8 @@ fn test_de_enum_map() {
Token::I32(3),
Token::EnumMapSep,
Token::Str("e"),
Token::I32(5),
Token::Str("d"),
Token::I32(4),
Token::EnumMapEnd,
],
@@ -488,7 +457,7 @@ fn test_lifetimes() {
assert_ser_tokens(
&Lifetimes::LifetimeMap { a: &value },
&[
Token::EnumMapStart("Lifetimes", "LifetimeMap", Some(1)),
Token::EnumMapStart("Lifetimes", "LifetimeMap", 1),
Token::EnumMapSep,
Token::Str("a"),
@@ -501,7 +470,7 @@ fn test_lifetimes() {
assert_ser_tokens(
&Lifetimes::NoLifetimeMap { a: 5 },
&[
Token::EnumMapStart("Lifetimes", "NoLifetimeMap", Some(1)),
Token::EnumMapStart("Lifetimes", "NoLifetimeMap", 1),
Token::EnumMapSep,
Token::Str("a"),
@@ -516,8 +485,8 @@ fn test_lifetimes() {
fn test_generic_struct() {
assert_tokens(
&GenericStruct { x: 5u32 },
vec![
Token::StructStart("GenericStruct", Some(1)),
&[
Token::StructStart("GenericStruct", 1),
Token::StructSep,
Token::Str("x"),
@@ -532,7 +501,7 @@ fn test_generic_struct() {
fn test_generic_newtype_struct() {
assert_tokens(
&GenericNewTypeStruct(5u32),
vec![
&[
Token::StructNewType("GenericNewTypeStruct"),
Token::U32(5),
]
@@ -543,8 +512,8 @@ fn test_generic_newtype_struct() {
fn test_generic_tuple_struct() {
assert_tokens(
&GenericTupleStruct(5u32, 6u32),
vec![
Token::TupleStructStart("GenericTupleStruct", Some(2)),
&[
Token::TupleStructStart("GenericTupleStruct", 2),
Token::TupleStructSep,
Token::U32(5),
@@ -561,7 +530,7 @@ fn test_generic_tuple_struct() {
fn test_generic_enum_unit() {
assert_tokens(
&GenericEnum::Unit::<u32, u32>,
vec![
&[
Token::EnumUnit("GenericEnum", "Unit"),
]
);
@@ -571,7 +540,7 @@ fn test_generic_enum_unit() {
fn test_generic_enum_newtype() {
assert_tokens(
&GenericEnum::NewType::<u32, u32>(5),
vec![
&[
Token::EnumNewType("GenericEnum", "NewType"),
Token::U32(5),
]
@@ -582,8 +551,8 @@ fn test_generic_enum_newtype() {
fn test_generic_enum_seq() {
assert_tokens(
&GenericEnum::Seq::<u32, u32>(5, 6),
vec![
Token::EnumSeqStart("GenericEnum", "Seq", Some(2)),
&[
Token::EnumSeqStart("GenericEnum", "Seq", 2),
Token::EnumSeqSep,
Token::U32(5),
@@ -600,8 +569,8 @@ fn test_generic_enum_seq() {
fn test_generic_enum_map() {
assert_tokens(
&GenericEnum::Map::<u32, u32> { x: 5, y: 6 },
vec![
Token::EnumMapStart("GenericEnum", "Map", Some(2)),
&[
Token::EnumMapStart("GenericEnum", "Map", 2),
Token::EnumMapSep,
Token::Str("x"),
@@ -620,8 +589,8 @@ fn test_generic_enum_map() {
fn test_default_ty_param() {
assert_tokens(
&DefaultTyParam::<i32> { phantom: PhantomData },
vec![
Token::StructStart("DefaultTyParam", Some(1)),
&[
Token::StructStart("DefaultTyParam", 1),
Token::StructSep,
Token::Str("phantom"),
@@ -3,7 +3,13 @@ use std::net;
use std::path::{Path, PathBuf};
use std::str;
use token::{self, Token};
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_ser_tokens,
assert_ser_tokens_error,
};
extern crate fnv;
use self::fnv::FnvHasher;
@@ -250,7 +256,7 @@ declare_ser_tests! {
}
test_tuple_struct {
TupleStruct(1, 2, 3) => &[
Token::TupleStructStart("TupleStruct", Some(3)),
Token::TupleStructStart("TupleStruct", 3),
Token::TupleStructSep,
Token::I32(1),
@@ -264,7 +270,7 @@ declare_ser_tests! {
}
test_struct {
Struct { a: 1, b: 2, c: 3 } => &[
Token::StructStart("Struct", Some(3)),
Token::StructStart("Struct", 3),
Token::StructSep,
Token::Str("a"),
Token::I32(1),
@@ -283,7 +289,7 @@ declare_ser_tests! {
Enum::Unit => &[Token::EnumUnit("Enum", "Unit")],
Enum::One(42) => &[Token::EnumNewType("Enum", "One"), Token::I32(42)],
Enum::Seq(1, 2) => &[
Token::EnumSeqStart("Enum", "Seq", Some(2)),
Token::EnumSeqStart("Enum", "Seq", 2),
Token::EnumSeqSep,
Token::I32(1),
@@ -292,7 +298,7 @@ declare_ser_tests! {
Token::EnumSeqEnd,
],
Enum::Map { a: 1, b: 2 } => &[
Token::EnumMapStart("Enum", "Map", Some(2)),
Token::EnumMapStart("Enum", "Map", 2),
Token::EnumMapSep,
Token::Str("a"),
Token::I32(1),
@@ -341,7 +347,7 @@ declare_ser_tests! {
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "unstable")]
#[test]
fn test_net_ipaddr() {
assert_ser_tokens(
@@ -355,16 +361,16 @@ fn test_cannot_serialize_paths() {
let path = unsafe {
str::from_utf8_unchecked(b"Hello \xF0\x90\x80World")
};
token::assert_ser_tokens_error(
assert_ser_tokens_error(
&Path::new(path),
&[Token::Str("Hello World")],
token::Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
&[],
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
let mut path_buf = PathBuf::new();
path_buf.push(path);
token::assert_ser_tokens_error(
assert_ser_tokens_error(
&path_buf,
&[Token::Str("Hello World")],
token::Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
&[],
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
}