mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-24 22:47:58 +00:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c915189f4 | |||
| c5541cddeb | |||
| 63561609a6 | |||
| 5dc356ddb0 | |||
| dc36fd38d6 | |||
| 26873bf3d5 | |||
| ff53323790 | |||
| fd3869d380 | |||
| 1d538bc59d | |||
| 784cfcd49e | |||
| a142d319e7 | |||
| da3bf3c20a | |||
| 1672306fa1 | |||
| 7fc780ba1b | |||
| 7fb2bd50bf | |||
| 2aeb51ad51 | |||
| 0482b756e8 | |||
| 1d9c707a76 | |||
| 199ed417bd | |||
| 199a02cb68 | |||
| b6371f045f | |||
| fd84aec485 | |||
| ed6777e59f | |||
| 22024a2b71 | |||
| 8eff38b6f6 | |||
| fa562d449d | |||
| c9d55362d6 | |||
| 23031d057f | |||
| 882d394352 | |||
| fbdede68a4 | |||
| e88ef4715c | |||
| 94f3dd25d8 | |||
| 2c58a9c11d | |||
| 97528b59cf | |||
| 6715fb6652 | |||
| fefc010deb | |||
| 6cbb72decf | |||
| 7e25ed863c | |||
| 5a56394814 | |||
| de1059f648 | |||
| 97f08086dd | |||
| 0348a3914d | |||
| 5dc245d2ce | |||
| 71cc95248c | |||
| 2cb7d66767 | |||
| 49fa208242 | |||
| d2fef27721 | |||
| 351b7039a8 | |||
| 7585ce9ed4 | |||
| 578a0178b5 | |||
| 6c9cebdcc3 | |||
| 35e2022e9a | |||
| 0058e3a8d4 | |||
| abf28ee167 | |||
| 5f1cb9b96c | |||
| 8f8fc6f3ff | |||
| 24787195a1 | |||
| 5885111863 | |||
| b1cb5379de | |||
| 447d08bd91 | |||
| b0512a4479 | |||
| 8663435a05 | |||
| 327990bc5f | |||
| 57753c9044 | |||
| e35603eb85 | |||
| 8fa40fe7e1 | |||
| d4c20829f6 | |||
| dbe2beacb0 | |||
| b9a938a01c | |||
| 4dd7345568 | |||
| b3cf9375d4 | |||
| 1751155a3a | |||
| 5dae700aec | |||
| affa9382be | |||
| 10f23dddfe | |||
| d30cf07254 | |||
| 31491b822f | |||
| 4c19cfead5 | |||
| b2754c2c3b | |||
| f56976db1d | |||
| 77b8a8baa0 | |||
| 0b9190cce3 | |||
| 2a40c5dd24 | |||
| 60ab494226 |
+4
-1
@@ -1,3 +1,4 @@
|
|||||||
|
sudo: false
|
||||||
language: rust
|
language: rust
|
||||||
rust:
|
rust:
|
||||||
- stable
|
- stable
|
||||||
@@ -25,10 +26,12 @@ after_success: |
|
|||||||
(cd serde && cargo doc --no-deps) &&
|
(cd serde && cargo doc --no-deps) &&
|
||||||
(cd serde_codegen && cargo doc --no-deps) &&
|
(cd serde_codegen && cargo doc --no-deps) &&
|
||||||
(cd serde_macros && cargo doc --no-deps) &&
|
(cd serde_macros && cargo doc --no-deps) &&
|
||||||
|
(cd serde_json && cargo doc --no-deps) &&
|
||||||
cp -r serde/target/doc target/doc/serde &&
|
cp -r serde/target/doc target/doc/serde &&
|
||||||
cp -r serde_codegen/target/doc target/doc/serde_codegen &&
|
cp -r serde_codegen/target/doc target/doc/serde_codegen &&
|
||||||
cp -r serde_macros/target/doc target/doc/serde_macros &&
|
cp -r serde_macros/target/doc target/doc/serde_macros &&
|
||||||
|
cp -r serde_json/target/doc target/doc/serde_json &&
|
||||||
echo "<meta http-equiv=refresh content=0;url=`echo $TRAVIS_REPO_SLUG | cut -d '/' -f 2`/index.html>" > target/doc/index.html &&
|
echo "<meta http-equiv=refresh content=0;url=`echo $TRAVIS_REPO_SLUG | cut -d '/' -f 2`/index.html>" > target/doc/index.html &&
|
||||||
sudo pip install ghp-import &&
|
pip install ghp-import &&
|
||||||
ghp-import -n target/doc &&
|
ghp-import -n target/doc &&
|
||||||
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
|
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
|
||||||
|
|||||||
@@ -10,78 +10,210 @@ information. In many situations, the handshake protocol between serializers and
|
|||||||
serializees can be completely optimized away, leaving Serde to perform roughly
|
serializees can be completely optimized away, leaving Serde to perform roughly
|
||||||
the same speed as a hand written serializer for a specific type.
|
the same speed as a hand written serializer for a specific type.
|
||||||
|
|
||||||
Documentation is available at http://serde-rs.github.io/serde/serde
|
Documentation is available at:
|
||||||
|
|
||||||
Making a Type Serializable
|
* [serde](https://serde-rs.github.io/serde/serde/serde/index.html)
|
||||||
==========================
|
* [serde\_json](https://serde-rs.github.io/serde/serde_json/serde_json/index.html)
|
||||||
|
* [serde\_codegen](https://serde-rs.github.io/serde/serde_codegen/serde_codegen/index.html)
|
||||||
|
|
||||||
The simplest way to make a type serializable is to use the `serde_macros`
|
Using Serde
|
||||||
syntax extension, which comes with a `#[derive(Serialize, Deserialize)]`
|
===========
|
||||||
annotation, which automatically generates implementations of
|
|
||||||
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
|
Here is a simple example that demonstrates how to use Serde by serializing and
|
||||||
and
|
deserializing to JSON. Serde comes with some powerful code generation libraries
|
||||||
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
|
that work with Stable and Nightly Rust that eliminate much of the complexity of
|
||||||
for the annotated type:
|
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`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[package]
|
||||||
|
name = "serde_example_nightly"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = "*"
|
||||||
|
serde_json = "*"
|
||||||
|
serde_macros = "*"
|
||||||
|
```
|
||||||
|
|
||||||
|
`src/main.rs`
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
#![feature(custom_derive, plugin)]
|
#![feature(custom_derive, plugin)]
|
||||||
#![plugin(serde_macros)]
|
#![plugin(serde_macros)]
|
||||||
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
...
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct Point {
|
struct Point {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: 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_point).unwrap();
|
||||||
|
|
||||||
|
println!("{:?}", deserialized);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Serde bundles a high performance JSON serializer and deserializer,
|
When run, it produces:
|
||||||
[serde::json](http://serde-rs.github.io/serde/serde/json/index.html),
|
|
||||||
which comes with the helper functions
|
```
|
||||||
[to_string](http://serde-rs.github.io/serde/serde/json/ser/fn.to_string.html)
|
% cargo run
|
||||||
and
|
{"x":1,"y":2}
|
||||||
[from_str](http://serde-rs.github.io/serde/serde/json/de/fn.from_str.html)
|
Point { x: 1, y: 2 }
|
||||||
that make it easy to go to and from JSON:
|
```
|
||||||
|
|
||||||
|
Stable Rust is a little more complicated because it does not yet support
|
||||||
|
compiler plugins. Instead we need to use the code generation library
|
||||||
|
[syntex](https://github.com/erickt/rust-syntex) for this:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[package]
|
||||||
|
name = "serde_example"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
serde_codegen = "*"
|
||||||
|
syntex = "*"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = "*"
|
||||||
|
serde_json = "*"
|
||||||
|
```
|
||||||
|
|
||||||
|
`src/main.rs`:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use serde::json;
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
...
|
include!(concat!(env!("OUT_DIR"), "/main.rs"));
|
||||||
|
|
||||||
let point = Point { x: 1, y: 2 };
|
|
||||||
let serialized_point = json::to_string(&point).unwrap();
|
|
||||||
|
|
||||||
println!("{}", serialized_point); // prints: {"x":1,"y":2}
|
|
||||||
|
|
||||||
let deserialize_point: Point = json::from_str(&serialized_point).unwrap();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
[serde::json](http://serde-rs.github.io/serde/serde/json/index.html) also
|
`src/main.rs.in`:
|
||||||
supports a generic
|
|
||||||
[Value](http://serde-rs.github.io/serde/serde/json/value/enum.Value.html)
|
|
||||||
type, which can represent any JSON value. Also, any
|
|
||||||
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
|
|
||||||
and
|
|
||||||
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
|
|
||||||
can be converted into a
|
|
||||||
[Value](http://serde-rs.github.io/serde/serde/json/value/enum.Value.html)
|
|
||||||
with the methods
|
|
||||||
[to_value](http://serde-rs.github.io/serde/serde/json/value/fn.to_value.html)
|
|
||||||
and
|
|
||||||
[from_value](http://serde-rs.github.io/serde/serde/json/value/fn.from_value.html):
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let point = Point { x: 1, y: 2 };
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
let point_value = json::to_value(&point).unwrap();
|
struct Point {
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
}
|
||||||
|
|
||||||
println!("{}", point_value.find("x")); // prints: Some(1)
|
fn main() {
|
||||||
|
let point = Point { x: 1, y: 2 };
|
||||||
|
let serialized = serde_json::to_string(&point).unwrap();
|
||||||
|
|
||||||
let deserialize_point: Point = json::from_value(point_value).unwrap();
|
println!("{}", serialized);
|
||||||
|
|
||||||
|
let deserialized: Point = serde_json::from_str(&serialized_point).unwrap();
|
||||||
|
|
||||||
|
println!("{:?}", deserialized);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This also produces:
|
||||||
|
|
||||||
|
```
|
||||||
|
% 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
|
||||||
|
deploy with Stable Rust and `serde_codegen`. It's possible to combine both
|
||||||
|
approaches in one setup:
|
||||||
|
|
||||||
|
`Cargo.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[package]
|
||||||
|
name = "serde_example"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["serde_codegen"]
|
||||||
|
nightly = ["serde_macros"]
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
serde_codegen = { version = "*", optional = true }
|
||||||
|
syntex = "*"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = "*"
|
||||||
|
serde_json = "*"
|
||||||
|
serde_macros = { version = "*", optional = true }
|
||||||
|
```
|
||||||
|
|
||||||
|
`build.rs`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[cfg(not(feature = "serde_macros"))]
|
||||||
|
mod inner {
|
||||||
|
extern crate syntex;
|
||||||
|
extern crate serde_codegen;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
|
|
||||||
|
let src = Path::new("src/main.rs.in");
|
||||||
|
let dst = Path::new(&out_dir).join("main.rs");
|
||||||
|
|
||||||
|
let mut registry = syntex::Registry::new();
|
||||||
|
|
||||||
|
serde_codegen::register(&mut registry);
|
||||||
|
registry.expand("", &src, &dst).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde_macros")]
|
||||||
|
mod inner {
|
||||||
|
pub fn main() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
inner::main();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`src/main.rs`:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#![cfg_attr(feature = "serde_macros", feature(custom_derive, plugin))]
|
||||||
|
#![cfg_attr(feature = "serde_macros", plugin(serde_macros))]
|
||||||
|
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
#[cfg(feature = "serde_macros")]
|
||||||
|
include!("main.rs.in");
|
||||||
|
|
||||||
|
#[cfg(not(feature = "serde_macros"))]
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/main.rs"));
|
||||||
|
```
|
||||||
|
|
||||||
|
The `src/main.rs.in` is the same as before.
|
||||||
|
|
||||||
Serialization without Macros
|
Serialization without Macros
|
||||||
============================
|
============================
|
||||||
|
|
||||||
@@ -187,7 +319,7 @@ impl serde::Serialize for Point {
|
|||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: serde::Serializer
|
where S: serde::Serializer
|
||||||
{
|
{
|
||||||
serializer.visit_named_map("Point", PointMapVisitor {
|
serializer.visit_struct("Point", PointMapVisitor {
|
||||||
value: self,
|
value: self,
|
||||||
state: 0,
|
state: 0,
|
||||||
})
|
})
|
||||||
@@ -206,11 +338,11 @@ impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
|
|||||||
match self.state {
|
match self.state {
|
||||||
0 => {
|
0 => {
|
||||||
self.state += 1;
|
self.state += 1;
|
||||||
Ok(Some(try!(serializer.visit_map_elt("x", &self.value.x))))
|
Ok(Some(try!(serializer.visit_struct_elt("x", &self.value.x))))
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
self.state += 1;
|
self.state += 1;
|
||||||
Ok(Some(try!(serializer.visit_map_elt("y", &self.value.y))))
|
Ok(Some(try!(serializer.visit_struct_elt("y", &self.value.y))))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@@ -275,7 +407,7 @@ to generate an error for a few common error conditions. Here's how it could be u
|
|||||||
fn visit_string<E>(&mut self, _: String) -> Result<i32, E>
|
fn visit_string<E>(&mut self, _: String) -> Result<i32, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(serde::de::Error::syntax_error())
|
Err(serde::de::Error::syntax("expect a string"))
|
||||||
}
|
}
|
||||||
|
|
||||||
...
|
...
|
||||||
@@ -366,7 +498,7 @@ impl serde::Deserialize for PointField {
|
|||||||
match value {
|
match value {
|
||||||
"x" => Ok(Field::X),
|
"x" => Ok(Field::X),
|
||||||
"y" => Ok(Field::Y),
|
"y" => Ok(Field::Y),
|
||||||
_ => Err(serde::de::Error::syntax_error()),
|
_ => Err(serde::de::Error::syntax("expected x or y")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,7 +515,7 @@ impl serde::Deserialize for Point {
|
|||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Point, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Point, D::Error>
|
||||||
where D: serde::de::Deserializer
|
where D: serde::de::Deserializer
|
||||||
{
|
{
|
||||||
deserializer.visit_named_map("Point", PointVisitor)
|
deserializer.visit_struct("Point", PointVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +524,9 @@ struct PointVisitor;
|
|||||||
impl serde::de::Visitor for PointVisitor {
|
impl serde::de::Visitor for PointVisitor {
|
||||||
type Value = Point;
|
type Value = Point;
|
||||||
|
|
||||||
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Point, V::Error>
|
fn visit_struct<V>(&mut self,
|
||||||
|
_fields: &[&str],
|
||||||
|
mut visitor: V) -> Result<Point, V::Error>
|
||||||
where V: serde::de::MapVisitor
|
where V: serde::de::MapVisitor
|
||||||
{
|
{
|
||||||
let mut x = None;
|
let mut x = None;
|
||||||
|
|||||||
+3
-3
@@ -1,13 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "0.4.3"
|
version = "0.5.1"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
repository = "https://github.com/serde-rs/serde"
|
repository = "https://github.com/serde-rs/serde"
|
||||||
documentation = "http://serde-rs.github.io/serde/serde"
|
documentation = "https://serde-rs.github.io/serde/serde/serde/index.html"
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
keywords = ["serialization"]
|
keywords = ["serde", "serialization"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num = "*"
|
num = "*"
|
||||||
|
|||||||
+93
-124
@@ -34,6 +34,7 @@ use de::{
|
|||||||
Error,
|
Error,
|
||||||
MapVisitor,
|
MapVisitor,
|
||||||
SeqVisitor,
|
SeqVisitor,
|
||||||
|
Type,
|
||||||
VariantVisitor,
|
VariantVisitor,
|
||||||
Visitor,
|
Visitor,
|
||||||
};
|
};
|
||||||
@@ -85,7 +86,7 @@ impl Visitor for BoolVisitor {
|
|||||||
match s.trim() {
|
match s.trim() {
|
||||||
"true" => Ok(true),
|
"true" => Ok(true),
|
||||||
"false" => Ok(false),
|
"false" => Ok(false),
|
||||||
_ => Err(Error::syntax_error()),
|
_ => Err(Error::type_mismatch(Type::Bool)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,14 +102,14 @@ impl Deserialize for bool {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! impl_deserialize_num_method {
|
macro_rules! impl_deserialize_num_method {
|
||||||
($src_ty:ty, $method:ident, $from_method:ident) => {
|
($src_ty:ty, $method:ident, $from_method:ident, $ty:expr) => {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $method<E>(&mut self, v: $src_ty) -> Result<T, E>
|
fn $method<E>(&mut self, v: $src_ty) -> Result<T, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
match FromPrimitive::$from_method(v) {
|
match FromPrimitive::$from_method(v) {
|
||||||
Some(v) => Ok(v),
|
Some(v) => Ok(v),
|
||||||
None => Err(Error::syntax_error()),
|
None => Err(Error::type_mismatch($ty)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,24 +133,24 @@ impl<
|
|||||||
> Visitor for PrimitiveVisitor<T> {
|
> Visitor for PrimitiveVisitor<T> {
|
||||||
type Value = T;
|
type Value = T;
|
||||||
|
|
||||||
impl_deserialize_num_method!(isize, visit_isize, from_isize);
|
impl_deserialize_num_method!(isize, visit_isize, from_isize, Type::Isize);
|
||||||
impl_deserialize_num_method!(i8, visit_i8, from_i8);
|
impl_deserialize_num_method!(i8, visit_i8, from_i8, Type::I8);
|
||||||
impl_deserialize_num_method!(i16, visit_i16, from_i16);
|
impl_deserialize_num_method!(i16, visit_i16, from_i16, Type::I16);
|
||||||
impl_deserialize_num_method!(i32, visit_i32, from_i32);
|
impl_deserialize_num_method!(i32, visit_i32, from_i32, Type::I32);
|
||||||
impl_deserialize_num_method!(i64, visit_i64, from_i64);
|
impl_deserialize_num_method!(i64, visit_i64, from_i64, Type::I64);
|
||||||
impl_deserialize_num_method!(usize, visit_usize, from_usize);
|
impl_deserialize_num_method!(usize, visit_usize, from_usize, Type::Usize);
|
||||||
impl_deserialize_num_method!(u8, visit_u8, from_u8);
|
impl_deserialize_num_method!(u8, visit_u8, from_u8, Type::U8);
|
||||||
impl_deserialize_num_method!(u16, visit_u16, from_u16);
|
impl_deserialize_num_method!(u16, visit_u16, from_u16, Type::U16);
|
||||||
impl_deserialize_num_method!(u32, visit_u32, from_u32);
|
impl_deserialize_num_method!(u32, visit_u32, from_u32, Type::U32);
|
||||||
impl_deserialize_num_method!(u64, visit_u64, from_u64);
|
impl_deserialize_num_method!(u64, visit_u64, from_u64, Type::U64);
|
||||||
impl_deserialize_num_method!(f32, visit_f32, from_f32);
|
impl_deserialize_num_method!(f32, visit_f32, from_f32, Type::F32);
|
||||||
impl_deserialize_num_method!(f64, visit_f64, from_f64);
|
impl_deserialize_num_method!(f64, visit_f64, from_f64, Type::F64);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
|
fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
str::FromStr::from_str(v.trim()).or(Err(Error::syntax_error()))
|
str::FromStr::from_str(v.trim()).or(Err(Error::type_mismatch(Type::Str)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,12 +201,12 @@ impl Visitor for CharVisitor {
|
|||||||
let mut iter = v.chars();
|
let mut iter = v.chars();
|
||||||
if let Some(v) = iter.next() {
|
if let Some(v) = iter.next() {
|
||||||
if iter.next().is_some() {
|
if iter.next().is_some() {
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Char))
|
||||||
} else {
|
} else {
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(Error::end_of_stream_error())
|
Err(Error::end_of_stream())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,7 +244,7 @@ impl Visitor for StringVisitor {
|
|||||||
{
|
{
|
||||||
match str::from_utf8(v) {
|
match str::from_utf8(v) {
|
||||||
Ok(s) => Ok(s.to_string()),
|
Ok(s) => Ok(s.to_string()),
|
||||||
Err(_) => Err(Error::syntax_error()),
|
Err(_) => Err(Error::type_mismatch(Type::String)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +253,7 @@ impl Visitor for StringVisitor {
|
|||||||
{
|
{
|
||||||
match String::from_utf8(v) {
|
match String::from_utf8(v) {
|
||||||
Ok(s) => Ok(s),
|
Ok(s) => Ok(s),
|
||||||
Err(_) => Err(Error::syntax_error()),
|
Err(_) => Err(Error::type_mismatch(Type::String)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -495,7 +496,7 @@ macro_rules! array_impls {
|
|||||||
$(
|
$(
|
||||||
let $name = match try!(visitor.visit()) {
|
let $name = match try!(visitor.visit()) {
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
None => { return Err(Error::end_of_stream_error()); }
|
None => { return Err(Error::end_of_stream()); }
|
||||||
};
|
};
|
||||||
)+;
|
)+;
|
||||||
|
|
||||||
@@ -565,12 +566,21 @@ array_impls! {
|
|||||||
|
|
||||||
macro_rules! tuple_impls {
|
macro_rules! tuple_impls {
|
||||||
() => {};
|
() => {};
|
||||||
($($visitor:ident => ($($name:ident),+),)+) => {
|
($($len:expr => $visitor:ident => ($($name:ident),+),)+) => {
|
||||||
$(
|
$(
|
||||||
struct $visitor<$($name,)+> {
|
pub struct $visitor<$($name,)+> {
|
||||||
marker: PhantomData<($($name,)+)>,
|
marker: PhantomData<($($name,)+)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
$($name: Deserialize,)+
|
||||||
|
> $visitor<$($name,)+> {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
$visitor { marker: PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
$($name: Deserialize,)+
|
$($name: Deserialize,)+
|
||||||
> Visitor for $visitor<$($name,)+> {
|
> Visitor for $visitor<$($name,)+> {
|
||||||
@@ -584,7 +594,7 @@ macro_rules! tuple_impls {
|
|||||||
$(
|
$(
|
||||||
let $name = match try!(visitor.visit()) {
|
let $name = match try!(visitor.visit()) {
|
||||||
Some(value) => value,
|
Some(value) => value,
|
||||||
None => { return Err(Error::end_of_stream_error()); }
|
None => { return Err(Error::end_of_stream()); }
|
||||||
};
|
};
|
||||||
)+;
|
)+;
|
||||||
|
|
||||||
@@ -601,7 +611,7 @@ macro_rules! tuple_impls {
|
|||||||
fn deserialize<D>(deserializer: &mut D) -> Result<($($name,)+), D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<($($name,)+), D::Error>
|
||||||
where D: Deserializer,
|
where D: Deserializer,
|
||||||
{
|
{
|
||||||
deserializer.visit_tuple($visitor { marker: PhantomData })
|
deserializer.visit_tuple($len, $visitor::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
@@ -609,18 +619,18 @@ macro_rules! tuple_impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tuple_impls! {
|
tuple_impls! {
|
||||||
TupleVisitor1 => (T0),
|
1 => TupleVisitor1 => (T0),
|
||||||
TupleVisitor2 => (T0, T1),
|
2 => TupleVisitor2 => (T0, T1),
|
||||||
TupleVisitor3 => (T0, T1, T2),
|
3 => TupleVisitor3 => (T0, T1, T2),
|
||||||
TupleVisitor4 => (T0, T1, T2, T3),
|
4 => TupleVisitor4 => (T0, T1, T2, T3),
|
||||||
TupleVisitor5 => (T0, T1, T2, T3, T4),
|
5 => TupleVisitor5 => (T0, T1, T2, T3, T4),
|
||||||
TupleVisitor6 => (T0, T1, T2, T3, T4, T5),
|
6 => TupleVisitor6 => (T0, T1, T2, T3, T4, T5),
|
||||||
TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6),
|
7 => TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6),
|
||||||
TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7),
|
8 => TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7),
|
||||||
TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8),
|
9 => TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8),
|
||||||
TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9),
|
10 => TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9),
|
||||||
TupleVisitor11 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10),
|
11 => TupleVisitor11 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10),
|
||||||
TupleVisitor12 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11),
|
12 => TupleVisitor12 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11),
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -839,7 +849,7 @@ impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable +
|
|||||||
fn deserialize<D>(deserializer: &mut D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
|
fn deserialize<D>(deserializer: &mut D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
|
||||||
let value = try!(Deserialize::deserialize(deserializer));
|
let value = try!(Deserialize::deserialize(deserializer));
|
||||||
if value == Zero::zero() {
|
if value == Zero::zero() {
|
||||||
return Err(Error::syntax_error())
|
return Err(Error::syntax("expected a non-zero value"))
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
Ok(NonZero::new(value))
|
Ok(NonZero::new(value))
|
||||||
@@ -849,126 +859,85 @@ impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable +
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
|
impl<T, E> Deserialize for Result<T, E> where T: Deserialize, E: Deserialize {
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Result<T, E>, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Result<T, E>, D::Error>
|
||||||
where D: Deserializer {
|
where D: Deserializer {
|
||||||
enum Field {
|
enum Field {
|
||||||
Field0,
|
Ok,
|
||||||
Field1,
|
Err,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserialize for Field {
|
impl Deserialize for Field {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
|
fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
|
||||||
where D: Deserializer {
|
where D: Deserializer
|
||||||
struct FieldVisitor<D> {
|
{
|
||||||
phantom: PhantomData<D>,
|
struct FieldVisitor;
|
||||||
}
|
|
||||||
|
|
||||||
impl<D> ::de::Visitor for FieldVisitor<D> where D: Deserializer {
|
impl ::de::Visitor for FieldVisitor {
|
||||||
type Value = Field;
|
type Value = Field;
|
||||||
|
|
||||||
|
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E> where E: Error {
|
||||||
|
match value {
|
||||||
|
0 => Ok(Field::Ok),
|
||||||
|
1 => Ok(Field::Err),
|
||||||
|
_ => Err(Error::unknown_field(&value.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E> where E: Error {
|
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E> where E: Error {
|
||||||
match value {
|
match value {
|
||||||
"Ok" => Ok(Field::Field0),
|
"Ok" => Ok(Field::Ok),
|
||||||
"Err" => Ok(Field::Field1),
|
"Err" => Ok(Field::Err),
|
||||||
_ => Err(Error::unknown_field_error(value)),
|
_ => Err(Error::unknown_field(value)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bytes<E>(&mut self, value: &[u8]) -> Result<Field, E> where E: Error {
|
fn visit_bytes<E>(&mut self, value: &[u8]) -> Result<Field, E> where E: Error {
|
||||||
match str::from_utf8(value) {
|
match value {
|
||||||
Ok(s) => self.visit_str(s),
|
b"Ok" => Ok(Field::Ok),
|
||||||
_ => Err(Error::syntax_error()),
|
b"Err" => Ok(Field::Err),
|
||||||
|
_ => {
|
||||||
|
match str::from_utf8(value) {
|
||||||
|
Ok(value) => Err(Error::unknown_field(value)),
|
||||||
|
Err(_) => Err(Error::type_mismatch(Type::String)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.visit(FieldVisitor::<D> {
|
deserializer.visit(FieldVisitor)
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Visitor<D, T, E>(PhantomData<D>, PhantomData<T>, PhantomData<E>)
|
struct Visitor<T, E>(PhantomData<Result<T, E>>);
|
||||||
where D: Deserializer, T: Deserialize, E: Deserialize;
|
|
||||||
|
|
||||||
impl<D, T, E> EnumVisitor for Visitor<D, T, E> where D: Deserializer,
|
impl<T, E> EnumVisitor for Visitor<T, E>
|
||||||
T: Deserialize,
|
where T: Deserialize,
|
||||||
E: Deserialize {
|
E: Deserialize
|
||||||
|
{
|
||||||
type Value = Result<T, E>;
|
type Value = Result<T, E>;
|
||||||
|
|
||||||
fn visit<V>(&mut self, mut visitor: V) -> Result<Result<T, E>, V::Error>
|
fn visit<V>(&mut self, mut visitor: V) -> Result<Result<T, E>, V::Error>
|
||||||
where V: VariantVisitor {
|
where V: VariantVisitor
|
||||||
match match visitor.visit_variant() {
|
{
|
||||||
Ok(val) => val,
|
match try!(visitor.visit_variant()) {
|
||||||
Err(err) => return Err(From::from(err)),
|
Field::Ok => {
|
||||||
} {
|
let value = try!(visitor.visit_newtype());
|
||||||
Field::Field0 => {
|
Ok(Ok(value))
|
||||||
struct Visitor<D, T, E>(PhantomData<D>, PhantomData<T>, PhantomData<E>)
|
|
||||||
where D: Deserializer,
|
|
||||||
T: Deserialize,
|
|
||||||
E: Deserialize;
|
|
||||||
impl <D, T, E> ::de::Visitor for Visitor<D, T, E> where D: Deserializer,
|
|
||||||
T: Deserialize,
|
|
||||||
E: Deserialize {
|
|
||||||
type Value = Result<T, E>;
|
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, mut visitor: V)
|
|
||||||
-> Result<Result<T, E>, V::Error> where V: SeqVisitor {
|
|
||||||
let field0 = match match visitor.visit() {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(err) => return Err(From::from(err)),
|
|
||||||
} {
|
|
||||||
Some(value) => value,
|
|
||||||
None => return Err(Error::end_of_stream_error()),
|
|
||||||
};
|
|
||||||
match visitor.end() {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(err) => return Err(From::from(err)),
|
|
||||||
};
|
|
||||||
Ok(Result::Ok(field0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visitor.visit_seq(Visitor::<D, T, E>(PhantomData,
|
|
||||||
PhantomData,
|
|
||||||
PhantomData))
|
|
||||||
}
|
}
|
||||||
Field::Field1 => {
|
Field::Err => {
|
||||||
struct Visitor<D, T, E>(PhantomData<D>, PhantomData<T>, PhantomData<E>)
|
let value = try!(visitor.visit_newtype());
|
||||||
where D: Deserializer,
|
Ok(Err(value))
|
||||||
T: Deserialize,
|
|
||||||
E: Deserialize;
|
|
||||||
impl <D, T, E> ::de::Visitor for Visitor<D, T, E> where D: Deserializer,
|
|
||||||
T: Deserialize,
|
|
||||||
E: Deserialize {
|
|
||||||
type Value = Result<T, E>;
|
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, mut visitor: V)
|
|
||||||
-> Result<Result<T, E>, V::Error> where V: SeqVisitor {
|
|
||||||
let field0 = match match visitor.visit() {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(err) => return Err(From::from(err)),
|
|
||||||
} {
|
|
||||||
Some(value) => value,
|
|
||||||
None => return Err(Error::end_of_stream_error()),
|
|
||||||
};
|
|
||||||
match visitor.end() {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(err) => return Err(From::from(err)),
|
|
||||||
};
|
|
||||||
Ok(Result::Err(field0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visitor.visit_seq(Visitor::<D, T, E>(PhantomData,
|
|
||||||
PhantomData,
|
|
||||||
PhantomData))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.visit_enum("Result",
|
const VARIANTS: &'static [&'static str] = &["Ok", "Err"];
|
||||||
Visitor::<D, T, E>(PhantomData, PhantomData, PhantomData))
|
|
||||||
|
deserializer.visit_enum("Result", VARIANTS, Visitor(PhantomData))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+149
-46
@@ -5,14 +5,65 @@ pub mod value;
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub trait Error {
|
/// `Error` is a trait that allows a `Deserialize` to generically create a
|
||||||
fn syntax_error() -> Self;
|
/// `Deserializer` error.
|
||||||
|
pub trait Error: Sized {
|
||||||
|
/// Raised when there is general error when deserializing a type.
|
||||||
|
fn syntax(msg: &str) -> Self;
|
||||||
|
|
||||||
fn end_of_stream_error() -> Self;
|
/// Raised when a fixed sized sequence or map was passed in the wrong amount of arguments.
|
||||||
|
fn length_mismatch(_len: usize) -> Self {
|
||||||
|
Error::syntax("incorrect length")
|
||||||
|
}
|
||||||
|
|
||||||
fn unknown_field_error(field: &str) -> Self;
|
/// Raised when a `Deserialize` was passed an incorrect type.
|
||||||
|
fn type_mismatch(_type: Type) -> Self {
|
||||||
|
Error::syntax("incorrect type")
|
||||||
|
}
|
||||||
|
|
||||||
fn missing_field_error(field: &'static str) -> Self;
|
/// Raised when a `Deserialize` type unexpectedly hit the end of the stream.
|
||||||
|
fn end_of_stream() -> Self;
|
||||||
|
|
||||||
|
/// Raised when a `Deserialize` struct type received an unexpected struct field.
|
||||||
|
fn unknown_field(field: &str) -> Self;
|
||||||
|
|
||||||
|
/// Raised when a `Deserialize` struct type did not receive a field.
|
||||||
|
fn missing_field(field: &'static str) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Type` represents all the primitive types that can be deserialized. This is used by
|
||||||
|
/// `Error::kind_mismatch`.
|
||||||
|
pub enum Type {
|
||||||
|
Bool,
|
||||||
|
Usize,
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
Isize,
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
Char,
|
||||||
|
Str,
|
||||||
|
String,
|
||||||
|
Unit,
|
||||||
|
Option,
|
||||||
|
Seq,
|
||||||
|
Map,
|
||||||
|
UnitStruct,
|
||||||
|
NewtypeStruct,
|
||||||
|
TupleStruct,
|
||||||
|
Struct,
|
||||||
|
Tuple,
|
||||||
|
Enum,
|
||||||
|
StructVariant,
|
||||||
|
TupleVariant,
|
||||||
|
UnitVariant,
|
||||||
|
Bytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -208,28 +259,47 @@ pub trait Deserializer {
|
|||||||
self.visit(visitor)
|
self.visit(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method hints that the `Deserialize` type is expecting a named unit. This allows
|
/// This method hints that the `Deserialize` type is expecting a unit struct. This allows
|
||||||
/// deserializers to a named unit that aren't tagged as a named unit.
|
/// deserializers to a unit struct that aren't tagged as a unit struct.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_unit<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
|
fn visit_unit_struct<V>(&mut self,
|
||||||
|
_name: &'static str,
|
||||||
|
visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where V: Visitor,
|
where V: Visitor,
|
||||||
{
|
{
|
||||||
self.visit(visitor)
|
self.visit_unit(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method hints that the `Deserialize` type is expecting a named sequence.
|
/// This method hints that the `Deserialize` type is expecting a newtype struct. This allows
|
||||||
/// This allows deserializers to parse sequences that aren't tagged as sequences.
|
/// deserializers to a newtype struct that aren't tagged as a newtype struct.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_seq<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
|
fn visit_newtype_struct<V>(&mut self,
|
||||||
|
name: &'static str,
|
||||||
|
visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where V: Visitor,
|
where V: Visitor,
|
||||||
{
|
{
|
||||||
self.visit_seq(visitor)
|
self.visit_tuple_struct(name, 1, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method hints that the `Deserialize` type is expecting a named map. This allows
|
/// 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 visit_tuple_struct<V>(&mut self,
|
||||||
|
_name: &'static str,
|
||||||
|
len: usize,
|
||||||
|
visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where V: Visitor,
|
||||||
|
{
|
||||||
|
self.visit_tuple(len, visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method hints that the `Deserialize` type is expecting a struct. This allows
|
||||||
/// deserializers to parse sequences that aren't tagged as maps.
|
/// deserializers to parse sequences that aren't tagged as maps.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_map<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
|
fn visit_struct<V>(&mut self,
|
||||||
|
_name: &'static str,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where V: Visitor,
|
where V: Visitor,
|
||||||
{
|
{
|
||||||
self.visit_map(visitor)
|
self.visit_map(visitor)
|
||||||
@@ -238,20 +308,23 @@ pub trait Deserializer {
|
|||||||
/// This method hints that the `Deserialize` type is expecting a tuple value. This allows
|
/// 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.
|
/// deserializers that provide a custom tuple serialization to properly deserialize the type.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_tuple<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
|
fn visit_tuple<V>(&mut self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where V: Visitor,
|
where V: Visitor,
|
||||||
{
|
{
|
||||||
self.visit(visitor)
|
self.visit_seq(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method hints that the `Deserialize` type is expecting an enum value. This allows
|
/// 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
|
/// deserializers that provide a custom enumeration serialization to properly deserialize the
|
||||||
/// type.
|
/// type.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum<V>(&mut self, _enum: &str, _visitor: V) -> Result<V::Value, Self::Error>
|
fn visit_enum<V>(&mut self,
|
||||||
|
_enum: &'static str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
_visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where V: EnumVisitor,
|
where V: EnumVisitor,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::syntax("expected an enum"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method hints that the `Deserialize` type is expecting a `Vec<u8>`. This allows
|
/// This method hints that the `Deserialize` type is expecting a `Vec<u8>`. This allows
|
||||||
@@ -261,7 +334,7 @@ pub trait Deserializer {
|
|||||||
fn visit_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
|
fn visit_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where V: Visitor,
|
where V: Visitor,
|
||||||
{
|
{
|
||||||
self.visit(visitor)
|
self.visit_seq(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify a format string for the deserializer.
|
/// Specify a format string for the deserializer.
|
||||||
@@ -282,7 +355,7 @@ pub trait Visitor {
|
|||||||
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,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Bool))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_isize<E>(&mut self, v: isize) -> Result<Self::Value, E>
|
fn visit_isize<E>(&mut self, v: isize) -> Result<Self::Value, E>
|
||||||
@@ -312,7 +385,7 @@ pub trait Visitor {
|
|||||||
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,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::I64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_usize<E>(&mut self, v: usize) -> Result<Self::Value, E>
|
fn visit_usize<E>(&mut self, v: usize) -> Result<Self::Value, E>
|
||||||
@@ -342,7 +415,7 @@ pub trait Visitor {
|
|||||||
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,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::U64))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_f32<E>(&mut self, v: f32) -> Result<Self::Value, E>
|
fn visit_f32<E>(&mut self, v: f32) -> Result<Self::Value, E>
|
||||||
@@ -354,7 +427,7 @@ pub trait Visitor {
|
|||||||
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,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::F64))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -369,7 +442,7 @@ pub trait Visitor {
|
|||||||
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,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Str))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -382,11 +455,11 @@ pub trait Visitor {
|
|||||||
fn visit_unit<E>(&mut self) -> Result<Self::Value, E>
|
fn visit_unit<E>(&mut self) -> Result<Self::Value, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_unit<E>(&mut self, _name: &str) -> Result<Self::Value, E>
|
fn visit_unit_struct<E>(&mut self, _name: &'static str) -> Result<Self::Value, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
self.visit_unit()
|
self.visit_unit()
|
||||||
@@ -395,31 +468,37 @@ pub trait Visitor {
|
|||||||
fn visit_none<E>(&mut self) -> Result<Self::Value, E>
|
fn visit_none<E>(&mut self) -> Result<Self::Value, E>
|
||||||
where E: Error,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Option))
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
where D: Deserializer,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Option))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_newtype_struct<D>(&mut self, _deserializer: &mut D) -> Result<Self::Value, D::Error>
|
||||||
|
where D: Deserializer,
|
||||||
|
{
|
||||||
|
Err(Error::type_mismatch(Type::NewtypeStruct))
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
where V: SeqVisitor,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Seq))
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
where V: MapVisitor,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Map))
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
where E: Error,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::Bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<Self::Value, E>
|
fn visit_byte_buf<E>(&mut self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||||
@@ -501,7 +580,7 @@ pub trait MapVisitor {
|
|||||||
fn missing_field<V>(&mut self, field: &'static str) -> Result<V, Self::Error>
|
fn missing_field<V>(&mut self, field: &'static str) -> Result<V, Self::Error>
|
||||||
where V: Deserialize,
|
where V: Deserialize,
|
||||||
{
|
{
|
||||||
Err(Error::missing_field_error(field))
|
Err(Error::missing_field(field))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,21 +644,35 @@ pub trait VariantVisitor {
|
|||||||
|
|
||||||
/// `visit_unit` is called when deserializing a variant with no values.
|
/// `visit_unit` is called when deserializing a variant with no values.
|
||||||
fn visit_unit(&mut self) -> Result<(), Self::Error> {
|
fn visit_unit(&mut self) -> Result<(), Self::Error> {
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::UnitVariant))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `visit_seq` is called when deserializing a tuple-like variant.
|
/// `visit_newtype` is called when deserializing a variant with a single value. By default this
|
||||||
fn visit_seq<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
|
/// uses the `visit_tuple` method to deserialize the value.
|
||||||
where V: Visitor
|
#[inline]
|
||||||
|
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
|
||||||
|
where T: Deserialize,
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
let (value,) = try!(self.visit_tuple(1, impls::TupleVisitor1::new()));
|
||||||
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `visit_map` is called when deserializing a struct-like variant.
|
/// `visit_tuple` is called when deserializing a tuple-like variant.
|
||||||
fn visit_map<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
|
fn visit_tuple<V>(&mut self,
|
||||||
|
_len: usize,
|
||||||
|
_visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where V: Visitor
|
where V: Visitor
|
||||||
{
|
{
|
||||||
Err(Error::syntax_error())
|
Err(Error::type_mismatch(Type::TupleVariant))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `visit_struct` is called when deserializing a struct-like variant.
|
||||||
|
fn visit_struct<V>(&mut self,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
_visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where V: Visitor
|
||||||
|
{
|
||||||
|
Err(Error::type_mismatch(Type::StructVariant))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,16 +689,26 @@ impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
|
|||||||
(**self).visit_unit()
|
(**self).visit_unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
|
fn visit_newtype<D>(&mut self) -> Result<D, T::Error>
|
||||||
where V: Visitor,
|
where D: Deserialize,
|
||||||
{
|
{
|
||||||
(**self).visit_seq(visitor)
|
(**self).visit_newtype()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
|
fn visit_tuple<V>(&mut self,
|
||||||
|
len: usize,
|
||||||
|
visitor: V) -> Result<V::Value, T::Error>
|
||||||
where V: Visitor,
|
where V: Visitor,
|
||||||
{
|
{
|
||||||
(**self).visit_map(visitor)
|
(**self).visit_tuple(len, visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_struct<V>(&mut self,
|
||||||
|
fields: &'static [&'static str],
|
||||||
|
visitor: V) -> Result<V::Value, T::Error>
|
||||||
|
where V: Visitor,
|
||||||
|
{
|
||||||
|
(**self).visit_struct(fields, visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-14
@@ -24,10 +24,10 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl de::Error for Error {
|
impl de::Error for Error {
|
||||||
fn syntax_error() -> Self { Error::SyntaxError }
|
fn syntax(_: &str) -> Self { Error::SyntaxError }
|
||||||
fn end_of_stream_error() -> Self { Error::EndOfStreamError }
|
fn end_of_stream() -> Self { Error::EndOfStreamError }
|
||||||
fn unknown_field_error(field: &str) -> Self { Error::UnknownFieldError(field.to_string()) }
|
fn unknown_field(field: &str) -> Self { Error::UnknownFieldError(String::from(field)) }
|
||||||
fn missing_field_error(field: &'static str) -> Self { Error::MissingFieldError(field) }
|
fn missing_field(field: &'static str) -> Self { Error::MissingFieldError(field) }
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -89,7 +89,7 @@ macro_rules! primitive_deserializer {
|
|||||||
{
|
{
|
||||||
match self.0.take() {
|
match self.0.take() {
|
||||||
Some(v) => visitor.$method(v),
|
Some(v) => visitor.$method(v),
|
||||||
None => Err(de::Error::end_of_stream_error()),
|
None => Err(de::Error::end_of_stream()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,11 +132,14 @@ impl<'a> de::Deserializer for StrDeserializer<'a> {
|
|||||||
{
|
{
|
||||||
match self.0.take() {
|
match self.0.take() {
|
||||||
Some(v) => visitor.visit_str(v),
|
Some(v) => visitor.visit_str(v),
|
||||||
None => Err(de::Error::end_of_stream_error()),
|
None => Err(de::Error::end_of_stream()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_enum<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
mut visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::EnumVisitor,
|
where V: de::EnumVisitor,
|
||||||
{
|
{
|
||||||
visitor.visit(self)
|
visitor.visit(self)
|
||||||
@@ -178,11 +181,14 @@ impl de::Deserializer for StringDeserializer {
|
|||||||
{
|
{
|
||||||
match self.0.take() {
|
match self.0.take() {
|
||||||
Some(string) => visitor.visit_string(string),
|
Some(string) => visitor.visit_string(string),
|
||||||
None => Err(de::Error::end_of_stream_error()),
|
None => Err(de::Error::end_of_stream()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_enum<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
mut visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::EnumVisitor,
|
where V: de::EnumVisitor,
|
||||||
{
|
{
|
||||||
visitor.visit(self)
|
visitor.visit(self)
|
||||||
@@ -255,7 +261,7 @@ impl<I, T> de::SeqVisitor for SeqDeserializer<I>
|
|||||||
if self.len == 0 {
|
if self.len == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(de::Error::end_of_stream_error())
|
Err(de::Error::length_mismatch(self.len))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,7 +374,7 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
|
|||||||
let mut de = value.into_deserializer();
|
let mut de = value.into_deserializer();
|
||||||
de::Deserialize::deserialize(&mut de)
|
de::Deserialize::deserialize(&mut de)
|
||||||
}
|
}
|
||||||
None => Err(de::Error::syntax_error())
|
None => Err(de::Error::syntax("expected a map value"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,7 +382,7 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
|
|||||||
if self.len == 0 {
|
if self.len == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(de::Error::end_of_stream_error())
|
Err(de::Error::length_mismatch(self.len))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,7 +438,7 @@ impl<'a> de::Deserializer for BytesDeserializer<'a> {
|
|||||||
{
|
{
|
||||||
match self.0.take() {
|
match self.0.take() {
|
||||||
Some(bytes) => visitor.visit_bytes(bytes),
|
Some(bytes) => visitor.visit_bytes(bytes),
|
||||||
None => Err(de::Error::end_of_stream_error()),
|
None => Err(de::Error::end_of_stream()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,7 +465,7 @@ impl de::Deserializer for ByteBufDeserializer {
|
|||||||
{
|
{
|
||||||
match self.0.take() {
|
match self.0.take() {
|
||||||
Some(bytes) => visitor.visit_byte_buf(bytes),
|
Some(bytes) => visitor.visit_byte_buf(bytes),
|
||||||
None => Err(de::Error::end_of_stream_error()),
|
None => Err(de::Error::end_of_stream()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -5,7 +5,7 @@
|
|||||||
//! handshake protocol between serializers and serializees can be completely optimized away,
|
//! 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
|
//! leaving serde to perform roughly the same speed as a hand written serializer for a specific
|
||||||
//! type.
|
//! type.
|
||||||
#![doc(html_root_url="http://erickt.github.io/rust-serde")]
|
#![doc(html_root_url="https://serde-rs.github.io/serde/serde")]
|
||||||
#![cfg_attr(feature = "nightly", feature(collections, core, enumset, nonzero, step_trait, vecmap, zero_one))]
|
#![cfg_attr(feature = "nightly", feature(collections, core, enumset, nonzero, step_trait, vecmap, zero_one))]
|
||||||
|
|
||||||
extern crate num;
|
extern crate num;
|
||||||
@@ -22,5 +22,4 @@ pub use de::{Deserialize, Deserializer, Error};
|
|||||||
pub mod bytes;
|
pub mod bytes;
|
||||||
pub mod de;
|
pub mod de;
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
pub mod json;
|
|
||||||
pub mod ser;
|
pub mod ser;
|
||||||
|
|||||||
+26
-81
@@ -15,7 +15,6 @@ use std::collections::vec_map::VecMap;
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::marker::PhantomData;
|
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
use std::num;
|
use std::num;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
@@ -98,6 +97,26 @@ 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.visit_seq_elt(value));
|
||||||
|
Ok(Some(()))
|
||||||
|
}
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn len(&self) -> Option<usize> {
|
||||||
|
Some(if self.is_some() { 1 } else { 0 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub struct SeqIteratorVisitor<Iter> {
|
pub struct SeqIteratorVisitor<Iter> {
|
||||||
@@ -127,8 +146,8 @@ impl<T, Iter> SeqVisitor for SeqIteratorVisitor<Iter>
|
|||||||
{
|
{
|
||||||
match self.iter.next() {
|
match self.iter.next() {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
let value = try!(serializer.visit_seq_elt(value));
|
try!(serializer.visit_seq_elt(value));
|
||||||
Ok(Some(value))
|
Ok(Some(()))
|
||||||
}
|
}
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
@@ -612,85 +631,11 @@ impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, {
|
|||||||
impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
|
impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
|
||||||
match *self {
|
match *self {
|
||||||
Result::Ok(ref field0) => {
|
Result::Ok(ref value) => {
|
||||||
struct Visitor<'a, T, E> where T: Serialize + 'a, E: Serialize + 'a {
|
serializer.visit_newtype_variant("Result", 0, "Ok", value)
|
||||||
state: usize,
|
|
||||||
value: (&'a T,),
|
|
||||||
_structure_ty: PhantomData<&'a Result<T, E>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, E> SeqVisitor for Visitor<'a, T, E> where T: Serialize + 'a,
|
|
||||||
E: Serialize + 'a {
|
|
||||||
#[inline]
|
|
||||||
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
|
|
||||||
where S: Serializer {
|
|
||||||
match self.state {
|
|
||||||
0 => {
|
|
||||||
self.state += 1;
|
|
||||||
let v = match serializer.visit_seq_elt(&self.value.0) {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(err) => return Err(From::from(err)),
|
|
||||||
};
|
|
||||||
Ok(Some(v))
|
|
||||||
}
|
|
||||||
_ => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn len(&self) -> Option<usize> {
|
|
||||||
Some(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let field0: &T = field0;
|
|
||||||
let data: PhantomData<&Result<&T,E>> = PhantomData;
|
|
||||||
let visitor = Visitor {
|
|
||||||
value: (&field0,),
|
|
||||||
state: 0,
|
|
||||||
_structure_ty: data
|
|
||||||
};
|
|
||||||
serializer.visit_enum_seq("Result", "Ok", visitor)
|
|
||||||
}
|
}
|
||||||
Result::Err(ref field0) => {
|
Result::Err(ref value) => {
|
||||||
struct Visitor<'a, T, E> where T: Serialize + 'a, E: Serialize + 'a {
|
serializer.visit_newtype_variant("Result", 1, "Err", value)
|
||||||
state: usize,
|
|
||||||
value: (&'a E,),
|
|
||||||
_structure_ty: PhantomData<&'a Result<T, E>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, E> SeqVisitor for Visitor<'a, T, E> where T: Serialize + 'a,
|
|
||||||
E: Serialize + 'a {
|
|
||||||
#[inline]
|
|
||||||
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
|
|
||||||
where S: Serializer {
|
|
||||||
match self.state {
|
|
||||||
0 => {
|
|
||||||
self.state += 1;
|
|
||||||
let v = match serializer.visit_seq_elt(&self.value.0) {
|
|
||||||
Ok(val) => val,
|
|
||||||
Err(err) => return Err(From::from(err)),
|
|
||||||
};
|
|
||||||
Ok(Some(v))
|
|
||||||
}
|
|
||||||
_ => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn len(&self) -> Option<usize> {
|
|
||||||
Some(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let field0: &E = field0;
|
|
||||||
let data: PhantomData<&Result<T,&E>> = PhantomData;
|
|
||||||
let visitor = Visitor {
|
|
||||||
value: (&field0,),
|
|
||||||
state: 0,
|
|
||||||
_structure_ty: data
|
|
||||||
};
|
|
||||||
serializer.visit_enum_seq("Result", "Err", visitor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+65
-30
@@ -113,17 +113,48 @@ pub trait Serializer {
|
|||||||
fn visit_unit(&mut self) -> Result<(), Self::Error>;
|
fn visit_unit(&mut self) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_unit(&mut self, _name: &str) -> Result<(), Self::Error> {
|
fn visit_unit_struct(&mut self, _name: &'static str) -> Result<(), Self::Error> {
|
||||||
self.visit_unit()
|
self.visit_unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_unit(&mut self,
|
fn visit_unit_variant(&mut self,
|
||||||
_name: &str,
|
_name: &'static str,
|
||||||
_variant: &str) -> Result<(), Self::Error> {
|
_variant_index: usize,
|
||||||
|
_variant: &'static str) -> Result<(), Self::Error> {
|
||||||
self.visit_unit()
|
self.visit_unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The `visit_newtype_struct` 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 visit_newtype_struct<T>(&mut self,
|
||||||
|
name: &'static str,
|
||||||
|
value: T) -> Result<(), Self::Error>
|
||||||
|
where T: Serialize,
|
||||||
|
{
|
||||||
|
self.visit_tuple_struct(name, Some(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The `visit_newtype_variant` 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 visit_newtype_variant<T>(&mut self,
|
||||||
|
name: &'static str,
|
||||||
|
variant_index: usize,
|
||||||
|
variant: &'static str,
|
||||||
|
value: T) -> Result<(), Self::Error>
|
||||||
|
where T: Serialize,
|
||||||
|
{
|
||||||
|
self.visit_tuple_variant(
|
||||||
|
name,
|
||||||
|
variant_index,
|
||||||
|
variant,
|
||||||
|
Some(value))
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_none(&mut self) -> Result<(), Self::Error>;
|
fn visit_none(&mut self) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error>
|
fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error>
|
||||||
@@ -150,36 +181,37 @@ pub trait Serializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_seq<V>(&mut self,
|
fn visit_tuple_struct<V>(&mut self,
|
||||||
_name: &'static str,
|
_name: &'static str,
|
||||||
visitor: V) -> Result<(), Self::Error>
|
visitor: V) -> Result<(), Self::Error>
|
||||||
where V: SeqVisitor,
|
where V: SeqVisitor,
|
||||||
{
|
{
|
||||||
self.visit_tuple(visitor)
|
self.visit_tuple(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
|
fn visit_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
|
||||||
where T: Serialize
|
where T: Serialize
|
||||||
{
|
{
|
||||||
self.visit_tuple_elt(value)
|
self.visit_tuple_elt(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_seq<V>(&mut self,
|
fn visit_tuple_variant<V>(&mut self,
|
||||||
_name: &'static str,
|
_name: &'static str,
|
||||||
_variant: &'static str,
|
_variant_index: usize,
|
||||||
visitor: V) -> Result<(), Self::Error>
|
variant: &'static str,
|
||||||
|
visitor: V) -> Result<(), Self::Error>
|
||||||
where V: SeqVisitor,
|
where V: SeqVisitor,
|
||||||
{
|
{
|
||||||
self.visit_tuple(visitor)
|
self.visit_tuple_struct(variant, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
|
fn visit_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
|
||||||
where T: Serialize
|
where T: Serialize
|
||||||
{
|
{
|
||||||
self.visit_tuple_elt(value)
|
self.visit_tuple_struct_elt(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
|
fn visit_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
|
||||||
@@ -190,38 +222,41 @@ pub trait Serializer {
|
|||||||
V: Serialize;
|
V: Serialize;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_map<V>(&mut self,
|
fn visit_struct<V>(&mut self,
|
||||||
_name: &'static str,
|
_name: &'static str,
|
||||||
visitor: V) -> Result<(), Self::Error>
|
visitor: V) -> Result<(), Self::Error>
|
||||||
where V: MapVisitor,
|
where V: MapVisitor,
|
||||||
{
|
{
|
||||||
self.visit_map(visitor)
|
self.visit_map(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_named_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
|
fn visit_struct_elt<V>(&mut self,
|
||||||
where K: Serialize,
|
key: &'static str,
|
||||||
V: Serialize,
|
value: V) -> Result<(), Self::Error>
|
||||||
|
where V: Serialize,
|
||||||
{
|
{
|
||||||
self.visit_map_elt(key, value)
|
self.visit_map_elt(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_map<V>(&mut self,
|
fn visit_struct_variant<V>(&mut self,
|
||||||
_name: &'static str,
|
_name: &'static str,
|
||||||
variant: &'static str,
|
_variant_index: usize,
|
||||||
visitor: V) -> Result<(), Self::Error>
|
variant: &'static str,
|
||||||
|
visitor: V) -> Result<(), Self::Error>
|
||||||
where V: MapVisitor,
|
where V: MapVisitor,
|
||||||
{
|
{
|
||||||
self.visit_named_map(variant, visitor)
|
self.visit_struct(variant, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
|
fn visit_struct_variant_elt<V>(&mut self,
|
||||||
where K: Serialize,
|
key: &'static str,
|
||||||
V: Serialize,
|
value: V) -> Result<(), Self::Error>
|
||||||
|
where V: Serialize,
|
||||||
{
|
{
|
||||||
self.visit_named_map_elt(key, value)
|
self.visit_struct_elt(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specify a format string for the serializer.
|
/// Specify a format string for the serializer.
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_codegen"
|
name = "serde_codegen"
|
||||||
version = "0.4.3"
|
version = "0.5.1"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Macros to auto-generate implementations for the serde framework"
|
description = "Macros to auto-generate implementations for the serde framework"
|
||||||
repository = "https://github.com/erickt/rust-serde"
|
repository = "https://github.com/serde-rs/serde"
|
||||||
|
documentation = "https://serde-rs.github.io/serde/serde_codegen/serde_codegen/index.html"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
keywords = ["serde", "serialization"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["with-syntex"]
|
default = ["with-syntex"]
|
||||||
nightly = ["quasi_macros"]
|
nightly = ["quasi_macros"]
|
||||||
with-syntex = ["quasi/with-syntex", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"]
|
with-syntex = ["quasi/with-syntex", "quasi_codegen", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
quasi_codegen = { verision = "*", optional = true }
|
quasi_codegen = { verision = "*", optional = true }
|
||||||
|
|||||||
@@ -16,15 +16,20 @@ pub enum FieldNames {
|
|||||||
|
|
||||||
/// Represents field attribute information
|
/// Represents field attribute information
|
||||||
pub struct FieldAttrs {
|
pub struct FieldAttrs {
|
||||||
|
skip_serializing_field: bool,
|
||||||
names: FieldNames,
|
names: FieldNames,
|
||||||
use_default: bool,
|
use_default: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FieldAttrs {
|
impl FieldAttrs {
|
||||||
|
|
||||||
/// Create a FieldAttr with a single default field name
|
/// Create a FieldAttr with a single default field name
|
||||||
pub fn new(default_value: bool, name: P<ast::Expr>) -> FieldAttrs {
|
pub fn new(
|
||||||
|
skip_serializing_field: bool,
|
||||||
|
default_value: bool,
|
||||||
|
name: P<ast::Expr>,
|
||||||
|
) -> FieldAttrs {
|
||||||
FieldAttrs {
|
FieldAttrs {
|
||||||
|
skip_serializing_field: skip_serializing_field,
|
||||||
names: FieldNames::Global(name),
|
names: FieldNames::Global(name),
|
||||||
use_default: default_value,
|
use_default: default_value,
|
||||||
}
|
}
|
||||||
@@ -32,12 +37,14 @@ impl FieldAttrs {
|
|||||||
|
|
||||||
/// Create a FieldAttr with format specific field names
|
/// Create a FieldAttr with format specific field names
|
||||||
pub fn new_with_formats(
|
pub fn new_with_formats(
|
||||||
|
skip_serializing_field: bool,
|
||||||
default_value: bool,
|
default_value: bool,
|
||||||
default_name: P<ast::Expr>,
|
default_name: P<ast::Expr>,
|
||||||
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
|
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
|
||||||
) -> FieldAttrs {
|
) -> FieldAttrs {
|
||||||
FieldAttrs {
|
FieldAttrs {
|
||||||
names: FieldNames::Format {
|
skip_serializing_field: skip_serializing_field,
|
||||||
|
names: FieldNames::Format {
|
||||||
formats: formats,
|
formats: formats,
|
||||||
default: default_name,
|
default: default_name,
|
||||||
},
|
},
|
||||||
@@ -105,4 +112,9 @@ impl FieldAttrs {
|
|||||||
pub fn use_default(&self) -> bool {
|
pub fn use_default(&self) -> bool {
|
||||||
self.use_default
|
self.use_default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Predicate for ignoring a field when serializing a value
|
||||||
|
pub fn skip_serializing_field(&self) -> bool {
|
||||||
|
self.skip_serializing_field
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+278
-54
@@ -129,15 +129,24 @@ fn deserialize_item_struct(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (named_fields.is_empty(), unnamed_fields == 0) {
|
match (named_fields.is_empty(), unnamed_fields) {
|
||||||
(true, true) => {
|
(true, 0) => {
|
||||||
deserialize_unit_struct(
|
deserialize_unit_struct(
|
||||||
cx,
|
cx,
|
||||||
&builder,
|
&builder,
|
||||||
item.ident,
|
item.ident,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(true, false) => {
|
(true, 1) => {
|
||||||
|
deserialize_newtype_struct(
|
||||||
|
cx,
|
||||||
|
&builder,
|
||||||
|
item.ident,
|
||||||
|
impl_generics,
|
||||||
|
ty,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(true, _) => {
|
||||||
deserialize_tuple_struct(
|
deserialize_tuple_struct(
|
||||||
cx,
|
cx,
|
||||||
&builder,
|
&builder,
|
||||||
@@ -147,7 +156,7 @@ fn deserialize_item_struct(
|
|||||||
unnamed_fields,
|
unnamed_fields,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(false, true) => {
|
(false, 0) => {
|
||||||
deserialize_struct(
|
deserialize_struct(
|
||||||
cx,
|
cx,
|
||||||
&builder,
|
&builder,
|
||||||
@@ -157,7 +166,7 @@ fn deserialize_item_struct(
|
|||||||
struct_def,
|
struct_def,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(false, false) => {
|
(false, _) => {
|
||||||
cx.bug("struct has named and unnamed fields")
|
cx.bug("struct has named and unnamed fields")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,11 +199,25 @@ fn deserialize_visitor(
|
|||||||
(
|
(
|
||||||
builder.item().tuple_struct("__Visitor")
|
builder.item().tuple_struct("__Visitor")
|
||||||
.generics().with(trait_generics.clone()).build()
|
.generics().with(trait_generics.clone()).build()
|
||||||
.with_tys(
|
.with_tys({
|
||||||
trait_generics.ty_params.iter().map(|ty_param| {
|
let lifetimes = trait_generics.lifetimes.iter()
|
||||||
builder.ty().phantom_data().id(ty_param.ident)
|
.map(|lifetime_def| {
|
||||||
})
|
builder.ty()
|
||||||
)
|
.phantom_data()
|
||||||
|
.ref_().lifetime(lifetime_def.lifetime.name)
|
||||||
|
.ty()
|
||||||
|
.unit()
|
||||||
|
});
|
||||||
|
|
||||||
|
let ty_params = trait_generics.ty_params.iter()
|
||||||
|
.map(|ty_param| {
|
||||||
|
builder.ty()
|
||||||
|
.phantom_data()
|
||||||
|
.id(ty_param.ident)
|
||||||
|
});
|
||||||
|
|
||||||
|
lifetimes.chain(ty_params)
|
||||||
|
})
|
||||||
.build(),
|
.build(),
|
||||||
builder.ty().path()
|
builder.ty().path()
|
||||||
.segment("__Visitor").with_generics(trait_generics.clone()).build()
|
.segment("__Visitor").with_generics(trait_generics.clone()).build()
|
||||||
@@ -204,11 +227,11 @@ fn deserialize_visitor(
|
|||||||
.with_tys(forward_tys)
|
.with_tys(forward_tys)
|
||||||
.with_tys(placeholders)
|
.with_tys(placeholders)
|
||||||
.build().build()
|
.build().build()
|
||||||
.with_args(
|
.with_args({
|
||||||
trait_generics.ty_params.iter().map(|_| {
|
let len = trait_generics.lifetimes.len() + trait_generics.ty_params.len();
|
||||||
builder.expr().phantom_data()
|
|
||||||
})
|
(0 .. len).map(|_| builder.expr().phantom_data())
|
||||||
)
|
})
|
||||||
.build(),
|
.build(),
|
||||||
trait_generics,
|
trait_generics,
|
||||||
)
|
)
|
||||||
@@ -260,7 +283,59 @@ fn deserialize_unit_struct(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.visit_named_unit($type_name, __Visitor)
|
deserializer.visit_unit_struct($type_name, __Visitor)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_newtype_struct(
|
||||||
|
cx: &ExtCtxt,
|
||||||
|
builder: &aster::AstBuilder,
|
||||||
|
type_ident: Ident,
|
||||||
|
impl_generics: &ast::Generics,
|
||||||
|
ty: P<ast::Ty>,
|
||||||
|
) -> P<ast::Expr> {
|
||||||
|
let where_clause = &impl_generics.where_clause;
|
||||||
|
|
||||||
|
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
|
||||||
|
deserialize_visitor(
|
||||||
|
builder,
|
||||||
|
impl_generics,
|
||||||
|
vec![deserializer_ty_param(builder)],
|
||||||
|
vec![deserializer_ty_arg(builder)],
|
||||||
|
);
|
||||||
|
|
||||||
|
let visit_seq_expr = deserialize_seq(
|
||||||
|
cx,
|
||||||
|
builder,
|
||||||
|
builder.path().id(type_ident).build(),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
let type_name = builder.expr().str(type_ident);
|
||||||
|
|
||||||
|
quote_expr!(cx, {
|
||||||
|
$visitor_item
|
||||||
|
|
||||||
|
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
|
||||||
|
type Value = $ty;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_newtype_struct<D>(&mut self, deserializer: &mut D) -> ::std::result::Result<Self::Value, D::Error>
|
||||||
|
where D: ::serde::de::Deserializer,
|
||||||
|
{
|
||||||
|
let value = try!(::serde::de::Deserialize::deserialize(deserializer));
|
||||||
|
Ok($type_ident(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
||||||
|
where __V: ::serde::de::SeqVisitor,
|
||||||
|
{
|
||||||
|
$visit_seq_expr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.visit_newtype_struct($type_name, $visitor_expr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,6 +372,7 @@ fn deserialize_tuple_struct(
|
|||||||
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
|
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
|
||||||
type Value = $ty;
|
type Value = $ty;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
||||||
where __V: ::serde::de::SeqVisitor,
|
where __V: ::serde::de::SeqVisitor,
|
||||||
{
|
{
|
||||||
@@ -304,7 +380,7 @@ fn deserialize_tuple_struct(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.visit_named_seq($type_name, $visitor_expr)
|
deserializer.visit_tuple_struct($type_name, $fields, $visitor_expr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +397,7 @@ fn deserialize_seq(
|
|||||||
let $name = match try!(visitor.visit()) {
|
let $name = match try!(visitor.visit()) {
|
||||||
Some(value) => { value },
|
Some(value) => { value },
|
||||||
None => {
|
None => {
|
||||||
return Err(::serde::de::Error::end_of_stream_error());
|
return Err(::serde::de::Error::end_of_stream());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
).unwrap()
|
).unwrap()
|
||||||
@@ -342,6 +418,51 @@ fn deserialize_seq(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct_as_seq(
|
||||||
|
cx: &ExtCtxt,
|
||||||
|
builder: &aster::AstBuilder,
|
||||||
|
struct_path: ast::Path,
|
||||||
|
struct_def: &StructDef,
|
||||||
|
) -> P<ast::Expr> {
|
||||||
|
let let_values: Vec<P<ast::Stmt>> = (0 .. struct_def.fields.len())
|
||||||
|
.map(|i| {
|
||||||
|
let name = builder.id(format!("__field{}", i));
|
||||||
|
quote_stmt!(cx,
|
||||||
|
let $name = match try!(visitor.visit()) {
|
||||||
|
Some(value) => { value },
|
||||||
|
None => {
|
||||||
|
return Err(::serde::de::Error::end_of_stream());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
).unwrap()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let result = builder.expr().struct_path(struct_path)
|
||||||
|
.with_id_exprs(
|
||||||
|
struct_def.fields.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, field)| {
|
||||||
|
(
|
||||||
|
match field.node.kind {
|
||||||
|
ast::NamedField(name, _) => name.clone(),
|
||||||
|
ast::UnnamedField(_) => panic!("struct contains unnamed fields"),
|
||||||
|
},
|
||||||
|
builder.expr().id(format!("__field{}", i)),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
quote_expr!(cx, {
|
||||||
|
$let_values
|
||||||
|
|
||||||
|
try!(visitor.end());
|
||||||
|
|
||||||
|
Ok($result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_struct(
|
fn deserialize_struct(
|
||||||
cx: &ExtCtxt,
|
cx: &ExtCtxt,
|
||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
@@ -352,19 +473,27 @@ fn deserialize_struct(
|
|||||||
) -> P<ast::Expr> {
|
) -> P<ast::Expr> {
|
||||||
let where_clause = &impl_generics.where_clause;
|
let where_clause = &impl_generics.where_clause;
|
||||||
|
|
||||||
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
|
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) = deserialize_visitor(
|
||||||
deserialize_visitor(
|
builder,
|
||||||
builder,
|
&impl_generics,
|
||||||
&impl_generics,
|
vec![deserializer_ty_param(builder)],
|
||||||
vec![deserializer_ty_param(builder)],
|
vec![deserializer_ty_arg(builder)],
|
||||||
vec![deserializer_ty_arg(builder)],
|
);
|
||||||
);
|
|
||||||
|
|
||||||
let (field_visitor, visit_map_expr) = deserialize_struct_visitor(
|
let type_path = builder.path().id(type_ident).build();
|
||||||
|
|
||||||
|
let visit_seq_expr = deserialize_struct_as_seq(
|
||||||
|
cx,
|
||||||
|
builder,
|
||||||
|
type_path.clone(),
|
||||||
|
struct_def
|
||||||
|
);
|
||||||
|
|
||||||
|
let (field_visitor, fields_stmt, visit_map_expr) = deserialize_struct_visitor(
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
struct_def,
|
struct_def,
|
||||||
builder.path().id(type_ident).build(),
|
type_path.clone()
|
||||||
);
|
);
|
||||||
|
|
||||||
let type_name = builder.expr().str(type_ident);
|
let type_name = builder.expr().str(type_ident);
|
||||||
@@ -377,6 +506,13 @@ fn deserialize_struct(
|
|||||||
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
|
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
|
||||||
type Value = $ty;
|
type Value = $ty;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
||||||
|
where __V: ::serde::de::SeqVisitor,
|
||||||
|
{
|
||||||
|
$visit_seq_expr
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
||||||
where __V: ::serde::de::MapVisitor,
|
where __V: ::serde::de::MapVisitor,
|
||||||
@@ -385,7 +521,9 @@ fn deserialize_struct(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.visit_named_map($type_name, $visitor_expr)
|
$fields_stmt
|
||||||
|
|
||||||
|
deserializer.visit_struct($type_name, FIELDS, $visitor_expr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,11 +545,25 @@ fn deserialize_item_enum(
|
|||||||
enum_def.variants.iter()
|
enum_def.variants.iter()
|
||||||
.map(|variant|
|
.map(|variant|
|
||||||
attr::FieldAttrs::new(
|
attr::FieldAttrs::new(
|
||||||
|
false,
|
||||||
true,
|
true,
|
||||||
builder.expr().str(variant.node.name)))
|
builder.expr().str(variant.node.name)))
|
||||||
.collect()
|
.collect()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let variants_expr = builder.expr().addr_of().slice()
|
||||||
|
.with_exprs(
|
||||||
|
enum_def.variants.iter()
|
||||||
|
.map(|variant| {
|
||||||
|
builder.expr().str(variant.node.name)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let variants_stmt = quote_stmt!(cx,
|
||||||
|
const VARIANTS: &'static [&'static str] = $variants_expr;
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
// Match arms to extract a variant from a string
|
// Match arms to extract a variant from a string
|
||||||
let variant_arms: Vec<_> = enum_def.variants.iter()
|
let variant_arms: Vec<_> = enum_def.variants.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@@ -458,7 +610,9 @@ fn deserialize_item_enum(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.visit_enum($type_name, $visitor_expr)
|
$variants_stmt
|
||||||
|
|
||||||
|
deserializer.visit_enum($type_name, VARIANTS, $visitor_expr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,6 +633,12 @@ fn deserialize_variant(
|
|||||||
Ok($type_ident::$variant_ident)
|
Ok($type_ident::$variant_ident)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
ast::TupleVariantKind(ref args) if args.len() == 1 => {
|
||||||
|
quote_expr!(cx, {
|
||||||
|
let val = try!(visitor.visit_newtype());
|
||||||
|
Ok($type_ident::$variant_ident(val))
|
||||||
|
})
|
||||||
|
}
|
||||||
ast::TupleVariantKind(ref args) => {
|
ast::TupleVariantKind(ref args) => {
|
||||||
deserialize_tuple_variant(
|
deserialize_tuple_variant(
|
||||||
cx,
|
cx,
|
||||||
@@ -543,7 +703,7 @@ fn deserialize_tuple_variant(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor.visit_seq($visitor_expr)
|
visitor.visit_tuple($fields, $visitor_expr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,11 +718,23 @@ fn deserialize_struct_variant(
|
|||||||
) -> P<ast::Expr> {
|
) -> P<ast::Expr> {
|
||||||
let where_clause = &generics.where_clause;
|
let where_clause = &generics.where_clause;
|
||||||
|
|
||||||
let (field_visitor, field_expr) = deserialize_struct_visitor(
|
let type_path = builder.path()
|
||||||
|
.id(type_ident)
|
||||||
|
.id(variant_ident)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let visit_seq_expr = deserialize_struct_as_seq(
|
||||||
|
cx,
|
||||||
|
builder,
|
||||||
|
type_path.clone(),
|
||||||
|
struct_def
|
||||||
|
);
|
||||||
|
|
||||||
|
let (field_visitor, fields_stmt, field_expr) = deserialize_struct_visitor(
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
struct_def,
|
struct_def,
|
||||||
builder.path().id(type_ident).id(variant_ident).build(),
|
type_path
|
||||||
);
|
);
|
||||||
|
|
||||||
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
|
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
|
||||||
@@ -581,6 +753,14 @@ fn deserialize_struct_variant(
|
|||||||
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
|
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
|
||||||
type Value = $ty;
|
type Value = $ty;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
||||||
|
where __V: ::serde::de::SeqVisitor,
|
||||||
|
{
|
||||||
|
$visit_seq_expr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
|
||||||
where __V: ::serde::de::MapVisitor,
|
where __V: ::serde::de::MapVisitor,
|
||||||
{
|
{
|
||||||
@@ -588,7 +768,9 @@ fn deserialize_struct_variant(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor.visit_map($visitor_expr)
|
$fields_stmt
|
||||||
|
|
||||||
|
visitor.visit_struct(FIELDS, $visitor_expr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,6 +794,20 @@ fn deserialize_field_visitor(
|
|||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
let index_field_arms: Vec<_> = field_idents.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(field_index, field_ident)| {
|
||||||
|
quote_arm!(cx, $field_index => { Ok(__Field::$field_ident) })
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let index_body = quote_expr!(cx,
|
||||||
|
match value {
|
||||||
|
$index_field_arms
|
||||||
|
_ => { Err(::serde::de::Error::syntax("expected a field")) }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// A set of all the formats that have specialized field attributes
|
// A set of all the formats that have specialized field attributes
|
||||||
let formats = field_attrs.iter()
|
let formats = field_attrs.iter()
|
||||||
.fold(HashSet::new(), |mut set, field_expr| {
|
.fold(HashSet::new(), |mut set, field_expr| {
|
||||||
@@ -628,15 +824,15 @@ fn deserialize_field_visitor(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let body = if formats.is_empty() {
|
let str_body = if formats.is_empty() {
|
||||||
// No formats specific attributes, so no match on format required
|
// No formats specific attributes, so no match on format required
|
||||||
quote_expr!(cx,
|
quote_expr!(cx,
|
||||||
match value {
|
match value {
|
||||||
$default_field_arms
|
$default_field_arms
|
||||||
_ => { Err(::serde::de::Error::unknown_field_error(value)) }
|
_ => { Err(::serde::de::Error::unknown_field(value)) }
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let field_arms : Vec<_> = formats.iter()
|
let field_arms: Vec<_> = formats.iter()
|
||||||
.map(|fmt| {
|
.map(|fmt| {
|
||||||
field_idents.iter()
|
field_idents.iter()
|
||||||
.zip(field_attrs.iter())
|
.zip(field_attrs.iter())
|
||||||
@@ -648,27 +844,28 @@ fn deserialize_field_visitor(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let fmt_matches : Vec<_> = formats.iter()
|
let fmt_matches: Vec<_> = formats.iter()
|
||||||
.zip(field_arms.iter())
|
.zip(field_arms.iter())
|
||||||
.map(|(ref fmt, ref arms)| {
|
.map(|(ref fmt, ref arms)| {
|
||||||
quote_arm!(cx, $fmt => {
|
quote_arm!(cx, $fmt => {
|
||||||
match value {
|
match value {
|
||||||
$arms
|
$arms
|
||||||
_ => {
|
_ => {
|
||||||
Err(::serde::de::Error::unknown_field_error(value))
|
Err(::serde::de::Error::unknown_field(value))
|
||||||
}
|
}
|
||||||
}})
|
}})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
quote_expr!(cx,
|
quote_expr!(cx,
|
||||||
match __D::format() {
|
match __D::format() {
|
||||||
$fmt_matches
|
$fmt_matches
|
||||||
_ => match value {
|
_ => match value {
|
||||||
$default_field_arms
|
$default_field_arms
|
||||||
_ => { Err(::serde::de::Error::unknown_field_error(value)) }
|
_ => { Err(::serde::de::Error::unknown_field(value)) }
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let impl_item = quote_item!(cx,
|
let impl_item = quote_item!(cx,
|
||||||
@@ -688,10 +885,16 @@ fn deserialize_field_visitor(
|
|||||||
{
|
{
|
||||||
type Value = __Field;
|
type Value = __Field;
|
||||||
|
|
||||||
|
fn visit_usize<E>(&mut self, value: usize) -> ::std::result::Result<__Field, E>
|
||||||
|
where E: ::serde::de::Error,
|
||||||
|
{
|
||||||
|
$index_body
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_str<E>(&mut self, value: &str) -> ::std::result::Result<__Field, E>
|
fn visit_str<E>(&mut self, value: &str) -> ::std::result::Result<__Field, E>
|
||||||
where E: ::serde::de::Error,
|
where E: ::serde::de::Error,
|
||||||
{
|
{
|
||||||
$body
|
$str_body
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_bytes<E>(&mut self, value: &[u8]) -> ::std::result::Result<__Field, E>
|
fn visit_bytes<E>(&mut self, value: &[u8]) -> ::std::result::Result<__Field, E>
|
||||||
@@ -700,13 +903,18 @@ fn deserialize_field_visitor(
|
|||||||
// TODO: would be better to generate a byte string literal match
|
// TODO: would be better to generate a byte string literal match
|
||||||
match ::std::str::from_utf8(value) {
|
match ::std::str::from_utf8(value) {
|
||||||
Ok(s) => self.visit_str(s),
|
Ok(s) => self.visit_str(s),
|
||||||
_ => Err(::serde::de::Error::syntax_error()),
|
_ => {
|
||||||
|
Err(
|
||||||
|
::serde::de::Error::syntax(
|
||||||
|
"could not convert a byte string to a String"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializer.visit(
|
deserializer.visit(__FieldVisitor::<D>{ phantom: PhantomData })
|
||||||
__FieldVisitor::<D>{ phantom: PhantomData })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).unwrap();
|
).unwrap();
|
||||||
@@ -719,7 +927,7 @@ fn deserialize_struct_visitor(
|
|||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
struct_def: &ast::StructDef,
|
struct_def: &ast::StructDef,
|
||||||
struct_path: ast::Path,
|
struct_path: ast::Path,
|
||||||
) -> (Vec<P<ast::Item>>, P<ast::Expr>) {
|
) -> (Vec<P<ast::Item>>, P<ast::Stmt>, P<ast::Expr>) {
|
||||||
let field_visitor = deserialize_field_visitor(
|
let field_visitor = deserialize_field_visitor(
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
@@ -733,7 +941,23 @@ fn deserialize_struct_visitor(
|
|||||||
struct_def,
|
struct_def,
|
||||||
);
|
);
|
||||||
|
|
||||||
(field_visitor, visit_map_expr)
|
let fields_expr = builder.expr().addr_of().slice()
|
||||||
|
.with_exprs(
|
||||||
|
struct_def.fields.iter()
|
||||||
|
.map(|field| {
|
||||||
|
match field.node.kind {
|
||||||
|
ast::NamedField(name, _) => builder.expr().str(name),
|
||||||
|
ast::UnnamedField(_) => panic!("struct contains unnamed fields"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let fields_stmt = quote_stmt!(cx,
|
||||||
|
const FIELDS: &'static [&'static str] = $fields_expr;
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
(field_visitor, fields_stmt, visit_map_expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_map(
|
fn deserialize_map(
|
||||||
|
|||||||
+24
-10
@@ -58,10 +58,18 @@ fn default_value(mi: &ast::MetaItem) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn skip_serializing_field(mi: &ast::MetaItem) -> bool {
|
||||||
|
if let ast::MetaItem_::MetaWord(ref n) = mi.node {
|
||||||
|
n == &"skip_serializing"
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn field_attrs<'a>(
|
fn field_attrs<'a>(
|
||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
field: &'a ast::StructField,
|
field: &'a ast::StructField,
|
||||||
) -> (Rename<'a>, bool) {
|
) -> (Rename<'a>, bool, bool) {
|
||||||
field.node.attrs.iter()
|
field.node.attrs.iter()
|
||||||
.find(|sa| {
|
.find(|sa| {
|
||||||
if let ast::MetaList(ref n, _) = sa.node.value.node {
|
if let ast::MetaList(ref n, _) = sa.node.value.node {
|
||||||
@@ -73,15 +81,18 @@ fn field_attrs<'a>(
|
|||||||
.and_then(|sa| {
|
.and_then(|sa| {
|
||||||
if let ast::MetaList(_, ref vals) = sa.node.value.node {
|
if let ast::MetaList(_, ref vals) = sa.node.value.node {
|
||||||
attr::mark_used(&sa);
|
attr::mark_used(&sa);
|
||||||
Some((vals.iter()
|
Some((
|
||||||
.fold(None, |v, mi| v.or(rename(builder, mi)))
|
vals.iter()
|
||||||
.unwrap_or(Rename::None),
|
.fold(None, |v, mi| v.or(rename(builder, mi)))
|
||||||
vals.iter().any(|mi| default_value(mi))))
|
.unwrap_or(Rename::None),
|
||||||
|
vals.iter().any(|mi| default_value(mi)),
|
||||||
|
vals.iter().any(|mi| skip_serializing_field(mi)),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
Some((Rename::None, false))
|
Some((Rename::None, false, false))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or((Rename::None, false))
|
.unwrap_or((Rename::None, false, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn struct_field_attrs(
|
pub fn struct_field_attrs(
|
||||||
@@ -92,23 +103,26 @@ pub fn struct_field_attrs(
|
|||||||
struct_def.fields.iter()
|
struct_def.fields.iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
match field_attrs(builder, field) {
|
match field_attrs(builder, field) {
|
||||||
(Rename::Global(rename), default_value) =>
|
(Rename::Global(rename), default_value, skip_serializing_field) =>
|
||||||
FieldAttrs::new(
|
FieldAttrs::new(
|
||||||
|
skip_serializing_field,
|
||||||
default_value,
|
default_value,
|
||||||
builder.expr().build_lit(P(rename.clone()))),
|
builder.expr().build_lit(P(rename.clone()))),
|
||||||
(Rename::Format(renames), default_value) => {
|
(Rename::Format(renames), default_value, skip_serializing_field) => {
|
||||||
let mut res = HashMap::new();
|
let mut res = HashMap::new();
|
||||||
res.extend(
|
res.extend(
|
||||||
renames.into_iter()
|
renames.into_iter()
|
||||||
.map(|(k,v)|
|
.map(|(k,v)|
|
||||||
(k, builder.expr().build_lit(P(v.clone())))));
|
(k, builder.expr().build_lit(P(v.clone())))));
|
||||||
FieldAttrs::new_with_formats(
|
FieldAttrs::new_with_formats(
|
||||||
|
skip_serializing_field,
|
||||||
default_value,
|
default_value,
|
||||||
default_field_name(cx, builder, field.node.kind),
|
default_field_name(cx, builder, field.node.kind),
|
||||||
res)
|
res)
|
||||||
},
|
},
|
||||||
(Rename::None, default_value) => {
|
(Rename::None, default_value, skip_serializing_field) => {
|
||||||
FieldAttrs::new(
|
FieldAttrs::new(
|
||||||
|
skip_serializing_field,
|
||||||
default_value,
|
default_value,
|
||||||
default_field_name(cx, builder, field.node.kind))
|
default_field_name(cx, builder, field.node.kind))
|
||||||
}
|
}
|
||||||
|
|||||||
+79
-49
@@ -55,10 +55,7 @@ pub fn expand_derive_serialize(
|
|||||||
&builder,
|
&builder,
|
||||||
&item,
|
&item,
|
||||||
&impl_generics,
|
&impl_generics,
|
||||||
builder.ty()
|
ty.clone(),
|
||||||
.ref_()
|
|
||||||
.lifetime("'__a")
|
|
||||||
.build_ty(ty.clone()),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let where_clause = &impl_generics.where_clause;
|
let where_clause = &impl_generics.where_clause;
|
||||||
@@ -127,15 +124,22 @@ fn serialize_item_struct(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (named_fields.is_empty(), unnamed_fields == 0) {
|
match (named_fields.is_empty(), unnamed_fields) {
|
||||||
(true, true) => {
|
(true, 0) => {
|
||||||
serialize_unit_struct(
|
serialize_unit_struct(
|
||||||
cx,
|
cx,
|
||||||
&builder,
|
&builder,
|
||||||
item.ident,
|
item.ident,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(true, false) => {
|
(true, 1) => {
|
||||||
|
serialize_newtype_struct(
|
||||||
|
cx,
|
||||||
|
&builder,
|
||||||
|
item.ident,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(true, _) => {
|
||||||
serialize_tuple_struct(
|
serialize_tuple_struct(
|
||||||
cx,
|
cx,
|
||||||
&builder,
|
&builder,
|
||||||
@@ -145,7 +149,7 @@ fn serialize_item_struct(
|
|||||||
unnamed_fields,
|
unnamed_fields,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(false, true) => {
|
(false, 0) => {
|
||||||
serialize_struct(
|
serialize_struct(
|
||||||
cx,
|
cx,
|
||||||
&builder,
|
&builder,
|
||||||
@@ -156,7 +160,7 @@ fn serialize_item_struct(
|
|||||||
named_fields,
|
named_fields,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(false, false) => {
|
(false, _) => {
|
||||||
cx.bug("struct has named and unnamed fields")
|
cx.bug("struct has named and unnamed fields")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,7 +173,17 @@ fn serialize_unit_struct(
|
|||||||
) -> P<ast::Expr> {
|
) -> P<ast::Expr> {
|
||||||
let type_name = builder.expr().str(type_ident);
|
let type_name = builder.expr().str(type_ident);
|
||||||
|
|
||||||
quote_expr!(cx, serializer.visit_named_unit($type_name))
|
quote_expr!(cx, serializer.visit_unit_struct($type_name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_newtype_struct(
|
||||||
|
cx: &ExtCtxt,
|
||||||
|
builder: &aster::AstBuilder,
|
||||||
|
type_ident: Ident
|
||||||
|
) -> P<ast::Expr> {
|
||||||
|
let type_name = builder.expr().str(type_ident);
|
||||||
|
|
||||||
|
quote_expr!(cx, serializer.visit_newtype_struct($type_name, &self.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple_struct(
|
fn serialize_tuple_struct(
|
||||||
@@ -184,7 +198,10 @@ fn serialize_tuple_struct(
|
|||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
ty.clone(),
|
ty.clone(),
|
||||||
ty,
|
builder.ty()
|
||||||
|
.ref_()
|
||||||
|
.lifetime("'__a")
|
||||||
|
.build_ty(ty.clone()),
|
||||||
fields,
|
fields,
|
||||||
impl_generics,
|
impl_generics,
|
||||||
);
|
);
|
||||||
@@ -194,10 +211,10 @@ fn serialize_tuple_struct(
|
|||||||
quote_expr!(cx, {
|
quote_expr!(cx, {
|
||||||
$visitor_struct
|
$visitor_struct
|
||||||
$visitor_impl
|
$visitor_impl
|
||||||
serializer.visit_named_seq($type_name, Visitor {
|
serializer.visit_tuple_struct($type_name, Visitor {
|
||||||
value: self,
|
value: self,
|
||||||
state: 0,
|
state: 0,
|
||||||
_structure_ty: ::std::marker::PhantomData,
|
_structure_ty: ::std::marker::PhantomData::<&$ty>,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -215,7 +232,10 @@ fn serialize_struct(
|
|||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
ty.clone(),
|
ty.clone(),
|
||||||
ty,
|
builder.ty()
|
||||||
|
.ref_()
|
||||||
|
.lifetime("'__a")
|
||||||
|
.build_ty(ty.clone()),
|
||||||
struct_def,
|
struct_def,
|
||||||
impl_generics,
|
impl_generics,
|
||||||
fields.iter().map(|field| quote_expr!(cx, &self.value.$field)),
|
fields.iter().map(|field| quote_expr!(cx, &self.value.$field)),
|
||||||
@@ -226,10 +246,10 @@ fn serialize_struct(
|
|||||||
quote_expr!(cx, {
|
quote_expr!(cx, {
|
||||||
$visitor_struct
|
$visitor_struct
|
||||||
$visitor_impl
|
$visitor_impl
|
||||||
serializer.visit_named_map($type_name, Visitor {
|
serializer.visit_struct($type_name, Visitor {
|
||||||
value: self,
|
value: self,
|
||||||
state: 0,
|
state: 0,
|
||||||
_structure_ty: ::std::marker::PhantomData,
|
_structure_ty: ::std::marker::PhantomData::<&$ty>,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -243,7 +263,8 @@ fn serialize_item_enum(
|
|||||||
enum_def: &ast::EnumDef,
|
enum_def: &ast::EnumDef,
|
||||||
) -> P<ast::Expr> {
|
) -> P<ast::Expr> {
|
||||||
let arms: Vec<ast::Arm> = enum_def.variants.iter()
|
let arms: Vec<ast::Arm> = enum_def.variants.iter()
|
||||||
.map(|variant| {
|
.enumerate()
|
||||||
|
.map(|(variant_index, variant)| {
|
||||||
serialize_variant(
|
serialize_variant(
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
@@ -251,6 +272,7 @@ fn serialize_item_enum(
|
|||||||
impl_generics,
|
impl_generics,
|
||||||
ty.clone(),
|
ty.clone(),
|
||||||
variant,
|
variant,
|
||||||
|
variant_index,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@@ -269,6 +291,7 @@ fn serialize_variant(
|
|||||||
generics: &ast::Generics,
|
generics: &ast::Generics,
|
||||||
ty: P<ast::Ty>,
|
ty: P<ast::Ty>,
|
||||||
variant: &ast::Variant,
|
variant: &ast::Variant,
|
||||||
|
variant_index: usize,
|
||||||
) -> ast::Arm {
|
) -> ast::Arm {
|
||||||
let type_name = builder.expr().str(type_ident);
|
let type_name = builder.expr().str(type_ident);
|
||||||
let variant_ident = variant.node.name;
|
let variant_ident = variant.node.name;
|
||||||
@@ -282,14 +305,34 @@ fn serialize_variant(
|
|||||||
|
|
||||||
quote_arm!(cx,
|
quote_arm!(cx,
|
||||||
$pat => {
|
$pat => {
|
||||||
::serde::ser::Serializer::visit_enum_unit(
|
::serde::ser::Serializer::visit_unit_variant(
|
||||||
serializer,
|
serializer,
|
||||||
$type_name,
|
$type_name,
|
||||||
|
$variant_index,
|
||||||
$variant_name,
|
$variant_name,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
ast::TupleVariantKind(ref args) if args.len() == 1 => {
|
||||||
|
let field = builder.id("__simple_value");
|
||||||
|
let field = builder.pat().ref_id(field);
|
||||||
|
let pat = builder.pat().enum_()
|
||||||
|
.id(type_ident).id(variant_ident).build()
|
||||||
|
.with_pats(Some(field).into_iter())
|
||||||
|
.build();
|
||||||
|
quote_arm!(cx,
|
||||||
|
$pat => {
|
||||||
|
::serde::ser::Serializer::visit_newtype_variant(
|
||||||
|
serializer,
|
||||||
|
$type_name,
|
||||||
|
$variant_index,
|
||||||
|
$variant_name,
|
||||||
|
__simple_value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
ast::TupleVariantKind(ref args) => {
|
ast::TupleVariantKind(ref args) => {
|
||||||
let fields: Vec<ast::Ident> = (0 .. args.len())
|
let fields: Vec<ast::Ident> = (0 .. args.len())
|
||||||
.map(|i| builder.id(format!("__field{}", i)))
|
.map(|i| builder.id(format!("__field{}", i)))
|
||||||
@@ -304,6 +347,7 @@ fn serialize_variant(
|
|||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
type_name,
|
type_name,
|
||||||
|
variant_index,
|
||||||
variant_name,
|
variant_name,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
@@ -340,6 +384,7 @@ fn serialize_variant(
|
|||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
type_name,
|
type_name,
|
||||||
|
variant_index,
|
||||||
variant_name,
|
variant_name,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
@@ -356,6 +401,7 @@ fn serialize_tuple_variant(
|
|||||||
cx: &ExtCtxt,
|
cx: &ExtCtxt,
|
||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
type_name: P<ast::Expr>,
|
type_name: P<ast::Expr>,
|
||||||
|
variant_index: usize,
|
||||||
variant_name: P<ast::Expr>,
|
variant_name: P<ast::Expr>,
|
||||||
generics: &ast::Generics,
|
generics: &ast::Generics,
|
||||||
structure_ty: P<ast::Ty>,
|
structure_ty: P<ast::Ty>,
|
||||||
@@ -376,7 +422,7 @@ fn serialize_tuple_variant(
|
|||||||
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
|
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
structure_ty,
|
structure_ty.clone(),
|
||||||
variant_ty,
|
variant_ty,
|
||||||
args.len(),
|
args.len(),
|
||||||
generics,
|
generics,
|
||||||
@@ -385,9 +431,7 @@ fn serialize_tuple_variant(
|
|||||||
let value_expr = builder.expr().tuple()
|
let value_expr = builder.expr().tuple()
|
||||||
.with_exprs(
|
.with_exprs(
|
||||||
fields.iter().map(|field| {
|
fields.iter().map(|field| {
|
||||||
builder.expr()
|
builder.expr().id(field)
|
||||||
.addr_of()
|
|
||||||
.id(field)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
@@ -395,10 +439,10 @@ fn serialize_tuple_variant(
|
|||||||
quote_expr!(cx, {
|
quote_expr!(cx, {
|
||||||
$visitor_struct
|
$visitor_struct
|
||||||
$visitor_impl
|
$visitor_impl
|
||||||
serializer.visit_enum_seq($type_name, $variant_name, Visitor {
|
serializer.visit_tuple_variant($type_name, $variant_index, $variant_name, Visitor {
|
||||||
value: $value_expr,
|
value: $value_expr,
|
||||||
state: 0,
|
state: 0,
|
||||||
_structure_ty: ::std::marker::PhantomData,
|
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -407,6 +451,7 @@ fn serialize_struct_variant(
|
|||||||
cx: &ExtCtxt,
|
cx: &ExtCtxt,
|
||||||
builder: &aster::AstBuilder,
|
builder: &aster::AstBuilder,
|
||||||
type_name: P<ast::Expr>,
|
type_name: P<ast::Expr>,
|
||||||
|
variant_index: usize,
|
||||||
variant_name: P<ast::Expr>,
|
variant_name: P<ast::Expr>,
|
||||||
generics: &ast::Generics,
|
generics: &ast::Generics,
|
||||||
structure_ty: P<ast::Ty>,
|
structure_ty: P<ast::Ty>,
|
||||||
@@ -427,9 +472,7 @@ fn serialize_struct_variant(
|
|||||||
let value_expr = builder.expr().tuple()
|
let value_expr = builder.expr().tuple()
|
||||||
.with_exprs(
|
.with_exprs(
|
||||||
fields.iter().map(|field| {
|
fields.iter().map(|field| {
|
||||||
builder.expr()
|
builder.expr().id(field)
|
||||||
.addr_of()
|
|
||||||
.id(field)
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
@@ -437,7 +480,7 @@ fn serialize_struct_variant(
|
|||||||
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
|
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
|
||||||
cx,
|
cx,
|
||||||
builder,
|
builder,
|
||||||
structure_ty,
|
structure_ty.clone(),
|
||||||
value_ty,
|
value_ty,
|
||||||
struct_def,
|
struct_def,
|
||||||
generics,
|
generics,
|
||||||
@@ -451,10 +494,10 @@ fn serialize_struct_variant(
|
|||||||
quote_expr!(cx, {
|
quote_expr!(cx, {
|
||||||
$visitor_struct
|
$visitor_struct
|
||||||
$visitor_impl
|
$visitor_impl
|
||||||
serializer.visit_enum_map($type_name, $variant_name, Visitor {
|
serializer.visit_struct_variant($type_name, $variant_index, $variant_name, Visitor {
|
||||||
value: $value_expr,
|
value: $value_expr,
|
||||||
state: 0,
|
state: 0,
|
||||||
_structure_ty: ::std::marker::PhantomData,
|
_structure_ty: ::std::marker::PhantomData::<&$structure_ty>,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -476,7 +519,7 @@ fn serialize_tuple_struct_visitor(
|
|||||||
quote_arm!(cx,
|
quote_arm!(cx,
|
||||||
$i => {
|
$i => {
|
||||||
self.state += 1;
|
self.state += 1;
|
||||||
let v = try!(serializer.visit_named_seq_elt(&$expr));
|
let v = try!(serializer.visit_tuple_struct_elt(&$expr));
|
||||||
Ok(Some(v))
|
Ok(Some(v))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -494,19 +537,12 @@ fn serialize_tuple_struct_visitor(
|
|||||||
.strip_bounds()
|
.strip_bounds()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Variants don't necessarily reference all generic lifetimes and type parameters,
|
|
||||||
// so to avoid a compilation failure, we'll just add a phantom type to capture these
|
|
||||||
// unused values.
|
|
||||||
let structure_ty = builder.ty()
|
|
||||||
.phantom_data()
|
|
||||||
.build(structure_ty);
|
|
||||||
|
|
||||||
(
|
(
|
||||||
quote_item!(cx,
|
quote_item!(cx,
|
||||||
struct Visitor $visitor_impl_generics $where_clause {
|
struct Visitor $visitor_impl_generics $where_clause {
|
||||||
state: usize,
|
state: usize,
|
||||||
value: $variant_ty,
|
value: $variant_ty,
|
||||||
_structure_ty: $structure_ty,
|
_structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>,
|
||||||
}
|
}
|
||||||
).unwrap(),
|
).unwrap(),
|
||||||
|
|
||||||
@@ -550,6 +586,7 @@ fn serialize_struct_visitor<I>(
|
|||||||
|
|
||||||
let arms: Vec<ast::Arm> = field_attrs.into_iter()
|
let arms: Vec<ast::Arm> = field_attrs.into_iter()
|
||||||
.zip(value_exprs)
|
.zip(value_exprs)
|
||||||
|
.filter(|&(ref field, _)| !field.skip_serializing_field())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (field, value_expr))| {
|
.map(|(i, (field, value_expr))| {
|
||||||
let key_expr = field.serializer_key_expr(cx);
|
let key_expr = field.serializer_key_expr(cx);
|
||||||
@@ -559,7 +596,7 @@ fn serialize_struct_visitor<I>(
|
|||||||
Ok(
|
Ok(
|
||||||
Some(
|
Some(
|
||||||
try!(
|
try!(
|
||||||
serializer.visit_named_map_elt(
|
serializer.visit_struct_elt(
|
||||||
$key_expr,
|
$key_expr,
|
||||||
$value_expr,
|
$value_expr,
|
||||||
)
|
)
|
||||||
@@ -582,19 +619,12 @@ fn serialize_struct_visitor<I>(
|
|||||||
.strip_bounds()
|
.strip_bounds()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Variants don't necessarily reference all generic lifetimes and type parameters,
|
|
||||||
// so to avoid a compilation failure, we'll just add a phantom type to capture these
|
|
||||||
// unused values.
|
|
||||||
let structure_ty = builder.ty()
|
|
||||||
.phantom_data()
|
|
||||||
.build(structure_ty);
|
|
||||||
|
|
||||||
(
|
(
|
||||||
quote_item!(cx,
|
quote_item!(cx,
|
||||||
struct Visitor $visitor_impl_generics $where_clause {
|
struct Visitor $visitor_impl_generics $where_clause {
|
||||||
state: usize,
|
state: usize,
|
||||||
value: $variant_ty,
|
value: $variant_ty,
|
||||||
_structure_ty: $structure_ty,
|
_structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>,
|
||||||
}
|
}
|
||||||
).unwrap(),
|
).unwrap(),
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "0.5.1"
|
||||||
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
|
license = "MIT/Apache-2.0"
|
||||||
|
description = "A JSON serialization file format"
|
||||||
|
repository = "https://github.com/serde-rs/serde"
|
||||||
|
documentation = "https://serde-rs.github.io/serde/serde_json/serde_json/index.html"
|
||||||
|
readme = "../README.md"
|
||||||
|
keywords = ["json", "serde", "serialization"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
num = "*"
|
||||||
|
serde = { version = "*", path = "../serde" }
|
||||||
@@ -10,8 +10,9 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use ser::{self, Serialize};
|
use serde::ser::{self, Serialize};
|
||||||
use json::value::{self, Value};
|
|
||||||
|
use value::{self, Value};
|
||||||
|
|
||||||
pub struct ArrayBuilder {
|
pub struct ArrayBuilder {
|
||||||
array: Vec<Value>,
|
array: Vec<Value>,
|
||||||
@@ -3,10 +3,10 @@ use std::i32;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use de;
|
use serde::de;
|
||||||
use iter::LineColIterator;
|
use serde::iter::LineColIterator;
|
||||||
|
|
||||||
use super::error::{Error, ErrorCode};
|
use super::error::{Error, ErrorCode, Result};
|
||||||
|
|
||||||
pub struct Deserializer<Iter: Iterator<Item=io::Result<u8>>> {
|
pub struct Deserializer<Iter: Iterator<Item=io::Result<u8>>> {
|
||||||
rdr: LineColIterator<Iter>,
|
rdr: LineColIterator<Iter>,
|
||||||
@@ -28,98 +28,128 @@ impl<Iter> Deserializer<Iter>
|
|||||||
{
|
{
|
||||||
/// Creates the JSON parser from an `std::iter::Iterator`.
|
/// Creates the JSON parser from an `std::iter::Iterator`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(rdr: Iter) -> Result<Deserializer<Iter>, Error> {
|
pub fn new(rdr: Iter) -> Deserializer<Iter> {
|
||||||
let mut deserializer = Deserializer {
|
Deserializer {
|
||||||
rdr: LineColIterator::new(rdr),
|
rdr: LineColIterator::new(rdr),
|
||||||
ch: None,
|
ch: None,
|
||||||
str_buf: Vec::with_capacity(128),
|
str_buf: Vec::with_capacity(128),
|
||||||
};
|
}
|
||||||
|
|
||||||
try!(deserializer.bump());
|
|
||||||
|
|
||||||
Ok(deserializer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn end(&mut self) -> Result<(), Error> {
|
pub fn end(&mut self) -> Result<()> {
|
||||||
try!(self.parse_whitespace());
|
try!(self.parse_whitespace());
|
||||||
if self.eof() {
|
if try!(self.eof()) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(self.error(ErrorCode::TrailingCharacters))
|
Err(self.error(ErrorCode::TrailingCharacters))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eof(&self) -> bool { self.ch.is_none() }
|
fn eof(&mut self) -> Result<bool> {
|
||||||
|
Ok(try!(self.peek()).is_none())
|
||||||
fn ch_or_null(&self) -> u8 { self.ch.unwrap_or(b'\x00') }
|
|
||||||
|
|
||||||
fn bump(&mut self) -> Result<(), Error> {
|
|
||||||
self.ch = match self.rdr.next() {
|
|
||||||
Some(Err(err)) => { return Err(Error::IoError(err)); }
|
|
||||||
Some(Ok(ch)) => Some(ch),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_char(&mut self) -> Result<Option<u8>, Error> {
|
fn peek(&mut self) -> Result<Option<u8>> {
|
||||||
try!(self.bump());
|
match self.ch {
|
||||||
Ok(self.ch)
|
Some(ch) => Ok(Some(ch)),
|
||||||
|
None => {
|
||||||
|
match self.rdr.next() {
|
||||||
|
Some(Err(err)) => Err(Error::IoError(err)),
|
||||||
|
Some(Ok(ch)) => {
|
||||||
|
self.ch = Some(ch);
|
||||||
|
Ok(self.ch)
|
||||||
|
}
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ch_is(&self, c: u8) -> bool {
|
fn peek_or_null(&mut self) -> Result<u8> {
|
||||||
self.ch == Some(c)
|
Ok(try!(self.peek()).unwrap_or(b'\x00'))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eat_char(&mut self) {
|
||||||
|
self.ch = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_char(&mut self) -> Result<Option<u8>> {
|
||||||
|
match self.ch.take() {
|
||||||
|
Some(ch) => Ok(Some(ch)),
|
||||||
|
None => {
|
||||||
|
match self.rdr.next() {
|
||||||
|
Some(Err(err)) => Err(Error::IoError(err)),
|
||||||
|
Some(Ok(ch)) => Ok(Some(ch)),
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_char_or_null(&mut self) -> Result<u8> {
|
||||||
|
Ok(try!(self.next_char()).unwrap_or(b'\x00'))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error(&mut self, reason: ErrorCode) -> Error {
|
fn error(&mut self, reason: ErrorCode) -> Error {
|
||||||
Error::SyntaxError(reason, self.rdr.line(), self.rdr.col())
|
Error::SyntaxError(reason, self.rdr.line(), self.rdr.col())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_whitespace(&mut self) -> Result<(), Error> {
|
fn parse_whitespace(&mut self) -> Result<()> {
|
||||||
while self.ch_is(b' ') ||
|
loop {
|
||||||
self.ch_is(b'\n') ||
|
match try!(self.peek_or_null()) {
|
||||||
self.ch_is(b'\t') ||
|
b' ' | b'\n' | b'\t' | b'\r' => {
|
||||||
self.ch_is(b'\r') { try!(self.bump()); }
|
self.eat_char();
|
||||||
|
}
|
||||||
Ok(())
|
_ => { return Ok(()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_value<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
fn parse_value<V>(&mut self, mut visitor: V) -> Result<V::Value>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
try!(self.parse_whitespace());
|
try!(self.parse_whitespace());
|
||||||
|
|
||||||
if self.eof() {
|
if try!(self.eof()) {
|
||||||
return Err(self.error(ErrorCode::EOFWhileParsingValue));
|
return Err(self.error(ErrorCode::EOFWhileParsingValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = match self.ch_or_null() {
|
let value = match try!(self.peek_or_null()) {
|
||||||
b'n' => {
|
b'n' => {
|
||||||
|
self.eat_char();
|
||||||
try!(self.parse_ident(b"ull"));
|
try!(self.parse_ident(b"ull"));
|
||||||
visitor.visit_unit()
|
visitor.visit_unit()
|
||||||
}
|
}
|
||||||
b't' => {
|
b't' => {
|
||||||
|
self.eat_char();
|
||||||
try!(self.parse_ident(b"rue"));
|
try!(self.parse_ident(b"rue"));
|
||||||
visitor.visit_bool(true)
|
visitor.visit_bool(true)
|
||||||
}
|
}
|
||||||
b'f' => {
|
b'f' => {
|
||||||
|
self.eat_char();
|
||||||
try!(self.parse_ident(b"alse"));
|
try!(self.parse_ident(b"alse"));
|
||||||
visitor.visit_bool(false)
|
visitor.visit_bool(false)
|
||||||
}
|
}
|
||||||
b'0' ... b'9' | b'-' => self.parse_number(visitor),
|
b'-' => {
|
||||||
|
self.eat_char();
|
||||||
|
self.parse_integer(false, visitor)
|
||||||
|
}
|
||||||
|
b'0' ... b'9' => {
|
||||||
|
self.parse_integer(true, visitor)
|
||||||
|
}
|
||||||
b'"' => {
|
b'"' => {
|
||||||
|
self.eat_char();
|
||||||
try!(self.parse_string());
|
try!(self.parse_string());
|
||||||
let s = str::from_utf8(&self.str_buf).unwrap();
|
let s = str::from_utf8(&self.str_buf).unwrap();
|
||||||
visitor.visit_str(s)
|
visitor.visit_str(s)
|
||||||
}
|
}
|
||||||
b'[' => {
|
b'[' => {
|
||||||
try!(self.bump());
|
self.eat_char();
|
||||||
visitor.visit_seq(SeqVisitor::new(self))
|
visitor.visit_seq(SeqVisitor::new(self))
|
||||||
}
|
}
|
||||||
b'{' => {
|
b'{' => {
|
||||||
try!(self.bump());
|
self.eat_char();
|
||||||
visitor.visit_map(MapVisitor::new(self))
|
visitor.visit_map(MapVisitor::new(self))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -134,147 +164,207 @@ impl<Iter> Deserializer<Iter>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ident(&mut self, ident: &[u8]) -> Result<(), Error> {
|
fn parse_ident(&mut self, ident: &[u8]) -> Result<()> {
|
||||||
for c in ident {
|
for c in ident {
|
||||||
if Some(*c) != try!(self.next_char()) {
|
if Some(*c) != try!(self.next_char()) {
|
||||||
return Err(self.error(ErrorCode::ExpectedSomeIdent));
|
return Err(self.error(ErrorCode::ExpectedSomeIdent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try!(self.bump());
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_number<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
fn parse_integer<V>(&mut self, pos: bool, visitor: V) -> Result<V::Value>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
let mut neg = false;
|
match try!(self.next_char_or_null()) {
|
||||||
|
|
||||||
if self.ch_is(b'-') {
|
|
||||||
try!(self.bump());
|
|
||||||
neg = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = try!(self.parse_integer());
|
|
||||||
|
|
||||||
if self.ch_is(b'.') || self.ch_is(b'e') || self.ch_is(b'E') {
|
|
||||||
let mut res = res as f64;
|
|
||||||
|
|
||||||
if self.ch_is(b'.') {
|
|
||||||
res = try!(self.parse_decimal(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.ch_is(b'e') || self.ch_is(b'E') {
|
|
||||||
res = try!(self.parse_exponent(res));
|
|
||||||
}
|
|
||||||
|
|
||||||
if neg {
|
|
||||||
visitor.visit_f64(-res)
|
|
||||||
} else {
|
|
||||||
visitor.visit_f64(res)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if neg {
|
|
||||||
let res = -(res as i64);
|
|
||||||
|
|
||||||
// Make sure we didn't underflow.
|
|
||||||
if res > 0 {
|
|
||||||
Err(self.error(ErrorCode::InvalidNumber))
|
|
||||||
} else {
|
|
||||||
visitor.visit_i64(res)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
visitor.visit_u64(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_integer(&mut self) -> Result<u64, Error> {
|
|
||||||
let mut accum: u64 = 0;
|
|
||||||
|
|
||||||
match self.ch_or_null() {
|
|
||||||
b'0' => {
|
b'0' => {
|
||||||
try!(self.bump());
|
|
||||||
|
|
||||||
// There can be only one leading '0'.
|
// There can be only one leading '0'.
|
||||||
match self.ch_or_null() {
|
match try!(self.peek_or_null()) {
|
||||||
b'0' ... b'9' => {
|
b'0' ... b'9' => {
|
||||||
return Err(self.error(ErrorCode::InvalidNumber));
|
Err(self.error(ErrorCode::InvalidNumber))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.parse_number(pos, 0, visitor)
|
||||||
}
|
}
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
b'1' ... b'9' => {
|
c @ b'1' ... b'9' => {
|
||||||
while !self.eof() {
|
let mut res: u64 = (c as u64) - ('0' as u64);
|
||||||
match self.ch_or_null() {
|
|
||||||
c @ b'0' ... b'9' => {
|
|
||||||
accum = try_or_invalid!(self, accum.checked_mul(10));
|
|
||||||
accum = try_or_invalid!(self, accum.checked_add((c as u64) - ('0' as u64)));
|
|
||||||
|
|
||||||
try!(self.bump());
|
loop {
|
||||||
|
match try!(self.peek_or_null()) {
|
||||||
|
c @ b'0' ... b'9' => {
|
||||||
|
self.eat_char();
|
||||||
|
|
||||||
|
let digit = (c as u64) - ('0' as u64);
|
||||||
|
|
||||||
|
// We need to be careful with overflow. If we can, try to keep the
|
||||||
|
// number as a `u64` until we grow too large. At that point, switch to
|
||||||
|
// parsing the value as a `f64`.
|
||||||
|
match res.checked_mul(10).and_then(|val| val.checked_add(digit)) {
|
||||||
|
Some(res_) => { res = res_; }
|
||||||
|
None => {
|
||||||
|
return self.parse_float(
|
||||||
|
pos,
|
||||||
|
(res as f64) * 10.0 + (digit as f64),
|
||||||
|
visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return self.parse_number(pos, res, visitor);
|
||||||
}
|
}
|
||||||
_ => break,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
|
_ => {
|
||||||
|
Err(self.error(ErrorCode::InvalidNumber))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(accum)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
|
fn parse_float<V>(&mut self,
|
||||||
try!(self.bump());
|
pos: bool,
|
||||||
|
mut res: f64,
|
||||||
|
mut visitor: V) -> Result<V::Value>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
match try!(self.next_char_or_null()) {
|
||||||
|
c @ b'0' ... b'9' => {
|
||||||
|
let digit = (c as u64) - ('0' as u64);
|
||||||
|
|
||||||
|
res *= 10.0;
|
||||||
|
res += digit as f64;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
match try!(self.peek_or_null()) {
|
||||||
|
b'.' => {
|
||||||
|
return self.parse_decimal(pos, res, visitor);
|
||||||
|
}
|
||||||
|
b'e' | b'E' => {
|
||||||
|
return self.parse_exponent(pos, res, visitor);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if !pos {
|
||||||
|
res = -res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return visitor.visit_f64(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_number<V>(&mut self,
|
||||||
|
pos: bool,
|
||||||
|
res: u64,
|
||||||
|
mut visitor: V) -> Result<V::Value>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
match try!(self.peek_or_null()) {
|
||||||
|
b'.' => {
|
||||||
|
self.parse_decimal(pos, res as f64, visitor)
|
||||||
|
}
|
||||||
|
b'e' | b'E' => {
|
||||||
|
self.parse_exponent(pos, res as f64, visitor)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if pos {
|
||||||
|
visitor.visit_u64(res)
|
||||||
|
} else {
|
||||||
|
// FIXME: `wrapping_neg` will be stable in Rust 1.2
|
||||||
|
//let res_i64 = (res as i64).wrapping_neg();
|
||||||
|
let res_i64 = (!res + 1) as i64;
|
||||||
|
|
||||||
|
// Convert into a float if we underflow.
|
||||||
|
if res_i64 > 0 {
|
||||||
|
visitor.visit_f64(-(res as f64))
|
||||||
|
} else {
|
||||||
|
visitor.visit_i64(res_i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_decimal<V>(&mut self,
|
||||||
|
pos: bool,
|
||||||
|
mut res: f64,
|
||||||
|
mut visitor: V) -> Result<V::Value>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
self.eat_char();
|
||||||
|
|
||||||
|
let mut dec = 0.1;
|
||||||
|
|
||||||
// Make sure a digit follows the decimal place.
|
// Make sure a digit follows the decimal place.
|
||||||
match self.ch_or_null() {
|
match try!(self.next_char_or_null()) {
|
||||||
b'0' ... b'9' => (),
|
c @ b'0' ... b'9' => {
|
||||||
|
res += (((c as u64) - (b'0' as u64)) as f64) * dec;
|
||||||
|
}
|
||||||
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
|
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut res = res;
|
loop {
|
||||||
let mut dec = 1.0;
|
match try!(self.peek_or_null()) {
|
||||||
while !self.eof() {
|
|
||||||
match self.ch_or_null() {
|
|
||||||
c @ b'0' ... b'9' => {
|
c @ b'0' ... b'9' => {
|
||||||
|
self.eat_char();
|
||||||
|
|
||||||
dec /= 10.0;
|
dec /= 10.0;
|
||||||
res += (((c as u64) - (b'0' as u64)) as f64) * dec;
|
res += (((c as u64) - (b'0' as u64)) as f64) * dec;
|
||||||
try!(self.bump());
|
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match try!(self.peek_or_null()) {
|
||||||
|
b'e' | b'E' => {
|
||||||
|
self.parse_exponent(pos, res, visitor)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if pos {
|
||||||
|
visitor.visit_f64(res)
|
||||||
|
} else {
|
||||||
|
visitor.visit_f64(-res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
|
fn parse_exponent<V>(&mut self,
|
||||||
try!(self.bump());
|
pos: bool,
|
||||||
|
mut res: f64,
|
||||||
|
mut visitor: V) -> Result<V::Value>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
self.eat_char();
|
||||||
|
|
||||||
let mut exp: u64 = 0;
|
let pos_exp = match try!(self.peek_or_null()) {
|
||||||
let mut neg_exp = false;
|
b'+' => { self.eat_char(); true }
|
||||||
|
b'-' => { self.eat_char(); false }
|
||||||
if self.ch_is(b'+') {
|
_ => { true }
|
||||||
try!(self.bump());
|
};
|
||||||
} else if self.ch_is(b'-') {
|
|
||||||
try!(self.bump());
|
|
||||||
neg_exp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure a digit follows the exponent place.
|
// Make sure a digit follows the exponent place.
|
||||||
match self.ch_or_null() {
|
let mut exp = match try!(self.next_char_or_null()) {
|
||||||
b'0' ... b'9' => (),
|
c @ b'0' ... b'9' => { (c as u64) - (b'0' as u64) }
|
||||||
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
|
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
|
||||||
}
|
};
|
||||||
while !self.eof() {
|
|
||||||
match self.ch_or_null() {
|
loop {
|
||||||
|
match try!(self.peek_or_null()) {
|
||||||
c @ b'0' ... b'9' => {
|
c @ b'0' ... b'9' => {
|
||||||
|
self.eat_char();
|
||||||
|
|
||||||
exp = try_or_invalid!(self, exp.checked_mul(10));
|
exp = try_or_invalid!(self, exp.checked_mul(10));
|
||||||
exp = try_or_invalid!(self, exp.checked_add((c as u64) - (b'0' as u64)));
|
exp = try_or_invalid!(self, exp.checked_add((c as u64) - (b'0' as u64)));
|
||||||
|
|
||||||
try!(self.bump());
|
|
||||||
}
|
}
|
||||||
_ => break
|
_ => { break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,21 +374,24 @@ impl<Iter> Deserializer<Iter>
|
|||||||
return Err(self.error(ErrorCode::InvalidNumber));
|
return Err(self.error(ErrorCode::InvalidNumber));
|
||||||
};
|
};
|
||||||
|
|
||||||
if neg_exp {
|
if pos_exp {
|
||||||
res /= exp;
|
|
||||||
} else {
|
|
||||||
res *= exp;
|
res *= exp;
|
||||||
|
} else {
|
||||||
|
res /= exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(res)
|
if pos {
|
||||||
|
visitor.visit_f64(res)
|
||||||
|
} else {
|
||||||
|
visitor.visit_f64(-res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_hex_escape(&mut self) -> Result<u16, Error> {
|
fn decode_hex_escape(&mut self) -> Result<u16> {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut n = 0u16;
|
let mut n = 0u16;
|
||||||
while i < 4 && !self.eof() {
|
while i < 4 && !try!(self.eof()) {
|
||||||
try!(self.bump());
|
n = match try!(self.next_char_or_null()) {
|
||||||
n = match self.ch_or_null() {
|
|
||||||
c @ b'0' ... b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)),
|
c @ b'0' ... b'9' => n * 16_u16 + ((c as u16) - (b'0' as u16)),
|
||||||
b'a' | b'A' => n * 16_u16 + 10_u16,
|
b'a' | b'A' => n * 16_u16 + 10_u16,
|
||||||
b'b' | b'B' => n * 16_u16 + 11_u16,
|
b'b' | b'B' => n * 16_u16 + 11_u16,
|
||||||
@@ -320,7 +413,7 @@ impl<Iter> Deserializer<Iter>
|
|||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_string(&mut self) -> Result<(), Error> {
|
fn parse_string(&mut self) -> Result<()> {
|
||||||
self.str_buf.clear();
|
self.str_buf.clear();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -331,7 +424,6 @@ impl<Iter> Deserializer<Iter>
|
|||||||
|
|
||||||
match ch {
|
match ch {
|
||||||
b'"' => {
|
b'"' => {
|
||||||
try!(self.bump());
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
b'\\' => {
|
b'\\' => {
|
||||||
@@ -409,16 +501,13 @@ impl<Iter> Deserializer<Iter>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_object_colon(&mut self) -> Result<(), Error> {
|
fn parse_object_colon(&mut self) -> Result<()> {
|
||||||
try!(self.parse_whitespace());
|
try!(self.parse_whitespace());
|
||||||
|
|
||||||
if self.ch_is(b':') {
|
match try!(self.next_char()) {
|
||||||
try!(self.bump());
|
Some(b':') => Ok(()),
|
||||||
Ok(())
|
Some(_) => Err(self.error(ErrorCode::ExpectedColon)),
|
||||||
} else if self.eof() {
|
None => Err(self.error(ErrorCode::EOFWhileParsingObject)),
|
||||||
Err(self.error(ErrorCode::EOFWhileParsingObject))
|
|
||||||
} else {
|
|
||||||
Err(self.error(ErrorCode::ExpectedColon))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,54 +518,74 @@ impl<Iter> de::Deserializer for Deserializer<Iter>
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
fn visit<V>(&mut self, visitor: V) -> Result<V::Value>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
self.parse_value(visitor)
|
self.parse_value(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses a `null` as a None, and any other values as a `Some(...)`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
try!(self.parse_whitespace());
|
try!(self.parse_whitespace());
|
||||||
|
|
||||||
if self.eof() {
|
match try!(self.peek_or_null()) {
|
||||||
return Err(self.error(ErrorCode::EOFWhileParsingValue));
|
b'n' => {
|
||||||
}
|
self.eat_char();
|
||||||
|
try!(self.parse_ident(b"ull"));
|
||||||
if self.ch_is(b'n') {
|
visitor.visit_none()
|
||||||
try!(self.parse_ident(b"ull"));
|
}
|
||||||
visitor.visit_none()
|
_ => {
|
||||||
} else {
|
visitor.visit_some(self)
|
||||||
visitor.visit_some(self)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parses a newtype struct as the underlying value.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_newtype_struct<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
mut visitor: V) -> Result<V::Value>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
visitor.visit_newtype_struct(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses an enum as an object like `{"$KEY":$VALUE}`, where $VALUE is either a straight
|
||||||
|
/// value, a `[..]`, or a `{..}`.
|
||||||
|
#[inline]
|
||||||
|
fn visit_enum<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
mut visitor: V) -> Result<V::Value>
|
||||||
where V: de::EnumVisitor,
|
where V: de::EnumVisitor,
|
||||||
{
|
{
|
||||||
try!(self.parse_whitespace());
|
try!(self.parse_whitespace());
|
||||||
|
|
||||||
if self.ch_is(b'{') {
|
match try!(self.next_char_or_null()) {
|
||||||
try!(self.bump());
|
b'{' => {
|
||||||
try!(self.parse_whitespace());
|
try!(self.parse_whitespace());
|
||||||
|
|
||||||
let value = {
|
let value = {
|
||||||
try!(visitor.visit(&mut *self))
|
try!(visitor.visit(&mut *self))
|
||||||
};
|
};
|
||||||
|
|
||||||
try!(self.parse_whitespace());
|
try!(self.parse_whitespace());
|
||||||
|
|
||||||
if self.ch_is(b'}') {
|
match try!(self.next_char_or_null()) {
|
||||||
try!(self.bump());
|
b'}' => {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
} else {
|
}
|
||||||
|
_ => {
|
||||||
|
Err(self.error(ErrorCode::ExpectedSomeValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
Err(self.error(ErrorCode::ExpectedSomeValue))
|
Err(self.error(ErrorCode::ExpectedSomeValue))
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Err(self.error(ErrorCode::ExpectedSomeValue))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,24 +614,27 @@ impl<'a, Iter> de::SeqVisitor for SeqVisitor<'a, Iter>
|
|||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn visit<T>(&mut self) -> Result<Option<T>, Error>
|
fn visit<T>(&mut self) -> Result<Option<T>>
|
||||||
where T: de::Deserialize,
|
where T: de::Deserialize,
|
||||||
{
|
{
|
||||||
try!(self.de.parse_whitespace());
|
try!(self.de.parse_whitespace());
|
||||||
|
|
||||||
if self.de.ch_is(b']') {
|
match try!(self.de.peek()) {
|
||||||
return Ok(None);
|
Some(b']') => {
|
||||||
}
|
return Ok(None);
|
||||||
|
}
|
||||||
if self.first {
|
Some(b',') if !self.first => {
|
||||||
self.first = false;
|
self.de.eat_char();
|
||||||
} else {
|
}
|
||||||
if self.de.ch_is(b',') {
|
Some(_) => {
|
||||||
try!(self.de.bump());
|
if self.first {
|
||||||
} else if self.de.eof() {
|
self.first = false;
|
||||||
|
} else {
|
||||||
|
return Err(self.de.error(ErrorCode::ExpectedListCommaOrEnd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
return Err(self.de.error(ErrorCode::EOFWhileParsingList));
|
return Err(self.de.error(ErrorCode::EOFWhileParsingList));
|
||||||
} else {
|
|
||||||
return Err(self.de.error(ErrorCode::ExpectedListCommaOrEnd));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,15 +642,17 @@ impl<'a, Iter> de::SeqVisitor for SeqVisitor<'a, Iter>
|
|||||||
Ok(Some(value))
|
Ok(Some(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(&mut self) -> Result<(), Error> {
|
fn end(&mut self) -> Result<()> {
|
||||||
try!(self.de.parse_whitespace());
|
try!(self.de.parse_whitespace());
|
||||||
|
|
||||||
if self.de.ch_is(b']') {
|
match try!(self.de.next_char()) {
|
||||||
self.de.bump()
|
Some(b']') => { Ok(()) }
|
||||||
} else if self.de.eof() {
|
Some(_) => {
|
||||||
Err(self.de.error(ErrorCode::EOFWhileParsingList))
|
Err(self.de.error(ErrorCode::TrailingCharacters))
|
||||||
} else {
|
}
|
||||||
Err(self.de.error(ErrorCode::TrailingCharacters))
|
None => {
|
||||||
|
Err(self.de.error(ErrorCode::EOFWhileParsingList))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,40 +676,45 @@ impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter>
|
|||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn visit_key<K>(&mut self) -> Result<Option<K>, Error>
|
fn visit_key<K>(&mut self) -> Result<Option<K>>
|
||||||
where K: de::Deserialize,
|
where K: de::Deserialize,
|
||||||
{
|
{
|
||||||
try!(self.de.parse_whitespace());
|
try!(self.de.parse_whitespace());
|
||||||
|
|
||||||
if self.de.ch_is(b'}') {
|
match try!(self.de.peek()) {
|
||||||
return Ok(None);
|
Some(b'}') => {
|
||||||
}
|
return Ok(None);
|
||||||
|
}
|
||||||
if self.first {
|
Some(b',') if !self.first => {
|
||||||
self.first = false;
|
self.de.eat_char();
|
||||||
} else {
|
|
||||||
if self.de.ch_is(b',') {
|
|
||||||
try!(self.de.bump());
|
|
||||||
try!(self.de.parse_whitespace());
|
try!(self.de.parse_whitespace());
|
||||||
} else if self.de.eof() {
|
}
|
||||||
|
Some(_) => {
|
||||||
|
if self.first {
|
||||||
|
self.first = false;
|
||||||
|
} else {
|
||||||
|
return Err(self.de.error(ErrorCode::ExpectedObjectCommaOrEnd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
return Err(self.de.error(ErrorCode::EOFWhileParsingObject));
|
return Err(self.de.error(ErrorCode::EOFWhileParsingObject));
|
||||||
} else {
|
|
||||||
return Err(self.de.error(ErrorCode::ExpectedObjectCommaOrEnd));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.de.eof() {
|
match try!(self.de.peek()) {
|
||||||
return Err(self.de.error(ErrorCode::EOFWhileParsingValue));
|
Some(b'"') => {
|
||||||
|
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
|
||||||
|
}
|
||||||
|
Some(_) => {
|
||||||
|
Err(self.de.error(ErrorCode::KeyMustBeAString))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
Err(self.de.error(ErrorCode::EOFWhileParsingValue))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.de.ch_is(b'"') {
|
|
||||||
return Err(self.de.error(ErrorCode::KeyMustBeAString));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some(try!(de::Deserialize::deserialize(self.de))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_value<V>(&mut self) -> Result<V, Error>
|
fn visit_value<V>(&mut self) -> Result<V>
|
||||||
where V: de::Deserialize,
|
where V: de::Deserialize,
|
||||||
{
|
{
|
||||||
try!(self.de.parse_object_colon());
|
try!(self.de.parse_object_colon());
|
||||||
@@ -603,20 +722,21 @@ impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter>
|
|||||||
Ok(try!(de::Deserialize::deserialize(self.de)))
|
Ok(try!(de::Deserialize::deserialize(self.de)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(&mut self) -> Result<(), Error> {
|
fn end(&mut self) -> Result<()> {
|
||||||
try!(self.de.parse_whitespace());
|
try!(self.de.parse_whitespace());
|
||||||
|
|
||||||
if self.de.ch_is(b'}') {
|
match try!(self.de.next_char()) {
|
||||||
try!(self.de.bump());
|
Some(b'}') => { Ok(()) }
|
||||||
Ok(())
|
Some(_) => {
|
||||||
} else if self.de.eof() {
|
Err(self.de.error(ErrorCode::TrailingCharacters))
|
||||||
Err(self.de.error(ErrorCode::EOFWhileParsingObject))
|
}
|
||||||
} else {
|
None => {
|
||||||
Err(self.de.error(ErrorCode::TrailingCharacters))
|
Err(self.de.error(ErrorCode::EOFWhileParsingObject))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V, Error>
|
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V>
|
||||||
where V: de::Deserialize,
|
where V: de::Deserialize,
|
||||||
{
|
{
|
||||||
let mut de = de::value::ValueDeserializer::into_deserializer(());
|
let mut de = de::value::ValueDeserializer::into_deserializer(());
|
||||||
@@ -629,41 +749,47 @@ impl<Iter> de::VariantVisitor for Deserializer<Iter>
|
|||||||
{
|
{
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn visit_variant<V>(&mut self) -> Result<V, Error>
|
fn visit_variant<V>(&mut self) -> Result<V>
|
||||||
where V: de::Deserialize
|
where V: de::Deserialize
|
||||||
{
|
{
|
||||||
de::Deserialize::deserialize(self)
|
let val = try!(de::Deserialize::deserialize(self));
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_unit(&mut self) -> Result<(), Error> {
|
|
||||||
try!(self.parse_object_colon());
|
try!(self.parse_object_colon());
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_unit(&mut self) -> Result<()> {
|
||||||
de::Deserialize::deserialize(self)
|
de::Deserialize::deserialize(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
fn visit_newtype<T>(&mut self) -> Result<T>
|
||||||
|
where T: de::Deserialize,
|
||||||
|
{
|
||||||
|
de::Deserialize::deserialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_tuple<V>(&mut self,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V) -> Result<V::Value>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
try!(self.parse_object_colon());
|
|
||||||
|
|
||||||
de::Deserializer::visit(self, visitor)
|
de::Deserializer::visit(self, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
fn visit_struct<V>(&mut self,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
visitor: V) -> Result<V::Value>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
try!(self.parse_object_colon());
|
|
||||||
|
|
||||||
de::Deserializer::visit(self, visitor)
|
de::Deserializer::visit(self, visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a json value from a `std::io::Read`.
|
/// Decodes a json value from a `std::io::Read`.
|
||||||
pub fn from_iter<I, T>(iter: I) -> Result<T, Error>
|
pub fn from_iter<I, T>(iter: I) -> Result<T>
|
||||||
where I: Iterator<Item=io::Result<u8>>,
|
where I: Iterator<Item=io::Result<u8>>,
|
||||||
T: de::Deserialize,
|
T: de::Deserialize,
|
||||||
{
|
{
|
||||||
let mut de = try!(Deserializer::new(iter));
|
let mut de = Deserializer::new(iter);
|
||||||
let value = try!(de::Deserialize::deserialize(&mut de));
|
let value = try!(de::Deserialize::deserialize(&mut de));
|
||||||
|
|
||||||
// Make sure the whole stream has been consumed.
|
// Make sure the whole stream has been consumed.
|
||||||
@@ -672,7 +798,7 @@ pub fn from_iter<I, T>(iter: I) -> Result<T, Error>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a json value from a `std::io::Read`.
|
/// Decodes a json value from a `std::io::Read`.
|
||||||
pub fn from_reader<R, T>(rdr: R) -> Result<T, Error>
|
pub fn from_reader<R, T>(rdr: R) -> Result<T>
|
||||||
where R: io::Read,
|
where R: io::Read,
|
||||||
T: de::Deserialize,
|
T: de::Deserialize,
|
||||||
{
|
{
|
||||||
@@ -680,14 +806,14 @@ pub fn from_reader<R, T>(rdr: R) -> Result<T, Error>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a json value from a `&str`.
|
/// Decodes a json value from a `&str`.
|
||||||
pub fn from_slice<T>(v: &[u8]) -> Result<T, Error>
|
pub fn from_slice<T>(v: &[u8]) -> Result<T>
|
||||||
where T: de::Deserialize
|
where T: de::Deserialize
|
||||||
{
|
{
|
||||||
from_iter(v.iter().map(|byte| Ok(*byte)))
|
from_iter(v.iter().map(|byte| Ok(*byte)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a json value from a `&str`.
|
/// Decodes a json value from a `&str`.
|
||||||
pub fn from_str<T>(s: &str) -> Result<T, Error>
|
pub fn from_str<T>(s: &str) -> Result<T>
|
||||||
where T: de::Deserialize
|
where T: de::Deserialize
|
||||||
{
|
{
|
||||||
from_slice(s.as_bytes())
|
from_slice(s.as_bytes())
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::result;
|
||||||
|
|
||||||
use de;
|
use serde::de;
|
||||||
|
|
||||||
/// The errors that can arise while parsing a JSON stream.
|
/// The errors that can arise while parsing a JSON stream.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
@@ -151,35 +152,38 @@ impl From<de::value::Error> for Error {
|
|||||||
fn from(error: de::value::Error) -> Error {
|
fn from(error: de::value::Error) -> Error {
|
||||||
match error {
|
match error {
|
||||||
de::value::Error::SyntaxError => {
|
de::value::Error::SyntaxError => {
|
||||||
de::Error::syntax_error()
|
Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)
|
||||||
}
|
}
|
||||||
de::value::Error::EndOfStreamError => {
|
de::value::Error::EndOfStreamError => {
|
||||||
de::Error::end_of_stream_error()
|
de::Error::end_of_stream()
|
||||||
}
|
}
|
||||||
de::value::Error::UnknownFieldError(field) => {
|
de::value::Error::UnknownFieldError(field) => {
|
||||||
Error::SyntaxError(ErrorCode::UnknownField(field), 0, 0)
|
Error::SyntaxError(ErrorCode::UnknownField(field), 0, 0)
|
||||||
}
|
}
|
||||||
de::value::Error::MissingFieldError(field) => {
|
de::value::Error::MissingFieldError(field) => {
|
||||||
de::Error::missing_field_error(field)
|
de::Error::missing_field(field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl de::Error for Error {
|
impl de::Error for Error {
|
||||||
fn syntax_error() -> Error {
|
fn syntax(_: &str) -> Error {
|
||||||
Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)
|
Error::SyntaxError(ErrorCode::ExpectedSomeValue, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end_of_stream_error() -> Error {
|
fn end_of_stream() -> Error {
|
||||||
Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 0, 0)
|
Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unknown_field_error(field: &str) -> Error {
|
fn unknown_field(field: &str) -> Error {
|
||||||
Error::SyntaxError(ErrorCode::UnknownField(field.to_string()), 0, 0)
|
Error::SyntaxError(ErrorCode::UnknownField(field.to_string()), 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing_field_error(field: &'static str) -> Error {
|
fn missing_field(field: &'static str) -> Error {
|
||||||
Error::MissingFieldError(field)
|
Error::MissingFieldError(field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper alias for `Result` objects that return a JSON `Error`.
|
||||||
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
//! encode structured data in a text format that can be easily read by humans. Its simple syntax
|
//! encode structured data in a text format that can be easily read by humans. Its simple syntax
|
||||||
//! and native compatibility with JavaScript have made it a widely used format.
|
//! and native compatibility with JavaScript have made it a widely used format.
|
||||||
//!
|
//!
|
||||||
//! Data types that can be encoded are JavaScript types (see the `serde::json:Value` enum for more
|
//! Data types that can be encoded are JavaScript types (see the `serde_json:Value` enum for more
|
||||||
//! details):
|
//! details):
|
||||||
//!
|
//!
|
||||||
//! * `Boolean`: equivalent to rust's `bool`
|
//! * `Boolean`: equivalent to rust's `bool`
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
//! * `String`: equivalent to rust's `String`
|
//! * `String`: equivalent to rust's `String`
|
||||||
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
|
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
|
||||||
//! same array
|
//! same array
|
||||||
//! * `Object`: equivalent to rust's `BTreeMap<String, serde::json::Value>`
|
//! * `Object`: equivalent to rust's `BTreeMap<String, serde_json::Value>`
|
||||||
//! * `Null`
|
//! * `Null`
|
||||||
//!
|
//!
|
||||||
//! An object is a series of string keys mapping to values, in `"key": value` format. Arrays are
|
//! An object is a series of string keys mapping to values, in `"key": value` format. Arrays are
|
||||||
@@ -48,8 +48,8 @@
|
|||||||
//! `serde::Deserialize` trait. Serde provides provides an annotation to automatically generate
|
//! `serde::Deserialize` trait. Serde provides provides an annotation to automatically generate
|
||||||
//! the code for these traits: `#[derive(Serialize, Deserialize)]`.
|
//! the code for these traits: `#[derive(Serialize, Deserialize)]`.
|
||||||
//!
|
//!
|
||||||
//! The JSON API also provides an enum `serde::json::Value` and a method `to_value` to serialize
|
//! The JSON API also provides an enum `serde_json::Value` and a method `to_value` to serialize
|
||||||
//! objects. A `serde::json::Value` value can be serialized as a string or buffer using the
|
//! objects. A `serde_json::Value` value can be serialized as a string or buffer using the
|
||||||
//! functions described above. You can also use the `json::Serializer` object, which implements the
|
//! functions described above. You can also use the `json::Serializer` object, which implements the
|
||||||
//! `Serializer` trait.
|
//! `Serializer` trait.
|
||||||
//!
|
//!
|
||||||
@@ -61,12 +61,12 @@
|
|||||||
//! //#![feature(custom_derive, plugin)]
|
//! //#![feature(custom_derive, plugin)]
|
||||||
//! //#![plugin(serde_macros)]
|
//! //#![plugin(serde_macros)]
|
||||||
//!
|
//!
|
||||||
//! extern crate serde;
|
//! extern crate serde_json;
|
||||||
//!
|
//!
|
||||||
//! use serde::json::{self, Value};
|
//! use serde_json::Value;
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! let data: Value = json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
|
//! let data: Value = serde_json::from_str("{\"foo\": 13, \"bar\": \"baz\"}").unwrap();
|
||||||
//! println!("data: {:?}", data);
|
//! println!("data: {:?}", data);
|
||||||
//! // data: {"bar":"baz","foo":13}
|
//! // data: {"bar":"baz","foo":13}
|
||||||
//! println!("object? {}", data.is_object());
|
//! println!("object? {}", data.is_object());
|
||||||
@@ -92,8 +92,11 @@
|
|||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
extern crate num;
|
||||||
|
extern crate serde;
|
||||||
|
|
||||||
pub use self::de::{Deserializer, from_str};
|
pub use self::de::{Deserializer, from_str};
|
||||||
pub use self::error::{Error, ErrorCode};
|
pub use self::error::{Error, ErrorCode, Result};
|
||||||
pub use self::ser::{
|
pub use self::ser::{
|
||||||
Serializer,
|
Serializer,
|
||||||
to_writer,
|
to_writer,
|
||||||
@@ -2,7 +2,7 @@ use std::io;
|
|||||||
use std::num::FpCategory;
|
use std::num::FpCategory;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
|
|
||||||
use ser;
|
use serde::ser;
|
||||||
|
|
||||||
/// A structure for implementing serialization to JSON.
|
/// A structure for implementing serialization to JSON.
|
||||||
pub struct Serializer<W, F=CompactFormatter> {
|
pub struct Serializer<W, F=CompactFormatter> {
|
||||||
@@ -158,8 +158,21 @@ impl<W, F> ser::Serializer for Serializer<W, F>
|
|||||||
self.writer.write_all(b"null")
|
self.writer.write_all(b"null")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Override `visit_newtype_struct` to serialize newtypes without an object wrapper.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> io::Result<()> {
|
fn visit_newtype_struct<T>(&mut self,
|
||||||
|
_name: &'static str,
|
||||||
|
value: T) -> Result<(), Self::Error>
|
||||||
|
where T: ser::Serialize,
|
||||||
|
{
|
||||||
|
value.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_unit_variant(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str) -> io::Result<()> {
|
||||||
try!(self.formatter.open(&mut self.writer, b'{'));
|
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||||
try!(self.formatter.comma(&mut self.writer, true));
|
try!(self.formatter.comma(&mut self.writer, true));
|
||||||
try!(self.visit_str(variant));
|
try!(self.visit_str(variant));
|
||||||
@@ -168,6 +181,22 @@ impl<W, F> ser::Serializer for Serializer<W, F>
|
|||||||
self.formatter.close(&mut self.writer, b'}')
|
self.formatter.close(&mut self.writer, b'}')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_newtype_variant<T>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str,
|
||||||
|
value: T) -> io::Result<()>
|
||||||
|
where T: ser::Serialize,
|
||||||
|
{
|
||||||
|
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||||
|
try!(self.formatter.comma(&mut self.writer, true));
|
||||||
|
try!(self.visit_str(variant));
|
||||||
|
try!(self.formatter.colon(&mut self.writer));
|
||||||
|
try!(value.serialize(self));
|
||||||
|
self.formatter.close(&mut self.writer, b'}')
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
|
fn visit_seq<V>(&mut self, mut visitor: V) -> io::Result<()>
|
||||||
where V: ser::SeqVisitor,
|
where V: ser::SeqVisitor,
|
||||||
@@ -190,7 +219,11 @@ impl<W, F> ser::Serializer for Serializer<W, F>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
|
fn visit_tuple_variant<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str,
|
||||||
|
visitor: V) -> io::Result<()>
|
||||||
where V: ser::SeqVisitor,
|
where V: ser::SeqVisitor,
|
||||||
{
|
{
|
||||||
try!(self.formatter.open(&mut self.writer, b'{'));
|
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||||
@@ -206,9 +239,11 @@ impl<W, F> ser::Serializer for Serializer<W, F>
|
|||||||
where T: ser::Serialize,
|
where T: ser::Serialize,
|
||||||
{
|
{
|
||||||
try!(self.formatter.comma(&mut self.writer, self.first));
|
try!(self.formatter.comma(&mut self.writer, self.first));
|
||||||
|
try!(value.serialize(self));
|
||||||
|
|
||||||
self.first = false;
|
self.first = false;
|
||||||
|
|
||||||
value.serialize(self)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -232,7 +267,11 @@ impl<W, F> ser::Serializer for Serializer<W, F>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> io::Result<()>
|
fn visit_struct_variant<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str,
|
||||||
|
visitor: V) -> io::Result<()>
|
||||||
where V: ser::MapVisitor,
|
where V: ser::MapVisitor,
|
||||||
{
|
{
|
||||||
try!(self.formatter.open(&mut self.writer, b'{'));
|
try!(self.formatter.open(&mut self.writer, b'{'));
|
||||||
@@ -250,11 +289,14 @@ impl<W, F> ser::Serializer for Serializer<W, F>
|
|||||||
V: ser::Serialize,
|
V: ser::Serialize,
|
||||||
{
|
{
|
||||||
try!(self.formatter.comma(&mut self.writer, self.first));
|
try!(self.formatter.comma(&mut self.writer, self.first));
|
||||||
self.first = false;
|
|
||||||
|
|
||||||
try!(key.serialize(self));
|
try!(key.serialize(self));
|
||||||
try!(self.formatter.colon(&mut self.writer));
|
try!(self.formatter.colon(&mut self.writer));
|
||||||
value.serialize(self)
|
try!(value.serialize(self));
|
||||||
|
|
||||||
|
self.first = false;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -423,12 +465,7 @@ fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> io::Result<()>
|
|||||||
match value.classify() {
|
match value.classify() {
|
||||||
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
|
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
|
||||||
_ => {
|
_ => {
|
||||||
let s = format!("{:?}", value);
|
write!(wr, "{:?}", value)
|
||||||
try!(wr.write_all(s.as_bytes()));
|
|
||||||
if !s.contains('.') {
|
|
||||||
try!(wr.write_all(b".0"))
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,12 +476,7 @@ fn fmt_f64_or_null<W>(wr: &mut W, value: f64) -> io::Result<()>
|
|||||||
match value.classify() {
|
match value.classify() {
|
||||||
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
|
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
|
||||||
_ => {
|
_ => {
|
||||||
let s = format!("{:?}", value);
|
write!(wr, "{:?}", value)
|
||||||
try!(wr.write_all(s.as_bytes()));
|
|
||||||
if !s.contains('.') {
|
|
||||||
try!(wr.write_all(b".0"))
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,9 +6,10 @@ use std::vec;
|
|||||||
|
|
||||||
use num::NumCast;
|
use num::NumCast;
|
||||||
|
|
||||||
use de;
|
use serde::de;
|
||||||
use ser;
|
use serde::ser;
|
||||||
use super::error::Error;
|
|
||||||
|
use error::Error;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
@@ -458,7 +459,10 @@ impl ser::Serializer for Serializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_unit(&mut self, _name: &str, variant: &str) -> Result<(), ()> {
|
fn visit_unit_variant(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str) -> Result<(), ()> {
|
||||||
let mut values = BTreeMap::new();
|
let mut values = BTreeMap::new();
|
||||||
values.insert(variant.to_string(), Value::Array(vec![]));
|
values.insert(variant.to_string(), Value::Array(vec![]));
|
||||||
|
|
||||||
@@ -467,6 +471,22 @@ impl ser::Serializer for Serializer {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_newtype_variant<T>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str,
|
||||||
|
value: T) -> Result<(), ()>
|
||||||
|
where T: ser::Serialize,
|
||||||
|
{
|
||||||
|
let mut values = BTreeMap::new();
|
||||||
|
values.insert(variant.to_string(), to_value(&value));
|
||||||
|
|
||||||
|
self.state.push(State::Value(Value::Object(values)));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), ()>
|
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), ()>
|
||||||
where V: ser::SeqVisitor,
|
where V: ser::SeqVisitor,
|
||||||
@@ -489,7 +509,11 @@ impl ser::Serializer for Serializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_seq<V>(&mut self, _name: &str, variant: &str, visitor: V) -> Result<(), ()>
|
fn visit_tuple_variant<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str,
|
||||||
|
visitor: V) -> Result<(), ()>
|
||||||
where V: ser::SeqVisitor,
|
where V: ser::SeqVisitor,
|
||||||
{
|
{
|
||||||
try!(self.visit_seq(visitor));
|
try!(self.visit_seq(visitor));
|
||||||
@@ -548,7 +572,11 @@ impl ser::Serializer for Serializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum_map<V>(&mut self, _name: &str, variant: &str, visitor: V) -> Result<(), ()>
|
fn visit_struct_variant<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str,
|
||||||
|
visitor: V) -> Result<(), ()>
|
||||||
where V: ser::MapVisitor,
|
where V: ser::MapVisitor,
|
||||||
{
|
{
|
||||||
try!(self.visit_map(visitor));
|
try!(self.visit_map(visitor));
|
||||||
@@ -622,7 +650,7 @@ impl de::Deserializer for Deserializer {
|
|||||||
{
|
{
|
||||||
let value = match self.value.take() {
|
let value = match self.value.take() {
|
||||||
Some(value) => value,
|
Some(value) => value,
|
||||||
None => { return Err(de::Error::end_of_stream_error()); }
|
None => { return Err(de::Error::end_of_stream()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
match value {
|
match value {
|
||||||
@@ -659,58 +687,121 @@ impl de::Deserializer for Deserializer {
|
|||||||
match self.value {
|
match self.value {
|
||||||
Some(Value::Null) => visitor.visit_none(),
|
Some(Value::Null) => visitor.visit_none(),
|
||||||
Some(_) => visitor.visit_some(self),
|
Some(_) => visitor.visit_some(self),
|
||||||
None => Err(de::Error::end_of_stream_error()),
|
None => Err(de::Error::end_of_stream()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_enum<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
mut visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::EnumVisitor,
|
where V: de::EnumVisitor,
|
||||||
{
|
{
|
||||||
let value = match self.value.take() {
|
let value = match self.value.take() {
|
||||||
Some(Value::Object(value)) => value,
|
Some(Value::Object(value)) => value,
|
||||||
Some(_) => { return Err(de::Error::syntax_error()); }
|
Some(_) => { return Err(de::Error::syntax("expected an enum")); }
|
||||||
None => { return Err(de::Error::end_of_stream_error()); }
|
None => { return Err(de::Error::end_of_stream()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut iter = value.into_iter();
|
let mut iter = value.into_iter();
|
||||||
|
|
||||||
let value = match iter.next() {
|
let (variant, value) = match iter.next() {
|
||||||
Some((variant, Value::Array(fields))) => {
|
Some(v) => v,
|
||||||
self.value = Some(Value::String(variant));
|
None => return Err(de::Error::syntax("expected a variant name")),
|
||||||
|
|
||||||
let len = fields.len();
|
|
||||||
try!(visitor.visit(SeqDeserializer {
|
|
||||||
de: self,
|
|
||||||
iter: fields.into_iter(),
|
|
||||||
len: len,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
Some((variant, Value::Object(fields))) => {
|
|
||||||
let len = fields.len();
|
|
||||||
try!(visitor.visit(MapDeserializer {
|
|
||||||
de: self,
|
|
||||||
iter: fields.into_iter(),
|
|
||||||
value: Some(Value::String(variant)),
|
|
||||||
len: len,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
Some(_) => { return Err(de::Error::syntax_error()); }
|
|
||||||
None => { return Err(de::Error::syntax_error()); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// enums are encoded in json as maps with a single key:value pair
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
Some(_) => Err(de::Error::syntax_error()),
|
Some(_) => Err(de::Error::syntax("expected map")),
|
||||||
None => Ok(value)
|
None => visitor.visit(VariantDeserializer {
|
||||||
|
de: self,
|
||||||
|
val: Some(value),
|
||||||
|
variant: Some(Value::String(variant)),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_newtype_struct<V>(&mut self,
|
||||||
|
_name: &'static str,
|
||||||
|
mut visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
visitor.visit_newtype_struct(self)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format() -> &'static str {
|
fn format() -> &'static str {
|
||||||
"json"
|
"json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VariantDeserializer<'a> {
|
||||||
|
de: &'a mut Deserializer,
|
||||||
|
val: Option<Value>,
|
||||||
|
variant: Option<Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> de::VariantVisitor for VariantDeserializer<'a> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn visit_variant<V>(&mut self) -> Result<V, Error>
|
||||||
|
where V: de::Deserialize,
|
||||||
|
{
|
||||||
|
de::Deserialize::deserialize(&mut Deserializer::new(self.variant.take().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_unit(&mut self) -> Result<(), Error> {
|
||||||
|
de::Deserialize::deserialize(&mut Deserializer::new(self.val.take().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_newtype<T>(&mut self) -> Result<T, Error>
|
||||||
|
where T: de::Deserialize,
|
||||||
|
{
|
||||||
|
de::Deserialize::deserialize(&mut Deserializer::new(self.val.take().unwrap()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_tuple<V>(&mut self,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V) -> Result<V::Value, Error>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
if let Value::Array(fields) = self.val.take().unwrap() {
|
||||||
|
de::Deserializer::visit(
|
||||||
|
&mut SeqDeserializer {
|
||||||
|
de: self.de,
|
||||||
|
len: fields.len(),
|
||||||
|
iter: fields.into_iter(),
|
||||||
|
},
|
||||||
|
visitor,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Err(de::Error::syntax("expected a tuple"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_struct<V>(&mut self,
|
||||||
|
_fields: &'static[&'static str],
|
||||||
|
visitor: V) -> Result<V::Value, Error>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
if let Value::Object(fields) = self.val.take().unwrap() {
|
||||||
|
de::Deserializer::visit(
|
||||||
|
&mut MapDeserializer {
|
||||||
|
de: self.de,
|
||||||
|
len: fields.len(),
|
||||||
|
iter: fields.into_iter(),
|
||||||
|
value: None,
|
||||||
|
},
|
||||||
|
visitor,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Err(de::Error::syntax("expected a struct"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct SeqDeserializer<'a> {
|
struct SeqDeserializer<'a> {
|
||||||
de: &'a mut Deserializer,
|
de: &'a mut Deserializer,
|
||||||
iter: vec::IntoIter<Value>,
|
iter: vec::IntoIter<Value>,
|
||||||
@@ -752,7 +843,7 @@ impl<'a> de::SeqVisitor for SeqDeserializer<'a> {
|
|||||||
if self.len == 0 {
|
if self.len == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(de::Error::end_of_stream_error())
|
Err(de::Error::length_mismatch(self.len))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -761,33 +852,6 @@ impl<'a> de::SeqVisitor for SeqDeserializer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> de::VariantVisitor for SeqDeserializer<'a> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn visit_variant<V>(&mut self) -> Result<V, Error>
|
|
||||||
where V: de::Deserialize,
|
|
||||||
{
|
|
||||||
de::Deserialize::deserialize(self.de)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_unit(&mut self) -> Result<(), Error>
|
|
||||||
{
|
|
||||||
de::Deserialize::deserialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where V: de::Visitor,
|
|
||||||
{
|
|
||||||
de::Deserializer::visit(self, visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where V: de::Visitor,
|
|
||||||
{
|
|
||||||
de::Deserializer::visit(self, visitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MapDeserializer<'a> {
|
struct MapDeserializer<'a> {
|
||||||
de: &'a mut Deserializer,
|
de: &'a mut Deserializer,
|
||||||
iter: btree_map::IntoIter<String, Value>,
|
iter: btree_map::IntoIter<String, Value>,
|
||||||
@@ -824,7 +888,7 @@ impl<'a> de::MapVisitor for MapDeserializer<'a> {
|
|||||||
if self.len == 0 {
|
if self.len == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(de::Error::end_of_stream_error())
|
Err(de::Error::length_mismatch(self.len))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -865,38 +929,10 @@ impl<'a> de::Deserializer for MapDeserializer<'a> {
|
|||||||
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
println!("MapDeserializer!");
|
|
||||||
visitor.visit_map(self)
|
visitor.visit_map(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> de::VariantVisitor for MapDeserializer<'a> {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
fn visit_variant<V>(&mut self) -> Result<V, Error>
|
|
||||||
where V: de::Deserialize,
|
|
||||||
{
|
|
||||||
self.de.value = self.value.take();
|
|
||||||
de::Deserialize::deserialize(self.de)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_unit(&mut self) -> Result<(), Error> {
|
|
||||||
de::Deserialize::deserialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where V: de::Visitor,
|
|
||||||
{
|
|
||||||
de::Deserializer::visit(self, visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
|
||||||
where V: de::Visitor,
|
|
||||||
{
|
|
||||||
de::Deserializer::visit(self, visitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Shortcut function to encode a `T` into a JSON `Value`
|
/// Shortcut function to encode a `T` into a JSON `Value`
|
||||||
pub fn to_value<T>(value: &T) -> Value
|
pub fn to_value<T>(value: &T) -> Value
|
||||||
where T: ser::Serialize
|
where T: ser::Serialize
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_macros"
|
name = "serde_macros"
|
||||||
version = "0.4.3"
|
version = "0.5.1"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Macros to auto-generate implementations for the serde framework"
|
description = "Macros to auto-generate implementations for the serde framework"
|
||||||
repository = "https://github.com/erickt/rust-serde"
|
repository = "https://github.com/serde-rs/serde"
|
||||||
|
documentation = "https://github.com/serde-rs/serde"
|
||||||
|
keywords = ["serde", "serialization"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "serde_macros"
|
name = "serde_macros"
|
||||||
plugin = true
|
plugin = true
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["serde/nightly"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde_codegen = { version = "*", path = "../serde_codegen", default-features = false, features = ["nightly"] }
|
serde_codegen = { version = "*", path = "../serde_codegen", default-features = false, features = ["nightly"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
num = "*"
|
num = "*"
|
||||||
rustc-serialize = "*"
|
rustc-serialize = "*"
|
||||||
serde = { version = "*", path = "../serde" }
|
serde = { version = "*", path = "../serde", features = ["nightly"] }
|
||||||
|
serde_json = { version = "*", path = "../serde_json" }
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
extern crate num;
|
extern crate num;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
include!("../../serde_tests/benches/bench.rs.in");
|
include!("../../serde_tests/benches/bench.rs.in");
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
#![plugin(serde_macros)]
|
#![plugin(serde_macros)]
|
||||||
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use serde::json;
|
|
||||||
|
|
||||||
// Creating serializable types with serde is quite simple with `serde_macros`. It implements a
|
// Creating serializable types with serde is quite simple with `serde_macros`. It implements a
|
||||||
// syntax extension that automatically generates the necessary serde trait implementations.
|
// syntax extension that automatically generates the necessary serde trait implementations.
|
||||||
@@ -18,7 +18,7 @@ fn main() {
|
|||||||
let point = Point { x: 5, y: 6 };
|
let point = Point { x: 5, y: 6 };
|
||||||
|
|
||||||
// Serializing to JSON is pretty simple by using the `to_string` method:
|
// Serializing to JSON is pretty simple by using the `to_string` method:
|
||||||
let serialized_point = json::to_string(&point).unwrap();
|
let serialized_point = serde_json::to_string(&point).unwrap();
|
||||||
|
|
||||||
println!("{}", serialized_point);
|
println!("{}", serialized_point);
|
||||||
// prints:
|
// prints:
|
||||||
@@ -26,7 +26,7 @@ fn main() {
|
|||||||
// {"x":5,"y":6}
|
// {"x":5,"y":6}
|
||||||
|
|
||||||
// There is also support for pretty printing using `to_string_pretty`:
|
// There is also support for pretty printing using `to_string_pretty`:
|
||||||
let serialized_point = json::to_string_pretty(&point).unwrap();
|
let serialized_point = serde_json::to_string_pretty(&point).unwrap();
|
||||||
|
|
||||||
println!("{}", serialized_point);
|
println!("{}", serialized_point);
|
||||||
// prints:
|
// prints:
|
||||||
@@ -37,7 +37,7 @@ fn main() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Values can also be deserialized with the same style using `from_str`:
|
// Values can also be deserialized with the same style using `from_str`:
|
||||||
let deserialized_point: Point = json::from_str(&serialized_point).unwrap();
|
let deserialized_point: Point = serde_json::from_str(&serialized_point).unwrap();
|
||||||
|
|
||||||
println!("{:?}", deserialized_point);
|
println!("{:?}", deserialized_point);
|
||||||
// prints:
|
// prints:
|
||||||
@@ -46,16 +46,18 @@ fn main() {
|
|||||||
|
|
||||||
// `Point`s aren't the only type that can be serialized to. Because `Point` members have the
|
// `Point`s aren't the only type that can be serialized to. Because `Point` members have the
|
||||||
// same type, they can be also serialized into a map. Also,
|
// same type, they can be also serialized into a map. Also,
|
||||||
let deserialized_map: BTreeMap<String, i64> = json::from_str(&serialized_point).unwrap();
|
let deserialized_map: BTreeMap<String, i64> =
|
||||||
|
serde_json::from_str(&serialized_point).unwrap();
|
||||||
|
|
||||||
println!("{:?}", deserialized_map);
|
println!("{:?}", deserialized_map);
|
||||||
// prints:
|
// prints:
|
||||||
//
|
//
|
||||||
// {"x": 5, "y": 6}
|
// {"x": 5, "y": 6}
|
||||||
|
|
||||||
// If you need to accept arbitrary data, you can also deserialize into `json::Value`, which
|
// If you need to accept arbitrary data, you can also deserialize into `serde_json::Value`,
|
||||||
// can represent all JSON values.
|
// which can represent all JSON values.
|
||||||
let deserialized_value: json::Value = json::from_str(&serialized_point).unwrap();
|
let deserialized_value: serde_json::Value =
|
||||||
|
serde_json::from_str(&serialized_point).unwrap();
|
||||||
|
|
||||||
println!("{:?}", deserialized_value);
|
println!("{:?}", deserialized_value);
|
||||||
// prints:
|
// prints:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#![plugin(serde_macros)]
|
#![plugin(serde_macros)]
|
||||||
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
include!("../../serde_tests/tests/test.rs.in");
|
include!("../../serde_tests/tests/test.rs.in");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_tests"
|
name = "serde_tests"
|
||||||
version = "0.4.3"
|
version = "0.5.0"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
@@ -11,7 +11,7 @@ keywords = ["serialization"]
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
syntex = { version = "*", optional = true }
|
syntex = { version = "*" }
|
||||||
syntex_syntax = { version = "*" }
|
syntex_syntax = { version = "*" }
|
||||||
serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-syntex"] }
|
serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-syntex"] }
|
||||||
|
|
||||||
@@ -19,6 +19,7 @@ serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-sy
|
|||||||
num = "*"
|
num = "*"
|
||||||
rustc-serialize = "*"
|
rustc-serialize = "*"
|
||||||
serde = { version = "*", path = "../serde" }
|
serde = { version = "*", path = "../serde" }
|
||||||
|
serde_json = { version = "*", path = "../serde_json" }
|
||||||
syntex = "*"
|
syntex = "*"
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
extern crate num;
|
extern crate num;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/bench.rs"));
|
include!(concat!(env!("OUT_DIR"), "/bench.rs"));
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl serde::de::Error for Error {
|
impl serde::de::Error for Error {
|
||||||
fn syntax_error() -> Error { Error::SyntaxError }
|
fn syntax(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
|
fn end_of_stream() -> Error { Error::EndOfStreamError }
|
||||||
|
|
||||||
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
|
fn unknown_field(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn missing_field_error(_: &'static str) -> Error { Error::SyntaxError }
|
fn missing_field(_: &'static str) -> Error { Error::SyntaxError }
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -288,7 +288,10 @@ mod deserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_enum<V>(&mut self, _name: &str, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_enum<V>(&mut self,
|
||||||
|
_name: &str,
|
||||||
|
_variants: &[&str],
|
||||||
|
mut visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::EnumVisitor,
|
where V: de::EnumVisitor,
|
||||||
{
|
{
|
||||||
match self.stack.pop() {
|
match self.stack.pop() {
|
||||||
@@ -350,7 +353,9 @@ mod deserializer {
|
|||||||
de::Deserialize::deserialize(self.de)
|
de::Deserialize::deserialize(self.de)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_tuple<V>(&mut self,
|
||||||
|
_len: usize,
|
||||||
|
mut visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
visitor.visit_seq(self)
|
visitor.visit_seq(self)
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ use test::Bencher;
|
|||||||
use rustc_serialize;
|
use rustc_serialize;
|
||||||
|
|
||||||
use serde::de::{self, Deserialize, Deserializer};
|
use serde::de::{self, Deserialize, Deserializer};
|
||||||
use serde::json::ser::escape_str;
|
|
||||||
use serde::json;
|
|
||||||
use serde::ser::{self, Serialize, Serializer};
|
use serde::ser::{self, Serialize, Serializer};
|
||||||
|
use serde_json::ser::escape_str;
|
||||||
|
use serde_json;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use rustc_serialize::Encodable;
|
use rustc_serialize::Encodable;
|
||||||
@@ -1123,18 +1123,18 @@ fn bench_encoder(b: &mut Bencher) {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_serializer() {
|
fn test_serializer() {
|
||||||
let log = Log::new();
|
let log = Log::new();
|
||||||
let json = json::to_vec(&log);
|
let json = serde_json::to_vec(&log);
|
||||||
assert_eq!(json, JSON_STR.as_bytes());
|
assert_eq!(json, JSON_STR.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_serializer(b: &mut Bencher) {
|
fn bench_serializer(b: &mut Bencher) {
|
||||||
let log = Log::new();
|
let log = Log::new();
|
||||||
let json = json::to_vec(&log);
|
let json = serde_json::to_vec(&log);
|
||||||
b.bytes = json.len() as u64;
|
b.bytes = json.len() as u64;
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let _ = json::to_vec(&log);
|
let _ = serde_json::to_vec(&log);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1142,7 +1142,7 @@ fn bench_serializer(b: &mut Bencher) {
|
|||||||
fn test_serializer_vec() {
|
fn test_serializer_vec() {
|
||||||
let log = Log::new();
|
let log = Log::new();
|
||||||
let wr = Vec::with_capacity(1024);
|
let wr = Vec::with_capacity(1024);
|
||||||
let mut serializer = json::Serializer::new(wr);
|
let mut serializer = serde_json::Serializer::new(wr);
|
||||||
log.serialize(&mut serializer).unwrap();
|
log.serialize(&mut serializer).unwrap();
|
||||||
|
|
||||||
let json = serializer.into_inner();
|
let json = serializer.into_inner();
|
||||||
@@ -1152,7 +1152,7 @@ fn test_serializer_vec() {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_serializer_vec(b: &mut Bencher) {
|
fn bench_serializer_vec(b: &mut Bencher) {
|
||||||
let log = Log::new();
|
let log = Log::new();
|
||||||
let json = json::to_vec(&log);
|
let json = serde_json::to_vec(&log);
|
||||||
b.bytes = json.len() as u64;
|
b.bytes = json.len() as u64;
|
||||||
|
|
||||||
let mut wr = Vec::with_capacity(1024);
|
let mut wr = Vec::with_capacity(1024);
|
||||||
@@ -1160,7 +1160,7 @@ fn bench_serializer_vec(b: &mut Bencher) {
|
|||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
wr.clear();
|
wr.clear();
|
||||||
|
|
||||||
let mut serializer = json::Serializer::new(wr.by_ref());
|
let mut serializer = serde_json::Serializer::new(wr.by_ref());
|
||||||
log.serialize(&mut serializer).unwrap();
|
log.serialize(&mut serializer).unwrap();
|
||||||
let _json = serializer.into_inner();
|
let _json = serializer.into_inner();
|
||||||
});
|
});
|
||||||
@@ -1169,7 +1169,7 @@ fn bench_serializer_vec(b: &mut Bencher) {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_serializer_slice(b: &mut Bencher) {
|
fn bench_serializer_slice(b: &mut Bencher) {
|
||||||
let log = Log::new();
|
let log = Log::new();
|
||||||
let json = json::to_vec(&log);
|
let json = serde_json::to_vec(&log);
|
||||||
b.bytes = json.len() as u64;
|
b.bytes = json.len() as u64;
|
||||||
|
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
@@ -1178,7 +1178,7 @@ fn bench_serializer_slice(b: &mut Bencher) {
|
|||||||
for item in buf.iter_mut(){ *item = 0; }
|
for item in buf.iter_mut(){ *item = 0; }
|
||||||
let mut wr = &mut buf[..];
|
let mut wr = &mut buf[..];
|
||||||
|
|
||||||
let mut serializer = json::Serializer::new(wr.by_ref());
|
let mut serializer = serde_json::Serializer::new(wr.by_ref());
|
||||||
log.serialize(&mut serializer).unwrap();
|
log.serialize(&mut serializer).unwrap();
|
||||||
let _json = serializer.into_inner();
|
let _json = serializer.into_inner();
|
||||||
});
|
});
|
||||||
@@ -1191,7 +1191,7 @@ fn test_serializer_my_mem_writer0() {
|
|||||||
let mut wr = MyMemWriter0::with_capacity(1024);
|
let mut wr = MyMemWriter0::with_capacity(1024);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut serializer = json::Serializer::new(wr.by_ref());
|
let mut serializer = serde_json::Serializer::new(wr.by_ref());
|
||||||
log.serialize(&mut serializer).unwrap();
|
log.serialize(&mut serializer).unwrap();
|
||||||
let _json = serializer.into_inner();
|
let _json = serializer.into_inner();
|
||||||
}
|
}
|
||||||
@@ -1202,7 +1202,7 @@ fn test_serializer_my_mem_writer0() {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_serializer_my_mem_writer0(b: &mut Bencher) {
|
fn bench_serializer_my_mem_writer0(b: &mut Bencher) {
|
||||||
let log = Log::new();
|
let log = Log::new();
|
||||||
let json = json::to_vec(&log);
|
let json = serde_json::to_vec(&log);
|
||||||
b.bytes = json.len() as u64;
|
b.bytes = json.len() as u64;
|
||||||
|
|
||||||
let mut wr = MyMemWriter0::with_capacity(1024);
|
let mut wr = MyMemWriter0::with_capacity(1024);
|
||||||
@@ -1210,7 +1210,7 @@ fn bench_serializer_my_mem_writer0(b: &mut Bencher) {
|
|||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
wr.buf.clear();
|
wr.buf.clear();
|
||||||
|
|
||||||
let mut serializer = json::Serializer::new(wr.by_ref());
|
let mut serializer = serde_json::Serializer::new(wr.by_ref());
|
||||||
log.serialize(&mut serializer).unwrap();
|
log.serialize(&mut serializer).unwrap();
|
||||||
let _json = serializer.into_inner();
|
let _json = serializer.into_inner();
|
||||||
});
|
});
|
||||||
@@ -1223,7 +1223,7 @@ fn test_serializer_my_mem_writer1() {
|
|||||||
let mut wr = MyMemWriter1::with_capacity(1024);
|
let mut wr = MyMemWriter1::with_capacity(1024);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut serializer = json::Serializer::new(wr.by_ref());
|
let mut serializer = serde_json::Serializer::new(wr.by_ref());
|
||||||
log.serialize(&mut serializer).unwrap();
|
log.serialize(&mut serializer).unwrap();
|
||||||
let _json = serializer.into_inner();
|
let _json = serializer.into_inner();
|
||||||
}
|
}
|
||||||
@@ -1234,7 +1234,7 @@ fn test_serializer_my_mem_writer1() {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_serializer_my_mem_writer1(b: &mut Bencher) {
|
fn bench_serializer_my_mem_writer1(b: &mut Bencher) {
|
||||||
let log = Log::new();
|
let log = Log::new();
|
||||||
let json = json::to_vec(&log);
|
let json = serde_json::to_vec(&log);
|
||||||
b.bytes = json.len() as u64;
|
b.bytes = json.len() as u64;
|
||||||
|
|
||||||
let mut wr = MyMemWriter1::with_capacity(1024);
|
let mut wr = MyMemWriter1::with_capacity(1024);
|
||||||
@@ -1242,7 +1242,7 @@ fn bench_serializer_my_mem_writer1(b: &mut Bencher) {
|
|||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
wr.buf.clear();
|
wr.buf.clear();
|
||||||
|
|
||||||
let mut serializer = json::Serializer::new(wr.by_ref());
|
let mut serializer = serde_json::Serializer::new(wr.by_ref());
|
||||||
log.serialize(&mut serializer).unwrap();
|
log.serialize(&mut serializer).unwrap();
|
||||||
let _json = serializer.into_inner();
|
let _json = serializer.into_inner();
|
||||||
});
|
});
|
||||||
@@ -1593,6 +1593,6 @@ fn bench_deserializer(b: &mut Bencher) {
|
|||||||
b.bytes = JSON_STR.len() as u64;
|
b.bytes = JSON_STR.len() as u64;
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let _log: Log = json::from_str(JSON_STR).unwrap();
|
let _log: Log = serde_json::from_str(JSON_STR).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl serde::de::Error for Error {
|
impl serde::de::Error for Error {
|
||||||
fn syntax_error() -> Error { Error::SyntaxError }
|
fn syntax(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn end_of_stream_error() -> Error { Error::EndOfStream }
|
fn end_of_stream() -> Error { Error::EndOfStream }
|
||||||
|
|
||||||
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
|
fn unknown_field(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn missing_field_error(_: &'static str) -> Error {
|
fn missing_field(_: &'static str) -> Error {
|
||||||
Error::MissingField
|
Error::MissingField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,17 +347,17 @@ mod deserializer {
|
|||||||
|
|
||||||
impl de::Deserializer<Error> for IsizeDeserializer {
|
impl de::Deserializer<Error> for IsizeDeserializer {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn end_of_stream_error(&mut self) -> Error {
|
fn end_of_stream(&mut self) -> Error {
|
||||||
EndOfStream
|
EndOfStream
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn syntax_error(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> Error {
|
fn syntax(&mut self, _token: de::Token, _expected: &[de::TokenKind]) -> Error {
|
||||||
SyntaxError
|
SyntaxError
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn unexpected_name_error(&mut self, _token: de::Token) -> Error {
|
fn unexpected_name(&mut self, _token: de::Token) -> Error {
|
||||||
SyntaxError
|
SyntaxError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl serde::de::Error for Error {
|
impl serde::de::Error for Error {
|
||||||
fn syntax_error() -> Error { Error::SyntaxError }
|
fn syntax(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn end_of_stream_error() -> Error { Error::EndOfStream }
|
fn end_of_stream() -> Error { Error::EndOfStream }
|
||||||
|
|
||||||
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
|
fn unknown_field(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn missing_field_error(_: &'static str) -> Error {
|
fn missing_field(_: &'static str) -> Error {
|
||||||
Error::MissingField
|
Error::MissingField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -398,7 +398,10 @@ mod deserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_named_map<V>(&mut self, name: &str, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_struct<V>(&mut self,
|
||||||
|
name: &str,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
mut visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
match self.stack.pop() {
|
match self.stack.pop() {
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl serde::de::Error for Error {
|
impl serde::de::Error for Error {
|
||||||
fn syntax_error() -> Error { Error::SyntaxError }
|
fn syntax(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
|
fn end_of_stream() -> Error { Error::EndOfStreamError }
|
||||||
|
|
||||||
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
|
fn unknown_field(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn missing_field_error(_: &'static str) -> Error { Error::SyntaxError }
|
fn missing_field(_: &'static str) -> Error { Error::SyntaxError }
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/test.rs"));
|
include!(concat!(env!("OUT_DIR"), "/test.rs"));
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use serde::json;
|
use std::default;
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
struct Default {
|
struct Default {
|
||||||
@@ -30,33 +31,39 @@ enum SerEnum<A> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Deserialize, Serialize)]
|
||||||
|
struct SkipSerializingFields<A: default::Default> {
|
||||||
|
a: i8,
|
||||||
|
#[serde(skip_serializing, default)]
|
||||||
|
b: A,
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default() {
|
fn test_default() {
|
||||||
let deserialized_value: Default = json::from_str(&"{\"a1\":1,\"a2\":2}").unwrap();
|
let deserialized_value: Default = serde_json::from_str(&"{\"a1\":1,\"a2\":2}").unwrap();
|
||||||
assert_eq!(deserialized_value, Default { a1: 1, a2: 2 });
|
assert_eq!(deserialized_value, Default { a1: 1, a2: 2 });
|
||||||
|
|
||||||
let deserialized_value: Default = json::from_str(&"{\"a1\":1}").unwrap();
|
let deserialized_value: Default = serde_json::from_str(&"{\"a1\":1}").unwrap();
|
||||||
assert_eq!(deserialized_value, Default { a1: 1, a2: 0 });
|
assert_eq!(deserialized_value, Default { a1: 1, a2: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rename() {
|
fn test_rename() {
|
||||||
let value = Rename { a1: 1, a2: 2 };
|
let value = Rename { a1: 1, a2: 2 };
|
||||||
let serialized_value = json::to_string(&value).unwrap();
|
let serialized_value = serde_json::to_string(&value).unwrap();
|
||||||
assert_eq!(serialized_value, "{\"a1\":1,\"a3\":2}");
|
assert_eq!(serialized_value, "{\"a1\":1,\"a3\":2}");
|
||||||
|
|
||||||
let deserialized_value: Rename = json::from_str(&serialized_value).unwrap();
|
let deserialized_value: Rename = serde_json::from_str(&serialized_value).unwrap();
|
||||||
assert_eq!(value, deserialized_value);
|
assert_eq!(value, deserialized_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_format_rename() {
|
fn test_format_rename() {
|
||||||
let value = FormatRename { a1: 1, a2: 2 };
|
let value = FormatRename { a1: 1, a2: 2 };
|
||||||
let serialized_value = json::to_string(&value).unwrap();
|
let serialized_value = serde_json::to_string(&value).unwrap();
|
||||||
assert_eq!(serialized_value, "{\"a1\":1,\"a5\":2}");
|
assert_eq!(serialized_value, "{\"a1\":1,\"a5\":2}");
|
||||||
|
|
||||||
let deserialized_value = json::from_str("{\"a1\":1,\"a5\":2}").unwrap();
|
let deserialized_value = serde_json::from_str("{\"a1\":1,\"a5\":2}").unwrap();
|
||||||
assert_eq!(value, deserialized_value);
|
assert_eq!(value, deserialized_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,10 +71,20 @@ fn test_format_rename() {
|
|||||||
fn test_enum_format_rename() {
|
fn test_enum_format_rename() {
|
||||||
let s1 = String::new();
|
let s1 = String::new();
|
||||||
let value = SerEnum::Map { a: 0i8, b: s1 };
|
let value = SerEnum::Map { a: 0i8, b: s1 };
|
||||||
let serialized_value = json::to_string(&value).unwrap();
|
let serialized_value = serde_json::to_string(&value).unwrap();
|
||||||
let ans = "{\"Map\":{\"a\":0,\"d\":\"\"}}";
|
let ans = "{\"Map\":{\"a\":0,\"d\":\"\"}}";
|
||||||
assert_eq!(serialized_value, ans);
|
assert_eq!(serialized_value, ans);
|
||||||
|
|
||||||
let deserialized_value = json::from_str(ans).unwrap();
|
let deserialized_value = serde_json::from_str(ans).unwrap();
|
||||||
assert_eq!(value, deserialized_value);
|
assert_eq!(value, deserialized_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_skip_serializing_fields() {
|
||||||
|
let value = SkipSerializingFields { a: 1, b: 2 };
|
||||||
|
let serialized_value = serde_json::to_string(&value).unwrap();
|
||||||
|
assert_eq!(serialized_value, "{\"a\":1}");
|
||||||
|
|
||||||
|
let deserialized_value: SkipSerializingFields<_> = serde_json::from_str(&serialized_value).unwrap();
|
||||||
|
assert_eq!(SkipSerializingFields { a: 1, b: 0 }, deserialized_value);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use serde;
|
use serde;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde::bytes::{ByteBuf, Bytes};
|
use serde::bytes::{ByteBuf, Bytes};
|
||||||
use serde::json;
|
use serde_json;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -9,13 +9,13 @@ use serde::json;
|
|||||||
struct Error;
|
struct Error;
|
||||||
|
|
||||||
impl serde::de::Error for Error {
|
impl serde::de::Error for Error {
|
||||||
fn syntax_error() -> Error { Error }
|
fn syntax(_: &str) -> Error { Error }
|
||||||
|
|
||||||
fn end_of_stream_error() -> Error { Error }
|
fn end_of_stream() -> Error { Error }
|
||||||
|
|
||||||
fn unknown_field_error(_field: &str) -> Error { Error }
|
fn unknown_field(_field: &str) -> Error { Error }
|
||||||
|
|
||||||
fn missing_field_error(_field: &'static str) -> Error { Error }
|
fn missing_field(_field: &'static str) -> Error { Error }
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -144,11 +144,11 @@ impl serde::Deserializer for BytesDeserializer {
|
|||||||
fn test_bytes_ser_json() {
|
fn test_bytes_ser_json() {
|
||||||
let buf = vec![];
|
let buf = vec![];
|
||||||
let bytes = Bytes::from(&buf);
|
let bytes = Bytes::from(&buf);
|
||||||
assert_eq!(json::to_string(&bytes).unwrap(), "[]".to_string());
|
assert_eq!(serde_json::to_string(&bytes).unwrap(), "[]".to_string());
|
||||||
|
|
||||||
let buf = vec![1, 2, 3];
|
let buf = vec![1, 2, 3];
|
||||||
let bytes = Bytes::from(&buf);
|
let bytes = Bytes::from(&buf);
|
||||||
assert_eq!(json::to_string(&bytes).unwrap(), "[1,2,3]".to_string());
|
assert_eq!(serde_json::to_string(&bytes).unwrap(), "[1,2,3]".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -167,10 +167,10 @@ fn test_bytes_ser_bytes() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_byte_buf_ser_json() {
|
fn test_byte_buf_ser_json() {
|
||||||
let bytes = ByteBuf::new();
|
let bytes = ByteBuf::new();
|
||||||
assert_eq!(json::to_string(&bytes).unwrap(), "[]".to_string());
|
assert_eq!(serde_json::to_string(&bytes).unwrap(), "[]".to_string());
|
||||||
|
|
||||||
let bytes = ByteBuf::from(vec![1, 2, 3]);
|
let bytes = ByteBuf::from(vec![1, 2, 3]);
|
||||||
assert_eq!(json::to_string(&bytes).unwrap(), "[1,2,3]".to_string());
|
assert_eq!(serde_json::to_string(&bytes).unwrap(), "[1,2,3]".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -189,11 +189,11 @@ fn test_byte_buf_ser_bytes() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_byte_buf_de_json() {
|
fn test_byte_buf_de_json() {
|
||||||
let bytes = ByteBuf::new();
|
let bytes = ByteBuf::new();
|
||||||
let v: ByteBuf = json::from_str("[]").unwrap();
|
let v: ByteBuf = serde_json::from_str("[]").unwrap();
|
||||||
assert_eq!(v, bytes);
|
assert_eq!(v, bytes);
|
||||||
|
|
||||||
let bytes = ByteBuf::from(vec![1, 2, 3]);
|
let bytes = ByteBuf::from(vec![1, 2, 3]);
|
||||||
let v: ByteBuf = json::from_str("[1, 2, 3]").unwrap();
|
let v: ByteBuf = serde_json::from_str("[1, 2, 3]").unwrap();
|
||||||
assert_eq!(v, bytes);
|
assert_eq!(v, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+134
-30
@@ -22,6 +22,7 @@ enum Token {
|
|||||||
Char(char),
|
Char(char),
|
||||||
Str(&'static str),
|
Str(&'static str),
|
||||||
String(String),
|
String(String),
|
||||||
|
Bytes(&'static [u8]),
|
||||||
|
|
||||||
Option(bool),
|
Option(bool),
|
||||||
|
|
||||||
@@ -38,6 +39,10 @@ enum Token {
|
|||||||
MapEnd,
|
MapEnd,
|
||||||
|
|
||||||
EnumStart(&'static str),
|
EnumStart(&'static str),
|
||||||
|
EnumUnit,
|
||||||
|
EnumNewtype,
|
||||||
|
EnumSeq,
|
||||||
|
EnumMap,
|
||||||
EnumEnd,
|
EnumEnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,15 +68,15 @@ enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl de::Error for Error {
|
impl de::Error for Error {
|
||||||
fn syntax_error() -> Error { Error::SyntaxError }
|
fn syntax(_: &str) -> Error { Error::SyntaxError }
|
||||||
|
|
||||||
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
|
fn end_of_stream() -> Error { Error::EndOfStreamError }
|
||||||
|
|
||||||
fn unknown_field_error(field: &str) -> Error {
|
fn unknown_field(field: &str) -> Error {
|
||||||
Error::UnknownFieldError(field.to_string())
|
Error::UnknownFieldError(field.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing_field_error(field: &'static str) -> Error {
|
fn missing_field(field: &'static str) -> Error {
|
||||||
Error::MissingFieldError(field)
|
Error::MissingFieldError(field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,6 +104,7 @@ impl Deserializer for TokenDeserializer {
|
|||||||
Some(Token::Char(v)) => visitor.visit_char(v),
|
Some(Token::Char(v)) => visitor.visit_char(v),
|
||||||
Some(Token::Str(v)) => visitor.visit_str(v),
|
Some(Token::Str(v)) => visitor.visit_str(v),
|
||||||
Some(Token::String(v)) => visitor.visit_string(v),
|
Some(Token::String(v)) => visitor.visit_string(v),
|
||||||
|
Some(Token::Bytes(v)) => visitor.visit_bytes(v),
|
||||||
Some(Token::Option(false)) => visitor.visit_none(),
|
Some(Token::Option(false)) => visitor.visit_none(),
|
||||||
Some(Token::Option(true)) => visitor.visit_some(self),
|
Some(Token::Option(true)) => visitor.visit_some(self),
|
||||||
Some(Token::Unit) => visitor.visit_unit(),
|
Some(Token::Unit) => visitor.visit_unit(),
|
||||||
@@ -143,7 +149,10 @@ impl Deserializer for TokenDeserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_enum<V>(&mut self, name: &str, mut visitor: V) -> Result<V::Value, Error>
|
fn visit_enum<V>(&mut self,
|
||||||
|
name: &str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
mut visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::EnumVisitor,
|
where V: de::EnumVisitor,
|
||||||
{
|
{
|
||||||
match self.tokens.next() {
|
match self.tokens.next() {
|
||||||
@@ -161,7 +170,7 @@ impl Deserializer for TokenDeserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_named_unit<V>(&mut self, name: &str, visitor: V) -> Result<V::Value, Error>
|
fn visit_unit_struct<V>(&mut self, name: &str, visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
match self.tokens.peek() {
|
match self.tokens.peek() {
|
||||||
@@ -178,7 +187,10 @@ impl Deserializer for TokenDeserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_named_seq<V>(&mut self, name: &str, visitor: V) -> Result<V::Value, Error>
|
fn visit_tuple_struct<V>(&mut self,
|
||||||
|
name: &str,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
match self.tokens.peek() {
|
match self.tokens.peek() {
|
||||||
@@ -195,7 +207,10 @@ impl Deserializer for TokenDeserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_named_map<V>(&mut self, name: &str, visitor: V) -> Result<V::Value, Error>
|
fn visit_struct<V>(&mut self,
|
||||||
|
name: &str,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
match self.tokens.peek() {
|
match self.tokens.peek() {
|
||||||
@@ -315,32 +330,66 @@ impl<'a> de::VariantVisitor for TokenDeserializerVariantVisitor<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_unit(&mut self) -> Result<(), Error> {
|
fn visit_unit(&mut self) -> Result<(), Error> {
|
||||||
de::Deserialize::deserialize(self.de)
|
match self.de.tokens.next() {
|
||||||
|
Some(Token::EnumUnit) => {
|
||||||
|
de::Deserialize::deserialize(self.de)
|
||||||
|
}
|
||||||
|
Some(_) => Err(Error::SyntaxError),
|
||||||
|
None => Err(Error::EndOfStreamError),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
fn visit_newtype<T>(&mut self) -> Result<T, Self::Error>
|
||||||
where V: de::Visitor,
|
where T: de::Deserialize,
|
||||||
{
|
{
|
||||||
de::Deserializer::visit(self.de, visitor)
|
match self.de.tokens.next() {
|
||||||
|
Some(Token::EnumNewtype) => {
|
||||||
|
de::Deserialize::deserialize(self.de)
|
||||||
|
}
|
||||||
|
Some(_) => Err(Error::SyntaxError),
|
||||||
|
None => Err(Error::EndOfStreamError),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
|
fn visit_tuple<V>(&mut self,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V) -> Result<V::Value, Error>
|
||||||
where V: de::Visitor,
|
where V: de::Visitor,
|
||||||
{
|
{
|
||||||
de::Deserializer::visit(self.de, visitor)
|
match self.de.tokens.next() {
|
||||||
|
Some(Token::EnumSeq) => {
|
||||||
|
de::Deserializer::visit(self.de, visitor)
|
||||||
|
}
|
||||||
|
Some(_) => Err(Error::SyntaxError),
|
||||||
|
None => Err(Error::EndOfStreamError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_struct<V>(&mut self,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
visitor: V) -> Result<V::Value, Error>
|
||||||
|
where V: de::Visitor,
|
||||||
|
{
|
||||||
|
match self.de.tokens.next() {
|
||||||
|
Some(Token::EnumMap) => {
|
||||||
|
de::Deserializer::visit(self.de, visitor)
|
||||||
|
}
|
||||||
|
Some(_) => Err(Error::SyntaxError),
|
||||||
|
None => Err(Error::EndOfStreamError),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
|
#[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
|
||||||
struct NamedUnit;
|
struct UnitStruct;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
struct NamedSeq(i32, i32, i32);
|
struct TupleStruct(i32, i32, i32);
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
struct NamedMap {
|
struct Struct {
|
||||||
a: i32,
|
a: i32,
|
||||||
b: i32,
|
b: i32,
|
||||||
c: i32,
|
c: i32,
|
||||||
@@ -349,6 +398,7 @@ struct NamedMap {
|
|||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
enum Enum {
|
enum Enum {
|
||||||
Unit,
|
Unit,
|
||||||
|
Simple(i32),
|
||||||
Seq(i32, i32, i32),
|
Seq(i32, i32, i32),
|
||||||
Map { a: i32, b: i32, c: i32 }
|
Map { a: i32, b: i32, c: i32 }
|
||||||
}
|
}
|
||||||
@@ -486,6 +536,24 @@ declare_tests! {
|
|||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
test_result {
|
||||||
|
Ok::<i32, i32>(0) => vec![
|
||||||
|
Token::EnumStart("Result"),
|
||||||
|
Token::Str("Ok"),
|
||||||
|
|
||||||
|
Token::EnumNewtype,
|
||||||
|
Token::I32(0),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
Err::<i32, i32>(1) => vec![
|
||||||
|
Token::EnumStart("Result"),
|
||||||
|
Token::Str("Err"),
|
||||||
|
|
||||||
|
Token::EnumNewtype,
|
||||||
|
Token::I32(1),
|
||||||
|
Token::SeqEnd,
|
||||||
|
],
|
||||||
|
}
|
||||||
test_unit {
|
test_unit {
|
||||||
() => vec![Token::Unit],
|
() => vec![Token::Unit],
|
||||||
() => vec![
|
() => vec![
|
||||||
@@ -498,19 +566,19 @@ declare_tests! {
|
|||||||
Token::SeqEnd,
|
Token::SeqEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
test_named_unit {
|
test_unit_struct {
|
||||||
NamedUnit => vec![Token::Unit],
|
UnitStruct => vec![Token::Unit],
|
||||||
NamedUnit => vec![
|
UnitStruct => vec![
|
||||||
Token::Name("NamedUnit"),
|
Token::Name("UnitStruct"),
|
||||||
Token::Unit,
|
Token::Unit,
|
||||||
],
|
],
|
||||||
NamedUnit => vec![
|
UnitStruct => vec![
|
||||||
Token::SeqStart(0),
|
Token::SeqStart(0),
|
||||||
Token::SeqEnd,
|
Token::SeqEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
test_named_seq {
|
test_tuple_struct {
|
||||||
NamedSeq(1, 2, 3) => vec![
|
TupleStruct(1, 2, 3) => vec![
|
||||||
Token::SeqStart(3),
|
Token::SeqStart(3),
|
||||||
Token::SeqSep,
|
Token::SeqSep,
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
@@ -522,8 +590,8 @@ declare_tests! {
|
|||||||
Token::I32(3),
|
Token::I32(3),
|
||||||
Token::SeqEnd,
|
Token::SeqEnd,
|
||||||
],
|
],
|
||||||
NamedSeq(1, 2, 3) => vec![
|
TupleStruct(1, 2, 3) => vec![
|
||||||
Token::Name("NamedSeq"),
|
Token::Name("TupleStruct"),
|
||||||
Token::SeqStart(3),
|
Token::SeqStart(3),
|
||||||
Token::SeqSep,
|
Token::SeqSep,
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
@@ -818,8 +886,8 @@ declare_tests! {
|
|||||||
Token::MapEnd,
|
Token::MapEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
test_named_map {
|
test_struct {
|
||||||
NamedMap { a: 1, b: 2, c: 3 } => vec![
|
Struct { a: 1, b: 2, c: 3 } => vec![
|
||||||
Token::MapStart(3),
|
Token::MapStart(3),
|
||||||
Token::MapSep,
|
Token::MapSep,
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
@@ -834,8 +902,8 @@ declare_tests! {
|
|||||||
Token::I32(3),
|
Token::I32(3),
|
||||||
Token::MapEnd,
|
Token::MapEnd,
|
||||||
],
|
],
|
||||||
NamedMap { a: 1, b: 2, c: 3 } => vec![
|
Struct { a: 1, b: 2, c: 3 } => vec![
|
||||||
Token::Name("NamedMap"),
|
Token::Name("Struct"),
|
||||||
Token::MapStart(3),
|
Token::MapStart(3),
|
||||||
Token::MapSep,
|
Token::MapSep,
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
@@ -855,14 +923,28 @@ declare_tests! {
|
|||||||
Enum::Unit => vec![
|
Enum::Unit => vec![
|
||||||
Token::EnumStart("Enum"),
|
Token::EnumStart("Enum"),
|
||||||
Token::Str("Unit"),
|
Token::Str("Unit"),
|
||||||
|
|
||||||
|
Token::EnumUnit,
|
||||||
Token::Unit,
|
Token::Unit,
|
||||||
Token::EnumEnd,
|
Token::EnumEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
test_enum_simple {
|
||||||
|
Enum::Simple(1) => vec![
|
||||||
|
Token::EnumStart("Enum"),
|
||||||
|
Token::Str("Simple"),
|
||||||
|
|
||||||
|
Token::EnumNewtype,
|
||||||
|
Token::I32(1),
|
||||||
|
Token::EnumEnd,
|
||||||
|
],
|
||||||
|
}
|
||||||
test_enum_seq {
|
test_enum_seq {
|
||||||
Enum::Seq(1, 2, 3) => vec![
|
Enum::Seq(1, 2, 3) => vec![
|
||||||
Token::EnumStart("Enum"),
|
Token::EnumStart("Enum"),
|
||||||
Token::Str("Seq"),
|
Token::Str("Seq"),
|
||||||
|
|
||||||
|
Token::EnumSeq,
|
||||||
Token::SeqStart(3),
|
Token::SeqStart(3),
|
||||||
Token::SeqSep,
|
Token::SeqSep,
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
@@ -880,6 +962,8 @@ declare_tests! {
|
|||||||
Enum::Map { a: 1, b: 2, c: 3 } => vec![
|
Enum::Map { a: 1, b: 2, c: 3 } => vec![
|
||||||
Token::EnumStart("Enum"),
|
Token::EnumStart("Enum"),
|
||||||
Token::Str("Map"),
|
Token::Str("Map"),
|
||||||
|
|
||||||
|
Token::EnumMap,
|
||||||
Token::MapStart(3),
|
Token::MapStart(3),
|
||||||
Token::MapSep,
|
Token::MapSep,
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
@@ -896,4 +980,24 @@ declare_tests! {
|
|||||||
Token::EnumEnd,
|
Token::EnumEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
test_enum_unit_usize {
|
||||||
|
Enum::Unit => vec![
|
||||||
|
Token::EnumStart("Enum"),
|
||||||
|
Token::Usize(0),
|
||||||
|
|
||||||
|
Token::EnumUnit,
|
||||||
|
Token::Unit,
|
||||||
|
Token::EnumEnd,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
test_enum_unit_bytes {
|
||||||
|
Enum::Unit => vec![
|
||||||
|
Token::EnumStart("Enum"),
|
||||||
|
Token::Bytes(b"Unit"),
|
||||||
|
|
||||||
|
Token::EnumUnit,
|
||||||
|
Token::Unit,
|
||||||
|
Token::EnumEnd,
|
||||||
|
],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+294
-25
@@ -1,10 +1,14 @@
|
|||||||
use std::fmt::Debug;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use std::f64;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::i64;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::u64;
|
||||||
|
|
||||||
use serde::de;
|
use serde::de;
|
||||||
use serde::ser;
|
use serde::ser;
|
||||||
|
|
||||||
use serde::json::{
|
use serde_json::{
|
||||||
self,
|
self,
|
||||||
Value,
|
Value,
|
||||||
from_str,
|
from_str,
|
||||||
@@ -12,7 +16,7 @@ use serde::json::{
|
|||||||
to_value,
|
to_value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::json::error::{Error, ErrorCode};
|
use serde_json::error::{Error, ErrorCode};
|
||||||
|
|
||||||
macro_rules! treemap {
|
macro_rules! treemap {
|
||||||
($($k:expr => $v:expr),*) => ({
|
($($k:expr => $v:expr),*) => ({
|
||||||
@@ -27,7 +31,7 @@ enum Animal {
|
|||||||
Dog,
|
Dog,
|
||||||
Frog(String, Vec<isize>),
|
Frog(String, Vec<isize>),
|
||||||
Cat { age: usize, name: String },
|
Cat { age: usize, name: String },
|
||||||
|
AntHive(Vec<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@@ -48,11 +52,11 @@ fn test_encode_ok<T>(errors: &[(T, &str)])
|
|||||||
for &(ref value, out) in errors {
|
for &(ref value, out) in errors {
|
||||||
let out = out.to_string();
|
let out = out.to_string();
|
||||||
|
|
||||||
let s = json::to_string(value).unwrap();
|
let s = serde_json::to_string(value).unwrap();
|
||||||
assert_eq!(s, out);
|
assert_eq!(s, out);
|
||||||
|
|
||||||
let v = to_value(&value);
|
let v = to_value(&value);
|
||||||
let s = json::to_string(&v).unwrap();
|
let s = serde_json::to_string(&v).unwrap();
|
||||||
assert_eq!(s, out);
|
assert_eq!(s, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,11 +67,11 @@ fn test_pretty_encode_ok<T>(errors: &[(T, &str)])
|
|||||||
for &(ref value, out) in errors {
|
for &(ref value, out) in errors {
|
||||||
let out = out.to_string();
|
let out = out.to_string();
|
||||||
|
|
||||||
let s = json::to_string_pretty(value).unwrap();
|
let s = serde_json::to_string_pretty(value).unwrap();
|
||||||
assert_eq!(s, out);
|
assert_eq!(s, out);
|
||||||
|
|
||||||
let v = to_value(&value);
|
let v = to_value(&value);
|
||||||
let s = json::to_string_pretty(&v).unwrap();
|
let s = serde_json::to_string_pretty(&v).unwrap();
|
||||||
assert_eq!(s, out);
|
assert_eq!(s, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,12 +85,23 @@ fn test_write_null() {
|
|||||||
test_pretty_encode_ok(tests);
|
test_pretty_encode_ok(tests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_write_u64() {
|
||||||
|
let tests = &[
|
||||||
|
(3u64, "3"),
|
||||||
|
(u64::MAX, &u64::MAX.to_string()),
|
||||||
|
];
|
||||||
|
test_encode_ok(tests);
|
||||||
|
test_pretty_encode_ok(tests);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_i64() {
|
fn test_write_i64() {
|
||||||
let tests = &[
|
let tests = &[
|
||||||
(3i64, "3"),
|
(3i64, "3"),
|
||||||
(-2i64, "-2"),
|
(-2i64, "-2"),
|
||||||
(-1234i64, "-1234"),
|
(-1234i64, "-1234"),
|
||||||
|
(i64::MIN, &i64::MIN.to_string()),
|
||||||
];
|
];
|
||||||
test_encode_ok(tests);
|
test_encode_ok(tests);
|
||||||
test_pretty_encode_ok(tests);
|
test_pretty_encode_ok(tests);
|
||||||
@@ -94,11 +109,18 @@ fn test_write_i64() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_f64() {
|
fn test_write_f64() {
|
||||||
|
let min_string = format!("{:?}", f64::MIN);
|
||||||
|
let max_string = format!("{:?}", f64::MAX);
|
||||||
|
let epsilon_string = format!("{:?}", f64::EPSILON);
|
||||||
|
|
||||||
let tests = &[
|
let tests = &[
|
||||||
(3.0, "3.0"),
|
(3.0, "3"),
|
||||||
(3.1, "3.1"),
|
(3.1, "3.1"),
|
||||||
(-1.5, "-1.5"),
|
(-1.5, "-1.5"),
|
||||||
(0.5, "0.5"),
|
(0.5, "0.5"),
|
||||||
|
(f64::MIN, &min_string),
|
||||||
|
(f64::MAX, &max_string),
|
||||||
|
(f64::EPSILON, &epsilon_string),
|
||||||
];
|
];
|
||||||
test_encode_ok(tests);
|
test_encode_ok(tests);
|
||||||
test_pretty_encode_ok(tests);
|
test_pretty_encode_ok(tests);
|
||||||
@@ -533,6 +555,10 @@ fn test_write_enum() {
|
|||||||
Animal::Cat { age: 5, name: "Kate".to_string() },
|
Animal::Cat { age: 5, name: "Kate".to_string() },
|
||||||
"{\"Cat\":{\"age\":5,\"name\":\"Kate\"}}"
|
"{\"Cat\":{\"age\":5,\"name\":\"Kate\"}}"
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
Animal::AntHive(vec!["Bob".to_string(), "Stuart".to_string()]),
|
||||||
|
"{\"AntHive\":[\"Bob\",\"Stuart\"]}",
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
test_pretty_encode_ok(&[
|
test_pretty_encode_ok(&[
|
||||||
@@ -616,7 +642,7 @@ fn test_write_option() {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_parse_ok<T>(errors: Vec<(&'static str, T)>)
|
fn test_parse_ok<T>(errors: Vec<(&str, T)>)
|
||||||
where T: Clone + Debug + PartialEq + ser::Serialize + de::Deserialize,
|
where T: Clone + Debug + PartialEq + ser::Serialize + de::Deserialize,
|
||||||
{
|
{
|
||||||
for (s, value) in errors {
|
for (s, value) in errors {
|
||||||
@@ -702,7 +728,6 @@ fn test_parse_number_errors() {
|
|||||||
("1e", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
|
("1e", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
|
||||||
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
|
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
|
||||||
("1a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 2)),
|
("1a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 2)),
|
||||||
("777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 20)),
|
|
||||||
("1e777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 22)),
|
("1e777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 22)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -713,28 +738,44 @@ fn test_parse_i64() {
|
|||||||
("-2", -2),
|
("-2", -2),
|
||||||
("-1234", -1234),
|
("-1234", -1234),
|
||||||
(" -1234 ", -1234),
|
(" -1234 ", -1234),
|
||||||
|
(&i64::MIN.to_string(), i64::MIN),
|
||||||
|
(&i64::MAX.to_string(), i64::MAX),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_u64() {
|
fn test_parse_u64() {
|
||||||
test_parse_ok(vec![
|
test_parse_ok(vec![
|
||||||
|
("0", 0u64),
|
||||||
("3", 3u64),
|
("3", 3u64),
|
||||||
("1234", 1234),
|
("1234", 1234),
|
||||||
|
(&u64::MAX.to_string(), u64::MAX),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_f64() {
|
fn test_parse_f64() {
|
||||||
test_parse_ok(vec![
|
test_parse_ok(vec![
|
||||||
|
("0.0", 0.0f64),
|
||||||
("3.0", 3.0f64),
|
("3.0", 3.0f64),
|
||||||
|
("3.00", 3.0f64),
|
||||||
("3.1", 3.1),
|
("3.1", 3.1),
|
||||||
("-1.2", -1.2),
|
("-1.2", -1.2),
|
||||||
("0.4", 0.4),
|
("0.4", 0.4),
|
||||||
("0.4e5", 0.4e5),
|
("0.4e5", 0.4e5),
|
||||||
|
("0.4e+5", 0.4e5),
|
||||||
("0.4e15", 0.4e15),
|
("0.4e15", 0.4e15),
|
||||||
("0.4e-01", 0.4e-01),
|
("0.4e+15", 0.4e15),
|
||||||
(" 0.4e-01 ", 0.4e-01),
|
("0.4e-01", 0.4e-1),
|
||||||
|
(" 0.4e-01 ", 0.4e-1),
|
||||||
|
("0.4e-001", 0.4e-1),
|
||||||
|
("0.4e-0", 0.4e0),
|
||||||
|
("0.00e00", 0.0),
|
||||||
|
("0.00e+00", 0.0),
|
||||||
|
("0.00e-00", 0.0),
|
||||||
|
(&format!("{:?}", (i64::MIN as f64) - 1.0), (i64::MIN as f64) - 1.0),
|
||||||
|
(&format!("{:?}", (u64::MAX as f64) + 1.0), (u64::MAX as f64) + 1.0),
|
||||||
|
(&format!("{:?}", f64::EPSILON), f64::EPSILON),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,8 +804,8 @@ fn test_parse_string() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parse_list() {
|
fn test_parse_list() {
|
||||||
test_parse_err::<Vec<f64>>(vec![
|
test_parse_err::<Vec<f64>>(vec![
|
||||||
("[", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 1)),
|
("[", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 1)),
|
||||||
("[ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
|
("[ ", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 2)),
|
||||||
("[1", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 2)),
|
("[1", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 2)),
|
||||||
("[1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
|
("[1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
|
||||||
("[1,]", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 4)),
|
("[1,]", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 4)),
|
||||||
@@ -815,8 +856,8 @@ fn test_parse_list() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parse_object() {
|
fn test_parse_object() {
|
||||||
test_parse_err::<BTreeMap<String, u32>>(vec![
|
test_parse_err::<BTreeMap<String, u32>>(vec![
|
||||||
("{", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 1)),
|
("{", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 1)),
|
||||||
("{ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
|
("{ ", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 2)),
|
||||||
("{1", Error::SyntaxError(ErrorCode::KeyMustBeAString, 1, 2)),
|
("{1", Error::SyntaxError(ErrorCode::KeyMustBeAString, 1, 2)),
|
||||||
("{ \"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 5)),
|
("{ \"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 5)),
|
||||||
("{\"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 4)),
|
("{\"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 4)),
|
||||||
@@ -868,7 +909,7 @@ fn test_parse_struct() {
|
|||||||
test_parse_err::<Outer>(vec![
|
test_parse_err::<Outer>(vec![
|
||||||
("5", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
|
("5", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
|
||||||
("\"hello\"", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 7)),
|
("\"hello\"", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 7)),
|
||||||
("{\"inner\": true}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 15)),
|
("{\"inner\": true}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 14)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
test_parse_ok(vec![
|
test_parse_ok(vec![
|
||||||
@@ -891,7 +932,7 @@ fn test_parse_struct() {
|
|||||||
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
|
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let v: Outer = from_str("{}").unwrap();
|
let v: Outer = from_str("{}").unwrap();
|
||||||
@@ -902,6 +943,22 @@ fn test_parse_struct() {
|
|||||||
inner: vec![],
|
inner: vec![],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let v: Outer = from_str(
|
||||||
|
"[
|
||||||
|
[
|
||||||
|
[ null, 2, [\"abc\", \"xyz\"] ]
|
||||||
|
]
|
||||||
|
]").unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
v,
|
||||||
|
Outer {
|
||||||
|
inner: vec![
|
||||||
|
Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -931,10 +988,10 @@ fn test_parse_enum_errors() {
|
|||||||
("{}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 2)),
|
("{}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 2)),
|
||||||
("{\"Dog\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 7)),
|
("{\"Dog\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 7)),
|
||||||
("{\"Dog\":}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 8)),
|
("{\"Dog\":}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 8)),
|
||||||
("{\"unknown\":[]}", Error::SyntaxError(ErrorCode::UnknownField("unknown".to_string()), 1, 11)),
|
("{\"unknown\":[]}", Error::SyntaxError(ErrorCode::UnknownField("unknown".to_string()), 1, 10)),
|
||||||
("{\"Dog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 9)),
|
("{\"Dog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 8)),
|
||||||
("{\"Frog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 10)),
|
("{\"Frog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 9)),
|
||||||
("{\"Cat\":[]}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 9)),
|
("{\"Cat\":[]}", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 9)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -959,6 +1016,10 @@ fn test_parse_enum() {
|
|||||||
" { \"Cat\" : { \"age\" : 5 , \"name\" : \"Kate\" } } ",
|
" { \"Cat\" : { \"age\" : 5 , \"name\" : \"Kate\" } } ",
|
||||||
Animal::Cat { age: 5, name: "Kate".to_string() },
|
Animal::Cat { age: 5, name: "Kate".to_string() },
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
" { \"AntHive\" : [\"Bob\", \"Stuart\"] } ",
|
||||||
|
Animal::AntHive(vec!["Bob".to_string(), "Stuart".to_string()]),
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
test_parse_ok(vec![
|
test_parse_ok(vec![
|
||||||
@@ -1064,7 +1125,7 @@ fn test_missing_fmt_renamed_field() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_path() {
|
fn test_find_path() {
|
||||||
let obj: Value = json::from_str(r#"{"x": {"a": 1}, "y": 2}"#).unwrap();
|
let obj: Value = serde_json::from_str(r#"{"x": {"a": 1}, "y": 2}"#).unwrap();
|
||||||
|
|
||||||
assert!(obj.find_path(&["x", "a"]).unwrap() == &Value::U64(1));
|
assert!(obj.find_path(&["x", "a"]).unwrap() == &Value::U64(1));
|
||||||
assert!(obj.find_path(&["y"]).unwrap() == &Value::U64(2));
|
assert!(obj.find_path(&["y"]).unwrap() == &Value::U64(2));
|
||||||
@@ -1073,9 +1134,217 @@ fn test_find_path() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lookup() {
|
fn test_lookup() {
|
||||||
let obj: Value = json::from_str(r#"{"x": {"a": 1}, "y": 2}"#).unwrap();
|
let obj: Value = serde_json::from_str(r#"{"x": {"a": 1}, "y": 2}"#).unwrap();
|
||||||
|
|
||||||
assert!(obj.lookup("x.a").unwrap() == &Value::U64(1));
|
assert!(obj.lookup("x.a").unwrap() == &Value::U64(1));
|
||||||
assert!(obj.lookup("y").unwrap() == &Value::U64(2));
|
assert!(obj.lookup("y").unwrap() == &Value::U64(2));
|
||||||
assert!(obj.lookup("z").is_none());
|
assert!(obj.lookup("z").is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serialize_seq_with_no_len() {
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
struct MyVec<T>(Vec<T>);
|
||||||
|
|
||||||
|
impl<T> ser::Serialize for MyVec<T>
|
||||||
|
where T: ser::Serialize,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
|
where S: ser::Serializer,
|
||||||
|
{
|
||||||
|
serializer.visit_seq(ser::impls::SeqIteratorVisitor::new(self.0.iter(), None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Visitor<T> {
|
||||||
|
marker: PhantomData<MyVec<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> de::Visitor for Visitor<T>
|
||||||
|
where T: de::Deserialize,
|
||||||
|
{
|
||||||
|
type Value = MyVec<T>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_unit<E>(&mut self) -> Result<MyVec<T>, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(MyVec(Vec::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<MyVec<T>, V::Error>
|
||||||
|
where V: de::SeqVisitor,
|
||||||
|
{
|
||||||
|
let mut values = Vec::new();
|
||||||
|
|
||||||
|
while let Some(value) = try!(visitor.visit()) {
|
||||||
|
values.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
try!(visitor.end());
|
||||||
|
|
||||||
|
Ok(MyVec(values))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> de::Deserialize for MyVec<T>
|
||||||
|
where T: de::Deserialize,
|
||||||
|
{
|
||||||
|
fn deserialize<D>(deserializer: &mut D) -> Result<MyVec<T>, D::Error>
|
||||||
|
where D: de::Deserializer,
|
||||||
|
{
|
||||||
|
deserializer.visit_map(Visitor { marker: PhantomData })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
vec.push(MyVec(Vec::new()));
|
||||||
|
vec.push(MyVec(Vec::new()));
|
||||||
|
let vec: MyVec<MyVec<u32>> = MyVec(vec);
|
||||||
|
|
||||||
|
test_encode_ok(&[
|
||||||
|
(
|
||||||
|
vec.clone(),
|
||||||
|
"[[],[]]",
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let s = serde_json::to_string_pretty(&vec).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
concat!(
|
||||||
|
"[\n",
|
||||||
|
" [\n",
|
||||||
|
" ],\n",
|
||||||
|
" [\n",
|
||||||
|
" ]\n",
|
||||||
|
"]"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serialize_map_with_no_len() {
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
struct Map<K, V>(BTreeMap<K, V>);
|
||||||
|
|
||||||
|
impl<K, V> ser::Serialize for Map<K, V>
|
||||||
|
where K: ser::Serialize + Ord,
|
||||||
|
V: ser::Serialize,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
|
where S: ser::Serializer,
|
||||||
|
{
|
||||||
|
serializer.visit_map(ser::impls::MapIteratorVisitor::new(self.0.iter(), None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Visitor<K, V> {
|
||||||
|
marker: PhantomData<Map<K, V>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> de::Visitor for Visitor<K, V>
|
||||||
|
where K: de::Deserialize + Eq + Ord,
|
||||||
|
V: de::Deserialize,
|
||||||
|
{
|
||||||
|
type Value = Map<K, V>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_unit<E>(&mut self) -> Result<Map<K, V>, E>
|
||||||
|
where E: de::Error,
|
||||||
|
{
|
||||||
|
Ok(Map(BTreeMap::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_map<Visitor>(&mut self, mut visitor: Visitor) -> Result<Map<K, V>, Visitor::Error>
|
||||||
|
where Visitor: de::MapVisitor,
|
||||||
|
{
|
||||||
|
let mut values = BTreeMap::new();
|
||||||
|
|
||||||
|
while let Some((key, value)) = try!(visitor.visit()) {
|
||||||
|
values.insert(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
try!(visitor.end());
|
||||||
|
|
||||||
|
Ok(Map(values))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K, V> de::Deserialize for Map<K, V>
|
||||||
|
where K: de::Deserialize + Eq + Ord,
|
||||||
|
V: de::Deserialize,
|
||||||
|
{
|
||||||
|
fn deserialize<D>(deserializer: &mut D) -> Result<Map<K, V>, D::Error>
|
||||||
|
where D: de::Deserializer,
|
||||||
|
{
|
||||||
|
deserializer.visit_map(Visitor { marker: PhantomData })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut map = BTreeMap::new();
|
||||||
|
map.insert("a", Map(BTreeMap::new()));
|
||||||
|
map.insert("b", Map(BTreeMap::new()));
|
||||||
|
let map: Map<_, Map<u32, u32>> = Map(map);
|
||||||
|
|
||||||
|
test_encode_ok(&[
|
||||||
|
(
|
||||||
|
map.clone(),
|
||||||
|
"{\"a\":{},\"b\":{}}",
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let s = serde_json::to_string_pretty(&map).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
s,
|
||||||
|
concat!(
|
||||||
|
"{\n",
|
||||||
|
" \"a\": {\n",
|
||||||
|
" },\n",
|
||||||
|
" \"b\": {\n",
|
||||||
|
" }\n",
|
||||||
|
"}"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_deserialize_from_stream() {
|
||||||
|
use std::net;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::thread;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
struct Message {
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let l = net::TcpListener::bind("localhost:20000").unwrap();
|
||||||
|
|
||||||
|
thread::spawn(|| {
|
||||||
|
let l = l;
|
||||||
|
for stream in l.incoming() {
|
||||||
|
let mut stream = stream.unwrap();
|
||||||
|
let read_stream = stream.try_clone().unwrap();
|
||||||
|
|
||||||
|
let mut de = serde_json::Deserializer::new(read_stream.bytes());
|
||||||
|
let request = Message::deserialize(&mut de).unwrap();
|
||||||
|
let response = Message { message: request.message };
|
||||||
|
serde_json::to_writer(&mut stream, &response).unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut stream = net::TcpStream::connect("localhost:20000").unwrap();
|
||||||
|
let request = Message { message: "hi there".to_string() };
|
||||||
|
serde_json::to_writer(&mut stream, &request).unwrap();
|
||||||
|
|
||||||
|
let mut de = serde_json::Deserializer::new(stream.bytes());
|
||||||
|
let response = Message::deserialize(&mut de).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(request, response);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use serde::json::value::Value;
|
use serde_json::value::Value;
|
||||||
use serde::json::builder::{ArrayBuilder, ObjectBuilder};
|
use serde_json::builder::{ArrayBuilder, ObjectBuilder};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_array_builder() {
|
fn test_array_builder() {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use serde::json::{self, Value};
|
use serde_json::{self, Value};
|
||||||
|
|
||||||
macro_rules! btreemap {
|
macro_rules! btreemap {
|
||||||
() => {
|
() => {
|
||||||
@@ -131,24 +131,43 @@ enum Lifetimes<'a> {
|
|||||||
NoLifetimeMap { a: i32 },
|
NoLifetimeMap { a: i32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GenericStruct<T> {
|
||||||
|
x: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GenericNewtypeStruct<T>(T);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct GenericTupleStruct<T, U>(T, U);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum GenericEnum<T, U> {
|
||||||
|
Unit,
|
||||||
|
Newtype(T),
|
||||||
|
Seq(T, U),
|
||||||
|
Map { x: T, y: U },
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_named_unit() {
|
fn test_named_unit() {
|
||||||
let named_unit = NamedUnit;
|
let named_unit = NamedUnit;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&named_unit).unwrap(),
|
serde_json::to_string(&named_unit).unwrap(),
|
||||||
"null".to_string()
|
"null".to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_value(&named_unit),
|
serde_json::to_value(&named_unit),
|
||||||
Value::Null
|
Value::Null
|
||||||
);
|
);
|
||||||
|
|
||||||
let v: NamedUnit = json::from_str("null").unwrap();
|
let v: NamedUnit = serde_json::from_str("null").unwrap();
|
||||||
assert_eq!(v, named_unit);
|
assert_eq!(v, named_unit);
|
||||||
|
|
||||||
let v: NamedUnit = json::from_value(Value::Null).unwrap();
|
let v: NamedUnit = serde_json::from_value(Value::Null).unwrap();
|
||||||
assert_eq!(v, named_unit);
|
assert_eq!(v, named_unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,25 +179,25 @@ fn test_ser_named_tuple() {
|
|||||||
let named_tuple = SerNamedTuple(&a, &mut b, c);
|
let named_tuple = SerNamedTuple(&a, &mut b, c);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&named_tuple).unwrap(),
|
serde_json::to_string(&named_tuple).unwrap(),
|
||||||
"[5,6,7]"
|
"[5,6,7]"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_value(&named_tuple),
|
serde_json::to_value(&named_tuple),
|
||||||
Value::Array(vec![Value::U64(5), Value::U64(6), Value::U64(7)])
|
Value::Array(vec![Value::U64(5), Value::U64(6), Value::U64(7)])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_de_named_tuple() {
|
fn test_de_named_tuple() {
|
||||||
let v: DeNamedTuple<i32, i32, i32> = json::from_str("[1,2,3]").unwrap();
|
let v: DeNamedTuple<i32, i32, i32> = serde_json::from_str("[1,2,3]").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v,
|
v,
|
||||||
DeNamedTuple(1, 2, 3)
|
DeNamedTuple(1, 2, 3)
|
||||||
);
|
);
|
||||||
|
|
||||||
let v: Value = json::from_str("[1,2,3]").unwrap();
|
let v: Value = serde_json::from_str("[1,2,3]").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v,
|
v,
|
||||||
Value::Array(vec![
|
Value::Array(vec![
|
||||||
@@ -201,12 +220,12 @@ fn test_ser_named_map() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&named_map).unwrap(),
|
serde_json::to_string(&named_map).unwrap(),
|
||||||
"{\"a\":5,\"b\":6,\"c\":7}"
|
"{\"a\":5,\"b\":6,\"c\":7}"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_value(&named_map),
|
serde_json::to_value(&named_map),
|
||||||
Value::Object(btreemap![
|
Value::Object(btreemap![
|
||||||
"a".to_string() => Value::U64(5),
|
"a".to_string() => Value::U64(5),
|
||||||
"b".to_string() => Value::U64(6),
|
"b".to_string() => Value::U64(6),
|
||||||
@@ -223,12 +242,12 @@ fn test_de_named_map() {
|
|||||||
c: 7,
|
c: 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
let v2: DeNamedMap<i32, i32, i32> = json::from_str(
|
let v2: DeNamedMap<i32, i32, i32> = serde_json::from_str(
|
||||||
"{\"a\":5,\"b\":6,\"c\":7}"
|
"{\"a\":5,\"b\":6,\"c\":7}"
|
||||||
).unwrap();
|
).unwrap();
|
||||||
assert_eq!(v, v2);
|
assert_eq!(v, v2);
|
||||||
|
|
||||||
let v2 = json::from_value(Value::Object(btreemap![
|
let v2 = serde_json::from_value(Value::Object(btreemap![
|
||||||
"a".to_string() => Value::U64(5),
|
"a".to_string() => Value::U64(5),
|
||||||
"b".to_string() => Value::U64(6),
|
"b".to_string() => Value::U64(6),
|
||||||
"c".to_string() => Value::U64(7)
|
"c".to_string() => Value::U64(7)
|
||||||
@@ -239,12 +258,12 @@ fn test_de_named_map() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_ser_enum_unit() {
|
fn test_ser_enum_unit() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&SerEnum::Unit::<u32, u32, u32>).unwrap(),
|
serde_json::to_string(&SerEnum::Unit::<u32, u32, u32>).unwrap(),
|
||||||
"{\"Unit\":[]}"
|
"{\"Unit\":[]}"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_value(&SerEnum::Unit::<u32, u32, u32>),
|
serde_json::to_value(&SerEnum::Unit::<u32, u32, u32>),
|
||||||
Value::Object(btreemap!(
|
Value::Object(btreemap!(
|
||||||
"Unit".to_string() => Value::Array(vec![]))
|
"Unit".to_string() => Value::Array(vec![]))
|
||||||
)
|
)
|
||||||
@@ -261,7 +280,7 @@ fn test_ser_enum_seq() {
|
|||||||
//let f = 6;
|
//let f = 6;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&SerEnum::Seq(
|
serde_json::to_string(&SerEnum::Seq(
|
||||||
a,
|
a,
|
||||||
b,
|
b,
|
||||||
&c,
|
&c,
|
||||||
@@ -273,7 +292,7 @@ fn test_ser_enum_seq() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_value(&SerEnum::Seq(
|
serde_json::to_value(&SerEnum::Seq(
|
||||||
a,
|
a,
|
||||||
b,
|
b,
|
||||||
&c,
|
&c,
|
||||||
@@ -304,7 +323,7 @@ fn test_ser_enum_map() {
|
|||||||
//let f = 6;
|
//let f = 6;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&SerEnum::Map {
|
serde_json::to_string(&SerEnum::Map {
|
||||||
a: a,
|
a: a,
|
||||||
b: b,
|
b: b,
|
||||||
c: &c,
|
c: &c,
|
||||||
@@ -316,7 +335,7 @@ fn test_ser_enum_map() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_value(&SerEnum::Map {
|
serde_json::to_value(&SerEnum::Map {
|
||||||
a: a,
|
a: a,
|
||||||
b: b,
|
b: b,
|
||||||
c: &c,
|
c: &c,
|
||||||
@@ -339,13 +358,13 @@ fn test_ser_enum_map() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_de_enum_unit() {
|
fn test_de_enum_unit() {
|
||||||
let v: DeEnum<_, _, _> = json::from_str("{\"Unit\":[]}").unwrap();
|
let v: DeEnum<_, _, _> = serde_json::from_str("{\"Unit\":[]}").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v,
|
v,
|
||||||
DeEnum::Unit::<u32, u32, u32>
|
DeEnum::Unit::<u32, u32, u32>
|
||||||
);
|
);
|
||||||
|
|
||||||
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
|
let v: DeEnum<_, _, _> = serde_json::from_value(Value::Object(btreemap!(
|
||||||
"Unit".to_string() => Value::Array(vec![]))
|
"Unit".to_string() => Value::Array(vec![]))
|
||||||
)).unwrap();
|
)).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -363,7 +382,7 @@ fn test_de_enum_seq() {
|
|||||||
let e = 5;
|
let e = 5;
|
||||||
//let f = 6;
|
//let f = 6;
|
||||||
|
|
||||||
let v: DeEnum<_, _, _> = json::from_str("{\"Seq\":[1,2,3,5]}").unwrap();
|
let v: DeEnum<_, _, _> = serde_json::from_str("{\"Seq\":[1,2,3,5]}").unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v,
|
v,
|
||||||
DeEnum::Seq(
|
DeEnum::Seq(
|
||||||
@@ -376,7 +395,7 @@ fn test_de_enum_seq() {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
|
let v: DeEnum<_, _, _> = serde_json::from_value(Value::Object(btreemap!(
|
||||||
"Seq".to_string() => Value::Array(vec![
|
"Seq".to_string() => Value::Array(vec![
|
||||||
Value::U64(1),
|
Value::U64(1),
|
||||||
Value::U64(2),
|
Value::U64(2),
|
||||||
@@ -408,7 +427,7 @@ fn test_de_enum_map() {
|
|||||||
let e = 5;
|
let e = 5;
|
||||||
//let f = 6;
|
//let f = 6;
|
||||||
|
|
||||||
let v: DeEnum<_, _, _> = json::from_str(
|
let v: DeEnum<_, _, _> = serde_json::from_str(
|
||||||
"{\"Map\":{\"a\":1,\"b\":2,\"c\":3,\"e\":5}}"
|
"{\"Map\":{\"a\":1,\"b\":2,\"c\":3,\"e\":5}}"
|
||||||
).unwrap();
|
).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -423,7 +442,7 @@ fn test_de_enum_map() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
|
let v: DeEnum<_, _, _> = serde_json::from_value(Value::Object(btreemap!(
|
||||||
"Map".to_string() => Value::Object(btreemap![
|
"Map".to_string() => Value::Object(btreemap![
|
||||||
"a".to_string() => Value::U64(1),
|
"a".to_string() => Value::U64(1),
|
||||||
"b".to_string() => Value::U64(2),
|
"b".to_string() => Value::U64(2),
|
||||||
@@ -452,26 +471,66 @@ fn test_lifetimes() {
|
|||||||
let value = 5;
|
let value = 5;
|
||||||
let lifetime = Lifetimes::LifetimeSeq(&value);
|
let lifetime = Lifetimes::LifetimeSeq(&value);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&lifetime).unwrap(),
|
serde_json::to_string(&lifetime).unwrap(),
|
||||||
"{\"LifetimeSeq\":[5]}"
|
"{\"LifetimeSeq\":5}"
|
||||||
);
|
);
|
||||||
|
|
||||||
let lifetime = Lifetimes::NoLifetimeSeq(5);
|
let lifetime = Lifetimes::NoLifetimeSeq(5);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&lifetime).unwrap(),
|
serde_json::to_string(&lifetime).unwrap(),
|
||||||
"{\"NoLifetimeSeq\":[5]}"
|
"{\"NoLifetimeSeq\":5}"
|
||||||
);
|
);
|
||||||
|
|
||||||
let value = 5;
|
let value = 5;
|
||||||
let lifetime = Lifetimes::LifetimeMap { a: &value };
|
let lifetime = Lifetimes::LifetimeMap { a: &value };
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&lifetime).unwrap(),
|
serde_json::to_string(&lifetime).unwrap(),
|
||||||
"{\"LifetimeMap\":{\"a\":5}}"
|
"{\"LifetimeMap\":{\"a\":5}}"
|
||||||
);
|
);
|
||||||
|
|
||||||
let lifetime = Lifetimes::NoLifetimeMap { a: 5 };
|
let lifetime = Lifetimes::NoLifetimeMap { a: 5 };
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json::to_string(&lifetime).unwrap(),
|
serde_json::to_string(&lifetime).unwrap(),
|
||||||
"{\"NoLifetimeMap\":{\"a\":5}}"
|
"{\"NoLifetimeMap\":{\"a\":5}}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! declare_tests {
|
||||||
|
($($name:ident { $($ty:ty : $value:expr => $str:expr,)+ })+) => {
|
||||||
|
$(
|
||||||
|
#[test]
|
||||||
|
fn $name() {
|
||||||
|
$(
|
||||||
|
let value: $ty = $value;
|
||||||
|
|
||||||
|
let string = serde_json::to_string(&value).unwrap();
|
||||||
|
assert_eq!(string, $str);
|
||||||
|
|
||||||
|
let expected: $ty = serde_json::from_str(&string).unwrap();
|
||||||
|
assert_eq!(value, expected);
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_tests! {
|
||||||
|
test_generic_struct {
|
||||||
|
GenericStruct<u32> : GenericStruct { x: 5 } => "{\"x\":5}",
|
||||||
|
}
|
||||||
|
test_generic_newtype_struct {
|
||||||
|
GenericNewtypeStruct<u32> : GenericNewtypeStruct(5) => "5",
|
||||||
|
}
|
||||||
|
test_generic_tuple_struct {
|
||||||
|
GenericTupleStruct<u32, u32> : GenericTupleStruct(5, 6) => "[5,6]",
|
||||||
|
}
|
||||||
|
test_generic_enum_newtype {
|
||||||
|
GenericEnum<u32, u32> : GenericEnum::Newtype(5) => "{\"Newtype\":5}",
|
||||||
|
}
|
||||||
|
test_generic_enum_seq {
|
||||||
|
GenericEnum<u32, u32> : GenericEnum::Seq(5, 6) => "{\"Seq\":[5,6]}",
|
||||||
|
}
|
||||||
|
test_generic_enum_map {
|
||||||
|
GenericEnum<u32, u32> : GenericEnum::Map { x: 5, y: 6 } => "{\"Map\":{\"x\":5,\"y\":6}}",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,17 +24,19 @@ pub enum Token<'a> {
|
|||||||
Option(bool),
|
Option(bool),
|
||||||
|
|
||||||
Unit,
|
Unit,
|
||||||
NamedUnit(&'a str),
|
UnitStruct(&'a str),
|
||||||
EnumUnit(&'a str, &'a str),
|
EnumUnit(&'a str, &'a str),
|
||||||
|
|
||||||
|
EnumNewtype(&'a str, &'a str),
|
||||||
|
|
||||||
SeqStart(Option<usize>),
|
SeqStart(Option<usize>),
|
||||||
NamedSeqStart(&'a str, Option<usize>),
|
TupleStructStart(&'a str, Option<usize>),
|
||||||
EnumSeqStart(&'a str, &'a str, Option<usize>),
|
EnumSeqStart(&'a str, &'a str, Option<usize>),
|
||||||
SeqSep,
|
SeqSep,
|
||||||
SeqEnd,
|
SeqEnd,
|
||||||
|
|
||||||
MapStart(Option<usize>),
|
MapStart(Option<usize>),
|
||||||
NamedMapStart(&'a str, Option<usize>),
|
StructStart(&'a str, Option<usize>),
|
||||||
EnumMapStart(&'a str, &'a str, Option<usize>),
|
EnumMapStart(&'a str, &'a str, Option<usize>),
|
||||||
MapSep,
|
MapSep,
|
||||||
MapEnd,
|
MapEnd,
|
||||||
@@ -80,13 +82,31 @@ impl<'a> Serializer for AssertSerializer<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_named_unit(&mut self, name: &str) -> Result<(), ()> {
|
fn visit_newtype_variant<T>(&mut self,
|
||||||
assert_eq!(self.iter.next().unwrap(), Token::NamedUnit(name));
|
name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str,
|
||||||
|
value: T) -> Result<(), ()>
|
||||||
|
where T: Serialize,
|
||||||
|
{
|
||||||
|
assert_eq!(self.iter.next(), Some(Token::EnumNewtype(name, variant)));
|
||||||
|
value.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_unit_struct(&mut self, name: &str) -> Result<(), ()> {
|
||||||
|
assert_eq!(self.iter.next().unwrap(), Token::UnitStruct(name));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_enum_unit(&mut self, name: &str, variant: &str) -> Result<(), ()> {
|
fn visit_unit_variant(&mut self,
|
||||||
assert_eq!(self.iter.next().unwrap(), Token::EnumUnit(name, variant));
|
name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str) -> Result<(), ()> {
|
||||||
|
assert_eq!(
|
||||||
|
self.iter.next().unwrap(),
|
||||||
|
Token::EnumUnit(name, variant)
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,25 +208,32 @@ impl<'a> Serializer for AssertSerializer<'a> {
|
|||||||
self.visit_sequence(visitor)
|
self.visit_sequence(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_named_seq<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
|
fn visit_tuple_struct<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
|
||||||
where V: SeqVisitor
|
where V: SeqVisitor
|
||||||
{
|
{
|
||||||
let len = visitor.len();
|
let len = visitor.len();
|
||||||
|
|
||||||
assert_eq!(self.iter.next().unwrap(), Token::NamedSeqStart(name, len));
|
assert_eq!(
|
||||||
|
self.iter.next().unwrap(),
|
||||||
|
Token::TupleStructStart(name, len)
|
||||||
|
);
|
||||||
|
|
||||||
self.visit_sequence(visitor)
|
self.visit_sequence(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_enum_seq<V>(&mut self,
|
fn visit_tuple_variant<V>(&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
variant: &str,
|
_variant_index: usize,
|
||||||
visitor: V) -> Result<(), ()>
|
variant: &str,
|
||||||
|
visitor: V) -> Result<(), ()>
|
||||||
where V: SeqVisitor
|
where V: SeqVisitor
|
||||||
{
|
{
|
||||||
let len = visitor.len();
|
let len = visitor.len();
|
||||||
|
|
||||||
assert_eq!(self.iter.next().unwrap(), Token::EnumSeqStart(name, variant, len));
|
assert_eq!(
|
||||||
|
self.iter.next().unwrap(),
|
||||||
|
Token::EnumSeqStart(name, variant, len)
|
||||||
|
);
|
||||||
|
|
||||||
self.visit_sequence(visitor)
|
self.visit_sequence(visitor)
|
||||||
}
|
}
|
||||||
@@ -228,22 +255,32 @@ impl<'a> Serializer for AssertSerializer<'a> {
|
|||||||
self.visit_mapping(visitor)
|
self.visit_mapping(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_named_map<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
|
fn visit_struct<V>(&mut self, name: &str, visitor: V) -> Result<(), ()>
|
||||||
where V: MapVisitor
|
where V: MapVisitor
|
||||||
{
|
{
|
||||||
let len = visitor.len();
|
let len = visitor.len();
|
||||||
|
|
||||||
assert_eq!(self.iter.next().unwrap(), Token::NamedMapStart(name, len));
|
assert_eq!(
|
||||||
|
self.iter.next().unwrap(),
|
||||||
|
Token::StructStart(name, len)
|
||||||
|
);
|
||||||
|
|
||||||
self.visit_mapping(visitor)
|
self.visit_mapping(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_enum_map<V>(&mut self, name: &str, variant: &str, visitor: V) -> Result<(), ()>
|
fn visit_struct_variant<V>(&mut self,
|
||||||
|
name: &str,
|
||||||
|
_variant_index: usize,
|
||||||
|
variant: &str,
|
||||||
|
visitor: V) -> Result<(), ()>
|
||||||
where V: MapVisitor
|
where V: MapVisitor
|
||||||
{
|
{
|
||||||
let len = visitor.len();
|
let len = visitor.len();
|
||||||
|
|
||||||
assert_eq!(self.iter.next().unwrap(), Token::EnumMapStart(name, variant, len));
|
assert_eq!(
|
||||||
|
self.iter.next().unwrap(),
|
||||||
|
Token::EnumMapStart(name, variant, len)
|
||||||
|
);
|
||||||
|
|
||||||
self.visit_mapping(visitor)
|
self.visit_mapping(visitor)
|
||||||
}
|
}
|
||||||
@@ -262,13 +299,13 @@ impl<'a> Serializer for AssertSerializer<'a> {
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct NamedUnit;
|
struct UnitStruct;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct NamedSeq(i32, i32, i32);
|
struct TupleStruct(i32, i32, i32);
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct NamedMap {
|
struct Struct {
|
||||||
a: i32,
|
a: i32,
|
||||||
b: i32,
|
b: i32,
|
||||||
c: i32,
|
c: i32,
|
||||||
@@ -277,6 +314,7 @@ struct NamedMap {
|
|||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
enum Enum {
|
enum Enum {
|
||||||
Unit,
|
Unit,
|
||||||
|
One(i32),
|
||||||
Seq(i32, i32),
|
Seq(i32, i32),
|
||||||
Map { a: i32, b: i32 },
|
Map { a: i32, b: i32 },
|
||||||
}
|
}
|
||||||
@@ -356,6 +394,16 @@ declare_tests! {
|
|||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
test_result {
|
||||||
|
Ok::<i32, i32>(0) => vec![
|
||||||
|
Token::EnumNewtype("Result", "Ok"),
|
||||||
|
Token::I32(0),
|
||||||
|
],
|
||||||
|
Err::<i32, i32>(1) => vec![
|
||||||
|
Token::EnumNewtype("Result", "Err"),
|
||||||
|
Token::I32(1),
|
||||||
|
],
|
||||||
|
}
|
||||||
test_slice {
|
test_slice {
|
||||||
&[0][..0] => vec![
|
&[0][..0] => vec![
|
||||||
Token::SeqStart(Some(0)),
|
Token::SeqStart(Some(0)),
|
||||||
@@ -480,12 +528,12 @@ declare_tests! {
|
|||||||
Token::MapEnd,
|
Token::MapEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
test_named_unit {
|
test_unit_struct {
|
||||||
NamedUnit => vec![Token::NamedUnit("NamedUnit")],
|
UnitStruct => vec![Token::UnitStruct("UnitStruct")],
|
||||||
}
|
}
|
||||||
test_named_seq {
|
test_tuple_struct {
|
||||||
NamedSeq(1, 2, 3) => vec![
|
TupleStruct(1, 2, 3) => vec![
|
||||||
Token::NamedSeqStart("NamedSeq", Some(3)),
|
Token::TupleStructStart("TupleStruct", Some(3)),
|
||||||
Token::SeqSep,
|
Token::SeqSep,
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
|
|
||||||
@@ -497,9 +545,9 @@ declare_tests! {
|
|||||||
Token::SeqEnd,
|
Token::SeqEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
test_named_map {
|
test_struct {
|
||||||
NamedMap { a: 1, b: 2, c: 3 } => vec![
|
Struct { a: 1, b: 2, c: 3 } => vec![
|
||||||
Token::NamedMapStart("NamedMap", Some(3)),
|
Token::StructStart("Struct", Some(3)),
|
||||||
Token::MapSep,
|
Token::MapSep,
|
||||||
Token::Str("a"),
|
Token::Str("a"),
|
||||||
Token::I32(1),
|
Token::I32(1),
|
||||||
@@ -516,6 +564,7 @@ declare_tests! {
|
|||||||
}
|
}
|
||||||
test_enum {
|
test_enum {
|
||||||
Enum::Unit => vec![Token::EnumUnit("Enum", "Unit")],
|
Enum::Unit => vec![Token::EnumUnit("Enum", "Unit")],
|
||||||
|
Enum::One(42) => vec![Token::EnumNewtype("Enum", "One"), Token::I32(42)],
|
||||||
Enum::Seq(1, 2) => vec![
|
Enum::Seq(1, 2) => vec![
|
||||||
Token::EnumSeqStart("Enum", "Seq", Some(2)),
|
Token::EnumSeqStart("Enum", "Seq", Some(2)),
|
||||||
Token::SeqSep,
|
Token::SeqSep,
|
||||||
|
|||||||
Reference in New Issue
Block a user