Compare commits

...

75 Commits

Author SHA1 Message Date
Erick Tryzelaar ac758ed3c8 Version bump 2015-07-16 11:28:18 -04:00
Erick Tryzelaar 236d40d73e Add Serializer hooks for sequence elements 2015-07-16 10:51:01 -04:00
Erick Tryzelaar 92029a05c6 Add Deserializer type hints
This allows file formats like bincode, which do not encode it's values
with a type tag, to deserialize values.
2015-07-16 10:50:54 -04:00
Erick Tryzelaar c7b9997dd1 Add all of the stdlib collection deserialization implementations 2015-07-16 10:42:34 -04:00
Erick Tryzelaar 48309bfdd0 Add all of the stdlib collection serialization implementations 2015-07-16 10:00:22 -04:00
Erick Tryzelaar f76d1ab10d Compile serde_macros tests with the nightly features 2015-07-16 10:00:22 -04:00
Erick Tryzelaar 45f552f006 Fix feature flag use for NonZero 2015-07-16 10:00:21 -04:00
Erick Tryzelaar 4d42cfea53 Fix warnings 2015-07-16 09:36:14 -04:00
Erick Tryzelaar 7109e2d379 Fix the tests 2015-07-16 09:35:09 -04:00
Erick Tryzelaar ff214643ce Merge remote-tracking branch 'remotes/origin/master' into nonzero
# Conflicts:
#	serde/src/de/impls.rs
2015-07-16 09:34:45 -04:00
Erick Tryzelaar 04918a52eb Merge pull request #105 from jnicholls/boolvisitor
Make BoolVisitor public so it is documented as being in existence
2015-07-16 07:41:49 -04:00
Erick Tryzelaar 5dd71600f7 Merge pull request #102 from pcwalton/result
Implement serialization for `Result`.
2015-07-16 07:29:28 -04:00
Patrick Walton ea9ed22e3e Implement serialization for NonZero values in nightly. 2015-07-14 12:00:46 -07:00
Jarred Nicholls 1611daf802 Make BoolVisitor public so it is documented as being in existence 2015-07-13 12:13:00 -04:00
Patrick Walton e24f52d3ae Implement serialization for Result.
Servo wants this.
2015-07-10 15:08:59 -07:00
Erick Tryzelaar bcc9e15b05 Merge pull request #94 from cmbrandenburg/master
Fix spelling in README.md
2015-07-01 10:38:13 -07:00
Craig M. Brandenburg af835a2699 Fix spelling in README.md 2015-06-29 07:18:48 -07:00
Erick Tryzelaar 5f2d306f9b Merge pull request #92 from SkylerLipthay/cow-impls
Add impls for Cow
2015-06-21 10:07:00 -07:00
Skyler Lipthay 36fb49b522 Add impls for Cow 2015-06-19 22:50:16 -07:00
Erick Tryzelaar ed5b4d7319 Fix serializing generic enums
This fixes generic enums with variants that don't use all lifetime
and typarams. Closes #88.
2015-06-18 08:45:03 -07:00
Erick Tryzelaar b09c0fc653 Fix an indent typo 2015-06-18 07:49:13 -07:00
Erick Tryzelaar ab3e40ca45 Version bump 2015-06-08 07:12:27 -07:00
Erick Tryzelaar 8f67e9c048 Switch exponent bounds checking back to using powi 2015-06-08 07:07:09 -07:00
Erick Tryzelaar 7dc1a64f03 Merge pull request #80 from ProtectedMode/master
Fix #77, integer overflow when parsing JSON scientific notation number.
2015-06-08 06:57:33 -07:00
Erick Tryzelaar ac3a3e922f Fix compilation with rust nightly (613e57b44) and syntex 0.7.0 2015-06-08 06:55:36 -07:00
Erick Tryzelaar 4e50c56542 Merge pull request #87 from Manishearth/patch-1
Use correct attribute syntax
2015-06-07 20:46:44 -07:00
Manish Goregaokar 26b1ed79c0 !!!!!! 2015-06-06 18:08:33 +05:30
ProtectedMode 2e8ef0f768 Add test for #77, integer overflow when parsing JSON scientific notation number. 2015-05-21 09:59:14 +02:00
Erick Tryzelaar c993414b92 serde_tests tests doesn't need the test crate 2015-05-20 22:57:19 -07:00
Erick Tryzelaar ed6ef4e149 Travis work 2015-05-20 22:44:50 -07:00
Erick Tryzelaar 859cdcc815 Remove unnecessary lifetime 2015-05-20 09:02:38 -07:00
ProtectedMode 745a95b607 Fix #77, integer overflow when parsing JSON scientific notation number. 2015-05-20 16:32:10 +02:00
Erick Tryzelaar 81d617bd93 The README is in a different location 2015-05-18 23:36:46 -07:00
Erick Tryzelaar 3396388222 Remove redundant import 2015-05-18 23:34:17 -07:00
Erick Tryzelaar ff8c3b3d51 Initial support for syntex 2015-05-18 23:34:17 -07:00
Erick Tryzelaar 3d0efd123f Minor cleanup 2015-05-18 22:49:50 -07:00
Erick Tryzelaar 8ca1b9ac3c default_value doesn't need to be public 2015-05-18 22:49:49 -07:00
Erick Tryzelaar 2c24be90d2 Switch to using MultiDecorator 2015-05-18 22:49:49 -07:00
Erick Tryzelaar 482f92af61 Add a single driver for tests and benchmarks 2015-05-18 22:47:36 -07:00
Erick Tryzelaar 24ac61f9f2 Pull codegen into it's own crate 2015-05-18 22:47:35 -07:00
Erick Tryzelaar 426394cd7b Version bump 2015-05-18 22:47:35 -07:00
Erick Tryzelaar 7c3e95a7c7 Ignore all target and Cargo.lock files 2015-05-18 22:47:35 -07:00
Erick Tryzelaar 9dd5f9dc7a Restructure directories to prep for syntex 2015-05-18 22:47:35 -07:00
Erick Tryzelaar e6776ffc37 Protect against json integer overflow
Closes #75
2015-05-18 22:40:29 -07:00
Erick Tryzelaar adae2bd3c5 Merge pull request #72 from borman/bytestrings
Improved support for byte strings
2015-05-18 22:28:37 -07:00
Erick Tryzelaar 14ca260c26 Merge pull request #70 from oli-obk/xml_requirements
changes needed for xml parsing
2015-05-18 22:25:15 -07:00
Erick Tryzelaar 64588f0cb6 Merge pull request #74 from tomprogrammer/array
Add serialization/deserialization for fixed size arrays
2015-05-18 22:21:59 -07:00
Erick Tryzelaar 50cac7f985 Rewrite Value::lookup to not require an allocation 2015-05-18 22:19:30 -07:00
Erick Tryzelaar 5fe85128c2 Merge pull request #76 from blaenk/json-lookup
implement lookup method for json::Value
2015-05-18 21:50:55 -07:00
Jorge Israel Peña bc236bde34 implement lookup method for json::Value 2015-05-17 21:24:00 -07:00
Thomas Bahn 15794a5ed6 Improve build time 2015-05-16 14:36:28 +02:00
Thomas Bahn 62058962de Add deserialiation implementations for fixed size arrays 2015-05-16 14:19:22 +02:00
Thomas Bahn 7d52366403 Add serialization implementations for fixed size arrays 2015-05-16 14:18:32 +02:00
Erick Tryzelaar ee45eb8340 Merge pull request #69 from hugoduncan/feature/format-specific-field-names
Adds serializer format specific field names
2015-05-14 21:59:05 -07:00
Hugo Duncan 801f37b305 Fix visitors for generic structs 2015-05-14 17:35:21 -04:00
Hugo Duncan bdec0b3e63 Update commas and blocks in match arms 2015-05-14 17:35:16 -04:00
Mikhail Borisov 5c631f3e58 WIP 2015-05-12 15:16:06 +03:00
Mikhail Borisov 5fd9daa865 WIP 2015-05-12 15:03:26 +03:00
Oliver Schneider 0485702a68 update benchmarks 2015-05-11 10:34:58 +02:00
Mikhail Borisov 875610044f Improved support for byte strings 2015-05-09 03:18:13 +03:00
Hugo Duncan ec483fc07d Add doc string for format method 2015-05-08 12:43:12 -04:00
Hugo Duncan 53e6e29571 Fix whitespace 2015-05-08 12:43:12 -04:00
Hugo Duncan c5eed99c6a Make forwarded trait name global 2015-05-08 12:43:12 -04:00
Hugo Duncan fe5176113b Add missing attr.rs file 2015-05-08 12:43:12 -04:00
Hugo Duncan 0f7c67efa7 Factor default attribute lookup into FieldAttrs 2015-05-08 12:43:12 -04:00
Hugo Duncan cd0ee64892 Add constructor functions for FieldAttrs 2015-05-08 12:43:12 -04:00
Hugo Duncan ec3af2cb6a Factor out attr module
Factors out field attribute code into the attr module.
2015-05-08 12:43:12 -04:00
Hugo Duncan 960b68937d Remove commented code and extra newline 2015-05-08 12:43:12 -04:00
Hugo Duncan a1e101b513 Make Value use the 'json' format string 2015-05-08 12:43:11 -04:00
Hugo Duncan c30311153c Rename fmt to format 2015-05-08 12:43:11 -04:00
Hugo Duncan a935ebe8b9 Adds serializer format specific field names
Allows different field names to be used for different external formats.

Field names are specified using the `rename` field attribute, e.g:

    #[serde(rename(xml= "a4", json="a5"))]

Reverts #62

Addresses #61
2015-05-08 12:43:11 -04:00
Oliver Schneider 83ee86122b address comments by erickt 2015-05-08 16:32:46 +02:00
Erick Tryzelaar af752ddcb5 Merge pull request #71 from lifthrasiir/json-split-branch
Replace a redundant `escape` variable with nested matches.
2015-05-07 10:51:57 -07:00
Kang Seonghoon 9550063275 Replace a redundant escape variable with nested matches.
This has a non-trivial performance effect due to the branch prediction,
but is expected to be no slower than the older code and, at least in
some cases, is slightly faster for a string-heavy JSON.
2015-05-08 01:53:24 +09:00
Oliver Schneider c117a680cf changes needed for xml parsing 2015-05-04 16:07:19 +02:00
52 changed files with 2836 additions and 1170 deletions
+2 -2
View File
@@ -1,2 +1,2 @@
/target/
/Cargo.lock
target
Cargo.lock
+25 -7
View File
@@ -1,16 +1,34 @@
language: rust
rust:
- stable
- beta
- nightly
env:
global:
secure: HO41LMpMXkF2In9+1sxWVu7fgolL+y9+4Q5PI6wZX2L5pDwpPJCjxaQarQXCEnoIxED1PlP03JuF7ULNz0zw1ylYhAOfOSdkxFZRnE2wMZqq6qvXBHwyMiDrAociIzoPKSGv7JVrKPsjsnd+96K6xxueIodQZrmAdyq7N/M82Mc=
matrix:
- CRATE=serde_tests TARGET=test
matrix:
include:
- rust: nightly
env: CRATE=serde_macros TARGET=test
- rust: nightly
env: CRATE=serde_macros TARGET=bench
- rust: nightly
env: CRATE=serde_tests TARGET=bench
script:
- cargo test
- cargo bench
- cargo doc
- (cd $CRATE && cargo $TARGET)
after_success: |
[ $TRAVIS_BRANCH = "master" ] &&
[ $TRAVIS_PULL_REQUEST = false ] &&
cargo doc &&
mkdir -p target/doc &&
(cd serde && cargo doc --no-deps) &&
(cd serde_codegen && cargo doc --no-deps) &&
(cd serde_macros && cargo doc --no-deps) &&
cp -r serde/target/doc target/doc/serde &&
cp -r serde_codegen/target/doc target/doc/serde_codegen &&
cp -r serde_macros/target/doc target/doc/serde_macros &&
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 &&
ghp-import -n target/doc &&
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
env:
global:
secure: HO41LMpMXkF2In9+1sxWVu7fgolL+y9+4Q5PI6wZX2L5pDwpPJCjxaQarQXCEnoIxED1PlP03JuF7ULNz0zw1ylYhAOfOSdkxFZRnE2wMZqq6qvXBHwyMiDrAociIzoPKSGv7JVrKPsjsnd+96K6xxueIodQZrmAdyq7N/M82Mc=
+3 -3
View File
@@ -24,8 +24,8 @@ and
for the annotated type:
```rust
#[feature(custom_derive, plugin)]
#[plugin(serde_macros)]
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
@@ -174,7 +174,7 @@ impl<K, V, I> MapVisitor for MapIteratorVisitor<I>
```
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
as a named map. Its visitor uses a simple state machine to iterate through all
the fields:
```rust
+5 -5
View File
@@ -1,17 +1,17 @@
[package]
name = "serde"
version = "0.3.3"
version = "0.4.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
repository = "https://github.com/serde-rs/serde"
documentation = "http://serde-rs.github.io/serde/serde"
readme = "README.md"
readme = "../README.md"
keywords = ["serialization"]
[dependencies]
num = "*"
[dev-dependencies]
rustc-serialize = "*"
serde_macros = { version = "*", path = "serde_macros" }
[features]
nightly = []
+94
View File
@@ -0,0 +1,94 @@
use std::cmp;
use std::io;
use std::slice;
trait IntoBufRead {
type IntoBuf: io::BufRead + BufReadExt;
fn into_buf_read(self) -> Self::IntoBuf;
}
trait BufReadExt {
fn get_buf(&self) -> &[u8];
fn read_u8(&mut self) -> io::Result<Option<u8>>;
}
struct SliceReader<'a> {
buf: &'a [u8],
}
impl<'a> io::Read for SliceReader<'a> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let amt = cmp::min(buf.len(), self.buf.len());
let (a, b) = self.buf.split_at(amt);
slice::bytes::copy_memory(buf, a);
*self.buf = b;
Ok(amt)
}
}
impl<'a> io::BufRead for SliceReader<'a> {
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) }
fn consume(&mut self, amt: usize) { *self.buf = &self.buf[amt..]; }
}
impl<'a> BufReadExt for SliceReader<'a> {
fn get_buf(&self) -> &[u8] { self.buf }
fn read_u8(&mut self) -> io::Result<Option<u8>> {
let byte = self.buf.get(0);
*self.buf = &self.buf[1..];
byte
}
}
struct BufReader<R> {
inner: R,
buf: io::Cursor<Vec<u8>>,
}
impl<R> BufReader<R> where R: io::Read {
fn new(inner: R) -> Self {
BufferedReader::with_capacity(io::DEFAULT_BUF_SIZE, inner)
}
fn new(cap: usize, inner: R) -> Self {
BufferedReader {
inner: inner,
buf: io::Cursor::new(Vec::with_capacity(cap)),
}
}
fn into_inner(self) -> R {
self.inner
}
}
impl<R> Read for BufReader<R> where R: io::Read {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
// If we don't have any buffered data and we're doing a massive read
// (larger than our internal buffer), bypass our internal buffer
// entirely.
if self.buf.get_ref().len() == self.buf.position() as usize &&
buf.len() >= self.buf.get_ref().capacity() {
return self.inner.read(buf);
}
try!(self.fill_buf());
self.buf.read(buf)
}
}
impl<R> BufReadExt for BufReader<R> {
fn get_buf(&self) -> &[u8] {
self.buf.get_ref()
}
fn read_u8(&mut self) -> io::Result<Option<u8>> {
if self.buf.get_ref().len() == self.buf.position() as usize {
}
let byte = self.buf.get(0);
*self.buf = &self.buf[1..];
byte
}
}
+43 -4
View File
@@ -1,6 +1,8 @@
//! Helper module to enable serializing bytes more efficiently
use std::ops;
use std::fmt;
use std::ascii;
use ser;
use de;
@@ -8,10 +10,17 @@ use de;
///////////////////////////////////////////////////////////////////////////////
/// `Bytes` wraps a `&[u8]` in order to serialize into a byte array.
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Bytes<'a> {
bytes: &'a [u8],
}
impl<'a> fmt::Debug for Bytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "b\"{}\"", escape_bytestring(self.bytes))
}
}
impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self {
Bytes {
@@ -28,6 +37,12 @@ impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
}
}
impl<'a> Into<&'a [u8]> for Bytes<'a> {
fn into(self) -> &'a [u8] {
self.bytes
}
}
impl<'a> ops::Deref for Bytes<'a> {
type Target = [u8];
@@ -46,7 +61,7 @@ impl<'a> ser::Serialize for Bytes<'a> {
///////////////////////////////////////////////////////////////////////////////
/// `ByteBuf` wraps a `Vec<u8>` in order to hook into serialize and from deserialize a byte array.
#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
@@ -65,10 +80,22 @@ impl ByteBuf {
}
}
impl<T> From<T> for ByteBuf where T: Into<Vec<u8>> {
fn from(bytes: T) -> Self {
impl fmt::Debug for ByteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "b\"{}\"", escape_bytestring(self.bytes.as_ref()))
}
}
impl Into<Vec<u8>> for ByteBuf {
fn into(self) -> Vec<u8> {
self.bytes
}
}
impl From<Vec<u8>> for ByteBuf {
fn from(bytes: Vec<u8>) -> Self {
ByteBuf {
bytes: bytes.into(),
bytes: bytes,
}
}
}
@@ -172,3 +199,15 @@ impl de::Deserialize for ByteBuf {
deserializer.visit_bytes(ByteBufVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
fn escape_bytestring(bytes: &[u8]) -> String {
let mut result = String::new();
for &b in bytes {
for esc in ascii::escape_default(b) {
result.push(esc as char);
}
}
result
}
+974
View File
@@ -0,0 +1,974 @@
use std::borrow::Cow;
use std::collections::{
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
HashMap,
HashSet,
VecDeque,
};
#[cfg(feature = "nightly")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(feature = "nightly")]
use collections::vec_map::VecMap;
use std::hash::Hash;
use std::marker::PhantomData;
use std::path;
use std::rc::Rc;
use std::str;
use std::sync::Arc;
use num::FromPrimitive;
#[cfg(feature = "nightly")]
use core::nonzero::{NonZero, Zeroable};
#[cfg(feature = "nightly")]
use std::num::Zero;
use de::{
Deserialize,
Deserializer,
EnumVisitor,
Error,
MapVisitor,
SeqVisitor,
VariantVisitor,
Visitor,
};
///////////////////////////////////////////////////////////////////////////////
pub struct UnitVisitor;
impl Visitor for UnitVisitor {
type Value = ();
fn visit_unit<E>(&mut self) -> Result<(), E>
where E: Error,
{
Ok(())
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), V::Error>
where V: SeqVisitor,
{
visitor.end()
}
}
impl Deserialize for () {
fn deserialize<D>(deserializer: &mut D) -> Result<(), D::Error>
where D: Deserializer,
{
deserializer.visit_unit(UnitVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct BoolVisitor;
impl Visitor for BoolVisitor {
type Value = bool;
fn visit_bool<E>(&mut self, v: bool) -> Result<bool, E>
where E: Error,
{
Ok(v)
}
fn visit_str<E>(&mut self, s: &str) -> Result<bool, E>
where E: Error,
{
match s.trim() {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(Error::syntax_error()),
}
}
}
impl Deserialize for bool {
fn deserialize<D>(deserializer: &mut D) -> Result<bool, D::Error>
where D: Deserializer,
{
deserializer.visit_bool(BoolVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_deserialize_num_method {
($src_ty:ty, $method:ident, $from_method:ident) => {
#[inline]
fn $method<E>(&mut self, v: $src_ty) -> Result<T, E>
where E: Error,
{
match FromPrimitive::$from_method(v) {
Some(v) => Ok(v),
None => Err(Error::syntax_error()),
}
}
}
}
pub struct PrimitiveVisitor<T> {
marker: PhantomData<T>,
}
impl<T> PrimitiveVisitor<T> {
#[inline]
pub fn new() -> Self {
PrimitiveVisitor {
marker: PhantomData,
}
}
}
impl<
T: Deserialize + FromPrimitive + str::FromStr
> Visitor for PrimitiveVisitor<T> {
type Value = T;
impl_deserialize_num_method!(isize, visit_isize, from_isize);
impl_deserialize_num_method!(i8, visit_i8, from_i8);
impl_deserialize_num_method!(i16, visit_i16, from_i16);
impl_deserialize_num_method!(i32, visit_i32, from_i32);
impl_deserialize_num_method!(i64, visit_i64, from_i64);
impl_deserialize_num_method!(usize, visit_usize, from_usize);
impl_deserialize_num_method!(u8, visit_u8, from_u8);
impl_deserialize_num_method!(u16, visit_u16, from_u16);
impl_deserialize_num_method!(u32, visit_u32, from_u32);
impl_deserialize_num_method!(u64, visit_u64, from_u64);
impl_deserialize_num_method!(f32, visit_f32, from_f32);
impl_deserialize_num_method!(f64, visit_f64, from_f64);
#[inline]
fn visit_str<E>(&mut self, v: &str) -> Result<T, E>
where E: Error,
{
str::FromStr::from_str(v.trim()).or(Err(Error::syntax_error()))
}
}
macro_rules! impl_deserialize_num {
($ty:ty, $method:ident) => {
impl Deserialize for $ty {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.$method(PrimitiveVisitor::new())
}
}
}
}
impl_deserialize_num!(isize, visit_isize);
impl_deserialize_num!(i8, visit_i8);
impl_deserialize_num!(i16, visit_i16);
impl_deserialize_num!(i32, visit_i32);
impl_deserialize_num!(i64, visit_i64);
impl_deserialize_num!(usize, visit_usize);
impl_deserialize_num!(u8, visit_u8);
impl_deserialize_num!(u16, visit_u16);
impl_deserialize_num!(u32, visit_u32);
impl_deserialize_num!(u64, visit_u64);
impl_deserialize_num!(f32, visit_f32);
impl_deserialize_num!(f64, visit_f64);
///////////////////////////////////////////////////////////////////////////////
struct CharVisitor;
impl Visitor for CharVisitor {
type Value = char;
#[inline]
fn visit_char<E>(&mut self, v: char) -> Result<char, E>
where E: Error,
{
Ok(v)
}
#[inline]
fn visit_str<E>(&mut self, v: &str) -> Result<char, E>
where E: Error,
{
let mut iter = v.chars();
if let Some(v) = iter.next() {
if iter.next().is_some() {
Err(Error::syntax_error())
} else {
Ok(v)
}
} else {
Err(Error::end_of_stream_error())
}
}
}
impl Deserialize for char {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<char, D::Error>
where D: Deserializer,
{
deserializer.visit_char(CharVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
struct StringVisitor;
impl Visitor for StringVisitor {
type Value = String;
fn visit_str<E>(&mut self, v: &str) -> Result<String, E>
where E: Error,
{
Ok(v.to_string())
}
fn visit_string<E>(&mut self, v: String) -> Result<String, E>
where E: Error,
{
Ok(v)
}
fn visit_bytes<E>(&mut self, v: &[u8]) -> Result<String, E>
where E: Error,
{
match str::from_utf8(v) {
Ok(s) => Ok(s.to_string()),
Err(_) => Err(Error::syntax_error()),
}
}
fn visit_byte_buf<'a, E>(&mut self, v: Vec<u8>) -> Result<String, E>
where E: Error,
{
match String::from_utf8(v) {
Ok(s) => Ok(s),
Err(_) => Err(Error::syntax_error()),
}
}
}
impl Deserialize for String {
fn deserialize<D>(deserializer: &mut D) -> Result<String, D::Error>
where D: Deserializer,
{
deserializer.visit_string(StringVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
struct OptionVisitor<T> {
marker: PhantomData<T>,
}
impl<
T: Deserialize,
> Visitor for OptionVisitor<T> {
type Value = Option<T>;
#[inline]
fn visit_none<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
{
Ok(None)
}
#[inline]
fn visit_some<D>(&mut self, deserializer: &mut D) -> Result<Option<T>, D::Error>
where D: Deserializer,
{
Ok(Some(try!(Deserialize::deserialize(deserializer))))
}
}
impl<T> Deserialize for Option<T> where T: Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<Option<T>, D::Error>
where D: Deserializer,
{
deserializer.visit_option(OptionVisitor { marker: PhantomData })
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! set_impl {
(
$ty:ty,
< $($constraints:ident),* >,
$visitor_name:ident,
$visitor:ident,
$ctor:expr,
$with_capacity:expr,
$insert:expr
) => {
pub struct $visitor_name<T> {
marker: PhantomData<T>,
}
impl<T> $visitor_name<T> {
pub fn new() -> Self {
$visitor_name {
marker: PhantomData,
}
}
}
impl<T> Visitor for $visitor_name<T>
where T: $($constraints +)*,
{
type Value = $ty;
#[inline]
fn visit_unit<E>(&mut self) -> Result<$ty, E>
where E: Error,
{
Ok($ctor)
}
#[inline]
fn visit_seq<V>(&mut self, mut $visitor: V) -> Result<$ty, V::Error>
where V: SeqVisitor,
{
let mut values = $with_capacity;
while let Some(value) = try!($visitor.visit()) {
$insert(&mut values, value);
}
try!($visitor.end());
Ok(values)
}
}
impl<T> Deserialize for $ty
where T: $($constraints +)*,
{
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.visit_seq($visitor_name::new())
}
}
}
}
set_impl!(
BinaryHeap<T>,
<Deserialize, Ord>,
BinaryHeapVisitor,
visitor,
BinaryHeap::new(),
BinaryHeap::with_capacity(visitor.size_hint().0),
BinaryHeap::push);
set_impl!(
BTreeSet<T>,
<Deserialize, Eq, Ord>,
BTreeSetVisitor,
visitor,
BTreeSet::new(),
BTreeSet::new(),
BTreeSet::insert);
#[cfg(feature = "nightly")]
set_impl!(
EnumSet<T>,
<Deserialize, CLike>,
EnumSetVisitor,
visitor,
EnumSet::new(),
EnumSet::new(),
EnumSet::insert);
set_impl!(
LinkedList<T>,
<Deserialize>,
LinkedListVisitor,
visitor,
LinkedList::new(),
LinkedList::new(),
LinkedList::push_back);
set_impl!(
HashSet<T>,
<Deserialize, Eq, Hash>,
HashSetVisitor,
visitor,
HashSet::new(),
HashSet::with_capacity(visitor.size_hint().0),
HashSet::insert);
set_impl!(
Vec<T>,
<Deserialize>,
VecVisitor,
visitor,
Vec::new(),
Vec::with_capacity(visitor.size_hint().0),
Vec::push);
set_impl!(
VecDeque<T>,
<Deserialize>,
VecDequeVisitor,
visitor,
VecDeque::new(),
VecDeque::with_capacity(visitor.size_hint().0),
VecDeque::push_back);
///////////////////////////////////////////////////////////////////////////////
struct ArrayVisitor0<T> {
marker: PhantomData<T>,
}
impl<T> ArrayVisitor0<T> {
pub fn new() -> Self {
ArrayVisitor0 {
marker: PhantomData,
}
}
}
impl<T> Visitor for ArrayVisitor0<T> where T: Deserialize + Default {
type Value = [T; 0];
#[inline]
fn visit_unit<E>(&mut self) -> Result<[T; 0], E>
where E: Error,
{
Ok([T::default(); 0])
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<[T; 0], V::Error>
where V: SeqVisitor,
{
try!(visitor.end());
Ok([T::default(); 0])
}
}
impl<T> Deserialize for [T; 0]
where T: Deserialize + Default
{
fn deserialize<D>(deserializer: &mut D) -> Result<[T; 0], D::Error>
where D: Deserializer,
{
deserializer.visit_seq(ArrayVisitor0::new())
}
}
macro_rules! array_impls {
($($visitor:ident, $len:expr => ($($name:ident),+),)+) => {
$(
struct $visitor<T> {
marker: PhantomData<T>,
}
impl<T> $visitor<T> {
pub fn new() -> Self {
$visitor {
marker: PhantomData
}
}
}
impl<T> Visitor for $visitor<T> where T: Deserialize {
type Value = [T; $len];
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<[T; $len], V::Error>
where V: SeqVisitor,
{
$(
let $name = match try!(visitor.visit()) {
Some(val) => val,
None => { return Err(Error::end_of_stream_error()); }
};
)+;
try!(visitor.end());
Ok([$($name,)+])
}
}
impl<T> Deserialize for [T; $len]
where T: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<[T; $len], D::Error>
where D: Deserializer,
{
deserializer.visit_seq($visitor::new())
}
}
)+
}
}
array_impls! {
ArrayVisitor1, 1 => (a),
ArrayVisitor2, 2 => (a, b),
ArrayVisitor3, 3 => (a, b, c),
ArrayVisitor4, 4 => (a, b, c, d),
ArrayVisitor5, 5 => (a, b, c, d, e),
ArrayVisitor6, 6 => (a, b, c, d, e, f),
ArrayVisitor7, 7 => (a, b, c, d, e, f, g),
ArrayVisitor8, 8 => (a, b, c, d, e, f, g, h),
ArrayVisitor9, 9 => (a, b, c, d, e, f, g, h, i),
ArrayVisitor10, 10 => (a, b, c, d, e, f, g, h, i, j),
ArrayVisitor11, 11 => (a, b, c, d, e, f, g, h, i, j, k),
ArrayVisitor12, 12 => (a, b, c, d, e, f, g, h, i, j, k, l),
ArrayVisitor13, 13 => (a, b, c, d, e, f, g, h, i, j, k, l, m),
ArrayVisitor14, 14 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n),
ArrayVisitor15, 15 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o),
ArrayVisitor16, 16 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p),
ArrayVisitor17, 17 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q),
ArrayVisitor18, 18 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r),
ArrayVisitor19, 19 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s),
ArrayVisitor20, 20 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s ,t),
ArrayVisitor21, 21 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u),
ArrayVisitor22, 22 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v),
ArrayVisitor23, 23 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w),
ArrayVisitor24, 24 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x),
ArrayVisitor25, 25 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y),
ArrayVisitor26, 26 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z),
ArrayVisitor27, 27 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa),
ArrayVisitor28, 28 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab),
ArrayVisitor29, 29 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab, ac),
ArrayVisitor30, 30 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab, ac, ad),
ArrayVisitor31, 31 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab, ac, ad, ae),
ArrayVisitor32, 32 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x,
y, z, aa, ab, ac, ad, ae, af),
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
() => {};
($($visitor:ident => ($($name:ident),+),)+) => {
$(
struct $visitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<
$($name: Deserialize,)+
> Visitor for $visitor<$($name,)+> {
type Value = ($($name,)+);
#[inline]
#[allow(non_snake_case)]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<($($name,)+), V::Error>
where V: SeqVisitor,
{
$(
let $name = match try!(visitor.visit()) {
Some(value) => value,
None => { return Err(Error::end_of_stream_error()); }
};
)+;
try!(visitor.end());
Ok(($($name,)+))
}
}
impl<
$($name: Deserialize),+
> Deserialize for ($($name,)+) {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<($($name,)+), D::Error>
where D: Deserializer,
{
deserializer.visit_tuple($visitor { marker: PhantomData })
}
}
)+
}
}
tuple_impls! {
TupleVisitor1 => (T0),
TupleVisitor2 => (T0, T1),
TupleVisitor3 => (T0, T1, T2),
TupleVisitor4 => (T0, T1, T2, T3),
TupleVisitor5 => (T0, T1, T2, T3, T4),
TupleVisitor6 => (T0, T1, T2, T3, T4, T5),
TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6),
TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7),
TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8),
TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9),
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),
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! map_impl {
(
$ty:ty,
< $($constraints:ident),* >,
$visitor_name:ident,
$visitor:ident,
$ctor:expr,
$with_capacity:expr,
$insert:expr
) => {
pub struct $visitor_name<K, V> {
marker: PhantomData<$ty>,
}
impl<K, V> $visitor_name<K, V> {
pub fn new() -> Self {
$visitor_name {
marker: PhantomData,
}
}
}
impl<K, V> Visitor for $visitor_name<K, V>
where K: $($constraints +)*,
V: Deserialize,
{
type Value = $ty;
#[inline]
fn visit_unit<E>(&mut self) -> Result<$ty, E>
where E: Error,
{
Ok($ctor)
}
#[inline]
fn visit_map<Visitor>(&mut self, mut $visitor: Visitor) -> Result<$ty, Visitor::Error>
where Visitor: MapVisitor,
{
let mut values = $with_capacity;
while let Some((key, value)) = try!($visitor.visit()) {
$insert(&mut values, key, value);
}
try!($visitor.end());
Ok(values)
}
}
impl<K, V> Deserialize for $ty
where K: $($constraints +)*,
V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.visit_map($visitor_name::new())
}
}
}
}
map_impl!(
BTreeMap<K, V>,
<Deserialize, Eq, Ord>,
BTreeMapVisitor,
visitor,
BTreeMap::new(),
BTreeMap::new(),
BTreeMap::insert);
map_impl!(
HashMap<K, V>,
<Deserialize, Eq, Hash>,
HashMapVisitor,
visitor,
HashMap::new(),
HashMap::with_capacity(visitor.size_hint().0),
HashMap::insert);
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "nightly")]
pub struct VecMapVisitor<V> {
marker: PhantomData<VecMap<V>>,
}
#[cfg(feature = "nightly")]
impl<V> VecMapVisitor<V> {
#[inline]
pub fn new() -> Self {
VecMapVisitor {
marker: PhantomData,
}
}
}
#[cfg(feature = "nightly")]
impl<V> Visitor for VecMapVisitor<V>
where V: Deserialize,
{
type Value = VecMap<V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<VecMap<V>, E>
where E: Error,
{
Ok(VecMap::new())
}
#[inline]
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<VecMap<V>, V_::Error>
where V_: MapVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = VecMap::with_capacity(len);
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
#[cfg(feature = "nightly")]
impl<V> Deserialize for VecMap<V>
where V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<VecMap<V>, D::Error>
where D: Deserializer,
{
deserializer.visit_map(VecMapVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
struct PathBufVisitor;
impl Visitor for PathBufVisitor {
type Value = path::PathBuf;
fn visit_str<E>(&mut self, v: &str) -> Result<path::PathBuf, E>
where E: Error,
{
Ok(From::from(v))
}
fn visit_string<E>(&mut self, v: String) -> Result<path::PathBuf, E>
where E: Error,
{
self.visit_str(&v)
}
}
impl Deserialize for path::PathBuf {
fn deserialize<D>(deserializer: &mut D) -> Result<path::PathBuf, D::Error>
where D: Deserializer,
{
deserializer.visit(PathBufVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
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))
}
}
impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deserialize, {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<Cow<'a, T>, D::Error>
where D: Deserializer,
{
let val = try!(Deserialize::deserialize(deserializer));
Ok(Cow::Owned(val))
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "nightly")]
impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero {
fn deserialize<D>(deserializer: &mut D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
let value = try!(Deserialize::deserialize(deserializer));
if value == Zero::zero() {
return Err(Error::syntax_error())
}
unsafe {
Ok(NonZero::new(value))
}
}
}
///////////////////////////////////////////////////////////////////////////////
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>
where D: Deserializer {
enum Field {
Field0,
Field1,
}
impl Deserialize for Field {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
where D: Deserializer {
struct FieldVisitor<D> {
phantom: PhantomData<D>,
}
impl<D> ::de::Visitor for FieldVisitor<D> where D: Deserializer {
type Value = Field;
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E> where E: Error {
match value {
"Ok" => Ok(Field::Field0),
"Err" => Ok(Field::Field1),
_ => Err(Error::unknown_field_error(value)),
}
}
fn visit_bytes<E>(&mut self, value: &[u8]) -> Result<Field, E> where E: Error {
match str::from_utf8(value) {
Ok(s) => self.visit_str(s),
_ => Err(Error::syntax_error()),
}
}
}
deserializer.visit(FieldVisitor::<D> {
phantom: PhantomData,
})
}
}
struct Visitor<D, T, E>(PhantomData<D>, PhantomData<T>, PhantomData<E>)
where D: Deserializer, T: Deserialize, E: Deserialize;
impl<D, T, E> EnumVisitor for Visitor<D, T, E> where D: Deserializer,
T: Deserialize,
E: Deserialize {
type Value = Result<T, E>;
fn visit<V>(&mut self, mut visitor: V) -> Result<Result<T, E>, V::Error>
where V: VariantVisitor {
match match visitor.visit_variant() {
Ok(val) => val,
Err(err) => return Err(From::from(err)),
} {
Field::Field0 => {
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 => {
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::Err(field0))
}
}
visitor.visit_seq(Visitor::<D, T, E>(PhantomData,
PhantomData,
PhantomData))
}
}
}
}
deserializer.visit_enum("Result",
Visitor::<D, T, E>(PhantomData, PhantomData, PhantomData))
}
}
+189 -30
View File
@@ -25,18 +25,164 @@ pub trait Deserialize {
///////////////////////////////////////////////////////////////////////////////
/// `Deserializer` is an abstract trait that can deserialize values into a `Visitor`.
/// `Deserializer` is a trait that can deserialize values by threading a `Visitor` trait through a
/// value. It supports two entry point styles which enables different kinds of deserialization.
///
/// 1) The `visit` method. File formats like JSON embed the type of it's construct in it's file
/// format. This allows the `Deserializer` to deserialize into a generic type like
/// `json::Value`, which can represent all JSON types.
///
/// 2) The `visit_*` methods. File formats like bincode do not embed in it's format how to decode
/// it's values. It relies instead on the `Deserialize` type to hint to the `Deserializer` with
/// the `visit_*` methods how it should parse the next value. One downside though to only
/// supporting the `visit_*` types is that it does not allow for deserializing into a generic
/// `json::Value`-esque type.
pub trait Deserializer {
type Error: Error;
/// The `visit` method walks a visitor through a value as it is being deserialized.
/// This method walks a visitor through a value as it is being deserialized.
fn visit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor;
/// The `visit_option` method allows a `Deserialize` type to inform the `Deserializer` that
/// it's expecting an optional value. This allows deserializers that encode an optional value
/// as a nullable value to convert the null value into a `None`, and a regular value as
/// `Some(value)`.
/// This method hints that the `Deserialize` type is expecting a `bool` value.
#[inline]
fn visit_bool<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `usize` value.
#[inline]
fn visit_usize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u8` value.
#[inline]
fn visit_u8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u16` value.
#[inline]
fn visit_u16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u32` value.
#[inline]
fn visit_u32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `u64` value.
#[inline]
fn visit_u64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `isize` value.
#[inline]
fn visit_isize<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i8` value.
#[inline]
fn visit_i8<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i16` value.
#[inline]
fn visit_i16<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i32` value.
#[inline]
fn visit_i32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `i64` value.
#[inline]
fn visit_i64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `f32` value.
#[inline]
fn visit_f32<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `f64` value.
#[inline]
fn visit_f64<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `char` value.
#[inline]
fn visit_char<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `&str` value.
#[inline]
fn visit_str<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting a `String` value.
#[inline]
fn visit_string<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit_str(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `unit` value.
#[inline]
fn visit_unit<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an `Option` value. This allows
/// deserializers that encode an optional value as a nullable value to convert the null value
/// into a `None`, and a regular value as `Some(value)`.
#[inline]
fn visit_option<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
@@ -44,9 +190,8 @@ pub trait Deserializer {
self.visit(visitor)
}
/// The `visit_seq` method allows a `Deserialize` type to inform the `Deserializer` that it's
/// expecting a sequence of values. This allows deserializers to parse sequences that aren't
/// tagged as sequences.
/// This method hints that the `Deserialize` type is expecting a sequence value. This allows
/// deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn visit_seq<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
@@ -54,9 +199,8 @@ pub trait Deserializer {
self.visit(visitor)
}
/// The `visit_map` method allows a `Deserialize` type to inform the `Deserializer` that it's
/// expecting a map of values. This allows deserializers to parse sequences that aren't tagged
/// as maps.
/// This method hints that the `Deserialize` type is expecting a map of values. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn visit_map<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
@@ -64,9 +208,8 @@ pub trait Deserializer {
self.visit(visitor)
}
/// The `visit_named_unit` method allows a `Deserialize` type to inform the `Deserializer` that
/// it's expecting a named unit. This allows deserializers to a named unit that aren't tagged
/// as a named unit.
/// This method hints that the `Deserialize` type is expecting a named unit. This allows
/// deserializers to a named unit that aren't tagged as a named unit.
#[inline]
fn visit_named_unit<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
@@ -74,9 +217,8 @@ pub trait Deserializer {
self.visit(visitor)
}
/// The `visit_named_seq` method allows a `Deserialize` type to inform the `Deserializer` that
/// it's expecting a named sequence of values. This allows deserializers to parse sequences
/// that aren't tagged as sequences.
/// This method hints that the `Deserialize` type is expecting a named sequence.
/// This allows deserializers to parse sequences that aren't tagged as sequences.
#[inline]
fn visit_named_seq<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
@@ -84,9 +226,8 @@ pub trait Deserializer {
self.visit_seq(visitor)
}
/// The `visit_named_map` method allows a `Deserialize` type to inform the `Deserializer` that
/// it's expecting a map of values. This allows deserializers to parse sequences that aren't
/// tagged as maps.
/// This method hints that the `Deserialize` type is expecting a named map. This allows
/// deserializers to parse sequences that aren't tagged as maps.
#[inline]
fn visit_named_map<V>(&mut self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
@@ -94,9 +235,18 @@ pub trait Deserializer {
self.visit_map(visitor)
}
/// The `visit_enum` method allows a `Deserialize` type to inform the `Deserializer` that it's
/// expecting an enum value. This allows deserializers that provide a custom enumeration
/// serialization to properly deserialize the type.
/// This method hints that the `Deserialize` type is expecting a tuple value. This allows
/// deserializers that provide a custom tuple serialization to properly deserialize the type.
#[inline]
fn visit_tuple<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// This method hints that the `Deserialize` type is expecting an enum value. This allows
/// deserializers that provide a custom enumeration serialization to properly deserialize the
/// type.
#[inline]
fn visit_enum<V>(&mut self, _enum: &str, _visitor: V) -> Result<V::Value, Self::Error>
where V: EnumVisitor,
@@ -104,21 +254,30 @@ pub trait Deserializer {
Err(Error::syntax_error())
}
/// The `visit_bytes` method allows a `Deserialize` type to inform the `Deserializer` that it's
/// expecting a `Vec<u8>`. This allows deserializers that provide a custom byte vector
/// serialization to properly deserialize the type.
/// This method hints that the `Deserialize` type is expecting a `Vec<u8>`. This allows
/// deserializers that provide a custom byte vector serialization to properly deserialize the
/// type.
#[inline]
fn visit_bytes<V>(&mut self, visitor: V) -> Result<V::Value, Self::Error>
where V: Visitor,
{
self.visit(visitor)
}
/// Specify a format string for the deserializer.
///
/// The deserializer format is used to determine which format
/// specific field attributes should be used with the
/// deserializer.
fn format() -> &'static str {
""
}
}
///////////////////////////////////////////////////////////////////////////////
pub trait Visitor {
type Value;
type Value: Deserialize;
fn visit_bool<E>(&mut self, _v: bool) -> Result<Self::Value, E>
where E: Error,
@@ -263,10 +422,10 @@ pub trait Visitor {
Err(Error::syntax_error())
}
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>
where E: Error,
{
Err(Error::syntax_error())
self.visit_bytes(&v)
}
}
+54
View File
@@ -12,6 +12,7 @@ use std::hash::Hash;
use std::vec;
use de;
use bytes;
///////////////////////////////////////////////////////////////////////////////
@@ -409,3 +410,56 @@ impl<K, V> ValueDeserializer for HashMap<K, V>
MapDeserializer::new(self.into_iter(), len)
}
}
///////////////////////////////////////////////////////////////////////////////
impl<'a> ValueDeserializer for bytes::Bytes<'a>
{
type Deserializer = BytesDeserializer<'a>;
fn into_deserializer(self) -> BytesDeserializer<'a> {
BytesDeserializer(Some(self.into()))
}
}
pub struct BytesDeserializer<'a> (Option<&'a [u8]>);
impl<'a> de::Deserializer for BytesDeserializer<'a> {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.0.take() {
Some(bytes) => visitor.visit_bytes(bytes),
None => Err(de::Error::end_of_stream_error()),
}
}
}
///////////////////////////////////////////////////////////////////////////////
impl ValueDeserializer for bytes::ByteBuf
{
type Deserializer = ByteBufDeserializer;
fn into_deserializer(self) -> Self::Deserializer {
ByteBufDeserializer(Some(self.into()))
}
}
pub struct ByteBufDeserializer(Option<Vec<u8>>);
impl de::Deserializer for ByteBufDeserializer {
type Error = Error;
fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Error>
where V: de::Visitor,
{
match self.0.take() {
Some(bytes) => visitor.visit_byte_buf(bytes),
None => Err(de::Error::end_of_stream_error()),
}
}
}
+7 -1
View File
@@ -1,4 +1,5 @@
use std::io;
use std::iter::Peekable;
pub struct LineColIterator<Iter: Iterator<Item=io::Result<u8>>> {
iter: Iter,
@@ -25,12 +26,17 @@ impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
pub fn get_ref(&self) -> &Iter { &self.iter }
/// Gets a mutable reference to the underlying iterator.
pub fn get_mut(&self) -> &Iter { &self.iter }
pub fn get_mut(&mut self) -> &mut Iter { &mut self.iter }
/// Unwraps this `LineColIterator`, returning the underlying iterator.
pub fn into_inner(self) -> Iter { self.iter }
}
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Peekable<Iter>> {
/// peeks at the next value
pub fn peek(&mut self) -> Option<&io::Result<u8>> { self.iter.peek() }
}
impl<Iter: Iterator<Item=io::Result<u8>>> Iterator for LineColIterator<Iter> {
type Item = io::Result<u8>;
fn next(&mut self) -> Option<io::Result<u8>> {
+91 -72
View File
@@ -1,4 +1,5 @@
use std::char;
use std::i32;
use std::io;
use std::str;
@@ -13,6 +14,15 @@ pub struct Deserializer<Iter: Iterator<Item=io::Result<u8>>> {
str_buf: Vec<u8>,
}
macro_rules! try_or_invalid {
($self_:expr, $e:expr) => {
match $e {
Some(v) => v,
None => { return Err($self_.error(ErrorCode::InvalidNumber)); }
}
}
}
impl<Iter> Deserializer<Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
@@ -180,7 +190,7 @@ impl<Iter> Deserializer<Iter>
}
fn parse_integer(&mut self) -> Result<u64, Error> {
let mut res = 0;
let mut accum: u64 = 0;
match self.ch_or_null() {
b'0' => {
@@ -198,8 +208,9 @@ impl<Iter> Deserializer<Iter>
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
res *= 10;
res += (c as u64) - (b'0' as u64);
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());
}
_ => break,
@@ -209,7 +220,7 @@ impl<Iter> Deserializer<Iter>
_ => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
Ok(res)
Ok(accum)
}
fn parse_decimal(&mut self, res: f64) -> Result<f64, Error> {
@@ -240,7 +251,7 @@ impl<Iter> Deserializer<Iter>
fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
try!(self.bump());
let mut exp = 0;
let mut exp: u64 = 0;
let mut neg_exp = false;
if self.ch_is(b'+') {
@@ -258,8 +269,8 @@ impl<Iter> Deserializer<Iter>
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
exp *= 10;
exp += (c as i32) - (b'0' as i32);
exp = try_or_invalid!(self, exp.checked_mul(10));
exp = try_or_invalid!(self, exp.checked_add((c as u64) - (b'0' as u64)));
try!(self.bump());
}
@@ -267,7 +278,12 @@ impl<Iter> Deserializer<Iter>
}
}
let exp: f64 = 10_f64.powi(exp);
let exp = if exp <= i32::MAX as u64 {
10_f64.powi(exp as i32)
} else {
return Err(self.error(ErrorCode::InvalidNumber));
};
if neg_exp {
res /= exp;
} else {
@@ -307,89 +323,87 @@ impl<Iter> Deserializer<Iter>
fn parse_string(&mut self) -> Result<(), Error> {
self.str_buf.clear();
let mut escape = false;
loop {
let ch = match try!(self.next_char()) {
Some(ch) => ch,
None => { return Err(self.error(ErrorCode::EOFWhileParsingString)); }
};
if escape {
match ch {
b'"' => self.str_buf.push(b'"'),
b'\\' => self.str_buf.push(b'\\'),
b'/' => self.str_buf.push(b'/'),
b'b' => self.str_buf.push(b'\x08'),
b'f' => self.str_buf.push(b'\x0c'),
b'n' => self.str_buf.push(b'\n'),
b'r' => self.str_buf.push(b'\r'),
b't' => self.str_buf.push(b'\t'),
b'u' => {
let c = match try!(self.decode_hex_escape()) {
0xDC00 ... 0xDFFF => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
match ch {
b'"' => {
try!(self.bump());
return Ok(());
}
b'\\' => {
let ch = match try!(self.next_char()) {
Some(ch) => ch,
None => { return Err(self.error(ErrorCode::EOFWhileParsingString)); }
};
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800 ... 0xDBFF => {
match (try!(self.next_char()), try!(self.next_char())) {
(Some(b'\\'), Some(b'u')) => (),
_ => {
return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape));
}
}
let n2 = try!(self.decode_hex_escape());
if n2 < 0xDC00 || n2 > 0xDFFF {
match ch {
b'"' => self.str_buf.push(b'"'),
b'\\' => self.str_buf.push(b'\\'),
b'/' => self.str_buf.push(b'/'),
b'b' => self.str_buf.push(b'\x08'),
b'f' => self.str_buf.push(b'\x0c'),
b'n' => self.str_buf.push(b'\n'),
b'r' => self.str_buf.push(b'\r'),
b't' => self.str_buf.push(b'\t'),
b'u' => {
let c = match try!(self.decode_hex_escape()) {
0xDC00 ... 0xDFFF => {
return Err(self.error(ErrorCode::LoneLeadingSurrogateInHexEscape));
}
let n = (((n1 - 0xD800) as u32) << 10 |
(n2 - 0xDC00) as u32) + 0x1_0000;
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
n1 @ 0xD800 ... 0xDBFF => {
match (try!(self.next_char()), try!(self.next_char())) {
(Some(b'\\'), Some(b'u')) => (),
_ => {
return Err(self.error(ErrorCode::UnexpectedEndOfHexEscape));
}
}
match char::from_u32(n as u32) {
Some(c) => c,
None => {
return Err(self.error(ErrorCode::InvalidUnicodeCodePoint));
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));
}
}
}
}
};
};
// 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));
// 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));
}
}
}
escape = false;
} else {
match ch {
b'"' => {
try!(self.bump());
return Ok(());
}
b'\\' => {
escape = true;
}
ch => {
self.str_buf.push(ch);
}
ch => {
self.str_buf.push(ch);
}
}
}
@@ -465,6 +479,11 @@ impl<Iter> de::Deserializer for Deserializer<Iter>
Err(self.error(ErrorCode::ExpectedSomeValue))
}
}
#[inline]
fn format() -> &'static str {
"json"
}
}
struct SeqVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
@@ -256,6 +256,11 @@ impl<W, F> ser::Serializer for Serializer<W, F>
try!(self.formatter.colon(&mut self.writer));
value.serialize(self)
}
#[inline]
fn format() -> &'static str {
"json"
}
}
pub trait Formatter {
+34 -2
View File
@@ -37,8 +37,30 @@ impl Value {
/// Otherwise, it will return the `Value` associated with the final key.
pub fn find_path<'a>(&'a self, keys: &[&str]) -> Option<&'a Value>{
let mut target = self;
for key in keys.iter() {
match target.find(*key) {
for key in keys {
match target.find(key) {
Some(t) => { target = t; },
None => return None
}
}
Some(target)
}
/// Looks up a value by path.
///
/// This is a convenience method that splits the path by `'.'`
/// and then feeds the sequence of keys into the `find_path`
/// method.
///
/// ``` ignore
/// let obj: Value = json::from_str(r#"{"x": {"a": 1}}"#).unwrap();
///
/// assert!(obj.lookup("x.a").unwrap() == &Value::U64(1));
/// ```
pub fn lookup<'a>(&'a self, path: &str) -> Option<&'a Value> {
let mut target = self;
for key in path.split('.') {
match target.find(key) {
Some(t) => { target = t; },
None => return None
}
@@ -571,6 +593,11 @@ impl ser::Serializer for Serializer {
Ok(())
}
#[inline]
fn format() -> &'static str {
"json"
}
}
pub struct Deserializer {
@@ -677,6 +704,11 @@ impl de::Deserializer for Deserializer {
None => Ok(value)
}
}
#[inline]
fn format() -> &'static str {
"json"
}
}
struct SeqDeserializer<'a> {
+7
View File
@@ -6,9 +6,16 @@
//! 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")]
#![cfg_attr(feature = "nightly", feature(collections, core, enumset, nonzero, step_trait, vecmap, zero_one))]
extern crate num;
#[cfg(feature = "nightly")]
extern crate collections;
#[cfg(feature = "nightly")]
extern crate core;
pub use ser::{Serialize, Serializer};
pub use de::{Deserialize, Deserializer, Error};
+241 -9
View File
@@ -1,9 +1,32 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::borrow::Cow;
use std::collections::{
BinaryHeap,
BTreeMap,
BTreeSet,
LinkedList,
HashMap,
HashSet,
VecDeque,
};
#[cfg(feature = "nightly")]
use collections::enum_set::{CLike, EnumSet};
#[cfg(feature = "nightly")]
use std::collections::vec_map::VecMap;
use std::hash::Hash;
#[cfg(feature = "nightly")]
use std::iter;
use std::marker::PhantomData;
#[cfg(feature = "nightly")]
use std::num;
#[cfg(feature = "nightly")]
use std::ops;
use std::path;
use std::rc::Rc;
use std::sync::Arc;
#[cfg(feature = "nightly")]
use core::nonzero::{NonZero, Zeroable};
use super::{
Serialize,
Serializer,
@@ -119,7 +142,7 @@ impl<T, Iter> SeqVisitor for SeqIteratorVisitor<Iter>
///////////////////////////////////////////////////////////////////////////////
impl<'a, T> Serialize for &'a [T]
impl<T> Serialize for [T]
where T: Serialize,
{
#[inline]
@@ -130,12 +153,63 @@ impl<'a, T> Serialize for &'a [T]
}
}
impl<T> Serialize for Vec<T> where T: Serialize {
macro_rules! array_impls {
($len:expr) => {
impl<T> Serialize for [T; $len] where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some($len)))
}
}
}
}
array_impls!(0);
array_impls!(1);
array_impls!(2);
array_impls!(3);
array_impls!(4);
array_impls!(5);
array_impls!(6);
array_impls!(7);
array_impls!(8);
array_impls!(9);
array_impls!(10);
array_impls!(11);
array_impls!(12);
array_impls!(13);
array_impls!(14);
array_impls!(15);
array_impls!(16);
array_impls!(17);
array_impls!(18);
array_impls!(19);
array_impls!(20);
array_impls!(21);
array_impls!(22);
array_impls!(23);
array_impls!(24);
array_impls!(25);
array_impls!(26);
array_impls!(27);
array_impls!(28);
array_impls!(29);
array_impls!(30);
array_impls!(31);
array_impls!(32);
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for BinaryHeap<T>
where T: Serialize + Ord
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(&self[..]).serialize(serializer)
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
@@ -150,6 +224,18 @@ impl<T> Serialize for BTreeSet<T>
}
}
#[cfg(feature = "nightly")]
impl<T> Serialize for EnumSet<T>
where T: Serialize + CLike
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
impl<T> Serialize for HashSet<T>
where T: Serialize + Eq + Hash,
{
@@ -161,6 +247,49 @@ impl<T> Serialize for HashSet<T>
}
}
impl<T> Serialize for LinkedList<T>
where T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
#[cfg(feature = "nightly")]
impl<A> Serialize for ops::Range<A>
where A: Serialize + Clone + iter::Step + num::One,
for<'a> &'a A: ops::Add<&'a A, Output = A>,
{
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
let len = iter::Step::steps_between(&self.start, &self.end, &A::one());
serializer.visit_seq(SeqIteratorVisitor::new(self.clone(), len))
}
}
impl<T> Serialize for Vec<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(&self[..]).serialize(serializer)
}
}
impl<T> Serialize for VecDeque<T> where T: Serialize {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
///////////////////////////////////////////////////////////////////////////////
impl Serialize for () {
@@ -210,7 +339,7 @@ macro_rules! tuple_impls {
$(
$state => {
self.state += 1;
Ok(Some(try!(serializer.visit_seq_elt(&e!(self.tuple.$idx)))))
Ok(Some(try!(serializer.visit_tuple_elt(&e!(self.tuple.$idx)))))
}
)+
_ => {
@@ -229,7 +358,7 @@ macro_rules! tuple_impls {
{
#[inline]
fn serialize<S: Serializer>(&self, serializer: &mut S) -> Result<(), S::Error> {
serializer.visit_seq($TupleVisitor::new(self))
serializer.visit_tuple($TupleVisitor::new(self))
}
}
)+
@@ -410,8 +539,7 @@ impl<K, V> Serialize for HashMap<K, V>
}
}
// FIXME: `VecMap` is unstable.
/*
#[cfg(feature = "nightly")]
impl<V> Serialize for VecMap<V>
where V: Serialize,
{
@@ -422,7 +550,6 @@ impl<V> Serialize for VecMap<V>
serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len())))
}
}
*/
///////////////////////////////////////////////////////////////////////////////
@@ -471,6 +598,104 @@ impl<T> Serialize for Arc<T> where T: Serialize, {
}
}
impl<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned, {
#[inline]
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
where S: Serializer,
{
(**self).serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
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 {
match *self {
Result::Ok(ref field0) => {
struct Visitor<'a, T, E> where T: Serialize + 'a, E: Serialize + 'a {
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) => {
struct Visitor<'a, T, E> where T: Serialize + 'a, E: Serialize + 'a {
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)
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
impl Serialize for path::Path {
@@ -488,3 +713,10 @@ impl Serialize for path::PathBuf {
self.to_str().unwrap().serialize(serializer)
}
}
#[cfg(feature = "nightly")]
impl<T> Serialize for NonZero<T> where T: Serialize + Zeroable {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
(**self).serialize(serializer)
}
}
+65 -13
View File
@@ -104,7 +104,7 @@ pub trait Serializer {
fn visit_str(&mut self, value: &str) -> Result<(), Self::Error>;
/// `visit_bytes` is a hook that enables those serialization formats that support serializing
/// byte slices separately from generic arrays. By default it serializes as a regular array.
/// byte slices separately from generic arrays. By default it serializes as a regular array.
#[inline]
fn visit_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> {
self.visit_seq(impls::SeqIteratorVisitor::new(value.iter(), Some(value.len())))
@@ -132,13 +132,37 @@ pub trait Serializer {
fn visit_seq<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor;
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize;
#[inline]
fn visit_tuple<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
}
#[inline]
fn visit_tuple_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_seq_elt(value)
}
#[inline]
fn visit_named_seq<V>(&mut self,
_name: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
self.visit_tuple(visitor)
}
#[inline]
fn visit_named_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_tuple_elt(value)
}
#[inline]
@@ -148,15 +172,23 @@ pub trait Serializer {
visitor: V) -> Result<(), Self::Error>
where V: SeqVisitor,
{
self.visit_seq(visitor)
self.visit_tuple(visitor)
}
fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize;
#[inline]
fn visit_enum_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error>
where T: Serialize
{
self.visit_tuple_elt(value)
}
fn visit_map<V>(&mut self, visitor: V) -> Result<(), Self::Error>
where V: MapVisitor;
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize;
#[inline]
fn visit_named_map<V>(&mut self,
_name: &'static str,
@@ -167,18 +199,38 @@ pub trait Serializer {
}
#[inline]
fn visit_enum_map<V>(&mut self,
_name: &'static str,
_variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
fn visit_named_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize,
{
self.visit_map(visitor)
self.visit_map_elt(key, value)
}
fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
#[inline]
fn visit_enum_map<V>(&mut self,
_name: &'static str,
variant: &'static str,
visitor: V) -> Result<(), Self::Error>
where V: MapVisitor,
{
self.visit_named_map(variant, visitor)
}
#[inline]
fn visit_enum_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where K: Serialize,
V: Serialize;
V: Serialize,
{
self.visit_named_map_elt(key, value)
}
/// Specify a format string for the serializer.
///
/// The serializer format is used to determine which format
/// specific field attributes should be used with the serializer.
fn format() -> &'static str {
""
}
}
pub trait SeqVisitor {
+24
View File
@@ -0,0 +1,24 @@
[package]
name = "serde_codegen"
version = "0.4.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
repository = "https://github.com/erickt/rust-serde"
build = "build.rs"
[features]
default = ["with-syntex"]
nightly = ["quasi_macros"]
with-syntex = ["quasi/with-syntex", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"]
[build-dependencies]
quasi_codegen = { verision = "*", optional = true }
syntex = { version = "*", optional = true }
[dependencies]
aster = { version = "*", default-features = false }
quasi = { verision = "*", default-features = false }
quasi_macros = { version = "*", optional = true }
syntex = { version = "*", optional = true }
syntex_syntax = { version = "*", optional = true }
+28
View File
@@ -0,0 +1,28 @@
#[cfg(feature = "with-syntex")]
mod inner {
extern crate syntex;
extern crate quasi_codegen;
use std::env;
use std::path::Path;
pub fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let mut registry = syntex::Registry::new();
quasi_codegen::register(&mut registry);
let src = Path::new("src/lib.rs.in");
let dst = Path::new(&out_dir).join("lib.rs");
registry.expand("", &src, &dst).unwrap();
}
}
#[cfg(not(feature = "with-syntex"))]
mod inner {
pub fn main() {}
}
fn main() {
inner::main();
}
+108
View File
@@ -0,0 +1,108 @@
use std::collections::HashMap;
use std::collections::HashSet;
use syntax::ast;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
/// Represents field name information
pub enum FieldNames {
Global(P<ast::Expr>),
Format{
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
default: P<ast::Expr>,
}
}
/// Represents field attribute information
pub struct FieldAttrs {
names: FieldNames,
use_default: bool,
}
impl FieldAttrs {
/// Create a FieldAttr with a single default field name
pub fn new(default_value: bool, name: P<ast::Expr>) -> FieldAttrs {
FieldAttrs {
names: FieldNames::Global(name),
use_default: default_value,
}
}
/// Create a FieldAttr with format specific field names
pub fn new_with_formats(
default_value: bool,
default_name: P<ast::Expr>,
formats: HashMap<P<ast::Expr>, P<ast::Expr>>,
) -> FieldAttrs {
FieldAttrs {
names: FieldNames::Format {
formats: formats,
default: default_name,
},
use_default: default_value,
}
}
/// Return a set of formats that the field has attributes for.
pub fn formats(&self) -> HashSet<P<ast::Expr>> {
match self.names {
FieldNames::Format{ref formats, default: _} => {
let mut set = HashSet::new();
for (fmt, _) in formats.iter() {
set.insert(fmt.clone());
};
set
},
_ => HashSet::new()
}
}
/// Return an expression for the field key name for serialisation.
///
/// The resulting expression assumes that `S` refers to a type
/// that implements `Serializer`.
pub fn serializer_key_expr(self, cx: &ExtCtxt) -> P<ast::Expr> {
match self.names {
FieldNames::Global(x) => x,
FieldNames::Format{formats, default} => {
let arms = formats.iter()
.map(|(fmt, lit)| {
quote_arm!(cx, $fmt => { $lit })
})
.collect::<Vec<_>>();
quote_expr!(cx,
{
match S::format() {
$arms
_ => { $default }
}
})
},
}
}
/// Return the default field name for the field.
pub fn default_key_expr(&self) -> &P<ast::Expr> {
match self.names {
FieldNames::Global(ref expr) => expr,
FieldNames::Format{formats: _, ref default} => default
}
}
/// Return the field name for the field in the specified format.
pub fn key_expr(&self, format: &P<ast::Expr>) -> &P<ast::Expr> {
match self.names {
FieldNames::Global(ref expr) =>
expr,
FieldNames::Format{ref formats, ref default} =>
formats.get(format).unwrap_or(default)
}
}
/// Predicate for using a field's default value
pub fn use_default(&self) -> bool {
self.use_default
}
}
@@ -1,4 +1,9 @@
use std::collections::HashSet;
use aster;
use syntax::ast::{
self,
Ident,
MetaItem,
Item,
@@ -6,23 +11,32 @@ use syntax::ast::{
StructDef,
EnumDef,
};
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::owned_slice::OwnedSlice;
use syntax::ptr::P;
use aster;
use attr;
use field;
pub fn expand_derive_deserialize(
cx: &mut ExtCtxt,
span: Span,
_mitem: &MetaItem,
item: &Item,
push: &mut FnMut(P<ast::Item>)
meta_item: &MetaItem,
annotatable: &Annotatable,
push: &mut FnMut(Annotatable)
) {
let item = match *annotatable {
Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
"`derive` may only be applied to structs and enums");
return;
}
};
let builder = aster::AstBuilder::new().span(span);
let generics = match item.node {
@@ -44,7 +58,7 @@ pub fn expand_derive_deserialize(
let body = deserialize_body(
cx,
&builder,
item,
&item,
&impl_generics,
ty.clone(),
);
@@ -62,7 +76,7 @@ pub fn expand_derive_deserialize(
}
).unwrap();
push(impl_item)
push(Annotatable::Item(impl_item))
}
fn deserialize_body(
@@ -154,14 +168,25 @@ fn deserialize_item_struct(
fn deserialize_visitor(
builder: &aster::AstBuilder,
trait_generics: &ast::Generics,
) -> (P<ast::Item>, P<ast::Ty>, P<ast::Expr>) {
if trait_generics.ty_params.is_empty() {
forward_ty_params: Vec<ast::TyParam>,
forward_tys: Vec<P<ast::Ty>>
) -> (P<ast::Item>, P<ast::Ty>, P<ast::Expr>, ast::Generics) {
if trait_generics.ty_params.is_empty() && forward_tys.is_empty() {
(
builder.item().tuple_struct("__Visitor").build(),
builder.ty().id("__Visitor"),
builder.expr().id("__Visitor"),
trait_generics.clone(),
)
} else {
let placeholders : Vec<_> = trait_generics.ty_params.iter()
.map(|t| builder.ty().id(t.ident))
.collect();
let mut trait_generics = trait_generics.clone();
let mut ty_params = forward_ty_params.clone();
ty_params.extend(trait_generics.ty_params.into_vec());
trait_generics.ty_params = OwnedSlice::from_vec(ty_params);
(
builder.item().tuple_struct("__Visitor")
.generics().with(trait_generics.clone()).build()
@@ -174,17 +199,38 @@ fn deserialize_visitor(
builder.ty().path()
.segment("__Visitor").with_generics(trait_generics.clone()).build()
.build(),
builder.expr().call().id("__Visitor")
builder.expr().call()
.path().segment("__Visitor")
.with_tys(forward_tys)
.with_tys(placeholders)
.build().build()
.with_args(
trait_generics.ty_params.iter().map(|_| {
builder.expr().phantom_data()
})
)
.build(),
trait_generics,
)
}
}
fn deserializer_ty_param(builder: &aster::AstBuilder) -> ast::TyParam {
builder.ty_param("__D")
.trait_bound(builder.path()
.global()
.segment("serde").build()
.segment("de").build()
.id("Deserializer")
.build())
.build()
.build()
}
fn deserializer_ty_arg(builder: &aster::AstBuilder) -> P<ast::Ty>{
builder.ty().id("__D")
}
fn deserialize_unit_struct(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
@@ -228,10 +274,13 @@ fn deserialize_tuple_struct(
) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
impl_generics,
);
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,
@@ -245,7 +294,7 @@ fn deserialize_tuple_struct(
quote_expr!(cx, {
$visitor_item
impl $impl_generics ::serde::de::Visitor for $visitor_ty $where_clause {
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
type Value = $ty;
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
@@ -270,7 +319,7 @@ fn deserialize_seq(
let name = builder.id(format!("__field{}", i));
quote_stmt!(cx,
let $name = match try!(visitor.visit()) {
Some(value) => value,
Some(value) => { value },
None => {
return Err(::serde::de::Error::end_of_stream_error());
}
@@ -303,10 +352,13 @@ fn deserialize_struct(
) -> P<ast::Expr> {
let where_clause = &impl_generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
impl_generics,
);
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 (field_visitor, visit_map_expr) = deserialize_struct_visitor(
cx,
@@ -322,7 +374,7 @@ fn deserialize_struct(
$visitor_item
impl $impl_generics ::serde::de::Visitor for $visitor_ty $where_clause {
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
type Value = $ty;
#[inline]
@@ -353,7 +405,10 @@ fn deserialize_item_enum(
cx,
builder,
enum_def.variants.iter()
.map(|variant| builder.expr().str(variant.node.name))
.map(|variant|
attr::FieldAttrs::new(
true,
builder.expr().str(variant.node.name)))
.collect()
);
@@ -378,17 +433,20 @@ fn deserialize_item_enum(
})
.collect();
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
impl_generics,
);
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
deserialize_visitor(
builder,
impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
quote_expr!(cx, {
$variant_visitor
$visitor_item
impl $impl_generics ::serde::de::EnumVisitor for $visitor_ty $where_clause {
impl $visitor_generics ::serde::de::EnumVisitor for $visitor_ty $where_clause {
type Value = $ty;
fn visit<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
@@ -457,10 +515,13 @@ fn deserialize_tuple_variant(
) -> P<ast::Expr> {
let where_clause = &generics.where_clause;
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
generics,
);
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
deserialize_visitor(
builder,
generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
let visit_seq_expr = deserialize_seq(
cx,
@@ -472,7 +533,7 @@ fn deserialize_tuple_variant(
quote_expr!(cx, {
$visitor_item
impl $generics ::serde::de::Visitor for $visitor_ty $where_clause {
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
type Value = $ty;
fn visit_seq<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
@@ -504,17 +565,20 @@ fn deserialize_struct_variant(
builder.path().id(type_ident).id(variant_ident).build(),
);
let (visitor_item, visitor_ty, visitor_expr) = deserialize_visitor(
builder,
generics,
);
let (visitor_item, visitor_ty, visitor_expr, visitor_generics) =
deserialize_visitor(
builder,
generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
quote_expr!(cx, {
$field_visitor
$visitor_item
impl $generics ::serde::de::Visitor for $visitor_ty $where_clause {
impl $visitor_generics ::serde::de::Visitor for $visitor_ty $where_clause {
type Value = $ty;
fn visit_map<__V>(&mut self, mut visitor: __V) -> ::std::result::Result<$ty, __V::Error>
@@ -531,10 +595,10 @@ fn deserialize_struct_variant(
fn deserialize_field_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
field_exprs: Vec<P<ast::Expr>>,
field_attrs: Vec<attr::FieldAttrs>,
) -> Vec<P<ast::Item>> {
// Create the field names for the fields.
let field_idents: Vec<ast::Ident> = (0 .. field_exprs.len())
let field_idents: Vec<ast::Ident> = (0 .. field_attrs.len())
.map(|i| builder.id(format!("__field{}", i)))
.collect();
@@ -548,43 +612,106 @@ fn deserialize_field_visitor(
)
.build();
// A set of all the formats that have specialized field attributes
let formats = field_attrs.iter()
.fold(HashSet::new(), |mut set, field_expr| {
set.extend(field_expr.formats());
set
});
// Match arms to extract a field from a string
let field_arms: Vec<_> = field_idents.iter()
.zip(field_exprs.into_iter())
let default_field_arms: Vec<_> = field_idents.iter()
.zip(field_attrs.iter())
.map(|(field_ident, field_expr)| {
quote_arm!(cx, $field_expr => { Ok(__Field::$field_ident) })
let expr = field_expr.default_key_expr();
quote_arm!(cx, $expr => { Ok(__Field::$field_ident) })
})
.collect();
vec![
field_enum,
let body = if formats.is_empty() {
// No formats specific attributes, so no match on format required
quote_expr!(cx,
match value {
$default_field_arms
_ => { Err(::serde::de::Error::unknown_field_error(value)) }
})
} else {
let field_arms : Vec<_> = formats.iter()
.map(|fmt| {
field_idents.iter()
.zip(field_attrs.iter())
.map(|(field_ident, field_expr)| {
let expr = field_expr.key_expr(fmt);
quote_arm!(cx, $expr => { Ok(__Field::$field_ident) })
})
.collect::<Vec<_>>()
})
.collect();
quote_item!(cx,
impl ::serde::de::Deserialize for __Field {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<__Field, 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) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
match value {
$field_arms
_ => Err(::serde::de::Error::unknown_field_error(value)),
}
let fmt_matches : Vec<_> = formats.iter()
.zip(field_arms.iter())
.map(|(ref fmt, ref arms)| {
quote_arm!(cx, $fmt => {
match value {
$arms
_ => {
Err(::serde::de::Error::unknown_field_error(value))
}
}})
})
.collect();
quote_expr!(cx,
match __D::format() {
$fmt_matches
_ => match value {
$default_field_arms
_ => { Err(::serde::de::Error::unknown_field_error(value)) }
}
})
};
let impl_item = quote_item!(cx,
impl ::serde::de::Deserialize for __Field {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> ::std::result::Result<__Field, D::Error>
where D: ::serde::de::Deserializer,
{
use std::marker::PhantomData;
struct __FieldVisitor<D> {
phantom: PhantomData<D>
}
impl<__D> ::serde::de::Visitor for __FieldVisitor<__D>
where __D: ::serde::de::Deserializer
{
type Value = __Field;
fn visit_str<E>(&mut self, value: &str) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
$body
}
deserializer.visit(__FieldVisitor)
fn visit_bytes<E>(&mut self, value: &[u8]) -> ::std::result::Result<__Field, E>
where E: ::serde::de::Error,
{
// TODO: would be better to generate a byte string literal match
match ::std::str::from_utf8(value) {
Ok(s) => self.visit_str(s),
_ => Err(::serde::de::Error::syntax_error()),
}
}
}
deserializer.visit(
__FieldVisitor::<D>{ phantom: PhantomData })
}
).unwrap(),
]
}
).unwrap();
vec![field_enum, impl_item]
}
fn deserialize_struct_visitor(
@@ -596,7 +723,7 @@ fn deserialize_struct_visitor(
let field_visitor = deserialize_field_visitor(
cx,
builder,
field::struct_field_strs(cx, builder, struct_def, field::Direction::Deserialize),
field::struct_field_attrs(cx, builder, struct_def),
);
let visit_map_expr = deserialize_map(
@@ -637,25 +764,36 @@ fn deserialize_map(
.collect();
let extract_values: Vec<P<ast::Stmt>> = field_names.iter()
.zip(struct_def.fields.iter())
.map(|(field_name, field)| {
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) {
.zip(field::struct_field_attrs(cx, builder, struct_def).iter())
.map(|(field_name, field_attr)| {
let missing_expr = if field_attr.use_default() {
quote_expr!(cx, ::std::default::Default::default())
} else {
quote_expr!(cx, try!(visitor.missing_field($name_str)))
let formats = field_attr.formats();
let arms : Vec<_> = formats.iter()
.map(|format| {
let key_expr = field_attr.key_expr(format);
quote_arm!(cx, $format => { $key_expr })
})
.collect();
let default = field_attr.default_key_expr();
if arms.is_empty() {
quote_expr!(cx, try!(visitor.missing_field($default)))
} else {
quote_expr!(
cx,
try!(visitor.missing_field(
match __D::format() {
$arms
_ => { $default }
})))
}
};
quote_stmt!(cx,
let $field_name = match $field_name {
Some($field_name) => $field_name,
None => $missing_expr,
None => $missing_expr
};
).unwrap()
})
+133
View File
@@ -0,0 +1,133 @@
use std::collections::HashMap;
use aster;
use syntax::ast;
use syntax::attr;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
use attr::FieldAttrs;
enum Rename<'a> {
None,
Global(&'a ast::Lit),
Format(HashMap<P<ast::Expr>, &'a ast::Lit>)
}
fn rename<'a>(
builder: &aster::AstBuilder,
mi: &'a ast::MetaItem,
) -> Option<Rename<'a>>
{
match mi.node {
ast::MetaNameValue(ref n, ref lit) => {
if n == &"rename" {
Some(Rename::Global(lit))
} else {
None
}
},
ast::MetaList(ref n, ref items) => {
if n == &"rename" {
let mut m = HashMap::new();
m.extend(
items.iter()
.filter_map(
|item|
match item.node {
ast::MetaNameValue(ref n, ref lit) =>
Some((builder.expr().str(n),
lit)),
_ => None
}));
Some(Rename::Format(m))
} else {
None
}
},
_ => None
}
}
fn default_value(mi: &ast::MetaItem) -> bool {
if let ast::MetaItem_::MetaWord(ref n) = mi.node {
n == &"default"
} else {
false
}
}
fn field_attrs<'a>(
builder: &aster::AstBuilder,
field: &'a ast::StructField,
) -> (Rename<'a>, bool) {
field.node.attrs.iter()
.find(|sa| {
if let ast::MetaList(ref n, _) = sa.node.value.node {
n == &"serde"
} else {
false
}
})
.and_then(|sa| {
if let ast::MetaList(_, ref vals) = sa.node.value.node {
attr::mark_used(&sa);
Some((vals.iter()
.fold(None, |v, mi| v.or(rename(builder, mi)))
.unwrap_or(Rename::None),
vals.iter().any(|mi| default_value(mi))))
} else {
Some((Rename::None, false))
}
})
.unwrap_or((Rename::None, false))
}
pub fn struct_field_attrs(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
struct_def: &ast::StructDef,
) -> Vec<FieldAttrs> {
struct_def.fields.iter()
.map(|field| {
match field_attrs(builder, field) {
(Rename::Global(rename), default_value) =>
FieldAttrs::new(
default_value,
builder.expr().build_lit(P(rename.clone()))),
(Rename::Format(renames), default_value) => {
let mut res = HashMap::new();
res.extend(
renames.into_iter()
.map(|(k,v)|
(k, builder.expr().build_lit(P(v.clone())))));
FieldAttrs::new_with_formats(
default_value,
default_field_name(cx, builder, field.node.kind),
res)
},
(Rename::None, default_value) => {
FieldAttrs::new(
default_value,
default_field_name(cx, builder, field.node.kind))
}
}
})
.collect()
}
fn default_field_name(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
kind: ast::StructFieldKind,
) -> P<ast::Expr> {
match kind {
ast::NamedField(name, _) => {
builder.expr().str(name)
}
ast::UnnamedField(_) => {
cx.bug("struct has named and unnamed fields")
}
}
}
+73
View File
@@ -0,0 +1,73 @@
#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))]
#![cfg_attr(not(feature = "with-syntex"), plugin(quasi_macros))]
extern crate aster;
extern crate quasi;
#[cfg(feature = "with-syntex")]
extern crate syntex;
#[cfg(feature = "with-syntex")]
extern crate syntex_syntax as syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate syntax;
#[cfg(not(feature = "with-syntex"))]
extern crate rustc;
#[cfg(feature = "with-syntex")]
include!(concat!(env!("OUT_DIR"), "/lib.rs"));
#[cfg(not(feature = "with-syntex"))]
include!("lib.rs.in");
#[cfg(feature = "with-syntex")]
pub fn register(reg: &mut syntex::Registry) {
use syntax::{ast, fold};
reg.add_attr("feature(custom_derive)");
reg.add_attr("feature(custom_attribute)");
reg.add_decorator("derive_Serialize", ser::expand_derive_serialize);
reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize);
reg.add_post_expansion_pass(strip_attributes);
/// Strip the serde attributes from the crate.
#[cfg(feature = "with-syntex")]
fn strip_attributes(krate: ast::Crate) -> ast::Crate {
/// Helper folder that strips the serde attributes after the extensions have been expanded.
struct StripAttributeFolder;
impl fold::Folder for StripAttributeFolder {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
match attr.node.value.node {
ast::MetaList(ref n, _) if n == &"serde" => { return None; }
_ => {}
}
Some(attr)
}
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
fold::noop_fold_mac(mac, self)
}
}
fold::Folder::fold_crate(&mut StripAttributeFolder, krate)
}
}
#[cfg(not(feature = "with-syntex"))]
pub fn register(reg: &mut rustc::plugin::Registry) {
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Serialize"),
syntax::ext::base::MultiDecorator(
Box::new(ser::expand_derive_serialize)));
reg.register_syntax_extension(
syntax::parse::token::intern("derive_Deserialize"),
syntax::ext::base::MultiDecorator(
Box::new(de::expand_derive_deserialize)));
}
+4
View File
@@ -0,0 +1,4 @@
mod attr;
mod de;
mod field;
mod ser;
@@ -1,3 +1,5 @@
use aster;
use syntax::ast::{
Ident,
MetaItem,
@@ -7,21 +9,29 @@ use syntax::ast::{
};
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use aster;
use field::{Direction, struct_field_strs};
use field::struct_field_attrs;
pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
span: Span,
_mitem: &MetaItem,
item: &Item,
push: &mut FnMut(P<ast::Item>)
meta_item: &MetaItem,
annotatable: &Annotatable,
push: &mut FnMut(Annotatable)
) {
let item = match *annotatable {
Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
"`derive` may only be applied to structs and enums");
return;
}
};
let builder = aster::AstBuilder::new().span(span);
let generics = match item.node {
@@ -43,9 +53,12 @@ pub fn expand_derive_serialize(
let body = serialize_body(
cx,
&builder,
item,
&item,
&impl_generics,
ty.clone(),
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
);
let where_clause = &impl_generics.where_clause;
@@ -61,7 +74,7 @@ pub fn expand_derive_serialize(
}
).unwrap();
push(impl_item)
push(Annotatable::Item(impl_item))
}
fn serialize_body(
@@ -88,6 +101,7 @@ fn serialize_body(
builder,
item.ident,
impl_generics,
ty,
enum_def,
)
}
@@ -166,15 +180,11 @@ fn serialize_tuple_struct(
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
let value_ty = builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty);
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
value_ty,
ty.clone(),
ty,
fields,
impl_generics,
);
@@ -187,6 +197,7 @@ fn serialize_tuple_struct(
serializer.visit_named_seq($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
@@ -200,15 +211,11 @@ fn serialize_struct(
struct_def: &StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> {
let value_ty = builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone());
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
builder,
value_ty,
ty.clone(),
ty,
struct_def,
impl_generics,
fields.iter().map(|field| quote_expr!(cx, &self.value.$field)),
@@ -222,6 +229,7 @@ fn serialize_struct(
serializer.visit_named_map($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
@@ -231,6 +239,7 @@ fn serialize_item_enum(
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
enum_def: &ast::EnumDef,
) -> P<ast::Expr> {
let arms: Vec<ast::Arm> = enum_def.variants.iter()
@@ -240,6 +249,7 @@ fn serialize_item_enum(
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
)
})
@@ -257,6 +267,7 @@ fn serialize_variant(
builder: &aster::AstBuilder,
type_ident: Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
variant: &ast::Variant,
) -> ast::Arm {
let type_name = builder.expr().str(type_ident);
@@ -276,7 +287,7 @@ fn serialize_variant(
$type_name,
$variant_name,
)
},
}
)
}
ast::TupleVariantKind(ref args) => {
@@ -295,6 +306,7 @@ fn serialize_variant(
type_name,
variant_name,
generics,
ty,
args,
fields,
);
@@ -330,6 +342,7 @@ fn serialize_variant(
type_name,
variant_name,
generics,
ty,
struct_def,
fields,
);
@@ -345,10 +358,11 @@ fn serialize_tuple_variant(
type_name: P<ast::Expr>,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
args: &[ast::VariantArg],
fields: Vec<Ident>,
) -> P<ast::Expr> {
let value_ty = builder.ty().tuple()
let variant_ty = builder.ty().tuple()
.with_tys(
args.iter().map(|arg| {
builder.ty()
@@ -359,6 +373,15 @@ fn serialize_tuple_variant(
)
.build();
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
structure_ty,
variant_ty,
args.len(),
generics,
);
let value_expr = builder.expr().tuple()
.with_exprs(
fields.iter().map(|field| {
@@ -369,20 +392,13 @@ fn serialize_tuple_variant(
)
.build();
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
value_ty,
args.len(),
generics,
);
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_enum_seq($type_name, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
@@ -393,6 +409,7 @@ fn serialize_struct_variant(
type_name: P<ast::Expr>,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
struct_def: &ast::StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> {
@@ -420,6 +437,7 @@ fn serialize_struct_variant(
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
builder,
structure_ty,
value_ty,
struct_def,
generics,
@@ -436,6 +454,7 @@ fn serialize_struct_variant(
serializer.visit_enum_map($type_name, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
@@ -443,7 +462,8 @@ fn serialize_struct_variant(
fn serialize_tuple_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
value_ty: P<ast::Ty>,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
fields: usize,
generics: &ast::Generics
) -> (P<ast::Item>, P<ast::Item>) {
@@ -456,7 +476,7 @@ fn serialize_tuple_struct_visitor(
quote_arm!(cx,
$i => {
self.state += 1;
let v = try!(serializer.visit_seq_elt(&$expr));
let v = try!(serializer.visit_named_seq_elt(&$expr));
Ok(Some(v))
}
)
@@ -474,11 +494,19 @@ fn serialize_tuple_struct_visitor(
.strip_bounds()
.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,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $value_ty,
value: $variant_ty,
_structure_ty: $structure_ty,
}
).unwrap(),
@@ -488,11 +516,11 @@ fn serialize_tuple_struct_visitor(
$where_clause {
#[inline]
fn visit<S>(&mut self, serializer: &mut S) -> ::std::result::Result<Option<()>, S::Error>
where S: ::serde::ser::Serializer,
where S: ::serde::ser::Serializer
{
match self.state {
$arms
_ => Ok(None),
_ => Ok(None)
}
}
@@ -508,7 +536,8 @@ fn serialize_tuple_struct_visitor(
fn serialize_struct_visitor<I>(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
value_ty: P<ast::Ty>,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
struct_def: &StructDef,
generics: &ast::Generics,
value_exprs: I,
@@ -517,19 +546,20 @@ fn serialize_struct_visitor<I>(
{
let len = struct_def.fields.len();
let key_exprs = struct_field_strs(cx, builder, struct_def, Direction::Serialize);
let field_attrs = struct_field_attrs(cx, builder, struct_def);
let arms: Vec<ast::Arm> = key_exprs.iter()
let arms: Vec<ast::Arm> = field_attrs.into_iter()
.zip(value_exprs)
.enumerate()
.map(|(i, (key_expr, value_expr))| {
.map(|(i, (field, value_expr))| {
let key_expr = field.serializer_key_expr(cx);
quote_arm!(cx,
$i => {
self.state += 1;
Ok(
Some(
try!(
serializer.visit_map_elt(
serializer.visit_named_map_elt(
$key_expr,
$value_expr,
)
@@ -552,11 +582,19 @@ fn serialize_struct_visitor<I>(
.strip_bounds()
.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,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $value_ty,
value: $variant_ty,
_structure_ty: $structure_ty,
}
).unwrap(),
@@ -571,7 +609,7 @@ fn serialize_struct_visitor<I>(
{
match self.state {
$arms
_ => Ok(None),
_ => Ok(None)
}
}
+10 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_macros"
version = "0.3.3"
version = "0.4.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
@@ -10,7 +10,13 @@ repository = "https://github.com/erickt/rust-serde"
name = "serde_macros"
plugin = true
[features]
default = ["serde/nightly"]
[dependencies]
aster = "*"
quasi = "*"
quasi_macros = "*"
serde_codegen = { version = "*", path = "../serde_codegen", default-features = false, features = ["nightly"] }
[dev-dependencies]
num = "*"
rustc-serialize = "*"
serde = { version = "*", path = "../serde" }
+9
View File
@@ -0,0 +1,9 @@
#![feature(custom_attribute, custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate num;
extern crate rustc_serialize;
extern crate serde;
extern crate test;
include!("../../serde_tests/benches/bench.rs.in");
-96
View File
@@ -1,96 +0,0 @@
use syntax::ast;
use syntax::attr;
use syntax::ext::base::ExtCtxt;
use syntax::ptr::P;
use aster;
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 {
n == &"serde"
} else {
false
}
})
.and_then(|sa| {
if let ast::MetaList(_, ref vals) = sa.node.value.node {
attr::mark_used(&sa);
vals.iter().fold(None, |v, mi| {
if let ast::MetaNameValue(ref n, ref lit) = mi.node {
if n == &"rename" || n == &dir_attr {
Some(lit)
} else {
v
}
} else {
v
}
})
} else {
None
}
})
}
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_rename(field, &direction) {
Some(rename) => builder.expr().build_lit(P(rename.clone())),
None => {
match field.node.kind {
ast::NamedField(name, _) => {
builder.expr().str(name)
}
ast::UnnamedField(_) => {
cx.bug("struct has named and unnamed fields")
}
}
}
}
})
.collect()
}
pub fn default_value(field: &ast::StructField) -> bool {
field.node.attrs.iter()
.any(|sa| {
if let ast::MetaItem_::MetaList(ref n, ref vals) = sa.node.value.node {
if n == &"serde" {
attr::mark_used(&sa);
vals.iter()
.map(|mi|
if let ast::MetaItem_::MetaWord(ref n) = mi.node {
n == &"default"
} else {
false
})
.any(|x| x)
} else {
false
}
}
else {
false
}
})
}
+4 -21
View File
@@ -1,27 +1,10 @@
#![feature(custom_derive, plugin, plugin_registrar, rustc_private, unboxed_closures)]
#![plugin(quasi_macros)]
#![feature(plugin_registrar, rustc_private)]
extern crate aster;
extern crate quasi;
extern crate serde_codegen;
extern crate rustc;
extern crate syntax;
use syntax::ext::base::Decorator;
use syntax::parse::token;
use rustc::plugin::Registry;
mod ser;
mod de;
mod field;
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
token::intern("derive_Serialize"),
Decorator(Box::new(ser::expand_derive_serialize)));
reg.register_syntax_extension(
token::intern("derive_Deserialize"),
Decorator(Box::new(de::expand_derive_deserialize)));
pub fn plugin_registrar(reg: &mut rustc::plugin::Registry) {
serde_codegen::register(reg);
}
+7
View File
@@ -0,0 +1,7 @@
#![feature(test, custom_attribute, custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
extern crate test;
include!("../../serde_tests/tests/test.rs.in");
+30
View File
@@ -0,0 +1,30 @@
[package]
name = "serde_tests"
version = "0.4.3"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
repository = "https://github.com/serde-rs/serde"
documentation = "http://serde-rs.github.io/serde/serde"
readme = "README.md"
keywords = ["serialization"]
build = "build.rs"
[build-dependencies]
syntex = { version = "*", optional = true }
syntex_syntax = { version = "*" }
serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-syntex"] }
[dev-dependencies]
num = "*"
rustc-serialize = "*"
serde = { version = "*", path = "../serde" }
syntex = "*"
[[test]]
name = "test"
path = "tests/test.rs"
[[bench]]
name = "bench"
path = "benches/bench.rs"
+8
View File
@@ -0,0 +1,8 @@
#![feature(test)]
extern crate num;
extern crate rustc_serialize;
extern crate serde;
extern crate test;
include!(concat!(env!("OUT_DIR"), "/bench.rs"));
+5
View File
@@ -0,0 +1,5 @@
mod bench_enum;
mod bench_log;
mod bench_map;
mod bench_struct;
mod bench_vec;
@@ -1,18 +1,8 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate rustc_serialize;
extern crate test;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde;
use serde::de::{Deserializer, Deserialize};
use Animal::{Dog, Frog};
//////////////////////////////////////////////////////////////////////////////
#[derive(Clone, PartialEq, Debug, RustcDecodable, Deserialize)]
@@ -408,7 +398,7 @@ mod deserializer {
#[bench]
fn bench_decoder_dog(b: &mut Bencher) {
b.iter(|| {
let animal = Dog;
let animal = Animal::Dog;
let mut d = decoder::AnimalDecoder::new(animal.clone());
let value: Animal = Decodable::decode(&mut d).unwrap();
@@ -420,7 +410,7 @@ fn bench_decoder_dog(b: &mut Bencher) {
#[bench]
fn bench_decoder_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Frog("Henry".to_string(), 349);
let animal = Animal::Frog("Henry".to_string(), 349);
let mut d = decoder::AnimalDecoder::new(animal.clone());
let value: Animal = Decodable::decode(&mut d).unwrap();
@@ -432,7 +422,7 @@ fn bench_decoder_frog(b: &mut Bencher) {
#[bench]
fn bench_deserializer_dog(b: &mut Bencher) {
b.iter(|| {
let animal = Dog;
let animal = Animal::Dog;
let mut d = deserializer::AnimalDeserializer::new(animal.clone());
let value: Animal = Deserialize::deserialize(&mut d).unwrap();
@@ -444,7 +434,7 @@ fn bench_deserializer_dog(b: &mut Bencher) {
#[bench]
fn bench_deserializer_frog(b: &mut Bencher) {
b.iter(|| {
let animal = Frog("Henry".to_string(), 349);
let animal = Animal::Frog("Henry".to_string(), 349);
let mut d = deserializer::AnimalDeserializer::new(animal.clone());
let value: Animal = Deserialize::deserialize(&mut d).unwrap();
@@ -1,20 +1,14 @@
#![feature(custom_derive, collections, plugin, test)]
#![allow(non_camel_case_types)]
#![plugin(serde_macros)]
extern crate num;
extern crate rustc_serialize;
extern crate serde;
extern crate test;
use std::io::{self, Read, Write};
use num::FromPrimitive;
use test::Bencher;
use rustc_serialize;
use serde::de::{self, Deserialize, Deserializer};
use serde::json::ser::escape_str;
use serde::json;
use serde::ser::{self, Serialize, Serializer};
use std::str::FromStr;
use rustc_serialize::Encodable;
@@ -31,6 +25,7 @@ struct Http {
request_uri: String,
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum HttpProtocol {
HTTP_PROTOCOL_UNKNOWN,
@@ -53,6 +48,11 @@ impl rustc_serialize::Decodable for HttpProtocol {
}
}
impl FromStr for HttpProtocol {
type Err = ();
fn from_str(_s: &str) -> Result<HttpProtocol, ()> { unimplemented!() }
}
impl FromPrimitive for HttpProtocol {
fn from_i64(i: i64) -> Option<HttpProtocol> {
FromPrimitive::from_u64(i as u64)
@@ -86,6 +86,7 @@ impl de::Deserialize for HttpProtocol {
}
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum HttpMethod {
METHOD_UNKNOWN,
@@ -101,6 +102,11 @@ enum HttpMethod {
PATCH,
}
impl FromStr for HttpMethod {
type Err = ();
fn from_str(_s: &str) -> Result<HttpMethod, ()> { unimplemented!() }
}
impl FromPrimitive for HttpMethod {
fn from_i64(i: i64) -> Option<HttpMethod> {
FromPrimitive::from_u64(i as u64)
@@ -157,6 +163,7 @@ impl de::Deserialize for HttpMethod {
}
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum CacheStatus {
CACHESTATUS_UNKNOWN,
@@ -165,6 +172,11 @@ enum CacheStatus {
Hit,
}
impl FromStr for CacheStatus {
type Err = ();
fn from_str(_s: &str) -> Result<CacheStatus, ()> { unimplemented!() }
}
impl FromPrimitive for CacheStatus {
fn from_i64(i: i64) -> Option<CacheStatus> {
FromPrimitive::from_u64(i as u64)
@@ -222,6 +234,7 @@ struct Origin {
protocol: OriginProtocol,
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum OriginProtocol {
ORIGIN_PROTOCOL_UNKNOWN,
@@ -229,6 +242,11 @@ enum OriginProtocol {
HTTPS,
}
impl FromStr for OriginProtocol {
type Err = ();
fn from_str(_s: &str) -> Result<OriginProtocol, ()> { unimplemented!() }
}
impl FromPrimitive for OriginProtocol {
fn from_i64(i: i64) -> Option<OriginProtocol> {
FromPrimitive::from_u64(i as u64)
@@ -277,6 +295,7 @@ impl de::Deserialize for OriginProtocol {
}
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum ZonePlan {
ZONEPLAN_UNKNOWN,
@@ -286,6 +305,11 @@ enum ZonePlan {
ENT,
}
impl FromStr for ZonePlan {
type Err = ();
fn from_str(_s: &str) -> Result<ZonePlan, ()> { unimplemented!() }
}
impl FromPrimitive for ZonePlan {
fn from_i64(i: i64) -> Option<ZonePlan> {
FromPrimitive::from_u64(i as u64)
@@ -596,6 +620,11 @@ enum Country {
ZW,
}
impl FromStr for Country {
type Err = ();
fn from_str(_s: &str) -> Result<Country, ()> { unimplemented!() }
}
impl FromPrimitive for Country {
fn from_i64(i: i64) -> Option<Country> {
FromPrimitive::from_u64(i as u64)
@@ -987,12 +1016,20 @@ impl MyMemWriter0 {
impl Write for MyMemWriter0 {
#[cfg(feature = "nightly")]
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buf.push_all(buf);
Ok(buf.len())
}
#[cfg(not(feature = "nightly"))]
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buf.extend(buf.iter().cloned());
Ok(buf.len())
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
@@ -1,16 +1,10 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate rustc_serialize;
extern crate test;
use std::fmt::Debug;
use std::collections::HashMap;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde;
use serde::de::{Deserializer, Deserialize};
//////////////////////////////////////////////////////////////////////////////
@@ -1,15 +1,9 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate rustc_serialize;
extern crate test;
use std::collections::HashMap;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde;
use serde::de::{Deserializer, Deserialize};
//////////////////////////////////////////////////////////////////////////////
@@ -34,8 +28,6 @@ pub struct Outer {
pub enum Error {
EndOfStream,
SyntaxError,
UnexpectedName,
ConversionError,
MissingField,
OtherError,
}
@@ -1,15 +1,9 @@
#![feature(plugin, test)]
#![plugin(serde_macros)]
extern crate serde;
extern crate rustc_serialize;
extern crate test;
use std::fmt::Debug;
use test::Bencher;
use rustc_serialize::{Decoder, Decodable};
use serde;
use serde::de::{Deserializer, Deserialize};
//////////////////////////////////////////////////////////////////////////////
+22
View File
@@ -0,0 +1,22 @@
extern crate syntex;
extern crate serde_codegen;
use std::env;
use std::path::Path;
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
for &(src, dst) in &[
("tests/test.rs.in", "test.rs"),
("benches/bench.rs.in", "bench.rs"),
] {
let src = Path::new(src);
let dst = Path::new(&out_dir).join(dst);
let mut registry = syntex::Registry::new();
serde_codegen::register(&mut registry);
registry.expand("", &src, &dst).unwrap();
}
}
+3
View File
@@ -0,0 +1,3 @@
extern crate serde;
include!(concat!(env!("OUT_DIR"), "/test.rs"));
+7
View File
@@ -0,0 +1,7 @@
mod test_annotations;
mod test_bytes;
mod test_de;
mod test_json;
mod test_json_builder;
mod test_macros;
mod test_ser;
@@ -1,9 +1,3 @@
#![feature(custom_attribute, custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate test;
extern crate serde;
use serde::json;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -21,12 +15,22 @@ struct Rename {
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct DirectionRename {
struct FormatRename {
a1: i32,
#[serde(rename_serialize="a3", rename_deserialize="a4")]
#[serde(rename(xml= "a4", json="a5"))]
a2: i32,
}
#[derive(Debug, PartialEq, Deserialize, Serialize)]
enum SerEnum<A> {
Map {
a: i8,
#[serde(rename(xml= "c", json="d"))]
b: A,
},
}
#[test]
fn test_default() {
let deserialized_value: Default = json::from_str(&"{\"a1\":1,\"a2\":2}").unwrap();
@@ -47,11 +51,23 @@ fn test_rename() {
}
#[test]
fn test_direction_rename() {
let value = DirectionRename { a1: 1, a2: 2 };
fn test_format_rename() {
let value = FormatRename { a1: 1, a2: 2 };
let serialized_value = json::to_string(&value).unwrap();
assert_eq!(serialized_value, "{\"a1\":1,\"a3\":2}");
assert_eq!(serialized_value, "{\"a1\":1,\"a5\":2}");
let deserialized_value = json::from_str("{\"a1\":1,\"a4\":2}").unwrap();
let deserialized_value = json::from_str("{\"a1\":1,\"a5\":2}").unwrap();
assert_eq!(value, deserialized_value);
}
#[test]
fn test_enum_format_rename() {
let s1 = String::new();
let value = SerEnum::Map { a: 0i8, b: s1 };
let serialized_value = json::to_string(&value).unwrap();
let ans = "{\"Map\":{\"a\":0,\"d\":\"\"}}";
assert_eq!(serialized_value, ans);
let deserialized_value = json::from_str(ans).unwrap();
assert_eq!(value, deserialized_value);
}
@@ -1,9 +1,4 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate test;
extern crate serde;
use serde;
use serde::Serialize;
use serde::bytes::{ByteBuf, Bytes};
use serde::json;
@@ -1,9 +1,3 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate test;
extern crate serde;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::iter;
use std::vec;
@@ -652,6 +646,46 @@ declare_tests! {
Token::SeqEnd,
],
}
test_array {
[0; 0] => vec![
Token::Unit,
],
[0; 0] => vec![
Token::SeqStart(0),
Token::SeqEnd,
],
([0; 0], [1], [2, 3]) => vec![
Token::SeqStart(3),
Token::SeqSep,
Token::SeqStart(0),
Token::SeqEnd,
Token::SeqSep,
Token::SeqStart(1),
Token::SeqSep,
Token::I32(1),
Token::SeqEnd,
Token::SeqSep,
Token::SeqStart(2),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
Token::SeqEnd,
],
[0; 0] => vec![
Token::Name("Anything"),
Token::Unit,
],
[0; 0] => vec![
Token::Name("Anything"),
Token::SeqStart(0),
Token::SeqEnd,
],
}
test_tuple {
(1,) => vec![
Token::SeqStart(1),
@@ -1,9 +1,3 @@
#![feature(custom_derive, plugin, test, custom_attribute)]
#![plugin(serde_macros)]
extern crate test;
extern crate serde;
use std::fmt::Debug;
use std::collections::BTreeMap;
@@ -708,6 +702,8 @@ fn test_parse_number_errors() {
("1e", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
("1a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 2)),
("777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 20)),
("1e777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 22)),
]);
}
@@ -1024,7 +1020,7 @@ fn test_missing_field() {
fn test_missing_renamed_field() {
#[derive(Debug, PartialEq, Deserialize)]
struct Foo {
#[serde(rename_deserialize="y")]
#[serde(rename="y")]
x: Option<u32>,
}
@@ -1042,3 +1038,44 @@ fn test_missing_renamed_field() {
))).unwrap();
assert_eq!(value, Foo { x: Some(5) });
}
#[test]
fn test_missing_fmt_renamed_field() {
#[derive(Debug, PartialEq, Deserialize)]
struct Foo {
#[serde(rename(json="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) });
}
#[test]
fn test_find_path() {
let obj: Value = json::from_str(r#"{"x": {"a": 1}, "y": 2}"#).unwrap();
assert!(obj.find_path(&["x", "a"]).unwrap() == &Value::U64(1));
assert!(obj.find_path(&["y"]).unwrap() == &Value::U64(2));
assert!(obj.find_path(&["z"]).is_none());
}
#[test]
fn test_lookup() {
let obj: Value = json::from_str(r#"{"x": {"a": 1}, "y": 2}"#).unwrap();
assert!(obj.lookup("x.a").unwrap() == &Value::U64(1));
assert!(obj.lookup("y").unwrap() == &Value::U64(2));
assert!(obj.lookup("z").is_none());
}
@@ -1,5 +1,3 @@
extern crate serde;
use std::collections::BTreeMap;
use serde::json::value::Value;
@@ -1,8 +1,3 @@
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
use std::collections::BTreeMap;
use serde::json::{self, Value};
@@ -128,6 +123,14 @@ enum DeEnum<B, C: /* Trait */, D> /* where D: Trait */ {
},
}
#[derive(Serialize)]
enum Lifetimes<'a> {
LifetimeSeq(&'a i32),
NoLifetimeSeq(i32),
LifetimeMap { a: &'a i32 },
NoLifetimeMap { a: i32 },
}
#[test]
fn test_named_unit() {
let named_unit = NamedUnit;
@@ -443,3 +446,32 @@ fn test_de_enum_map() {
}
);
}
#[test]
fn test_lifetimes() {
let value = 5;
let lifetime = Lifetimes::LifetimeSeq(&value);
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"LifetimeSeq\":[5]}"
);
let lifetime = Lifetimes::NoLifetimeSeq(5);
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"NoLifetimeSeq\":[5]}"
);
let value = 5;
let lifetime = Lifetimes::LifetimeMap { a: &value };
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"LifetimeMap\":{\"a\":5}}"
);
let lifetime = Lifetimes::NoLifetimeMap { a: 5 };
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"NoLifetimeMap\":{\"a\":5}}"
);
}
@@ -1,9 +1,3 @@
#![feature(custom_derive, plugin, test)]
#![plugin(serde_macros)]
extern crate test;
extern crate serde;
use std::vec;
use std::collections::BTreeMap;
@@ -380,6 +374,24 @@ declare_tests! {
Token::SeqEnd,
],
}
test_array {
[0; 0] => vec![
Token::SeqStart(Some(0)),
Token::SeqEnd,
],
[1, 2, 3] => vec![
Token::SeqStart(Some(3)),
Token::SeqSep,
Token::I32(1),
Token::SeqSep,
Token::I32(2),
Token::SeqSep,
Token::I32(3),
Token::SeqEnd,
],
}
test_vec {
Vec::<isize>::new() => vec![
Token::SeqStart(Some(0)),
-686
View File
@@ -1,686 +0,0 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::Hash;
use std::marker::PhantomData;
use std::path;
use std::rc::Rc;
use std::sync::Arc;
use num::FromPrimitive;
use de::{
Deserialize,
Deserializer,
Error,
MapVisitor,
SeqVisitor,
Visitor,
};
///////////////////////////////////////////////////////////////////////////////
pub struct UnitVisitor;
impl Visitor for UnitVisitor {
type Value = ();
fn visit_unit<E>(&mut self) -> Result<(), E>
where E: Error,
{
Ok(())
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), V::Error>
where V: SeqVisitor,
{
visitor.end()
}
}
impl Deserialize for () {
fn deserialize<D>(deserializer: &mut D) -> Result<(), D::Error>
where D: Deserializer,
{
deserializer.visit(UnitVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
struct BoolVisitor;
impl Visitor for BoolVisitor {
type Value = bool;
fn visit_bool<E>(&mut self, v: bool) -> Result<bool, E>
where E: Error,
{
Ok(v)
}
}
impl Deserialize for bool {
fn deserialize<D>(deserializer: &mut D) -> Result<bool, D::Error>
where D: Deserializer,
{
deserializer.visit(BoolVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! impl_deserialize_num_method {
($src_ty:ty, $method:ident, $from_method:ident) => {
#[inline]
fn $method<E>(&mut self, v: $src_ty) -> Result<T, E>
where E: Error,
{
match FromPrimitive::$from_method(v) {
Some(v) => Ok(v),
None => Err(Error::syntax_error()),
}
}
}
}
pub struct PrimitiveVisitor<T> {
marker: PhantomData<T>,
}
impl<T> PrimitiveVisitor<T> {
#[inline]
pub fn new() -> Self {
PrimitiveVisitor {
marker: PhantomData,
}
}
}
impl<
T: Deserialize + FromPrimitive
> Visitor for PrimitiveVisitor<T> {
type Value = T;
impl_deserialize_num_method!(isize, visit_isize, from_isize);
impl_deserialize_num_method!(i8, visit_i8, from_i8);
impl_deserialize_num_method!(i16, visit_i16, from_i16);
impl_deserialize_num_method!(i32, visit_i32, from_i32);
impl_deserialize_num_method!(i64, visit_i64, from_i64);
impl_deserialize_num_method!(usize, visit_usize, from_usize);
impl_deserialize_num_method!(u8, visit_u8, from_u8);
impl_deserialize_num_method!(u16, visit_u16, from_u16);
impl_deserialize_num_method!(u32, visit_u32, from_u32);
impl_deserialize_num_method!(u64, visit_u64, from_u64);
impl_deserialize_num_method!(f32, visit_f32, from_f32);
impl_deserialize_num_method!(f64, visit_f64, from_f64);
}
macro_rules! impl_deserialize_num {
($ty:ty) => {
impl Deserialize for $ty {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<$ty, D::Error>
where D: Deserializer,
{
deserializer.visit(PrimitiveVisitor::new())
}
}
}
}
impl_deserialize_num!(isize);
impl_deserialize_num!(i8);
impl_deserialize_num!(i16);
impl_deserialize_num!(i32);
impl_deserialize_num!(i64);
impl_deserialize_num!(usize);
impl_deserialize_num!(u8);
impl_deserialize_num!(u16);
impl_deserialize_num!(u32);
impl_deserialize_num!(u64);
impl_deserialize_num!(f32);
impl_deserialize_num!(f64);
///////////////////////////////////////////////////////////////////////////////
struct CharVisitor;
impl Visitor for CharVisitor {
type Value = char;
#[inline]
fn visit_char<E>(&mut self, v: char) -> Result<char, E>
where E: Error,
{
Ok(v)
}
#[inline]
fn visit_str<E>(&mut self, v: &str) -> Result<char, E>
where E: Error,
{
let mut iter = v.chars();
if let Some(v) = iter.next() {
if iter.next().is_some() {
Err(Error::syntax_error())
} else {
Ok(v)
}
} else {
Err(Error::end_of_stream_error())
}
}
}
impl Deserialize for char {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<char, D::Error>
where D: Deserializer,
{
deserializer.visit(CharVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
struct StringVisitor;
impl Visitor for StringVisitor {
type Value = String;
fn visit_str<E>(&mut self, v: &str) -> Result<String, E>
where E: Error,
{
Ok(v.to_string())
}
fn visit_string<E>(&mut self, v: String) -> Result<String, E>
where E: Error,
{
Ok(v)
}
}
impl Deserialize for String {
fn deserialize<D>(deserializer: &mut D) -> Result<String, D::Error>
where D: Deserializer,
{
deserializer.visit(StringVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
struct OptionVisitor<T> {
marker: PhantomData<T>,
}
impl<
T: Deserialize,
> Visitor for OptionVisitor<T> {
type Value = Option<T>;
#[inline]
fn visit_none<E>(&mut self) -> Result<Option<T>, E>
where E: Error,
{
Ok(None)
}
#[inline]
fn visit_some<D>(&mut self, deserializer: &mut D) -> Result<Option<T>, D::Error>
where D: Deserializer,
{
Ok(Some(try!(Deserialize::deserialize(deserializer))))
}
}
impl<T> Deserialize for Option<T> where T: Deserialize {
fn deserialize<D>(deserializer: &mut D) -> Result<Option<T>, D::Error>
where D: Deserializer,
{
deserializer.visit_option(OptionVisitor { marker: PhantomData })
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct BTreeSetVisitor<T> {
marker: PhantomData<T>,
}
impl<T> BTreeSetVisitor<T> {
pub fn new() -> Self {
BTreeSetVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for BTreeSetVisitor<T>
where T: Deserialize + Eq + Ord,
{
type Value = BTreeSet<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<BTreeSet<T>, E>
where E: Error,
{
Ok(BTreeSet::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<BTreeSet<T>, V::Error>
where V: SeqVisitor,
{
let mut values = BTreeSet::new();
while let Some(value) = try!(visitor.visit()) {
values.insert(value);
}
try!(visitor.end());
Ok(values)
}
}
impl<T> Deserialize for BTreeSet<T>
where T: Deserialize + Eq + Ord,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeSet<T>, D::Error>
where D: Deserializer,
{
deserializer.visit(BTreeSetVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct HashSetVisitor<T> {
marker: PhantomData<T>,
}
impl<T> HashSetVisitor<T> {
pub fn new() -> Self {
HashSetVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for HashSetVisitor<T>
where T: Deserialize + Eq + Hash,
{
type Value = HashSet<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<HashSet<T>, E>
where E: Error,
{
Ok(HashSet::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<HashSet<T>, V::Error>
where V: SeqVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = HashSet::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.insert(value);
}
try!(visitor.end());
Ok(values)
}
}
impl<T> Deserialize for HashSet<T>
where T: Deserialize + Eq + Hash,
{
fn deserialize<D>(deserializer: &mut D) -> Result<HashSet<T>, D::Error>
where D: Deserializer,
{
deserializer.visit(HashSetVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct VecVisitor<T> {
marker: PhantomData<T>,
}
impl<T> VecVisitor<T> {
pub fn new() -> Self {
VecVisitor {
marker: PhantomData,
}
}
}
impl<T> Visitor for VecVisitor<T> where T: Deserialize {
type Value = Vec<T>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<Vec<T>, E>
where E: Error,
{
Ok(Vec::new())
}
#[inline]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<Vec<T>, V::Error>
where V: SeqVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
try!(visitor.end());
Ok(values)
}
}
impl<T> Deserialize for Vec<T>
where T: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<Vec<T>, D::Error>
where D: Deserializer,
{
deserializer.visit(VecVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
() => {};
($($visitor:ident => ($($name:ident),+),)+) => {
$(
struct $visitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<
$($name: Deserialize,)+
> Visitor for $visitor<$($name,)+> {
type Value = ($($name,)+);
#[inline]
#[allow(non_snake_case)]
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<($($name,)+), V::Error>
where V: SeqVisitor,
{
$(
let $name = match try!(visitor.visit()) {
Some(value) => value,
None => { return Err(Error::end_of_stream_error()); }
};
)+;
try!(visitor.end());
Ok(($($name,)+))
}
}
impl<
$($name: Deserialize),+
> Deserialize for ($($name,)+) {
#[inline]
fn deserialize<D>(deserializer: &mut D) -> Result<($($name,)+), D::Error>
where D: Deserializer,
{
deserializer.visit($visitor { marker: PhantomData })
}
}
)+
}
}
tuple_impls! {
TupleVisitor1 => (T0),
TupleVisitor2 => (T0, T1),
TupleVisitor3 => (T0, T1, T2),
TupleVisitor4 => (T0, T1, T2, T3),
TupleVisitor5 => (T0, T1, T2, T3, T4),
TupleVisitor6 => (T0, T1, T2, T3, T4, T5),
TupleVisitor7 => (T0, T1, T2, T3, T4, T5, T6),
TupleVisitor8 => (T0, T1, T2, T3, T4, T5, T6, T7),
TupleVisitor9 => (T0, T1, T2, T3, T4, T5, T6, T7, T8),
TupleVisitor10 => (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9),
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),
}
///////////////////////////////////////////////////////////////////////////////
pub struct BTreeMapVisitor<K, V> {
marker: PhantomData<BTreeMap<K, V>>,
}
impl<K, V> BTreeMapVisitor<K, V> {
#[inline]
pub fn new() -> Self {
BTreeMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> Visitor for BTreeMapVisitor<K, V>
where K: Deserialize + Ord,
V: Deserialize
{
type Value = BTreeMap<K, V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<BTreeMap<K, V>, E>
where E: Error,
{
Ok(BTreeMap::new())
}
#[inline]
fn visit_map<Visitor>(&mut self, mut visitor: Visitor) -> Result<BTreeMap<K, V>, Visitor::Error>
where Visitor: MapVisitor,
{
let mut values = BTreeMap::new();
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
impl<K, V> Deserialize for BTreeMap<K, V>
where K: Deserialize + Eq + Ord,
V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<BTreeMap<K, V>, D::Error>
where D: Deserializer,
{
deserializer.visit(BTreeMapVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
pub struct HashMapVisitor<K, V> {
marker: PhantomData<HashMap<K, V>>,
}
impl<K, V> HashMapVisitor<K, V> {
#[inline]
pub fn new() -> Self {
HashMapVisitor {
marker: PhantomData,
}
}
}
impl<K, V> Visitor for HashMapVisitor<K, V>
where K: Deserialize + Eq + Hash,
V: Deserialize,
{
type Value = HashMap<K, V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<HashMap<K, V>, E>
where E: Error,
{
Ok(HashMap::new())
}
#[inline]
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<HashMap<K, V>, V_::Error>
where V_: MapVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = HashMap::with_capacity(len);
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
impl<K, V> Deserialize for HashMap<K, V>
where K: Deserialize + Eq + Hash,
V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<HashMap<K, V>, D::Error>
where D: Deserializer,
{
deserializer.visit(HashMapVisitor::new())
}
}
///////////////////////////////////////////////////////////////////////////////
// FIXME: `VecMap` is unstable.
/*
pub struct VecMapVisitor<V> {
marker: PhantomData<VecMap<V>>,
}
impl<V> VecMapVisitor<V> {
#[inline]
pub fn new() -> Self {
VecMapVisitor {
marker: PhantomData,
}
}
}
impl<V> Visitor for VecMapVisitor<V>
where V: Deserialize,
{
type Value = VecMap<V>;
#[inline]
fn visit_unit<E>(&mut self) -> Result<VecMap<V>, E>
where E: Error,
{
Ok(VecMap::new())
}
#[inline]
fn visit_map<V_>(&mut self, mut visitor: V_) -> Result<VecMap<V>, V_::Error>
where V_: MapVisitor,
{
let (len, _) = visitor.size_hint();
let mut values = VecMap::with_capacity(len);
while let Some((key, value)) = try!(visitor.visit()) {
values.insert(key, value);
}
try!(visitor.end());
Ok(values)
}
}
impl<V> Deserialize for VecMap<V>
where V: Deserialize,
{
fn deserialize<D>(deserializer: &mut D) -> Result<VecMap<V>, D::Error>
where D: Deserializer,
{
deserializer.visit(VecMapVisitor::new())
}
}
*/
///////////////////////////////////////////////////////////////////////////////
struct PathBufVisitor;
impl Visitor for PathBufVisitor {
type Value = path::PathBuf;
fn visit_str<E>(&mut self, v: &str) -> Result<path::PathBuf, E>
where E: Error,
{
Ok(From::from(v))
}
fn visit_string<E>(&mut self, v: String) -> Result<path::PathBuf, E>
where E: Error,
{
self.visit_str(&v)
}
}
impl Deserialize for path::PathBuf {
fn deserialize<D>(deserializer: &mut D) -> Result<path::PathBuf, D::Error>
where D: Deserializer,
{
deserializer.visit(PathBufVisitor)
}
}
///////////////////////////////////////////////////////////////////////////////
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))
}
}