mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-26 01:37:55 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c68b959696 | |||
| eab80172e4 | |||
| c1259fbc87 | |||
| 58e30eaee4 | |||
| bafa941004 | |||
| f347b2d363 | |||
| 3f9fc49cca | |||
| c913527944 | |||
| 8fafc7420c | |||
| bea1c5b0f5 | |||
| aa37caf216 | |||
| 2440b59aae | |||
| 873cfbe9ab | |||
| c96efcb87a | |||
| b53026a21b | |||
| c7901e532e | |||
| 2af0701be6 | |||
| ae79451b7a | |||
| b220f264a5 | |||
| 1a2b3815ef | |||
| 6fbf40b83c | |||
| 1d6ecf3c2c |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.0" # remember to update html_root_url
|
version = "1.0.4" # 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"
|
||||||
|
|||||||
+47
-7
@@ -897,6 +897,44 @@ parse_impl!(net::SocketAddrV6);
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
struct PathVisitor;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl<'a> Visitor<'a> for PathVisitor {
|
||||||
|
type Value = &'a Path;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a borrowed path")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
Ok(v.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
str::from_utf8(v)
|
||||||
|
.map(AsRef::as_ref)
|
||||||
|
.map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl<'de: 'a, 'a> Deserialize<'de> for &'a Path {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_str(PathVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
struct PathBufVisitor;
|
struct PathBufVisitor;
|
||||||
|
|
||||||
@@ -1471,22 +1509,24 @@ where
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
#[allow(deprecated)] // num::Zero is deprecated but there is no replacement
|
|
||||||
impl<'de, T> Deserialize<'de> for NonZero<T>
|
impl<'de, T> Deserialize<'de> for NonZero<T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de> + PartialEq + Zeroable + Zero,
|
T: Deserialize<'de> + Zeroable,
|
||||||
{
|
{
|
||||||
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let value = try!(Deserialize::deserialize(deserializer));
|
let value = try!(Deserialize::deserialize(deserializer));
|
||||||
if value == Zero::zero() {
|
unsafe {
|
||||||
return Err(Error::custom("expected a non-zero value"));
|
let ptr = &value as *const T as *const u8;
|
||||||
|
if slice::from_raw_parts(ptr, mem::size_of::<T>()).iter().all(|&b| b == 0) {
|
||||||
|
return Err(Error::custom("expected a non-zero value"));
|
||||||
|
}
|
||||||
|
// Waiting for a safe way to construct NonZero<T>:
|
||||||
|
// https://github.com/rust-lang/rust/issues/27730#issuecomment-269726075
|
||||||
|
Ok(NonZero::new(value))
|
||||||
}
|
}
|
||||||
// Waiting for a safe way to construct NonZero<T>:
|
|
||||||
// https://github.com/rust-lang/rust/issues/27730#issuecomment-269726075
|
|
||||||
unsafe { Ok(NonZero::new(value)) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-6
@@ -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.0")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.4")]
|
||||||
|
|
||||||
// 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)]
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
// discussion of these features please refer to this issue:
|
// discussion of these features please refer to this issue:
|
||||||
//
|
//
|
||||||
// https://github.com/serde-rs/serde/issues/812
|
// https://github.com/serde-rs/serde/issues/812
|
||||||
#![cfg_attr(feature = "unstable", feature(nonzero, specialization, zero_one))]
|
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
|
||||||
#![cfg_attr(all(feature = "std", feature = "unstable"), feature(into_boxed_c_str))]
|
#![cfg_attr(all(feature = "std", feature = "unstable"), feature(into_boxed_c_str))]
|
||||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||||
#![cfg_attr(feature = "collections", feature(collections))]
|
#![cfg_attr(feature = "collections", feature(collections))]
|
||||||
@@ -124,7 +124,7 @@ mod lib {
|
|||||||
pub use core::*;
|
pub use core::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::core::{cmp, iter, mem, ops, str};
|
pub use self::core::{cmp, iter, mem, ops, slice, str};
|
||||||
pub use self::core::{i8, i16, i32, i64, isize};
|
pub use self::core::{i8, i16, i32, i64, isize};
|
||||||
pub use self::core::{u8, u16, u32, u64, usize};
|
pub use self::core::{u8, u16, u32, u64, usize};
|
||||||
pub use self::core::{f32, f64};
|
pub use self::core::{f32, f64};
|
||||||
@@ -193,9 +193,6 @@ mod lib {
|
|||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
pub use core::nonzero::{NonZero, Zeroable};
|
pub use core::nonzero::{NonZero, Zeroable};
|
||||||
#[cfg(feature = "unstable")]
|
|
||||||
#[allow(deprecated)] // required for impl Deserialize for NonZero<T>
|
|
||||||
pub use core::num::Zero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
+220
-113
@@ -16,6 +16,7 @@ use de::Unexpected;
|
|||||||
#[cfg(any(feature = "std", feature = "collections"))]
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer,
|
pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer,
|
||||||
TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor,
|
TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor,
|
||||||
|
TagContentOtherField, TagContentOtherFieldVisitor,
|
||||||
InternallyTaggedUnitVisitor, UntaggedUnitVisitor};
|
InternallyTaggedUnitVisitor, UntaggedUnitVisitor};
|
||||||
|
|
||||||
/// If the missing field is of type `Option<T>` then treat is as `None`,
|
/// If the missing field is of type `Option<T>` then treat is as `None`,
|
||||||
@@ -232,7 +233,7 @@ mod content {
|
|||||||
///
|
///
|
||||||
/// Not public API. Use serde-value instead.
|
/// Not public API. Use serde-value instead.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Content {
|
pub enum Content<'de> {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
|
|
||||||
U8(u8),
|
U8(u8),
|
||||||
@@ -250,18 +251,20 @@ mod content {
|
|||||||
|
|
||||||
Char(char),
|
Char(char),
|
||||||
String(String),
|
String(String),
|
||||||
Bytes(Vec<u8>),
|
Str(&'de str),
|
||||||
|
ByteBuf(Vec<u8>),
|
||||||
|
Bytes(&'de [u8]),
|
||||||
|
|
||||||
None,
|
None,
|
||||||
Some(Box<Content>),
|
Some(Box<Content<'de>>),
|
||||||
|
|
||||||
Unit,
|
Unit,
|
||||||
Newtype(Box<Content>),
|
Newtype(Box<Content<'de>>),
|
||||||
Seq(Vec<Content>),
|
Seq(Vec<Content<'de>>),
|
||||||
Map(Vec<(Content, Content)>),
|
Map(Vec<(Content<'de>, Content<'de>)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Content {
|
impl<'de> Content<'de> {
|
||||||
fn unexpected(&self) -> Unexpected {
|
fn unexpected(&self) -> Unexpected {
|
||||||
match *self {
|
match *self {
|
||||||
Content::Bool(b) => Unexpected::Bool(b),
|
Content::Bool(b) => Unexpected::Bool(b),
|
||||||
@@ -277,7 +280,9 @@ mod content {
|
|||||||
Content::F64(f) => Unexpected::Float(f),
|
Content::F64(f) => Unexpected::Float(f),
|
||||||
Content::Char(c) => Unexpected::Char(c),
|
Content::Char(c) => Unexpected::Char(c),
|
||||||
Content::String(ref s) => Unexpected::Str(s),
|
Content::String(ref s) => Unexpected::Str(s),
|
||||||
Content::Bytes(ref b) => Unexpected::Bytes(b),
|
Content::Str(s) => Unexpected::Str(s),
|
||||||
|
Content::ByteBuf(ref b) => Unexpected::Bytes(b),
|
||||||
|
Content::Bytes(b) => Unexpected::Bytes(b),
|
||||||
Content::None | Content::Some(_) => Unexpected::Option,
|
Content::None | Content::Some(_) => Unexpected::Option,
|
||||||
Content::Unit => Unexpected::Unit,
|
Content::Unit => Unexpected::Unit,
|
||||||
Content::Newtype(_) => Unexpected::NewtypeStruct,
|
Content::Newtype(_) => Unexpected::NewtypeStruct,
|
||||||
@@ -287,21 +292,30 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Content {
|
impl<'de> Deserialize<'de> for Content<'de> {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
// Untagged and internally tagged enums are only supported in
|
// Untagged and internally tagged enums are only supported in
|
||||||
// self-describing formats.
|
// self-describing formats.
|
||||||
deserializer.deserialize_any(ContentVisitor)
|
let visitor = ContentVisitor { value: PhantomData };
|
||||||
|
deserializer.deserialize_any(visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContentVisitor;
|
struct ContentVisitor<'de> {
|
||||||
|
value: PhantomData<Content<'de>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for ContentVisitor {
|
impl<'de> ContentVisitor<'de> {
|
||||||
type Value = Content;
|
fn new() -> Self {
|
||||||
|
ContentVisitor { value: PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for ContentVisitor<'de> {
|
||||||
|
type Value = Content<'de>;
|
||||||
|
|
||||||
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt.write_str("any value")
|
fmt.write_str("any value")
|
||||||
@@ -398,6 +412,13 @@ mod content {
|
|||||||
Ok(Content::String(value.into()))
|
Ok(Content::String(value.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<F>(self, value: &'de str) -> Result<Self::Value, F>
|
||||||
|
where
|
||||||
|
F: de::Error,
|
||||||
|
{
|
||||||
|
Ok(Content::Str(value))
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
|
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
|
||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
@@ -409,14 +430,21 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
Ok(Content::Bytes(value.into()))
|
Ok(Content::ByteBuf(value.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_bytes<F>(self, value: &'de [u8]) -> Result<Self::Value, F>
|
||||||
|
where
|
||||||
|
F: de::Error,
|
||||||
|
{
|
||||||
|
Ok(Content::Bytes(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
|
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
|
||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
Ok(Content::Bytes(value))
|
Ok(Content::ByteBuf(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_unit<F>(self) -> Result<Self::Value, F>
|
fn visit_unit<F>(self) -> Result<Self::Value, F>
|
||||||
@@ -480,23 +508,24 @@ mod content {
|
|||||||
/// This is the type of the map keys in an internally tagged enum.
|
/// This is the type of the map keys in an internally tagged enum.
|
||||||
///
|
///
|
||||||
/// Not public API.
|
/// Not public API.
|
||||||
pub enum TagOrContent {
|
pub enum TagOrContent<'de> {
|
||||||
Tag,
|
Tag,
|
||||||
Content(Content),
|
Content(Content<'de>),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TagOrContentVisitor {
|
struct TagOrContentVisitor<'de> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
|
value: PhantomData<TagOrContent<'de>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TagOrContentVisitor {
|
impl<'de> TagOrContentVisitor<'de> {
|
||||||
fn new(name: &'static str) -> Self {
|
fn new(name: &'static str) -> Self {
|
||||||
TagOrContentVisitor { name: name }
|
TagOrContentVisitor { name: name, value: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> DeserializeSeed<'de> for TagOrContentVisitor {
|
impl<'de> DeserializeSeed<'de> for TagOrContentVisitor<'de> {
|
||||||
type Value = TagOrContent;
|
type Value = TagOrContent<'de>;
|
||||||
|
|
||||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
where
|
where
|
||||||
@@ -508,8 +537,8 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for TagOrContentVisitor {
|
impl<'de> Visitor<'de> for TagOrContentVisitor<'de> {
|
||||||
type Value = TagOrContent;
|
type Value = TagOrContent<'de>;
|
||||||
|
|
||||||
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(fmt, "a type tag `{}` or any other value", self.name)
|
write!(fmt, "a type tag `{}` or any other value", self.name)
|
||||||
@@ -519,7 +548,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_bool(value)
|
.visit_bool(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -528,14 +557,14 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor.visit_i8(value).map(TagOrContent::Content)
|
ContentVisitor::new().visit_i8(value).map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
|
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
|
||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_i16(value)
|
.visit_i16(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -544,7 +573,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_i32(value)
|
.visit_i32(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -553,7 +582,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_i64(value)
|
.visit_i64(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -562,14 +591,14 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor.visit_u8(value).map(TagOrContent::Content)
|
ContentVisitor::new().visit_u8(value).map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
|
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
|
||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_u16(value)
|
.visit_u16(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -578,7 +607,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_u32(value)
|
.visit_u32(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -587,7 +616,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_u64(value)
|
.visit_u64(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -596,7 +625,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_f32(value)
|
.visit_f32(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -605,7 +634,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_f64(value)
|
.visit_f64(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -614,7 +643,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_char(value)
|
.visit_char(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -626,12 +655,25 @@ mod content {
|
|||||||
if value == self.name {
|
if value == self.name {
|
||||||
Ok(TagOrContent::Tag)
|
Ok(TagOrContent::Tag)
|
||||||
} else {
|
} else {
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_str(value)
|
.visit_str(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<F>(self, value: &'de str) -> Result<Self::Value, F>
|
||||||
|
where
|
||||||
|
F: de::Error,
|
||||||
|
{
|
||||||
|
if value == self.name {
|
||||||
|
Ok(TagOrContent::Tag)
|
||||||
|
} else {
|
||||||
|
ContentVisitor::new()
|
||||||
|
.visit_borrowed_str(value)
|
||||||
|
.map(TagOrContent::Content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
|
fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
|
||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
@@ -639,7 +681,7 @@ mod content {
|
|||||||
if value == self.name {
|
if value == self.name {
|
||||||
Ok(TagOrContent::Tag)
|
Ok(TagOrContent::Tag)
|
||||||
} else {
|
} else {
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_string(value)
|
.visit_string(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -652,12 +694,25 @@ mod content {
|
|||||||
if value == self.name.as_bytes() {
|
if value == self.name.as_bytes() {
|
||||||
Ok(TagOrContent::Tag)
|
Ok(TagOrContent::Tag)
|
||||||
} else {
|
} else {
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_bytes(value)
|
.visit_bytes(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_bytes<F>(self, value: &'de [u8]) -> Result<Self::Value, F>
|
||||||
|
where
|
||||||
|
F: de::Error,
|
||||||
|
{
|
||||||
|
if value == self.name.as_bytes() {
|
||||||
|
Ok(TagOrContent::Tag)
|
||||||
|
} else {
|
||||||
|
ContentVisitor::new()
|
||||||
|
.visit_borrowed_bytes(value)
|
||||||
|
.map(TagOrContent::Content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
|
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
|
||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
@@ -665,7 +720,7 @@ mod content {
|
|||||||
if value == self.name.as_bytes() {
|
if value == self.name.as_bytes() {
|
||||||
Ok(TagOrContent::Tag)
|
Ok(TagOrContent::Tag)
|
||||||
} else {
|
} else {
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_byte_buf(value)
|
.visit_byte_buf(value)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -675,21 +730,21 @@ mod content {
|
|||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor.visit_unit().map(TagOrContent::Content)
|
ContentVisitor::new().visit_unit().map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_none<F>(self) -> Result<Self::Value, F>
|
fn visit_none<F>(self) -> Result<Self::Value, F>
|
||||||
where
|
where
|
||||||
F: de::Error,
|
F: de::Error,
|
||||||
{
|
{
|
||||||
ContentVisitor.visit_none().map(TagOrContent::Content)
|
ContentVisitor::new().visit_none().map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_some(deserializer)
|
.visit_some(deserializer)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -698,7 +753,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_newtype_struct(deserializer)
|
.visit_newtype_struct(deserializer)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -707,7 +762,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
V: SeqAccess<'de>,
|
V: SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_seq(visitor)
|
.visit_seq(visitor)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -716,7 +771,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
V: MapAccess<'de>,
|
V: MapAccess<'de>,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_map(visitor)
|
.visit_map(visitor)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -725,7 +780,7 @@ mod content {
|
|||||||
where
|
where
|
||||||
V: EnumAccess<'de>,
|
V: EnumAccess<'de>,
|
||||||
{
|
{
|
||||||
ContentVisitor
|
ContentVisitor::new()
|
||||||
.visit_enum(visitor)
|
.visit_enum(visitor)
|
||||||
.map(TagOrContent::Content)
|
.map(TagOrContent::Content)
|
||||||
}
|
}
|
||||||
@@ -734,33 +789,33 @@ mod content {
|
|||||||
/// Used by generated code to deserialize an internally tagged enum.
|
/// Used by generated code to deserialize an internally tagged enum.
|
||||||
///
|
///
|
||||||
/// Not public API.
|
/// Not public API.
|
||||||
pub struct TaggedContent<T> {
|
pub struct TaggedContent<'de, T> {
|
||||||
pub tag: T,
|
pub tag: T,
|
||||||
pub content: Content,
|
pub content: Content<'de>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Not public API.
|
/// Not public API.
|
||||||
pub struct TaggedContentVisitor<T> {
|
pub struct TaggedContentVisitor<'de, T> {
|
||||||
tag_name: &'static str,
|
tag_name: &'static str,
|
||||||
tag: PhantomData<T>,
|
value: PhantomData<TaggedContent<'de, T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> TaggedContentVisitor<T> {
|
impl<'de, T> TaggedContentVisitor<'de, T> {
|
||||||
/// Visitor for the content of an internally tagged enum with the given tag
|
/// Visitor for the content of an internally tagged enum with the given tag
|
||||||
/// name.
|
/// name.
|
||||||
pub fn new(name: &'static str) -> Self {
|
pub fn new(name: &'static str) -> Self {
|
||||||
TaggedContentVisitor {
|
TaggedContentVisitor {
|
||||||
tag_name: name,
|
tag_name: name,
|
||||||
tag: PhantomData,
|
value: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<T>
|
impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<'de, T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
{
|
{
|
||||||
type Value = TaggedContent<T>;
|
type Value = TaggedContent<'de, T>;
|
||||||
|
|
||||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
where
|
where
|
||||||
@@ -772,11 +827,11 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, T> Visitor<'de> for TaggedContentVisitor<T>
|
impl<'de, T> Visitor<'de> for TaggedContentVisitor<'de, T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
{
|
{
|
||||||
type Value = TaggedContent<T>;
|
type Value = TaggedContent<'de, T>;
|
||||||
|
|
||||||
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt.write_str("any value")
|
fmt.write_str("any value")
|
||||||
@@ -863,15 +918,63 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used by generated code to deserialize an adjacently tagged enum when
|
||||||
|
/// ignoring unrelated fields is allowed.
|
||||||
|
///
|
||||||
|
/// Not public API.
|
||||||
|
pub enum TagContentOtherField {
|
||||||
|
Tag,
|
||||||
|
Content,
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Not public API.
|
||||||
|
pub struct TagContentOtherFieldVisitor {
|
||||||
|
pub tag: &'static str,
|
||||||
|
pub content: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> DeserializeSeed<'de> for TagContentOtherFieldVisitor {
|
||||||
|
type Value = TagContentOtherField;
|
||||||
|
|
||||||
|
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_str(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for TagContentOtherFieldVisitor {
|
||||||
|
type Value = TagContentOtherField;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(formatter, "{:?}, {:?}, or other ignored fields", self.tag, self.content)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: de::Error,
|
||||||
|
{
|
||||||
|
if field == self.tag {
|
||||||
|
Ok(TagContentOtherField::Tag)
|
||||||
|
} else if field == self.content {
|
||||||
|
Ok(TagContentOtherField::Content)
|
||||||
|
} else {
|
||||||
|
Ok(TagContentOtherField::Other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Not public API
|
/// Not public API
|
||||||
pub struct ContentDeserializer<E> {
|
pub struct ContentDeserializer<'de, E> {
|
||||||
content: Content,
|
content: Content<'de>,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<E>
|
impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -895,6 +998,9 @@ mod content {
|
|||||||
Content::F64(v) => visitor.visit_f64(v),
|
Content::F64(v) => visitor.visit_f64(v),
|
||||||
Content::Char(v) => visitor.visit_char(v),
|
Content::Char(v) => visitor.visit_char(v),
|
||||||
Content::String(v) => visitor.visit_string(v),
|
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::Unit => visitor.visit_unit(),
|
Content::Unit => visitor.visit_unit(),
|
||||||
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)),
|
||||||
@@ -916,7 +1022,6 @@ mod content {
|
|||||||
try!(map_visitor.end());
|
try!(map_visitor.end());
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
Content::Bytes(v) => visitor.visit_byte_buf(v),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,9 +1104,9 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> ContentDeserializer<E> {
|
impl<'de, E> ContentDeserializer<'de, E> {
|
||||||
/// private API, don't use
|
/// private API, don't use
|
||||||
pub fn new(content: Content) -> Self {
|
pub fn new(content: Content<'de>) -> Self {
|
||||||
ContentDeserializer {
|
ContentDeserializer {
|
||||||
content: content,
|
content: content,
|
||||||
err: PhantomData,
|
err: PhantomData,
|
||||||
@@ -1009,21 +1114,21 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EnumDeserializer<E>
|
struct EnumDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
variant: Content,
|
variant: Content<'de>,
|
||||||
value: Option<Content>,
|
value: Option<Content<'de>>,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<E>
|
impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
type Error = E;
|
type Error = E;
|
||||||
type Variant = VariantDeserializer<Self::Error>;
|
type Variant = VariantDeserializer<'de, Self::Error>;
|
||||||
|
|
||||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), E>
|
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), E>
|
||||||
where
|
where
|
||||||
@@ -1038,15 +1143,15 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VariantDeserializer<E>
|
struct VariantDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
value: Option<Content>,
|
value: Option<Content<'de>>,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<E>
|
impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1102,19 +1207,19 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SeqDeserializer<E>
|
struct SeqDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
iter: <Vec<Content> as IntoIterator>::IntoIter,
|
iter: <Vec<Content<'de>> as IntoIterator>::IntoIter,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> SeqDeserializer<E>
|
impl<'de, E> SeqDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
fn new(vec: Vec<Content>) -> Self {
|
fn new(vec: Vec<Content<'de>>) -> Self {
|
||||||
SeqDeserializer {
|
SeqDeserializer {
|
||||||
iter: vec.into_iter(),
|
iter: vec.into_iter(),
|
||||||
err: PhantomData,
|
err: PhantomData,
|
||||||
@@ -1122,7 +1227,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> de::Deserializer<'de> for SeqDeserializer<E>
|
impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1154,7 +1259,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<E>
|
impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1178,20 +1283,20 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MapDeserializer<E>
|
struct MapDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
iter: <Vec<(Content, Content)> as IntoIterator>::IntoIter,
|
iter: <Vec<(Content<'de>, Content<'de>)> as IntoIterator>::IntoIter,
|
||||||
value: Option<Content>,
|
value: Option<Content<'de>>,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> MapDeserializer<E>
|
impl<'de, E> MapDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
fn new(map: Vec<(Content, Content)>) -> Self {
|
fn new(map: Vec<(Content<'de>, Content<'de>)>) -> Self {
|
||||||
MapDeserializer {
|
MapDeserializer {
|
||||||
iter: map.into_iter(),
|
iter: map.into_iter(),
|
||||||
value: None,
|
value: None,
|
||||||
@@ -1200,7 +1305,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> de::MapAccess<'de> for MapDeserializer<E>
|
impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1234,7 +1339,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> de::Deserializer<'de> for MapDeserializer<E>
|
impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1256,14 +1361,14 @@ mod content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Not public API.
|
/// Not public API.
|
||||||
pub struct ContentRefDeserializer<'a, E> {
|
pub struct ContentRefDeserializer<'a, 'de: 'a, E> {
|
||||||
content: &'a Content,
|
content: &'a Content<'de>,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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, E>
|
impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1287,6 +1392,9 @@ mod content {
|
|||||||
Content::F64(v) => visitor.visit_f64(v),
|
Content::F64(v) => visitor.visit_f64(v),
|
||||||
Content::Char(v) => visitor.visit_char(v),
|
Content::Char(v) => visitor.visit_char(v),
|
||||||
Content::String(ref v) => visitor.visit_str(v),
|
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::Unit => visitor.visit_unit(),
|
Content::Unit => visitor.visit_unit(),
|
||||||
Content::None => visitor.visit_none(),
|
Content::None => visitor.visit_none(),
|
||||||
Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)),
|
Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)),
|
||||||
@@ -1312,7 +1420,6 @@ mod content {
|
|||||||
try!(map_visitor.end());
|
try!(map_visitor.end());
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
Content::Bytes(ref v) => visitor.visit_bytes(v),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1391,9 +1498,9 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E> ContentRefDeserializer<'a, E> {
|
impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> {
|
||||||
/// private API, don't use
|
/// private API, don't use
|
||||||
pub fn new(content: &'a Content) -> Self {
|
pub fn new(content: &'a Content<'de>) -> Self {
|
||||||
ContentRefDeserializer {
|
ContentRefDeserializer {
|
||||||
content: content,
|
content: content,
|
||||||
err: PhantomData,
|
err: PhantomData,
|
||||||
@@ -1401,21 +1508,21 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EnumRefDeserializer<'a, E>
|
struct EnumRefDeserializer<'a, 'de: 'a, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
variant: &'a Content,
|
variant: &'a Content<'de>,
|
||||||
value: Option<&'a Content>,
|
value: Option<&'a Content<'de>>,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, E>
|
impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
type Error = E;
|
type Error = E;
|
||||||
type Variant = VariantRefDeserializer<'a, Self::Error>;
|
type Variant = VariantRefDeserializer<'a, 'de, Self::Error>;
|
||||||
|
|
||||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
|
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
|
||||||
where
|
where
|
||||||
@@ -1430,15 +1537,15 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VariantRefDeserializer<'a, E>
|
struct VariantRefDeserializer<'a, 'de: 'a, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
value: Option<&'a Content>,
|
value: Option<&'a Content<'de>>,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, E>
|
impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1494,19 +1601,19 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SeqRefDeserializer<'a, E>
|
struct SeqRefDeserializer<'a, 'de: 'a, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
iter: <&'a [Content] as IntoIterator>::IntoIter,
|
iter: <&'a [Content<'de>] as IntoIterator>::IntoIter,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E> SeqRefDeserializer<'a, E>
|
impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
fn new(vec: &'a [Content]) -> Self {
|
fn new(vec: &'a [Content<'de>]) -> Self {
|
||||||
SeqRefDeserializer {
|
SeqRefDeserializer {
|
||||||
iter: vec.into_iter(),
|
iter: vec.into_iter(),
|
||||||
err: PhantomData,
|
err: PhantomData,
|
||||||
@@ -1514,7 +1621,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E>
|
impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1546,7 +1653,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, E>
|
impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1570,20 +1677,20 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MapRefDeserializer<'a, E>
|
struct MapRefDeserializer<'a, 'de: 'a, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
iter: <&'a [(Content, Content)] as IntoIterator>::IntoIter,
|
iter: <&'a [(Content<'de>, Content<'de>)] as IntoIterator>::IntoIter,
|
||||||
value: Option<&'a Content>,
|
value: Option<&'a Content<'de>>,
|
||||||
err: PhantomData<E>,
|
err: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E> MapRefDeserializer<'a, E>
|
impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
fn new(map: &'a [(Content, Content)]) -> Self {
|
fn new(map: &'a [(Content<'de>, Content<'de>)]) -> Self {
|
||||||
MapRefDeserializer {
|
MapRefDeserializer {
|
||||||
iter: map.into_iter(),
|
iter: map.into_iter(),
|
||||||
value: None,
|
value: None,
|
||||||
@@ -1592,7 +1699,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, E>
|
impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1627,7 +1734,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E>
|
impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1648,7 +1755,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<E>
|
impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
@@ -1659,7 +1766,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, E>
|
impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, 'de, E>
|
||||||
where
|
where
|
||||||
E: de::Error,
|
E: de::Error,
|
||||||
{
|
{
|
||||||
|
|||||||
+13
-3
@@ -346,11 +346,21 @@ deref_impl!(<T> Serialize for Arc<T> where T: Serialize);
|
|||||||
#[cfg(any(feature = "std", feature = "collections"))]
|
#[cfg(any(feature = "std", feature = "collections"))]
|
||||||
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
|
||||||
deref_impl!(<T> Serialize for NonZero<T> where T: Serialize + Zeroable);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
impl<T> Serialize for NonZero<T>
|
||||||
|
where
|
||||||
|
T: Serialize + Zeroable + Clone,
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
self.clone().get().serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Serialize for Cell<T>
|
impl<T> Serialize for Cell<T>
|
||||||
where
|
where
|
||||||
T: Serialize + Copy,
|
T: Serialize + Copy,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.0" # remember to update html_root_url
|
version = "1.0.4" # 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)]"
|
||||||
|
|||||||
+59
-12
@@ -795,9 +795,19 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
|
|
||||||
let expecting = format!("adjacently tagged enum {}", params.type_name());
|
let expecting = format!("adjacently tagged enum {}", params.type_name());
|
||||||
let type_name = cattrs.name().deserialize_name();
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
let deny_unknown_fields = cattrs.deny_unknown_fields();
|
||||||
|
|
||||||
|
/// If unknown fields are allowed, we pick the visitor that can
|
||||||
|
/// step over those. Otherwise we pick the visitor that fails on
|
||||||
|
/// unknown keys.
|
||||||
|
let field_visitor_ty = if deny_unknown_fields {
|
||||||
|
quote! { _serde::private::de::TagOrContentFieldVisitor }
|
||||||
|
} else {
|
||||||
|
quote! { _serde::private::de::TagContentOtherFieldVisitor }
|
||||||
|
};
|
||||||
|
|
||||||
let tag_or_content = quote! {
|
let tag_or_content = quote! {
|
||||||
_serde::private::de::TagOrContentFieldVisitor {
|
#field_visitor_ty {
|
||||||
tag: #tag,
|
tag: #tag,
|
||||||
content: #content,
|
content: #content,
|
||||||
}
|
}
|
||||||
@@ -844,9 +854,46 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let visit_third_key = quote! {
|
/// Advance the map by one key, returning early in case of error.
|
||||||
// Visit the third key in the map, hopefully there isn't one.
|
let next_key = quote! {
|
||||||
match try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) {
|
try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content))
|
||||||
|
};
|
||||||
|
|
||||||
|
/// When allowing unknown fields, we want to transparently step through keys we don't care
|
||||||
|
/// about until we find `tag`, `content`, or run out of keys.
|
||||||
|
let next_relevant_key = if deny_unknown_fields {
|
||||||
|
next_key
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
let mut __rk : _serde::export::Option<_serde::private::de::TagOrContentField> = _serde::export::None;
|
||||||
|
while let _serde::export::Some(__k) = #next_key {
|
||||||
|
match __k {
|
||||||
|
_serde::private::de::TagContentOtherField::Other => {
|
||||||
|
try!(_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map));
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
_serde::private::de::TagContentOtherField::Tag => {
|
||||||
|
__rk = _serde::export::Some(_serde::private::de::TagOrContentField::Tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_serde::private::de::TagContentOtherField::Content => {
|
||||||
|
__rk = _serde::export::Some(_serde::private::de::TagOrContentField::Content);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__rk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Step through remaining keys, looking for duplicates of previously-seen keys.
|
||||||
|
/// When unknown fields are denied, any key that isn't a duplicate will at this
|
||||||
|
/// point immediately produce an error.
|
||||||
|
let visit_remaining_keys = quote! {
|
||||||
|
match #next_relevant_key {
|
||||||
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
||||||
_serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag))
|
_serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag))
|
||||||
}
|
}
|
||||||
@@ -895,14 +942,14 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
fn visit_map<__A>(self, mut __map: __A) -> _serde::export::Result<Self::Value, __A::Error>
|
fn visit_map<__A>(self, mut __map: __A) -> _serde::export::Result<Self::Value, __A::Error>
|
||||||
where __A: _serde::de::MapAccess<'de>
|
where __A: _serde::de::MapAccess<'de>
|
||||||
{
|
{
|
||||||
// Visit the first key.
|
// Visit the first relevant key.
|
||||||
match try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) {
|
match #next_relevant_key {
|
||||||
// First key is the tag.
|
// First key is the tag.
|
||||||
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
||||||
// Parse the tag.
|
// Parse the tag.
|
||||||
let __field = try!(_serde::de::MapAccess::next_value(&mut __map));
|
let __field = try!(_serde::de::MapAccess::next_value(&mut __map));
|
||||||
// Visit the second key.
|
// Visit the second key.
|
||||||
match try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) {
|
match #next_relevant_key {
|
||||||
// Second key is a duplicate of the tag.
|
// Second key is a duplicate of the tag.
|
||||||
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
||||||
_serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag))
|
_serde::export::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag))
|
||||||
@@ -915,8 +962,8 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
marker: _serde::export::PhantomData,
|
marker: _serde::export::PhantomData,
|
||||||
lifetime: _serde::export::PhantomData,
|
lifetime: _serde::export::PhantomData,
|
||||||
}));
|
}));
|
||||||
// Visit the third key, hopefully there isn't one.
|
// Visit remaining keys, looking for duplicates.
|
||||||
#visit_third_key
|
#visit_remaining_keys
|
||||||
}
|
}
|
||||||
// There is no second key; might be okay if the we have a unit variant.
|
// There is no second key; might be okay if the we have a unit variant.
|
||||||
_serde::export::None => #missing_content
|
_serde::export::None => #missing_content
|
||||||
@@ -927,7 +974,7 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
// Buffer up the content.
|
// Buffer up the content.
|
||||||
let __content = try!(_serde::de::MapAccess::next_value::<_serde::private::de::Content>(&mut __map));
|
let __content = try!(_serde::de::MapAccess::next_value::<_serde::private::de::Content>(&mut __map));
|
||||||
// Visit the second key.
|
// Visit the second key.
|
||||||
match try!(_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)) {
|
match #next_relevant_key {
|
||||||
// Second key is the tag.
|
// Second key is the tag.
|
||||||
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
|
||||||
let __deserializer = _serde::private::de::ContentDeserializer::<__A::Error>::new(__content);
|
let __deserializer = _serde::private::de::ContentDeserializer::<__A::Error>::new(__content);
|
||||||
@@ -936,8 +983,8 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
// Deserialize the buffered content now that we know the variant.
|
// Deserialize the buffered content now that we know the variant.
|
||||||
#(#variant_arms)*
|
#(#variant_arms)*
|
||||||
});
|
});
|
||||||
// Visit the third key, hopefully there isn't one.
|
// Visit remaining keys, looking for duplicates.
|
||||||
#visit_third_key
|
#visit_remaining_keys
|
||||||
}
|
}
|
||||||
// Second key is a duplicate of the content.
|
// Second key is a duplicate of the content.
|
||||||
_serde::export::Some(_serde::private::de::TagOrContentField::Content) => {
|
_serde::export::Some(_serde::private::de::TagOrContentField::Content) => {
|
||||||
|
|||||||
@@ -16,7 +16,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.0")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.4")]
|
||||||
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ pub enum Style {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Container<'a> {
|
impl<'a> Container<'a> {
|
||||||
pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Container<'a> {
|
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> {
|
||||||
let attrs = attr::Container::from_ast(cx, item);
|
let attrs = attr::Container::from_ast(cx, item);
|
||||||
|
|
||||||
let mut body = match item.body {
|
let mut body = match item.body {
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ pub enum Identifier {
|
|||||||
|
|
||||||
impl Container {
|
impl Container {
|
||||||
/// Extract out the `#[serde(...)]` attributes from an item.
|
/// Extract out the `#[serde(...)]` attributes from an item.
|
||||||
pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self {
|
pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self {
|
||||||
let mut ser_name = Attr::none(cx, "rename");
|
let mut ser_name = Attr::none(cx, "rename");
|
||||||
let mut de_name = Attr::none(cx, "rename");
|
let mut de_name = Attr::none(cx, "rename");
|
||||||
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
|
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
|
||||||
@@ -421,7 +421,7 @@ impl Container {
|
|||||||
|
|
||||||
fn decide_tag(
|
fn decide_tag(
|
||||||
cx: &Ctxt,
|
cx: &Ctxt,
|
||||||
item: &syn::MacroInput,
|
item: &syn::DeriveInput,
|
||||||
untagged: BoolAttr,
|
untagged: BoolAttr,
|
||||||
internal_tag: Attr<String>,
|
internal_tag: Attr<String>,
|
||||||
content: Attr<String>,
|
content: Attr<String>,
|
||||||
@@ -477,7 +477,7 @@ fn decide_tag(
|
|||||||
|
|
||||||
fn decide_identifier(
|
fn decide_identifier(
|
||||||
cx: &Ctxt,
|
cx: &Ctxt,
|
||||||
item: &syn::MacroInput,
|
item: &syn::DeriveInput,
|
||||||
field_identifier: BoolAttr,
|
field_identifier: BoolAttr,
|
||||||
variant_identifier: BoolAttr,
|
variant_identifier: BoolAttr,
|
||||||
) -> Identifier {
|
) -> Identifier {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_test"
|
name = "serde_test"
|
||||||
version = "1.0.0" # remember to update html_root_url
|
version = "1.0.4" # 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.0")]
|
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.4")]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ extern crate serde_derive;
|
|||||||
|
|
||||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||||
use std::net;
|
use std::net;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::ffi::{CString, OsString};
|
use std::ffi::{CString, OsString};
|
||||||
@@ -710,6 +710,11 @@ declare_tests! {
|
|||||||
"1.2.3.4:1234".parse::<net::SocketAddrV4>().unwrap() => &[Token::Str("1.2.3.4:1234")],
|
"1.2.3.4:1234".parse::<net::SocketAddrV4>().unwrap() => &[Token::Str("1.2.3.4:1234")],
|
||||||
"[::1]:1234".parse::<net::SocketAddrV6>().unwrap() => &[Token::Str("[::1]:1234")],
|
"[::1]:1234".parse::<net::SocketAddrV6>().unwrap() => &[Token::Str("[::1]:1234")],
|
||||||
}
|
}
|
||||||
|
test_path {
|
||||||
|
Path::new("/usr/local/lib") => &[
|
||||||
|
Token::BorrowedStr("/usr/local/lib"),
|
||||||
|
],
|
||||||
|
}
|
||||||
test_path_buf {
|
test_path_buf {
|
||||||
PathBuf::from("/usr/local/lib") => &[
|
PathBuf::from("/usr/local/lib") => &[
|
||||||
Token::String("/usr/local/lib"),
|
Token::String("/usr/local/lib"),
|
||||||
|
|||||||
@@ -695,6 +695,30 @@ fn test_internally_tagged_enum() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_internally_tagged_borrow() {
|
||||||
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum Input<'a> {
|
||||||
|
Package { name: &'a str },
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_tokens(
|
||||||
|
&Input::Package { name: "borrowed" },
|
||||||
|
&[
|
||||||
|
Token::Struct { name: "Input", len: 2 },
|
||||||
|
|
||||||
|
Token::BorrowedStr("type"),
|
||||||
|
Token::BorrowedStr("Package"),
|
||||||
|
|
||||||
|
Token::BorrowedStr("name"),
|
||||||
|
Token::BorrowedStr("borrowed"),
|
||||||
|
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_adjacently_tagged_enum() {
|
fn test_adjacently_tagged_enum() {
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@@ -751,6 +775,31 @@ fn test_adjacently_tagged_enum() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// unit with excess content (f, g, h)
|
||||||
|
assert_de_tokens(
|
||||||
|
&AdjacentlyTagged::Unit::<u8>,
|
||||||
|
&[
|
||||||
|
Token::Struct { name: "AdjacentlyTagged", len: 3 },
|
||||||
|
|
||||||
|
Token::Str("f"),
|
||||||
|
Token::Unit,
|
||||||
|
|
||||||
|
Token::Str("t"),
|
||||||
|
Token::Str("Unit"),
|
||||||
|
|
||||||
|
Token::Str("g"),
|
||||||
|
Token::Unit,
|
||||||
|
|
||||||
|
Token::Str("c"),
|
||||||
|
Token::Unit,
|
||||||
|
|
||||||
|
Token::Str("h"),
|
||||||
|
Token::Unit,
|
||||||
|
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
// newtype with tag first
|
// newtype with tag first
|
||||||
assert_tokens(
|
assert_tokens(
|
||||||
&AdjacentlyTagged::Newtype::<u8>(1),
|
&AdjacentlyTagged::Newtype::<u8>(1),
|
||||||
@@ -860,6 +909,66 @@ fn test_adjacently_tagged_enum() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_adjacently_tagged_enum_deny_unknown_fields() {
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
#[serde(tag = "t", content = "c", deny_unknown_fields)]
|
||||||
|
enum AdjacentlyTagged {
|
||||||
|
Unit,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&AdjacentlyTagged::Unit,
|
||||||
|
&[
|
||||||
|
Token::Struct { name: "AdjacentlyTagged", len: 2},
|
||||||
|
|
||||||
|
Token::Str("t"),
|
||||||
|
Token::Str("Unit"),
|
||||||
|
|
||||||
|
Token::Str("c"),
|
||||||
|
Token::Unit,
|
||||||
|
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||||
|
&[
|
||||||
|
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
||||||
|
|
||||||
|
Token::Str("t"),
|
||||||
|
Token::Str("Unit"),
|
||||||
|
|
||||||
|
Token::Str("c"),
|
||||||
|
Token::Unit,
|
||||||
|
|
||||||
|
Token::Str("h"),
|
||||||
|
],
|
||||||
|
r#"invalid value: string "h", expected "t" or "c""#
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||||
|
&[
|
||||||
|
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
||||||
|
|
||||||
|
Token::Str("h"),
|
||||||
|
],
|
||||||
|
r#"invalid value: string "h", expected "t" or "c""#
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<AdjacentlyTagged>(
|
||||||
|
&[
|
||||||
|
Token::Struct { name: "AdjacentlyTagged", len: 3},
|
||||||
|
|
||||||
|
Token::Str("c"),
|
||||||
|
Token::Unit,
|
||||||
|
|
||||||
|
Token::Str("h"),
|
||||||
|
],
|
||||||
|
r#"invalid value: string "h", expected "t" or "c""#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_enum_in_internally_tagged_enum() {
|
fn test_enum_in_internally_tagged_enum() {
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
|||||||
Reference in New Issue
Block a user