Merge branch 'origin/1.0' into 'origin/master'

This commit is contained in:
David Tolnay
2017-04-18 14:03:00 -07:00
109 changed files with 12404 additions and 9061 deletions
+1 -1
View File
@@ -1,8 +1,8 @@
[workspace] [workspace]
members = [ members = [
"serde", "serde",
"serde_codegen_internals",
"serde_derive", "serde_derive",
"serde_derive_internals",
"serde_test", "serde_test",
"test_suite", "test_suite",
"test_suite/no_std", "test_suite/no_std",
+6 -1
View File
@@ -1,4 +1,9 @@
# Serde   [![Build Status](https://api.travis-ci.org/serde-rs/serde.svg?branch=master)](https://travis-ci.org/serde-rs/serde) [![Latest Version](https://img.shields.io/crates/v/serde.svg)](https://crates.io/crates/serde) # Serde   [![Build Status]][travis] [![Latest Version]][crates.io]
[Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master
[travis]: https://travis-ci.org/serde-rs/serde
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
+5
View File
@@ -0,0 +1,5 @@
fn_args_layout = "Block"
array_layout = "Block"
where_style = "Rfc"
generics_indent = "Block"
fn_call_style = "Block"
+56 -15
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "0.9.14" version = "0.9.14" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
@@ -9,27 +9,68 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/" documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"] keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"] categories = ["encoding"]
readme = "../README.md" readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
publish = false # this branch contains breaking changes
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[features]
default = ["std"]
derive = ["serde_derive"]
std = []
unstable = []
alloc = ["unstable"]
collections = ["alloc"]
unstable-testing = ["unstable", "std"]
# to get serde_derive picked up by play.integer32.com
playground = ["serde_derive"]
[dependencies] [dependencies]
serde_derive = { version = "0.9", optional = true, path = "../serde_derive" } serde_derive = { version = "0.9", optional = true, path = "../serde_derive" }
[dev-dependencies] [dev-dependencies]
serde_derive = { version = "0.9", path = "../serde_derive" } serde_derive = { version = "0.9", path = "../serde_derive" }
### FEATURES #################################################################
[features]
default = ["std"]
# Re-export the derive(Serialize, Deserialize) macros. This is specifically
# intended for library crates that provide optional Serde impls behind a Cargo
# cfg of their own. All other crates should depend on serde_derive directly.
#
# Please refer to the long comment above the line `pub use serde_derive::*` in
# src/lib.rs before enabling this feature. If you think you need this feature
# and your use case does not precisely match the one described in the comment,
# please open an issue to let us know about your use case.
derive = ["serde_derive"]
# Provide impls for common standard library types like Vec<T> and HashMap<K, V>.
# Requires a dependency on the Rust standard library.
std = []
# Provide impls for types that require unstable functionality. For tracking and
# discussion of unstable functionality please refer to this issue:
#
# https://github.com/serde-rs/serde/issues/812
unstable = []
# Provide impls for types that require memory allocation like Box<T> and Rc<T>.
# This is a subset of std but may be enabled without depending on all of std.
#
# Requires a dependency on the unstable core allocation library:
#
# https://doc.rust-lang.org/alloc/
alloc = ["unstable"]
# Provide impls for collection types like String and Cow<T>. This is a subset of
# std but may be enabled without depending on all of std.
#
# Requires a dependency on the unstable collections library:
#
# https://doc.rust-lang.org/collections/
collections = ["alloc"]
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
# does not preserve identity and may result in multiple copies of the same data.
# Be sure that this is what you want before enabling this feature.
rc = []
# Get serde_derive picked up by the Integer 32 playground. Not public API.
#
# http://play.integer32.com/
playground = ["serde_derive"]
-315
View File
@@ -1,315 +0,0 @@
//! Wrapper types to enable optimized handling of `&[u8]` and `Vec<u8>`.
//!
//! Without specialization, Rust forces us to treat `&[u8]` just like any other
//! slice and `Vec<u8>` just like any other vector. In reality this particular
//! slice and vector can often be serialized and deserialized in a more
//! efficient, compact representation in many formats.
//!
//! When working with such a format, you can opt into specialized handling of
//! `&[u8]` by wrapping it in `bytes::Bytes` and `Vec<u8>` by wrapping it in
//! `bytes::ByteBuf`.
//!
//! Rust support for specialization is being tracked in
//! [rust-lang/rust#31844][specialization]. Once it lands in the stable compiler
//! we will be deprecating these wrapper types in favor of optimizing `&[u8]`
//! and `Vec<u8>` out of the box.
//!
//! [specialization]: https://github.com/rust-lang/rust/issues/31844
use core::{ops, fmt, char, iter, slice};
use core::fmt::Write;
use ser;
#[cfg(any(feature = "std", feature = "collections"))]
pub use self::bytebuf::ByteBuf;
#[cfg(any(feature = "std", feature = "collections"))]
#[doc(hidden)] // does anybody need this?
pub use self::bytebuf::ByteBufVisitor;
#[cfg(feature = "collections")]
use collections::Vec;
///////////////////////////////////////////////////////////////////////////////
/// Wraps a `&[u8]` in order to serialize in an efficient way. Does not support
/// deserialization.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::Bytes;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize)]
/// struct Packet<'a> {
/// destination: IpAddr,
/// payload: Bytes<'a>,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Bytes<'a> {
bytes: &'a [u8],
}
impl<'a> Bytes<'a> {
/// Wrap an existing `&[u8]`.
pub fn new(bytes: &'a [u8]) -> Self {
Bytes { bytes: bytes }
}
}
impl<'a> fmt::Debug for Bytes<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\""));
for c in escape_bytestring(self.bytes) {
try!(f.write_char(c));
}
f.write_char('"')
}
}
impl<'a> From<&'a [u8]> for Bytes<'a> {
fn from(bytes: &'a [u8]) -> Self {
Bytes::new(bytes)
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<'a> From<&'a Vec<u8>> for Bytes<'a> {
fn from(bytes: &'a Vec<u8>) -> Self {
Bytes::new(bytes)
}
}
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];
fn deref(&self) -> &[u8] {
self.bytes
}
}
impl<'a> ser::Serialize for Bytes<'a> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self.bytes)
}
}
///////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))]
mod bytebuf {
use core::cmp;
use core::ops;
use core::fmt;
use core::fmt::Write;
use ser;
use de;
#[cfg(feature = "collections")]
use collections::{String, Vec};
/// Wraps a `Vec<u8>` in order to serialize and deserialize in an efficient
/// way.
///
/// ```rust
/// # #[macro_use] extern crate serde_derive;
/// # extern crate serde;
/// # use std::net::IpAddr;
/// #
/// use serde::bytes::ByteBuf;
///
/// # #[allow(dead_code)]
/// #[derive(Serialize, Deserialize)]
/// struct Packet {
/// destination: IpAddr,
/// payload: ByteBuf,
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Clone, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ByteBuf {
bytes: Vec<u8>,
}
impl ByteBuf {
/// Construct a new, empty `ByteBuf`.
pub fn new() -> Self {
ByteBuf::from(Vec::new())
}
/// Construct a new, empty `ByteBuf` with the specified capacity.
pub fn with_capacity(cap: usize) -> Self {
ByteBuf::from(Vec::with_capacity(cap))
}
/// Wrap existing bytes in a `ByteBuf`.
pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
ByteBuf { bytes: bytes.into() }
}
}
impl fmt::Debug for ByteBuf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(f.write_str("b\""));
for c in super::escape_bytestring(self.bytes.as_ref()) {
try!(f.write_char(c));
}
f.write_char('"')
}
}
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::from(bytes)
}
}
impl AsRef<Vec<u8>> for ByteBuf {
fn as_ref(&self) -> &Vec<u8> {
&self.bytes
}
}
impl AsRef<[u8]> for ByteBuf {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
impl AsMut<Vec<u8>> for ByteBuf {
fn as_mut(&mut self) -> &mut Vec<u8> {
&mut self.bytes
}
}
impl AsMut<[u8]> for ByteBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
}
impl ops::Deref for ByteBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes[..]
}
}
impl ops::DerefMut for ByteBuf {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..]
}
}
impl ser::Serialize for ByteBuf {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: ser::Serializer
{
serializer.serialize_bytes(self)
}
}
/// This type implements the `serde::de::Visitor` trait for a `ByteBuf`.
pub struct ByteBufVisitor;
impl de::Visitor for ByteBufVisitor {
type Value = ByteBuf;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("byte array")
}
#[inline]
fn visit_unit<E>(self) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::new())
}
#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
where V: de::SeqVisitor
{
let len = cmp::min(visitor.size_hint().0, 4096);
let mut values = Vec::with_capacity(len);
while let Some(value) = try!(visitor.visit()) {
values.push(value);
}
Ok(ByteBuf::from(values))
}
#[inline]
fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
#[inline]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
where E: de::Error
{
Ok(ByteBuf::from(v))
}
}
impl de::Deserialize for ByteBuf {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
where D: de::Deserializer
{
deserializer.deserialize_byte_buf(ByteBufVisitor)
}
}
}
///////////////////////////////////////////////////////////////////////////////
#[inline]
fn escape_bytestring<'a>
(bytes: &'a [u8])
-> iter::FlatMap<slice::Iter<'a, u8>, char::EscapeDefault, fn(&u8) -> char::EscapeDefault> {
fn f(b: &u8) -> char::EscapeDefault {
char::from_u32(*b as u32).unwrap().escape_default()
}
bytes.iter().flat_map(f as fn(&u8) -> char::EscapeDefault)
}
File diff suppressed because it is too large Load Diff
+89 -382
View File
@@ -1,6 +1,4 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT // Copyright 2017 Serde Developers
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
// //
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
@@ -8,402 +6,111 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// Extracted from https://github.com/rust-num/num. use lib::*;
// Rust 1.5 is unhappy that this private module is undocumented. macro_rules! int_to_int {
#![allow(missing_docs)] ($dst:ident, $n:ident) => (
if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 {
use core::{usize, u8, u16, u32, u64}; Some($n as $dst)
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::mem::size_of;
/// Numbers which have upper and lower bounds
pub trait Bounded {
// FIXME (#5527): These should be associated constants
/// returns the smallest finite number this type can represent
fn min_value() -> Self;
/// returns the largest finite number this type can represent
fn max_value() -> Self;
}
macro_rules! bounded_impl {
($t:ty, $min:expr, $max:expr) => {
impl Bounded for $t {
#[inline]
fn min_value() -> $t { $min }
#[inline]
fn max_value() -> $t { $max }
}
}
}
bounded_impl!(usize, usize::MIN, usize::MAX);
bounded_impl!(u8, u8::MIN, u8::MAX);
bounded_impl!(u16, u16::MIN, u16::MAX);
bounded_impl!(u32, u32::MIN, u32::MAX);
bounded_impl!(u64, u64::MIN, u64::MAX);
bounded_impl!(isize, isize::MIN, isize::MAX);
bounded_impl!(i8, i8::MIN, i8::MAX);
bounded_impl!(i16, i16::MIN, i16::MAX);
bounded_impl!(i32, i32::MIN, i32::MAX);
bounded_impl!(i64, i64::MIN, i64::MAX);
bounded_impl!(f32, f32::MIN, f32::MAX);
bounded_impl!(f64, f64::MIN, f64::MAX);
/// A generic trait for converting a value to a number.
pub trait ToPrimitive {
/// Converts the value of `self` to an `isize`.
#[inline]
fn to_isize(&self) -> Option<isize> {
self.to_i64().and_then(|x| x.to_isize())
}
/// Converts the value of `self` to an `i8`.
#[inline]
fn to_i8(&self) -> Option<i8> {
self.to_i64().and_then(|x| x.to_i8())
}
/// Converts the value of `self` to an `i16`.
#[inline]
fn to_i16(&self) -> Option<i16> {
self.to_i64().and_then(|x| x.to_i16())
}
/// Converts the value of `self` to an `i32`.
#[inline]
fn to_i32(&self) -> Option<i32> {
self.to_i64().and_then(|x| x.to_i32())
}
/// Converts the value of `self` to an `i64`.
fn to_i64(&self) -> Option<i64>;
/// Converts the value of `self` to a `usize`.
#[inline]
fn to_usize(&self) -> Option<usize> {
self.to_u64().and_then(|x| x.to_usize())
}
/// Converts the value of `self` to an `u8`.
#[inline]
fn to_u8(&self) -> Option<u8> {
self.to_u64().and_then(|x| x.to_u8())
}
/// Converts the value of `self` to an `u16`.
#[inline]
fn to_u16(&self) -> Option<u16> {
self.to_u64().and_then(|x| x.to_u16())
}
/// Converts the value of `self` to an `u32`.
#[inline]
fn to_u32(&self) -> Option<u32> {
self.to_u64().and_then(|x| x.to_u32())
}
/// Converts the value of `self` to an `u64`.
#[inline]
fn to_u64(&self) -> Option<u64>;
/// Converts the value of `self` to an `f32`.
#[inline]
fn to_f32(&self) -> Option<f32> {
self.to_f64().and_then(|x| x.to_f32())
}
/// Converts the value of `self` to an `f64`.
#[inline]
fn to_f64(&self) -> Option<f64> {
self.to_i64().and_then(|x| x.to_f64())
}
}
macro_rules! impl_to_primitive_int_to_int {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let n = $slf as i64;
let min_value: $DstT = Bounded::min_value();
let max_value: $DstT = Bounded::max_value();
if min_value as i64 <= n && n <= max_value as i64 {
Some($slf as $DstT)
} else {
None
}
}
}
)
}
macro_rules! impl_to_primitive_int_to_uint {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
let zero: $SrcT = 0;
let max_value: $DstT = Bounded::max_value();
if zero <= $slf && $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_int {
($T:ty) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) }
#[inline]
fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) }
#[inline]
fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) }
#[inline]
fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) }
#[inline]
fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) }
#[inline]
fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) }
#[inline]
fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) }
#[inline]
fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) }
#[inline]
fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) }
#[inline]
fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) }
#[inline]
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
#[inline]
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
}
)
}
impl_to_primitive_int! { isize }
impl_to_primitive_int! { i8 }
impl_to_primitive_int! { i16 }
impl_to_primitive_int! { i32 }
impl_to_primitive_int! { i64 }
macro_rules! impl_to_primitive_uint_to_int {
($DstT:ty, $slf:expr) => (
{
let max_value: $DstT = Bounded::max_value();
if $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
)
}
macro_rules! impl_to_primitive_uint_to_uint {
($SrcT:ty, $DstT:ty, $slf:expr) => (
{
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else {
let zero: $SrcT = 0;
let max_value: $DstT = Bounded::max_value();
if zero <= $slf && $slf as u64 <= max_value as u64 {
Some($slf as $DstT)
} else {
None
}
}
}
)
}
macro_rules! impl_to_primitive_uint {
($T:ty) => (
impl ToPrimitive for $T {
#[inline]
fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) }
#[inline]
fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) }
#[inline]
fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) }
#[inline]
fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) }
#[inline]
fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) }
#[inline]
fn to_usize(&self) -> Option<usize> {
impl_to_primitive_uint_to_uint!($T, usize, *self)
}
#[inline]
fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) }
#[inline]
fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) }
#[inline]
fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) }
#[inline]
fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) }
#[inline]
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
#[inline]
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
}
)
}
impl_to_primitive_uint! { usize }
impl_to_primitive_uint! { u8 }
impl_to_primitive_uint! { u16 }
impl_to_primitive_uint! { u32 }
impl_to_primitive_uint! { u64 }
macro_rules! impl_to_primitive_float_to_float {
($SrcT:ident, $DstT:ident, $slf:expr) => (
if size_of::<$SrcT>() <= size_of::<$DstT>() {
Some($slf as $DstT)
} else { } else {
let n = $slf as f64; None
let max_value: $SrcT = ::core::$SrcT::MAX;
if -max_value as f64 <= n && n <= max_value as f64 {
Some($slf as $DstT)
} else {
None
}
} }
) )
} }
macro_rules! impl_to_primitive_float { macro_rules! int_to_uint {
($T:ident) => ( ($dst:ident, $n:ident) => (
impl ToPrimitive for $T { if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
#[inline] Some($n as $dst)
fn to_isize(&self) -> Option<isize> { Some(*self as isize) } } else {
#[inline] None
fn to_i8(&self) -> Option<i8> { Some(*self as i8) }
#[inline]
fn to_i16(&self) -> Option<i16> { Some(*self as i16) }
#[inline]
fn to_i32(&self) -> Option<i32> { Some(*self as i32) }
#[inline]
fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
#[inline]
fn to_usize(&self) -> Option<usize> { Some(*self as usize) }
#[inline]
fn to_u8(&self) -> Option<u8> { Some(*self as u8) }
#[inline]
fn to_u16(&self) -> Option<u16> { Some(*self as u16) }
#[inline]
fn to_u32(&self) -> Option<u32> { Some(*self as u32) }
#[inline]
fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
#[inline]
fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) }
#[inline]
fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) }
} }
) )
} }
impl_to_primitive_float! { f32 } macro_rules! uint_to {
impl_to_primitive_float! { f64 } ($dst:ident, $n:ident) => (
if $n as u64 <= $dst::MAX as u64 {
Some($n as $dst)
} else {
None
}
)
}
pub trait FromPrimitive: Sized { pub trait FromPrimitive: Sized {
#[inline] fn from_isize(n: isize) -> Option<Self>;
fn from_isize(n: isize) -> Option<Self> { fn from_i8(n: i8) -> Option<Self>;
FromPrimitive::from_i64(n as i64) fn from_i16(n: i16) -> Option<Self>;
} fn from_i32(n: i32) -> Option<Self>;
#[inline]
fn from_i8(n: i8) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
fn from_i64(n: i64) -> Option<Self>; fn from_i64(n: i64) -> Option<Self>;
fn from_usize(n: usize) -> Option<Self>;
#[inline] fn from_u8(n: u8) -> Option<Self>;
fn from_usize(n: usize) -> Option<Self> { fn from_u16(n: u16) -> Option<Self>;
FromPrimitive::from_u64(n as u64) fn from_u32(n: u32) -> Option<Self>;
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
FromPrimitive::from_u64(n as u64)
}
fn from_u64(n: u64) -> Option<Self>; fn from_u64(n: u64) -> Option<Self>;
#[inline]
fn from_f32(n: f32) -> Option<Self> {
FromPrimitive::from_f64(n as f64)
}
#[inline]
fn from_f64(n: f64) -> Option<Self> {
FromPrimitive::from_i64(n as i64)
}
} }
macro_rules! impl_from_primitive { macro_rules! impl_from_primitive_for_int {
($T:ty, $to_ty:ident) => ( ($t:ident) => (
impl FromPrimitive for $T { impl FromPrimitive for $t {
#[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() } #[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() } #[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() } #[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() } #[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!($t, n) }
#[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() } #[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() } #[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() } #[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() } #[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
#[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
} }
) )
} }
impl_from_primitive! { isize, to_isize } macro_rules! impl_from_primitive_for_uint {
impl_from_primitive! { i8, to_i8 } ($t:ident) => (
impl_from_primitive! { i16, to_i16 } impl FromPrimitive for $t {
impl_from_primitive! { i32, to_i32 } #[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!($t, n) }
impl_from_primitive! { i64, to_i64 } #[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!($t, n) }
impl_from_primitive! { usize, to_usize } #[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) }
impl_from_primitive! { u8, to_u8 } #[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!($t, n) }
impl_from_primitive! { u16, to_u16 } #[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!($t, n) }
impl_from_primitive! { u32, to_u32 } #[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
impl_from_primitive! { u64, to_u64 } #[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
impl_from_primitive! { f32, to_f32 } #[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
impl_from_primitive! { f64, to_f64 } #[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
}
)
}
macro_rules! impl_from_primitive_for_float {
($t:ident) => (
impl FromPrimitive for $t {
#[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) }
#[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) }
#[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) }
#[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
}
)
}
impl_from_primitive_for_int!(isize);
impl_from_primitive_for_int!(i8);
impl_from_primitive_for_int!(i16);
impl_from_primitive_for_int!(i32);
impl_from_primitive_for_int!(i64);
impl_from_primitive_for_uint!(usize);
impl_from_primitive_for_uint!(u8);
impl_from_primitive_for_uint!(u16);
impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64);
+215
View File
@@ -0,0 +1,215 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
/// An efficient way of discarding data from a deserializer.
///
/// Think of this like `serde_json::Value` in that it can be deserialized from
/// any type, except that it does not store any information about the data that
/// gets deserialized.
///
/// ```rust
/// use std::fmt;
/// use std::marker::PhantomData;
///
/// use serde::de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, IgnoredAny};
///
/// /// A seed that can be used to deserialize only the `n`th element of a sequence
/// /// while efficiently discarding elements of any type before or after index `n`.
/// ///
/// /// For example to deserialize only the element at index 3:
/// ///
/// /// ```rust
/// /// NthElement::new(3).deserialize(deserializer)
/// /// ```
/// pub struct NthElement<T> {
/// n: usize,
/// marker: PhantomData<T>,
/// }
///
/// impl<T> NthElement<T> {
/// pub fn new(n: usize) -> Self {
/// NthElement {
/// n: n,
/// marker: PhantomData,
/// }
/// }
/// }
///
/// impl<'de, T> Visitor<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// {
/// type Value = T;
///
/// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// write!(formatter, "a sequence in which we care about element {}", self.n)
/// }
///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
/// where A: SeqAccess<'de>
/// {
/// // Skip over the first `n` elements.
/// for i in 0..self.n {
/// // It is an error if the sequence ends before we get to element `n`.
/// if seq.next_element::<IgnoredAny>()?.is_none() {
/// return Err(de::Error::invalid_length(i, &self));
/// }
/// }
///
/// // Deserialize the one we care about.
/// let nth = match seq.next_element()? {
/// Some(nth) => nth,
/// None => {
/// return Err(de::Error::invalid_length(self.n, &self));
/// }
/// };
///
/// // Skip over any remaining elements in the sequence after `n`.
/// while let Some(IgnoredAny) = seq.next_element()? {
/// // ignore
/// }
///
/// Ok(nth)
/// }
/// }
///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// {
/// type Value = T;
///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de>
/// {
/// deserializer.deserialize_seq(self)
/// }
/// }
///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de>
/// # {
/// // Deserialize only the sequence element at index 3 from this deserializer.
/// // The element at index 3 is required to be a string. Elements before and
/// // after index 3 are allowed to be of any type.
/// let s: String = NthElement::new(3).deserialize(deserializer)?;
/// # Ok(())
/// # }
/// ```
#[derive(Copy, Clone, Debug, Default)]
pub struct IgnoredAny;
impl<'de> Visitor<'de> for IgnoredAny {
type Value = IgnoredAny;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("anything at all")
}
#[inline]
fn visit_bool<E>(self, x: bool) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_i64<E>(self, x: i64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_u64<E>(self, x: u64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_f64<E>(self, x: f64) -> Result<Self::Value, E> {
let _ = x;
Ok(IgnoredAny)
}
#[inline]
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
let _ = s;
Ok(IgnoredAny)
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
IgnoredAny::deserialize(deserializer)
}
#[inline]
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
IgnoredAny::deserialize(deserializer)
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E> {
Ok(IgnoredAny)
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
while let Some(IgnoredAny) = try!(seq.next_element()) {
// Gobble
}
Ok(IgnoredAny)
}
#[inline]
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) {
// Gobble
}
Ok(IgnoredAny)
}
#[inline]
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
let _ = bytes;
Ok(IgnoredAny)
}
}
impl<'de> Deserialize<'de> for IgnoredAny {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<IgnoredAny, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_ignored_any(IgnoredAny)
}
}
+677 -705
View File
File diff suppressed because it is too large Load Diff
+997 -588
View File
File diff suppressed because it is too large Load Diff
-44
View File
@@ -1,44 +0,0 @@
use core::marker::PhantomData;
use de::{Deserialize, Deserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))]
pub use de::content::{Content, ContentRefDeserializer, ContentDeserializer, TaggedContentVisitor,
TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor,
UntaggedUnitVisitor};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
pub fn missing_field<V, E>(field: &'static str) -> Result<V, E>
where V: Deserialize,
E: Error
{
struct MissingFieldDeserializer<E>(&'static str, PhantomData<E>);
impl<E> Deserializer for MissingFieldDeserializer<E>
where E: Error
{
type Error = E;
fn deserialize<V>(self, _visitor: V) -> Result<V::Value, E>
where V: Visitor
{
Err(Error::missing_field(self.0))
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, E>
where V: Visitor
{
visitor.visit_none()
}
forward_to_deserialize! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq
seq_fixed_size bytes byte_buf map unit_struct newtype_struct
tuple_struct struct struct_field tuple enum ignored_any
}
}
let deserializer = MissingFieldDeserializer(field, PhantomData);
Deserialize::deserialize(deserializer)
}
+54
View File
@@ -0,0 +1,54 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use lib::*;
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
#[inline]
pub fn encode(c: char) -> Encode {
let code = c as u32;
let mut buf = [0; 4];
let pos = if code < MAX_ONE_B {
buf[3] = code as u8;
3
} else if code < MAX_TWO_B {
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B {
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
1
} else {
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
Encode { buf: buf, pos: pos }
}
pub struct Encode {
buf: [u8; 4],
pos: usize,
}
impl Encode {
pub fn as_str(&self) -> &str {
str::from_utf8(&self.buf[self.pos..]).unwrap()
}
}
+540 -476
View File
File diff suppressed because it is too large Load Diff
-17
View File
@@ -1,17 +0,0 @@
//! A stand-in for `std::error`
use core::fmt::{Debug, Display};
/// A stand-in for `std::error::Error`, which requires no allocation.
pub trait Error: Debug + Display {
/// A short description of the error.
///
/// The description should not contain newlines or sentence-ending
/// punctuation, to facilitate embedding in larger user-facing
/// strings.
fn description(&self) -> &str;
/// The lower-level cause of this error, if any.
fn cause(&self) -> Option<&Error> {
None
}
}
+39 -34
View File
@@ -1,36 +1,41 @@
#[cfg(all(feature = "collections", not(feature = "std")))] // Copyright 2017 Serde Developers
use collections::String;
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(all(feature = "collections", not(feature = "std")))]
use collections::borrow::Cow;
pub use core::clone::Clone;
pub use core::convert::{From, Into};
pub use core::default::Default;
pub use core::fmt;
pub use core::marker::PhantomData;
pub use core::option::Option::{self, None, Some};
pub use core::result::Result::{self, Ok, Err};
#[cfg(any(feature = "collections", feature = "std"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
// //
// let value = &_serde::export::from_utf8_lossy(bytes); // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// Err(_serde::de::Error::unknown_variant(value, VARIANTS)) // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// so it is okay for the return type to be different from the std case as long // option. This file may not be copied, modified, or distributed
// as the above works. // except according to those terms.
#[cfg(not(any(feature = "collections", feature = "std")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str { pub use lib::clone::Clone;
use core::str; pub use lib::convert::{From, Into};
// Three unicode replacement characters if it fails. They look like a pub use lib::default::Default;
// white-on-black question mark. The user will recognize it as invalid pub use lib::fmt::{self, Formatter};
// UTF-8. pub use lib::marker::PhantomData;
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}") pub use lib::option::Option::{self, None, Some};
pub use lib::result::Result::{self, Ok, Err};
pub use self::string::from_utf8_lossy;
mod string {
use lib::*;
#[cfg(any(feature = "std", feature = "collections"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes)
}
// The generated code calls this like:
//
// let value = &_serde::export::from_utf8_lossy(bytes);
// Err(_serde::de::Error::unknown_variant(value, VARIANTS))
//
// so it is okay for the return type to be different from the std case as long
// as the above works.
#[cfg(not(any(feature = "std", feature = "collections")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
// Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid
// UTF-8.
str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}")
}
} }
-73
View File
@@ -1,73 +0,0 @@
//! Module that contains helper iterators.
use std::io;
use std::iter::Peekable;
/// Iterator over a byte stream that tracks the current position's line and column.
pub struct LineColIterator<Iter: Iterator<Item = io::Result<u8>>> {
iter: Iter,
line: usize,
col: usize,
}
impl<Iter: Iterator<Item = io::Result<u8>>> LineColIterator<Iter> {
/// Construct a new `LineColIterator<Iter>`.
pub fn new(iter: Iter) -> LineColIterator<Iter> {
LineColIterator {
iter: iter,
line: 1,
col: 0,
}
}
/// Report the current line inside the iterator.
pub fn line(&self) -> usize {
self.line
}
/// Report the current column inside the iterator.
pub fn col(&self) -> usize {
self.col
}
/// Gets a reference to the underlying iterator.
pub fn get_ref(&self) -> &Iter {
&self.iter
}
/// Gets a mutable reference to the underlying iterator.
pub fn get_mut(&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>> {
match self.iter.next() {
None => None,
Some(Ok(b'\n')) => {
self.line += 1;
self.col = 0;
Some(Ok(b'\n'))
}
Some(Ok(c)) => {
self.col += 1;
Some(Ok(c))
}
Some(Err(e)) => Some(Err(e)),
}
}
}
+170 -58
View File
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! # Serde //! # Serde
//! //!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data //! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
@@ -9,63 +17,92 @@
//! these two groups interact with each other, allowing any supported data //! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format. //! structure to be serialized and deserialized using any supported data format.
//! //!
//! See the Serde website https://serde.rs/ for additional documentation and //! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples. //! usage examples.
//! //!
//! ### Design //! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//! //!
//! Where many other languages rely on runtime reflection for serializing data, //! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure //! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements //! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's code //! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! generation to automatically derive implementations at compile time). This //! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in //! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can //! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde //! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform roughly the same speed as a handwritten serializer //! serialization to perform the same speed as a handwritten serializer for the
//! for the specific selection of data structure and data format. //! specific selection of data structure and data format.
//! //!
//! ### Data formats //! ## Data formats
//! //!
//! The following is a partial list of data formats that have been implemented //! The following is a partial list of data formats that have been implemented
//! for Serde by the community. //! for Serde by the community.
//! //!
//! - [JSON](https://github.com/serde-rs/json), the ubiquitous JavaScript Object //! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! Notation used by many HTTP APIs. //! - [Bincode], a compact binary format
//! - [Bincode](https://github.com/TyOverby/bincode), a compact binary format
//! used for IPC within the Servo rendering engine. //! used for IPC within the Servo rendering engine.
//! - [CBOR](https://github.com/pyfisch/cbor), a Concise Binary Object //! - [CBOR], a Concise Binary Object Representation designed for small message
//! Representation designed for small message size without the need for //! size without the need for version negotiation.
//! version negotiation. //! - [YAML], a popular human-friendly configuration language that ain't markup
//! - [YAML](https://github.com/dtolnay/serde-yaml), a popular human-friendly //! language.
//! configuration language that ain't markup language. //! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [MessagePack](https://github.com/3Hren/msgpack-rust), an efficient binary //! - [TOML], a minimal configuration format used by [Cargo].
//! format that resembles a compact JSON. //! - [Pickle], a format common in the Python world.
//! - [TOML](https://github.com/alexcrichton/toml-rs), a minimal configuration //! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! format used by [Cargo](http://doc.crates.io/manifest.html). //! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Pickle](https://github.com/birkenfeld/serde-pickle), a format common in //! - [URL], the x-www-form-urlencoded format.
//! the Python world. //! - [XML], the flexible machine-friendly W3C standard.
//! - [Hjson](https://github.com/laktak/hjson-rust), a variant of JSON designed
//! to be readable and writable by humans.
//! - [BSON](https://github.com/zonyitoo/bson-rs), the data storage and network
//! transfer format used by MongoDB.
//! - [URL](https://github.com/nox/serde_urlencoded), the x-www-form-urlencoded
//! format.
//! - [XML](https://github.com/serde-rs/xml), the flexible machine-friendly W3C
//! standard. *(deserialization only)*
//! - [Envy](https://github.com/softprops/envy), a way to deserialize
//! environment variables into Rust structs. *(deserialization only)*
//! - [Redis](https://github.com/OneSignal/serde-redis), deserialize values from
//! Redis when using [redis-rs](https://crates.io/crates/redis).
//! *(deserialization only)* //! *(deserialization only)*
//! - [Envy], a way to deserialize environment variables into Rust structs.
//! *(deserialization only)*
//! - [Redis], deserialize values from Redis when using [redis-rs].
//! *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis
#![doc(html_root_url="https://docs.serde.rs")] ////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/0.9.13")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(nonzero, specialization, zero_one, into_boxed_c_str))]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization, zero_one))]
#![cfg_attr(all(feature = "std", feature = "unstable"), feature(into_boxed_c_str))]
#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections))] #![cfg_attr(feature = "collections", feature(collections))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]
#![deny(missing_docs)] // Whitelisted clippy lints.
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist))]
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#![cfg_attr(feature = "cargo-clippy", allow(zero_prefixed_literal))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "collections")] #[cfg(feature = "collections")]
extern crate collections; extern crate collections;
@@ -73,40 +110,115 @@ extern crate collections;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
#[cfg(feature = "unstable")] #[cfg(all(feature = "unstable", feature = "std"))]
extern crate core as actual_core; extern crate core;
/// A facade around all the types we need from the `std`, `core`, `alloc`, and
/// `collections` crates. This avoids elaborate import wrangling having to
/// happen in every module.
mod lib {
mod core {
#[cfg(feature = "std")]
pub use std::*;
#[cfg(not(feature = "std"))]
pub use core::*;
}
pub use self::core::{cmp, iter, mem, ops, str};
pub use self::core::{i8, i16, i32, i64, isize};
pub use self::core::{u8, u16, u32, u64, usize};
pub use self::core::{f32, f64};
pub use self::core::cell::{Cell, RefCell};
pub use self::core::clone::{self, Clone};
pub use self::core::convert::{self, From, Into};
pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData};
pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result};
#[cfg(feature = "std")]
pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "collections", not(feature = "std")))]
pub use collections::borrow::{Cow, ToOwned};
#[cfg(feature = "std")]
pub use std::string::String;
#[cfg(all(feature = "collections", not(feature = "std")))]
pub use collections::string::{String, ToString};
#[cfg(feature = "std")]
pub use std::vec::Vec;
#[cfg(all(feature = "collections", not(feature = "std")))]
pub use collections::vec::Vec;
#[cfg(feature = "std")]
pub use std::boxed::Box;
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::boxed::Box;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::rc::Rc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::Rc;
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::Arc;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::Arc;
#[cfg(feature = "std")]
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(all(feature = "collections", not(feature = "std")))]
pub use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(feature = "std")]
pub use std::{error, net};
#[cfg(feature = "std")]
pub use std::collections::{HashMap, HashSet};
#[cfg(feature = "std")]
pub use std::ffi::{CString, CStr, OsString, OsStr};
#[cfg(feature = "std")]
pub use std::hash::{Hash, BuildHasher};
#[cfg(feature = "std")]
pub use std::io::Write;
#[cfg(feature = "std")]
pub use std::path::{Path, PathBuf};
#[cfg(feature = "std")]
pub use std::time::Duration;
#[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "std")]
mod core {
pub use std::{ops, hash, fmt, cmp, marker, mem, i8, i16, i32, i64, u8, u16, u32, u64, isize,
usize, f32, f64, char, str, num, slice, iter, cell, default, result, option,
clone, convert};
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
pub use actual_core::nonzero; pub use core::nonzero::{NonZero, Zeroable};
#[cfg(feature = "unstable")]
#[allow(deprecated)] // required for impl Deserialize for NonZero<T>
pub use core::num::Zero;
} }
////////////////////////////////////////////////////////////////////////////////
#[macro_use]
mod macros;
pub mod ser;
pub mod de;
#[doc(inline)] #[doc(inline)]
pub use ser::{Serialize, Serializer}; pub use ser::{Serialize, Serializer};
#[doc(inline)] #[doc(inline)]
pub use de::{Deserialize, Deserializer}; pub use de::{Deserialize, Deserializer};
#[macro_use]
mod macros;
pub mod bytes;
pub mod de;
#[cfg(feature = "std")]
#[doc(hidden)]
pub mod iter;
pub mod ser;
#[cfg_attr(feature = "std", doc(hidden))]
pub mod error;
mod utils;
// Generated code uses these to support no_std. Not public API. // Generated code uses these to support no_std. Not public API.
#[doc(hidden)] #[doc(hidden)]
pub mod export; pub mod export;
// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;
// Re-export #[derive(Serialize, Deserialize)]. // Re-export #[derive(Serialize, Deserialize)].
// //
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286. // This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
+198 -163
View File
@@ -1,107 +1,10 @@
#[doc(hidden)] // Copyright 2017 Serde Developers
#[macro_export] //
macro_rules! forward_to_deserialize_method { // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
($func:ident($($arg:ty),*)) => { // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
#[inline] // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> $crate::export::Result<__V::Value, Self::Error> // option. This file may not be copied, modified, or distributed
where __V: $crate::de::Visitor // except according to those terms.
{
self.deserialize(visitor)
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_helper {
(bool) => {
forward_to_deserialize_method!{deserialize_bool()}
};
(u8) => {
forward_to_deserialize_method!{deserialize_u8()}
};
(u16) => {
forward_to_deserialize_method!{deserialize_u16()}
};
(u32) => {
forward_to_deserialize_method!{deserialize_u32()}
};
(u64) => {
forward_to_deserialize_method!{deserialize_u64()}
};
(i8) => {
forward_to_deserialize_method!{deserialize_i8()}
};
(i16) => {
forward_to_deserialize_method!{deserialize_i16()}
};
(i32) => {
forward_to_deserialize_method!{deserialize_i32()}
};
(i64) => {
forward_to_deserialize_method!{deserialize_i64()}
};
(f32) => {
forward_to_deserialize_method!{deserialize_f32()}
};
(f64) => {
forward_to_deserialize_method!{deserialize_f64()}
};
(char) => {
forward_to_deserialize_method!{deserialize_char()}
};
(str) => {
forward_to_deserialize_method!{deserialize_str()}
};
(string) => {
forward_to_deserialize_method!{deserialize_string()}
};
(unit) => {
forward_to_deserialize_method!{deserialize_unit()}
};
(option) => {
forward_to_deserialize_method!{deserialize_option()}
};
(seq) => {
forward_to_deserialize_method!{deserialize_seq()}
};
(seq_fixed_size) => {
forward_to_deserialize_method!{deserialize_seq_fixed_size(usize)}
};
(bytes) => {
forward_to_deserialize_method!{deserialize_bytes()}
};
(byte_buf) => {
forward_to_deserialize_method!{deserialize_byte_buf()}
};
(map) => {
forward_to_deserialize_method!{deserialize_map()}
};
(unit_struct) => {
forward_to_deserialize_method!{deserialize_unit_struct(&'static str)}
};
(newtype_struct) => {
forward_to_deserialize_method!{deserialize_newtype_struct(&'static str)}
};
(tuple_struct) => {
forward_to_deserialize_method!{deserialize_tuple_struct(&'static str, usize)}
};
(struct) => {
forward_to_deserialize_method!{deserialize_struct(&'static str, &'static [&'static str])}
};
(struct_field) => {
forward_to_deserialize_method!{deserialize_struct_field()}
};
(tuple) => {
forward_to_deserialize_method!{deserialize_tuple(usize)}
};
(enum) => {
forward_to_deserialize_method!{deserialize_enum(&'static str, &'static [&'static str])}
};
(ignored_any) => {
forward_to_deserialize_method!{deserialize_ignored_any()}
};
}
// Super explicit first paragraph because this shows up at the top level and // Super explicit first paragraph because this shows up at the top level and
// trips up people who are just looking for basic Serialize / Deserialize // trips up people who are just looking for basic Serialize / Deserialize
@@ -110,98 +13,230 @@ macro_rules! forward_to_deserialize_helper {
/// Helper macro when implementing the `Deserializer` part of a new data format /// Helper macro when implementing the `Deserializer` part of a new data format
/// for Serde. /// for Serde.
/// ///
/// Some `Deserializer` implementations for self-describing formats do not care /// Some [`Deserializer`] implementations for self-describing formats do not
/// what hint the `Visitor` gives them, they just want to blindly call the /// care what hint the [`Visitor`] gives them, they just want to blindly call
/// `Visitor` method corresponding to the data they can tell is in the input. /// the [`Visitor`] method corresponding to the data they can tell is in the
/// This requires repetitive implementations of all the `Deserializer` trait /// input. This requires repetitive implementations of all the [`Deserializer`]
/// methods. /// trait methods.
/// ///
/// ```rust /// ```rust
/// # #[macro_use] extern crate serde; /// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor}; /// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer; /// #
/// # impl Deserializer for MyDeserializer { /// # struct MyDeserializer;
/// #
/// # impl<'de> Deserializer<'de> for MyDeserializer {
/// # type Error = value::Error; /// # type Error = value::Error;
/// # fn deserialize<V>(self, _: V) -> Result<V::Value, Self::Error> /// #
/// # where V: Visitor /// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # { unimplemented!() } /// # where V: Visitor<'de>
/// # {
/// # unimplemented!()
/// # }
/// # /// #
/// #[inline] /// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> /// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor /// where V: Visitor<'de>
/// { /// {
/// self.deserialize(visitor) /// self.deserialize_any(visitor)
/// } /// }
/// # forward_to_deserialize! { /// #
/// # u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option /// # forward_to_deserialize_any! {
/// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct /// # i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// # tuple_struct struct struct_field tuple enum ignored_any /// # byte_buf option unit unit_struct newtype_struct seq tuple
/// # tuple_struct map struct enum identifier ignored_any
/// # } /// # }
/// # } /// # }
/// #
/// # fn main() {} /// # fn main() {}
/// ``` /// ```
/// ///
/// The `forward_to_deserialize!` macro implements these simple forwarding /// The `forward_to_deserialize_any!` macro implements these simple forwarding
/// methods so that they forward directly to `Deserializer::deserialize`. You /// methods so that they forward directly to [`Deserializer::deserialize_any`].
/// can choose which methods to forward. /// You can choose which methods to forward.
/// ///
/// ```rust /// ```rust
/// # #[macro_use] extern crate serde; /// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor}; /// # use serde::de::{value, Deserializer, Visitor};
/// # pub struct MyDeserializer; /// #
/// impl Deserializer for MyDeserializer { /// # struct MyDeserializer;
/// #
/// impl<'de> Deserializer<'de> for MyDeserializer {
/// # type Error = value::Error; /// # type Error = value::Error;
/// fn deserialize<V>(self, visitor: V) -> Result<V::Value, Self::Error> /// #
/// where V: Visitor /// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// { /// {
/// /* ... */ /// /* ... */
/// # let _ = visitor; /// # let _ = visitor;
/// # unimplemented!() /// # unimplemented!()
/// } /// }
/// ///
/// forward_to_deserialize! { /// forward_to_deserialize_any! {
/// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option /// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct /// byte_buf option unit unit_struct newtype_struct seq tuple
/// tuple_struct struct struct_field tuple enum ignored_any /// tuple_struct map struct enum identifier ignored_any
/// } /// }
/// } /// }
/// #
/// # fn main() {} /// # fn main() {}
/// ``` /// ```
///
/// The macro assumes the convention that your `Deserializer` lifetime parameter
/// is called `'de` and that the `Visitor` type parameters on each method are
/// called `V`. A different type parameter and a different lifetime can be
/// specified explicitly if necessary.
///
/// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use std::marker::PhantomData;
/// #
/// # use serde::de::{value, Deserializer, Visitor};
/// #
/// # struct MyDeserializer<V>(PhantomData<V>);
/// #
/// # impl<'q, V> Deserializer<'q> for MyDeserializer<V> {
/// # type Error = value::Error;
/// #
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
/// # where W: Visitor<'q>
/// # {
/// # unimplemented!()
/// # }
/// #
/// forward_to_deserialize_any! {
/// <W: Visitor<'q>>
/// bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
/// byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
/// map struct enum identifier ignored_any
/// }
/// # }
/// #
/// # fn main() {}
/// ```
///
/// [`Deserializer`]: trait.Deserializer.html
/// [`Visitor`]: de/trait.Visitor.html
/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any
#[macro_export] #[macro_export]
macro_rules! forward_to_deserialize { macro_rules! forward_to_deserialize_any {
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
$(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})*
};
// This case must be after the previous one.
($($func:ident)*) => { ($($func:ident)*) => {
$(forward_to_deserialize_helper!{$func})* $(forward_to_deserialize_any_helper!{$func<'de, V>})*
}; };
} }
/// Seralize the `$value` that implements Display as a string, #[doc(hidden)]
/// when that string is statically known to never have more than #[macro_export]
/// a constant `$MAX_LEN` bytes. macro_rules! forward_to_deserialize_any_method {
/// ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
/// Panics if the Display impl tries to write more than `$MAX_LEN` bytes. #[inline]
#[cfg(feature = "std")] fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error>
// Not exported where
macro_rules! serialize_display_bounded_length { $v: $crate::de::Visitor<$l>,
($value: expr, $MAX_LEN: expr, $serializer: expr) => {
{ {
use std::io::Write; $(
let mut buffer: [u8; $MAX_LEN] = unsafe { ::std::mem::uninitialized() }; let _ = $arg;
let remaining_len; )*
{ self.deserialize_any(visitor)
let mut remaining = &mut buffer[..];
write!(remaining, "{}", $value).unwrap();
remaining_len = remaining.len()
}
let written_len = buffer.len() - remaining_len;
let written = &buffer[..written_len];
// write! only provides std::fmt::Formatter to Display implementations,
// which has methods write_str and write_char but no method to write arbitrary bytes.
// Therefore, `written` is well-formed in UTF-8.
let written_str = unsafe {
::std::str::from_utf8_unchecked(written)
};
$serializer.serialize_str(written_str)
} }
} };
}
#[doc(hidden)]
#[macro_export]
macro_rules! forward_to_deserialize_any_helper {
(bool<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()}
};
(i8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i8<$l, $v>()}
};
(i16<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i16<$l, $v>()}
};
(i32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i32<$l, $v>()}
};
(i64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()}
};
(u8<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()}
};
(u16<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u16<$l, $v>()}
};
(u32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u32<$l, $v>()}
};
(u64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()}
};
(f32<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()}
};
(f64<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_f64<$l, $v>()}
};
(char<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_char<$l, $v>()}
};
(str<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_str<$l, $v>()}
};
(string<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_string<$l, $v>()}
};
(bytes<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_bytes<$l, $v>()}
};
(byte_buf<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_byte_buf<$l, $v>()}
};
(option<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_option<$l, $v>()}
};
(unit<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_unit<$l, $v>()}
};
(unit_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_unit_struct<$l, $v>(name: &'static str)}
};
(newtype_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)}
};
(seq<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_seq<$l, $v>()}
};
(tuple<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_tuple<$l, $v>(len: usize)}
};
(tuple_struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)}
};
(map<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_map<$l, $v>()}
};
(struct<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])}
};
(enum<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])}
};
(identifier<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_identifier<$l, $v>()}
};
(ignored_any<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_ignored_any<$l, $v>()}
};
} }
File diff suppressed because it is too large Load Diff
+148
View File
@@ -0,0 +1,148 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[doc(hidden)]
#[macro_export]
macro_rules! __private_serialize {
() => {
trait Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: $crate::Serializer;
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __private_deserialize {
() => {
trait Deserialize<'de>: Sized {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: $crate::Deserializer<'de>;
}
};
}
/// Used only by Serde doc tests. Not public API.
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented {
($($func:ident)*) => {
$(
__serialize_unimplemented_helper!($func);
)*
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented_method {
($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => {
fn $func $(<$t: ?Sized + $crate::Serialize>)* (self $(, _: $arg)*) -> $crate::export::Result<Self::$ret, Self::Error> {
unimplemented!()
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __serialize_unimplemented_helper {
(bool) => {
__serialize_unimplemented_method!(serialize_bool(bool) -> Ok);
};
(i8) => {
__serialize_unimplemented_method!(serialize_i8(i8) -> Ok);
};
(i16) => {
__serialize_unimplemented_method!(serialize_i16(i16) -> Ok);
};
(i32) => {
__serialize_unimplemented_method!(serialize_i32(i32) -> Ok);
};
(i64) => {
__serialize_unimplemented_method!(serialize_i64(i64) -> Ok);
};
(u8) => {
__serialize_unimplemented_method!(serialize_u8(u8) -> Ok);
};
(u16) => {
__serialize_unimplemented_method!(serialize_u16(u16) -> Ok);
};
(u32) => {
__serialize_unimplemented_method!(serialize_u32(u32) -> Ok);
};
(u64) => {
__serialize_unimplemented_method!(serialize_u64(u64) -> Ok);
};
(f32) => {
__serialize_unimplemented_method!(serialize_f32(f32) -> Ok);
};
(f64) => {
__serialize_unimplemented_method!(serialize_f64(f64) -> Ok);
};
(char) => {
__serialize_unimplemented_method!(serialize_char(char) -> Ok);
};
(str) => {
__serialize_unimplemented_method!(serialize_str(&str) -> Ok);
};
(bytes) => {
__serialize_unimplemented_method!(serialize_bytes(&[u8]) -> Ok);
};
(none) => {
__serialize_unimplemented_method!(serialize_none() -> Ok);
};
(some) => {
__serialize_unimplemented_method!(serialize_some<T>(&T) -> Ok);
};
(unit) => {
__serialize_unimplemented_method!(serialize_unit() -> Ok);
};
(unit_struct) => {
__serialize_unimplemented_method!(serialize_unit_struct(&str) -> Ok);
};
(unit_variant) => {
__serialize_unimplemented_method!(serialize_unit_variant(&str, u32, &str) -> Ok);
};
(newtype_struct) => {
__serialize_unimplemented_method!(serialize_newtype_struct<T>(&str, &T) -> Ok);
};
(newtype_variant) => {
__serialize_unimplemented_method!(serialize_newtype_variant<T>(&str, u32, &str, &T) -> Ok);
};
(seq) => {
type SerializeSeq = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_seq(Option<usize>) -> SerializeSeq);
};
(tuple) => {
type SerializeTuple = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple(usize) -> SerializeTuple);
};
(tuple_struct) => {
type SerializeTupleStruct = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple_struct(&str, usize) -> SerializeTupleStruct);
};
(tuple_variant) => {
type SerializeTupleVariant = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_tuple_variant(&str, u32, &str, usize) -> SerializeTupleVariant);
};
(map) => {
type SerializeMap = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_map(Option<usize>) -> SerializeMap);
};
(struct) => {
type SerializeStruct = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_struct(&str, usize) -> SerializeStruct);
};
(struct_variant) => {
type SerializeStructVariant = $crate::ser::Impossible<Self::Ok, Self::Error>;
__serialize_unimplemented_method!(serialize_struct_variant(&str, u32, &str, usize) -> SerializeStructVariant);
};
}
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
mod macros;
pub mod ser;
pub mod de;
File diff suppressed because it is too large Load Diff
-607
View File
@@ -1,607 +0,0 @@
use core::marker::PhantomData;
#[cfg(all(not(feature = "std"), feature = "collections"))]
use collections::{String, Vec};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::boxed::Box;
#[cfg(feature = "collections")]
use collections::borrow::ToOwned;
use ser::{self, Serialize, Serializer};
pub struct SerializeTupleVariantAsMapValue<M> {
map: M,
name: &'static str,
fields: Vec<Content>,
}
impl<M> SerializeTupleVariantAsMapValue<M> {
pub fn new(map: M, name: &'static str, len: usize) -> Self {
SerializeTupleVariantAsMapValue {
map: map,
name: name,
fields: Vec::with_capacity(len),
}
}
}
impl<M> ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue<M>
where M: ser::SerializeMap
{
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), M::Error> {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
self.map.end()
}
}
pub struct SerializeStructVariantAsMapValue<M> {
map: M,
name: &'static str,
fields: Vec<(&'static str, Content)>,
}
impl<M> SerializeStructVariantAsMapValue<M> {
pub fn new(map: M, name: &'static str, len: usize) -> Self {
SerializeStructVariantAsMapValue {
map: map,
name: name,
fields: Vec::with_capacity(len),
}
}
}
impl<M> ser::SerializeStructVariant for SerializeStructVariantAsMapValue<M>
where M: ser::SerializeMap
{
type Ok = M::Ok;
type Error = M::Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), M::Error> {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
self.map.end()
}
}
#[derive(Debug)]
enum Content {
Bool(bool),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
F32(f32),
F64(f64),
Char(char),
String(String),
Bytes(Vec<u8>),
None,
Some(Box<Content>),
Unit,
UnitStruct(&'static str),
UnitVariant(&'static str, usize, &'static str),
NewtypeStruct(&'static str, Box<Content>),
NewtypeVariant(&'static str, usize, &'static str, Box<Content>),
Seq(Vec<Content>),
SeqFixedSize(Vec<Content>),
Tuple(Vec<Content>),
TupleStruct(&'static str, Vec<Content>),
TupleVariant(&'static str, usize, &'static str, Vec<Content>),
Map(Vec<(Content, Content)>),
Struct(&'static str, Vec<(&'static str, Content)>),
StructVariant(&'static str, usize, &'static str, Vec<(&'static str, Content)>),
}
impl Serialize for Content {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
match *self {
Content::Bool(b) => serializer.serialize_bool(b),
Content::U8(u) => serializer.serialize_u8(u),
Content::U16(u) => serializer.serialize_u16(u),
Content::U32(u) => serializer.serialize_u32(u),
Content::U64(u) => serializer.serialize_u64(u),
Content::I8(i) => serializer.serialize_i8(i),
Content::I16(i) => serializer.serialize_i16(i),
Content::I32(i) => serializer.serialize_i32(i),
Content::I64(i) => serializer.serialize_i64(i),
Content::F32(f) => serializer.serialize_f32(f),
Content::F64(f) => serializer.serialize_f64(f),
Content::Char(c) => serializer.serialize_char(c),
Content::String(ref s) => serializer.serialize_str(s),
Content::Bytes(ref b) => serializer.serialize_bytes(b),
Content::None => serializer.serialize_none(),
Content::Some(ref c) => serializer.serialize_some(&**c),
Content::Unit => serializer.serialize_unit(),
Content::UnitStruct(n) => serializer.serialize_unit_struct(n),
Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v),
Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c),
Content::NewtypeVariant(n, i, v, ref c) => {
serializer.serialize_newtype_variant(n, i, v, &**c)
}
Content::Seq(ref elements) => elements.serialize(serializer),
Content::SeqFixedSize(ref elements) => {
use ser::SerializeSeq;
let mut seq = try!(serializer.serialize_seq_fixed_size(elements.len()));
for e in elements {
try!(seq.serialize_element(e));
}
seq.end()
}
Content::Tuple(ref elements) => {
use ser::SerializeTuple;
let mut tuple = try!(serializer.serialize_tuple(elements.len()));
for e in elements {
try!(tuple.serialize_element(e));
}
tuple.end()
}
Content::TupleStruct(n, ref fields) => {
use ser::SerializeTupleStruct;
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len()));
for f in fields {
try!(ts.serialize_field(f));
}
ts.end()
}
Content::TupleVariant(n, i, v, ref fields) => {
use ser::SerializeTupleVariant;
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
for f in fields {
try!(tv.serialize_field(f));
}
tv.end()
}
Content::Map(ref entries) => {
use ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len())));
for &(ref k, ref v) in entries {
try!(map.serialize_entry(k, v));
}
map.end()
}
Content::Struct(n, ref fields) => {
use ser::SerializeStruct;
let mut s = try!(serializer.serialize_struct(n, fields.len()));
for &(k, ref v) in fields {
try!(s.serialize_field(k, v));
}
s.end()
}
Content::StructVariant(n, i, v, ref fields) => {
use ser::SerializeStructVariant;
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len()));
for &(k, ref v) in fields {
try!(sv.serialize_field(k, v));
}
sv.end()
}
}
}
}
struct ContentSerializer<E> {
error: PhantomData<E>,
}
impl<E> ContentSerializer<E> {
fn new() -> Self {
ContentSerializer { error: PhantomData }
}
}
impl<E> Serializer for ContentSerializer<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
type SerializeSeq = SerializeSeq<E>;
type SerializeTuple = SerializeTuple<E>;
type SerializeTupleStruct = SerializeTupleStruct<E>;
type SerializeTupleVariant = SerializeTupleVariant<E>;
type SerializeMap = SerializeMap<E>;
type SerializeStruct = SerializeStruct<E>;
type SerializeStructVariant = SerializeStructVariant<E>;
fn serialize_bool(self, v: bool) -> Result<Content, E> {
Ok(Content::Bool(v))
}
fn serialize_i8(self, v: i8) -> Result<Content, E> {
Ok(Content::I8(v))
}
fn serialize_i16(self, v: i16) -> Result<Content, E> {
Ok(Content::I16(v))
}
fn serialize_i32(self, v: i32) -> Result<Content, E> {
Ok(Content::I32(v))
}
fn serialize_i64(self, v: i64) -> Result<Content, E> {
Ok(Content::I64(v))
}
fn serialize_u8(self, v: u8) -> Result<Content, E> {
Ok(Content::U8(v))
}
fn serialize_u16(self, v: u16) -> Result<Content, E> {
Ok(Content::U16(v))
}
fn serialize_u32(self, v: u32) -> Result<Content, E> {
Ok(Content::U32(v))
}
fn serialize_u64(self, v: u64) -> Result<Content, E> {
Ok(Content::U64(v))
}
fn serialize_f32(self, v: f32) -> Result<Content, E> {
Ok(Content::F32(v))
}
fn serialize_f64(self, v: f64) -> Result<Content, E> {
Ok(Content::F64(v))
}
fn serialize_char(self, v: char) -> Result<Content, E> {
Ok(Content::Char(v))
}
fn serialize_str(self, value: &str) -> Result<Content, E> {
Ok(Content::String(value.to_owned()))
}
fn serialize_bytes(self, value: &[u8]) -> Result<Content, E> {
Ok(Content::Bytes(value.to_owned()))
}
fn serialize_none(self) -> Result<Content, E> {
Ok(Content::None)
}
fn serialize_some<T: ?Sized + Serialize>(self, value: &T) -> Result<Content, E> {
Ok(Content::Some(Box::new(try!(value.serialize(self)))))
}
fn serialize_unit(self) -> Result<Content, E> {
Ok(Content::Unit)
}
fn serialize_unit_struct(self, name: &'static str) -> Result<Content, E> {
Ok(Content::UnitStruct(name))
}
fn serialize_unit_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str)
-> Result<Content, E> {
Ok(Content::UnitVariant(name, variant_index, variant))
}
fn serialize_newtype_struct<T: ?Sized + Serialize>(self,
name: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))))
}
fn serialize_newtype_variant<T: ?Sized + Serialize>(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
value: &T)
-> Result<Content, E> {
Ok(Content::NewtypeVariant(name,
variant_index,
variant,
Box::new(try!(value.serialize(self)))))
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: false,
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
})
}
fn serialize_seq_fixed_size(self, size: usize) -> Result<Self::SerializeSeq, E> {
Ok(SerializeSeq {
fixed_size: true,
elements: Vec::with_capacity(size),
error: PhantomData,
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
Ok(SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeTupleStruct, E> {
Ok(SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, E> {
Ok(SerializeTupleVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
Ok(SerializeMap {
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
})
}
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, E> {
Ok(SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_struct_variant(self,
name: &'static str,
variant_index: usize,
variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, E> {
Ok(SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
}
struct SerializeSeq<E> {
fixed_size: bool,
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeSeq for SerializeSeq<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(if self.fixed_size {
Content::SeqFixedSize(self.elements)
} else {
Content::Seq(self.elements)
})
}
}
struct SerializeTuple<E> {
elements: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTuple for SerializeTuple<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_element<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Tuple(self.elements))
}
}
struct SerializeTupleStruct<E> {
name: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleStruct for SerializeTupleStruct<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleStruct(self.name, self.fields))
}
}
struct SerializeTupleVariant<E> {
name: &'static str,
variant_index: usize,
variant: &'static str,
fields: Vec<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeTupleVariant for SerializeTupleVariant<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields))
}
}
struct SerializeMap<E> {
entries: Vec<(Content, Content)>,
key: Option<Content>,
error: PhantomData<E>,
}
impl<E> ser::SerializeMap for SerializeMap<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_key<T: ?Sized + Serialize>(&mut self, key: &T) -> Result<(), E> {
let key = try!(key.serialize(ContentSerializer::<E>::new()));
self.key = Some(key);
Ok(())
}
fn serialize_value<T: ?Sized + Serialize>(&mut self, value: &T) -> Result<(), E> {
let key = self.key.take().expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Map(self.entries))
}
fn serialize_entry<K: ?Sized + Serialize, V: ?Sized + Serialize>(&mut self,
key: &K,
value: &V)
-> Result<(), E> {
let key = try!(key.serialize(ContentSerializer::<E>::new()));
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value));
Ok(())
}
}
struct SerializeStruct<E> {
name: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStruct for SerializeStruct<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::Struct(self.name, self.fields))
}
}
struct SerializeStructVariant<E> {
name: &'static str,
variant_index: usize,
variant: &'static str,
fields: Vec<(&'static str, Content)>,
error: PhantomData<E>,
}
impl<E> ser::SerializeStructVariant for SerializeStructVariant<E>
where E: ser::Error
{
type Ok = Content;
type Error = E;
fn serialize_field<T: ?Sized + Serialize>(&mut self,
key: &'static str,
value: &T)
-> Result<(), E> {
let value = try!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value));
Ok(())
}
fn end(self) -> Result<Content, E> {
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields))
}
}
+280 -495
View File
File diff suppressed because it is too large Load Diff
+120 -49
View File
@@ -1,6 +1,14 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module contains `Impossible` serializer and its implementations. //! This module contains `Impossible` serializer and its implementations.
use core::marker::PhantomData; use lib::*;
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct, use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant}; SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
@@ -9,11 +17,19 @@ use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
/// serializing one of the compound types. /// serializing one of the compound types.
/// ///
/// This type cannot be instantiated, but implements every one of the traits /// This type cannot be instantiated, but implements every one of the traits
/// corresponding to the `Serializer` compound types: `SerializeSeq`, /// corresponding to the [`Serializer`] compound types: [`SerializeSeq`],
/// `SerializeTuple`, `SerializeTupleStruct`, `SerializeTupleVariant`, /// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
/// `SerializeMap`, `SerializeStruct`, and `SerializeStructVariant`. /// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
/// ///
/// ```rust,ignore /// ```rust
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::ser::{Serializer, Impossible};
/// # use serde::private::ser::Error;
/// #
/// # struct MySerializer;
/// #
/// impl Serializer for MySerializer { /// impl Serializer for MySerializer {
/// type Ok = (); /// type Ok = ();
/// type Error = Error; /// type Error = Error;
@@ -27,130 +43,185 @@ use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
/// -> Result<Self::SerializeSeq, Error> { /// -> Result<Self::SerializeSeq, Error> {
/// // Given Impossible cannot be instantiated, the only /// // Given Impossible cannot be instantiated, the only
/// // thing we can do here is to return an error. /// // thing we can do here is to return an error.
/// # stringify! {
/// Err(...) /// Err(...)
/// # };
/// # unimplemented!()
/// } /// }
/// ///
/// /* other Serializer methods */ /// /* other Serializer methods */
/// # __serialize_unimplemented! {
/// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant
/// # tuple tuple_struct tuple_variant map struct struct_variant
/// # }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
pub struct Impossible<Ok, E> { ///
/// [`Serializer`]: trait.Serializer.html
/// [`SerializeSeq`]: trait.SerializeSeq.html
/// [`SerializeTuple`]: trait.SerializeTuple.html
/// [`SerializeTupleStruct`]: trait.SerializeTupleStruct.html
/// [`SerializeTupleVariant`]: trait.SerializeTupleVariant.html
/// [`SerializeMap`]: trait.SerializeMap.html
/// [`SerializeStruct`]: trait.SerializeStruct.html
/// [`SerializeStructVariant`]: trait.SerializeStructVariant.html
pub struct Impossible<Ok, Error> {
void: Void, void: Void,
_marker: PhantomData<(Ok, E)>, ok: PhantomData<Ok>,
error: PhantomData<Error>,
} }
enum Void {} enum Void {}
impl<Ok, E> SerializeSeq for Impossible<Ok, E> impl<Ok, Error> SerializeSeq for Impossible<Ok, Error>
where E: ser::Error where
Error: ser::Error,
{ {
type Ok = Ok; type Ok = Ok;
type Error = E; type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> { fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {} match self.void {}
} }
fn end(self) -> Result<Ok, E> { fn end(self) -> Result<Ok, Error> {
match self.void {} match self.void {}
} }
} }
impl<Ok, E> SerializeTuple for Impossible<Ok, E> impl<Ok, Error> SerializeTuple for Impossible<Ok, Error>
where E: ser::Error where
Error: ser::Error,
{ {
type Ok = Ok; type Ok = Ok;
type Error = E; type Error = Error;
fn serialize_element<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> { fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {} match self.void {}
} }
fn end(self) -> Result<Ok, E> { fn end(self) -> Result<Ok, Error> {
match self.void {} match self.void {}
} }
} }
impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E> impl<Ok, Error> SerializeTupleStruct for Impossible<Ok, Error>
where E: ser::Error where
Error: ser::Error,
{ {
type Ok = Ok; type Ok = Ok;
type Error = E; type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> { fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {} match self.void {}
} }
fn end(self) -> Result<Ok, E> { fn end(self) -> Result<Ok, Error> {
match self.void {} match self.void {}
} }
} }
impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E> impl<Ok, Error> SerializeTupleVariant for Impossible<Ok, Error>
where E: ser::Error where
Error: ser::Error,
{ {
type Ok = Ok; type Ok = Ok;
type Error = E; type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> { fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {} match self.void {}
} }
fn end(self) -> Result<Ok, E> { fn end(self) -> Result<Ok, Error> {
match self.void {} match self.void {}
} }
} }
impl<Ok, E> SerializeMap for Impossible<Ok, E> impl<Ok, Error> SerializeMap for Impossible<Ok, Error>
where E: ser::Error where
Error: ser::Error,
{ {
type Ok = Ok; type Ok = Ok;
type Error = E; type Error = Error;
fn serialize_key<T: ?Sized + Serialize>(&mut self, _key: &T) -> Result<(), E> { fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = key;
match self.void {} match self.void {}
} }
fn serialize_value<T: ?Sized + Serialize>(&mut self, _value: &T) -> Result<(), E> { fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where
T: Serialize,
{
let _ = value;
match self.void {} match self.void {}
} }
fn end(self) -> Result<Ok, E> { fn end(self) -> Result<Ok, Error> {
match self.void {} match self.void {}
} }
} }
impl<Ok, E> SerializeStruct for Impossible<Ok, E> impl<Ok, Error> SerializeStruct for Impossible<Ok, Error>
where E: ser::Error where
Error: ser::Error,
{ {
type Ok = Ok; type Ok = Ok;
type Error = E; type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
_key: &'static str, where
_value: &T) T: Serialize,
-> Result<(), E> { {
let _ = key;
let _ = value;
match self.void {} match self.void {}
} }
fn end(self) -> Result<Ok, E> { fn end(self) -> Result<Ok, Error> {
match self.void {} match self.void {}
} }
} }
impl<Ok, E> SerializeStructVariant for Impossible<Ok, E> impl<Ok, Error> SerializeStructVariant for Impossible<Ok, Error>
where E: ser::Error where
Error: ser::Error,
{ {
type Ok = Ok; type Ok = Ok;
type Error = E; type Error = Error;
fn serialize_field<T: ?Sized + Serialize>(&mut self, fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
_key: &'static str, where
_value: &T) T: Serialize,
-> Result<(), E> { {
let _ = key;
let _ = value;
match self.void {} match self.void {}
} }
fn end(self) -> Result<Ok, E> { fn end(self) -> Result<Ok, Error> {
match self.void {} match self.void {}
} }
} }
+1227 -341
View File
File diff suppressed because it is too large Load Diff
-315
View File
@@ -1,315 +0,0 @@
use core::fmt::{self, Display};
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
#[cfg(any(feature = "std", feature = "collections"))]
use ser::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
/// Not public API.
pub fn serialize_tagged_newtype<S, T>(serializer: S,
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
value: &T)
-> Result<S::Ok, S::Error>
where S: Serializer,
T: Serialize
{
value.serialize(TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
})
}
struct TaggedSerializer<S> {
type_ident: &'static str,
variant_ident: &'static str,
tag: &'static str,
variant_name: &'static str,
delegate: S,
}
enum Unsupported {
Boolean,
Integer,
Float,
Char,
String,
ByteArray,
Optional,
Unit,
UnitStruct,
Sequence,
Tuple,
TupleStruct,
#[cfg(not(any(feature = "std", feature = "collections")))]
Enum,
}
impl Display for Unsupported {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match *self {
Unsupported::Boolean => formatter.write_str("a boolean"),
Unsupported::Integer => formatter.write_str("an integer"),
Unsupported::Float => formatter.write_str("a float"),
Unsupported::Char => formatter.write_str("a char"),
Unsupported::String => formatter.write_str("a string"),
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
Unsupported::Unit => formatter.write_str("unit"),
Unsupported::UnitStruct => formatter.write_str("a unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "collections")))]
Unsupported::Enum => formatter.write_str("an enum"),
}
}
}
struct Error {
type_ident: &'static str,
variant_ident: &'static str,
ty: Unsupported,
}
impl Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter,
"cannot serialize tagged newtype variant {}::{} containing {}",
self.type_ident,
self.variant_ident,
self.ty)
}
}
impl<S> TaggedSerializer<S>
where S: Serializer
{
fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom(Error {
type_ident: self.type_ident,
variant_ident: self.variant_ident,
ty: what,
})
}
}
impl<S> Serializer for TaggedSerializer<S>
where S: Serializer
{
type Ok = S::Ok;
type Error = S::Error;
type SerializeSeq = Impossible<S::Ok, S::Error>;
type SerializeTuple = Impossible<S::Ok, S::Error>;
type SerializeTupleStruct = Impossible<S::Ok, S::Error>;
type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct;
#[cfg(not(any(feature = "std", feature = "collections")))]
type SerializeTupleVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))]
type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>;
#[cfg(not(any(feature = "std", feature = "collections")))]
type SerializeStructVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))]
type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where T: Serialize
{
Err(self.bad_type(Unsupported::Optional))
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str)
-> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, &()));
map.end()
}
fn serialize_newtype_struct<T: ?Sized>(self,
_: &'static str,
value: &T)
-> Result<Self::Ok, Self::Error>
where T: Serialize
{
value.serialize(self)
}
fn serialize_newtype_variant<T: ?Sized>(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
inner_value: &T)
-> Result<Self::Ok, Self::Error>
where T: Serialize
{
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, inner_value));
map.end()
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_seq_fixed_size(self, _: usize) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(self,
_: &'static str,
_: usize)
-> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_tuple_variant(self,
_: &'static str,
_: usize,
_: &'static str,
_: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> {
// Lack of push-based serialization means we need to buffer the content
// of the tuple variant, so it requires std.
Err(self.bad_type(Unsupported::Enum))
}
#[cfg(any(feature = "std", feature = "collections"))]
fn serialize_tuple_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
len: usize)
-> Result<Self::SerializeTupleVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1)));
try!(map.serialize_entry(self.tag, self.variant_name));
Ok(map)
}
fn serialize_struct(self,
name: &'static str,
len: usize)
-> Result<Self::SerializeStruct, Self::Error> {
let mut state = try!(self.delegate.serialize_struct(name, len + 1));
try!(state.serialize_field(self.tag, self.variant_name));
Ok(state)
}
#[cfg(not(any(feature = "std", feature = "collections")))]
fn serialize_struct_variant(self,
_: &'static str,
_: usize,
_: &'static str,
_: usize)
-> Result<Self::SerializeStructVariant, Self::Error> {
// Lack of push-based serialization means we need to buffer the content
// of the struct variant, so it requires std.
Err(self.bad_type(Unsupported::Enum))
}
#[cfg(any(feature = "std", feature = "collections"))]
fn serialize_struct_variant(self,
_: &'static str,
_: usize,
inner_variant: &'static str,
len: usize)
-> Result<Self::SerializeStructVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len))
}
}
-74
View File
@@ -1,74 +0,0 @@
//! Private utility functions
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
#[inline]
pub fn encode_utf8(c: char) -> EncodeUtf8 {
let code = c as u32;
let mut buf = [0; 4];
let pos = if code < MAX_ONE_B {
buf[3] = code as u8;
3
} else if code < MAX_TWO_B {
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
2
} else if code < MAX_THREE_B {
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
1
} else {
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
0
};
EncodeUtf8 {
buf: buf,
pos: pos,
}
}
pub struct EncodeUtf8 {
buf: [u8; 4],
pos: usize,
}
impl EncodeUtf8 {
// FIXME: use this from_utf8_unchecked, since we know it can never fail
pub fn as_str(&self) -> &str {
::core::str::from_utf8(&self.buf[self.pos..]).unwrap()
}
}
#[allow(non_upper_case_globals)]
const Pattern_White_Space_table: &'static [(char, char)] = &[('\u{9}', '\u{d}'),
('\u{20}', '\u{20}'),
('\u{85}', '\u{85}'),
('\u{200e}', '\u{200f}'),
('\u{2028}', '\u{2029}')];
fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool {
use core::cmp::Ordering::{Equal, Less, Greater};
r.binary_search_by(|&(lo, hi)| if c < lo {
Greater
} else if hi < c {
Less
} else {
Equal
})
.is_ok()
}
#[allow(non_snake_case)]
pub fn Pattern_White_Space(c: char) -> bool {
bsearch_range_table(c, Pattern_White_Space_table)
}
-9
View File
@@ -1,9 +0,0 @@
extern crate syn;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
+4 -6
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "0.9.14" version = "0.9.14" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -8,11 +8,9 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html" documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization", "no_std"] keywords = ["serde", "serialization", "no_std"]
readme = "../README.md" readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
publish = false # this branch contains breaking changes
[features]
unstable = []
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
@@ -23,5 +21,5 @@ proc-macro = true
[dependencies] [dependencies]
quote = "0.3.8" quote = "0.3.8"
serde_codegen_internals = { version = "=0.14.2", default-features = false, path = "../serde_codegen_internals" } serde_derive_internals = { version = "=0.14.2", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.11", features = ["visit"] } syn = { version = "0.11", features = ["visit"] }
+126 -102
View File
@@ -1,33 +1,21 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::collections::HashSet; use std::collections::HashSet;
use syn::{self, visit}; use syn::{self, visit};
use internals::ast::Item; use internals::ast::Container;
use internals::attr; use internals::attr;
macro_rules! path { macro_rules! path {
($first:ident $(:: $rest:ident)*) => { ($($path:tt)+) => {
syn::Path { syn::parse_path(stringify!($($path)+)).unwrap()
global: false,
segments: vec![
stringify!($first).into(),
$(
stringify!($rest).into(),
)*
],
}
};
(::$first:ident $(:: $rest:ident)*) => {
syn::Path {
global: true,
segments: vec![
stringify!($first).into(),
$(
stringify!($rest).into(),
)*
],
}
}; };
} }
@@ -36,29 +24,43 @@ macro_rules! path {
// allowed here". // allowed here".
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics { pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
syn::Generics { syn::Generics {
ty_params: generics.ty_params ty_params: generics
.ty_params
.iter() .iter()
.map(|ty_param| syn::TyParam { default: None, ..ty_param.clone() }) .map(
|ty_param| {
syn::TyParam {
default: None,
..ty_param.clone()
}
},
)
.collect(), .collect(),
..generics.clone() ..generics.clone()
} }
} }
pub fn with_where_predicates(generics: &syn::Generics, pub fn with_where_predicates(
predicates: &[syn::WherePredicate]) generics: &syn::Generics,
-> syn::Generics { predicates: &[syn::WherePredicate],
) -> syn::Generics {
let mut generics = generics.clone(); let mut generics = generics.clone();
generics.where_clause.predicates.extend_from_slice(predicates); generics
.where_clause
.predicates
.extend_from_slice(predicates);
generics generics
} }
pub fn with_where_predicates_from_fields<F>(item: &Item, pub fn with_where_predicates_from_fields<F>(
generics: &syn::Generics, cont: &Container,
from_field: F) generics: &syn::Generics,
-> syn::Generics from_field: F,
where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]> ) -> syn::Generics
where
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
{ {
let predicates = item.body let predicates = cont.body
.all_fields() .all_fields()
.flat_map(|field| from_field(&field.attrs)) .flat_map(|field| from_field(&field.attrs))
.flat_map(|predicates| predicates.to_vec()); .flat_map(|predicates| predicates.to_vec());
@@ -79,12 +81,14 @@ pub fn with_where_predicates_from_fields<F>(item: &Item,
// #[serde(skip_serializing)] // #[serde(skip_serializing)]
// c: C, // c: C,
// } // }
pub fn with_bound<F>(item: &Item, pub fn with_bound<F>(
generics: &syn::Generics, cont: &Container,
filter: F, generics: &syn::Generics,
bound: &syn::Path) filter: F,
-> syn::Generics bound: &syn::Path,
where F: Fn(&attr::Field) -> bool ) -> syn::Generics
where
F: Fn(&attr::Field) -> bool,
{ {
struct FindTyParams { struct FindTyParams {
// Set of all generic type parameters on the current struct (A, B, C in // Set of all generic type parameters on the current struct (A, B, C in
@@ -114,12 +118,13 @@ pub fn with_bound<F>(item: &Item,
} }
} }
let all_ty_params: HashSet<_> = generics.ty_params let all_ty_params: HashSet<_> = generics
.ty_params
.iter() .iter()
.map(|ty_param| ty_param.ident.clone()) .map(|ty_param| ty_param.ident.clone())
.collect(); .collect();
let relevant_tys = item.body let relevant_tys = cont.body
.all_fields() .all_fields()
.filter(|&field| filter(&field.attrs)) .filter(|&field| filter(&field.attrs))
.map(|field| &field.ty); .map(|field| &field.ty);
@@ -132,58 +137,66 @@ pub fn with_bound<F>(item: &Item,
visit::walk_ty(&mut visitor, ty); visit::walk_ty(&mut visitor, ty);
} }
let new_predicates = generics.ty_params let new_predicates = generics
.ty_params
.iter() .iter()
.map(|ty_param| ty_param.ident.clone()) .map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id)) .filter(|id| visitor.relevant_ty_params.contains(id))
.map(|id| { .map(
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate { |id| {
bound_lifetimes: Vec::new(), syn::WherePredicate::BoundPredicate(
// the type parameter that is being bounded e.g. T syn::WhereBoundPredicate {
bounded_ty: syn::Ty::Path(None, id.into()),
// the bound e.g. Serialize
bounds: vec![syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(), bound_lifetimes: Vec::new(),
trait_ref: bound.clone(), // the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
// the bound e.g. Serialize
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
}, },
syn::TraitBoundModifier::None )
)], },
}) );
});
let mut generics = generics.clone(); let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates); generics.where_clause.predicates.extend(new_predicates);
generics generics
} }
pub fn with_self_bound(item: &Item, pub fn with_self_bound(cont: &Container, generics: &syn::Generics, bound: &syn::Path) -> syn::Generics {
generics: &syn::Generics,
bound: &syn::Path)
-> syn::Generics
{
let mut generics = generics.clone(); let mut generics = generics.clone();
generics.where_clause.predicates.push( generics
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate { .where_clause
bound_lifetimes: Vec::new(), .predicates
// the type that is being bounded e.g. MyStruct<'a, T> .push(
bounded_ty: type_of_item(item), syn::WherePredicate::BoundPredicate(
// the bound e.g. Default syn::WhereBoundPredicate {
bounds: vec![syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(), bound_lifetimes: Vec::new(),
trait_ref: bound.clone(), // the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
// the bound e.g. Default
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
}, },
syn::TraitBoundModifier::None ),
)], );
})
);
generics generics
} }
pub fn with_lifetime_bound(generics: &syn::Generics, pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
lifetime: &str)
-> syn::Generics {
let mut generics = generics.clone(); let mut generics = generics.clone();
for lifetime_def in &mut generics.lifetimes { for lifetime_def in &mut generics.lifetimes {
@@ -191,38 +204,49 @@ pub fn with_lifetime_bound(generics: &syn::Generics,
} }
for ty_param in &mut generics.ty_params { for ty_param in &mut generics.ty_params {
ty_param.bounds.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime))); ty_param
.bounds
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
} }
generics.lifetimes.push(syn::LifetimeDef { generics
attrs: Vec::new(), .lifetimes
lifetime: syn::Lifetime::new(lifetime), .push(
bounds: Vec::new(), syn::LifetimeDef {
}); attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
},
);
generics generics
} }
fn type_of_item(item: &Item) -> syn::Ty { fn type_of_item(cont: &Container) -> syn::Ty {
syn::Ty::Path(None, syn::Path { syn::Ty::Path(
global: false, None,
segments: vec![ syn::Path {
syn::PathSegment { global: false,
ident: item.ident.clone(), segments: vec![
parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData { syn::PathSegment {
lifetimes: item.generics ident: cont.ident.clone(),
.lifetimes parameters: syn::PathParameters::AngleBracketed(
.iter() syn::AngleBracketedParameterData {
.map(|def| def.lifetime.clone()) lifetimes: cont.generics
.collect(), .lifetimes
types: item.generics .iter()
.map(|def| def.lifetime.clone())
.collect(),
types: cont.generics
.ty_params .ty_params
.iter() .iter()
.map(|param| syn::Ty::Path(None, param.ident.clone().into())) .map(|param| syn::Ty::Path(None, param.ident.clone().into()))
.collect(), .collect(),
bindings: Vec::new(), bindings: Vec::new(),
}), },
} ),
] },
}) ],
},
)
} }
+908 -595
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use quote::{Tokens, ToTokens}; use quote::{Tokens, ToTokens};
pub enum Fragment { pub enum Fragment {
+11 -1
View File
@@ -1,3 +1,13 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive/0.9.13")]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))] #![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
@@ -8,7 +18,7 @@ extern crate syn;
#[macro_use] #[macro_use]
extern crate quote; extern crate quote;
extern crate serde_codegen_internals as internals; extern crate serde_derive_internals as internals;
extern crate proc_macro; extern crate proc_macro;
use proc_macro::TokenStream; use proc_macro::TokenStream;
+472 -325
View File
File diff suppressed because it is too large Load Diff
@@ -1,18 +1,19 @@
[package] [package]
name = "serde_codegen_internals" name = "serde_derive_internals"
version = "0.14.2" version = "0.14.2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "AST representation used by Serde codegen. Unstable." description = "AST representation used by Serde derive macros. Unstable."
homepage = "https://serde.rs" homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_codegen_internals/" documentation = "https://docs.serde.rs/serde_derive_internals/"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
readme = "../README.md" readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies] [dependencies]
syn = { version = "0.11", default-features = false, features = ["parsing"] } syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
synom = "0.11"
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
@@ -1,10 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syn; use syn;
use attr; use attr;
use check;
use Ctxt; use Ctxt;
pub struct Item<'a> { pub struct Container<'a> {
pub ident: syn::Ident, pub ident: syn::Ident,
pub attrs: attr::Item, pub attrs: attr::Container,
pub body: Body<'a>, pub body: Body<'a>,
pub generics: &'a syn::Generics, pub generics: &'a syn::Generics,
} }
@@ -27,6 +36,7 @@ pub struct Field<'a> {
pub ty: &'a syn::Ty, pub ty: &'a syn::Ty,
} }
#[derive(Copy, Clone)]
pub enum Style { pub enum Style {
Struct, Struct,
Tuple, Tuple,
@@ -34,9 +44,9 @@ pub enum Style {
Unit, Unit,
} }
impl<'a> Item<'a> { impl<'a> Container<'a> {
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> { pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Container<'a> {
let attrs = attr::Item::from_ast(cx, item); let attrs = attr::Container::from_ast(cx, item);
let mut body = match item.body { let mut body = match item.body {
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)), syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
@@ -62,12 +72,14 @@ impl<'a> Item<'a> {
} }
} }
Item { let item = Container {
ident: item.ident.clone(), ident: item.ident.clone(),
attrs: attrs, attrs: attrs,
body: body, body: body,
generics: &item.generics, generics: &item.generics,
} };
check::check(cx, &item);
item
} }
} }
@@ -81,6 +93,10 @@ impl<'a> Body<'a> {
Body::Struct(_, ref fields) => Box::new(fields.iter()), Body::Struct(_, ref fields) => Box::new(fields.iter()),
} }
} }
pub fn has_getter(&self) -> bool {
self.all_fields().any(|f| f.attrs.getter().is_some())
}
} }
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> { fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
@@ -1,11 +1,21 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use Ctxt; use Ctxt;
use syn; use syn;
use syn::MetaItem::{List, NameValue, Word}; use syn::MetaItem::{List, NameValue, Word};
use syn::NestedMetaItem::{Literal, MetaItem}; use syn::NestedMetaItem::{Literal, MetaItem};
use synom::IResult;
use std::collections::BTreeSet;
use std::str::FromStr; use std::str::FromStr;
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints // This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and // are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
// `attr::Field::from_ast`. Each returns an instance of the corresponding // `attr::Field::from_ast`. Each returns an instance of the corresponding
// struct. Note that none of them return a Result. Unrecognized, malformed, or // struct. Note that none of them return a Result. Unrecognized, malformed, or
// duplicated attributes result in a span_err but otherwise are ignored. The // duplicated attributes result in a span_err but otherwise are ignored. The
@@ -90,7 +100,7 @@ impl Name {
/// Represents container (e.g. struct) attribute information /// Represents container (e.g. struct) attribute information
#[derive(Debug)] #[derive(Debug)]
pub struct Item { pub struct Container {
name: Name, name: Name,
deny_unknown_fields: bool, deny_unknown_fields: bool,
default: Default, default: Default,
@@ -100,6 +110,8 @@ pub struct Item {
tag: EnumTag, tag: EnumTag,
from_type: Option<syn::Ty>, from_type: Option<syn::Ty>,
into_type: Option<syn::Ty>, into_type: Option<syn::Ty>,
remote: Option<syn::Path>,
identifier: Identifier,
} }
/// Styles of representing an enum. /// Styles of representing an enum.
@@ -134,7 +146,24 @@ pub enum EnumTag {
None, None,
} }
impl Item { /// Whether this enum represents the fields of a struct or the variants of an
/// enum.
#[derive(Copy, Clone, Debug)]
pub enum Identifier {
/// It does not.
No,
/// This enum represents the fields of a struct. All of the variants must be
/// unit variants, except possibly one which is annotated with
/// `#[serde(other)]` and is a newtype variant.
Field,
/// This enum represents the variants of an enum. All of the variants must
/// be unit variants.
Variant,
}
impl Container {
/// Extract out the `#[serde(...)]` attributes from an item. /// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self { pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self {
let mut ser_name = Attr::none(cx, "rename"); let mut ser_name = Attr::none(cx, "rename");
@@ -149,11 +178,14 @@ impl Item {
let mut content = Attr::none(cx, "content"); let mut content = Attr::none(cx, "content");
let mut from_type = Attr::none(cx, "from"); let mut from_type = Attr::none(cx, "from");
let mut into_type = Attr::none(cx, "into"); let mut into_type = Attr::none(cx, "into");
let mut remote = Attr::none(cx, "remote");
let mut field_identifier = BoolAttr::none(cx, "field_identifier");
let mut variant_identifier = BoolAttr::none(cx, "variant_identifier");
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) { for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items { for meta_item in meta_items {
match meta_item { match meta_item {
// Parse `#[serde(rename="foo")]` // Parse `#[serde(rename = "foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone()); ser_name.set(s.clone());
@@ -161,7 +193,7 @@ impl Item {
} }
} }
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => { MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) { if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser); ser_name.set_opt(ser);
@@ -169,7 +201,7 @@ impl Item {
} }
} }
// Parse `#[serde(rename_all="foo")]` // Parse `#[serde(rename_all = "foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => { MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) { match RenameRule::from_str(&s) {
@@ -201,7 +233,7 @@ impl Item {
} }
} }
// Parse `#[serde(default="...")]` // Parse `#[serde(default = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => { MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
match item.body { match item.body {
@@ -216,7 +248,7 @@ impl Item {
} }
} }
// Parse `#[serde(bound="D: Serialize")]` // Parse `#[serde(bound = "D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => { MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
@@ -225,7 +257,7 @@ impl Item {
} }
} }
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` // Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]`
MetaItem(List(ref name, ref meta_items)) if name == "bound" => { MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser); ser_bound.set_opt(ser);
@@ -288,6 +320,23 @@ impl Item {
} }
} }
// Parse `#[serde(remote = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "remote" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
remote.set(path);
}
}
// Parse `#[serde(field_identifier)]`
MetaItem(Word(ref name)) if name == "field_identifier" => {
field_identifier.set_true();
}
// Parse `#[serde(variant_identifier)]`
MetaItem(Word(ref name)) if name == "variant_identifier" => {
variant_identifier.set_true();
}
MetaItem(ref meta_item) => { MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`", cx.error(format!("unknown serde container attribute `{}`",
meta_item.name())); meta_item.name()));
@@ -300,53 +349,7 @@ impl Item {
} }
} }
let tag = match (untagged.get(), internal_tag.get(), content.get()) { Container {
(false, None, None) => EnumTag::External,
(true, None, None) => EnumTag::None,
(false, Some(tag), None) => {
// Check that there are no tuple variants.
if let syn::Body::Enum(ref variants) = item.body {
for variant in variants {
match variant.data {
syn::VariantData::Struct(_) |
syn::VariantData::Unit => {}
syn::VariantData::Tuple(ref fields) => {
if fields.len() != 1 {
cx.error("#[serde(tag = \"...\")] cannot be used with tuple \
variants");
break;
}
}
}
}
}
EnumTag::Internal { tag: tag }
}
(true, Some(_), None) => {
cx.error("enum cannot be both untagged and internally tagged");
EnumTag::External // doesn't matter, will error
}
(false, None, Some(_)) => {
cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together");
EnumTag::External
}
(true, None, Some(_)) => {
cx.error("untagged enum cannot have #[serde(content = \"...\")]");
EnumTag::External
}
(false, Some(tag), Some(content)) => {
EnumTag::Adjacent {
tag: tag,
content: content,
}
}
(true, Some(_), Some(_)) => {
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
EnumTag::External
}
};
Item {
name: Name { name: Name {
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()), serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()), deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
@@ -356,9 +359,11 @@ impl Item {
rename_all: rename_all.get().unwrap_or(RenameRule::None), rename_all: rename_all.get().unwrap_or(RenameRule::None),
ser_bound: ser_bound.get(), ser_bound: ser_bound.get(),
de_bound: de_bound.get(), de_bound: de_bound.get(),
tag: tag, tag: decide_tag(cx, item, untagged, internal_tag, content),
from_type: from_type.get(), from_type: from_type.get(),
into_type: into_type.get(), into_type: into_type.get(),
remote: remote.get(),
identifier: decide_identifier(cx, item, field_identifier, variant_identifier),
} }
} }
@@ -397,6 +402,93 @@ impl Item {
pub fn into_type(&self) -> Option<&syn::Ty> { pub fn into_type(&self) -> Option<&syn::Ty> {
self.into_type.as_ref() self.into_type.as_ref()
} }
pub fn remote(&self) -> Option<&syn::Path> {
self.remote.as_ref()
}
pub fn identifier(&self) -> Identifier {
self.identifier
}
}
fn decide_tag(
cx: &Ctxt,
item: &syn::MacroInput,
untagged: BoolAttr,
internal_tag: Attr<String>,
content: Attr<String>,
) -> EnumTag {
match (untagged.get(), internal_tag.get(), content.get()) {
(false, None, None) => EnumTag::External,
(true, None, None) => EnumTag::None,
(false, Some(tag), None) => {
// Check that there are no tuple variants.
if let syn::Body::Enum(ref variants) = item.body {
for variant in variants {
match variant.data {
syn::VariantData::Struct(_) |
syn::VariantData::Unit => {}
syn::VariantData::Tuple(ref fields) => {
if fields.len() != 1 {
cx.error("#[serde(tag = \"...\")] cannot be used with tuple \
variants");
break;
}
}
}
}
}
EnumTag::Internal { tag: tag }
}
(true, Some(_), None) => {
cx.error("enum cannot be both untagged and internally tagged");
EnumTag::External // doesn't matter, will error
}
(false, None, Some(_)) => {
cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together");
EnumTag::External
}
(true, None, Some(_)) => {
cx.error("untagged enum cannot have #[serde(content = \"...\")]");
EnumTag::External
}
(false, Some(tag), Some(content)) => {
EnumTag::Adjacent {
tag: tag,
content: content,
}
}
(true, Some(_), Some(_)) => {
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
EnumTag::External
}
}
}
fn decide_identifier(
cx: &Ctxt,
item: &syn::MacroInput,
field_identifier: BoolAttr,
variant_identifier: BoolAttr,
) -> Identifier {
match (&item.body, field_identifier.get(), variant_identifier.get()) {
(_, false, false) => Identifier::No,
(_, true, true) => {
cx.error("`field_identifier` and `variant_identifier` cannot both be set");
Identifier::No
}
(&syn::Body::Struct(_), true, false) => {
cx.error("`field_identifier` can only be used on an enum");
Identifier::No
}
(&syn::Body::Struct(_), false, true) => {
cx.error("`variant_identifier` can only be used on an enum");
Identifier::No
}
(&syn::Body::Enum(_), true, false) => Identifier::Field,
(&syn::Body::Enum(_), false, true) => Identifier::Variant,
}
} }
/// Represents variant attribute information /// Represents variant attribute information
@@ -408,6 +500,7 @@ pub struct Variant {
rename_all: RenameRule, rename_all: RenameRule,
skip_deserializing: bool, skip_deserializing: bool,
skip_serializing: bool, skip_serializing: bool,
other: bool,
} }
impl Variant { impl Variant {
@@ -417,11 +510,12 @@ impl Variant {
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing"); let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing"); let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
let mut rename_all = Attr::none(cx, "rename_all"); let mut rename_all = Attr::none(cx, "rename_all");
let mut other = BoolAttr::none(cx, "other");
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) { for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items { for meta_item in meta_items {
match meta_item { match meta_item {
// Parse `#[serde(rename="foo")]` // Parse `#[serde(rename = "foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone()); ser_name.set(s.clone());
@@ -429,7 +523,7 @@ impl Variant {
} }
} }
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => { MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) { if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser); ser_name.set_opt(ser);
@@ -437,7 +531,7 @@ impl Variant {
} }
} }
// Parse `#[serde(rename_all="foo")]` // Parse `#[serde(rename_all = "foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => { MetaItem(NameValue(ref name, ref lit)) if name == "rename_all" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) { match RenameRule::from_str(&s) {
@@ -455,11 +549,17 @@ impl Variant {
MetaItem(Word(ref name)) if name == "skip_deserializing" => { MetaItem(Word(ref name)) if name == "skip_deserializing" => {
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip_serializing)]` // Parse `#[serde(skip_serializing)]`
MetaItem(Word(ref name)) if name == "skip_serializing" => { MetaItem(Word(ref name)) if name == "skip_serializing" => {
skip_serializing.set_true(); skip_serializing.set_true();
} }
// Parse `#[serde(other)]`
MetaItem(Word(ref name)) if name == "other" => {
other.set_true();
}
MetaItem(ref meta_item) => { MetaItem(ref meta_item) => {
cx.error(format!("unknown serde variant attribute `{}`", meta_item.name())); cx.error(format!("unknown serde variant attribute `{}`", meta_item.name()));
} }
@@ -485,6 +585,7 @@ impl Variant {
rename_all: rename_all.get().unwrap_or(RenameRule::None), rename_all: rename_all.get().unwrap_or(RenameRule::None),
skip_deserializing: skip_deserializing.get(), skip_deserializing: skip_deserializing.get(),
skip_serializing: skip_serializing.get(), skip_serializing: skip_serializing.get(),
other: other.get(),
} }
} }
@@ -512,6 +613,10 @@ impl Variant {
pub fn skip_serializing(&self) -> bool { pub fn skip_serializing(&self) -> bool {
self.skip_serializing self.skip_serializing
} }
pub fn other(&self) -> bool {
self.other
}
} }
/// Represents field attribute information /// Represents field attribute information
@@ -528,6 +633,8 @@ pub struct Field {
deserialize_with: Option<syn::Path>, deserialize_with: Option<syn::Path>,
ser_bound: Option<Vec<syn::WherePredicate>>, ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>, de_bound: Option<Vec<syn::WherePredicate>>,
borrowed_lifetimes: BTreeSet<syn::Lifetime>,
getter: Option<syn::Path>,
} }
/// Represents the default to use for a field when deserializing. /// Represents the default to use for a field when deserializing.
@@ -554,6 +661,8 @@ impl Field {
let mut deserialize_with = Attr::none(cx, "deserialize_with"); let mut deserialize_with = Attr::none(cx, "deserialize_with");
let mut ser_bound = Attr::none(cx, "bound"); let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound"); let mut de_bound = Attr::none(cx, "bound");
let mut borrowed_lifetimes = Attr::none(cx, "borrow");
let mut getter = Attr::none(cx, "getter");
let ident = match field.ident { let ident = match field.ident {
Some(ref ident) => ident.to_string(), Some(ref ident) => ident.to_string(),
@@ -563,7 +672,7 @@ impl Field {
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) { for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items { for meta_item in meta_items {
match meta_item { match meta_item {
// Parse `#[serde(rename="foo")]` // Parse `#[serde(rename = "foo")]`
MetaItem(NameValue(ref name, ref lit)) if name == "rename" => { MetaItem(NameValue(ref name, ref lit)) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
ser_name.set(s.clone()); ser_name.set(s.clone());
@@ -571,7 +680,7 @@ impl Field {
} }
} }
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` // Parse `#[serde(rename(serialize = "foo", deserialize = "bar"))]`
MetaItem(List(ref name, ref meta_items)) if name == "rename" => { MetaItem(List(ref name, ref meta_items)) if name == "rename" => {
if let Ok((ser, de)) = get_renames(cx, meta_items) { if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser); ser_name.set_opt(ser);
@@ -584,7 +693,7 @@ impl Field {
default.set(Default::Default); default.set(Default::Default);
} }
// Parse `#[serde(default="...")]` // Parse `#[serde(default = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => { MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
default.set(Default::Path(path)); default.set(Default::Path(path));
@@ -601,28 +710,28 @@ impl Field {
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip_serializing_if="...")]` // Parse `#[serde(skip_serializing_if = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => { MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
skip_serializing_if.set(path); skip_serializing_if.set(path);
} }
} }
// Parse `#[serde(serialize_with="...")]` // Parse `#[serde(serialize_with = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => { MetaItem(NameValue(ref name, ref lit)) if name == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
serialize_with.set(path); serialize_with.set(path);
} }
} }
// Parse `#[serde(deserialize_with="...")]` // Parse `#[serde(deserialize_with = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => { MetaItem(NameValue(ref name, ref lit)) if name == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
deserialize_with.set(path); deserialize_with.set(path);
} }
} }
// Parse `#[serde(with="...")]` // Parse `#[serde(with = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "with" => { MetaItem(NameValue(ref name, ref lit)) if name == "with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
let mut ser_path = path.clone(); let mut ser_path = path.clone();
@@ -634,7 +743,7 @@ impl Field {
} }
} }
// Parse `#[serde(bound="D: Serialize")]` // Parse `#[serde(bound = "D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => { MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) { parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
@@ -643,7 +752,7 @@ impl Field {
} }
} }
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]` // Parse `#[serde(bound(serialize = "D: Serialize", deserialize = "D: Deserialize"))]`
MetaItem(List(ref name, ref meta_items)) if name == "bound" => { MetaItem(List(ref name, ref meta_items)) if name == "bound" => {
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) { if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser); ser_bound.set_opt(ser);
@@ -651,6 +760,34 @@ impl Field {
} }
} }
// Parse `#[serde(borrow)]`
MetaItem(Word(ref name)) if name == "borrow" => {
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
borrowed_lifetimes.set(borrowable);
}
}
// Parse `#[serde(borrow = "'a + 'b")]`
MetaItem(NameValue(ref name, ref lit)) if name == "borrow" => {
if let Ok(lifetimes) = parse_lit_into_lifetimes(cx, name.as_ref(), lit) {
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
for lifetime in &lifetimes {
if !borrowable.contains(lifetime) {
cx.error(format!("field `{}` does not have lifetime {}", ident, lifetime.ident));
}
}
borrowed_lifetimes.set(lifetimes);
}
}
}
// Parse `#[serde(getter = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "getter" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
getter.set(path);
}
}
MetaItem(ref meta_item) => { MetaItem(ref meta_item) => {
cx.error(format!("unknown serde field attribute `{}`", meta_item.name())); cx.error(format!("unknown serde field attribute `{}`", meta_item.name()));
} }
@@ -663,11 +800,35 @@ impl Field {
} }
// Is skip_deserializing, initialize the field to Default::default() // Is skip_deserializing, initialize the field to Default::default()
// unless a different default is specified by `#[serde(default="...")]` // unless a different default is specified by `#[serde(default = "...")]`
if skip_deserializing.0.value.is_some() { if skip_deserializing.0.value.is_some() {
default.set_if_none(Default::Default); default.set_if_none(Default::Default);
} }
let mut borrowed_lifetimes = borrowed_lifetimes.get().unwrap_or_default();
if !borrowed_lifetimes.is_empty() {
// Cow<str> and Cow<[u8]> never borrow by default:
//
// impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
//
// A #[serde(borrow)] attribute enables borrowing that corresponds
// roughly to these impls:
//
// impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str>
// impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]>
if is_cow(&field.ty, "str") {
let path = syn::parse_path("_serde::private::de::borrow_cow_str").unwrap();
deserialize_with.set_if_none(path);
} else if is_cow(&field.ty, "[u8]") {
let path = syn::parse_path("_serde::private::de::borrow_cow_bytes").unwrap();
deserialize_with.set_if_none(path);
}
} else if is_rptr(&field.ty, "str") || is_rptr(&field.ty, "[u8]") {
// Types &str and &[u8] are always implicitly borrowed. No need for
// a #[serde(borrow)].
borrowed_lifetimes = borrowable_lifetimes(cx, &ident, &field.ty).unwrap();
}
let ser_name = ser_name.get(); let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some(); let ser_renamed = ser_name.is_some();
let de_name = de_name.get(); let de_name = de_name.get();
@@ -687,6 +848,8 @@ impl Field {
deserialize_with: deserialize_with.get(), deserialize_with: deserialize_with.get(),
ser_bound: ser_bound.get(), ser_bound: ser_bound.get(),
de_bound: de_bound.get(), de_bound: de_bound.get(),
borrowed_lifetimes: borrowed_lifetimes,
getter: getter.get(),
} }
} }
@@ -734,6 +897,14 @@ impl Field {
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..]) self.de_bound.as_ref().map(|vec| &vec[..])
} }
pub fn borrowed_lifetimes(&self) -> &BTreeSet<syn::Lifetime> {
&self.borrowed_lifetimes
}
pub fn getter(&self) -> Option<&syn::Path> {
self.getter.as_ref()
}
} }
type SerAndDe<T> = (Option<T>, Option<T>); type SerAndDe<T> = (Option<T>, Option<T>);
@@ -836,3 +1007,174 @@ fn parse_lit_into_ty(cx: &Ctxt,
cx.error(format!("failed to parse type: {} = {:?}", attr_name, string)) cx.error(format!("failed to parse type: {} = {:?}", attr_name, string))
}) })
} }
// Parses a string literal like "'a + 'b + 'c" containing a nonempty list of
// lifetimes separated by `+`.
fn parse_lit_into_lifetimes(cx: &Ctxt,
attr_name: &str,
lit: &syn::Lit)
-> Result<BTreeSet<syn::Lifetime>, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
if string.is_empty() {
cx.error("at least one lifetime must be borrowed");
return Err(());
}
named!(lifetimes -> Vec<syn::Lifetime>,
separated_nonempty_list!(punct!("+"), syn::parse::lifetime)
);
if let IResult::Done(rest, o) = lifetimes(&string) {
if rest.trim().is_empty() {
let mut set = BTreeSet::new();
for lifetime in o {
if !set.insert(lifetime.clone()) {
cx.error(format!("duplicate borrowed lifetime `{}`", lifetime.ident));
}
}
return Ok(set);
}
}
Err(cx.error(format!("failed to parse borrowed lifetimes: {:?}", string)))
}
// Whether the type looks like it might be `std::borrow::Cow<T>` where elem="T".
// This can have false negatives and false positives.
//
// False negative:
//
// use std::borrow::Cow as Pig;
//
// #[derive(Deserialize)]
// struct S<'a> {
// #[serde(borrow)]
// pig: Pig<'a, str>,
// }
//
// False positive:
//
// type str = [i16];
//
// #[derive(Deserialize)]
// struct S<'a> {
// #[serde(borrow)]
// cow: Cow<'a, str>,
// }
fn is_cow(ty: &syn::Ty, elem: &str) -> bool {
let path = match *ty {
syn::Ty::Path(None, ref path) => path,
_ => {
return false;
}
};
let seg = match path.segments.last() {
Some(seg) => seg,
None => {
return false;
}
};
let params = match seg.parameters {
syn::PathParameters::AngleBracketed(ref params) => params,
_ => {
return false;
}
};
seg.ident == "Cow"
&& params.lifetimes.len() == 1
&& params.types == vec![syn::parse_type(elem).unwrap()]
&& params.bindings.is_empty()
}
// Whether the type looks like it might be `&T` where elem="T". This can have
// false negatives and false positives.
//
// False negative:
//
// type Yarn = str;
//
// #[derive(Deserialize)]
// struct S<'a> {
// r: &'a Yarn,
// }
//
// False positive:
//
// type str = [i16];
//
// #[derive(Deserialize)]
// struct S<'a> {
// r: &'a str,
// }
fn is_rptr(ty: &syn::Ty, elem: &str) -> bool {
match *ty {
syn::Ty::Rptr(Some(_), ref mut_ty) => {
mut_ty.mutability == syn::Mutability::Immutable
&& mut_ty.ty == syn::parse_type(elem).unwrap()
}
_ => false,
}
}
// All lifetimes that this type could borrow from a Deserializer.
//
// For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand
// a type `for<'a> fn(&'a str)` could not borrow `'a` from the Deserializer.
//
// This is used when there is an explicit or implicit `#[serde(borrow)]`
// attribute on the field so there must be at least one borrowable lifetime.
fn borrowable_lifetimes(cx: &Ctxt,
name: &str,
ty: &syn::Ty)
-> Result<BTreeSet<syn::Lifetime>, ()> {
let mut lifetimes = BTreeSet::new();
collect_lifetimes(ty, &mut lifetimes);
if lifetimes.is_empty() {
Err(cx.error(format!("field `{}` has no lifetimes to borrow", name)))
} else {
Ok(lifetimes)
}
}
fn collect_lifetimes(ty: &syn::Ty, out: &mut BTreeSet<syn::Lifetime>) {
match *ty {
syn::Ty::Slice(ref elem) |
syn::Ty::Array(ref elem, _) |
syn::Ty::Paren(ref elem) => {
collect_lifetimes(elem, out);
}
syn::Ty::Ptr(ref elem) => {
collect_lifetimes(&elem.ty, out);
}
syn::Ty::Rptr(ref lifetime, ref elem) => {
out.extend(lifetime.iter().cloned());
collect_lifetimes(&elem.ty, out);
}
syn::Ty::Tup(ref elems) => {
for elem in elems {
collect_lifetimes(elem, out);
}
}
syn::Ty::Path(ref qself, ref path) => {
if let Some(ref qself) = *qself {
collect_lifetimes(&qself.ty, out);
}
for seg in &path.segments {
if let syn::PathParameters::AngleBracketed(ref params) = seg.parameters {
out.extend(params.lifetimes.iter().cloned());
for ty in &params.types {
collect_lifetimes(ty, out);
}
for binding in &params.bindings {
collect_lifetimes(&binding.ty, out);
}
}
}
}
syn::Ty::BareFn(_) |
syn::Ty::Never |
syn::Ty::TraitObject(_) |
syn::Ty::ImplTrait(_) |
syn::Ty::Infer |
syn::Ty::Mac(_) => {}
}
}
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::str::FromStr; use std::str::FromStr;
@@ -7,6 +15,8 @@ use self::RenameRule::*;
pub enum RenameRule { pub enum RenameRule {
/// Don't apply a default rename rule. /// Don't apply a default rename rule.
None, None,
/// Rename direct children to "lowercase" style.
LowerCase,
/// Rename direct children to "PascalCase" style, as typically used for enum variants. /// Rename direct children to "PascalCase" style, as typically used for enum variants.
PascalCase, PascalCase,
/// Rename direct children to "camelCase" style. /// Rename direct children to "camelCase" style.
@@ -23,6 +33,7 @@ impl RenameRule {
pub fn apply_to_variant(&self, variant: &str) -> String { pub fn apply_to_variant(&self, variant: &str) -> String {
match *self { match *self {
None | PascalCase => variant.to_owned(), None | PascalCase => variant.to_owned(),
LowerCase => variant.to_ascii_lowercase(),
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..], CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
SnakeCase => { SnakeCase => {
let mut snake = String::new(); let mut snake = String::new();
@@ -41,7 +52,7 @@ impl RenameRule {
pub fn apply_to_field(&self, field: &str) -> String { pub fn apply_to_field(&self, field: &str) -> String {
match *self { match *self {
None | SnakeCase => field.to_owned(), None | LowerCase | SnakeCase => field.to_owned(),
PascalCase => { PascalCase => {
let mut pascal = String::new(); let mut pascal = String::new();
let mut capitalize = true; let mut capitalize = true;
@@ -72,6 +83,7 @@ impl FromStr for RenameRule {
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> { fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
match rename_all_str { match rename_all_str {
"lowercase" => Ok(LowerCase),
"PascalCase" => Ok(PascalCase), "PascalCase" => Ok(PascalCase),
"camelCase" => Ok(CamelCase), "camelCase" => Ok(CamelCase),
"snake_case" => Ok(SnakeCase), "snake_case" => Ok(SnakeCase),
@@ -84,12 +96,13 @@ impl FromStr for RenameRule {
#[test] #[test]
fn rename_variants() { fn rename_variants() {
for &(original, camel, snake, screaming, kebab) in for &(original, lower, camel, snake, screaming, kebab) in
&[("Outcome", "outcome", "outcome", "OUTCOME", "outcome"), &[("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome"),
("VeryTasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"), ("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
("A", "a", "a", "A", "a"), ("A", "a", "a", "a", "A", "a"),
("Z42", "z42", "z42", "Z42", "z42")] { ("Z42", "z42", "z42", "z42", "Z42", "z42")] {
assert_eq!(None.apply_to_variant(original), original); assert_eq!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower);
assert_eq!(PascalCase.apply_to_variant(original), original); assert_eq!(PascalCase.apply_to_variant(original), original);
assert_eq!(CamelCase.apply_to_variant(original), camel); assert_eq!(CamelCase.apply_to_variant(original), camel);
assert_eq!(SnakeCase.apply_to_variant(original), snake); assert_eq!(SnakeCase.apply_to_variant(original), snake);
+93
View File
@@ -0,0 +1,93 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{Body, Container, Style};
use attr::Identifier;
use Ctxt;
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
check_getter(cx, cont);
check_identifier(cx, cont);
}
/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
match cont.body {
Body::Enum(_) => {
if cont.body.has_getter() {
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
}
}
Body::Struct(_, _) => {
if cont.body.has_getter() && cont.attrs.remote().is_none() {
cx.error("#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]");
}
}
}
}
/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match cont.body {
Body::Enum(ref variants) => variants,
Body::Struct(_, _) => {
return;
}
};
for (i, variant) in variants.iter().enumerate() {
match (variant.style, cont.attrs.identifier(), variant.attrs.other()) {
// The `other` attribute may only be used in a field_identifier.
(_, Identifier::Variant, true) | (_, Identifier::No, true) => {
cx.error("#[serde(other)] may only be used inside a field_identifier");
}
// Variant with `other` attribute must be the last one.
(Style::Unit, Identifier::Field, true) => {
if i < variants.len() - 1 {
cx.error("#[serde(other)] must be the last variant");
}
}
// Variant with `other` attribute must be a unit variant.
(_, Identifier::Field, true) => {
cx.error("#[serde(other)] must be on a unit variant");
}
// Any sort of variant is allowed if this is not an identifier.
(_, Identifier::No, false) => {}
// Unit variant without `other` attribute is always fine.
(Style::Unit, _, false) => {}
// The last field is allowed to be a newtype catch-all.
(Style::Newtype, Identifier::Field, false) => {
if i < variants.len() - 1 {
cx.error(format!("`{}` must be the last variant", variant.ident));
}
}
(_, Identifier::Field, false) => {
cx.error("field_identifier may only contain unit variants");
}
(_, Identifier::Variant, false) => {
cx.error("variant_identifier may only contain unit variants");
}
}
}
}
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Display; use std::fmt::Display;
use std::cell::RefCell; use std::cell::RefCell;
+20
View File
@@ -0,0 +1,20 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate syn;
#[macro_use]
extern crate synom;
pub mod ast;
pub mod attr;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
mod check;
+3 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "0.9.14" version = "0.9.14" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
@@ -8,8 +8,9 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/" documentation = "https://docs.serde.rs/serde_test/"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
readme = "../README.md" readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
publish = false # this branch contains breaking changes
[dependencies] [dependencies]
serde = { version = "0.9", path = "../serde" } serde = { version = "0.9", path = "../serde" }
+25 -12
View File
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use de::Deserializer; use de::Deserializer;
@@ -8,8 +16,9 @@ use token::Token;
use std::fmt::Debug; use std::fmt::Debug;
/// Runs both `assert_ser_tokens` and `assert_de_tokens`. /// Runs both `assert_ser_tokens` and `assert_de_tokens`.
pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>]) pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
where T: Serialize + Deserialize + PartialEq + Debug where
T: Serialize + Deserialize<'de> + PartialEq + Debug,
{ {
assert_ser_tokens(value, tokens); assert_ser_tokens(value, tokens);
assert_de_tokens(value, tokens); assert_de_tokens(value, tokens);
@@ -17,38 +26,42 @@ pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>])
/// Asserts that `value` serializes to the given `tokens`. /// Asserts that `value` serializes to the given `tokens`.
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token]) pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where T: Serialize where
T: Serialize,
{ {
let mut ser = Serializer::new(tokens.iter()); let mut ser = Serializer::new(tokens);
assert_eq!(Serialize::serialize(value, &mut ser), Ok(())); assert_eq!(Serialize::serialize(value, &mut ser), Ok(()));
assert_eq!(ser.next_token(), None); assert_eq!(ser.next_token(), None);
} }
/// Asserts that `value` serializes to the given `tokens`, and then yields `error`. /// Asserts that `value` serializes to the given `tokens`, and then yields `error`.
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error) pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error)
where T: Serialize + PartialEq + Debug where
T: Serialize + PartialEq + Debug,
{ {
let mut ser = Serializer::new(tokens.iter()); let mut ser = Serializer::new(tokens);
let v: Result<(), Error> = Serialize::serialize(value, &mut ser); let v: Result<(), Error> = Serialize::serialize(value, &mut ser);
assert_eq!(v.as_ref(), Err(&error)); assert_eq!(v.as_ref(), Err(&error));
assert_eq!(ser.next_token(), None); assert_eq!(ser.next_token(), None);
} }
/// Asserts that the given `tokens` deserialize into `value`. /// Asserts that the given `tokens` deserialize into `value`.
pub fn assert_de_tokens<T>(value: &T, tokens: &[Token<'static>]) pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
where T: Deserialize + PartialEq + Debug where
T: Deserialize<'de> + PartialEq + Debug,
{ {
let mut de = Deserializer::new(tokens.to_vec().into_iter()); let mut de = Deserializer::new(tokens);
let v: Result<T, Error> = Deserialize::deserialize(&mut de); let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v.as_ref(), Ok(value)); assert_eq!(v.as_ref(), Ok(value));
assert_eq!(de.next_token(), None); assert_eq!(de.next_token(), None);
} }
/// Asserts that the given `tokens` yield `error` when deserializing. /// Asserts that the given `tokens` yield `error` when deserializing.
pub fn assert_de_tokens_error<T>(tokens: &[Token<'static>], error: Error) pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: Error)
where T: Deserialize + PartialEq + Debug where
T: Deserialize<'de> + PartialEq + Debug,
{ {
let mut de = Deserializer::new(tokens.to_vec().into_iter()); let mut de = Deserializer::new(tokens);
let v: Result<T, Error> = Deserialize::deserialize(&mut de); let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v, Err(error)); assert_eq!(v, Err(error));
// There may be one token left if a peek caused the error // There may be one token left if a peek caused the error
+344 -328
View File
@@ -1,35 +1,43 @@
use std::iter; // Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::de::{self, Deserialize, DeserializeSeed, EnumVisitor, MapVisitor, SeqVisitor, use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
VariantVisitor, Visitor}; SeqAccess, VariantAccess, Visitor};
use serde::de::value::{ValueDeserializer, MapVisitorDeserializer, SeqVisitorDeserializer}; use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
use error::Error; use error::Error;
use token::Token; use token::Token;
/// A `Deserializer` that reads from a list of tokens. /// A `Deserializer` that reads from a list of tokens.
pub struct Deserializer<I> #[derive(Debug)]
where I: Iterator<Item = Token<'static>> pub struct Deserializer<'de> {
{ tokens: &'de [Token],
tokens: iter::Peekable<I>,
} }
impl<I> Deserializer<I> impl<'de> Deserializer<'de> {
where I: Iterator<Item = Token<'static>>
{
/// Creates the deserializer. /// Creates the deserializer.
pub fn new(tokens: I) -> Deserializer<I> { pub fn new(tokens: &'de [Token]) -> Self {
Deserializer { tokens: tokens.peekable() } Deserializer { tokens: tokens }
} }
/// Pulls the next token off of the deserializer, ignoring it. /// Pulls the next token off of the deserializer, ignoring it.
pub fn next_token(&mut self) -> Option<Token<'static>> { pub fn next_token(&mut self) -> Option<Token> {
self.tokens.next() if let Some((&first, rest)) = self.tokens.split_first() {
self.tokens = rest;
Some(first)
} else {
None
}
} }
/// Pulls the next token off of the deserializer and checks if it matches an expected token. /// Pulls the next token off of the deserializer and checks if it matches an expected token.
pub fn expect_token(&mut self, expected: Token) -> Result<(), Error> { pub fn expect_token(&mut self, expected: Token) -> Result<(), Error> {
match self.tokens.next() { match self.next_token() {
Some(token) => { Some(token) => {
if expected == token { if expected == token {
Ok(()) Ok(())
@@ -41,151 +49,176 @@ impl<I> Deserializer<I>
} }
} }
fn visit_seq<V>(&mut self, fn visit_seq<V>(
len: Option<usize>, &mut self,
sep: Token<'static>, len: Option<usize>,
end: Token<'static>, end: Token,
visitor: V) visitor: V,
-> Result<V::Value, Error> ) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
let value = try!(visitor.visit_seq(DeserializerSeqVisitor { let value = try!(
de: self, visitor.visit_seq(
len: len, DeserializerSeqVisitor {
sep: sep, de: self,
end: end.clone(), len: len,
})); end: end.clone(),
},
)
);
try!(self.expect_token(end)); try!(self.expect_token(end));
Ok(value) Ok(value)
} }
fn visit_map<V>(&mut self, fn visit_map<V>(
len: Option<usize>, &mut self,
sep: Token<'static>, len: Option<usize>,
end: Token<'static>, end: Token,
visitor: V) visitor: V,
-> Result<V::Value, Error> ) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
let value = try!(visitor.visit_map(DeserializerMapVisitor { let value = try!(
de: self, visitor.visit_map(
len: len, DeserializerMapVisitor {
sep: sep, de: self,
end: end.clone(), len: len,
})); end: end.clone(),
},
)
);
try!(self.expect_token(end)); try!(self.expect_token(end));
Ok(value) Ok(value)
} }
} }
impl<'a, I> de::Deserializer for &'a mut Deserializer<I> impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where I: Iterator<Item = Token<'static>>
{
type Error = Error; type Error = Error;
forward_to_deserialize! { forward_to_deserialize_any! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
seq bytes byte_buf map struct_field ignored_any byte_buf unit seq map identifier ignored_any
} }
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error> fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
match self.tokens.next() { let token = self.next_token().ok_or(Error::EndOfTokens)?;
Some(Token::Bool(v)) => visitor.visit_bool(v), match token {
Some(Token::I8(v)) => visitor.visit_i8(v), Token::Bool(v) => visitor.visit_bool(v),
Some(Token::I16(v)) => visitor.visit_i16(v), Token::I8(v) => visitor.visit_i8(v),
Some(Token::I32(v)) => visitor.visit_i32(v), Token::I16(v) => visitor.visit_i16(v),
Some(Token::I64(v)) => visitor.visit_i64(v), Token::I32(v) => visitor.visit_i32(v),
Some(Token::U8(v)) => visitor.visit_u8(v), Token::I64(v) => visitor.visit_i64(v),
Some(Token::U16(v)) => visitor.visit_u16(v), Token::U8(v) => visitor.visit_u8(v),
Some(Token::U32(v)) => visitor.visit_u32(v), Token::U16(v) => visitor.visit_u16(v),
Some(Token::U64(v)) => visitor.visit_u64(v), Token::U32(v) => visitor.visit_u32(v),
Some(Token::F32(v)) => visitor.visit_f32(v), Token::U64(v) => visitor.visit_u64(v),
Some(Token::F64(v)) => visitor.visit_f64(v), Token::F32(v) => visitor.visit_f32(v),
Some(Token::Char(v)) => visitor.visit_char(v), Token::F64(v) => visitor.visit_f64(v),
Some(Token::Str(v)) => visitor.visit_str(v), Token::Char(v) => visitor.visit_char(v),
Some(Token::String(v)) => visitor.visit_string(v), Token::Str(v) => visitor.visit_str(v),
Some(Token::Bytes(v)) => visitor.visit_bytes(v), Token::BorrowedStr(v) => visitor.visit_borrowed_str(v),
Some(Token::ByteBuf(v)) => visitor.visit_byte_buf(v), Token::String(v) => visitor.visit_string(v.to_owned()),
Some(Token::Option(false)) => visitor.visit_none(), Token::Bytes(v) => visitor.visit_bytes(v),
Some(Token::Option(true)) => visitor.visit_some(self), Token::BorrowedBytes(v) => visitor.visit_borrowed_bytes(v),
Some(Token::Unit) => visitor.visit_unit(), Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()),
Some(Token::UnitStruct(_name)) => visitor.visit_unit(), Token::None => visitor.visit_none(),
Some(Token::SeqStart(len)) => { Token::Some => visitor.visit_some(self),
self.visit_seq(len, Token::SeqSep, Token::SeqEnd, visitor) Token::Unit => visitor.visit_unit(),
Token::UnitStruct(_name) => visitor.visit_unit(),
Token::NewtypeStruct(_name) => visitor.visit_newtype_struct(self),
Token::Seq(len) => self.visit_seq(len, Token::SeqEnd, visitor),
Token::Tuple(len) => self.visit_seq(Some(len), Token::TupleEnd, visitor),
Token::TupleStruct(_, len) => self.visit_seq(Some(len), Token::TupleStructEnd, visitor),
Token::Map(len) => self.visit_map(len, Token::MapEnd, visitor),
Token::Struct(_, len) => self.visit_map(Some(len), Token::StructEnd, visitor),
Token::Enum(_) => {
let variant = self.next_token().ok_or(Error::EndOfTokens)?;
let next = *self.tokens.first().ok_or(Error::EndOfTokens)?;
match (variant, next) {
(Token::Str(variant), Token::Unit) => {
self.next_token();
visitor.visit_str(variant)
}
(Token::Bytes(variant), Token::Unit) => {
self.next_token();
visitor.visit_bytes(variant)
}
(Token::U32(variant), Token::Unit) => {
self.next_token();
visitor.visit_u32(variant)
}
(variant, Token::Unit) => Err(Error::UnexpectedToken(variant)),
(variant, _) => {
visitor.visit_map(EnumMapVisitor::new(self, variant, EnumFormat::Any))
}
}
} }
Some(Token::SeqArrayStart(len)) => { Token::UnitVariant(_, variant) => visitor.visit_str(variant),
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) Token::NewtypeVariant(_, variant) => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),)
} }
Some(Token::TupleStart(len)) => { Token::TupleVariant(_, variant, _) => {
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor) visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),)
} }
Some(Token::TupleStructStart(_, len)) => { Token::StructVariant(_, variant, _) => {
self.visit_seq(Some(len), visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),)
Token::TupleStructSep,
Token::TupleStructEnd,
visitor)
} }
Some(Token::MapStart(len)) => { Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd |
self.visit_map(len, Token::MapSep, Token::MapEnd, visitor) Token::StructEnd | Token::TupleVariantEnd | Token::StructVariantEnd => {
Err(Error::UnexpectedToken(token))
} }
Some(Token::StructStart(_, len)) => {
self.visit_map(Some(len), Token::StructSep, Token::StructEnd, visitor)
}
Some(Token::EnumUnit(_, variant)) => visitor.visit_str(variant),
Some(Token::EnumStart(variant)) |
Some(Token::EnumNewType(_, variant)) |
Some(Token::EnumSeqStart(_, variant, _)) |
Some(Token::EnumMapStart(_, variant, _)) => {
visitor.visit_map(EnumMapVisitor::new(self, variant))
}
Some(token) => Err(Error::UnexpectedToken(token)),
None => Err(Error::EndOfTokens),
} }
} }
/// Hook into `Option` deserializing so we can treat `Unit` as a /// Hook into `Option` deserializing so we can treat `Unit` as a
/// `None`, or a regular value as `Some(value)`. /// `None`, or a regular value as `Some(value)`.
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
match self.tokens.peek() { match self.tokens.first() {
Some(&Token::Unit) | Some(&Token::Unit) |
Some(&Token::Option(false)) => { Some(&Token::None) => {
self.tokens.next(); self.next_token();
visitor.visit_none() visitor.visit_none()
} }
Some(&Token::Option(true)) => { Some(&Token::Some) => {
self.tokens.next(); self.next_token();
visitor.visit_some(self) visitor.visit_some(self)
} }
Some(_) => visitor.visit_some(self), Some(_) => self.deserialize_any(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
fn deserialize_enum<V>(self, fn deserialize_enum<V>(
name: &str, self,
_variants: &'static [&'static str], name: &str,
visitor: V) _variants: &'static [&'static str],
-> Result<V::Value, Error> visitor: V,
where V: Visitor ) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{ {
match self.tokens.peek() { match self.tokens.first() {
Some(&Token::EnumStart(n)) if name == n => { Some(&Token::Enum(n)) if name == n => {
self.tokens.next(); self.next_token();
visitor.visit_enum(DeserializerEnumVisitor { de: self }) visitor.visit_enum(DeserializerEnumVisitor { de: self })
} }
Some(&Token::EnumUnit(n, _)) | Some(&Token::UnitVariant(n, _)) |
Some(&Token::EnumNewType(n, _)) | Some(&Token::NewtypeVariant(n, _)) |
Some(&Token::EnumSeqStart(n, _, _)) | Some(&Token::TupleVariant(n, _, _)) |
Some(&Token::EnumMapStart(n, _, _)) if name == n => { Some(&Token::StructVariant(n, _, _)) if name == n => {
visitor.visit_enum(DeserializerEnumVisitor { de: self }) visitor.visit_enum(DeserializerEnumVisitor { de: self })
} }
Some(_) => { Some(_) => {
let token = self.tokens.next().unwrap(); let token = self.next_token().unwrap();
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
@@ -193,157 +226,134 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
} }
fn deserialize_unit_struct<V>(self, name: &str, visitor: V) -> Result<V::Value, Error> fn deserialize_unit_struct<V>(self, name: &str, visitor: V) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
match self.tokens.peek() { match self.tokens.first() {
Some(&Token::UnitStruct(n)) => { Some(&Token::UnitStruct(n)) => {
self.tokens.next(); self.next_token();
if name == n { if name == n {
visitor.visit_unit() visitor.visit_unit()
} else { } else {
Err(Error::InvalidName(n)) Err(Error::InvalidName(n))
} }
} }
Some(_) => self.deserialize(visitor), Some(_) => self.deserialize_any(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
fn deserialize_newtype_struct<V>(self, name: &str, visitor: V) -> Result<V::Value, Error> fn deserialize_newtype_struct<V>(self, name: &str, visitor: V) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
match self.tokens.peek() { match self.tokens.first() {
Some(&Token::StructNewType(n)) => { Some(&Token::NewtypeStruct(n)) => {
self.tokens.next(); self.next_token();
if name == n { if name == n {
visitor.visit_newtype_struct(self) visitor.visit_newtype_struct(self)
} else { } else {
Err(Error::InvalidName(n)) Err(Error::InvalidName(n))
} }
} }
Some(_) => self.deserialize(visitor), Some(_) => self.deserialize_any(visitor),
None => Err(Error::EndOfTokens),
}
}
fn deserialize_seq_fixed_size<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor
{
match self.tokens.peek() {
Some(&Token::SeqArrayStart(_)) => {
self.tokens.next();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error> fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
match self.tokens.peek() { match self.tokens.first() {
Some(&Token::Unit) | Some(&Token::Unit) |
Some(&Token::UnitStruct(_)) => { Some(&Token::UnitStruct(_)) => {
self.tokens.next(); self.next_token();
visitor.visit_unit() visitor.visit_unit()
} }
Some(&Token::SeqStart(_)) => { Some(&Token::Seq(_)) => {
self.tokens.next(); self.next_token();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) self.visit_seq(Some(len), Token::SeqEnd, visitor)
} }
Some(&Token::SeqArrayStart(_)) => { Some(&Token::Tuple(_)) => {
self.tokens.next(); self.next_token();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) self.visit_seq(Some(len), Token::TupleEnd, visitor)
} }
Some(&Token::TupleStart(_)) => { Some(&Token::TupleStruct(_, _)) => {
self.tokens.next(); self.next_token();
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor) self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
} }
Some(&Token::TupleStructStart(_, _)) => { Some(_) => self.deserialize_any(visitor),
self.tokens.next();
self.visit_seq(Some(len),
Token::TupleStructSep,
Token::TupleStructEnd,
visitor)
}
Some(_) => self.deserialize(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
fn deserialize_tuple_struct<V>(self, fn deserialize_tuple_struct<V>(
name: &str, self,
len: usize, name: &str,
visitor: V) len: usize,
-> Result<V::Value, Error> visitor: V,
where V: Visitor ) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{ {
match self.tokens.peek() { match self.tokens.first() {
Some(&Token::Unit) => { Some(&Token::Unit) => {
self.tokens.next(); self.next_token();
visitor.visit_unit() visitor.visit_unit()
} }
Some(&Token::UnitStruct(n)) => { Some(&Token::UnitStruct(n)) => {
self.tokens.next(); self.next_token();
if name == n { if name == n {
visitor.visit_unit() visitor.visit_unit()
} else { } else {
Err(Error::InvalidName(n)) Err(Error::InvalidName(n))
} }
} }
Some(&Token::SeqStart(_)) => { Some(&Token::Seq(_)) => {
self.tokens.next(); self.next_token();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) self.visit_seq(Some(len), Token::SeqEnd, visitor)
} }
Some(&Token::SeqArrayStart(_)) => { Some(&Token::Tuple(_)) => {
self.tokens.next(); self.next_token();
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) self.visit_seq(Some(len), Token::TupleEnd, visitor)
} }
Some(&Token::TupleStart(_)) => { Some(&Token::TupleStruct(n, _)) => {
self.tokens.next(); self.next_token();
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
}
Some(&Token::TupleStructStart(n, _)) => {
self.tokens.next();
if name == n { if name == n {
self.visit_seq(Some(len), self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
Token::TupleStructSep,
Token::TupleStructEnd,
visitor)
} else { } else {
Err(Error::InvalidName(n)) Err(Error::InvalidName(n))
} }
} }
Some(_) => self.deserialize(visitor), Some(_) => self.deserialize_any(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
fn deserialize_struct<V>(self, fn deserialize_struct<V>(
name: &str, self,
fields: &'static [&'static str], name: &str,
visitor: V) fields: &'static [&'static str],
-> Result<V::Value, Error> visitor: V,
where V: Visitor ) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{ {
match self.tokens.peek() { match self.tokens.first() {
Some(&Token::StructStart(n, _)) => { Some(&Token::Struct(n, _)) => {
self.tokens.next(); self.next_token();
if name == n { if name == n {
self.visit_map(Some(fields.len()), self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
Token::StructSep,
Token::StructEnd,
visitor)
} else { } else {
Err(Error::InvalidName(n)) Err(Error::InvalidName(n))
} }
} }
Some(&Token::MapStart(_)) => { Some(&Token::Map(_)) => {
self.tokens.next(); self.next_token();
self.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor) self.visit_map(Some(fields.len()), Token::MapEnd, visitor)
} }
Some(_) => self.deserialize(visitor), Some(_) => self.deserialize_any(visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
@@ -351,108 +361,84 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct DeserializerSeqVisitor<'a, I: 'a> struct DeserializerSeqVisitor<'a, 'de: 'a> {
where I: Iterator<Item = Token<'static>> de: &'a mut Deserializer<'de>,
{
de: &'a mut Deserializer<I>,
len: Option<usize>, len: Option<usize>,
sep: Token<'static>, end: Token,
end: Token<'static>,
} }
impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I> impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> {
where I: Iterator<Item = Token<'static>>
{
type Error = Error; type Error = Error;
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error> fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
where T: DeserializeSeed where
T: DeserializeSeed<'de>,
{ {
if self.de.tokens.peek() == Some(&self.end) { if self.de.tokens.first() == Some(&self.end) {
return Ok(None); return Ok(None);
} }
match self.de.tokens.next() { self.len = self.len.map(|len| len.saturating_sub(1));
Some(ref token) if *token == self.sep => { seed.deserialize(&mut *self.de).map(Some)
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some)
}
Some(other) => Err(Error::UnexpectedToken(other)),
None => Err(Error::EndOfTokens),
}
} }
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> Option<usize> {
let len = self.len.unwrap_or(0); self.len
(len, self.len)
} }
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct DeserializerMapVisitor<'a, I: 'a> struct DeserializerMapVisitor<'a, 'de: 'a> {
where I: Iterator<Item = Token<'static>> de: &'a mut Deserializer<'de>,
{
de: &'a mut Deserializer<I>,
len: Option<usize>, len: Option<usize>,
sep: Token<'static>, end: Token,
end: Token<'static>,
} }
impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I> impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> {
where I: Iterator<Item = Token<'static>>
{
type Error = Error; type Error = Error;
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error> fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed where
K: DeserializeSeed<'de>,
{ {
if self.de.tokens.peek() == Some(&self.end) { if self.de.tokens.first() == Some(&self.end) {
return Ok(None); return Ok(None);
} }
match self.de.tokens.next() { self.len = self.len.map(|len| len.saturating_sub(1));
Some(ref token) if *token == self.sep => { seed.deserialize(&mut *self.de).map(Some)
self.len = self.len.map(|len| len.saturating_sub(1));
seed.deserialize(&mut *self.de).map(Some)
}
Some(other) => Err(Error::UnexpectedToken(other)),
None => Err(Error::EndOfTokens),
}
} }
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error> fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed where
V: DeserializeSeed<'de>,
{ {
seed.deserialize(&mut *self.de) seed.deserialize(&mut *self.de)
} }
fn size_hint(&self) -> (usize, Option<usize>) { fn size_hint(&self) -> Option<usize> {
let len = self.len.unwrap_or(0); self.len
(len, self.len)
} }
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct DeserializerEnumVisitor<'a, I: 'a> struct DeserializerEnumVisitor<'a, 'de: 'a> {
where I: Iterator<Item = Token<'static>> de: &'a mut Deserializer<'de>,
{
de: &'a mut Deserializer<I>,
} }
impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I> impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
where I: Iterator<Item = Token<'static>>
{
type Error = Error; type Error = Error;
type Variant = Self; type Variant = Self;
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error> fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
where V: DeserializeSeed where
V: DeserializeSeed<'de>,
{ {
match self.de.tokens.peek() { match self.de.tokens.first() {
Some(&Token::EnumUnit(_, v)) | Some(&Token::UnitVariant(_, v)) |
Some(&Token::EnumNewType(_, v)) | Some(&Token::NewtypeVariant(_, v)) |
Some(&Token::EnumSeqStart(_, v, _)) | Some(&Token::TupleVariant(_, v, _)) |
Some(&Token::EnumMapStart(_, v, _)) => { Some(&Token::StructVariant(_, v, _)) => {
let de = v.into_deserializer(); let de = v.into_deserializer();
let value = try!(seed.deserialize(de)); let value = try!(seed.deserialize(de));
Ok((value, self)) Ok((value, self))
@@ -466,15 +452,13 @@ impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I>
} }
} }
impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I> impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
where I: Iterator<Item = Token<'static>>
{
type Error = Error; type Error = Error;
fn visit_unit(self) -> Result<(), Error> { fn unit_variant(self) -> Result<(), Error> {
match self.de.tokens.peek() { match self.de.tokens.first() {
Some(&Token::EnumUnit(_, _)) => { Some(&Token::UnitVariant(_, _)) => {
self.de.tokens.next(); self.de.next_token();
Ok(()) Ok(())
} }
Some(_) => Deserialize::deserialize(self.de), Some(_) => Deserialize::deserialize(self.de),
@@ -482,12 +466,13 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
} }
} }
fn visit_newtype_seed<T>(self, seed: T) -> Result<T::Value, Self::Error> fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where T: DeserializeSeed where
T: DeserializeSeed<'de>,
{ {
match self.de.tokens.peek() { match self.de.tokens.first() {
Some(&Token::EnumNewType(_, _)) => { Some(&Token::NewtypeVariant(_, _)) => {
self.de.tokens.next(); self.de.next_token();
seed.deserialize(self.de) seed.deserialize(self.de)
} }
Some(_) => seed.deserialize(self.de), Some(_) => seed.deserialize(self.de),
@@ -495,59 +480,61 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
} }
} }
fn visit_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Error> fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
match self.de.tokens.peek() { match self.de.tokens.first() {
Some(&Token::EnumSeqStart(_, _, enum_len)) => { Some(&Token::TupleVariant(_, _, enum_len)) => {
let token = self.de.tokens.next().unwrap(); let token = self.de.next_token().unwrap();
if len == enum_len { if len == enum_len {
self.de.visit_seq(Some(len), Token::EnumSeqSep, Token::EnumSeqEnd, visitor) self.de
.visit_seq(Some(len), Token::TupleVariantEnd, visitor)
} else { } else {
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
} }
Some(&Token::SeqStart(Some(enum_len))) => { Some(&Token::Seq(Some(enum_len))) => {
let token = self.de.tokens.next().unwrap(); let token = self.de.next_token().unwrap();
if len == enum_len { if len == enum_len {
self.de.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor) self.de.visit_seq(Some(len), Token::SeqEnd, visitor)
} else { } else {
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
} }
Some(_) => de::Deserializer::deserialize(self.de, visitor), Some(_) => de::Deserializer::deserialize_any(self.de, visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
fn visit_struct<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error> fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
where V: Visitor where
V: Visitor<'de>,
{ {
match self.de.tokens.peek() { match self.de.tokens.first() {
Some(&Token::EnumMapStart(_, _, enum_len)) => { Some(&Token::StructVariant(_, _, enum_len)) => {
let token = self.de.tokens.next().unwrap(); let token = self.de.next_token().unwrap();
if fields.len() == enum_len { if fields.len() == enum_len {
self.de.visit_map(Some(fields.len()), self.de
Token::EnumMapSep, .visit_map(Some(fields.len()), Token::StructVariantEnd, visitor)
Token::EnumMapEnd,
visitor)
} else { } else {
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
} }
Some(&Token::MapStart(Some(enum_len))) => { Some(&Token::Map(Some(enum_len))) => {
let token = self.de.tokens.next().unwrap(); let token = self.de.next_token().unwrap();
if fields.len() == enum_len { if fields.len() == enum_len {
self.de.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor) self.de
.visit_map(Some(fields.len()), Token::MapEnd, visitor)
} else { } else {
Err(Error::UnexpectedToken(token)) Err(Error::UnexpectedToken(token))
} }
} }
Some(_) => de::Deserializer::deserialize(self.de, visitor), Some(_) => de::Deserializer::deserialize_any(self.de, visitor),
None => Err(Error::EndOfTokens), None => Err(Error::EndOfTokens),
} }
} }
@@ -555,69 +542,98 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
struct EnumMapVisitor<'a, I: 'a> struct EnumMapVisitor<'a, 'de: 'a> {
where I: Iterator<Item = Token<'static>> de: &'a mut Deserializer<'de>,
{ variant: Option<Token>,
de: &'a mut Deserializer<I>, format: EnumFormat,
variant: Option<&'a str>,
} }
impl<'a, I: 'a> EnumMapVisitor<'a, I> enum EnumFormat {
where I: Iterator<Item = Token<'static>> Seq,
{ Map,
fn new(de: &'a mut Deserializer<I>, variant: &'a str) -> Self { Any,
}
impl<'a, 'de> EnumMapVisitor<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>, variant: Token, format: EnumFormat) -> Self {
EnumMapVisitor { EnumMapVisitor {
de: de, de: de,
variant: Some(variant), variant: Some(variant),
format: format,
} }
} }
} }
impl<'a, I: 'a> MapVisitor for EnumMapVisitor<'a, I> impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
where I: Iterator<Item = Token<'static>>
{
type Error = Error; type Error = Error;
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error> fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
where K: DeserializeSeed where
K: DeserializeSeed<'de>,
{ {
match self.variant.take() { match self.variant.take() {
Some(variant) => seed.deserialize(variant.into_deserializer()).map(Some), Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(Token::Bytes(variant)) => {
seed.deserialize(BytesDeserializer { value: variant })
.map(Some)
}
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(other) => Err(Error::UnexpectedToken(other)),
None => Ok(None), None => Ok(None),
} }
} }
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error> fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
where V: DeserializeSeed where
V: DeserializeSeed<'de>,
{ {
match self.de.tokens.peek() { match self.format {
Some(&Token::EnumSeqSep) => { EnumFormat::Seq => {
let value = { let value = {
let visitor = DeserializerSeqVisitor { let visitor = DeserializerSeqVisitor {
de: self.de, de: self.de,
len: None, len: None,
sep: Token::EnumSeqSep, end: Token::TupleVariantEnd,
end: Token::EnumSeqEnd,
}; };
try!(seed.deserialize(SeqVisitorDeserializer::new(visitor))) try!(seed.deserialize(SeqAccessDeserializer::new(visitor)))
}; };
try!(self.de.expect_token(Token::EnumSeqEnd)); try!(self.de.expect_token(Token::TupleVariantEnd));
Ok(value) Ok(value)
} }
Some(&Token::EnumMapSep) => { EnumFormat::Map => {
let value = { let value = {
let visitor = DeserializerMapVisitor { let visitor = DeserializerMapVisitor {
de: self.de, de: self.de,
len: None, len: None,
sep: Token::EnumMapSep, end: Token::StructVariantEnd,
end: Token::EnumMapEnd,
}; };
try!(seed.deserialize(MapVisitorDeserializer::new(visitor))) try!(seed.deserialize(MapAccessDeserializer::new(visitor)))
}; };
try!(self.de.expect_token(Token::EnumMapEnd)); try!(self.de.expect_token(Token::StructVariantEnd));
Ok(value) Ok(value)
} }
_ => seed.deserialize(&mut *self.de), EnumFormat::Any => seed.deserialize(&mut *self.de),
} }
} }
} }
struct BytesDeserializer {
value: &'static [u8],
}
impl<'de> de::Deserializer<'de> for BytesDeserializer {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_bytes(self.value)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct enum identifier ignored_any
}
}
+9 -1
View File
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::error; use std::error;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
@@ -15,7 +23,7 @@ pub enum Error {
InvalidName(&'static str), InvalidName(&'static str),
/// `Serialize` generated a token that didn't match the test. /// `Serialize` generated a token that didn't match the test.
UnexpectedToken(Token<'static>), UnexpectedToken(Token),
/// The expected token list was too short. /// The expected token list was too short.
EndOfTokens, EndOfTokens,
+10
View File
@@ -1,3 +1,13 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_test/0.9.13")]
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
+160 -134
View File
@@ -1,4 +1,10 @@
use std::marker::PhantomData; // Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{ser, Serialize}; use serde::{ser, Serialize};
@@ -6,33 +12,54 @@ use error::Error;
use token::Token; use token::Token;
/// A `Serializer` that ensures that a value serializes to a given list of tokens. /// A `Serializer` that ensures that a value serializes to a given list of tokens.
pub struct Serializer<'a, I> #[derive(Debug)]
where I: Iterator<Item = &'a Token<'a>> pub struct Serializer<'a> {
{ tokens: &'a [Token],
tokens: I,
phantom: PhantomData<&'a Token<'a>>,
} }
impl<'a, I> Serializer<'a, I> impl<'a> Serializer<'a> {
where I: Iterator<Item = &'a Token<'a>>
{
/// Creates the serializer. /// Creates the serializer.
pub fn new(tokens: I) -> Serializer<'a, I> { pub fn new(tokens: &'a [Token]) -> Self {
Serializer { Serializer { tokens: tokens }
tokens: tokens,
phantom: PhantomData,
}
} }
/// Pulls the next token off of the serializer, ignoring it. /// Pulls the next token off of the serializer, ignoring it.
pub fn next_token(&mut self) -> Option<&'a Token<'a>> { pub fn next_token(&mut self) -> Option<Token> {
self.tokens.next() if let Some((&first, rest)) = self.tokens.split_first() {
self.tokens = rest;
Some(first)
} else {
None
}
} }
} }
impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I> macro_rules! assert_next_token {
where I: Iterator<Item = &'a Token<'a>> ($ser:ident, $expected:ident($a:expr)) => {
{ assert_next_token!($ser, $expected { a: $a });
};
($ser:ident, $expected:ident($a:expr, $b:expr)) => {
assert_next_token!($ser, $expected { a: $a, b: $b });
};
($ser:ident, $expected:ident($a:expr, $b:expr, $c:expr)) => {
assert_next_token!($ser, $expected { a: $a, b: $b, c: $c });
};
($ser:ident, $expected:ident $({ $($n:ident: $v:expr),* })*) => {
match $ser.next_token() {
Some(Token::$expected $(($($n),*))*) $(if $($n == $v)&&*)* => {}
Some(other) => {
panic!("expected Token::{} but serialized as {:?}",
stringify!($expected), other);
}
None => {
panic!("expected Token::{} after end of serialized tokens",
stringify!($expected));
}
}
};
}
impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
@@ -45,322 +72,321 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
type SerializeStructVariant = Self; type SerializeStructVariant = Self;
fn serialize_bool(self, v: bool) -> Result<(), Error> { fn serialize_bool(self, v: bool) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v))); assert_next_token!(self, Bool(v));
Ok(()) Ok(())
} }
fn serialize_i8(self, v: i8) -> Result<(), Error> { fn serialize_i8(self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v))); assert_next_token!(self, I8(v));
Ok(()) Ok(())
} }
fn serialize_i16(self, v: i16) -> Result<(), Error> { fn serialize_i16(self, v: i16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v))); assert_next_token!(self, I16(v));
Ok(()) Ok(())
} }
fn serialize_i32(self, v: i32) -> Result<(), Error> { fn serialize_i32(self, v: i32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v))); assert_next_token!(self, I32(v));
Ok(()) Ok(())
} }
fn serialize_i64(self, v: i64) -> Result<(), Error> { fn serialize_i64(self, v: i64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v))); assert_next_token!(self, I64(v));
Ok(()) Ok(())
} }
fn serialize_u8(self, v: u8) -> Result<(), Error> { fn serialize_u8(self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v))); assert_next_token!(self, U8(v));
Ok(()) Ok(())
} }
fn serialize_u16(self, v: u16) -> Result<(), Error> { fn serialize_u16(self, v: u16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v))); assert_next_token!(self, U16(v));
Ok(()) Ok(())
} }
fn serialize_u32(self, v: u32) -> Result<(), Error> { fn serialize_u32(self, v: u32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v))); assert_next_token!(self, U32(v));
Ok(()) Ok(())
} }
fn serialize_u64(self, v: u64) -> Result<(), Error> { fn serialize_u64(self, v: u64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v))); assert_next_token!(self, U64(v));
Ok(()) Ok(())
} }
fn serialize_f32(self, v: f32) -> Result<(), Error> { fn serialize_f32(self, v: f32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v))); assert_next_token!(self, F32(v));
Ok(()) Ok(())
} }
fn serialize_f64(self, v: f64) -> Result<(), Error> { fn serialize_f64(self, v: f64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v))); assert_next_token!(self, F64(v));
Ok(()) Ok(())
} }
fn serialize_char(self, v: char) -> Result<(), Error> { fn serialize_char(self, v: char) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v))); assert_next_token!(self, Char(v));
Ok(()) Ok(())
} }
fn serialize_str(self, v: &str) -> Result<(), Error> { fn serialize_str(self, v: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v))); assert_next_token!(self, Str(v));
Ok(()) Ok(())
} }
fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> { fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bytes(value))); assert_next_token!(self, Bytes(value));
Ok(()) Ok(())
} }
fn serialize_unit(self) -> Result<(), Error> { fn serialize_unit(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit)); assert_next_token!(self, Unit);
Ok(()) Ok(())
} }
fn serialize_unit_struct(self, name: &str) -> Result<(), Error> { fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name))); assert_next_token!(self, UnitStruct(name));
Ok(()) Ok(())
} }
fn serialize_unit_variant(self, fn serialize_unit_variant(
name: &str, self,
_variant_index: usize, name: &'static str,
variant: &str) _variant_index: u32,
-> Result<(), Error> { variant: &'static str,
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant))); ) -> Result<(), Error> {
if self.tokens.first() == Some(&Token::Enum(name)) {
self.next_token();
assert_next_token!(self, Str(variant));
assert_next_token!(self, Unit);
} else {
assert_next_token!(self, UnitVariant(name, variant));
}
Ok(()) Ok(())
} }
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error> fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
where T: Serialize where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name))); assert_next_token!(self, NewtypeStruct(name));
value.serialize(self) value.serialize(self)
} }
fn serialize_newtype_variant<T: ?Sized>(self, fn serialize_newtype_variant<T: ?Sized>(
name: &str, self,
_variant_index: usize, name: &'static str,
variant: &str, _variant_index: u32,
value: &T) variant: &'static str,
-> Result<(), Error> value: &T,
where T: Serialize ) -> Result<(), Error>
where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant))); if self.tokens.first() == Some(&Token::Enum(name)) {
self.next_token();
assert_next_token!(self, Str(variant));
} else {
assert_next_token!(self, NewtypeVariant(name, variant));
}
value.serialize(self) value.serialize(self)
} }
fn serialize_none(self) -> Result<(), Error> { fn serialize_none(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false))); assert_next_token!(self, None);
Ok(()) Ok(())
} }
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error> fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
where T: Serialize where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::Option(true))); assert_next_token!(self, Some);
value.serialize(self) value.serialize(self)
} }
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> { fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len))); assert_next_token!(self, Seq(len));
Ok(self)
}
fn serialize_seq_fixed_size(self, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
Ok(self) Ok(self)
} }
fn serialize_tuple(self, len: usize) -> Result<Self, Error> { fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len))); assert_next_token!(self, Tuple(len));
Ok(self) Ok(self)
} }
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> { fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), assert_next_token!(self, TupleStruct(name, len));
Some(&Token::TupleStructStart(name, len)));
Ok(self) Ok(self)
} }
fn serialize_tuple_variant(self, fn serialize_tuple_variant(
name: &str, self,
_variant_index: usize, name: &'static str,
variant: &str, _variant_index: u32,
len: usize) variant: &'static str,
-> Result<Self, Error> { len: usize,
assert_eq!(self.tokens.next(), ) -> Result<Self, Error> {
Some(&Token::EnumSeqStart(name, variant, len))); assert_next_token!(self, TupleVariant(name, variant, len));
Ok(self) Ok(self)
} }
fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> { fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len))); assert_next_token!(self, Map(len));
Ok(self) Ok(self)
} }
fn serialize_struct(self, name: &str, len: usize) -> Result<Self, Error> { fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len))); assert_next_token!(self, Struct(name, len));
Ok(self) Ok(self)
} }
fn serialize_struct_variant(self, fn serialize_struct_variant(
name: &str, self,
_variant_index: usize, name: &'static str,
variant: &str, _variant_index: u32,
len: usize) variant: &'static str,
-> Result<Self, Error> { len: usize,
assert_eq!(self.tokens.next(), ) -> Result<Self, Error> {
Some(&Token::EnumMapStart(name, variant, len))); assert_next_token!(self, StructVariant(name, variant, len));
Ok(self) Ok(self)
} }
} }
impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I> impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(&mut **self) value.serialize(&mut **self)
} }
fn end(self) -> Result<(), Error> { fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd)); assert_next_token!(self, SeqEnd);
Ok(()) Ok(())
} }
} }
impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I> impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(&mut **self) value.serialize(&mut **self)
} }
fn end(self) -> Result<(), Error> { fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd)); assert_next_token!(self, TupleEnd);
Ok(()) Ok(())
} }
} }
impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I> impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(&mut **self) value.serialize(&mut **self)
} }
fn end(self) -> Result<(), Error> { fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd)); assert_next_token!(self, TupleStructEnd);
Ok(()) Ok(())
} }
} }
impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I> impl<'s, 'a> ser::SerializeTupleVariant for &'s mut Serializer<'a> {
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
where T: Serialize where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(&mut **self) value.serialize(&mut **self)
} }
fn end(self) -> Result<(), Error> { fn end(self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd)); assert_next_token!(self, TupleVariantEnd);
Ok(()) Ok(())
} }
} }
impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I> impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error> fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
where T: Serialize where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
key.serialize(&mut **self) key.serialize(&mut **self)
} }
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where T: Serialize where
T: Serialize,
{ {
value.serialize(&mut **self) value.serialize(&mut **self)
} }
fn end(self) -> Result<(), Self::Error> { fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::MapEnd)); assert_next_token!(self, MapEnd);
Ok(()) Ok(())
} }
} }
impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I> impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, fn serialize_field<T: ?Sized>(
key: &'static str, &mut self,
value: &T) key: &'static str,
-> Result<(), Self::Error> value: &T,
where T: Serialize ) -> Result<(), Self::Error>
where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(&mut **self)); try!(key.serialize(&mut **self));
value.serialize(&mut **self) value.serialize(&mut **self)
} }
fn end(self) -> Result<(), Self::Error> { fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::StructEnd)); assert_next_token!(self, StructEnd);
Ok(()) Ok(())
} }
} }
impl<'s, 'a, I> ser::SerializeStructVariant for &'s mut Serializer<'a, I> impl<'s, 'a> ser::SerializeStructVariant for &'s mut Serializer<'a> {
where I: Iterator<Item = &'a Token<'a>>
{
type Ok = (); type Ok = ();
type Error = Error; type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, fn serialize_field<T: ?Sized>(
key: &'static str, &mut self,
value: &T) key: &'static str,
-> Result<(), Self::Error> value: &T,
where T: Serialize ) -> Result<(), Self::Error>
where
T: Serialize,
{ {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(&mut **self)); try!(key.serialize(&mut **self));
value.serialize(&mut **self) value.serialize(&mut **self)
} }
fn end(self) -> Result<(), Self::Error> { fn end(self) -> Result<(), Self::Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd)); assert_next_token!(self, StructVariantEnd);
Ok(()) Ok(())
} }
} }
+43 -65
View File
@@ -1,5 +1,13 @@
#[derive(Clone, PartialEq, Debug)] // Copyright 2017 Serde Developers
pub enum Token<'a> { //
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Token {
/// A serialized `bool`. /// A serialized `bool`.
Bool(bool), Bool(bool),
@@ -37,90 +45,75 @@ pub enum Token<'a> {
Char(char), Char(char),
/// A serialized `str`. /// A serialized `str`.
Str(&'a str), Str(&'static str),
/// A borrowed `str`.
BorrowedStr(&'static str),
/// A serialized `String`. /// A serialized `String`.
String(String), String(&'static str),
/// A serialized `[u8]` /// A serialized `[u8]`
Bytes(&'a [u8]), Bytes(&'static [u8]),
/// A borrowed `[u8]`.
BorrowedBytes(&'static [u8]),
/// A serialized `ByteBuf` /// A serialized `ByteBuf`
ByteBuf(Vec<u8>), ByteBuf(&'static [u8]),
/// The header to a serialized `Option<T>`. /// The header to a serialized `Option<T>` containing some value.
/// ///
/// `None` is serialized as `Option(false)`, while `Some` is serialized as `Option(true)`, then /// The tokens of the value follow after this header.
/// the value contained in the option. Some,
Option(bool),
/// A serialized `Option<T>` containing none.
None,
/// A serialized `()`. /// A serialized `()`.
Unit, Unit,
/// A serialized unit struct of the given name. /// A serialized unit struct of the given name.
UnitStruct(&'a str), UnitStruct(&'static str),
/// The header to a serialized newtype struct of the given name. /// The header to a serialized newtype struct of the given name.
/// ///
/// Newtype structs are serialized with this header, followed by the value contained in the /// Newtype structs are serialized with this header, followed by the value contained in the
/// newtype struct. /// newtype struct.
StructNewType(&'a str), NewtypeStruct(&'static str),
/// The header to an enum of the given name. /// The header to an enum of the given name.
/// Enum(&'static str),
/// This token is only used for deserializers, and ensures that the following tokens are read as
/// an enum. Because this is never emitted by serializers, calling `assert_ser_tokens` or
/// `assert_tokens` will fail if this token is used.
///
/// TODO: Trash this.
EnumStart(&'a str),
/// A unit variant of an enum of the given name, of the given name. /// A unit variant of an enum of the given name, of the given name.
/// ///
/// The first string represents the name of the enum, and the second represents the name of the /// The first string represents the name of the enum, and the second represents the name of the
/// variant. /// variant.
EnumUnit(&'a str, &'a str), UnitVariant(&'static str, &'static str),
/// The header to a newtype variant of an enum of the given name, of the given name. /// The header to a newtype variant of an enum of the given name, of the given name.
/// ///
/// The first string represents the name of the enum, and the second represents the name of the /// The first string represents the name of the enum, and the second represents the name of the
/// variant. The value contained within this enum works the same as `StructNewType`. /// variant. The value contained within this enum works the same as `StructNewType`.
EnumNewType(&'a str, &'a str), NewtypeVariant(&'static str, &'static str),
/// The header to a sequence of the given length. /// The header to a sequence of the given length.
/// ///
/// These are serialized via `serialize_seq`, which takes an optional length. After this /// These are serialized via `serialize_seq`, which takes an optional length. After this
/// header is a list of elements, followed by `SeqEnd`. /// header is a list of elements, followed by `SeqEnd`.
SeqStart(Option<usize>), Seq(Option<usize>),
/// The header to an array of the given length.
///
/// These are serialized via `serialize_seq_fized_size`, which requires a length. After this
/// header is a list of elements, followed by `SeqEnd`.
SeqArrayStart(usize),
/// A separator, which occurs *before* every element in a sequence.
///
/// Elements in sequences are represented by a `SeqSep`, followed by the value of the element.
SeqSep,
/// An indicator of the end of a sequence. /// An indicator of the end of a sequence.
SeqEnd, SeqEnd,
/// The header to a tuple of the given length, similar to `SeqArrayStart`. /// The header to a tuple of the given length, similar to `SeqFixedSize`.
TupleStart(usize), Tuple(usize),
/// A separator, similar to `SeqSep`.
TupleSep,
/// An indicator of the end of a tuple, similar to `SeqEnd`. /// An indicator of the end of a tuple, similar to `SeqEnd`.
TupleEnd, TupleEnd,
/// The header to a tuple struct of the given name and length. /// The header to a tuple struct of the given name and length.
TupleStructStart(&'a str, usize), TupleStruct(&'static str, usize),
/// A separator, similar to `TupleSep`.
TupleStructSep,
/// An indicator of the end of a tuple struct, similar to `TupleEnd`. /// An indicator of the end of a tuple struct, similar to `TupleEnd`.
TupleStructEnd, TupleStructEnd,
@@ -129,42 +122,27 @@ pub enum Token<'a> {
/// ///
/// These are serialized via `serialize_map`, which takes an optional length. After this header /// These are serialized via `serialize_map`, which takes an optional length. After this header
/// is a list of key-value pairs, followed by `MapEnd`. /// is a list of key-value pairs, followed by `MapEnd`.
MapStart(Option<usize>), Map(Option<usize>),
/// A separator, which occurs *before* every key-value pair in a map.
///
/// Elements in maps are represented by a `MapSep`, followed by a serialized key, followed
/// by a serialized value.
MapSep,
/// An indicator of the end of a map. /// An indicator of the end of a map.
MapEnd, MapEnd,
/// The header of a struct of the given name and length, similar to `MapStart`. /// The header of a struct of the given name and length, similar to `Map`.
StructStart(&'a str, usize), Struct(&'static str, usize),
/// A separator, similar to `MapSep`.
StructSep,
/// An indicator of the end of a struct, similar to `MapEnd`. /// An indicator of the end of a struct, similar to `MapEnd`.
StructEnd, StructEnd,
/// The header to a tuple variant of an enum of the given name, of the given name and length. /// The header to a tuple variant of an enum of the given name, of the given name and length.
EnumSeqStart(&'a str, &'a str, usize), TupleVariant(&'static str, &'static str, usize),
/// A separator, similar to `TupleSep`.
EnumSeqSep,
/// An indicator of the end of a tuple variant, similar to `TupleEnd`. /// An indicator of the end of a tuple variant, similar to `TupleEnd`.
EnumSeqEnd, TupleVariantEnd,
/// The header of a struct variant of an enum of the given name, of the given name and length, /// The header of a struct variant of an enum of the given name, of the given name and length,
/// similar to `StructStart`. /// similar to `Struct`.
EnumMapStart(&'a str, &'a str, usize), StructVariant(&'static str, &'static str, usize),
/// A separator, similar to `StructSep`.
EnumMapSep,
/// An indicator of the end of a struct, similar to `StructEnd`. /// An indicator of the end of a struct, similar to `StructEnd`.
EnumMapEnd, StructVariantEnd,
} }
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "zzz")] //~^^ HELP: failed to parse borrowed lifetimes: "zzz"
s: &'a str,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "'a + 'a")] //~^^ HELP: duplicate borrowed lifetime `'a`
s: &'a str,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "")] //~^^ HELP: at least one lifetime must be borrowed
s: &'a str,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test {
#[serde(borrow)] //~^^ HELP: field `s` has no lifetimes to borrow
s: String,
}
fn main() {}
@@ -0,0 +1,18 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
#[serde(borrow = "'b")] //~^^ HELP: field `s` does not have lifetime 'b
s: &'a str,
}
fn main() {}
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier, variant_identifier)] //~^ HELP: `field_identifier` and `variant_identifier` cannot both be set
enum F {
A,
B,
}
fn main() {}
@@ -0,0 +1,16 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
struct S; //~^^ HELP: `field_identifier` can only be used on an enum
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
enum F {
A,
B(u8, u8), //~^^^^ HELP: field_identifier may only contain unit variants
}
fn main() {}
@@ -0,0 +1,20 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
enum F {
A,
Other(String), //~^^^^ HELP: `Other` must be the last variant
B,
}
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
enum F {
A,
#[serde(other)] //~^^^ HELP: #[serde(other)] may only be used inside a field_identifier
B,
}
fn main() {}
@@ -0,0 +1,20 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
enum F {
A,
#[serde(other)] //~^^^^ HELP: #[serde(other)] must be on a unit variant
Other(u8, u8),
}
fn main() {}
@@ -0,0 +1,21 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)]
enum F {
A,
#[serde(other)] //~^^^^ HELP: #[serde(other)] must be the last variant
Other,
B,
}
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(field_identifier)] //~^ HELP: field identifiers cannot be serialized
enum F {
A,
B,
}
fn main() {}
@@ -0,0 +1,16 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(variant_identifier)]
struct S; //~^^ HELP: `variant_identifier` can only be used on an enum
fn main() {}
@@ -0,0 +1,19 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
#[serde(variant_identifier)]
enum F {
A,
B(u8, u8), //~^^^^ HELP: variant_identifier may only contain unit variants
}
fn main() {}
@@ -0,0 +1,25 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
a: u8,
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "remote::S")]
struct S {
#[serde(getter = "~~~")] //~^^^ HELP: failed to parse path: "~~~"
a: u8,
}
fn main() {}
@@ -0,0 +1,24 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
a: u8,
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "~~~")] //~^ HELP: failed to parse path: "~~~"
struct S {
a: u8,
}
fn main() {}
@@ -0,0 +1,27 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub enum E {
A { a: u8 }
}
}
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
#[serde(remote = "remote::E")]
pub enum E {
A {
#[serde(getter = "get_a")] //~^^^^ HELP: #[serde(getter = "...")] is not allowed in an enum
a: u8,
}
}
fn main() {}
@@ -0,0 +1,25 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
pub a: u8,
pub b: u8,
}
}
#[derive(Serialize, Deserialize)] //~ ERROR: missing field `b` in initializer of `remote::S`
#[serde(remote = "remote::S")]
struct S {
a: u8, //~^^^ ERROR: missing field `b` in initializer of `remote::S`
}
fn main() {}
@@ -0,0 +1,24 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
struct S {
#[serde(getter = "S::get")] //~^^ HELP: #[serde(getter = "...")] can only be used in structs that have #[serde(remote = "...")]
a: u8,
}
impl S {
fn get(&self) -> u8 {
self.a
}
}
fn main() {}
@@ -0,0 +1,24 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
pub a: u8,
}
}
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::S")]
struct S {
b: u8, //~^^^ ERROR: no field `b` on type `&remote::S`
}
fn main() {}
@@ -0,0 +1,20 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S(pub u16);
}
#[derive(Deserialize)] //~ ERROR: mismatched types
#[serde(remote = "remote::S")]
struct S(u8); //~^^ expected u16, found u8
fn main() {}
@@ -0,0 +1,31 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
a: u8,
}
impl S {
pub fn get(&self) -> u16 {
self.a as u16
}
}
}
#[derive(Serialize)] //~ ERROR: mismatched types
#[serde(remote = "remote::S")]
struct S {
#[serde(getter = "remote::S::get")]
a: u8, //~^^^^ expected u8, found u16
}
fn main() {}
@@ -0,0 +1,24 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
mod remote {
pub struct S {
pub a: u16,
}
}
#[derive(Serialize)] //~ ERROR: mismatched types
#[serde(remote = "remote::S")]
struct S {
a: u8, //~^^^ expected u8, found u16
}
fn main() {}
@@ -1,9 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)] //~ ERROR: proc-macro derive panicked
struct Test<'a> {
s: &'a str, //~^^ HELP: Serde does not support deserializing fields of type &str
}
fn main() {}
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
+8
View File
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg(feature = "unstable")] #![cfg(feature = "unstable")]
extern crate compiletest_rs as compiletest; extern crate compiletest_rs as compiletest;
+8
View File
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
macro_rules! btreeset { macro_rules! btreeset {
() => { () => {
BTreeSet::new() BTreeSet::new()
+8
View File
@@ -1,3 +1,11 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deny(identity_op)] #![deny(identity_op)]
#[macro_use] #[macro_use]
File diff suppressed because it is too large Load Diff
+175
View File
@@ -0,0 +1,175 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
extern crate serde;
use serde::{Deserialize, Deserializer};
extern crate serde_test;
use serde_test::{Error, Token, assert_de_tokens, assert_de_tokens_error};
use std::borrow::Cow;
#[test]
fn test_borrowed_str() {
assert_de_tokens(&"borrowed", &[Token::BorrowedStr("borrowed")]);
}
#[test]
fn test_borrowed_str_from_string() {
assert_de_tokens_error::<&str>(
&[Token::String("borrowed")],
Error::Message("invalid type: string \"borrowed\", expected a borrowed string".to_owned(),),
);
}
#[test]
fn test_borrowed_str_from_str() {
assert_de_tokens_error::<&str>(
&[Token::Str("borrowed")],
Error::Message("invalid type: string \"borrowed\", expected a borrowed string".to_owned(),),
);
}
#[test]
fn test_string_from_borrowed_str() {
assert_de_tokens(&"owned".to_owned(), &[Token::BorrowedStr("owned")]);
}
#[test]
fn test_borrowed_bytes() {
assert_de_tokens(&&b"borrowed"[..], &[Token::BorrowedBytes(b"borrowed")]);
}
#[test]
fn test_borrowed_bytes_from_bytebuf() {
assert_de_tokens_error::<&[u8]>(
&[Token::ByteBuf(b"borrowed")],
Error::Message("invalid type: byte array, expected a borrowed byte array".to_owned(),),
);
}
#[test]
fn test_borrowed_bytes_from_bytes() {
assert_de_tokens_error::<&[u8]>(
&[Token::Bytes(b"borrowed")],
Error::Message("invalid type: byte array, expected a borrowed byte array".to_owned(),),
);
}
#[test]
fn test_tuple() {
assert_de_tokens(
&("str", &b"bytes"[..]),
&[
Token::Tuple(2),
Token::BorrowedStr("str"),
Token::BorrowedBytes(b"bytes"),
Token::TupleEnd,
],
);
}
#[test]
fn test_struct() {
#[derive(Deserialize, Debug, PartialEq)]
struct Borrowing<'a, 'b> {
bs: &'a str,
bb: &'b [u8],
}
assert_de_tokens(
&Borrowing {
bs: "str",
bb: b"bytes",
},
&[
Token::Struct("Borrowing", 2),
Token::BorrowedStr("bs"),
Token::BorrowedStr("str"),
Token::BorrowedStr("bb"),
Token::BorrowedBytes(b"bytes"),
Token::StructEnd,
],
);
}
#[test]
fn test_cow() {
#[derive(Deserialize)]
struct Cows<'a, 'b> {
copied: Cow<'a, str>,
#[serde(borrow)]
borrowed: Cow<'b, str>,
}
let tokens = &[
Token::Struct("Cows", 2),
Token::Str("copied"),
Token::BorrowedStr("copied"),
Token::Str("borrowed"),
Token::BorrowedStr("borrowed"),
Token::StructEnd,
];
let mut de = serde_test::Deserializer::new(tokens);
let cows = Cows::deserialize(&mut de).unwrap();
assert_eq!(de.next_token(), None);
match cows.copied {
Cow::Owned(ref s) if s == "copied" => {}
_ => panic!("expected a copied string"),
}
match cows.borrowed {
Cow::Borrowed("borrowed") => {}
_ => panic!("expected a borrowed string"),
}
}
#[test]
fn test_lifetimes() {
#[derive(Deserialize)]
struct Cows<'a, 'b> {
_copied: Cow<'a, str>,
#[serde(borrow)]
_borrowed: Cow<'b, str>,
}
// Tests that `'de: 'a` is not required by the Deserialize impl.
fn _cows_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Cows<'a, 'b>
where
D: Deserializer<'de>,
{
Deserialize::deserialize(deserializer).unwrap()
}
#[derive(Deserialize)]
struct Wrap<'a, 'b> {
#[serde(borrow = "'b")]
_cows: Cows<'a, 'b>,
}
// Tests that `'de: 'a` is not required by the Deserialize impl.
fn _wrap_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Wrap<'a, 'b>
where
D: Deserializer<'de>,
{
Deserialize::deserialize(deserializer).unwrap()
}
}

Some files were not shown because too many files have changed in this diff Show More