Compare commits

...

42 Commits

Author SHA1 Message Date
Erick Tryzelaar eb9c860cb4 Rename iterator.rs to iter.rs and expose it. 2015-04-26 09:23:08 -07:00
Erick Tryzelaar cf38b8dae5 Add some docs to LineColIterator, expose the underlying iterator 2015-04-26 09:22:56 -07:00
Erick Tryzelaar 75af81234f LineColIterator doesn't need to be peekable. 2015-04-26 09:21:52 -07:00
Erick Tryzelaar 7cc319acca Bump version to 0.3.2. 2015-04-26 09:21:26 -07:00
Erick Tryzelaar 3b44792ff3 Merge pull request #64 from oli-obk/missing_renamed_field
missing field errors displayed original field name instead of renamed
2015-04-26 08:09:00 -07:00
Erick Tryzelaar 678bad241e Merge pull request #66 from daniellandau/fix/compilation
Fix compilation for latest nightly
2015-04-25 08:13:39 -07:00
Daniel Landau 5b1225cc87 Fix compilation for latest nightly 2015-04-24 22:35:56 +03:00
Oliver Schneider 1748831152 missing field errors displayed original field name instead of renamed
closes #63
2015-04-23 17:28:42 +02:00
Erick Tryzelaar ed1b476a22 Merge pull request #58 from oli-obk/separate_line_col
separate out the line/column counting from character iteration
2015-04-22 11:02:55 -07:00
Erick Tryzelaar 79c59ebae1 Merge pull request #62 from hugoduncan/add-ser-de-rename
Add serialize, deserialize specific rename
2015-04-22 11:01:38 -07:00
Hugo Duncan fd6462f8d1 Add serialize, deserialize specific rename
Adds the rename_serialize and rename_deserialize field attributes to
specify serialisation and deserialisation specific renames.
2015-04-21 17:58:18 -04:00
Oliver Schneider c37f67b0a1 separate out the line/column counting from character iteration 2015-04-16 16:31:56 +02:00
Erick Tryzelaar 195f7380b5 Merge pull request #56 from derhaskell/patch-1
fixes struct serialization example for rust 1.0.0-beta
2015-04-13 06:21:37 -07:00
derhaskell becb8c48e8 fixes typo in deserialization example 2015-04-13 13:37:06 +02:00
derhaskell aa16ecf4d3 Update README.md 2015-04-13 13:28:47 +02:00
derhaskell ddda360fec Update README.md
fixes struct serialization example for rust 1.0.0-beta
2015-04-13 13:27:15 +02:00
Erick Tryzelaar cca72f2dbc Merge pull request #55 from sfackler/master
Add doc link to Cargo.toml and doc attr
2015-04-12 22:22:25 -07:00
Steven Fackler 5013b37c09 Add doc link to Cargo.toml and doc attr
The attribute allows cross-crate rustdoc links.
2015-04-12 22:21:00 -07:00
Erick Tryzelaar c90dc9f48f bump version to 0.3.1 2015-04-12 11:43:35 -07:00
Erick Tryzelaar 67e8ca354c Remove core feature 2015-04-12 11:36:09 -07:00
Erick Tryzelaar 9a4ba047c4 Remove collections feature flag and disable VecMap, which is unstable 2015-04-12 10:48:32 -07:00
Erick Tryzelaar 7622255d6f Remove the std_misc feature flag 2015-04-12 10:43:29 -07:00
Erick Tryzelaar 8ba1e7aceb Remove the need for the unicode feature flag 2015-04-12 10:42:57 -07:00
Erick Tryzelaar 5f6838130d Update to Rust HEAD 2015-04-12 10:32:54 -07:00
Erick Tryzelaar e0eff942b1 Add Error::unknown_field_error 2015-04-12 10:32:54 -07:00
Erick Tryzelaar 1da47c0870 Change de::VariantVisitor to let deserializers know the variant kind
This allows formats like cbor that encode a unit variant as just a
string to work.

[breaking-change]
2015-04-12 10:32:54 -07:00
Erick Tryzelaar d36879f5ee Merge pull request #54 from apoelstra/no-impl-bytebuf
Remove `impl Into<Vec<u8>> for ByteBuf` since it causes a compile error
2015-04-12 10:32:36 -07:00
Andrew Poelstra f363cb435a Remove impl Into<Vec<u8>> for ByteBuf since it causes a compile error
As BurntSushi observes, there is an `impl<T, U> Into<U> for T where U: From<T>`
in libcore. We have `From<Vec<u8>>` for `ByteBuf` since we have implemented
`From<T> for ByteBuf where T: Into<Vec<u8>>`, so this is redundant anyway.
2015-04-11 17:51:31 -05:00
Erick Tryzelaar d8506e9a6d Update to rust HEAD 2015-04-05 13:20:33 -04:00
Erick Tryzelaar 87503d11e9 Merge pull request #49 from alexcrichton/tweak-some-impls
Tweak some Deserialize/Serialize impls
2015-04-03 12:04:50 -04:00
Erick Tryzelaar d0b49d9b89 Finish updating to rust HEAD 2015-04-02 19:13:25 -07:00
Erick Tryzelaar b30965ede4 Get serde to build, but tests are still failing 2015-04-02 13:27:57 -07:00
Alex Crichton ace6d9e442 Generalize some serialization impls
* Impl Serialize for bare `str`
* Expand `&T` and `&mut T` blanket impls to include `T: ?Sized`
* Expand `Box<T>` blanket impl to include `T: ?Sized`
2015-04-02 12:54:21 -07:00
Alex Crichton e150553d58 Add deserialize impls for smart pointers
This allows deserializing into a Box/Arc/Rc pointer
2015-04-02 12:53:51 -07:00
Erick Tryzelaar ed569bd3f6 Update to latest rust nightly 2015-04-01 22:51:02 -07:00
Erick Tryzelaar d00c1ad6d0 Remove the use of serde_macros from the doctests
This has been disabled in the upcoming beta.
2015-04-01 22:19:14 -07:00
Erick Tryzelaar 2cd49060fa Rename #[serde(alias)] to #[serde(rename)] and add tests
Closes #9 and #47.
2015-04-01 22:14:28 -07:00
Erick Tryzelaar 54a970e694 Remove an unnecessary import 2015-04-01 22:13:34 -07:00
Erick Tryzelaar d57f02884f Work on the README, add a json example 2015-04-01 21:59:37 -07:00
Erick Tryzelaar dcf7037792 Add some basic docs 2015-03-31 22:33:18 -07:00
Erick Tryzelaar 55eb390778 Update the readme 2015-03-31 22:16:15 -07:00
Erick Tryzelaar 99b9524201 Change the name of ValueDeserializer::{,into_}deserializer 2015-03-31 20:45:59 -07:00
30 changed files with 1404 additions and 308 deletions
+6 -2
View File
@@ -1,14 +1,18 @@
[package]
name = "serde"
version = "0.3.0"
version = "0.3.2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A serialization/deserialization framework"
repository = "https://github.com/erickt/rust-serde"
documentation = "http://erickt.github.io/rust-serde/serde"
[dependencies]
num = "*"
[dev-dependencies]
rustc-serialize = "*"
[dev-dependencies.serde_macros]
path = "serde_macros/"
version = "0.3.0"
version = "0.3.2"
+409 -20
View File
@@ -1,34 +1,423 @@
Experimental Rust Serialization Library.
Serde Rust Serialization Framework
==================================
[![Build Status](https://travis-ci.org/erickt/rust-serde.png?branch=master)](https://travis-ci.org/erickt/rust-serde)
This is an experiment to modernize rust's `libserialize` library. It is designed to implement https://github.com/rust-lang/rfcs/pull/22. `rust-serde` is an attempt to address a major shortcoming in `libserialize`. For normal structures, when you say you want to deserialize into:
Serde is a powerful framework that enables serialization libraries to
generically serialize Rust data structures without the overhead of runtime type
information. In many situations, the handshake protocol between serializers and
serializees can be completely optimized away, leaving Serde to perform roughly
the same speed as a hand written serializer for a specific type.
Documentation is available at http://erickt.github.io/rust-serde/serde
Making a Type Serializable
==========================
The simplest way to make a type serializable is to use the `serde_macros`
syntax extension, which comes with a `#[derive(Serialize, Deserialize)]`
annotation, which automatically generates implementations of
[Serialize](http://erickt.github.io/rust-serde/serde/ser/trait.Serialize.html)
and
[Deserialize](http://erickt.github.io/rust-serde/serde/de/trait.Deserialize.html)
for the annotated type:
```rust
struct Foo {
x: int,
y: int,
#[feature(custom_derive, plugin)]
#[plugin(serde_macros)]
extern crate serde;
...
#[derive(Serialize, Deserialize)]
struct Point {
x: i32,
y: i32,
}
```
`libserialize`'s deserializer essentially asks for:
Serde bundles a high performance JSON serializer and deserializer,
[serde::json](http://erickt.github.io/rust-serde/serde/json/index.html),
which comes with the helper functions
[to_string](http://erickt.github.io/rust-serde/serde/json/ser/fn.to_string.html)
and
[from_str](http://erickt.github.io/rust-serde/serde/json/de/fn.from_str.html)
that make it easy to go to and from JSON:
* Is the next value a struct named "Foo"? If not, error.
* Is the next field named "x"? If not, error.
* Is the next value an "int"? If not, error.
* Is the next field named "y"? If not, error.
* Is the next value an "int"? If not, error.
* Is the struct finished? If not, error.
```rust
use serde::json;
While this works for user defined structures, it cannot support deserializing into a value like `json::Json`, which is an enum that can represent every JSON value. In order to support that, it needs to be able to do some lookahead:
...
* What is the next value type?
* If a struct, parse a struct.
* If an integer, parse an integer.
* ...
let point = Point { x: 1, y: 2 };
let serialized_point = json::to_string(&point).unwrap();
More formally, `libserialize` implements a LL(0) grammar, whereas `json::Json` requires a LL(1) grammar. `rust-serde` provides this by implementing a serializer and deserializer that produces a tagged token stream of values. This enables a `Deserializable` for `json::Json` to look at the next token before deciding on how to parse the value.
println!("{}", serialized_point); // prints: {"x":1,"y":2}
---
let deserialize_point: Point = json::from_str(&serialized_point).unwrap();
```
There is now also a new library variation called `serde2`. This removes the need for tagged values and replaces them with a `Visitor` pattern. This pattern is very similar to the `Iterator` pattern, but it threads some custom state through visiting each type. This gets many of the benefits of the `serde` library without needing to always pay for tagging the variants.
[serde::json](http://erickt.github.io/rust-serde/serde/json/index.html) also
supports a generic
[Value](http://erickt.github.io/rust-serde/serde/json/value/enum.Value.html)
type, which can represent any JSON value. Also, any
[Serialize](http://erickt.github.io/rust-serde/serde/ser/trait.Serialize.html)
and
[Deserialize](http://erickt.github.io/rust-serde/serde/de/trait.Deserialize.html)
can be converted into a
[Value](http://erickt.github.io/rust-serde/serde/json/value/enum.Value.html)
with the methods
[to_value](http://erickt.github.io/rust-serde/serde/json/value/fn.to_value.html)
and
[from_value](http://erickt.github.io/rust-serde/serde/json/value/fn.from_value.html):
```rust
let point = Point { x: 1, y: 2 };
let point_value = json::to_value(&point).unwrap();
println!("{}", point_value.find("x")); // prints: Some(1)
let deserialize_point: Point = json::from_value(point_value).unwrap();
```
Serialization without Macros
============================
Under the covers, Serde extensively uses the Visitor pattern to thread state
between the
[Serializer](http://erickt.github.io/rust-serde/serde/ser/trait.Serializer.html)
and
[Serialize](http://erickt.github.io/rust-serde/serde/ser/trait.Serialize.html)
without the two having specific information about each other's concrete type.
This has many of the same benefits as frameworks that use runtime type
information without the overhead. In fact, when compiling with optimizations,
Rust is able to remove most or all the visitor state, and generate code that's
nearly as fast as a hand written serializer format for a specific type.
To see it in action, lets look at how a simple type like `i32` is serialized.
The
[Serializer](http://erickt.github.io/rust-serde/serde/ser/trait.Serializer.html)
is threaded through the type:
```rust
impl serde::Serialize for i32 {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer,
{
serializer.visit_i32(*self)
}
}
```
As you can see it's pretty simple. More complex types like `BTreeMap` need to
pass a
[MapVisitor](http://erickt.github.io/rust-serde/serde/ser/trait.MapVisitor.html)
to the
[Serializer](http://erickt.github.io/rust-serde/serde/ser/trait.Serializer.html)
in order to walk through the type:
```rust
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,
V: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
pub struct MapIteratorVisitor<Iter> {
iter: Iter,
len: Option<usize>,
}
impl<K, V, Iter> MapIteratorVisitor<Iter>
where Iter: Iterator<Item=(K, V)>
{
#[inline]
pub fn new(iter: Iter, len: Option<usize>) -> MapIteratorVisitor<Iter> {
MapIteratorVisitor {
iter: iter,
len: len,
}
}
}
impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
where K: Serialize,
V: Serialize,
I: Iterator<Item=(K, V)>,
{
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: Serializer,
{
match self.iter.next() {
Some((key, value)) => {
let value = try!(serializer.visit_map_elt(key, value));
Ok(Some(value))
}
None => Ok(None)
}
}
#[inline]
fn len(&self) -> Option<usize> {
self.len
}
}
```
Serializing structs follow this same pattern. In fact, structs are represented
as a named map. It's visitor uses a simple state machine to iterate through all
the fields:
```rust
struct Point {
x: i32,
y: i32,
}
impl serde::Serialize for Point {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: serde::Serializer
{
serializer.visit_named_map("Point", PointMapVisitor {
value: self,
state: 0,
})
}
}
struct PointMapVisitor<'a> {
value: &'a Point,
state: u8,
}
impl<'a> serde::ser::MapVisitor for PointMapVisitor<'a> {
fn visit<S>(&mut self, serializer: &mut S) -> Result<Option<()>, S::Error>
where S: serde::Serializer
{
match self.state {
0 => {
self.state += 1;
Ok(Some(try!(serializer.visit_map_elt("x", &self.value.x))))
}
1 => {
self.state += 1;
Ok(Some(try!(serializer.visit_map_elt("y", &self.value.y))))
}
_ => {
Ok(None)
}
}
}
}
```
Deserialization without Macros
==============================
Deserialization is a little more complicated since there's a bit more error
handling that needs to occur. Let's start with the simple `i32`
[Deserialize](http://erickt.github.io/rust-serde/serde/de/trait.Deserialize.html)
implementation. It passes a
[Visitor](http://erickt.github.io/rust-serde/serde/de/trait.Visitor.html) to the
[Deserializer](http://erickt.github.io/rust-serde/serde/de/trait.Deserializer.html).
The [Visitor](http://erickt.github.io/rust-serde/serde/de/trait.Visitor.html)
can create the `i32` from a variety of different types:
```rust
impl Deserialize for i32 {
fn deserialize<D>(deserializer: &mut D) -> Result<i32, D::Error>
where D: serde::Deserializer,
{
deserializer.visit(I32Visitor)
}
}
struct I32Visitor;
impl serde::de::Visitor for I32Visitor {
type Value = i32;
fn visit_i16<E>(&mut self, value: i16) -> Result<i16, E>
where E: Error,
{
self.visit_i32(value as i32)
}
fn visit_i32<E>(&mut self, value: i32) -> Result<i32, E>
where E: Error,
{
Ok(value)
}
...
```
Since it's possible for this type to get passed an unexpected type, we need a
way to error out. This is done by way of the
[Error](http://erickt.github.io/rust-serde/serde/de/trait.Error.html) trait,
which allows a
[Deserialize](http://erickt.github.io/rust-serde/serde/de/trait.Deserialize.html)
to generate an error for a few common error conditions. Here's how it could be used:
```rust
...
fn visit_string<E>(&mut self, _: String) -> Result<i32, E>
where E: Error,
{
Err(serde::de::Error::syntax_error())
}
...
```
Maps follow a similar pattern as before, and use a
[MapVisitor](http://erickt.github.io/rust-serde/serde/de/trait.MapVisitor.html)
to walk through the values generated by the
[Deserializer](http://erickt.github.io/rust-serde/serde/de/trait.Deserializer.html).
```rust
impl<K, V> serde::Deserialize for BTreeMap<K, V>
where K: serde::Deserialize + Eq + Ord,
V: serde::Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: serde::Deserializer,
{
deserializer.visit(BTreeMapVisitor::new())
}
}
pub struct BTreeMapVisitor<K, V> {
marker: PhantomData<BTreeMap<K, V>>,
}
impl<K, V> BTreeMapVisitor<K, V> {
pub fn new() -> Self {
BTreeMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> serde::de::Visitor for BTreeMapVisitor<K, V>
where K: serde::de::Deserialize + Ord,
V: serde::de::Deserialize
{
type Value = BTreeMap<K, V>;
fn visit_unit<E>(&mut self) -> Result<BTreeMap<K, V>, E>
where E: Error,
{
Ok(BTreeMap::new())
}
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<BTreeMap<K, V>, V_::Error>
where V_: MapVisitor,
{
let mut values = BTreeMap::new();
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
```
Deserializing structs goes a step further in order to support not allocating a
`String` to hold the field names. This is done by custom field enum that
deserializes an enum variant from a string. So for our `Point` example from
before, we need to generate:
```rust
enum PointField {
X,
Y,
}
impl serde::Deserialize for PointField {
fn deserialize<D>(deserializer: &mut D) -> Result<PointField, D::Error>
where D: serde::de::Deserializer
{
struct FieldVisitor;
impl serde::de::Visitor for FieldVisitor {
type Value = Field;
fn visit_str<E>(&mut self, value: &str) -> Result<PointField, E>
where E: serde::de::Error
{
match value {
"x" => Ok(Field::X),
"y" => Ok(Field::Y),
_ => Err(serde::de::Error::syntax_error()),
}
}
}
deserializer.visit(FieldVisitor)
}
}
```
This is then used in our actual deserializer:
```rust
impl serde::Deserialize for Point {
fn deserialize<D>(deserializer: &mut D) -> Result<Point, D::Error>
where D: serde::de::Deserializer
{
deserializer.visit_named_map("Point", PointVisitor)
}
}
struct PointVisitor;
impl serde::de::Visitor for PointVisitor {
type Value = Point;
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Point, V::Error>
where V: serde::de::MapVisitor
{
let mut x = None;
let mut y = None;
loop {
match try!(visitor.visit_key()) {
Some(Field::X) => { x = Some(try!(visitor.visit_value())); }
Some(Field::Y) => { y = Some(try!(visitor.visit_value())); }
None => { break; }
}
}
let x = match x {
Some(x) => x,
None => try!(visitor.missing_field("x")),
};
let y = match y {
Some(y) => y,
None => try!(visitor.missing_field("y")),
};
try!(visitor.end());
Ok(Point{ x: x, y: y })
}
}
```
+5 -5
View File
@@ -34,6 +34,8 @@ impl serde::de::Error for Error {
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn missing_field_error(_: &'static str) -> Error { Error::SyntaxError }
}
@@ -339,10 +341,8 @@ mod deserializer {
de::Deserialize::deserialize(self.de)
}
fn visit_value<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self.de, visitor)
fn visit_unit(&mut self) -> Result<(), Error> {
de::Deserialize::deserialize(self.de)
}
}
@@ -360,7 +360,7 @@ mod deserializer {
de::Deserialize::deserialize(self.de)
}
fn visit_value<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_seq(self)
+365 -10
View File
@@ -1,13 +1,14 @@
#![feature(custom_derive, collections, core, plugin, test)]
#![feature(custom_derive, collections, plugin, test)]
#![allow(non_camel_case_types)]
#![plugin(serde_macros)]
extern crate serde;
extern crate num;
extern crate rustc_serialize;
extern crate serde;
extern crate test;
use std::io::{self, Read, Write};
use std::num::FromPrimitive;
use num::FromPrimitive;
use test::Bencher;
use serde::de::{self, Deserialize, Deserializer};
@@ -30,7 +31,7 @@ struct Http {
request_uri: String,
}
#[derive(Copy, Debug, PartialEq, FromPrimitive)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum HttpProtocol {
HTTP_PROTOCOL_UNKNOWN,
HTTP10,
@@ -52,6 +53,21 @@ impl rustc_serialize::Decodable for HttpProtocol {
}
}
impl FromPrimitive for HttpProtocol {
fn from_i64(i: i64) -> Option<HttpProtocol> {
FromPrimitive::from_u64(i as u64)
}
fn from_u64(n: u64) -> Option<HttpProtocol> {
match n {
0 => Some(HttpProtocol::HTTP_PROTOCOL_UNKNOWN),
1 => Some(HttpProtocol::HTTP10),
2 => Some(HttpProtocol::HTTP11),
_ => None,
}
}
}
impl ser::Serialize for HttpProtocol {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -70,7 +86,7 @@ impl de::Deserialize for HttpProtocol {
}
}
#[derive(Copy, Debug, PartialEq, FromPrimitive)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum HttpMethod {
METHOD_UNKNOWN,
GET,
@@ -85,6 +101,29 @@ enum HttpMethod {
PATCH,
}
impl FromPrimitive for HttpMethod {
fn from_i64(i: i64) -> Option<HttpMethod> {
FromPrimitive::from_u64(i as u64)
}
fn from_u64(n: u64) -> Option<HttpMethod> {
match n {
0 => Some(HttpMethod::METHOD_UNKNOWN),
1 => Some(HttpMethod::GET),
2 => Some(HttpMethod::POST),
3 => Some(HttpMethod::DELETE),
4 => Some(HttpMethod::PUT),
5 => Some(HttpMethod::HEAD),
6 => Some(HttpMethod::PURGE),
7 => Some(HttpMethod::OPTIONS),
8 => Some(HttpMethod::PROPFIND),
9 => Some(HttpMethod::MKCOL),
10 => Some(HttpMethod::PATCH),
_ => None,
}
}
}
impl rustc_serialize::Encodable for HttpMethod {
fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(*self as usize).encode(s)
@@ -118,7 +157,7 @@ impl de::Deserialize for HttpMethod {
}
}
#[derive(Copy, Debug, PartialEq, FromPrimitive)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum CacheStatus {
CACHESTATUS_UNKNOWN,
Miss,
@@ -126,6 +165,22 @@ enum CacheStatus {
Hit,
}
impl FromPrimitive for CacheStatus {
fn from_i64(i: i64) -> Option<CacheStatus> {
FromPrimitive::from_u64(i as u64)
}
fn from_u64(n: u64) -> Option<CacheStatus> {
match n {
0 => Some(CacheStatus::CACHESTATUS_UNKNOWN),
1 => Some(CacheStatus::Miss),
2 => Some(CacheStatus::Expired),
3 => Some(CacheStatus::Hit),
_ => None,
}
}
}
impl rustc_serialize::Encodable for CacheStatus {
fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(*self as u8).encode(s)
@@ -167,13 +222,28 @@ struct Origin {
protocol: OriginProtocol,
}
#[derive(Copy, Debug, PartialEq, FromPrimitive)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum OriginProtocol {
ORIGIN_PROTOCOL_UNKNOWN,
HTTP,
HTTPS,
}
impl FromPrimitive for OriginProtocol {
fn from_i64(i: i64) -> Option<OriginProtocol> {
FromPrimitive::from_u64(i as u64)
}
fn from_u64(n: u64) -> Option<OriginProtocol> {
match n {
0 => Some(OriginProtocol::ORIGIN_PROTOCOL_UNKNOWN),
1 => Some(OriginProtocol::HTTP),
2 => Some(OriginProtocol::HTTPS),
_ => None,
}
}
}
impl rustc_serialize::Encodable for OriginProtocol {
fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(*self as u8).encode(s)
@@ -207,7 +277,7 @@ impl de::Deserialize for OriginProtocol {
}
}
#[derive(Copy, Debug, PartialEq, FromPrimitive)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum ZonePlan {
ZONEPLAN_UNKNOWN,
FREE,
@@ -216,6 +286,23 @@ enum ZonePlan {
ENT,
}
impl FromPrimitive for ZonePlan {
fn from_i64(i: i64) -> Option<ZonePlan> {
FromPrimitive::from_u64(i as u64)
}
fn from_u64(n: u64) -> Option<ZonePlan> {
match n {
0 => Some(ZonePlan::ZONEPLAN_UNKNOWN),
1 => Some(ZonePlan::FREE),
2 => Some(ZonePlan::PRO),
3 => Some(ZonePlan::BIZ),
4 => Some(ZonePlan::ENT),
_ => None,
}
}
}
impl rustc_serialize::Encodable for ZonePlan {
fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(*self as u8).encode(s)
@@ -249,7 +336,7 @@ impl de::Deserialize for ZonePlan {
}
}
#[derive(Copy, Debug, PartialEq, FromPrimitive)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum Country {
UNKNOWN,
A1,
@@ -509,6 +596,274 @@ enum Country {
ZW,
}
impl FromPrimitive for Country {
fn from_i64(i: i64) -> Option<Country> {
FromPrimitive::from_u64(i as u64)
}
fn from_u64(n: u64) -> Option<Country> {
match n {
0 => Some(Country::UNKNOWN),
1 => Some(Country::A1),
2 => Some(Country::A2),
3 => Some(Country::O1),
4 => Some(Country::AD),
5 => Some(Country::AE),
6 => Some(Country::AF),
7 => Some(Country::AG),
8 => Some(Country::AI),
9 => Some(Country::AL),
10 => Some(Country::AM),
11 => Some(Country::AO),
12 => Some(Country::AP),
13 => Some(Country::AQ),
14 => Some(Country::AR),
15 => Some(Country::AS),
16 => Some(Country::AT),
17 => Some(Country::AU),
18 => Some(Country::AW),
19 => Some(Country::AX),
20 => Some(Country::AZ),
21 => Some(Country::BA),
22 => Some(Country::BB),
23 => Some(Country::BD),
24 => Some(Country::BE),
25 => Some(Country::BF),
26 => Some(Country::BG),
27 => Some(Country::BH),
28 => Some(Country::BI),
29 => Some(Country::BJ),
30 => Some(Country::BL),
31 => Some(Country::BM),
32 => Some(Country::BN),
33 => Some(Country::BO),
34 => Some(Country::BQ),
35 => Some(Country::BR),
36 => Some(Country::BS),
37 => Some(Country::BT),
38 => Some(Country::BV),
39 => Some(Country::BW),
40 => Some(Country::BY),
41 => Some(Country::BZ),
42 => Some(Country::CA),
43 => Some(Country::CC),
44 => Some(Country::CD),
45 => Some(Country::CF),
46 => Some(Country::CG),
47 => Some(Country::CH),
48 => Some(Country::CI),
49 => Some(Country::CK),
50 => Some(Country::CL),
51 => Some(Country::CM),
52 => Some(Country::CN),
53 => Some(Country::CO),
54 => Some(Country::CR),
55 => Some(Country::CU),
56 => Some(Country::CV),
57 => Some(Country::CW),
58 => Some(Country::CX),
59 => Some(Country::CY),
60 => Some(Country::CZ),
61 => Some(Country::DE),
62 => Some(Country::DJ),
63 => Some(Country::DK),
64 => Some(Country::DM),
65 => Some(Country::DO),
66 => Some(Country::DZ),
67 => Some(Country::EC),
68 => Some(Country::EE),
69 => Some(Country::EG),
70 => Some(Country::EH),
71 => Some(Country::ER),
72 => Some(Country::ES),
73 => Some(Country::ET),
74 => Some(Country::EU),
75 => Some(Country::FI),
76 => Some(Country::FJ),
77 => Some(Country::FK),
78 => Some(Country::FM),
79 => Some(Country::FO),
80 => Some(Country::FR),
81 => Some(Country::GA),
82 => Some(Country::GB),
83 => Some(Country::GD),
84 => Some(Country::GE),
85 => Some(Country::GF),
86 => Some(Country::GG),
87 => Some(Country::GH),
88 => Some(Country::GI),
89 => Some(Country::GL),
90 => Some(Country::GM),
91 => Some(Country::GN),
92 => Some(Country::GP),
93 => Some(Country::GQ),
94 => Some(Country::GR),
95 => Some(Country::GS),
96 => Some(Country::GT),
97 => Some(Country::GU),
98 => Some(Country::GW),
99 => Some(Country::GY),
100 => Some(Country::HK),
101 => Some(Country::HM),
102 => Some(Country::HN),
103 => Some(Country::HR),
104 => Some(Country::HT),
105 => Some(Country::HU),
106 => Some(Country::ID),
107 => Some(Country::IE),
108 => Some(Country::IL),
109 => Some(Country::IM),
110 => Some(Country::IN),
111 => Some(Country::IO),
112 => Some(Country::IQ),
113 => Some(Country::IR),
114 => Some(Country::IS),
115 => Some(Country::IT),
116 => Some(Country::JE),
117 => Some(Country::JM),
118 => Some(Country::JO),
119 => Some(Country::JP),
120 => Some(Country::KE),
121 => Some(Country::KG),
122 => Some(Country::KH),
123 => Some(Country::KI),
124 => Some(Country::KM),
125 => Some(Country::KN),
126 => Some(Country::KP),
127 => Some(Country::KR),
128 => Some(Country::KW),
129 => Some(Country::KY),
130 => Some(Country::KZ),
131 => Some(Country::LA),
132 => Some(Country::LB),
133 => Some(Country::LC),
134 => Some(Country::LI),
135 => Some(Country::LK),
136 => Some(Country::LR),
137 => Some(Country::LS),
138 => Some(Country::LT),
139 => Some(Country::LU),
140 => Some(Country::LV),
141 => Some(Country::LY),
142 => Some(Country::MA),
143 => Some(Country::MC),
144 => Some(Country::MD),
145 => Some(Country::ME),
146 => Some(Country::MF),
147 => Some(Country::MG),
148 => Some(Country::MH),
149 => Some(Country::MK),
150 => Some(Country::ML),
151 => Some(Country::MM),
152 => Some(Country::MN),
153 => Some(Country::MO),
154 => Some(Country::MP),
155 => Some(Country::MQ),
156 => Some(Country::MR),
157 => Some(Country::MS),
158 => Some(Country::MT),
159 => Some(Country::MU),
160 => Some(Country::MV),
161 => Some(Country::MW),
162 => Some(Country::MX),
163 => Some(Country::MY),
164 => Some(Country::MZ),
165 => Some(Country::NA),
166 => Some(Country::NC),
167 => Some(Country::NE),
168 => Some(Country::NF),
169 => Some(Country::NG),
170 => Some(Country::NI),
171 => Some(Country::NL),
172 => Some(Country::NO),
173 => Some(Country::NP),
174 => Some(Country::NR),
175 => Some(Country::NU),
176 => Some(Country::NZ),
177 => Some(Country::OM),
178 => Some(Country::PA),
179 => Some(Country::PE),
180 => Some(Country::PF),
181 => Some(Country::PG),
182 => Some(Country::PH),
183 => Some(Country::PK),
184 => Some(Country::PL),
185 => Some(Country::PM),
186 => Some(Country::PN),
187 => Some(Country::PR),
188 => Some(Country::PS),
189 => Some(Country::PT),
190 => Some(Country::PW),
191 => Some(Country::PY),
192 => Some(Country::QA),
193 => Some(Country::RE),
194 => Some(Country::RO),
195 => Some(Country::RS),
196 => Some(Country::RU),
197 => Some(Country::RW),
198 => Some(Country::SA),
199 => Some(Country::SB),
200 => Some(Country::SC),
201 => Some(Country::SD),
202 => Some(Country::SE),
203 => Some(Country::SG),
204 => Some(Country::SH),
205 => Some(Country::SI),
206 => Some(Country::SJ),
207 => Some(Country::SK),
208 => Some(Country::SL),
209 => Some(Country::SM),
210 => Some(Country::SN),
211 => Some(Country::SO),
212 => Some(Country::SR),
213 => Some(Country::SS),
214 => Some(Country::ST),
215 => Some(Country::SV),
216 => Some(Country::SX),
217 => Some(Country::SY),
218 => Some(Country::SZ),
219 => Some(Country::TC),
220 => Some(Country::TD),
221 => Some(Country::TF),
222 => Some(Country::TG),
223 => Some(Country::TH),
224 => Some(Country::TJ),
225 => Some(Country::TK),
226 => Some(Country::TL),
227 => Some(Country::TM),
228 => Some(Country::TN),
229 => Some(Country::TO),
230 => Some(Country::TR),
231 => Some(Country::TT),
232 => Some(Country::TV),
233 => Some(Country::TW),
234 => Some(Country::TZ),
235 => Some(Country::UA),
236 => Some(Country::UG),
237 => Some(Country::UM),
238 => Some(Country::US),
239 => Some(Country::UY),
240 => Some(Country::UZ),
241 => Some(Country::VA),
242 => Some(Country::VC),
243 => Some(Country::VE),
244 => Some(Country::VG),
245 => Some(Country::VI),
246 => Some(Country::VN),
247 => Some(Country::VU),
248 => Some(Country::WF),
249 => Some(Country::WS),
250 => Some(Country::XX),
251 => Some(Country::YE),
252 => Some(Country::YT),
253 => Some(Country::ZA),
254 => Some(Country::ZM),
255 => Some(Country::ZW),
_ => None,
}
}
}
impl rustc_serialize::Encodable for Country {
fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(*self as u8).encode(s)
@@ -670,8 +1025,8 @@ fn push_all_bytes(dst: &mut Vec<u8>, src: &[u8]) {
dst.set_len(dst_len + src_len);
::std::ptr::copy_nonoverlapping(
dst.as_mut_ptr().offset(dst_len as isize),
src.as_ptr(),
dst.as_mut_ptr().offset(dst_len as isize),
src_len);
}
}
+2
View File
@@ -27,6 +27,8 @@ impl serde::de::Error for Error {
fn end_of_stream_error() -> Error { Error::EndOfStream }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn missing_field_error(_: &'static str) -> Error {
Error::MissingField
}
+2
View File
@@ -45,6 +45,8 @@ impl serde::de::Error for Error {
fn end_of_stream_error() -> Error { Error::EndOfStream }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn missing_field_error(_: &'static str) -> Error {
Error::MissingField
}
+2
View File
@@ -25,6 +25,8 @@ impl serde::de::Error for Error {
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
fn unknown_field_error(_: &str) -> Error { Error::SyntaxError }
fn missing_field_error(_: &'static str) -> Error { Error::SyntaxError }
}
+64
View File
@@ -0,0 +1,64 @@
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
use std::collections::BTreeMap;
use serde::json;
// Creating serializable types with serde is quite simple with `serde_macros`. It implements a
// syntax extension that automatically generates the necessary serde trait implementations.
#[derive(Debug, Serialize, Deserialize)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 5, y: 6 };
// Serializing to JSON is pretty simple by using the `to_string` method:
let serialized_point = json::to_string(&point).unwrap();
println!("{}", serialized_point);
// prints:
//
// {"x":5,"y":6}
// There is also support for pretty printing using `to_string_pretty`:
let serialized_point = json::to_string_pretty(&point).unwrap();
println!("{}", serialized_point);
// prints:
//
// {
// "x":5,
// "y":6
// }
// Values can also be deserialized with the same style using `from_str`:
let deserialized_point: Point = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_point);
// prints:
//
// Point { x: 5, y: 6 }
// `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,
let deserialized_map: BTreeMap<String, i64> = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_map);
// prints:
//
// {"x": 5, "y": 6}
// If you need to accept arbitrary data, you can also deserialize into `json::Value`, which
// can represent all JSON values.
let deserialized_value: json::Value = json::from_str(&serialized_point).unwrap();
println!("{:?}", deserialized_value);
// prints:
//
// {"x":5,"y":6}
}
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_macros"
version = "0.3.0"
version = "0.3.2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
+10 -8
View File
@@ -417,7 +417,7 @@ fn deserialize_variant(
match variant.node.kind {
ast::TupleVariantKind(ref args) if args.is_empty() => {
quote_expr!(cx, {
try!(visitor.visit_value(::serde::de::impls::UnitVisitor));
try!(visitor.visit_unit());
Ok($type_ident::$variant_ident)
})
}
@@ -482,7 +482,7 @@ fn deserialize_tuple_variant(
}
}
visitor.visit_value($visitor_expr)
visitor.visit_seq($visitor_expr)
})
}
@@ -524,7 +524,7 @@ fn deserialize_struct_variant(
}
}
visitor.visit_value($visitor_expr)
visitor.visit_map($visitor_expr)
})
}
@@ -575,7 +575,7 @@ fn deserialize_field_visitor(
{
match value {
$field_arms
_ => Err(::serde::de::Error::syntax_error()),
_ => Err(::serde::de::Error::unknown_field_error(value)),
}
}
}
@@ -596,7 +596,7 @@ fn deserialize_struct_visitor(
let field_visitor = deserialize_field_visitor(
cx,
builder,
field::struct_field_strs(cx, builder, struct_def),
field::struct_field_strs(cx, builder, struct_def, field::Direction::Deserialize),
);
let visit_map_expr = deserialize_map(
@@ -639,9 +639,11 @@ fn deserialize_map(
let extract_values: Vec<P<ast::Stmt>> = field_names.iter()
.zip(struct_def.fields.iter())
.map(|(field_name, field)| {
let name_str = match field.node.kind {
ast::NamedField(name, _) => builder.expr().str(name),
ast::UnnamedField(_) => panic!("struct contains unnamed fields"),
let rename = field::field_rename(field, &field::Direction::Deserialize);
let name_str = match (rename, field.node.kind) {
(Some(rename), _) => builder.expr().build_lit(P(rename.clone())),
(None, ast::NamedField(name, _)) => builder.expr().str(name),
(None, ast::UnnamedField(_)) => panic!("struct contains unnamed fields"),
};
let missing_expr = if field::default_value(field) {
+17 -4
View File
@@ -5,7 +5,19 @@ use syntax::ptr::P;
use aster;
fn field_alias(field: &ast::StructField) -> Option<&ast::Lit> {
pub enum Direction {
Serialize,
Deserialize,
}
pub fn field_rename<'a>(
field: &'a ast::StructField,
direction: &Direction,
) -> Option<&'a ast::Lit> {
let dir_attr = match *direction {
Direction::Serialize => "rename_serialize",
Direction::Deserialize => "rename_deserialize",
};
field.node.attrs.iter()
.find(|sa| {
if let ast::MetaList(ref n, _) = sa.node.value.node {
@@ -19,7 +31,7 @@ fn field_alias(field: &ast::StructField) -> Option<&ast::Lit> {
attr::mark_used(&sa);
vals.iter().fold(None, |v, mi| {
if let ast::MetaNameValue(ref n, ref lit) = mi.node {
if n == &"alias" {
if n == &"rename" || n == &dir_attr {
Some(lit)
} else {
v
@@ -38,11 +50,12 @@ pub fn struct_field_strs(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
struct_def: &ast::StructDef,
direction: Direction,
) -> Vec<P<ast::Expr>> {
struct_def.fields.iter()
.map(|field| {
match field_alias(field) {
Some(alias) => builder.expr().build_lit(P(alias.clone())),
match field_rename(field, &direction) {
Some(rename) => builder.expr().build_lit(P(rename.clone())),
None => {
match field.node.kind {
ast::NamedField(name, _) => {
+2 -2
View File
@@ -13,7 +13,7 @@ use syntax::ptr::P;
use aster;
use field::struct_field_strs;
use field::{Direction, struct_field_strs};
pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
@@ -517,7 +517,7 @@ fn serialize_struct_visitor<I>(
{
let len = struct_def.fields.len();
let key_exprs = struct_field_strs(cx, builder, struct_def);
let key_exprs = struct_field_strs(cx, builder, struct_def, Direction::Serialize);
let arms: Vec<ast::Arm> = key_exprs.iter()
.zip(value_exprs)
+13 -9
View File
@@ -1,3 +1,5 @@
//! Helper module to enable serializing bytes more efficiently
use std::ops;
use ser;
@@ -10,10 +12,18 @@ pub struct Bytes<'a> {
bytes: &'a [u8],
}
impl<'a, T> From<T> for Bytes<'a> where T: Into<&'a [u8]> {
fn from(bytes: T) -> Self {
impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self {
Bytes {
bytes: bytes.into(),
bytes: bytes,
}
}
}
impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
fn from(bytes: &'a Vec<u8>) -> Self {
Bytes {
bytes: &bytes,
}
}
}
@@ -87,12 +97,6 @@ impl AsMut<[u8]> for ByteBuf {
}
}
impl Into<Vec<u8>> for ByteBuf {
fn into(self) -> Vec<u8> {
self.bytes
}
}
impl ops::Deref for ByteBuf {
type Target = [u8];
+36 -2
View File
@@ -1,8 +1,11 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecMap};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::Hash;
use std::marker::PhantomData;
use std::num::FromPrimitive;
use std::path;
use std::rc::Rc;
use std::sync::Arc;
use num::FromPrimitive;
use de::{
Deserialize,
@@ -570,6 +573,8 @@ impl<K, V> Deserialize for HashMap<K, V>
///////////////////////////////////////////////////////////////////////////////
// FIXME: `VecMap` is unstable.
/*
pub struct VecMapVisitor<V> {
marker: PhantomData<VecMap<V>>,
}
@@ -621,6 +626,7 @@ impl<V> Deserialize for VecMap<V>
deserializer.visit(VecMapVisitor::new())
}
}
*/
///////////////////////////////////////////////////////////////////////////////
@@ -650,3 +656,31 @@ impl Deserialize for path::PathBuf {
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T: Deserialize> Deserialize for Box<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Box<T>, D::Error>
where D: Deserializer,
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Box::new(val))
}
}
impl<T: Deserialize> Deserialize for Arc<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Arc<T>, D::Error>
where D: Deserializer,
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Arc::new(val))
}
}
impl<T: Deserialize> Deserialize for Rc<T> {
fn deserialize<D>(deserializer: &mut D) -> Result<Rc<T>, D::Error>
where D: Deserializer,
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Rc::new(val))
}
}
+42 -10
View File
@@ -1,4 +1,4 @@
use std::str;
//! Generic deserialization framework.
pub mod impls;
pub mod value;
@@ -10,7 +10,9 @@ pub trait Error {
fn end_of_stream_error() -> Self;
fn missing_field_error(&'static str) -> Self;
fn unknown_field_error(field: &str) -> Self;
fn missing_field_error(field: &'static str) -> Self;
}
///////////////////////////////////////////////////////////////////////////////
@@ -200,10 +202,9 @@ pub trait Visitor {
fn visit_char<E>(&mut self, v: char) -> Result<Self::Value, E>
where E: Error,
{
// The unwraps in here should be safe.
let mut s = &mut [0; 4];
let len = v.encode_utf8(s).unwrap();
self.visit_str(str::from_utf8(&s[..len]).unwrap())
// FIXME: this allocation is required in order to be compatible with stable rust, which
// doesn't support encoding a `char` into a stack buffer.
self.visit_string(v.to_string())
}
fn visit_str<E>(&mut self, _v: &str) -> Result<Self::Value, E>
@@ -383,6 +384,8 @@ impl<'a, V_> MapVisitor for &'a mut V_ where V_: MapVisitor {
///////////////////////////////////////////////////////////////////////////////
/// `EnumVisitor` is a visitor that is created by the `Deserialize` and passed to the
/// `Deserializer` in order to deserialize enums.
pub trait EnumVisitor {
type Value;
@@ -392,14 +395,33 @@ pub trait EnumVisitor {
///////////////////////////////////////////////////////////////////////////////
/// `VariantVisitor` is a visitor that is created by the `Deserializer` and passed to the
/// `Deserialize` in order to deserialize a specific enum variant.
pub trait VariantVisitor {
type Error: Error;
/// `visit_variant` is called to identify which variant to deserialize.
fn visit_variant<V>(&mut self) -> Result<V, Self::Error>
where V: Deserialize;
fn visit_value<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// `visit_unit` is called when deserializing a variant with no values.
fn visit_unit(&mut self) -> Result<(), Self::Error> {
Err(Error::syntax_error())
}
/// `visit_seq` is called when deserializing a tuple-like variant.
fn visit_seq<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::syntax_error())
}
/// `visit_map` is called when deserializing a struct-like variant.
fn visit_map<V>(&mut self, _visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor
{
Err(Error::syntax_error())
}
}
impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
@@ -411,10 +433,20 @@ impl<'a, T> VariantVisitor for &'a mut T where T: VariantVisitor {
(**self).visit_variant()
}
fn visit_value<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
fn visit_unit(&mut self) -> Result<(), T::Error> {
(**self).visit_unit()
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
where V: Visitor,
{
(**self).visit_value(visitor)
(**self).visit_seq(visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, T::Error>
where V: Visitor,
{
(**self).visit_map(visitor)
}
}
+19 -21
View File
@@ -18,12 +18,14 @@ use de;
pub enum Error {
SyntaxError,
EndOfStreamError,
UnknownFieldError(String),
MissingFieldError(&'static str),
}
impl de::Error for Error {
fn syntax_error() -> Self { Error::SyntaxError }
fn end_of_stream_error() -> Self { Error::EndOfStreamError }
fn unknown_field_error(field: &str) -> Self { Error::UnknownFieldError(field.to_string()) }
fn missing_field_error(field: &'static str) -> Self { Error::MissingFieldError(field) }
}
@@ -32,7 +34,7 @@ impl de::Error for Error {
pub trait ValueDeserializer {
type Deserializer: de::Deserializer<Error=Error>;
fn deserializer(self) -> Self::Deserializer;
fn into_deserializer(self) -> Self::Deserializer;
}
///////////////////////////////////////////////////////////////////////////////
@@ -40,7 +42,7 @@ pub trait ValueDeserializer {
impl ValueDeserializer for () {
type Deserializer = UnitDeserializer;
fn deserializer(self) -> UnitDeserializer {
fn into_deserializer(self) -> UnitDeserializer {
UnitDeserializer
}
}
@@ -73,7 +75,7 @@ macro_rules! primitive_deserializer {
impl ValueDeserializer for $ty {
type Deserializer = $name;
fn deserializer(self) -> $name {
fn into_deserializer(self) -> $name {
$name(Some(self))
}
}
@@ -116,7 +118,7 @@ pub struct StrDeserializer<'a>(Option<&'a str>);
impl<'a> ValueDeserializer for &'a str {
type Deserializer = StrDeserializer<'a>;
fn deserializer(self) -> StrDeserializer<'a> {
fn into_deserializer(self) -> StrDeserializer<'a> {
StrDeserializer(Some(self))
}
}
@@ -149,10 +151,8 @@ impl<'a> de::VariantVisitor for StrDeserializer<'a> {
de::Deserialize::deserialize(self)
}
fn visit_value<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_unit()
fn visit_unit(&mut self) -> Result<(), Error> {
Ok(())
}
}
@@ -164,7 +164,7 @@ pub struct StringDeserializer(Option<String>);
impl ValueDeserializer for String {
type Deserializer = StringDeserializer;
fn deserializer(self) -> StringDeserializer {
fn into_deserializer(self) -> StringDeserializer {
StringDeserializer(Some(self))
}
}
@@ -197,10 +197,8 @@ impl<'a> de::VariantVisitor for StringDeserializer {
de::Deserialize::deserialize(self)
}
fn visit_value<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
visitor.visit_unit()
fn visit_unit(&mut self) -> Result<(), Error> {
Ok(())
}
}
@@ -245,7 +243,7 @@ impl<I, T> de::SeqVisitor for SeqDeserializer<I>
match self.iter.next() {
Some(value) => {
self.len -= 1;
let mut de = value.deserializer();
let mut de = value.into_deserializer();
Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
}
None => Ok(None),
@@ -272,7 +270,7 @@ impl<T> ValueDeserializer for Vec<T>
{
type Deserializer = SeqDeserializer<vec::IntoIter<T>>;
fn deserializer(self) -> SeqDeserializer<vec::IntoIter<T>> {
fn into_deserializer(self) -> SeqDeserializer<vec::IntoIter<T>> {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
@@ -283,7 +281,7 @@ impl<T> ValueDeserializer for BTreeSet<T>
{
type Deserializer = SeqDeserializer<btree_set::IntoIter<T>>;
fn deserializer(self) -> SeqDeserializer<btree_set::IntoIter<T>> {
fn into_deserializer(self) -> SeqDeserializer<btree_set::IntoIter<T>> {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
@@ -294,7 +292,7 @@ impl<T> ValueDeserializer for HashSet<T>
{
type Deserializer = SeqDeserializer<hash_set::IntoIter<T>>;
fn deserializer(self) -> SeqDeserializer<hash_set::IntoIter<T>> {
fn into_deserializer(self) -> SeqDeserializer<hash_set::IntoIter<T>> {
let len = self.len();
SeqDeserializer::new(self.into_iter(), len)
}
@@ -354,7 +352,7 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
Some((key, value)) => {
self.len -= 1;
self.value = Some(value);
let mut de = key.deserializer();
let mut de = key.into_deserializer();
Ok(Some(try!(de::Deserialize::deserialize(&mut de))))
}
None => Ok(None),
@@ -366,7 +364,7 @@ impl<I, K, V> de::MapVisitor for MapDeserializer<I, K, V>
{
match self.value.take() {
Some(value) => {
let mut de = value.deserializer();
let mut de = value.into_deserializer();
de::Deserialize::deserialize(&mut de)
}
None => Err(de::Error::syntax_error())
@@ -394,7 +392,7 @@ impl<K, V> ValueDeserializer for BTreeMap<K, V>
{
type Deserializer = MapDeserializer<btree_map::IntoIter<K, V>, K, V>;
fn deserializer(self) -> MapDeserializer<btree_map::IntoIter<K, V>, K, V> {
fn into_deserializer(self) -> MapDeserializer<btree_map::IntoIter<K, V>, K, V> {
let len = self.len();
MapDeserializer::new(self.into_iter(), len)
}
@@ -406,7 +404,7 @@ impl<K, V> ValueDeserializer for HashMap<K, V>
{
type Deserializer = MapDeserializer<hash_map::IntoIter<K, V>, K, V>;
fn deserializer(self) -> MapDeserializer<hash_map::IntoIter<K, V>, K, V> {
fn into_deserializer(self) -> MapDeserializer<hash_map::IntoIter<K, V>, K, V> {
let len = self.len();
MapDeserializer::new(self.into_iter(), len)
}
+51
View File
@@ -0,0 +1,51 @@
use std::io;
pub struct LineColIterator<Iter: Iterator<Item=io::Result<u8>>> {
iter: Iter,
line: usize,
col: usize,
}
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
pub fn new(iter: Iter) -> LineColIterator<Iter> {
LineColIterator {
iter: iter,
line: 1,
col: 0,
}
}
/// Report the current line inside the iterator.
pub fn line(&self) -> usize { self.line }
/// Report the current column inside the iterator.
pub fn col(&self) -> usize { self.col }
/// Gets a reference to the underlying iterator.
pub fn get_ref(&self) -> &Iter { &self.iter }
/// Gets a mutable reference to the underlying iterator.
pub fn get_mut(&self) -> &Iter { &self.iter }
/// Unwraps this `LineColIterator`, returning the underlying iterator.
pub fn into_inner(self) -> Iter { self.iter }
}
impl<Iter: Iterator<Item=io::Result<u8>>> Iterator for LineColIterator<Iter> {
type Item = io::Result<u8>;
fn next(&mut self) -> Option<io::Result<u8>> {
match self.iter.next() {
None => None,
Some(Ok(b'\n')) => {
self.line += 1;
self.col = 0;
Some(Ok(b'\n'))
},
Some(Ok(c)) => {
self.col += 1;
Some(Ok(c))
},
Some(Err(e)) => Some(Err(e)),
}
}
}
+50 -39
View File
@@ -1,18 +1,15 @@
use std::char;
use std::io;
use std::num::Float;
use std::str;
use unicode::str::Utf16Item;
use de;
use iter::LineColIterator;
use super::error::{Error, ErrorCode};
pub struct Deserializer<Iter> {
rdr: Iter,
pub struct Deserializer<Iter: Iterator<Item=io::Result<u8>>> {
rdr: LineColIterator<Iter>,
ch: Option<u8>,
line: usize,
col: usize,
str_buf: Vec<u8>,
}
@@ -23,10 +20,8 @@ impl<Iter> Deserializer<Iter>
#[inline]
pub fn new(rdr: Iter) -> Result<Deserializer<Iter>, Error> {
let mut deserializer = Deserializer {
rdr: rdr,
rdr: LineColIterator::new(rdr),
ch: None,
line: 1,
col: 0,
str_buf: Vec::with_capacity(128),
};
@@ -56,13 +51,6 @@ impl<Iter> Deserializer<Iter>
None => None,
};
if self.ch_is(b'\n') {
self.line += 1;
self.col = 1;
} else {
self.col += 1;
}
Ok(())
}
@@ -76,7 +64,7 @@ impl<Iter> Deserializer<Iter>
}
fn error(&mut self, reason: ErrorCode) -> Error {
Error::SyntaxError(reason, self.line, self.col)
Error::SyntaxError(reason, self.rdr.line(), self.rdr.col())
}
fn parse_whitespace(&mut self) -> Result<(), Error> {
@@ -346,35 +334,44 @@ impl<Iter> Deserializer<Iter>
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800 ... 0xDBFF => {
let c1 = try!(self.next_char());
let c2 = try!(self.next_char());
match (c1, c2) {
match (try!(self.next_char()), try!(self.next_char())) {
(Some(b'\\'), Some(b'u')) => (),
_ => {
return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape));
}
}
let buf = &[n1, try!(self.decode_hex_escape())];
match ::unicode::str::utf16_items(buf).next() {
Some(Utf16Item::ScalarValue(c)) => c,
_ => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
let n2 = try!(self.decode_hex_escape());
if n2 < 0xDC00 || n2 > 0xDFFF {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
let n = (((n1 - 0xD800) as u32) << 10 |
(n2 - 0xDC00) as u32) + 0x1_0000;
match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
}
}
n => match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
n => {
match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
}
}
}
};
let buf = &mut [0; 4];
let len = c.encode_utf8(buf).unwrap_or(0);
self.str_buf.extend(buf[..len].iter().map(|b| *b));
// FIXME: this allocation is required in order to be compatible with stable
// rust, which doesn't support encoding a `char` into a stack buffer.
let buf = c.to_string();
self.str_buf.extend(buf.bytes());
}
_ => {
return Err(self.error(ErrorCode::InvalidEscape));
@@ -470,12 +467,12 @@ impl<Iter> de::Deserializer for Deserializer<Iter>
}
}
struct SeqVisitor<'a, Iter: 'a> {
struct SeqVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
de: &'a mut Deserializer<Iter>,
first: bool,
}
impl<'a, Iter> SeqVisitor<'a, Iter> {
impl<'a, Iter: Iterator<Item=io::Result<u8>>> SeqVisitor<'a, Iter> {
fn new(de: &'a mut Deserializer<Iter>) -> Self {
SeqVisitor {
de: de,
@@ -527,12 +524,12 @@ impl<'a, Iter> de::SeqVisitor for SeqVisitor<'a, Iter>
}
}
struct MapVisitor<'a, Iter: 'a> {
struct MapVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
de: &'a mut Deserializer<Iter>,
first: bool,
}
impl<'a, Iter> MapVisitor<'a, Iter> {
impl<'a, Iter: Iterator<Item=io::Result<u8>>> MapVisitor<'a, Iter> {
fn new(de: &'a mut Deserializer<Iter>) -> Self {
MapVisitor {
de: de,
@@ -603,7 +600,7 @@ impl<'a, Iter> de::MapVisitor for MapVisitor<'a, Iter>
fn missing_field<V>(&mut self, _field: &'static str) -> Result<V, Error>
where V: de::Deserialize,
{
let mut de = de::value::ValueDeserializer::deserializer(());
let mut de = de::value::ValueDeserializer::into_deserializer(());
Ok(try!(de::Deserialize::deserialize(&mut de)))
}
}
@@ -619,7 +616,21 @@ impl<Iter> de::VariantVisitor for Deserializer<Iter>
de::Deserialize::deserialize(self)
}
fn visit_value<V>(&mut self, visitor: V) -> Result<V::Value, Error>
fn visit_unit(&mut self) -> Result<(), Error> {
try!(self.parse_object_colon());
de::Deserialize::deserialize(self)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_object_colon());
de::Deserializer::visit(self, visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
try!(self.parse_object_colon());
+15 -6
View File
@@ -5,7 +5,7 @@ use std::io;
use de;
/// The errors that can arise while parsing a JSON stream.
#[derive(Copy, Clone, PartialEq)]
#[derive(Clone, PartialEq)]
pub enum ErrorCode {
EOFWhileParsingList,
EOFWhileParsingObject,
@@ -28,6 +28,7 @@ pub enum ErrorCode {
InvalidUnicodeCodePoint,
KeyMustBeAString,
LoneLeadingSurrogateInHexEscape,
UnknownField(String),
MissingField(&'static str),
NotFourDigit,
NotUtf8,
@@ -65,6 +66,7 @@ impl fmt::Debug for ErrorCode {
ErrorCode::InvalidUnicodeCodePoint => "invalid unicode code point".fmt(f),
ErrorCode::KeyMustBeAString => "key must be a string".fmt(f),
ErrorCode::LoneLeadingSurrogateInHexEscape => "lone leading surrogate in hex escape".fmt(f),
ErrorCode::UnknownField(ref field) => write!(f, "unknown field \"{}\"", field),
ErrorCode::MissingField(ref field) => write!(f, "missing field \"{}\"", field),
ErrorCode::NotFourDigit => "invalid \\u escape (not four digits)".fmt(f),
ErrorCode::NotUtf8 => "contents not utf-8".fmt(f),
@@ -77,7 +79,7 @@ impl fmt::Debug for ErrorCode {
}
}
#[derive(Clone, PartialEq, Debug)]
#[derive(Debug)]
pub enum Error {
/// msg, line, col
SyntaxError(ErrorCode, usize, usize),
@@ -139,14 +141,14 @@ impl fmt::Display for Error {
}
}
impl error::FromError<io::Error> for Error {
fn from_error(error: io::Error) -> Error {
impl From<io::Error> for Error {
fn from(error: io::Error) -> Error {
Error::IoError(error)
}
}
impl error::FromError<de::value::Error> for Error {
fn from_error(error: de::value::Error) -> Error {
impl From<de::value::Error> for Error {
fn from(error: de::value::Error) -> Error {
match error {
de::value::Error::SyntaxError => {
de::Error::syntax_error()
@@ -154,6 +156,9 @@ impl error::FromError<de::value::Error> for Error {
de::value::Error::EndOfStreamError => {
de::Error::end_of_stream_error()
}
de::value::Error::UnknownFieldError(field) => {
Error::SyntaxError(ErrorCode::UnknownField(field), 0, 0)
}
de::value::Error::MissingFieldError(field) => {
de::Error::missing_field_error(field)
}
@@ -170,6 +175,10 @@ impl de::Error for Error {
Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 0, 0)
}
fn unknown_field_error(field: &str) -> Error {
Error::SyntaxError(ErrorCode::UnknownField(field.to_string()), 0, 0)
}
fn missing_field_error(field: &'static str) -> Error {
Error::MissingFieldError(field)
}
+4 -41
View File
@@ -50,53 +50,16 @@
//!
//! 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
//! functions described above. You can also use the `json::Encoder` object, which implements the
//! `Encoder` trait.
//! functions described above. You can also use the `json::Serializer` object, which implements the
//! `Serializer` trait.
//!
//! # Examples of use
//!
//! ## Using Autoserialization
//!
//! Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the
//! serialization API, using the derived serialization code.
//!
//! ```rust
//! // Required to use the annotations.
//! #![feature(custom_derive, plugin)]
//! #![plugin(serde_macros)]
//!
//! extern crate serde;
//!
//! use serde::json;
//!
//! // Automatically generate `Serialize` and `Deserialize` trait implementations
//! #[derive(Serialize, Deserialize)]
//! pub struct TestStruct {
//! data_int: u8,
//! data_str: String,
//! data_vector: Vec<u8>,
//! }
//!
//! fn main() {
//! let object = TestStruct {
//! data_int: 1,
//! data_str: "homura".to_string(),
//! data_vector: vec![2,3,4,5],
//! };
//!
//! // Serialize using `json::to_string`
//! let serialized = json::to_string(&object).unwrap();
//!
//! // Deserialize using `json::from_str`
//! let deserialized: TestStruct = json::from_str(&serialized).unwrap();
//! }
//! ```
//!
//! ## Parsing a `str` to `Value` and reading the result
//!
//! ```rust
//! #![feature(custom_derive, plugin)]
//! #![plugin(serde_macros)]
//! //#![feature(custom_derive, plugin)]
//! //#![plugin(serde_macros)]
//!
//! extern crate serde;
//!
+20 -7
View File
@@ -1,6 +1,5 @@
use std::{f32, f64};
use std::io;
use std::num::{Float, FpCategory};
use std::num::FpCategory;
use std::string::FromUtf8Error;
use ser;
@@ -386,9 +385,9 @@ pub fn escape_str<W>(wr: &mut W, value: &str) -> io::Result<()>
fn escape_char<W>(wr: &mut W, value: char) -> io::Result<()>
where W: io::Write
{
let buf = &mut [0; 4];
value.encode_utf8(buf);
escape_bytes(wr, buf)
// FIXME: this allocation is required in order to be compatible with stable
// rust, which doesn't support encoding a `char` into a stack buffer.
escape_bytes(wr, value.to_string().as_bytes())
}
fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> io::Result<()>
@@ -396,7 +395,14 @@ fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> io::Result<()>
{
match value.classify() {
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
_ => wr.write_all(f32::to_str_digits(value, 6).as_bytes()),
_ => {
let s = value.to_string();
try!(wr.write_all(s.as_bytes()));
if !s.contains('.') {
try!(wr.write_all(b".0"))
}
Ok(())
}
}
}
@@ -405,7 +411,14 @@ fn fmt_f64_or_null<W>(wr: &mut W, value: f64) -> io::Result<()>
{
match value.classify() {
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
_ => wr.write_all(f64::to_str_digits(value, 6).as_bytes()),
_ => {
let s = value.to_string();
try!(wr.write_all(s.as_bytes()));
if !s.contains('.') {
try!(wr.write_all(b".0"))
}
Ok(())
}
}
}
+29 -7
View File
@@ -1,10 +1,11 @@
use std::collections::{BTreeMap, btree_map};
use std::fmt;
use std::io;
use std::num;
use std::str;
use std::vec;
use num::NumCast;
use de;
use ser;
use super::error::Error;
@@ -165,7 +166,7 @@ impl Value {
pub fn as_i64(&self) -> Option<i64> {
match *self {
Value::I64(n) => Some(n),
Value::U64(n) => num::cast(n),
Value::U64(n) => NumCast::from(n),
_ => None
}
}
@@ -174,7 +175,7 @@ impl Value {
/// Returns None otherwise.
pub fn as_u64(&self) -> Option<u64> {
match *self {
Value::I64(n) => num::cast(n),
Value::I64(n) => NumCast::from(n),
Value::U64(n) => Some(n),
_ => None
}
@@ -184,8 +185,8 @@ impl Value {
/// Returns None otherwise.
pub fn as_f64(&self) -> Option<f64> {
match *self {
Value::I64(n) => num::cast(n),
Value::U64(n) => num::cast(n),
Value::I64(n) => NumCast::from(n),
Value::U64(n) => NumCast::from(n),
Value::F64(n) => Some(n),
_ => None
}
@@ -737,7 +738,18 @@ impl<'a> de::VariantVisitor for SeqDeserializer<'a> {
de::Deserialize::deserialize(self.de)
}
fn visit_value<V>(&mut self, visitor: V) -> Result<V::Value, Error>
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)
@@ -836,7 +848,17 @@ impl<'a> de::VariantVisitor for MapDeserializer<'a> {
de::Deserialize::deserialize(self.de)
}
fn visit_value<V>(&mut self, visitor: V) -> Result<V::Value, Error>
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)
+13 -5
View File
@@ -1,11 +1,19 @@
#![feature(collections, convert, core, std_misc, unicode)]
//! Serde Serialization Framework
//!
//! Serde is a powerful framework that enables serialization libraries to generically serialize
//! Rust data structures without the overhead of runtime type information. In many situations, the
//! handshake protocol between serializers and serializees can be completely optimized away,
//! leaving serde to perform roughly the same speed as a hand written serializer for a specific
//! type.
#![doc(html_root_url="http://erickt.github.io/rust-serde")]
extern crate unicode;
extern crate num;
pub use ser::{Serialize, Serializer};
pub use de::{Deserialize, Deserializer, Error};
pub mod ser;
pub mod de;
pub mod json;
pub mod bytes;
pub mod de;
pub mod iter;
pub mod json;
pub mod ser;
+11 -11
View File
@@ -1,5 +1,4 @@
use std::collections::hash_state::HashState;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecMap};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::Hash;
use std::path;
use std::rc::Rc;
@@ -44,12 +43,12 @@ impl_visit!(char, visit_char);
///////////////////////////////////////////////////////////////////////////////
impl<'a> Serialize for &'a str {
impl Serialize for str {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_str(*self)
serializer.visit_str(self)
}
}
@@ -151,9 +150,8 @@ impl<T> Serialize for BTreeSet<T>
}
}
impl<T, H> Serialize for HashSet<T, H>
impl<T> Serialize for HashSet<T>
where T: Serialize + Eq + Hash,
H: HashState,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -400,10 +398,9 @@ impl<K, V> Serialize for BTreeMap<K, V>
}
}
impl<K, V, H> Serialize for HashMap<K, V, H>
impl<K, V> Serialize for HashMap<K, V>
where K: Serialize + Eq + Hash,
V: Serialize,
H: HashState,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
@@ -413,6 +410,8 @@ impl<K, V, H> Serialize for HashMap<K, V, H>
}
}
// FIXME: `VecMap` is unstable.
/*
impl<V> Serialize for VecMap<V>
where V: Serialize,
{
@@ -423,10 +422,11 @@ impl<V> Serialize for VecMap<V>
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
*/
///////////////////////////////////////////////////////////////////////////////
impl<'a, T> Serialize for &'a T where T: Serialize {
impl<'a, T: ?Sized> Serialize for &'a T where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
@@ -435,7 +435,7 @@ impl<'a, T> Serialize for &'a T where T: Serialize {
}
}
impl<'a, T> Serialize for &'a mut T where T: Serialize {
impl<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
@@ -444,7 +444,7 @@ impl<'a, T> Serialize for &'a mut T where T: Serialize {
}
}
impl<T> Serialize for Box<T> where T: Serialize {
impl<T: ?Sized> Serialize for Box<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
+4 -5
View File
@@ -1,4 +1,4 @@
use std::str;
//! Generic serialization framework.
pub mod impls;
@@ -95,10 +95,9 @@ pub trait Serializer {
/// single character.
#[inline]
fn visit_char(&mut self, v: char) -> Result<(), Self::Error> {
// The unwraps in here should be safe.
let mut s = &mut [0; 4];
let len = v.encode_utf8(s).unwrap();
self.visit_str(str::from_utf8(&s[..len]).unwrap())
// FIXME: this allocation is required in order to be compatible with stable rust, which
// doesn't support encoding a `char` into a stack buffer.
self.visit_str(&v.to_string())
}
/// `visit_str` serializes a `&str`.
+57
View File
@@ -0,0 +1,57 @@
#![feature(custom_attribute, custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate test;
extern crate serde;
use serde::json;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Default {
a1: i32,
#[serde(default)]
a2: i32,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Rename {
a1: i32,
#[serde(rename="a3")]
a2: i32,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct DirectionRename {
a1: i32,
#[serde(rename_serialize="a3", rename_deserialize="a4")]
a2: i32,
}
#[test]
fn test_default() {
let deserialized_value: Default = json::from_str(&"{\"a1\":1,\"a2\":2}").unwrap();
assert_eq!(deserialized_value, Default { a1: 1, a2: 2 });
let deserialized_value: Default = json::from_str(&"{\"a1\":1}").unwrap();
assert_eq!(deserialized_value, Default { a1: 1, a2: 0 });
}
#[test]
fn test_rename() {
let value = Rename { a1: 1, a2: 2 };
let serialized_value = json::to_string(&value).unwrap();
assert_eq!(serialized_value, "{\"a1\":1,\"a3\":2}");
let deserialized_value: Rename = json::from_str(&serialized_value).unwrap();
assert_eq!(value, deserialized_value);
}
#[test]
fn test_direction_rename() {
let value = DirectionRename { a1: 1, a2: 2 };
let serialized_value = json::to_string(&value).unwrap();
assert_eq!(serialized_value, "{\"a1\":1,\"a3\":2}");
let deserialized_value = json::from_str("{\"a1\":1,\"a4\":2}").unwrap();
assert_eq!(value, deserialized_value);
}
+7 -3
View File
@@ -1,4 +1,4 @@
#![feature(convert, custom_derive, plugin, test)]
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate test;
@@ -18,6 +18,8 @@ impl serde::de::Error for Error {
fn end_of_stream_error() -> Error { Error }
fn unknown_field_error(_field: &str) -> Error { Error }
fn missing_field_error(_field: &'static str) -> Error { Error }
}
@@ -192,10 +194,12 @@ fn test_byte_buf_ser_bytes() {
#[test]
fn test_byte_buf_de_json() {
let bytes = ByteBuf::new();
assert_eq!(json::from_str("[]").unwrap(), bytes);
let v: ByteBuf = json::from_str("[]").unwrap();
assert_eq!(v, bytes);
let bytes = ByteBuf::from(vec![1, 2, 3]);
assert_eq!(json::from_str("[1, 2, 3]").unwrap(), bytes);
let v: ByteBuf = json::from_str("[1, 2, 3]").unwrap();
assert_eq!(v, bytes);
}
#[test]
+18 -3
View File
@@ -59,10 +59,11 @@ impl<'a> TokenDeserializer {
}
}
#[derive(Copy, PartialEq, Debug)]
#[derive(Clone, PartialEq, Debug)]
enum Error {
SyntaxError,
EndOfStreamError,
UnknownFieldError(String),
MissingFieldError(&'static str),
InvalidName(&'static str),
}
@@ -72,6 +73,10 @@ impl de::Error for Error {
fn end_of_stream_error() -> Error { Error::EndOfStreamError }
fn unknown_field_error(field: &str) -> Error {
Error::UnknownFieldError(field.to_string())
}
fn missing_field_error(field: &'static str) -> Error {
Error::MissingFieldError(field)
}
@@ -315,7 +320,17 @@ impl<'a> de::VariantVisitor for TokenDeserializerVariantVisitor<'a> {
de::Deserialize::deserialize(self.de)
}
fn visit_value<V>(&mut self, visitor: V) -> Result<V::Value, Error>
fn visit_unit(&mut self) -> Result<(), Error> {
de::Deserialize::deserialize(self.de)
}
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self.de, visitor)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
de::Deserializer::visit(self.de, visitor)
@@ -324,7 +339,7 @@ impl<'a> de::VariantVisitor for TokenDeserializerVariantVisitor<'a> {
//////////////////////////////////////////////////////////////////////////
#[derive(Copy, PartialEq, Debug, Deserialize)]
#[derive(Copy, Clone, PartialEq, Debug, Deserialize)]
struct NamedUnit;
#[derive(PartialEq, Debug, Deserialize)]
+79 -45
View File
@@ -1,4 +1,4 @@
#![feature(custom_derive, plugin, test)]
#![feature(custom_derive, plugin, test, custom_attribute)]
#![plugin(serde_macros)]
extern crate test;
@@ -101,7 +101,7 @@ fn test_write_i64() {
#[test]
fn test_write_f64() {
let tests = &[
(3.0, "3"),
(3.0, "3.0"),
(3.1, "3.1"),
(-1.5, "-1.5"),
(0.5, "0.5"),
@@ -626,23 +626,20 @@ fn test_parse_ok<T>(errors: Vec<(&'static str, T)>)
where T: Clone + Debug + PartialEq + ser::Serialize + de::Deserialize,
{
for (s, value) in errors {
let v: Result<T, Error> = from_str(s);
assert_eq!(v, Ok(value.clone()));
let v: T = from_str(s).unwrap();
assert_eq!(v, value.clone());
// Make sure we can deserialize into a `Value`.
let json_value: Result<Value, Error> = from_str(s);
assert_eq!(json_value, Ok(to_value(&value)));
let json_value = json_value.unwrap();
let json_value: Value = from_str(s).unwrap();
assert_eq!(json_value, to_value(&value));
// Make sure we can deserialize from a `Value`.
let v: Result<T, Error> = from_value(json_value.clone());
assert_eq!(v, Ok(value));
let v: T = from_value(json_value.clone()).unwrap();
assert_eq!(v, value);
// Make sure we can round trip back to `Value`.
let json_value2: Result<Value, Error> = from_value(json_value.clone());
assert_eq!(json_value2, Ok(json_value));
let json_value2: Value = from_value(json_value.clone()).unwrap();
assert_eq!(json_value2, json_value);
}
}
@@ -651,16 +648,28 @@ fn test_parse_err<T>(errors: Vec<(&'static str, Error)>)
where T: Debug + PartialEq + de::Deserialize,
{
for (s, err) in errors {
let v: Result<T, Error> = from_str(s);
assert_eq!(v, Err(err));
match (err, from_str::<T>(s).unwrap_err()) {
(
Error::SyntaxError(expected_code, expected_line, expected_col),
Error::SyntaxError(actual_code, actual_line, actual_col),
) => {
assert_eq!(
(expected_code, expected_line, expected_col),
(actual_code, actual_line, actual_col)
)
}
(expected_err, actual_err) => {
panic!("unexpected errors {} != {}", expected_err, actual_err)
}
}
}
}
#[test]
fn test_parse_null() {
test_parse_err::<()>(vec![
("n", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
("nul", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 4)),
("n", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 1)),
("nul", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 3)),
("nulla", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 5)),
]);
@@ -672,9 +681,9 @@ fn test_parse_null() {
#[test]
fn test_parse_bool() {
test_parse_err::<bool>(vec![
("t", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
("t", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 1)),
("truz", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 4)),
("f", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
("f", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 1)),
("faz", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 3)),
("truea", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 5)),
("falsea", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 6)),
@@ -693,11 +702,11 @@ fn test_parse_number_errors() {
test_parse_err::<f64>(vec![
("+", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
(".", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
("-", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
("-", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 1)),
("00", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
("1.", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
("1e", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 4)),
("1.", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
("1e", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
("1a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 2)),
]);
}
@@ -736,8 +745,8 @@ fn test_parse_f64() {
#[test]
fn test_parse_string() {
test_parse_err::<String>(vec![
("\"", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 2)),
("\"lol", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 5)),
("\"", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 1)),
("\"lol", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 4)),
("\"lol\"a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 6)),
]);
@@ -758,10 +767,10 @@ fn test_parse_string() {
#[test]
fn test_parse_list() {
test_parse_err::<Vec<f64>>(vec![
("[", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
("[ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
("[1", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 3)),
("[1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 4)),
("[", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 1)),
("[ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
("[1", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 2)),
("[1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
("[1,]", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 4)),
("[1 2]", Error::SyntaxError(ErrorCode::ExpectedListCommaOrEnd, 1, 4)),
("[]a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 3)),
@@ -810,17 +819,17 @@ fn test_parse_list() {
#[test]
fn test_parse_object() {
test_parse_err::<BTreeMap<String, u32>>(vec![
("{", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
("{ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
("{", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 1)),
("{ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
("{1", Error::SyntaxError(ErrorCode::KeyMustBeAString, 1, 2)),
("{ \"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 6)),
("{\"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 5)),
("{\"a\" ", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 6)),
("{ \"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 5)),
("{\"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 4)),
("{\"a\" ", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 5)),
("{\"a\" 1", Error::SyntaxError(ErrorCode::ExpectedColon, 1, 6)),
("{\"a\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 6)),
("{\"a\":1", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 7)),
("{\"a\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 5)),
("{\"a\":1", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 6)),
("{\"a\":1 1", Error::SyntaxError(ErrorCode::ExpectedObjectCommaOrEnd, 1, 8)),
("{\"a\":1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 8)),
("{\"a\":1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 7)),
("{}a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 3)),
]);
@@ -861,8 +870,8 @@ fn test_parse_object() {
#[test]
fn test_parse_struct() {
test_parse_err::<Outer>(vec![
("5", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 2)),
("\"hello\"", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 8)),
("5", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
("\"hello\"", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 7)),
("{\"inner\": true}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 15)),
]);
@@ -889,11 +898,13 @@ fn test_parse_struct() {
)
]);
let v: Outer = from_str("{}").unwrap();
assert_eq!(
from_str("{}"),
Ok(Outer {
v,
Outer {
inner: vec![],
})
}
);
}
@@ -922,9 +933,9 @@ fn test_parse_option() {
fn test_parse_enum_errors() {
test_parse_err::<Animal>(vec![
("{}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 2)),
("{\"Dog\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 8)),
("{\"Dog\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 7)),
("{\"Dog\":}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 8)),
("{\"unknown\":[]}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 11)),
("{\"unknown\":[]}", Error::SyntaxError(ErrorCode::UnknownField("unknown".to_string()), 1, 11)),
("{\"Dog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 9)),
("{\"Frog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 10)),
("{\"Cat\":[]}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 9)),
@@ -983,7 +994,7 @@ fn test_parse_trailing_whitespace() {
#[test]
fn test_multiline_errors() {
test_parse_err::<BTreeMap<String, String>>(vec![
("{\n \"foo\":\n \"bar\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 3, 8)),
("{\n \"foo\":\n \"bar\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 3, 6)),
]);
}
@@ -1008,3 +1019,26 @@ fn test_missing_field() {
))).unwrap();
assert_eq!(value, Foo { x: Some(5) });
}
#[test]
fn test_missing_renamed_field() {
#[derive(Debug, PartialEq, Deserialize)]
struct Foo {
#[serde(rename_deserialize="y")]
x: Option<u32>,
}
let value: Foo = from_str("{}").unwrap();
assert_eq!(value, Foo { x: None });
let value: Foo = from_str("{\"y\": 5}").unwrap();
assert_eq!(value, Foo { x: Some(5) });
let value: Foo = from_value(Value::Object(treemap!())).unwrap();
assert_eq!(value, Foo { x: None });
let value: Foo = from_value(Value::Object(treemap!(
"y".to_string() => Value::I64(5)
))).unwrap();
assert_eq!(value, Foo { x: Some(5) });
}
+51 -42
View File
@@ -142,10 +142,10 @@ fn test_named_unit() {
Value::Null
);
let v = json::from_str("null").unwrap();
let v: NamedUnit = json::from_str("null").unwrap();
assert_eq!(v, named_unit);
let v = json::from_value(Value::Null).unwrap();
let v: NamedUnit = json::from_value(Value::Null).unwrap();
assert_eq!(v, named_unit);
}
@@ -169,13 +169,15 @@ fn test_ser_named_tuple() {
#[test]
fn test_de_named_tuple() {
let v: DeNamedTuple<i32, i32, i32> = json::from_str("[1,2,3]").unwrap();
assert_eq!(
json::from_str("[1,2,3]").unwrap(),
v,
DeNamedTuple(1, 2, 3)
);
let v: Value = json::from_str("[1,2,3]").unwrap();
assert_eq!(
json::from_str("[1,2,3]").unwrap(),
v,
Value::Array(vec![
Value::U64(1),
Value::U64(2),
@@ -218,19 +220,17 @@ fn test_de_named_map() {
c: 7,
};
assert_eq!(
json::from_str("{\"a\":5,\"b\":6,\"c\":7}").unwrap(),
v
);
let v2: DeNamedMap<i32, i32, i32> = json::from_str(
"{\"a\":5,\"b\":6,\"c\":7}"
).unwrap();
assert_eq!(v, v2);
assert_eq!(
json::from_value(Value::Object(btreemap![
"a".to_string() => Value::U64(5),
"b".to_string() => Value::U64(6),
"c".to_string() => Value::U64(7)
])).unwrap(),
v
);
let v2 = json::from_value(Value::Object(btreemap![
"a".to_string() => Value::U64(5),
"b".to_string() => Value::U64(6),
"c".to_string() => Value::U64(7)
])).unwrap();
assert_eq!(v, v2);
}
#[test]
@@ -336,15 +336,17 @@ fn test_ser_enum_map() {
#[test]
fn test_de_enum_unit() {
let v: DeEnum<_, _, _> = json::from_str("{\"Unit\":[]}").unwrap();
assert_eq!(
json::from_str("{\"Unit\":[]}").unwrap(),
v,
DeEnum::Unit::<u32, u32, u32>
);
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
"Unit".to_string() => Value::Array(vec![]))
)).unwrap();
assert_eq!(
json::from_value(Value::Object(btreemap!(
"Unit".to_string() => Value::Array(vec![]))
)).unwrap(),
v,
DeEnum::Unit::<u32, u32, u32>
);
}
@@ -358,8 +360,9 @@ fn test_de_enum_seq() {
let e = 5;
//let f = 6;
let v: DeEnum<_, _, _> = json::from_str("{\"Seq\":[1,2,3,5]}").unwrap();
assert_eq!(
json::from_str("{\"Seq\":[1,2,3,5]}").unwrap(),
v,
DeEnum::Seq(
a,
b,
@@ -370,17 +373,18 @@ fn test_de_enum_seq() {
)
);
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
"Seq".to_string() => Value::Array(vec![
Value::U64(1),
Value::U64(2),
Value::U64(3),
//Value::U64(4),
Value::U64(5),
//Value::U64(6),
])
))).unwrap();
assert_eq!(
json::from_value(Value::Object(btreemap!(
"Seq".to_string() => Value::Array(vec![
Value::U64(1),
Value::U64(2),
Value::U64(3),
//Value::U64(4),
Value::U64(5),
//Value::U64(6),
])
))).unwrap(),
v,
DeEnum::Seq(
a,
b,
@@ -401,8 +405,11 @@ fn test_de_enum_map() {
let e = 5;
//let f = 6;
let v: DeEnum<_, _, _> = json::from_str(
"{\"Map\":{\"a\":1,\"b\":2,\"c\":3,\"e\":5}}"
).unwrap();
assert_eq!(
json::from_str("{\"Map\":{\"a\":1,\"b\":2,\"c\":3,\"e\":5}}").unwrap(),
v,
DeEnum::Map {
a: a,
b: b,
@@ -413,17 +420,19 @@ fn test_de_enum_map() {
}
);
let v: DeEnum<_, _, _> = json::from_value(Value::Object(btreemap!(
"Map".to_string() => Value::Object(btreemap![
"a".to_string() => Value::U64(1),
"b".to_string() => Value::U64(2),
"c".to_string() => Value::U64(3),
//"d".to_string() => Value::U64(4)
"e".to_string() => Value::U64(5)
//"f".to_string() => Value::U64(6)
])
))).unwrap();
assert_eq!(
json::from_value(Value::Object(btreemap!(
"Map".to_string() => Value::Object(btreemap![
"a".to_string() => Value::U64(1),
"b".to_string() => Value::U64(2),
"c".to_string() => Value::U64(3),
//"d".to_string() => Value::U64(4)
"e".to_string() => Value::U64(5)
//"f".to_string() => Value::U64(6)
])
))).unwrap(),
v,
DeEnum::Map {
a: a,
b: b,