mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-27 11:07:56 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| af795e2e54 | |||
| 6aa07fe0d6 | |||
| c455720f81 | |||
| b07a208716 | |||
| df93fab5fa | |||
| 1a972d2105 | |||
| 6d1807bb4a | |||
| b37cf858ce | |||
| 5f8fa33756 | |||
| f3f006f411 | |||
| 607966dcf7 | |||
| 6a8c39b2aa | |||
| 382f3c2771 | |||
| 85ca12a8c3 | |||
| 541f9180cf | |||
| 3c4961c48e | |||
| 184264ee92 | |||
| 6050229e7e | |||
| e1db820c9f | |||
| 0081cc961d | |||
| 9bc05803fe |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.38" # remember to update html_root_url
|
version = "1.0.42" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ macro_rules! declare_error_trait {
|
|||||||
/// For example if we try to deserialize a String out of a JSON file
|
/// For example if we try to deserialize a String out of a JSON file
|
||||||
/// containing an integer, the unexpected type is the integer and the
|
/// containing an integer, the unexpected type is the integer and the
|
||||||
/// expected type is the string.
|
/// expected type is the string.
|
||||||
|
#[cold]
|
||||||
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
|
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
|
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
|
||||||
}
|
}
|
||||||
@@ -213,6 +214,7 @@ macro_rules! declare_error_trait {
|
|||||||
/// For example if we try to deserialize a String out of some binary data
|
/// For example if we try to deserialize a String out of some binary data
|
||||||
/// that is not valid UTF-8, the unexpected value is the bytes and the
|
/// that is not valid UTF-8, the unexpected value is the bytes and the
|
||||||
/// expected value is a string.
|
/// expected value is a string.
|
||||||
|
#[cold]
|
||||||
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
|
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
|
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
|
||||||
}
|
}
|
||||||
@@ -226,12 +228,14 @@ macro_rules! declare_error_trait {
|
|||||||
/// The `exp` argument provides information about what data was being
|
/// The `exp` argument provides information about what data was being
|
||||||
/// expected. For example `exp` might say that a tuple of size 6 was
|
/// expected. For example `exp` might say that a tuple of size 6 was
|
||||||
/// expected.
|
/// expected.
|
||||||
|
#[cold]
|
||||||
fn invalid_length(len: usize, exp: &Expected) -> Self {
|
fn invalid_length(len: usize, exp: &Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
|
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raised when a `Deserialize` enum type received a variant with an
|
/// Raised when a `Deserialize` enum type received a variant with an
|
||||||
/// unrecognized name.
|
/// unrecognized name.
|
||||||
|
#[cold]
|
||||||
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
|
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
|
||||||
if expected.is_empty() {
|
if expected.is_empty() {
|
||||||
Error::custom(format_args!("unknown variant `{}`, there are no variants",
|
Error::custom(format_args!("unknown variant `{}`, there are no variants",
|
||||||
@@ -245,6 +249,7 @@ macro_rules! declare_error_trait {
|
|||||||
|
|
||||||
/// Raised when a `Deserialize` struct type received a field with an
|
/// Raised when a `Deserialize` struct type received a field with an
|
||||||
/// unrecognized name.
|
/// unrecognized name.
|
||||||
|
#[cold]
|
||||||
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
|
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
|
||||||
if expected.is_empty() {
|
if expected.is_empty() {
|
||||||
Error::custom(format_args!("unknown field `{}`, there are no fields",
|
Error::custom(format_args!("unknown field `{}`, there are no fields",
|
||||||
@@ -259,12 +264,14 @@ macro_rules! declare_error_trait {
|
|||||||
/// Raised when a `Deserialize` struct type expected to receive a required
|
/// Raised when a `Deserialize` struct type expected to receive a required
|
||||||
/// field with a particular name but that field was not present in the
|
/// field with a particular name but that field was not present in the
|
||||||
/// input.
|
/// input.
|
||||||
|
#[cold]
|
||||||
fn missing_field(field: &'static str) -> Self {
|
fn missing_field(field: &'static str) -> Self {
|
||||||
Error::custom(format_args!("missing field `{}`", field))
|
Error::custom(format_args!("missing field `{}`", field))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raised when a `Deserialize` struct type received more than one of the
|
/// Raised when a `Deserialize` struct type received more than one of the
|
||||||
/// same field.
|
/// same field.
|
||||||
|
#[cold]
|
||||||
fn duplicate_field(field: &'static str) -> Self {
|
fn duplicate_field(field: &'static str) -> Self {
|
||||||
Error::custom(format_args!("duplicate field `{}`", field))
|
Error::custom(format_args!("duplicate field `{}`", field))
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-10
@@ -58,6 +58,7 @@ type ErrorImpl = ();
|
|||||||
|
|
||||||
impl de::Error for Error {
|
impl de::Error for Error {
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cold]
|
||||||
fn custom<T>(msg: T) -> Self
|
fn custom<T>(msg: T) -> Self
|
||||||
where
|
where
|
||||||
T: Display,
|
T: Display,
|
||||||
@@ -68,6 +69,7 @@ impl de::Error for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cold]
|
||||||
fn custom<T>(msg: T) -> Self
|
fn custom<T>(msg: T) -> Self
|
||||||
where
|
where
|
||||||
T: Display,
|
T: Display,
|
||||||
@@ -78,6 +80,7 @@ impl de::Error for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ser::Error for Error {
|
impl ser::Error for Error {
|
||||||
|
#[cold]
|
||||||
fn custom<T>(msg: T) -> Self
|
fn custom<T>(msg: T) -> Self
|
||||||
where
|
where
|
||||||
T: Display,
|
T: Display,
|
||||||
@@ -652,11 +655,8 @@ where
|
|||||||
{
|
{
|
||||||
/// Check for remaining elements after passing a `SeqDeserializer` to
|
/// Check for remaining elements after passing a `SeqDeserializer` to
|
||||||
/// `Visitor::visit_seq`.
|
/// `Visitor::visit_seq`.
|
||||||
pub fn end(mut self) -> Result<(), E> {
|
pub fn end(self) -> Result<(), E> {
|
||||||
let mut remaining = 0;
|
let remaining = self.iter.count();
|
||||||
while self.iter.next().is_some() {
|
|
||||||
remaining += 1;
|
|
||||||
}
|
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@@ -849,11 +849,8 @@ where
|
|||||||
{
|
{
|
||||||
/// Check for remaining elements after passing a `MapDeserializer` to
|
/// Check for remaining elements after passing a `MapDeserializer` to
|
||||||
/// `Visitor::visit_map`.
|
/// `Visitor::visit_map`.
|
||||||
pub fn end(mut self) -> Result<(), E> {
|
pub fn end(self) -> Result<(), E> {
|
||||||
let mut remaining = 0;
|
let remaining = self.iter.count();
|
||||||
while self.iter.next().is_some() {
|
|
||||||
remaining += 1;
|
|
||||||
}
|
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -79,7 +79,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Serde types in rustdoc of other crates get linked to here.
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.38")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.42")]
|
||||||
// Support using Serde without the standard library!
|
// Support using Serde without the standard library!
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
// Unstable functionality only if the user asks for it. For tracking and
|
// Unstable functionality only if the user asks for it. For tracking and
|
||||||
|
|||||||
+608
-65
@@ -229,8 +229,8 @@ mod content {
|
|||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use super::size_hint;
|
use super::size_hint;
|
||||||
use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, MapAccess, SeqAccess,
|
use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, MapAccess,
|
||||||
Unexpected, Visitor};
|
SeqAccess, Unexpected, Visitor};
|
||||||
|
|
||||||
/// Used from generated code to buffer the contents of the Deserializer when
|
/// Used from generated code to buffer the contents of the Deserializer when
|
||||||
/// deserializing untagged enums and internally tagged enums.
|
/// deserializing untagged enums and internally tagged enums.
|
||||||
@@ -277,6 +277,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cold]
|
||||||
fn unexpected(&self) -> Unexpected {
|
fn unexpected(&self) -> Unexpected {
|
||||||
match *self {
|
match *self {
|
||||||
Content::Bool(b) => Unexpected::Bool(b),
|
Content::Bool(b) => Unexpected::Bool(b),
|
||||||
@@ -1013,6 +1014,62 @@ mod content {
|
|||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de, E> ContentDeserializer<'de, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
#[cold]
|
||||||
|
fn invalid_type(self, exp: &Expected) -> E {
|
||||||
|
de::Error::invalid_type(self.content.unexpected(), exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_integer<V>(self, visitor: V) -> Result<V::Value, E>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::U8(v) => visitor.visit_u8(v),
|
||||||
|
Content::U16(v) => visitor.visit_u16(v),
|
||||||
|
Content::U32(v) => visitor.visit_u32(v),
|
||||||
|
Content::U64(v) => visitor.visit_u64(v),
|
||||||
|
Content::I8(v) => visitor.visit_i8(v),
|
||||||
|
Content::I16(v) => visitor.visit_i16(v),
|
||||||
|
Content::I32(v) => visitor.visit_i32(v),
|
||||||
|
Content::I64(v) => visitor.visit_i64(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_content_seq<'de, V, E>(content: Vec<Content<'de>>, visitor: V) -> Result<V::Value, E>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
let seq = content.into_iter().map(ContentDeserializer::new);
|
||||||
|
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
||||||
|
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||||
|
try!(seq_visitor.end());
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_content_map<'de, V, E>(
|
||||||
|
content: Vec<(Content<'de>, Content<'de>)>,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, E>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
let map = content
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
||||||
|
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||||
|
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||||
|
try!(map_visitor.end());
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
/// Used when deserializing an internally tagged enum because the content will
|
/// Used when deserializing an internally tagged enum because the content will
|
||||||
/// be used exactly once.
|
/// be used exactly once.
|
||||||
impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E>
|
impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E>
|
||||||
@@ -1046,21 +1103,152 @@ mod content {
|
|||||||
Content::None => visitor.visit_none(),
|
Content::None => visitor.visit_none(),
|
||||||
Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)),
|
Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)),
|
||||||
Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)),
|
Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)),
|
||||||
Content::Seq(v) => {
|
Content::Seq(v) => visit_content_seq(v, visitor),
|
||||||
let seq = v.into_iter().map(ContentDeserializer::new);
|
Content::Map(v) => visit_content_map(v, visitor),
|
||||||
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
}
|
||||||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
}
|
||||||
try!(seq_visitor.end());
|
|
||||||
Ok(value)
|
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
}
|
where
|
||||||
Content::Map(v) => {
|
V: Visitor<'de>,
|
||||||
let map = v.into_iter()
|
{
|
||||||
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
match self.content {
|
||||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
Content::Bool(v) => visitor.visit_bool(v),
|
||||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
try!(map_visitor.end());
|
}
|
||||||
Ok(value)
|
}
|
||||||
}
|
|
||||||
|
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::F32(v) => visitor.visit_f32(v),
|
||||||
|
Content::F64(v) => visitor.visit_f64(v),
|
||||||
|
Content::U64(v) => visitor.visit_u64(v),
|
||||||
|
Content::I64(v) => visitor.visit_i64(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::F64(v) => visitor.visit_f64(v),
|
||||||
|
Content::U64(v) => visitor.visit_u64(v),
|
||||||
|
Content::I64(v) => visitor.visit_i64(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::Char(v) => visitor.visit_char(v),
|
||||||
|
Content::String(v) => visitor.visit_string(v),
|
||||||
|
Content::Str(v) => visitor.visit_borrowed_str(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_string(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::String(v) => visitor.visit_string(v),
|
||||||
|
Content::Str(v) => visitor.visit_borrowed_str(v),
|
||||||
|
Content::ByteBuf(v) => visitor.visit_byte_buf(v),
|
||||||
|
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_byte_buf(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::String(v) => visitor.visit_string(v),
|
||||||
|
Content::Str(v) => visitor.visit_borrowed_str(v),
|
||||||
|
Content::ByteBuf(v) => visitor.visit_byte_buf(v),
|
||||||
|
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
|
||||||
|
Content::Seq(v) => visit_content_seq(v, visitor),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1076,6 +1264,44 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::Unit => visitor.visit_unit(),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
// As a special case, allow deserializing untagged newtype
|
||||||
|
// variant containing unit struct.
|
||||||
|
//
|
||||||
|
// #[derive(Deserialize)]
|
||||||
|
// struct Info;
|
||||||
|
//
|
||||||
|
// #[derive(Deserialize)]
|
||||||
|
// #[serde(tag = "topic")]
|
||||||
|
// enum Message {
|
||||||
|
// Info(Info),
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// We want {"topic":"Info"} to deserialize even though
|
||||||
|
// ordinarily unit structs do not deserialize from empty map.
|
||||||
|
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
|
||||||
|
_ => self.deserialize_any(visitor),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_newtype_struct<V>(
|
fn deserialize_newtype_struct<V>(
|
||||||
self,
|
self,
|
||||||
_name: &str,
|
_name: &str,
|
||||||
@@ -1087,6 +1313,61 @@ mod content {
|
|||||||
visitor.visit_newtype_struct(self)
|
visitor.visit_newtype_struct(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::Seq(v) => visit_content_seq(v, visitor),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_seq(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_seq(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::Map(v) => visit_content_map(v, visitor),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self.content {
|
||||||
|
Content::Seq(v) => visit_content_seq(v, visitor),
|
||||||
|
Content::Map(v) => visit_content_map(v, visitor),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_enum<V>(
|
fn deserialize_enum<V>(
|
||||||
self,
|
self,
|
||||||
_name: &str,
|
_name: &str,
|
||||||
@@ -1129,38 +1410,23 @@ mod content {
|
|||||||
visitor.visit_enum(EnumDeserializer::new(variant, value))
|
visitor.visit_enum(EnumDeserializer::new(variant, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_unit_struct<V>(
|
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
self,
|
|
||||||
_name: &'static str,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Self::Error>
|
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.content {
|
match self.content {
|
||||||
// As a special case, allow deserializing untagged newtype
|
Content::String(v) => visitor.visit_string(v),
|
||||||
// variant containing unit struct.
|
Content::Str(v) => visitor.visit_borrowed_str(v),
|
||||||
//
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
// #[derive(Deserialize)]
|
|
||||||
// struct Info;
|
|
||||||
//
|
|
||||||
// #[derive(Deserialize)]
|
|
||||||
// #[serde(tag = "topic")]
|
|
||||||
// enum Message {
|
|
||||||
// Info(Info),
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// We want {"topic":"Info"} to deserialize even though
|
|
||||||
// ordinarily unit structs do not deserialize from empty map.
|
|
||||||
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
|
|
||||||
_ => self.deserialize_any(visitor),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
where
|
||||||
byte_buf unit seq tuple tuple_struct map struct identifier
|
V: Visitor<'de>,
|
||||||
ignored_any
|
{
|
||||||
|
drop(self);
|
||||||
|
visitor.visit_unit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1452,6 +1718,68 @@ mod content {
|
|||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
#[cold]
|
||||||
|
fn invalid_type(self, exp: &Expected) -> E {
|
||||||
|
de::Error::invalid_type(self.content.unexpected(), exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_integer<V>(self, visitor: V) -> Result<V::Value, E>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::U8(v) => visitor.visit_u8(v),
|
||||||
|
Content::U16(v) => visitor.visit_u16(v),
|
||||||
|
Content::U32(v) => visitor.visit_u32(v),
|
||||||
|
Content::U64(v) => visitor.visit_u64(v),
|
||||||
|
Content::I8(v) => visitor.visit_i8(v),
|
||||||
|
Content::I16(v) => visitor.visit_i16(v),
|
||||||
|
Content::I32(v) => visitor.visit_i32(v),
|
||||||
|
Content::I64(v) => visitor.visit_i64(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_content_seq_ref<'a, 'de, V, E>(
|
||||||
|
content: &'a [Content<'de>],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, E>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
let seq = content.into_iter().map(ContentRefDeserializer::new);
|
||||||
|
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
||||||
|
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
||||||
|
try!(seq_visitor.end());
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_content_map_ref<'a, 'de, V, E>(
|
||||||
|
content: &'a [(Content<'de>, Content<'de>)],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, E>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
let map = content.into_iter().map(|&(ref k, ref v)| {
|
||||||
|
(
|
||||||
|
ContentRefDeserializer::new(k),
|
||||||
|
ContentRefDeserializer::new(v),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||||
|
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||||
|
try!(map_visitor.end());
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
|
||||||
/// Used when deserializing an untagged enum because the content may need to be
|
/// Used when deserializing an untagged enum because the content may need to be
|
||||||
/// used more than once.
|
/// used more than once.
|
||||||
impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E>
|
impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E>
|
||||||
@@ -1487,28 +1815,155 @@ mod content {
|
|||||||
Content::Newtype(ref v) => {
|
Content::Newtype(ref v) => {
|
||||||
visitor.visit_newtype_struct(ContentRefDeserializer::new(v))
|
visitor.visit_newtype_struct(ContentRefDeserializer::new(v))
|
||||||
}
|
}
|
||||||
Content::Seq(ref v) => {
|
Content::Seq(ref v) => visit_content_seq_ref(v, visitor),
|
||||||
let seq = v.into_iter().map(ContentRefDeserializer::new);
|
Content::Map(ref v) => visit_content_map_ref(v, visitor),
|
||||||
let mut seq_visitor = de::value::SeqDeserializer::new(seq);
|
|
||||||
let value = try!(visitor.visit_seq(&mut seq_visitor));
|
|
||||||
try!(seq_visitor.end());
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
Content::Map(ref v) => {
|
|
||||||
let map = v.into_iter().map(|&(ref k, ref v)| {
|
|
||||||
(
|
|
||||||
ContentRefDeserializer::new(k),
|
|
||||||
ContentRefDeserializer::new(v),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
|
||||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
|
||||||
try!(map_visitor.end());
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::Bool(v) => visitor.visit_bool(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_integer(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::F32(v) => visitor.visit_f32(v),
|
||||||
|
Content::F64(v) => visitor.visit_f64(v),
|
||||||
|
Content::U64(v) => visitor.visit_u64(v),
|
||||||
|
Content::I64(v) => visitor.visit_i64(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::F64(v) => visitor.visit_f64(v),
|
||||||
|
Content::U64(v) => visitor.visit_u64(v),
|
||||||
|
Content::I64(v) => visitor.visit_i64(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::Char(v) => visitor.visit_char(v),
|
||||||
|
Content::String(ref v) => visitor.visit_str(v),
|
||||||
|
Content::Str(v) => visitor.visit_borrowed_str(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::String(ref v) => visitor.visit_str(v),
|
||||||
|
Content::Str(v) => visitor.visit_borrowed_str(v),
|
||||||
|
Content::ByteBuf(ref v) => visitor.visit_bytes(v),
|
||||||
|
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_str(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::String(ref v) => visitor.visit_str(v),
|
||||||
|
Content::Str(v) => visitor.visit_borrowed_str(v),
|
||||||
|
Content::ByteBuf(ref v) => visitor.visit_bytes(v),
|
||||||
|
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
|
||||||
|
Content::Seq(ref v) => visit_content_seq_ref(v, visitor),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_bytes(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, E>
|
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, E>
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
@@ -1521,6 +1976,27 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::Unit => visitor.visit_unit(),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_unit(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, E>
|
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, E>
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
@@ -1528,6 +2004,61 @@ mod content {
|
|||||||
visitor.visit_newtype_struct(self)
|
visitor.visit_newtype_struct(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::Seq(ref v) => visit_content_seq_ref(v, visitor),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_seq(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_seq(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::Map(ref v) => visit_content_map_ref(v, visitor),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::Seq(ref v) => visit_content_seq_ref(v, visitor),
|
||||||
|
Content::Map(ref v) => visit_content_map_ref(v, visitor),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_enum<V>(
|
fn deserialize_enum<V>(
|
||||||
self,
|
self,
|
||||||
_name: &str,
|
_name: &str,
|
||||||
@@ -1574,10 +2105,22 @@ mod content {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_to_deserialize_any! {
|
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
where
|
||||||
byte_buf unit unit_struct seq tuple tuple_struct map struct
|
V: Visitor<'de>,
|
||||||
identifier ignored_any
|
{
|
||||||
|
match *self.content {
|
||||||
|
Content::String(ref v) => visitor.visit_str(v),
|
||||||
|
Content::Str(v) => visitor.visit_borrowed_str(v),
|
||||||
|
_ => Err(self.invalid_type(&visitor)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_unit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.38" # remember to update html_root_url
|
version = "1.0.42" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
|
|||||||
+22
-20
@@ -16,6 +16,7 @@ use bound;
|
|||||||
use fragment::{Expr, Fragment, Match, Stmts};
|
use fragment::{Expr, Fragment, Match, Stmts};
|
||||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
use internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
use internals::{self, attr};
|
use internals::{self, attr};
|
||||||
|
use try;
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
@@ -36,10 +37,9 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
|
|||||||
|
|
||||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||||
let vis = &input.vis;
|
let vis = &input.vis;
|
||||||
let fun = quote_spanned!(Span::call_site()=> deserialize);
|
|
||||||
quote! {
|
quote! {
|
||||||
impl #de_impl_generics #ident #ty_generics #where_clause {
|
impl #de_impl_generics #ident #ty_generics #where_clause {
|
||||||
#vis fn #fun<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
|
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
|
||||||
where __D: _serde::Deserializer<#delife>
|
where __D: _serde::Deserializer<#delife>
|
||||||
{
|
{
|
||||||
#body
|
#body
|
||||||
@@ -63,10 +63,12 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let try_replacement = try::replacement();
|
||||||
let generated = quote! {
|
let generated = quote! {
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const #dummy_const: () = {
|
const #dummy_const: () = {
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
|
#try_replacement
|
||||||
#impl_block
|
#impl_block
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -583,11 +585,11 @@ fn deserialize_seq(
|
|||||||
|
|
||||||
let mut result = if is_struct {
|
let mut result = if is_struct {
|
||||||
let names = fields.iter().map(|f| &f.ident);
|
let names = fields.iter().map(|f| &f.ident);
|
||||||
quote_spanned! {Span::call_site()=>
|
quote! {
|
||||||
#type_path { #( #names: #vars ),* }
|
#type_path { #( #names: #vars ),* }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote_spanned! {Span::call_site()=>
|
quote! {
|
||||||
#type_path ( #(#vars),* )
|
#type_path ( #(#vars),* )
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -649,11 +651,10 @@ fn deserialize_seq_in_place(
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let dot = quote_spanned!(Span::call_site()=> .);
|
|
||||||
if field.attrs.skip_deserializing() {
|
if field.attrs.skip_deserializing() {
|
||||||
let default = Expr(expr_is_missing(field, cattrs));
|
let default = Expr(expr_is_missing(field, cattrs));
|
||||||
quote! {
|
quote! {
|
||||||
self.place #dot #field_name = #default;
|
self.place.#field_name = #default;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let return_invalid_length = quote! {
|
let return_invalid_length = quote! {
|
||||||
@@ -663,7 +664,7 @@ fn deserialize_seq_in_place(
|
|||||||
None => {
|
None => {
|
||||||
quote! {
|
quote! {
|
||||||
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
|
if let _serde::export::None = try!(_serde::de::SeqAccess::next_element_seed(&mut __seq,
|
||||||
_serde::private::de::InPlaceSeed(&mut self.place #dot #field_name)))
|
_serde::private::de::InPlaceSeed(&mut self.place.#field_name)))
|
||||||
{
|
{
|
||||||
#return_invalid_length
|
#return_invalid_length
|
||||||
}
|
}
|
||||||
@@ -676,7 +677,7 @@ fn deserialize_seq_in_place(
|
|||||||
#wrapper
|
#wrapper
|
||||||
match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) {
|
match try!(_serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)) {
|
||||||
_serde::export::Some(__wrap) => {
|
_serde::export::Some(__wrap) => {
|
||||||
self.place #dot #field_name = __wrap.value;
|
self.place.#field_name = __wrap.value;
|
||||||
}
|
}
|
||||||
_serde::export::None => {
|
_serde::export::None => {
|
||||||
#return_invalid_length
|
#return_invalid_length
|
||||||
@@ -732,7 +733,7 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = quote_spanned!(Span::call_site()=> #type_path(#value));
|
let mut result = quote!(#type_path(__field0));
|
||||||
if params.has_getter {
|
if params.has_getter {
|
||||||
let this = ¶ms.this;
|
let this = ¶ms.this;
|
||||||
result = quote! {
|
result = quote! {
|
||||||
@@ -745,6 +746,7 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
|
|||||||
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
||||||
where __E: _serde::Deserializer<#delife>
|
where __E: _serde::Deserializer<#delife>
|
||||||
{
|
{
|
||||||
|
let __field0 = #value;
|
||||||
_serde::export::Ok(#result)
|
_serde::export::Ok(#result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -757,13 +759,12 @@ fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> To
|
|||||||
|
|
||||||
let delife = params.borrowed.de_lifetime();
|
let delife = params.borrowed.de_lifetime();
|
||||||
|
|
||||||
let elem = quote_spanned!(Span::call_site()=> .0);
|
|
||||||
quote! {
|
quote! {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
|
||||||
where __E: _serde::Deserializer<#delife>
|
where __E: _serde::Deserializer<#delife>
|
||||||
{
|
{
|
||||||
_serde::Deserialize::deserialize_in_place(__e, &mut self.place #elem)
|
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1625,12 +1626,13 @@ fn deserialize_untagged_variant(
|
|||||||
let type_name = params.type_name();
|
let type_name = params.type_name();
|
||||||
let variant_name = variant.ident.as_ref();
|
let variant_name = variant.ident.as_ref();
|
||||||
quote_expr! {
|
quote_expr! {
|
||||||
_serde::export::Result::map(
|
match _serde::Deserializer::deserialize_any(
|
||||||
_serde::Deserializer::deserialize_any(
|
#deserializer,
|
||||||
#deserializer,
|
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
|
||||||
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
|
) {
|
||||||
),
|
_serde::export::Ok(()) => _serde::export::Ok(#this::#variant_ident),
|
||||||
|()| #this::#variant_ident)
|
_serde::export::Err(__err) => _serde::export::Err(__err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Style::Newtype => deserialize_untagged_newtype_variant(
|
Style::Newtype => deserialize_untagged_newtype_variant(
|
||||||
@@ -2305,9 +2307,9 @@ fn deserialize_map(
|
|||||||
let ident = field.ident.expect("struct contains unnamed fields");
|
let ident = field.ident.expect("struct contains unnamed fields");
|
||||||
if field.attrs.skip_deserializing() {
|
if field.attrs.skip_deserializing() {
|
||||||
let value = Expr(expr_is_missing(field, cattrs));
|
let value = Expr(expr_is_missing(field, cattrs));
|
||||||
quote_spanned!(Span::call_site()=> #ident: #value)
|
quote!(#ident: #value)
|
||||||
} else {
|
} else {
|
||||||
quote_spanned!(Span::call_site()=> #ident: #name)
|
quote!(#ident: #name)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2325,7 +2327,7 @@ fn deserialize_map(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = quote_spanned!(Span::call_site()=> #struct_path { #(#result),* });
|
let mut result = quote!(#struct_path { #(#result),* });
|
||||||
if params.has_getter {
|
if params.has_getter {
|
||||||
let this = ¶ms.this;
|
let this = ¶ms.this;
|
||||||
result = quote! {
|
result = quote! {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.38")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.42")]
|
||||||
#![cfg_attr(
|
#![cfg_attr(
|
||||||
feature = "cargo-clippy",
|
feature = "cargo-clippy",
|
||||||
allow(enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding)
|
allow(enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding)
|
||||||
@@ -43,14 +43,6 @@ extern crate proc_macro2;
|
|||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use syn::DeriveInput;
|
use syn::DeriveInput;
|
||||||
|
|
||||||
// Quote's default is def_site but it appears call_site is likely to stabilize
|
|
||||||
// before def_site. Thus we try to use only call_site.
|
|
||||||
macro_rules! quote {
|
|
||||||
($($tt:tt)*) => {
|
|
||||||
quote_spanned!($crate::proc_macro2::Span::call_site()=> $($tt)*)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod bound;
|
mod bound;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -58,6 +50,7 @@ mod fragment;
|
|||||||
|
|
||||||
mod de;
|
mod de;
|
||||||
mod ser;
|
mod ser;
|
||||||
|
mod try;
|
||||||
|
|
||||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||||
|
|||||||
+15
-7
@@ -15,6 +15,7 @@ use bound;
|
|||||||
use fragment::{Fragment, Match, Stmts};
|
use fragment::{Fragment, Match, Stmts};
|
||||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
use internals::ast::{Container, Data, Field, Style, Variant};
|
||||||
use internals::{attr, Ctxt};
|
use internals::{attr, Ctxt};
|
||||||
|
use try;
|
||||||
|
|
||||||
use std::u32;
|
use std::u32;
|
||||||
|
|
||||||
@@ -32,10 +33,9 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
|||||||
|
|
||||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||||
let vis = &input.vis;
|
let vis = &input.vis;
|
||||||
let fun = quote_spanned!(Span::call_site()=> serialize);
|
|
||||||
quote! {
|
quote! {
|
||||||
impl #impl_generics #ident #ty_generics #where_clause {
|
impl #impl_generics #ident #ty_generics #where_clause {
|
||||||
#vis fn #fun<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||||
where __S: _serde::Serializer
|
where __S: _serde::Serializer
|
||||||
{
|
{
|
||||||
#body
|
#body
|
||||||
@@ -55,10 +55,12 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let try_replacement = try::replacement();
|
||||||
let generated = quote! {
|
let generated = quote! {
|
||||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
const #dummy_const: () = {
|
const #dummy_const: () = {
|
||||||
extern crate serde as _serde;
|
extern crate serde as _serde;
|
||||||
|
#try_replacement
|
||||||
#impl_block
|
#impl_block
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -594,9 +596,15 @@ fn serialize_adjacently_tagged_variant(
|
|||||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
quote_expr! {
|
return quote_block! {
|
||||||
_serde::Serialize::serialize(#field_expr, __serializer)
|
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||||
}
|
__serializer, #type_name, 2));
|
||||||
|
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||||
|
&mut __struct, #tag, #variant_name));
|
||||||
|
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||||
|
&mut __struct, #content, #field_expr));
|
||||||
|
_serde::ser::SerializeStruct::end(__struct)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Style::Tuple => {
|
Style::Tuple => {
|
||||||
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
|
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
|
||||||
@@ -1056,9 +1064,9 @@ fn mut_if(is_mut: bool) -> Option<Tokens> {
|
|||||||
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
|
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
|
||||||
let self_var = ¶ms.self_var;
|
let self_var = ¶ms.self_var;
|
||||||
match (params.is_remote, field.attrs.getter()) {
|
match (params.is_remote, field.attrs.getter()) {
|
||||||
(false, None) => quote_spanned!(Span::call_site()=> &#self_var.#member),
|
(false, None) => quote!(&#self_var.#member),
|
||||||
(true, None) => {
|
(true, None) => {
|
||||||
let inner = quote_spanned!(Span::call_site()=> &#self_var.#member);
|
let inner = quote!(&#self_var.#member);
|
||||||
let ty = field.ty;
|
let ty = field.ty;
|
||||||
quote!(_serde::private::ser::constrain::<#ty>(#inner))
|
quote!(_serde::private::ser::constrain::<#ty>(#inner))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
use quote::Tokens;
|
||||||
|
use proc_macro2::{Op, Spacing};
|
||||||
|
|
||||||
|
// None of our generated code requires the `From::from` error conversion
|
||||||
|
// performed by the standard library's `try!` macro. With this simplified macro
|
||||||
|
// we see a significant improvement in type checking and borrow checking time of
|
||||||
|
// the generated code and a slight improvement in binary size.
|
||||||
|
pub fn replacement() -> Tokens {
|
||||||
|
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
|
||||||
|
let dollar = Op::new('$', Spacing::Alone);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! try {
|
||||||
|
(#dollar __expr:expr) => {
|
||||||
|
match #dollar __expr {
|
||||||
|
_serde::export::Ok(__val) => __val,
|
||||||
|
_serde::export::Err(__err) => {
|
||||||
|
return _serde::export::Err(__err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_test"
|
name = "serde_test"
|
||||||
version = "1.0.38" # remember to update html_root_url
|
version = "1.0.42" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.38")]
|
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.42")]
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ macro_rules! assert_next_token {
|
|||||||
($ser:expr, $expected:ident($v:expr)) => {
|
($ser:expr, $expected:ident($v:expr)) => {
|
||||||
assert_next_token!(
|
assert_next_token!(
|
||||||
$ser,
|
$ser,
|
||||||
format_args!("{}({:?})", stringify!($expected), $v),
|
format_args!(concat!(stringify!($expected), "({:?})"), $v),
|
||||||
Token::$expected(v),
|
Token::$expected(v),
|
||||||
v == $v
|
v == $v
|
||||||
);
|
);
|
||||||
@@ -56,13 +56,13 @@ macro_rules! assert_next_token {
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
$(
|
$(
|
||||||
write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap();
|
write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
|
||||||
)*
|
)*
|
||||||
buffer
|
buffer
|
||||||
};
|
};
|
||||||
assert_next_token!(
|
assert_next_token!(
|
||||||
$ser,
|
$ser,
|
||||||
format_args!("{} {{ {}}}", stringify!($expected), field_format()),
|
format_args!(concat!(stringify!($expected), " {{ {}}}"), field_format()),
|
||||||
Token::$expected { $($k),* },
|
Token::$expected { $($k),* },
|
||||||
($($k,)*) == compare
|
($($k,)*) == compare
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
use serde::de::{Deserializer, Visitor, SeqAccess, Error};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
|
||||||
|
where D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
deserializer.deserialize_byte_buf(ByteBufVisitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ByteBufVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for ByteBufVisitor {
|
||||||
|
type Value = Vec<u8>;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("byte array")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
|
||||||
|
where V: SeqAccess<'de>
|
||||||
|
{
|
||||||
|
let mut values = Vec::new();
|
||||||
|
while let Some(value) = try!(visitor.next_element()) {
|
||||||
|
values.push(value);
|
||||||
|
}
|
||||||
|
Ok(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where E: Error
|
||||||
|
{
|
||||||
|
Ok(v.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||||
|
where E: Error
|
||||||
|
{
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where E: Error
|
||||||
|
{
|
||||||
|
Ok(v.as_bytes().to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||||
|
where E: Error
|
||||||
|
{
|
||||||
|
Ok(v.into_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,11 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
extern crate serde;
|
||||||
extern crate serde_test;
|
extern crate serde_test;
|
||||||
|
|
||||||
|
mod bytes;
|
||||||
|
|
||||||
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens,
|
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens,
|
||||||
Token};
|
Token};
|
||||||
|
|
||||||
@@ -779,6 +783,158 @@ fn test_internally_tagged_enum() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_internally_tagged_bytes() {
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
enum InternallyTagged {
|
||||||
|
String {
|
||||||
|
string: String,
|
||||||
|
},
|
||||||
|
Bytes {
|
||||||
|
#[serde(with = "bytes")]
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::String { string: "\0".to_owned() },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "String",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("String"),
|
||||||
|
Token::Str("string"),
|
||||||
|
Token::Str("\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::String { string: "\0".to_owned() },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "String",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("String"),
|
||||||
|
Token::Str("string"),
|
||||||
|
Token::String("\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::String { string: "\0".to_owned() },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "String",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("String"),
|
||||||
|
Token::Str("string"),
|
||||||
|
Token::Bytes(b"\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::String { string: "\0".to_owned() },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "String",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("String"),
|
||||||
|
Token::Str("string"),
|
||||||
|
Token::ByteBuf(b"\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Bytes",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("Bytes"),
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::Str("\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Bytes",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("Bytes"),
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::String("\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Bytes",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("Bytes"),
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::Bytes(b"\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Bytes",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("Bytes"),
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::ByteBuf(b"\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Bytes",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
|
Token::Str("type"),
|
||||||
|
Token::Str("Bytes"),
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::Seq { len: Some(1) },
|
||||||
|
Token::U8(0),
|
||||||
|
Token::SeqEnd,
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@@ -1246,6 +1402,140 @@ fn test_enum_in_untagged_enum() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_untagged_bytes() {
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum Untagged {
|
||||||
|
String {
|
||||||
|
string: String,
|
||||||
|
},
|
||||||
|
Bytes {
|
||||||
|
#[serde(with = "bytes")]
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::String { string: "\0".to_owned() },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("string"),
|
||||||
|
Token::Str("\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::String { string: "\0".to_owned() },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("string"),
|
||||||
|
Token::String("\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::String { string: "\0".to_owned() },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("string"),
|
||||||
|
Token::Bytes(b"\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::String { string: "\0".to_owned() },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("string"),
|
||||||
|
Token::ByteBuf(b"\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::Str("\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::String("\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::Bytes(b"\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::ByteBuf(b"\0"),
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&Untagged::Bytes { bytes: vec![0] },
|
||||||
|
&[
|
||||||
|
Token::Struct {
|
||||||
|
name: "Untagged",
|
||||||
|
len: 1,
|
||||||
|
},
|
||||||
|
Token::Str("bytes"),
|
||||||
|
Token::Seq { len: Some(1) },
|
||||||
|
Token::U8(0),
|
||||||
|
Token::SeqEnd,
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rename_all() {
|
fn test_rename_all() {
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||||
|
|||||||
Reference in New Issue
Block a user