mirror of
https://github.com/serde-rs/serde.git
synced 2025-09-30 14:31:53 +00:00
Merge branch 'origin/1.0' into 'origin/master'
This commit is contained in:
commit
c567e749ef
@ -1,8 +1,8 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"serde",
|
||||
"serde_codegen_internals",
|
||||
"serde_derive",
|
||||
"serde_derive_internals",
|
||||
"serde_test",
|
||||
"test_suite",
|
||||
"test_suite/no_std",
|
||||
|
@ -1,4 +1,9 @@
|
||||
# Serde   [](https://travis-ci.org/serde-rs/serde) [](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.**
|
||||
|
||||
|
5
rustfmt.toml
Normal file
5
rustfmt.toml
Normal file
@ -0,0 +1,5 @@
|
||||
fn_args_layout = "Block"
|
||||
array_layout = "Block"
|
||||
where_style = "Rfc"
|
||||
generics_indent = "Block"
|
||||
fn_call_style = "Block"
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "0.9.14"
|
||||
version = "0.9.14" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
@ -9,27 +9,68 @@ repository = "https://github.com/serde-rs/serde"
|
||||
documentation = "https://docs.serde.rs/serde/"
|
||||
keywords = ["serde", "serialization", "no_std"]
|
||||
categories = ["encoding"]
|
||||
readme = "../README.md"
|
||||
readme = "README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
publish = false # this branch contains breaking changes
|
||||
|
||||
[badges]
|
||||
travis-ci = { 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"]
|
||||
appveyor = { repository = "serde-rs/serde" }
|
||||
|
||||
[dependencies]
|
||||
serde_derive = { version = "0.9", optional = true, path = "../serde_derive" }
|
||||
|
||||
[dev-dependencies]
|
||||
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"]
|
||||
|
@ -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
@ -1,6 +1,4 @@
|
||||
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
// 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
|
||||
@ -8,402 +6,111 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// 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.
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use core::{usize, u8, u16, u32, u64};
|
||||
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)
|
||||
macro_rules! int_to_int {
|
||||
($dst:ident, $n:ident) => (
|
||||
if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
let n = $slf as f64;
|
||||
let max_value: $SrcT = ::core::$SrcT::MAX;
|
||||
if -max_value as f64 <= n && n <= max_value as f64 {
|
||||
Some($slf as $DstT)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! impl_to_primitive_float {
|
||||
($T:ident) => (
|
||||
impl ToPrimitive for $T {
|
||||
#[inline]
|
||||
fn to_isize(&self) -> Option<isize> { Some(*self as isize) }
|
||||
#[inline]
|
||||
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) }
|
||||
macro_rules! int_to_uint {
|
||||
($dst:ident, $n:ident) => (
|
||||
if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
impl_to_primitive_float! { f32 }
|
||||
impl_to_primitive_float! { f64 }
|
||||
macro_rules! uint_to {
|
||||
($dst:ident, $n:ident) => (
|
||||
if $n as u64 <= $dst::MAX as u64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub trait FromPrimitive: Sized {
|
||||
#[inline]
|
||||
fn from_isize(n: isize) -> Option<Self> {
|
||||
FromPrimitive::from_i64(n as i64)
|
||||
}
|
||||
|
||||
#[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_isize(n: isize) -> Option<Self>;
|
||||
fn from_i8(n: i8) -> Option<Self>;
|
||||
fn from_i16(n: i16) -> Option<Self>;
|
||||
fn from_i32(n: i32) -> Option<Self>;
|
||||
fn from_i64(n: i64) -> Option<Self>;
|
||||
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> Option<Self> {
|
||||
FromPrimitive::from_u64(n as u64)
|
||||
}
|
||||
|
||||
#[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_usize(n: usize) -> Option<Self>;
|
||||
fn from_u8(n: u8) -> Option<Self>;
|
||||
fn from_u16(n: u16) -> Option<Self>;
|
||||
fn from_u32(n: u32) -> 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 {
|
||||
($T:ty, $to_ty:ident) => (
|
||||
impl FromPrimitive for $T {
|
||||
#[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
|
||||
#[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
|
||||
#[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
|
||||
#[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
|
||||
|
||||
#[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
|
||||
#[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
|
||||
#[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
|
||||
#[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
|
||||
|
||||
#[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
|
||||
#[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
|
||||
macro_rules! impl_from_primitive_for_int {
|
||||
($t:ident) => (
|
||||
impl FromPrimitive for $t {
|
||||
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!($t, n) }
|
||||
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!($t, n) }
|
||||
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) }
|
||||
#[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_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
impl_from_primitive! { isize, to_isize }
|
||||
impl_from_primitive! { i8, to_i8 }
|
||||
impl_from_primitive! { i16, to_i16 }
|
||||
impl_from_primitive! { i32, to_i32 }
|
||||
impl_from_primitive! { i64, to_i64 }
|
||||
impl_from_primitive! { usize, to_usize }
|
||||
impl_from_primitive! { u8, to_u8 }
|
||||
impl_from_primitive! { u16, to_u16 }
|
||||
impl_from_primitive! { u32, to_u32 }
|
||||
impl_from_primitive! { u64, to_u64 }
|
||||
impl_from_primitive! { f32, to_f32 }
|
||||
impl_from_primitive! { f64, to_f64 }
|
||||
macro_rules! impl_from_primitive_for_uint {
|
||||
($t:ident) => (
|
||||
impl FromPrimitive for $t {
|
||||
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
|
||||
#[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
serde/src/de/ignored_any.rs
Normal file
215
serde/src/de/ignored_any.rs
Normal 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)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
1585
serde/src/de/mod.rs
1585
serde/src/de/mod.rs
File diff suppressed because it is too large
Load Diff
@ -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
serde/src/de/utf8.rs
Normal file
54
serde/src/de/utf8.rs
Normal 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()
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
}
|
@ -1,36 +1,41 @@
|
||||
#[cfg(all(feature = "collections", not(feature = "std")))]
|
||||
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:
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// 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 = "collections", feature = "std")))]
|
||||
pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
|
||||
use core::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}")
|
||||
// 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.
|
||||
|
||||
pub use lib::clone::Clone;
|
||||
pub use lib::convert::{From, Into};
|
||||
pub use lib::default::Default;
|
||||
pub use lib::fmt::{self, Formatter};
|
||||
pub use lib::marker::PhantomData;
|
||||
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}")
|
||||
}
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
228
serde/src/lib.rs
228
serde/src/lib.rs
@ -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 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
|
||||
//! 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.
|
||||
//!
|
||||
//! ### Design
|
||||
//! [https://serde.rs/]: https://serde.rs/
|
||||
//!
|
||||
//! ## Design
|
||||
//!
|
||||
//! Where many other languages rely on runtime reflection for serializing data,
|
||||
//! 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
|
||||
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's code
|
||||
//! generation to automatically derive implementations at compile time). This
|
||||
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
|
||||
//! attribute to automatically generate implementations at compile time). This
|
||||
//! avoids any overhead of reflection or runtime type information. In fact in
|
||||
//! many situations the interaction between data structure and data format can
|
||||
//! be completely optimized away by the Rust compiler, leaving Serde
|
||||
//! serialization to perform roughly the same speed as a handwritten serializer
|
||||
//! for the specific selection of data structure and data format.
|
||||
//! serialization to perform the same speed as a handwritten serializer for the
|
||||
//! 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
|
||||
//! for Serde by the community.
|
||||
//!
|
||||
//! - [JSON](https://github.com/serde-rs/json), the ubiquitous JavaScript Object
|
||||
//! Notation used by many HTTP APIs.
|
||||
//! - [Bincode](https://github.com/TyOverby/bincode), a compact binary format
|
||||
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
|
||||
//! - [Bincode], a compact binary format
|
||||
//! used for IPC within the Servo rendering engine.
|
||||
//! - [CBOR](https://github.com/pyfisch/cbor), a Concise Binary Object
|
||||
//! Representation designed for small message size without the need for
|
||||
//! version negotiation.
|
||||
//! - [YAML](https://github.com/dtolnay/serde-yaml), a popular human-friendly
|
||||
//! configuration language that ain't markup language.
|
||||
//! - [MessagePack](https://github.com/3Hren/msgpack-rust), an efficient binary
|
||||
//! format that resembles a compact JSON.
|
||||
//! - [TOML](https://github.com/alexcrichton/toml-rs), a minimal configuration
|
||||
//! format used by [Cargo](http://doc.crates.io/manifest.html).
|
||||
//! - [Pickle](https://github.com/birkenfeld/serde-pickle), a format common in
|
||||
//! the Python world.
|
||||
//! - [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).
|
||||
//! - [CBOR], a Concise Binary Object Representation designed for small message
|
||||
//! size without the need for version negotiation.
|
||||
//! - [YAML], a popular human-friendly configuration language that ain't markup
|
||||
//! language.
|
||||
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
|
||||
//! - [TOML], a minimal configuration format used by [Cargo].
|
||||
//! - [Pickle], a format common in the Python world.
|
||||
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
|
||||
//! - [BSON], the data storage and network transfer format used by MongoDB.
|
||||
//! - [URL], the x-www-form-urlencoded format.
|
||||
//! - [XML], the flexible machine-friendly W3C standard.
|
||||
//! *(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(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 = "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")]
|
||||
extern crate collections;
|
||||
@ -73,40 +110,115 @@ extern crate collections;
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
extern crate core as actual_core;
|
||||
#[cfg(all(feature = "unstable", feature = "std"))]
|
||||
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")]
|
||||
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)]
|
||||
pub use ser::{Serialize, Serializer};
|
||||
#[doc(inline)]
|
||||
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.
|
||||
#[doc(hidden)]
|
||||
pub mod export;
|
||||
|
||||
// Helpers used by generated code and doc tests. Not public API.
|
||||
#[doc(hidden)]
|
||||
pub mod private;
|
||||
|
||||
// Re-export #[derive(Serialize, Deserialize)].
|
||||
//
|
||||
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
|
||||
|
@ -1,107 +1,10 @@
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! forward_to_deserialize_method {
|
||||
($func:ident($($arg:ty),*)) => {
|
||||
#[inline]
|
||||
fn $func<__V>(self, $(_: $arg,)* visitor: __V) -> $crate::export::Result<__V::Value, Self::Error>
|
||||
where __V: $crate::de::Visitor
|
||||
{
|
||||
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()}
|
||||
};
|
||||
}
|
||||
// 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.
|
||||
|
||||
// Super explicit first paragraph because this shows up at the top level and
|
||||
// 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
|
||||
/// for Serde.
|
||||
///
|
||||
/// Some `Deserializer` implementations for self-describing formats do not care
|
||||
/// what hint the `Visitor` gives them, they just want to blindly call the
|
||||
/// `Visitor` method corresponding to the data they can tell is in the input.
|
||||
/// This requires repetitive implementations of all the `Deserializer` trait
|
||||
/// methods.
|
||||
/// Some [`Deserializer`] implementations for self-describing formats do not
|
||||
/// care what hint the [`Visitor`] gives them, they just want to blindly call
|
||||
/// the [`Visitor`] method corresponding to the data they can tell is in the
|
||||
/// input. This requires repetitive implementations of all the [`Deserializer`]
|
||||
/// trait methods.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde;
|
||||
/// # #[macro_use]
|
||||
/// # extern crate serde;
|
||||
/// #
|
||||
/// # 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;
|
||||
/// # fn deserialize<V>(self, _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor
|
||||
/// # { unimplemented!() }
|
||||
/// #
|
||||
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor<'de>
|
||||
/// # {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
/// #
|
||||
/// #[inline]
|
||||
/// 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
|
||||
/// # seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
/// # tuple_struct struct struct_field tuple enum ignored_any
|
||||
/// #
|
||||
/// # forward_to_deserialize_any! {
|
||||
/// # 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() {}
|
||||
/// ```
|
||||
///
|
||||
/// The `forward_to_deserialize!` macro implements these simple forwarding
|
||||
/// methods so that they forward directly to `Deserializer::deserialize`. You
|
||||
/// can choose which methods to forward.
|
||||
/// The `forward_to_deserialize_any!` macro implements these simple forwarding
|
||||
/// methods so that they forward directly to [`Deserializer::deserialize_any`].
|
||||
/// You can choose which methods to forward.
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate serde;
|
||||
/// # #[macro_use]
|
||||
/// # extern crate serde;
|
||||
/// #
|
||||
/// # 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;
|
||||
/// 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;
|
||||
/// # unimplemented!()
|
||||
/// }
|
||||
///
|
||||
/// forward_to_deserialize! {
|
||||
/// bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
|
||||
/// seq seq_fixed_size bytes byte_buf map unit_struct newtype_struct
|
||||
/// tuple_struct struct struct_field tuple enum ignored_any
|
||||
/// 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
|
||||
/// }
|
||||
/// }
|
||||
/// #
|
||||
/// # 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_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)*) => {
|
||||
$(forward_to_deserialize_helper!{$func})*
|
||||
$(forward_to_deserialize_any_helper!{$func<'de, V>})*
|
||||
};
|
||||
}
|
||||
|
||||
/// Seralize the `$value` that implements Display as a string,
|
||||
/// when that string is statically known to never have more than
|
||||
/// a constant `$MAX_LEN` bytes.
|
||||
///
|
||||
/// Panics if the Display impl tries to write more than `$MAX_LEN` bytes.
|
||||
#[cfg(feature = "std")]
|
||||
// Not exported
|
||||
macro_rules! serialize_display_bounded_length {
|
||||
($value: expr, $MAX_LEN: expr, $serializer: expr) => {
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! forward_to_deserialize_any_method {
|
||||
($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => {
|
||||
#[inline]
|
||||
fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::export::Result<$v::Value, Self::Error>
|
||||
where
|
||||
$v: $crate::de::Visitor<$l>,
|
||||
{
|
||||
use std::io::Write;
|
||||
let mut buffer: [u8; $MAX_LEN] = unsafe { ::std::mem::uninitialized() };
|
||||
let remaining_len;
|
||||
{
|
||||
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)
|
||||
$(
|
||||
let _ = $arg;
|
||||
)*
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[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>()}
|
||||
};
|
||||
}
|
||||
|
1849
serde/src/private/de.rs
Normal file
1849
serde/src/private/de.rs
Normal file
File diff suppressed because it is too large
Load Diff
148
serde/src/private/macros.rs
Normal file
148
serde/src/private/macros.rs
Normal 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
serde/src/private/mod.rs
Normal file
12
serde/src/private/mod.rs
Normal 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;
|
1019
serde/src/private/ser.rs
Normal file
1019
serde/src/private/ser.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -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))
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use lib::*;
|
||||
|
||||
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
|
||||
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
|
||||
@ -9,11 +17,19 @@ use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
|
||||
/// serializing one of the compound types.
|
||||
///
|
||||
/// This type cannot be instantiated, but implements every one of the traits
|
||||
/// corresponding to the `Serializer` compound types: `SerializeSeq`,
|
||||
/// `SerializeTuple`, `SerializeTupleStruct`, `SerializeTupleVariant`,
|
||||
/// `SerializeMap`, `SerializeStruct`, and `SerializeStructVariant`.
|
||||
/// corresponding to the [`Serializer`] compound types: [`SerializeSeq`],
|
||||
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
|
||||
/// [`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 {
|
||||
/// type Ok = ();
|
||||
/// type Error = Error;
|
||||
@ -27,130 +43,185 @@ use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
|
||||
/// -> Result<Self::SerializeSeq, Error> {
|
||||
/// // Given Impossible cannot be instantiated, the only
|
||||
/// // thing we can do here is to return an error.
|
||||
/// # stringify! {
|
||||
/// Err(...)
|
||||
/// # };
|
||||
/// # unimplemented!()
|
||||
/// }
|
||||
///
|
||||
/// /* 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,
|
||||
_marker: PhantomData<(Ok, E)>,
|
||||
ok: PhantomData<Ok>,
|
||||
error: PhantomData<Error>,
|
||||
}
|
||||
|
||||
enum Void {}
|
||||
|
||||
impl<Ok, E> SerializeSeq for Impossible<Ok, E>
|
||||
where E: ser::Error
|
||||
impl<Ok, Error> SerializeSeq for Impossible<Ok, Error>
|
||||
where
|
||||
Error: ser::Error,
|
||||
{
|
||||
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 {}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Ok, E> {
|
||||
fn end(self) -> Result<Ok, Error> {
|
||||
match self.void {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ok, E> SerializeTuple for Impossible<Ok, E>
|
||||
where E: ser::Error
|
||||
impl<Ok, Error> SerializeTuple for Impossible<Ok, Error>
|
||||
where
|
||||
Error: ser::Error,
|
||||
{
|
||||
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 {}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Ok, E> {
|
||||
fn end(self) -> Result<Ok, Error> {
|
||||
match self.void {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ok, E> SerializeTupleStruct for Impossible<Ok, E>
|
||||
where E: ser::Error
|
||||
impl<Ok, Error> SerializeTupleStruct for Impossible<Ok, Error>
|
||||
where
|
||||
Error: ser::Error,
|
||||
{
|
||||
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 {}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Ok, E> {
|
||||
fn end(self) -> Result<Ok, Error> {
|
||||
match self.void {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ok, E> SerializeTupleVariant for Impossible<Ok, E>
|
||||
where E: ser::Error
|
||||
impl<Ok, Error> SerializeTupleVariant for Impossible<Ok, Error>
|
||||
where
|
||||
Error: ser::Error,
|
||||
{
|
||||
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 {}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Ok, E> {
|
||||
fn end(self) -> Result<Ok, Error> {
|
||||
match self.void {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ok, E> SerializeMap for Impossible<Ok, E>
|
||||
where E: ser::Error
|
||||
impl<Ok, Error> SerializeMap for Impossible<Ok, Error>
|
||||
where
|
||||
Error: ser::Error,
|
||||
{
|
||||
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 {}
|
||||
}
|
||||
|
||||
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 {}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Ok, E> {
|
||||
fn end(self) -> Result<Ok, Error> {
|
||||
match self.void {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ok, E> SerializeStruct for Impossible<Ok, E>
|
||||
where E: ser::Error
|
||||
impl<Ok, Error> SerializeStruct for Impossible<Ok, Error>
|
||||
where
|
||||
Error: ser::Error,
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
_key: &'static str,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let _ = key;
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Ok, E> {
|
||||
fn end(self) -> Result<Ok, Error> {
|
||||
match self.void {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ok, E> SerializeStructVariant for Impossible<Ok, E>
|
||||
where E: ser::Error
|
||||
impl<Ok, Error> SerializeStructVariant for Impossible<Ok, Error>
|
||||
where
|
||||
Error: ser::Error,
|
||||
{
|
||||
type Ok = Ok;
|
||||
type Error = E;
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T: ?Sized + Serialize>(&mut self,
|
||||
_key: &'static str,
|
||||
_value: &T)
|
||||
-> Result<(), E> {
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let _ = key;
|
||||
let _ = value;
|
||||
match self.void {}
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Ok, E> {
|
||||
fn end(self) -> Result<Ok, Error> {
|
||||
match self.void {}
|
||||
}
|
||||
}
|
||||
|
1568
serde/src/ser/mod.rs
1568
serde/src/ser/mod.rs
File diff suppressed because it is too large
Load Diff
@ -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))
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
extern crate syn;
|
||||
|
||||
pub mod ast;
|
||||
pub mod attr;
|
||||
|
||||
mod ctxt;
|
||||
pub use ctxt::Ctxt;
|
||||
|
||||
mod case;
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "0.9.14"
|
||||
version = "0.9.14" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
@ -8,11 +8,9 @@ homepage = "https://serde.rs"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
documentation = "https://serde.rs/codegen.html"
|
||||
keywords = ["serde", "serialization", "no_std"]
|
||||
readme = "../README.md"
|
||||
readme = "README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[features]
|
||||
unstable = []
|
||||
publish = false # this branch contains breaking changes
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "serde-rs/serde" }
|
||||
@ -23,5 +21,5 @@ proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
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"] }
|
||||
|
@ -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 syn::{self, visit};
|
||||
|
||||
use internals::ast::Item;
|
||||
use internals::ast::Container;
|
||||
use internals::attr;
|
||||
|
||||
macro_rules! path {
|
||||
($first:ident $(:: $rest:ident)*) => {
|
||||
syn::Path {
|
||||
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(),
|
||||
)*
|
||||
],
|
||||
}
|
||||
($($path:tt)+) => {
|
||||
syn::parse_path(stringify!($($path)+)).unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
@ -36,29 +24,43 @@ macro_rules! path {
|
||||
// allowed here".
|
||||
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
|
||||
syn::Generics {
|
||||
ty_params: generics.ty_params
|
||||
ty_params: generics
|
||||
.ty_params
|
||||
.iter()
|
||||
.map(|ty_param| syn::TyParam { default: None, ..ty_param.clone() })
|
||||
.map(
|
||||
|ty_param| {
|
||||
syn::TyParam {
|
||||
default: None,
|
||||
..ty_param.clone()
|
||||
}
|
||||
},
|
||||
)
|
||||
.collect(),
|
||||
..generics.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_where_predicates(generics: &syn::Generics,
|
||||
predicates: &[syn::WherePredicate])
|
||||
-> syn::Generics {
|
||||
pub fn with_where_predicates(
|
||||
generics: &syn::Generics,
|
||||
predicates: &[syn::WherePredicate],
|
||||
) -> syn::Generics {
|
||||
let mut generics = generics.clone();
|
||||
generics.where_clause.predicates.extend_from_slice(predicates);
|
||||
generics
|
||||
.where_clause
|
||||
.predicates
|
||||
.extend_from_slice(predicates);
|
||||
generics
|
||||
}
|
||||
|
||||
pub fn with_where_predicates_from_fields<F>(item: &Item,
|
||||
generics: &syn::Generics,
|
||||
from_field: F)
|
||||
-> syn::Generics
|
||||
where F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>
|
||||
pub fn with_where_predicates_from_fields<F>(
|
||||
cont: &Container,
|
||||
generics: &syn::Generics,
|
||||
from_field: F,
|
||||
) -> syn::Generics
|
||||
where
|
||||
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
|
||||
{
|
||||
let predicates = item.body
|
||||
let predicates = cont.body
|
||||
.all_fields()
|
||||
.flat_map(|field| from_field(&field.attrs))
|
||||
.flat_map(|predicates| predicates.to_vec());
|
||||
@ -79,12 +81,14 @@ pub fn with_where_predicates_from_fields<F>(item: &Item,
|
||||
// #[serde(skip_serializing)]
|
||||
// c: C,
|
||||
// }
|
||||
pub fn with_bound<F>(item: &Item,
|
||||
generics: &syn::Generics,
|
||||
filter: F,
|
||||
bound: &syn::Path)
|
||||
-> syn::Generics
|
||||
where F: Fn(&attr::Field) -> bool
|
||||
pub fn with_bound<F>(
|
||||
cont: &Container,
|
||||
generics: &syn::Generics,
|
||||
filter: F,
|
||||
bound: &syn::Path,
|
||||
) -> syn::Generics
|
||||
where
|
||||
F: Fn(&attr::Field) -> bool,
|
||||
{
|
||||
struct FindTyParams {
|
||||
// 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()
|
||||
.map(|ty_param| ty_param.ident.clone())
|
||||
.collect();
|
||||
|
||||
let relevant_tys = item.body
|
||||
let relevant_tys = cont.body
|
||||
.all_fields()
|
||||
.filter(|&field| filter(&field.attrs))
|
||||
.map(|field| &field.ty);
|
||||
@ -132,58 +137,66 @@ pub fn with_bound<F>(item: &Item,
|
||||
visit::walk_ty(&mut visitor, ty);
|
||||
}
|
||||
|
||||
let new_predicates = generics.ty_params
|
||||
let new_predicates = generics
|
||||
.ty_params
|
||||
.iter()
|
||||
.map(|ty_param| ty_param.ident.clone())
|
||||
.filter(|id| visitor.relevant_ty_params.contains(id))
|
||||
.map(|id| {
|
||||
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
|
||||
bound_lifetimes: Vec::new(),
|
||||
// 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 {
|
||||
.map(
|
||||
|id| {
|
||||
syn::WherePredicate::BoundPredicate(
|
||||
syn::WhereBoundPredicate {
|
||||
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();
|
||||
generics.where_clause.predicates.extend(new_predicates);
|
||||
generics
|
||||
}
|
||||
|
||||
pub fn with_self_bound(item: &Item,
|
||||
generics: &syn::Generics,
|
||||
bound: &syn::Path)
|
||||
-> syn::Generics
|
||||
{
|
||||
pub fn with_self_bound(cont: &Container, generics: &syn::Generics, bound: &syn::Path) -> syn::Generics {
|
||||
let mut generics = generics.clone();
|
||||
generics.where_clause.predicates.push(
|
||||
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
|
||||
bound_lifetimes: Vec::new(),
|
||||
// the type that is being bounded e.g. MyStruct<'a, T>
|
||||
bounded_ty: type_of_item(item),
|
||||
// the bound e.g. Default
|
||||
bounds: vec![syn::TyParamBound::Trait(
|
||||
syn::PolyTraitRef {
|
||||
generics
|
||||
.where_clause
|
||||
.predicates
|
||||
.push(
|
||||
syn::WherePredicate::BoundPredicate(
|
||||
syn::WhereBoundPredicate {
|
||||
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
|
||||
}
|
||||
|
||||
pub fn with_lifetime_bound(generics: &syn::Generics,
|
||||
lifetime: &str)
|
||||
-> syn::Generics {
|
||||
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
|
||||
let mut generics = generics.clone();
|
||||
|
||||
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 {
|
||||
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 {
|
||||
attrs: Vec::new(),
|
||||
lifetime: syn::Lifetime::new(lifetime),
|
||||
bounds: Vec::new(),
|
||||
});
|
||||
generics
|
||||
.lifetimes
|
||||
.push(
|
||||
syn::LifetimeDef {
|
||||
attrs: Vec::new(),
|
||||
lifetime: syn::Lifetime::new(lifetime),
|
||||
bounds: Vec::new(),
|
||||
},
|
||||
);
|
||||
|
||||
generics
|
||||
}
|
||||
|
||||
fn type_of_item(item: &Item) -> syn::Ty {
|
||||
syn::Ty::Path(None, syn::Path {
|
||||
global: false,
|
||||
segments: vec![
|
||||
syn::PathSegment {
|
||||
ident: item.ident.clone(),
|
||||
parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData {
|
||||
lifetimes: item.generics
|
||||
.lifetimes
|
||||
.iter()
|
||||
.map(|def| def.lifetime.clone())
|
||||
.collect(),
|
||||
types: item.generics
|
||||
fn type_of_item(cont: &Container) -> syn::Ty {
|
||||
syn::Ty::Path(
|
||||
None,
|
||||
syn::Path {
|
||||
global: false,
|
||||
segments: vec![
|
||||
syn::PathSegment {
|
||||
ident: cont.ident.clone(),
|
||||
parameters: syn::PathParameters::AngleBracketed(
|
||||
syn::AngleBracketedParameterData {
|
||||
lifetimes: cont.generics
|
||||
.lifetimes
|
||||
.iter()
|
||||
.map(|def| def.lifetime.clone())
|
||||
.collect(),
|
||||
types: cont.generics
|
||||
.ty_params
|
||||
.iter()
|
||||
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
|
||||
.collect(),
|
||||
bindings: Vec::new(),
|
||||
}),
|
||||
}
|
||||
]
|
||||
})
|
||||
bindings: Vec::new(),
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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};
|
||||
|
||||
pub enum Fragment {
|
||||
|
@ -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(used_underscore_binding))]
|
||||
|
||||
@ -8,7 +18,7 @@ extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
||||
extern crate serde_codegen_internals as internals;
|
||||
extern crate serde_derive_internals as internals;
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,19 @@
|
||||
[package]
|
||||
name = "serde_codegen_internals"
|
||||
name = "serde_derive_internals"
|
||||
version = "0.14.2"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||
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"
|
||||
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"]
|
||||
readme = "../README.md"
|
||||
readme = "README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "0.11", default-features = false, features = ["parsing"] }
|
||||
syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
|
||||
synom = "0.11"
|
||||
|
||||
[badges]
|
||||
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 attr;
|
||||
use check;
|
||||
use Ctxt;
|
||||
|
||||
pub struct Item<'a> {
|
||||
pub struct Container<'a> {
|
||||
pub ident: syn::Ident,
|
||||
pub attrs: attr::Item,
|
||||
pub attrs: attr::Container,
|
||||
pub body: Body<'a>,
|
||||
pub generics: &'a syn::Generics,
|
||||
}
|
||||
@ -27,6 +36,7 @@ pub struct Field<'a> {
|
||||
pub ty: &'a syn::Ty,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Style {
|
||||
Struct,
|
||||
Tuple,
|
||||
@ -34,9 +44,9 @@ pub enum Style {
|
||||
Unit,
|
||||
}
|
||||
|
||||
impl<'a> Item<'a> {
|
||||
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> {
|
||||
let attrs = attr::Item::from_ast(cx, item);
|
||||
impl<'a> Container<'a> {
|
||||
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Container<'a> {
|
||||
let attrs = attr::Container::from_ast(cx, item);
|
||||
|
||||
let mut body = match item.body {
|
||||
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(),
|
||||
attrs: attrs,
|
||||
body: body,
|
||||
generics: &item.generics,
|
||||
}
|
||||
};
|
||||
check::check(cx, &item);
|
||||
item
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +93,10 @@ impl<'a> Body<'a> {
|
||||
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>> {
|
@ -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 syn;
|
||||
use syn::MetaItem::{List, NameValue, Word};
|
||||
use syn::NestedMetaItem::{Literal, MetaItem};
|
||||
use synom::IResult;
|
||||
use std::collections::BTreeSet;
|
||||
use std::str::FromStr;
|
||||
|
||||
// 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
|
||||
// struct. Note that none of them return a Result. Unrecognized, malformed, or
|
||||
// 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
|
||||
#[derive(Debug)]
|
||||
pub struct Item {
|
||||
pub struct Container {
|
||||
name: Name,
|
||||
deny_unknown_fields: bool,
|
||||
default: Default,
|
||||
@ -100,6 +110,8 @@ pub struct Item {
|
||||
tag: EnumTag,
|
||||
from_type: Option<syn::Ty>,
|
||||
into_type: Option<syn::Ty>,
|
||||
remote: Option<syn::Path>,
|
||||
identifier: Identifier,
|
||||
}
|
||||
|
||||
/// Styles of representing an enum.
|
||||
@ -134,7 +146,24 @@ pub enum EnumTag {
|
||||
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.
|
||||
pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self {
|
||||
let mut ser_name = Attr::none(cx, "rename");
|
||||
@ -149,11 +178,14 @@ impl Item {
|
||||
let mut content = Attr::none(cx, "content");
|
||||
let mut from_type = Attr::none(cx, "from");
|
||||
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_item in meta_items {
|
||||
match meta_item {
|
||||
// Parse `#[serde(rename="foo")]`
|
||||
// Parse `#[serde(rename = "foo")]`
|
||||
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) {
|
||||
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" => {
|
||||
if let Ok((ser, de)) = get_renames(cx, meta_items) {
|
||||
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" => {
|
||||
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
|
||||
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" => {
|
||||
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
|
||||
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" => {
|
||||
if let Ok(where_predicates) =
|
||||
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" => {
|
||||
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
|
||||
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) => {
|
||||
cx.error(format!("unknown serde container attribute `{}`",
|
||||
meta_item.name()));
|
||||
@ -300,53 +349,7 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
let tag = 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
|
||||
}
|
||||
};
|
||||
|
||||
Item {
|
||||
Container {
|
||||
name: Name {
|
||||
serialize: ser_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),
|
||||
ser_bound: ser_bound.get(),
|
||||
de_bound: de_bound.get(),
|
||||
tag: tag,
|
||||
tag: decide_tag(cx, item, untagged, internal_tag, content),
|
||||
from_type: from_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> {
|
||||
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
|
||||
@ -408,6 +500,7 @@ pub struct Variant {
|
||||
rename_all: RenameRule,
|
||||
skip_deserializing: bool,
|
||||
skip_serializing: bool,
|
||||
other: bool,
|
||||
}
|
||||
|
||||
impl Variant {
|
||||
@ -417,11 +510,12 @@ impl Variant {
|
||||
let mut skip_deserializing = BoolAttr::none(cx, "skip_deserializing");
|
||||
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
|
||||
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_item in meta_items {
|
||||
match meta_item {
|
||||
// Parse `#[serde(rename="foo")]`
|
||||
// Parse `#[serde(rename = "foo")]`
|
||||
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) {
|
||||
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" => {
|
||||
if let Ok((ser, de)) = get_renames(cx, meta_items) {
|
||||
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" => {
|
||||
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
|
||||
match RenameRule::from_str(&s) {
|
||||
@ -455,11 +549,17 @@ impl Variant {
|
||||
MetaItem(Word(ref name)) if name == "skip_deserializing" => {
|
||||
skip_deserializing.set_true();
|
||||
}
|
||||
|
||||
// Parse `#[serde(skip_serializing)]`
|
||||
MetaItem(Word(ref name)) if name == "skip_serializing" => {
|
||||
skip_serializing.set_true();
|
||||
}
|
||||
|
||||
// Parse `#[serde(other)]`
|
||||
MetaItem(Word(ref name)) if name == "other" => {
|
||||
other.set_true();
|
||||
}
|
||||
|
||||
MetaItem(ref meta_item) => {
|
||||
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),
|
||||
skip_deserializing: skip_deserializing.get(),
|
||||
skip_serializing: skip_serializing.get(),
|
||||
other: other.get(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -512,6 +613,10 @@ impl Variant {
|
||||
pub fn skip_serializing(&self) -> bool {
|
||||
self.skip_serializing
|
||||
}
|
||||
|
||||
pub fn other(&self) -> bool {
|
||||
self.other
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents field attribute information
|
||||
@ -528,6 +633,8 @@ pub struct Field {
|
||||
deserialize_with: Option<syn::Path>,
|
||||
ser_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.
|
||||
@ -554,6 +661,8 @@ impl Field {
|
||||
let mut deserialize_with = Attr::none(cx, "deserialize_with");
|
||||
let mut ser_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 {
|
||||
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_item in meta_items {
|
||||
match meta_item {
|
||||
// Parse `#[serde(rename="foo")]`
|
||||
// Parse `#[serde(rename = "foo")]`
|
||||
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) {
|
||||
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" => {
|
||||
if let Ok((ser, de)) = get_renames(cx, meta_items) {
|
||||
ser_name.set_opt(ser);
|
||||
@ -584,7 +693,7 @@ impl Field {
|
||||
default.set(Default::Default);
|
||||
}
|
||||
|
||||
// Parse `#[serde(default="...")]`
|
||||
// Parse `#[serde(default = "...")]`
|
||||
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
|
||||
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
|
||||
default.set(Default::Path(path));
|
||||
@ -601,28 +710,28 @@ impl Field {
|
||||
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" => {
|
||||
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
|
||||
skip_serializing_if.set(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse `#[serde(serialize_with="...")]`
|
||||
// Parse `#[serde(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) {
|
||||
serialize_with.set(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse `#[serde(deserialize_with="...")]`
|
||||
// Parse `#[serde(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) {
|
||||
deserialize_with.set(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse `#[serde(with="...")]`
|
||||
// Parse `#[serde(with = "...")]`
|
||||
MetaItem(NameValue(ref name, ref lit)) if name == "with" => {
|
||||
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
|
||||
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" => {
|
||||
if let Ok(where_predicates) =
|
||||
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" => {
|
||||
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
|
||||
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) => {
|
||||
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()
|
||||
// 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() {
|
||||
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_renamed = ser_name.is_some();
|
||||
let de_name = de_name.get();
|
||||
@ -687,6 +848,8 @@ impl Field {
|
||||
deserialize_with: deserialize_with.get(),
|
||||
ser_bound: ser_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]> {
|
||||
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>);
|
||||
@ -836,3 +1007,174 @@ fn parse_lit_into_ty(cx: &Ctxt,
|
||||
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 ¶ms.types {
|
||||
collect_lifetimes(ty, out);
|
||||
}
|
||||
for binding in ¶ms.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::str::FromStr;
|
||||
|
||||
@ -7,6 +15,8 @@ use self::RenameRule::*;
|
||||
pub enum RenameRule {
|
||||
/// Don't apply a default rename rule.
|
||||
None,
|
||||
/// Rename direct children to "lowercase" style.
|
||||
LowerCase,
|
||||
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
|
||||
PascalCase,
|
||||
/// Rename direct children to "camelCase" style.
|
||||
@ -23,6 +33,7 @@ impl RenameRule {
|
||||
pub fn apply_to_variant(&self, variant: &str) -> String {
|
||||
match *self {
|
||||
None | PascalCase => variant.to_owned(),
|
||||
LowerCase => variant.to_ascii_lowercase(),
|
||||
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
|
||||
SnakeCase => {
|
||||
let mut snake = String::new();
|
||||
@ -41,7 +52,7 @@ impl RenameRule {
|
||||
|
||||
pub fn apply_to_field(&self, field: &str) -> String {
|
||||
match *self {
|
||||
None | SnakeCase => field.to_owned(),
|
||||
None | LowerCase | SnakeCase => field.to_owned(),
|
||||
PascalCase => {
|
||||
let mut pascal = String::new();
|
||||
let mut capitalize = true;
|
||||
@ -72,6 +83,7 @@ impl FromStr for RenameRule {
|
||||
|
||||
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
|
||||
match rename_all_str {
|
||||
"lowercase" => Ok(LowerCase),
|
||||
"PascalCase" => Ok(PascalCase),
|
||||
"camelCase" => Ok(CamelCase),
|
||||
"snake_case" => Ok(SnakeCase),
|
||||
@ -84,12 +96,13 @@ impl FromStr for RenameRule {
|
||||
|
||||
#[test]
|
||||
fn rename_variants() {
|
||||
for &(original, camel, snake, screaming, kebab) in
|
||||
&[("Outcome", "outcome", "outcome", "OUTCOME", "outcome"),
|
||||
("VeryTasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
|
||||
("A", "a", "a", "A", "a"),
|
||||
("Z42", "z42", "z42", "Z42", "z42")] {
|
||||
for &(original, lower, camel, snake, screaming, kebab) in
|
||||
&[("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome"),
|
||||
("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty"),
|
||||
("A", "a", "a", "a", "A", "a"),
|
||||
("Z42", "z42", "z42", "z42", "Z42", "z42")] {
|
||||
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!(CamelCase.apply_to_variant(original), camel);
|
||||
assert_eq!(SnakeCase.apply_to_variant(original), snake);
|
93
serde_derive_internals/src/check.rs
Normal file
93
serde_derive_internals/src/check.rs
Normal 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::cell::RefCell;
|
||||
|
20
serde_derive_internals/src/lib.rs
Normal file
20
serde_derive_internals/src/lib.rs
Normal 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;
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "0.9.14"
|
||||
version = "0.9.14" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||
@ -8,8 +8,9 @@ homepage = "https://serde.rs"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
documentation = "https://docs.serde.rs/serde_test/"
|
||||
keywords = ["serde", "serialization"]
|
||||
readme = "../README.md"
|
||||
readme = "README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
publish = false # this branch contains breaking changes
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "0.9", path = "../serde" }
|
||||
|
@ -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 de::Deserializer;
|
||||
@ -8,8 +16,9 @@ use token::Token;
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Runs both `assert_ser_tokens` and `assert_de_tokens`.
|
||||
pub fn assert_tokens<T>(value: &T, tokens: &[Token<'static>])
|
||||
where T: Serialize + Deserialize + PartialEq + Debug
|
||||
pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
|
||||
where
|
||||
T: Serialize + Deserialize<'de> + PartialEq + Debug,
|
||||
{
|
||||
assert_ser_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`.
|
||||
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!(ser.next_token(), None);
|
||||
}
|
||||
|
||||
/// 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)
|
||||
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);
|
||||
assert_eq!(v.as_ref(), Err(&error));
|
||||
assert_eq!(ser.next_token(), None);
|
||||
}
|
||||
|
||||
/// Asserts that the given `tokens` deserialize into `value`.
|
||||
pub fn assert_de_tokens<T>(value: &T, tokens: &[Token<'static>])
|
||||
where T: Deserialize + PartialEq + Debug
|
||||
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
|
||||
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);
|
||||
assert_eq!(v.as_ref(), Ok(value));
|
||||
assert_eq!(de.next_token(), None);
|
||||
}
|
||||
|
||||
/// Asserts that the given `tokens` yield `error` when deserializing.
|
||||
pub fn assert_de_tokens_error<T>(tokens: &[Token<'static>], error: Error)
|
||||
where T: Deserialize + PartialEq + Debug
|
||||
pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: Error)
|
||||
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);
|
||||
assert_eq!(v, Err(error));
|
||||
// There may be one token left if a peek caused the error
|
||||
|
@ -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,
|
||||
VariantVisitor, Visitor};
|
||||
use serde::de::value::{ValueDeserializer, MapVisitorDeserializer, SeqVisitorDeserializer};
|
||||
use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
|
||||
SeqAccess, VariantAccess, Visitor};
|
||||
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
|
||||
|
||||
use error::Error;
|
||||
use token::Token;
|
||||
|
||||
/// A `Deserializer` that reads from a list of tokens.
|
||||
pub struct Deserializer<I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
tokens: iter::Peekable<I>,
|
||||
#[derive(Debug)]
|
||||
pub struct Deserializer<'de> {
|
||||
tokens: &'de [Token],
|
||||
}
|
||||
|
||||
impl<I> Deserializer<I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
impl<'de> Deserializer<'de> {
|
||||
/// Creates the deserializer.
|
||||
pub fn new(tokens: I) -> Deserializer<I> {
|
||||
Deserializer { tokens: tokens.peekable() }
|
||||
pub fn new(tokens: &'de [Token]) -> Self {
|
||||
Deserializer { tokens: tokens }
|
||||
}
|
||||
|
||||
/// Pulls the next token off of the deserializer, ignoring it.
|
||||
pub fn next_token(&mut self) -> Option<Token<'static>> {
|
||||
self.tokens.next()
|
||||
pub fn next_token(&mut self) -> Option<Token> {
|
||||
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.
|
||||
pub fn expect_token(&mut self, expected: Token) -> Result<(), Error> {
|
||||
match self.tokens.next() {
|
||||
match self.next_token() {
|
||||
Some(token) => {
|
||||
if expected == token {
|
||||
Ok(())
|
||||
@ -41,151 +49,176 @@ impl<I> Deserializer<I>
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_seq<V>(&mut self,
|
||||
len: Option<usize>,
|
||||
sep: Token<'static>,
|
||||
end: Token<'static>,
|
||||
visitor: V)
|
||||
-> Result<V::Value, Error>
|
||||
where V: Visitor
|
||||
fn visit_seq<V>(
|
||||
&mut self,
|
||||
len: Option<usize>,
|
||||
end: Token,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
sep: sep,
|
||||
end: end.clone(),
|
||||
}));
|
||||
let value = try!(
|
||||
visitor.visit_seq(
|
||||
DeserializerSeqVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
end: end.clone(),
|
||||
},
|
||||
)
|
||||
);
|
||||
try!(self.expect_token(end));
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn visit_map<V>(&mut self,
|
||||
len: Option<usize>,
|
||||
sep: Token<'static>,
|
||||
end: Token<'static>,
|
||||
visitor: V)
|
||||
-> Result<V::Value, Error>
|
||||
where V: Visitor
|
||||
fn visit_map<V>(
|
||||
&mut self,
|
||||
len: Option<usize>,
|
||||
end: Token,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let value = try!(visitor.visit_map(DeserializerMapVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
sep: sep,
|
||||
end: end.clone(),
|
||||
}));
|
||||
let value = try!(
|
||||
visitor.visit_map(
|
||||
DeserializerMapVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
end: end.clone(),
|
||||
},
|
||||
)
|
||||
);
|
||||
try!(self.expect_token(end));
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
type Error = Error;
|
||||
|
||||
forward_to_deserialize! {
|
||||
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit
|
||||
seq bytes byte_buf map struct_field ignored_any
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf unit seq map identifier ignored_any
|
||||
}
|
||||
|
||||
fn deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where V: Visitor
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.tokens.next() {
|
||||
Some(Token::Bool(v)) => visitor.visit_bool(v),
|
||||
Some(Token::I8(v)) => visitor.visit_i8(v),
|
||||
Some(Token::I16(v)) => visitor.visit_i16(v),
|
||||
Some(Token::I32(v)) => visitor.visit_i32(v),
|
||||
Some(Token::I64(v)) => visitor.visit_i64(v),
|
||||
Some(Token::U8(v)) => visitor.visit_u8(v),
|
||||
Some(Token::U16(v)) => visitor.visit_u16(v),
|
||||
Some(Token::U32(v)) => visitor.visit_u32(v),
|
||||
Some(Token::U64(v)) => visitor.visit_u64(v),
|
||||
Some(Token::F32(v)) => visitor.visit_f32(v),
|
||||
Some(Token::F64(v)) => visitor.visit_f64(v),
|
||||
Some(Token::Char(v)) => visitor.visit_char(v),
|
||||
Some(Token::Str(v)) => visitor.visit_str(v),
|
||||
Some(Token::String(v)) => visitor.visit_string(v),
|
||||
Some(Token::Bytes(v)) => visitor.visit_bytes(v),
|
||||
Some(Token::ByteBuf(v)) => visitor.visit_byte_buf(v),
|
||||
Some(Token::Option(false)) => visitor.visit_none(),
|
||||
Some(Token::Option(true)) => visitor.visit_some(self),
|
||||
Some(Token::Unit) => visitor.visit_unit(),
|
||||
Some(Token::UnitStruct(_name)) => visitor.visit_unit(),
|
||||
Some(Token::SeqStart(len)) => {
|
||||
self.visit_seq(len, Token::SeqSep, Token::SeqEnd, visitor)
|
||||
let token = self.next_token().ok_or(Error::EndOfTokens)?;
|
||||
match token {
|
||||
Token::Bool(v) => visitor.visit_bool(v),
|
||||
Token::I8(v) => visitor.visit_i8(v),
|
||||
Token::I16(v) => visitor.visit_i16(v),
|
||||
Token::I32(v) => visitor.visit_i32(v),
|
||||
Token::I64(v) => visitor.visit_i64(v),
|
||||
Token::U8(v) => visitor.visit_u8(v),
|
||||
Token::U16(v) => visitor.visit_u16(v),
|
||||
Token::U32(v) => visitor.visit_u32(v),
|
||||
Token::U64(v) => visitor.visit_u64(v),
|
||||
Token::F32(v) => visitor.visit_f32(v),
|
||||
Token::F64(v) => visitor.visit_f64(v),
|
||||
Token::Char(v) => visitor.visit_char(v),
|
||||
Token::Str(v) => visitor.visit_str(v),
|
||||
Token::BorrowedStr(v) => visitor.visit_borrowed_str(v),
|
||||
Token::String(v) => visitor.visit_string(v.to_owned()),
|
||||
Token::Bytes(v) => visitor.visit_bytes(v),
|
||||
Token::BorrowedBytes(v) => visitor.visit_borrowed_bytes(v),
|
||||
Token::ByteBuf(v) => visitor.visit_byte_buf(v.to_vec()),
|
||||
Token::None => visitor.visit_none(),
|
||||
Token::Some => visitor.visit_some(self),
|
||||
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)) => {
|
||||
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
|
||||
Token::UnitVariant(_, variant) => visitor.visit_str(variant),
|
||||
Token::NewtypeVariant(_, variant) => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),)
|
||||
}
|
||||
Some(Token::TupleStart(len)) => {
|
||||
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
|
||||
Token::TupleVariant(_, variant, _) => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),)
|
||||
}
|
||||
Some(Token::TupleStructStart(_, len)) => {
|
||||
self.visit_seq(Some(len),
|
||||
Token::TupleStructSep,
|
||||
Token::TupleStructEnd,
|
||||
visitor)
|
||||
Token::StructVariant(_, variant, _) => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),)
|
||||
}
|
||||
Some(Token::MapStart(len)) => {
|
||||
self.visit_map(len, Token::MapSep, Token::MapEnd, visitor)
|
||||
Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd |
|
||||
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
|
||||
/// `None`, or a regular value as `Some(value)`.
|
||||
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::Option(false)) => {
|
||||
self.tokens.next();
|
||||
Some(&Token::None) => {
|
||||
self.next_token();
|
||||
visitor.visit_none()
|
||||
}
|
||||
Some(&Token::Option(true)) => {
|
||||
self.tokens.next();
|
||||
Some(&Token::Some) => {
|
||||
self.next_token();
|
||||
visitor.visit_some(self)
|
||||
}
|
||||
Some(_) => visitor.visit_some(self),
|
||||
Some(_) => self.deserialize_any(visitor),
|
||||
None => Err(Error::EndOfTokens),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(self,
|
||||
name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V)
|
||||
-> Result<V::Value, Error>
|
||||
where V: Visitor
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
name: &str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.tokens.peek() {
|
||||
Some(&Token::EnumStart(n)) if name == n => {
|
||||
self.tokens.next();
|
||||
match self.tokens.first() {
|
||||
Some(&Token::Enum(n)) if name == n => {
|
||||
self.next_token();
|
||||
|
||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
||||
}
|
||||
Some(&Token::EnumUnit(n, _)) |
|
||||
Some(&Token::EnumNewType(n, _)) |
|
||||
Some(&Token::EnumSeqStart(n, _, _)) |
|
||||
Some(&Token::EnumMapStart(n, _, _)) if name == n => {
|
||||
Some(&Token::UnitVariant(n, _)) |
|
||||
Some(&Token::NewtypeVariant(n, _)) |
|
||||
Some(&Token::TupleVariant(n, _, _)) |
|
||||
Some(&Token::StructVariant(n, _, _)) if name == n => {
|
||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
||||
}
|
||||
Some(_) => {
|
||||
let token = self.tokens.next().unwrap();
|
||||
let token = self.next_token().unwrap();
|
||||
Err(Error::UnexpectedToken(token))
|
||||
}
|
||||
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>
|
||||
where V: Visitor
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.tokens.peek() {
|
||||
match self.tokens.first() {
|
||||
Some(&Token::UnitStruct(n)) => {
|
||||
self.tokens.next();
|
||||
self.next_token();
|
||||
if name == n {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
Err(Error::InvalidName(n))
|
||||
}
|
||||
}
|
||||
Some(_) => self.deserialize(visitor),
|
||||
Some(_) => self.deserialize_any(visitor),
|
||||
None => Err(Error::EndOfTokens),
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
Some(&Token::StructNewType(n)) => {
|
||||
self.tokens.next();
|
||||
match self.tokens.first() {
|
||||
Some(&Token::NewtypeStruct(n)) => {
|
||||
self.next_token();
|
||||
if name == n {
|
||||
visitor.visit_newtype_struct(self)
|
||||
} else {
|
||||
Err(Error::InvalidName(n))
|
||||
}
|
||||
}
|
||||
Some(_) => self.deserialize(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),
|
||||
Some(_) => self.deserialize_any(visitor),
|
||||
None => Err(Error::EndOfTokens),
|
||||
}
|
||||
}
|
||||
|
||||
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::UnitStruct(_)) => {
|
||||
self.tokens.next();
|
||||
self.next_token();
|
||||
visitor.visit_unit()
|
||||
}
|
||||
Some(&Token::SeqStart(_)) => {
|
||||
self.tokens.next();
|
||||
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
|
||||
Some(&Token::Seq(_)) => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::SeqEnd, visitor)
|
||||
}
|
||||
Some(&Token::SeqArrayStart(_)) => {
|
||||
self.tokens.next();
|
||||
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
|
||||
Some(&Token::Tuple(_)) => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::TupleEnd, visitor)
|
||||
}
|
||||
Some(&Token::TupleStart(_)) => {
|
||||
self.tokens.next();
|
||||
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
|
||||
Some(&Token::TupleStruct(_, _)) => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
||||
}
|
||||
Some(&Token::TupleStructStart(_, _)) => {
|
||||
self.tokens.next();
|
||||
self.visit_seq(Some(len),
|
||||
Token::TupleStructSep,
|
||||
Token::TupleStructEnd,
|
||||
visitor)
|
||||
}
|
||||
Some(_) => self.deserialize(visitor),
|
||||
Some(_) => self.deserialize_any(visitor),
|
||||
None => Err(Error::EndOfTokens),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_tuple_struct<V>(self,
|
||||
name: &str,
|
||||
len: usize,
|
||||
visitor: V)
|
||||
-> Result<V::Value, Error>
|
||||
where V: Visitor
|
||||
fn deserialize_tuple_struct<V>(
|
||||
self,
|
||||
name: &str,
|
||||
len: usize,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.tokens.peek() {
|
||||
match self.tokens.first() {
|
||||
Some(&Token::Unit) => {
|
||||
self.tokens.next();
|
||||
self.next_token();
|
||||
visitor.visit_unit()
|
||||
}
|
||||
Some(&Token::UnitStruct(n)) => {
|
||||
self.tokens.next();
|
||||
self.next_token();
|
||||
if name == n {
|
||||
visitor.visit_unit()
|
||||
} else {
|
||||
Err(Error::InvalidName(n))
|
||||
}
|
||||
}
|
||||
Some(&Token::SeqStart(_)) => {
|
||||
self.tokens.next();
|
||||
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
|
||||
Some(&Token::Seq(_)) => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::SeqEnd, visitor)
|
||||
}
|
||||
Some(&Token::SeqArrayStart(_)) => {
|
||||
self.tokens.next();
|
||||
self.visit_seq(Some(len), Token::SeqSep, Token::SeqEnd, visitor)
|
||||
Some(&Token::Tuple(_)) => {
|
||||
self.next_token();
|
||||
self.visit_seq(Some(len), Token::TupleEnd, visitor)
|
||||
}
|
||||
Some(&Token::TupleStart(_)) => {
|
||||
self.tokens.next();
|
||||
self.visit_seq(Some(len), Token::TupleSep, Token::TupleEnd, visitor)
|
||||
}
|
||||
Some(&Token::TupleStructStart(n, _)) => {
|
||||
self.tokens.next();
|
||||
Some(&Token::TupleStruct(n, _)) => {
|
||||
self.next_token();
|
||||
if name == n {
|
||||
self.visit_seq(Some(len),
|
||||
Token::TupleStructSep,
|
||||
Token::TupleStructEnd,
|
||||
visitor)
|
||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
||||
} else {
|
||||
Err(Error::InvalidName(n))
|
||||
}
|
||||
}
|
||||
Some(_) => self.deserialize(visitor),
|
||||
Some(_) => self.deserialize_any(visitor),
|
||||
None => Err(Error::EndOfTokens),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_struct<V>(self,
|
||||
name: &str,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V)
|
||||
-> Result<V::Value, Error>
|
||||
where V: Visitor
|
||||
fn deserialize_struct<V>(
|
||||
self,
|
||||
name: &str,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.tokens.peek() {
|
||||
Some(&Token::StructStart(n, _)) => {
|
||||
self.tokens.next();
|
||||
match self.tokens.first() {
|
||||
Some(&Token::Struct(n, _)) => {
|
||||
self.next_token();
|
||||
if name == n {
|
||||
self.visit_map(Some(fields.len()),
|
||||
Token::StructSep,
|
||||
Token::StructEnd,
|
||||
visitor)
|
||||
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
|
||||
} else {
|
||||
Err(Error::InvalidName(n))
|
||||
}
|
||||
}
|
||||
Some(&Token::MapStart(_)) => {
|
||||
self.tokens.next();
|
||||
self.visit_map(Some(fields.len()), Token::MapSep, Token::MapEnd, visitor)
|
||||
Some(&Token::Map(_)) => {
|
||||
self.next_token();
|
||||
self.visit_map(Some(fields.len()), Token::MapEnd, visitor)
|
||||
}
|
||||
Some(_) => self.deserialize(visitor),
|
||||
Some(_) => self.deserialize_any(visitor),
|
||||
None => Err(Error::EndOfTokens),
|
||||
}
|
||||
}
|
||||
@ -351,108 +361,84 @@ impl<'a, I> de::Deserializer for &'a mut Deserializer<I>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct DeserializerSeqVisitor<'a, I: 'a>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
de: &'a mut Deserializer<I>,
|
||||
struct DeserializerSeqVisitor<'a, 'de: 'a> {
|
||||
de: &'a mut Deserializer<'de>,
|
||||
len: Option<usize>,
|
||||
sep: Token<'static>,
|
||||
end: Token<'static>,
|
||||
end: Token,
|
||||
}
|
||||
|
||||
impl<'a, I> SeqVisitor for DeserializerSeqVisitor<'a, I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
impl<'de, 'a> SeqAccess<'de> for DeserializerSeqVisitor<'a, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
|
||||
where T: DeserializeSeed
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
if self.de.tokens.peek() == Some(&self.end) {
|
||||
if self.de.tokens.first() == Some(&self.end) {
|
||||
return Ok(None);
|
||||
}
|
||||
match self.de.tokens.next() {
|
||||
Some(ref token) if *token == self.sep => {
|
||||
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),
|
||||
}
|
||||
self.len = self.len.map(|len| len.saturating_sub(1));
|
||||
seed.deserialize(&mut *self.de).map(Some)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.len.unwrap_or(0);
|
||||
(len, self.len)
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
self.len
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct DeserializerMapVisitor<'a, I: 'a>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
de: &'a mut Deserializer<I>,
|
||||
struct DeserializerMapVisitor<'a, 'de: 'a> {
|
||||
de: &'a mut Deserializer<'de>,
|
||||
len: Option<usize>,
|
||||
sep: Token<'static>,
|
||||
end: Token<'static>,
|
||||
end: Token,
|
||||
}
|
||||
|
||||
impl<'a, I> MapVisitor for DeserializerMapVisitor<'a, I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
impl<'de, 'a> MapAccess<'de> for DeserializerMapVisitor<'a, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
||||
where K: DeserializeSeed
|
||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
||||
where
|
||||
K: DeserializeSeed<'de>,
|
||||
{
|
||||
if self.de.tokens.peek() == Some(&self.end) {
|
||||
if self.de.tokens.first() == Some(&self.end) {
|
||||
return Ok(None);
|
||||
}
|
||||
match self.de.tokens.next() {
|
||||
Some(ref token) if *token == self.sep => {
|
||||
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),
|
||||
}
|
||||
self.len = self.len.map(|len| len.saturating_sub(1));
|
||||
seed.deserialize(&mut *self.de).map(Some)
|
||||
}
|
||||
|
||||
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
||||
where V: DeserializeSeed
|
||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
seed.deserialize(&mut *self.de)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.len.unwrap_or(0);
|
||||
(len, self.len)
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
self.len
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct DeserializerEnumVisitor<'a, I: 'a>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
de: &'a mut Deserializer<I>,
|
||||
struct DeserializerEnumVisitor<'a, 'de: 'a> {
|
||||
de: &'a mut Deserializer<'de>,
|
||||
}
|
||||
|
||||
impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
type Error = Error;
|
||||
type Variant = Self;
|
||||
|
||||
fn visit_variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
|
||||
where V: DeserializeSeed
|
||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.de.tokens.peek() {
|
||||
Some(&Token::EnumUnit(_, v)) |
|
||||
Some(&Token::EnumNewType(_, v)) |
|
||||
Some(&Token::EnumSeqStart(_, v, _)) |
|
||||
Some(&Token::EnumMapStart(_, v, _)) => {
|
||||
match self.de.tokens.first() {
|
||||
Some(&Token::UnitVariant(_, v)) |
|
||||
Some(&Token::NewtypeVariant(_, v)) |
|
||||
Some(&Token::TupleVariant(_, v, _)) |
|
||||
Some(&Token::StructVariant(_, v, _)) => {
|
||||
let de = v.into_deserializer();
|
||||
let value = try!(seed.deserialize(de));
|
||||
Ok((value, self))
|
||||
@ -466,15 +452,13 @@ impl<'a, I> EnumVisitor for DeserializerEnumVisitor<'a, I>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_unit(self) -> Result<(), Error> {
|
||||
match self.de.tokens.peek() {
|
||||
Some(&Token::EnumUnit(_, _)) => {
|
||||
self.de.tokens.next();
|
||||
fn unit_variant(self) -> Result<(), Error> {
|
||||
match self.de.tokens.first() {
|
||||
Some(&Token::UnitVariant(_, _)) => {
|
||||
self.de.next_token();
|
||||
Ok(())
|
||||
}
|
||||
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>
|
||||
where T: DeserializeSeed
|
||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.de.tokens.peek() {
|
||||
Some(&Token::EnumNewType(_, _)) => {
|
||||
self.de.tokens.next();
|
||||
match self.de.tokens.first() {
|
||||
Some(&Token::NewtypeVariant(_, _)) => {
|
||||
self.de.next_token();
|
||||
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>
|
||||
where V: Visitor
|
||||
fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.de.tokens.peek() {
|
||||
Some(&Token::EnumSeqStart(_, _, enum_len)) => {
|
||||
let token = self.de.tokens.next().unwrap();
|
||||
match self.de.tokens.first() {
|
||||
Some(&Token::TupleVariant(_, _, enum_len)) => {
|
||||
let token = self.de.next_token().unwrap();
|
||||
|
||||
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 {
|
||||
Err(Error::UnexpectedToken(token))
|
||||
}
|
||||
}
|
||||
Some(&Token::SeqStart(Some(enum_len))) => {
|
||||
let token = self.de.tokens.next().unwrap();
|
||||
Some(&Token::Seq(Some(enum_len))) => {
|
||||
let token = self.de.next_token().unwrap();
|
||||
|
||||
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 {
|
||||
Err(Error::UnexpectedToken(token))
|
||||
}
|
||||
}
|
||||
Some(_) => de::Deserializer::deserialize(self.de, visitor),
|
||||
Some(_) => de::Deserializer::deserialize_any(self.de, visitor),
|
||||
None => Err(Error::EndOfTokens),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_struct<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
|
||||
where V: Visitor
|
||||
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.de.tokens.peek() {
|
||||
Some(&Token::EnumMapStart(_, _, enum_len)) => {
|
||||
let token = self.de.tokens.next().unwrap();
|
||||
match self.de.tokens.first() {
|
||||
Some(&Token::StructVariant(_, _, enum_len)) => {
|
||||
let token = self.de.next_token().unwrap();
|
||||
|
||||
if fields.len() == enum_len {
|
||||
self.de.visit_map(Some(fields.len()),
|
||||
Token::EnumMapSep,
|
||||
Token::EnumMapEnd,
|
||||
visitor)
|
||||
self.de
|
||||
.visit_map(Some(fields.len()), Token::StructVariantEnd, visitor)
|
||||
} else {
|
||||
Err(Error::UnexpectedToken(token))
|
||||
}
|
||||
}
|
||||
Some(&Token::MapStart(Some(enum_len))) => {
|
||||
let token = self.de.tokens.next().unwrap();
|
||||
Some(&Token::Map(Some(enum_len))) => {
|
||||
let token = self.de.next_token().unwrap();
|
||||
|
||||
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 {
|
||||
Err(Error::UnexpectedToken(token))
|
||||
}
|
||||
}
|
||||
Some(_) => de::Deserializer::deserialize(self.de, visitor),
|
||||
Some(_) => de::Deserializer::deserialize_any(self.de, visitor),
|
||||
None => Err(Error::EndOfTokens),
|
||||
}
|
||||
}
|
||||
@ -555,69 +542,98 @@ impl<'a, I> VariantVisitor for DeserializerEnumVisitor<'a, I>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct EnumMapVisitor<'a, I: 'a>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
de: &'a mut Deserializer<I>,
|
||||
variant: Option<&'a str>,
|
||||
struct EnumMapVisitor<'a, 'de: 'a> {
|
||||
de: &'a mut Deserializer<'de>,
|
||||
variant: Option<Token>,
|
||||
format: EnumFormat,
|
||||
}
|
||||
|
||||
impl<'a, I: 'a> EnumMapVisitor<'a, I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
fn new(de: &'a mut Deserializer<I>, variant: &'a str) -> Self {
|
||||
enum EnumFormat {
|
||||
Seq,
|
||||
Map,
|
||||
Any,
|
||||
}
|
||||
|
||||
impl<'a, 'de> EnumMapVisitor<'a, 'de> {
|
||||
fn new(de: &'a mut Deserializer<'de>, variant: Token, format: EnumFormat) -> Self {
|
||||
EnumMapVisitor {
|
||||
de: de,
|
||||
variant: Some(variant),
|
||||
format: format,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I: 'a> MapVisitor for EnumMapVisitor<'a, I>
|
||||
where I: Iterator<Item = Token<'static>>
|
||||
{
|
||||
impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
||||
where K: DeserializeSeed
|
||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
|
||||
where
|
||||
K: DeserializeSeed<'de>,
|
||||
{
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
||||
where V: DeserializeSeed
|
||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.de.tokens.peek() {
|
||||
Some(&Token::EnumSeqSep) => {
|
||||
match self.format {
|
||||
EnumFormat::Seq => {
|
||||
let value = {
|
||||
let visitor = DeserializerSeqVisitor {
|
||||
de: self.de,
|
||||
len: None,
|
||||
sep: Token::EnumSeqSep,
|
||||
end: Token::EnumSeqEnd,
|
||||
end: Token::TupleVariantEnd,
|
||||
};
|
||||
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)
|
||||
}
|
||||
Some(&Token::EnumMapSep) => {
|
||||
EnumFormat::Map => {
|
||||
let value = {
|
||||
let visitor = DeserializerMapVisitor {
|
||||
de: self.de,
|
||||
len: None,
|
||||
sep: Token::EnumMapSep,
|
||||
end: Token::EnumMapEnd,
|
||||
end: Token::StructVariantEnd,
|
||||
};
|
||||
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)
|
||||
}
|
||||
_ => 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
|
||||
}
|
||||
}
|
||||
|
@ -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::fmt::{self, Display};
|
||||
|
||||
@ -15,7 +23,7 @@ pub enum Error {
|
||||
InvalidName(&'static str),
|
||||
|
||||
/// `Serialize` generated a token that didn't match the test.
|
||||
UnexpectedToken(Token<'static>),
|
||||
UnexpectedToken(Token),
|
||||
|
||||
/// The expected token list was too short.
|
||||
EndOfTokens,
|
||||
|
@ -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]
|
||||
extern crate serde;
|
||||
|
||||
|
@ -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};
|
||||
|
||||
@ -6,33 +12,54 @@ use error::Error;
|
||||
use token::Token;
|
||||
|
||||
/// A `Serializer` that ensures that a value serializes to a given list of tokens.
|
||||
pub struct Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
tokens: I,
|
||||
phantom: PhantomData<&'a Token<'a>>,
|
||||
#[derive(Debug)]
|
||||
pub struct Serializer<'a> {
|
||||
tokens: &'a [Token],
|
||||
}
|
||||
|
||||
impl<'a, I> Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
impl<'a> Serializer<'a> {
|
||||
/// Creates the serializer.
|
||||
pub fn new(tokens: I) -> Serializer<'a, I> {
|
||||
Serializer {
|
||||
tokens: tokens,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
pub fn new(tokens: &'a [Token]) -> Self {
|
||||
Serializer { tokens: tokens }
|
||||
}
|
||||
|
||||
/// Pulls the next token off of the serializer, ignoring it.
|
||||
pub fn next_token(&mut self) -> Option<&'a Token<'a>> {
|
||||
self.tokens.next()
|
||||
pub fn next_token(&mut self) -> Option<Token> {
|
||||
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>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
macro_rules! assert_next_token {
|
||||
($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 Error = Error;
|
||||
|
||||
@ -45,322 +72,321 @@ impl<'s, 'a, I> ser::Serializer for &'s mut Serializer<'a, I>
|
||||
type SerializeStructVariant = Self;
|
||||
|
||||
fn serialize_bool(self, v: bool) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
|
||||
assert_next_token!(self, Bool(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_i8(self, v: i8) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
|
||||
assert_next_token!(self, I8(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_i16(self, v: i16) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
|
||||
assert_next_token!(self, I16(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_i32(self, v: i32) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
|
||||
assert_next_token!(self, I32(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_i64(self, v: i64) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
|
||||
assert_next_token!(self, I64(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_u8(self, v: u8) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
|
||||
assert_next_token!(self, U8(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_u16(self, v: u16) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
|
||||
assert_next_token!(self, U16(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_u32(self, v: u32) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
|
||||
assert_next_token!(self, U32(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_u64(self, v: u64) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
|
||||
assert_next_token!(self, U64(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_f32(self, v: f32) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
|
||||
assert_next_token!(self, F32(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_f64(self, v: f64) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
|
||||
assert_next_token!(self, F64(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_char(self, v: char) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
|
||||
assert_next_token!(self, Char(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_str(self, v: &str) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
|
||||
assert_next_token!(self, Str(v));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::Unit));
|
||||
assert_next_token!(self, Unit);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, name: &str) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
|
||||
fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
|
||||
assert_next_token!(self, UnitStruct(name));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(self,
|
||||
name: &str,
|
||||
_variant_index: usize,
|
||||
variant: &str)
|
||||
-> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
|
||||
fn serialize_unit_variant(
|
||||
self,
|
||||
name: &'static str,
|
||||
_variant_index: u32,
|
||||
variant: &'static str,
|
||||
) -> 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(())
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(self,
|
||||
name: &str,
|
||||
_variant_index: usize,
|
||||
variant: &str,
|
||||
value: &T)
|
||||
-> Result<(), Error>
|
||||
where T: Serialize
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
self,
|
||||
name: &'static str,
|
||||
_variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T,
|
||||
) -> 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)
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
|
||||
assert_next_token!(self, None);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn serialize_seq_fixed_size(self, len: usize) -> Result<Self, Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
|
||||
assert_next_token!(self, Seq(len));
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
|
||||
assert_eq!(self.tokens.next(),
|
||||
Some(&Token::TupleStructStart(name, len)));
|
||||
assert_next_token!(self, TupleStruct(name, len));
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(self,
|
||||
name: &str,
|
||||
_variant_index: usize,
|
||||
variant: &str,
|
||||
len: usize)
|
||||
-> Result<Self, Error> {
|
||||
assert_eq!(self.tokens.next(),
|
||||
Some(&Token::EnumSeqStart(name, variant, len)));
|
||||
fn serialize_tuple_variant(
|
||||
self,
|
||||
name: &'static str,
|
||||
_variant_index: u32,
|
||||
variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self, Error> {
|
||||
assert_next_token!(self, TupleVariant(name, variant, len));
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn serialize_struct(self, name: &str, len: usize) -> Result<Self, Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
|
||||
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
|
||||
assert_next_token!(self, Struct(name, len));
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(self,
|
||||
name: &str,
|
||||
_variant_index: usize,
|
||||
variant: &str,
|
||||
len: usize)
|
||||
-> Result<Self, Error> {
|
||||
assert_eq!(self.tokens.next(),
|
||||
Some(&Token::EnumMapStart(name, variant, len)));
|
||||
fn serialize_struct_variant(
|
||||
self,
|
||||
name: &'static str,
|
||||
_variant_index: u32,
|
||||
variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self, Error> {
|
||||
assert_next_token!(self, StructVariant(name, variant, len));
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'a, I> ser::SerializeSeq for &'s mut Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = 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)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
|
||||
assert_next_token!(self, SeqEnd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'a, I> ser::SerializeTuple for &'s mut Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = 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)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
|
||||
assert_next_token!(self, TupleEnd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'a, I> ser::SerializeTupleStruct for &'s mut Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = 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)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
|
||||
assert_next_token!(self, TupleStructEnd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'a, I> ser::SerializeTupleVariant for &'s mut Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
impl<'s, 'a> ser::SerializeTupleVariant for &'s mut Serializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = 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)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
|
||||
assert_next_token!(self, TupleVariantEnd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'a, I> ser::SerializeMap for &'s mut Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = 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)
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where T: Serialize
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
value.serialize(&mut **self)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
|
||||
assert_next_token!(self, MapEnd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'a, I> ser::SerializeStruct for &'s mut Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self,
|
||||
key: &'static str,
|
||||
value: &T)
|
||||
-> Result<(), Self::Error>
|
||||
where T: Serialize
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
|
||||
try!(key.serialize(&mut **self));
|
||||
value.serialize(&mut **self)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
|
||||
assert_next_token!(self, StructEnd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s, 'a, I> ser::SerializeStructVariant for &'s mut Serializer<'a, I>
|
||||
where I: Iterator<Item = &'a Token<'a>>
|
||||
{
|
||||
impl<'s, 'a> ser::SerializeStructVariant for &'s mut Serializer<'a> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self,
|
||||
key: &'static str,
|
||||
value: &T)
|
||||
-> Result<(), Self::Error>
|
||||
where T: Serialize
|
||||
fn serialize_field<T: ?Sized>(
|
||||
&mut self,
|
||||
key: &'static str,
|
||||
value: &T,
|
||||
) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
|
||||
try!(key.serialize(&mut **self));
|
||||
value.serialize(&mut **self)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
|
||||
assert_next_token!(self, StructVariantEnd);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,13 @@
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum Token<'a> {
|
||||
// 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.
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum Token {
|
||||
/// A serialized `bool`.
|
||||
Bool(bool),
|
||||
|
||||
@ -37,90 +45,75 @@ pub enum Token<'a> {
|
||||
Char(char),
|
||||
|
||||
/// A serialized `str`.
|
||||
Str(&'a str),
|
||||
Str(&'static str),
|
||||
|
||||
/// A borrowed `str`.
|
||||
BorrowedStr(&'static str),
|
||||
|
||||
/// A serialized `String`.
|
||||
String(String),
|
||||
String(&'static str),
|
||||
|
||||
/// A serialized `[u8]`
|
||||
Bytes(&'a [u8]),
|
||||
Bytes(&'static [u8]),
|
||||
|
||||
/// A borrowed `[u8]`.
|
||||
BorrowedBytes(&'static [u8]),
|
||||
|
||||
/// 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 value contained in the option.
|
||||
Option(bool),
|
||||
/// The tokens of the value follow after this header.
|
||||
Some,
|
||||
|
||||
/// A serialized `Option<T>` containing none.
|
||||
None,
|
||||
|
||||
/// A serialized `()`.
|
||||
Unit,
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// Newtype structs are serialized with this header, followed by the value contained in the
|
||||
/// newtype struct.
|
||||
StructNewType(&'a str),
|
||||
NewtypeStruct(&'static str),
|
||||
|
||||
/// The header to an enum of the given name.
|
||||
///
|
||||
/// 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),
|
||||
Enum(&'static str),
|
||||
|
||||
/// 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
|
||||
/// 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 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`.
|
||||
EnumNewType(&'a str, &'a str),
|
||||
NewtypeVariant(&'static str, &'static str),
|
||||
|
||||
/// The header to a sequence of the given length.
|
||||
///
|
||||
/// These are serialized via `serialize_seq`, which takes an optional length. After this
|
||||
/// header is a list of elements, followed by `SeqEnd`.
|
||||
SeqStart(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,
|
||||
Seq(Option<usize>),
|
||||
|
||||
/// An indicator of the end of a sequence.
|
||||
SeqEnd,
|
||||
|
||||
/// The header to a tuple of the given length, similar to `SeqArrayStart`.
|
||||
TupleStart(usize),
|
||||
|
||||
/// A separator, similar to `SeqSep`.
|
||||
TupleSep,
|
||||
/// The header to a tuple of the given length, similar to `SeqFixedSize`.
|
||||
Tuple(usize),
|
||||
|
||||
/// An indicator of the end of a tuple, similar to `SeqEnd`.
|
||||
TupleEnd,
|
||||
|
||||
/// The header to a tuple struct of the given name and length.
|
||||
TupleStructStart(&'a str, usize),
|
||||
|
||||
/// A separator, similar to `TupleSep`.
|
||||
TupleStructSep,
|
||||
TupleStruct(&'static str, usize),
|
||||
|
||||
/// An indicator of the end of a tuple struct, similar to `TupleEnd`.
|
||||
TupleStructEnd,
|
||||
@ -129,42 +122,27 @@ pub enum Token<'a> {
|
||||
///
|
||||
/// These are serialized via `serialize_map`, which takes an optional length. After this header
|
||||
/// is a list of key-value pairs, followed by `MapEnd`.
|
||||
MapStart(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,
|
||||
Map(Option<usize>),
|
||||
|
||||
/// An indicator of the end of a map.
|
||||
MapEnd,
|
||||
|
||||
/// The header of a struct of the given name and length, similar to `MapStart`.
|
||||
StructStart(&'a str, usize),
|
||||
|
||||
/// A separator, similar to `MapSep`.
|
||||
StructSep,
|
||||
/// The header of a struct of the given name and length, similar to `Map`.
|
||||
Struct(&'static str, usize),
|
||||
|
||||
/// An indicator of the end of a struct, similar to `MapEnd`.
|
||||
StructEnd,
|
||||
|
||||
/// 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),
|
||||
|
||||
/// A separator, similar to `TupleSep`.
|
||||
EnumSeqSep,
|
||||
TupleVariant(&'static str, &'static str, usize),
|
||||
|
||||
/// 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,
|
||||
/// similar to `StructStart`.
|
||||
EnumMapStart(&'a str, &'a str, usize),
|
||||
|
||||
/// A separator, similar to `StructSep`.
|
||||
EnumMapSep,
|
||||
/// similar to `Struct`.
|
||||
StructVariant(&'static str, &'static str, usize),
|
||||
|
||||
/// An indicator of the end of a struct, similar to `StructEnd`.
|
||||
EnumMapEnd,
|
||||
StructVariantEnd,
|
||||
}
|
||||
|
18
test_suite/tests/compile-fail/borrow/bad_lifetimes.rs
Normal file
18
test_suite/tests/compile-fail/borrow/bad_lifetimes.rs
Normal file
@ -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() {}
|
18
test_suite/tests/compile-fail/borrow/duplicate_lifetime.rs
Normal file
18
test_suite/tests/compile-fail/borrow/duplicate_lifetime.rs
Normal file
@ -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() {}
|
18
test_suite/tests/compile-fail/borrow/empty_lifetimes.rs
Normal file
18
test_suite/tests/compile-fail/borrow/empty_lifetimes.rs
Normal file
@ -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() {}
|
18
test_suite/tests/compile-fail/borrow/no_lifetimes.rs
Normal file
18
test_suite/tests/compile-fail/borrow/no_lifetimes.rs
Normal file
@ -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() {}
|
18
test_suite/tests/compile-fail/borrow/wrong_lifetime.rs
Normal file
18
test_suite/tests/compile-fail/borrow/wrong_lifetime.rs
Normal file
@ -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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
extern crate serde_derive;
|
||||
|
||||
|
19
test_suite/tests/compile-fail/identifier/both.rs
Normal file
19
test_suite/tests/compile-fail/identifier/both.rs
Normal file
@ -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() {}
|
16
test_suite/tests/compile-fail/identifier/field_struct.rs
Normal file
16
test_suite/tests/compile-fail/identifier/field_struct.rs
Normal file
@ -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() {}
|
19
test_suite/tests/compile-fail/identifier/field_tuple.rs
Normal file
19
test_suite/tests/compile-fail/identifier/field_tuple.rs
Normal file
@ -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() {}
|
20
test_suite/tests/compile-fail/identifier/newtype_not_last.rs
Normal file
20
test_suite/tests/compile-fail/identifier/newtype_not_last.rs
Normal 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.
|
||||
|
||||
#[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() {}
|
19
test_suite/tests/compile-fail/identifier/not_identifier.rs
Normal file
19
test_suite/tests/compile-fail/identifier/not_identifier.rs
Normal file
@ -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() {}
|
20
test_suite/tests/compile-fail/identifier/not_unit.rs
Normal file
20
test_suite/tests/compile-fail/identifier/not_unit.rs
Normal 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.
|
||||
|
||||
#[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() {}
|
21
test_suite/tests/compile-fail/identifier/other_not_last.rs
Normal file
21
test_suite/tests/compile-fail/identifier/other_not_last.rs
Normal file
@ -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() {}
|
19
test_suite/tests/compile-fail/identifier/serialize.rs
Normal file
19
test_suite/tests/compile-fail/identifier/serialize.rs
Normal file
@ -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() {}
|
16
test_suite/tests/compile-fail/identifier/variant_struct.rs
Normal file
16
test_suite/tests/compile-fail/identifier/variant_struct.rs
Normal file
@ -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() {}
|
19
test_suite/tests/compile-fail/identifier/variant_tuple.rs
Normal file
19
test_suite/tests/compile-fail/identifier/variant_tuple.rs
Normal file
@ -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() {}
|
25
test_suite/tests/compile-fail/remote/bad_getter.rs
Normal file
25
test_suite/tests/compile-fail/remote/bad_getter.rs
Normal file
@ -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() {}
|
24
test_suite/tests/compile-fail/remote/bad_remote.rs
Normal file
24
test_suite/tests/compile-fail/remote/bad_remote.rs
Normal file
@ -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() {}
|
27
test_suite/tests/compile-fail/remote/enum_getter.rs
Normal file
27
test_suite/tests/compile-fail/remote/enum_getter.rs
Normal file
@ -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() {}
|
25
test_suite/tests/compile-fail/remote/missing_field.rs
Normal file
25
test_suite/tests/compile-fail/remote/missing_field.rs
Normal file
@ -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() {}
|
24
test_suite/tests/compile-fail/remote/nonremote_getter.rs
Normal file
24
test_suite/tests/compile-fail/remote/nonremote_getter.rs
Normal file
@ -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() {}
|
24
test_suite/tests/compile-fail/remote/unknown_field.rs
Normal file
24
test_suite/tests/compile-fail/remote/unknown_field.rs
Normal file
@ -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() {}
|
20
test_suite/tests/compile-fail/remote/wrong_de.rs
Normal file
20
test_suite/tests/compile-fail/remote/wrong_de.rs
Normal 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.
|
||||
|
||||
#[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() {}
|
31
test_suite/tests/compile-fail/remote/wrong_getter.rs
Normal file
31
test_suite/tests/compile-fail/remote/wrong_getter.rs
Normal file
@ -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() {}
|
24
test_suite/tests/compile-fail/remote/wrong_ser.rs
Normal file
24
test_suite/tests/compile-fail/remote/wrong_ser.rs
Normal file
@ -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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
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.
|
||||
|
||||
#![cfg(feature = "unstable")]
|
||||
|
||||
extern crate compiletest_rs as compiletest;
|
||||
|
@ -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 {
|
||||
() => {
|
||||
BTreeSet::new()
|
||||
|
@ -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)]
|
||||
|
||||
#[macro_use]
|
||||
|
File diff suppressed because it is too large
Load Diff
175
test_suite/tests/test_borrow.rs
Normal file
175
test_suite/tests/test_borrow.rs
Normal 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
Loading…
x
Reference in New Issue
Block a user