Compare commits

...

42 Commits

Author SHA1 Message Date
David Tolnay 9ecb0839de Release 1.0.9 2017-06-29 20:21:29 -07:00
David Tolnay 8a4c116812 Merge pull request #971 from serde-rs/remotede
Fix deserializer bounds on remote derive
2017-06-29 20:19:36 -07:00
David Tolnay 1d3e921ba6 Fix deserializer bounds on remote derive 2017-06-29 20:12:44 -07:00
David Tolnay 4fdba725fe Revert "Support deserialization of struct keys from integers"
This is not as useful as expected because the Serializer does not know the real
index of each struct field being serialized. The best it can do is keep a
counter, which goes wrong if fields are conditionally skipped.

This reverts commit eec7101894.
2017-06-18 09:11:21 -07:00
David Tolnay 75eed8cdde Merge pull request #958 from serde-rs/unused
Fix unused seq and map macros
2017-06-17 19:14:39 -07:00
David Tolnay 6801a13650 Fix unused seq and map macros 2017-06-17 19:01:12 -07:00
David Tolnay 25ab84d4b9 Merge pull request #957 from serde-rs/alloc
Merge crate `collections` into `alloc`
2017-06-17 18:59:43 -07:00
David Tolnay e43d3f3e4f Merge crate collections into alloc 2017-06-17 18:35:56 -07:00
David Tolnay b37d47c987 Merge pull request #956 from sfackler/int-field
Support deserialization of struct keys from integers
2017-06-17 18:26:45 -07:00
Steven Fackler eec7101894 Support deserialization of struct keys from integers
serde-cbor supports a "packed" serialization flag which causes keys to
be serialized as their indices, but the deserializer currently has to
hardcode support for this format. We can simply support deserialization
of struct keys from integers as we already do for enum variants.
2017-06-17 18:12:07 -07:00
David Tolnay fd3d1396d3 Release 1.0.8 2017-05-24 00:17:27 -07:00
David Tolnay c47b4c8e0b Release 1.0.7 2017-05-19 17:00:31 -07:00
David Tolnay 2d793b82f6 Merge pull request #940 from BurntSushi/ag-deser-borrowed
add borrowed value deserializers
2017-05-19 16:59:55 -07:00
Andrew Gallant 237be46e29 add borrowed value deserializers
This adds two new types to the `de::value` module,
`BorrowedStrDeserializer` and `BorrowedBytesDeserializer`. A
`BorrowedStrDeserializer` is just like `StrDeserializer`, except the
lifetime of the string is tied to the lifetime of the deserializer. This
can be useful when, for example, deserializing into a
`HashMap<&str, &str>` when the keys/values are tied to the deserializer
itself.

The `BorrowedBytesDeserializer` has no analog, but it's the same as
`BorrowedStrDeserialize` except for `&[u8]` instead of `&str`.
2017-05-19 19:55:34 -04:00
David Tolnay 3d7aad1e7b Release 1.0.6 2017-05-17 08:20:54 -07:00
David Tolnay e792874369 Merge pull request #935 from spikefoo/combined-skip
Add a combined skip attribute
2017-05-16 09:13:49 -07:00
spikefoo 1669c69714 Add a combined #serde[(skip)] field attribute 2017-05-16 12:33:26 +03:00
David Tolnay 4d5e450054 Release 1.0.5 2017-05-14 12:53:48 -07:00
David Tolnay 26b22e647d Merge pull request #933 from serde-rs/contentstr
Fix internally tagged struct variant containing unit variant containing borrowed string
2017-05-14 12:53:07 -07:00
David Tolnay cda1fc46b0 Fix internally tagged struct variant containing unit variant containing borrowed string 2017-05-14 12:39:42 -07:00
David Tolnay c68b959696 Release 1.0.4 2017-05-10 20:05:22 -07:00
David Tolnay eab80172e4 Merge pull request #926 from serde-rs/borrow
Support borrowing within internally tagged enum
2017-05-10 20:04:36 -07:00
David Tolnay c1259fbc87 Support borrowing within internally tagged enum 2017-05-10 19:56:05 -07:00
David Tolnay 58e30eaee4 Release 1.0.3 2017-05-10 10:15:39 -07:00
David Tolnay bafa941004 Merge pull request #924 from pshc/deserialize-borrowed-path
impl Deserialize for &'a Path
2017-05-10 10:14:25 -07:00
Paul Collier f347b2d363 impl Deserialize for &'a Path 2017-05-10 13:03:03 -04:00
David Tolnay 3f9fc49cca Merge pull request #922 from serde-rs/nonzero
Removed Deref impl for NonZero
2017-05-09 19:58:17 -07:00
David Tolnay c913527944 Removed Deref impl for NonZero 2017-05-09 19:48:54 -07:00
David Tolnay 8fafc7420c Release 1.0.2 2017-04-27 12:32:30 -07:00
David Tolnay bea1c5b0f5 Remove trailing whitespace 2017-04-27 12:31:13 -07:00
David Tolnay aa37caf216 Merge pull request #905 from TedDriggs/adjacent_tag_enums
Fix #816 - adjacently-tagged enums honor deny_unknown_fields
2017-04-27 12:27:31 -07:00
Ted Driggs 2440b59aae Address feedback on PR #905
* Added error test when deny_unknown_fields enabled
* Fixed next_relevant_key to use absolute paths
2017-04-27 12:21:32 -07:00
Ted Driggs 873cfbe9ab Fix #816 - adjacently-tagged enums honor deny_unknown_fields 2017-04-27 11:24:09 -07:00
David Tolnay c96efcb87a Merge pull request #900 from SuperFluffy/macro_to_derive_input
Replace deprecated MacroInput; completes c52e131
2017-04-25 08:10:26 -07:00
Richard Janis Goldschmidt b53026a21b Replace deprecated MacroInput; completes c52e13 2017-04-25 11:08:56 +02:00
David Tolnay c7901e532e Release 1.0.1 2017-04-23 16:40:56 -07:00
David Tolnay 2af0701be6 Merge tag 'v0.9.15' into 'origin/master' 2017-04-23 16:39:32 -07:00
David Tolnay ae79451b7a Release 0.9.15 2017-04-23 16:37:43 -07:00
David Tolnay b220f264a5 Merge pull request #898 from SimonSapin/z-is-dead
Remove usage of unstable core::num::Zero, which was removed upstream.
2017-04-23 16:35:57 -07:00
David Tolnay 1a2b3815ef Merge pull request #899 from SimonSapin/z-is-dead-in-0.9-too
Remove usage of unstable core::num::Zero, which was removed upstream.
2017-04-23 16:34:06 -07:00
Simon Sapin 6fbf40b83c Remove usage of unstable core::num::Zero, which was removed upstream.
https://github.com/rust-lang/rust/pull/41437
2017-04-24 08:29:38 +09:00
Simon Sapin 1d6ecf3c2c Remove usage of unstable core::num::Zero, which was removed upstream.
https://github.com/rust-lang/rust/pull/41437

Backport of https://github.com/serde-rs/serde/pull/898 to 0.9.x
2017-04-24 08:25:08 +09:00
24 changed files with 762 additions and 252 deletions
+4 -11
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.0" # remember to update html_root_url version = "1.0.9" # 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"
@@ -48,22 +48,15 @@ std = []
# https://github.com/serde-rs/serde/issues/812 # https://github.com/serde-rs/serde/issues/812
unstable = [] unstable = []
# Provide impls for types that require memory allocation like Box<T> and Rc<T>. # Provide impls for types in the Rust core allocation and collections library
# This is a subset of std but may be enabled without depending on all of std. # including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may
# be enabled without depending on all of std.
# #
# Requires a dependency on the unstable core allocation library: # Requires a dependency on the unstable core allocation library:
# #
# https://doc.rust-lang.org/alloc/ # https://doc.rust-lang.org/alloc/
alloc = ["unstable"] alloc = ["unstable"]
# Provide impls for collection types like String and Cow<T>. This is a subset of
# std but may be enabled without depending on all of std.
#
# Requires a dependency on the unstable collections library:
#
# https://doc.rust-lang.org/collections/
collections = ["alloc"]
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types # Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
# does not preserve identity and may result in multiple copies of the same data. # does not preserve identity and may result in multiple copies of the same data.
# Be sure that this is what you want before enabling this feature. # Be sure that this is what you want before enabling this feature.
+63 -23
View File
@@ -11,12 +11,12 @@ use lib::*;
use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess,
Visitor}; Visitor};
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::MapAccess; use de::MapAccess;
use de::from_primitive::FromPrimitive; use de::from_primitive::FromPrimitive;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
use private::de::size_hint; use private::de::size_hint;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -208,10 +208,10 @@ impl<'de> Deserialize<'de> for char {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
struct StringVisitor; struct StringVisitor;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Visitor<'de> for StringVisitor { impl<'de> Visitor<'de> for StringVisitor {
type Value = String; type Value = String;
@@ -254,7 +254,7 @@ impl<'de> Visitor<'de> for StringVisitor {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Deserialize<'de> for String { impl<'de> Deserialize<'de> for String {
fn deserialize<D>(deserializer: D) -> Result<String, D::Error> fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
where where
@@ -497,7 +497,7 @@ impl<'de, T> Deserialize<'de> for PhantomData<T> {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! seq_impl { macro_rules! seq_impl {
( (
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
@@ -552,7 +552,7 @@ macro_rules! seq_impl {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
BinaryHeap<T: Ord>, BinaryHeap<T: Ord>,
seq, seq,
@@ -560,7 +560,7 @@ seq_impl!(
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
BinaryHeap::push); BinaryHeap::push);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
BTreeSet<T: Eq + Ord>, BTreeSet<T: Eq + Ord>,
seq, seq,
@@ -568,7 +568,7 @@ seq_impl!(
BTreeSet::new(), BTreeSet::new(),
BTreeSet::insert); BTreeSet::insert);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
LinkedList<T>, LinkedList<T>,
seq, seq,
@@ -584,7 +584,7 @@ seq_impl!(
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
HashSet::insert); HashSet::insert);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
Vec<T>, Vec<T>,
seq, seq,
@@ -592,7 +592,7 @@ seq_impl!(
Vec::with_capacity(size_hint::cautious(seq.size_hint())), Vec::with_capacity(size_hint::cautious(seq.size_hint())),
Vec::push); Vec::push);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
VecDeque<T>, VecDeque<T>,
seq, seq,
@@ -790,7 +790,7 @@ tuple_impls! {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! map_impl { macro_rules! map_impl {
( (
$ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >, $ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
@@ -846,7 +846,7 @@ macro_rules! map_impl {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
map_impl!( map_impl!(
BTreeMap<K: Ord, V>, BTreeMap<K: Ord, V>,
map, map,
@@ -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;
@@ -1072,7 +1110,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, T> Deserialize<'de> for Box<[T]> impl<'de, T> Deserialize<'de> for Box<[T]>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
@@ -1085,7 +1123,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Deserialize<'de> for Box<str> { impl<'de> Deserialize<'de> for Box<str> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -1121,7 +1159,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
where where
T: ToOwned, T: ToOwned,
@@ -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)) }
} }
} }
+2 -2
View File
@@ -1262,7 +1262,7 @@ pub trait Visitor<'de>: Sized {
/// The default implementation forwards to `visit_str` and then drops the /// The default implementation forwards to `visit_str` and then drops the
/// `String`. /// `String`.
#[inline] #[inline]
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn visit_string<E>(self, v: String) -> Result<Self::Value, E> fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where where
E: Error, E: Error,
@@ -1321,7 +1321,7 @@ pub trait Visitor<'de>: Sized {
/// ///
/// The default implementation forwards to `visit_bytes` and then drops the /// The default implementation forwards to `visit_bytes` and then drops the
/// `Vec<u8>`. /// `Vec<u8>`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where where
E: Error, E: Error,
+126 -17
View File
@@ -51,13 +51,13 @@ pub struct Error {
err: ErrorImpl, err: ErrorImpl,
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
type ErrorImpl = Box<str>; type ErrorImpl = Box<str>;
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
type ErrorImpl = (); type ErrorImpl = ();
impl de::Error for Error { impl de::Error for Error {
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn custom<T>(msg: T) -> Self fn custom<T>(msg: T) -> Self
where where
T: Display, T: Display,
@@ -65,7 +65,7 @@ impl de::Error for Error {
Error { err: msg.to_string().into_boxed_str() } Error { err: msg.to_string().into_boxed_str() }
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn custom<T>(msg: T) -> Self fn custom<T>(msg: T) -> Self
where where
T: Display, T: Display,
@@ -85,12 +85,12 @@ impl ser::Error for Error {
} }
impl Display for Error { impl Display for Error {
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(&self.err) formatter.write_str(&self.err)
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str("Serde deserialization error") formatter.write_str("Serde deserialization error")
} }
@@ -355,15 +355,84 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `&str` with a lifetime tied to another
/// deserializer.
#[derive(Clone, Debug)]
pub struct BorrowedStrDeserializer<'de, E> {
value: &'de str,
marker: PhantomData<E>,
}
impl<'de, E> BorrowedStrDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given string.
pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> {
BorrowedStrDeserializer {
value: value,
marker: PhantomData,
}
}
}
impl<'de, E> de::Deserializer<'de> for BorrowedStrDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_borrowed_str(self.value)
}
fn deserialize_enum<V>(
self,
name: &str,
variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
let _ = name;
let _ = variants;
visitor.visit_enum(self)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct identifier ignored_any
}
}
impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
type Variant = private::UnitOnly<E>;
fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
where
T: de::DeserializeSeed<'de>,
{
seed.deserialize(self).map(private::unit_only)
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `String`. /// A deserializer holding a `String`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct StringDeserializer<E> { pub struct StringDeserializer<E> {
value: String, value: String,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, E> IntoDeserializer<'de, E> for String impl<'de, E> IntoDeserializer<'de, E> for String
where where
E: de::Error, E: de::Error,
@@ -378,7 +447,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, E> de::Deserializer<'de> for StringDeserializer<E> impl<'de, E> de::Deserializer<'de> for StringDeserializer<E>
where where
E: de::Error, E: de::Error,
@@ -413,7 +482,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer<E> impl<'de, 'a, E> de::EnumAccess<'de> for StringDeserializer<E>
where where
E: de::Error, E: de::Error,
@@ -432,14 +501,14 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `Cow<str>`. /// A deserializer holding a `Cow<str>`.
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CowStrDeserializer<'a, E> { pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>, value: Cow<'a, str>,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
where where
E: de::Error, E: de::Error,
@@ -454,7 +523,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E>
where where
E: de::Error, E: de::Error,
@@ -492,7 +561,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E> impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E>
where where
E: de::Error, E: de::Error,
@@ -510,6 +579,46 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `&[u8]` with a lifetime tied to another
/// deserializer.
#[derive(Clone, Debug)]
pub struct BorrowedBytesDeserializer<'de, E> {
value: &'de [u8],
marker: PhantomData<E>,
}
impl<'de, E> BorrowedBytesDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given byte slice.
pub fn new(value: &'de [u8]) -> BorrowedBytesDeserializer<'de, E> {
BorrowedBytesDeserializer {
value: value,
marker: PhantomData,
}
}
}
impl<'de, E> de::Deserializer<'de> for BorrowedBytesDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_borrowed_bytes(self.value)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct
map struct identifier ignored_any enum
}
}
////////////////////////////////////////////////////////////////////////////////
/// A deserializer that iterates over a sequence. /// A deserializer that iterates over a sequence.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SeqDeserializer<I, E> { pub struct SeqDeserializer<I, E> {
@@ -618,7 +727,7 @@ impl Expected for ExpectedInSeq {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T> impl<'de, T, E> IntoDeserializer<'de, E> for Vec<T>
where where
T: IntoDeserializer<'de, E>, T: IntoDeserializer<'de, E>,
@@ -631,7 +740,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T> impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet<T>
where where
T: IntoDeserializer<'de, E> + Eq + Ord, T: IntoDeserializer<'de, E> + Eq + Ord,
@@ -1036,7 +1145,7 @@ impl Expected for ExpectedInMap {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V> impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap<K, V>
where where
K: IntoDeserializer<'de, E> + Eq + Ord, K: IntoDeserializer<'de, E> + Eq + Ord,
+2 -2
View File
@@ -19,7 +19,7 @@ pub use self::string::from_utf8_lossy;
mod string { mod string {
use lib::*; use lib::*;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> { pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
String::from_utf8_lossy(bytes) String::from_utf8_lossy(bytes)
} }
@@ -31,7 +31,7 @@ mod string {
// //
// so it is okay for the return type to be different from the std case as long // so it is okay for the return type to be different from the std case as long
// as the above works. // as the above works.
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
pub fn from_utf8_lossy(bytes: &[u8]) -> &str { pub fn from_utf8_lossy(bytes: &[u8]) -> &str {
// Three unicode replacement characters if it fails. They look like a // Three unicode replacement characters if it fails. They look like a
// white-on-black question mark. The user will recognize it as invalid // white-on-black question mark. The user will recognize it as invalid
+14 -21
View File
@@ -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.9")]
// 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,10 +88,9 @@
// 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))]
// Whitelisted clippy lints. // Whitelisted clippy lints.
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))] #![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]
@@ -104,18 +103,15 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "collections")]
extern crate collections;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
#[cfg(all(feature = "unstable", feature = "std"))] #[cfg(all(feature = "unstable", feature = "std"))]
extern crate core; extern crate core;
/// A facade around all the types we need from the `std`, `core`, `alloc`, and /// A facade around all the types we need from the `std`, `core`, and `alloc`
/// `collections` crates. This avoids elaborate import wrangling having to /// crates. This avoids elaborate import wrangling having to happen in every
/// happen in every module. /// module.
mod lib { mod lib {
mod core { mod core {
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -124,7 +120,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};
@@ -140,18 +136,18 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::borrow::{Cow, ToOwned}; pub use std::borrow::{Cow, ToOwned};
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use collections::borrow::{Cow, ToOwned}; pub use alloc::borrow::{Cow, ToOwned};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::string::String; pub use std::string::String;
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use collections::string::{String, ToString}; pub use alloc::string::{String, ToString};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::vec::Vec; pub use std::vec::Vec;
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use collections::vec::Vec; pub use alloc::vec::Vec;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::boxed::Box; pub use std::boxed::Box;
@@ -170,8 +166,8 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque}; pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(all(feature = "collections", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque}; pub use alloc::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::{error, net}; pub use std::{error, net};
@@ -193,9 +189,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;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
+227 -120
View File
@@ -10,12 +10,13 @@ use lib::*;
use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor}; use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor};
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::Unexpected; use de::Unexpected;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
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`,
@@ -58,7 +59,7 @@ where
Deserialize::deserialize(deserializer) Deserialize::deserialize(deserializer)
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub fn borrow_cow_str<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, str>, D::Error> pub fn borrow_cow_str<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, str>, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
@@ -127,7 +128,7 @@ where
deserializer.deserialize_str(CowStrVisitor) deserializer.deserialize_str(CowStrVisitor)
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, [u8]>, D::Error> pub fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, [u8]>, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
@@ -209,7 +210,7 @@ pub mod size_hint {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
mod content { mod content {
// This module is private and nothing here should be used outside of // This module is private and nothing here should be used outside of
// generated code. // generated code.
@@ -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),
} }
} }
@@ -977,7 +1082,7 @@ mod content {
} }
(variant, Some(value)) (variant, Some(value))
} }
Content::String(variant) => (Content::String(variant), None), s @ Content::String(_) | s @ Content::Str(_) => (s, None),
other => { other => {
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),); return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),);
} }
@@ -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),
} }
} }
@@ -1369,7 +1476,7 @@ mod content {
} }
(variant, Some(value)) (variant, Some(value))
} }
ref s @ Content::String(_) => (s, None), ref s @ Content::String(_) | ref s @ Content::Str(_) => (s, None),
ref other => { ref other => {
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),); return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),);
} }
@@ -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 -13
View File
@@ -10,7 +10,7 @@ use lib::*;
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible}; use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue}; use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
/// Used to check that serde(getter) attributes return the expected type. /// Used to check that serde(getter) attributes return the expected type.
@@ -64,7 +64,7 @@ enum Unsupported {
Sequence, Sequence,
Tuple, Tuple,
TupleStruct, TupleStruct,
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
Enum, Enum,
} }
@@ -83,7 +83,7 @@ impl Display for Unsupported {
Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Sequence => formatter.write_str("a sequence"),
Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::Tuple => formatter.write_str("a tuple"),
Unsupported::TupleStruct => formatter.write_str("a tuple struct"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
Unsupported::Enum => formatter.write_str("an enum"), Unsupported::Enum => formatter.write_str("an enum"),
} }
} }
@@ -117,14 +117,14 @@ where
type SerializeMap = S::SerializeMap; type SerializeMap = S::SerializeMap;
type SerializeStruct = S::SerializeStruct; type SerializeStruct = S::SerializeStruct;
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
type SerializeTupleVariant = Impossible<S::Ok, S::Error>; type SerializeTupleVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>; type SerializeTupleVariant = SerializeTupleVariantAsMapValue<S::SerializeMap>;
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
type SerializeStructVariant = Impossible<S::Ok, S::Error>; type SerializeStructVariant = Impossible<S::Ok, S::Error>;
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>; type SerializeStructVariant = SerializeStructVariantAsMapValue<S::SerializeMap>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> { fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
@@ -257,7 +257,7 @@ where
Err(self.bad_type(Unsupported::TupleStruct)) Err(self.bad_type(Unsupported::TupleStruct))
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn serialize_tuple_variant( fn serialize_tuple_variant(
self, self,
_: &'static str, _: &'static str,
@@ -270,7 +270,7 @@ where
Err(self.bad_type(Unsupported::Enum)) Err(self.bad_type(Unsupported::Enum))
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn serialize_tuple_variant( fn serialize_tuple_variant(
self, self,
_: &'static str, _: &'static str,
@@ -300,7 +300,7 @@ where
Ok(state) Ok(state)
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn serialize_struct_variant( fn serialize_struct_variant(
self, self,
_: &'static str, _: &'static str,
@@ -313,7 +313,7 @@ where
Err(self.bad_type(Unsupported::Enum)) Err(self.bad_type(Unsupported::Enum))
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn serialize_struct_variant( fn serialize_struct_variant(
self, self,
_: &'static str, _: &'static str,
@@ -327,7 +327,7 @@ where
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),) Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),)
} }
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error> fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
where where
T: Display, T: Display,
@@ -363,7 +363,7 @@ impl Display for Error {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
mod content { mod content {
use lib::*; use lib::*;
+23 -11
View File
@@ -56,7 +56,7 @@ impl Serialize for str {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl Serialize for String { impl Serialize for String {
#[inline] #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -177,6 +177,7 @@ where
} }
} }
#[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! seq_impl { macro_rules! seq_impl {
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => { ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*> impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
@@ -195,22 +196,22 @@ macro_rules! seq_impl {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(BinaryHeap<T: Ord>); seq_impl!(BinaryHeap<T: Ord>);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(BTreeSet<T: Ord>); seq_impl!(BTreeSet<T: Ord>);
#[cfg(feature = "std")] #[cfg(feature = "std")]
seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>); seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(LinkedList<T>); seq_impl!(LinkedList<T>);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(Vec<T>); seq_impl!(Vec<T>);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(VecDeque<T>); seq_impl!(VecDeque<T>);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -290,6 +291,7 @@ tuple_impls! {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! map_impl { macro_rules! map_impl {
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*> impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
@@ -309,7 +311,7 @@ macro_rules! map_impl {
} }
} }
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
map_impl!(BTreeMap<K: Ord, V>); map_impl!(BTreeMap<K: Ord, V>);
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -343,14 +345,24 @@ deref_impl!(<T> Serialize for Rc<T> where T: Serialize);
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
deref_impl!(<T> Serialize for Arc<T> where T: Serialize); deref_impl!(<T> Serialize for Arc<T> where T: Serialize);
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
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,
+2 -2
View File
@@ -1321,7 +1321,7 @@ pub trait Serializer: Sized {
/// ///
/// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html /// [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
/// [`serialize_str`]: #tymethod.serialize_str /// [`serialize_str`]: #tymethod.serialize_str
#[cfg(any(feature = "std", feature = "collections"))] #[cfg(any(feature = "std", feature = "alloc"))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where where
T: Display, T: Display,
@@ -1358,7 +1358,7 @@ pub trait Serializer: Sized {
/// } /// }
/// } /// }
/// ``` /// ```
#[cfg(not(any(feature = "std", feature = "collections")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
where where
T: Display; T: Display;
+2 -2
View File
@@ -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.9" # 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)]"
@@ -20,5 +20,5 @@ proc-macro = true
[dependencies] [dependencies]
quote = "0.3.8" quote = "0.3.8"
serde_derive_internals = { version = "=0.15.0", default-features = false, path = "../serde_derive_internals" } serde_derive_internals = { version = "=0.15.1", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.11", features = ["visit"] } syn = { version = "0.11", features = ["visit"] }
+62 -17
View File
@@ -23,15 +23,14 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
let ident = &cont.ident; let ident = &cont.ident;
let params = Parameters::new(&cont); let params = Parameters::new(&cont);
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident)); let dummy_const = Ident::new(format!("_IMPL_DESERIALIZE_FOR_{}", ident));
let body = Stmts(deserialize_body(&cont, &params)); let body = Stmts(deserialize_body(&cont, &params));
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl();
let de_lifetime = params.de_lifetime_def();
quote! { quote! {
impl #impl_generics #ident #ty_generics #where_clause { impl #de_impl_generics #ident #ty_generics #where_clause {
fn deserialize<#de_lifetime, __D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error> fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
where __D: _serde::Deserializer<'de> where __D: _serde::Deserializer<'de>
{ {
#body #body
@@ -39,7 +38,6 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
} }
} }
} else { } else {
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
quote! { quote! {
#[automatically_derived] #[automatically_derived]
impl #de_impl_generics _serde::Deserialize<'de> for #ident #ty_generics #where_clause { impl #de_impl_generics _serde::Deserialize<'de> for #ident #ty_generics #where_clause {
@@ -795,9 +793,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 +852,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 +940,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 +960,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 +972,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 +981,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) => {
+1 -1
View File
@@ -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.9")]
#![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))]
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive_internals" name = "serde_derive_internals"
version = "0.15.0" # remember to update html_root_url version = "0.15.1" # 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 = "AST representation used by Serde derive macros. Unstable." description = "AST representation used by Serde derive macros. Unstable."
+1 -1
View File
@@ -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 {
+9 -3
View File
@@ -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 {
@@ -719,6 +719,12 @@ impl Field {
skip_deserializing.set_true(); skip_deserializing.set_true();
} }
// Parse `#[serde(skip)]`
MetaItem(Word(ref name)) if name == "skip" => {
skip_serializing.set_true();
skip_deserializing.set_true();
},
// Parse `#[serde(skip_serializing_if = "...")]` // Parse `#[serde(skip_serializing_if = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => { MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) { if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
+1 -1
View File
@@ -6,7 +6,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.15.0")] #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.15.1")]
extern crate syn; extern crate syn;
#[macro_use] #[macro_use]
+1 -1
View File
@@ -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.9" # 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"
+1 -1
View File
@@ -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.9")]
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
+35
View File
@@ -580,6 +580,41 @@ fn test_skip_serializing_struct() {
); );
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct SkipStruct<B>
{
a: i8,
#[serde(skip)]
b: B,
}
#[test]
fn test_skip_struct() {
assert_ser_tokens(
&SkipStruct { a: 1, b: 2 },
&[
Token::Struct { name: "SkipStruct", len: 1 },
Token::Str("a"),
Token::I8(1),
Token::StructEnd,
],
);
assert_de_tokens(
&SkipStruct { a: 1, b: 0 },
&[
Token::Struct { name: "SkipStruct", len: 1 },
Token::Str("a"),
Token::I8(1),
Token::StructEnd,
],
);
}
#[derive(Debug, PartialEq, Serialize)] #[derive(Debug, PartialEq, Serialize)]
enum SkipSerializingEnum<'a, B, C> enum SkipSerializingEnum<'a, B, C>
where where
+6 -1
View File
@@ -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"),
+28
View File
@@ -330,6 +330,34 @@ fn test_gen() {
struct EmptyArray { struct EmptyArray {
empty: [X; 0], empty: [X; 0],
} }
enum Or<A, B> {
A(A),
B(B),
}
#[derive(Serialize, Deserialize)]
#[serde(untagged, remote = "Or")]
enum OrDef<A, B> {
#[allow(dead_code)]
A(A),
#[allow(dead_code)]
B(B),
}
struct Str<'a>(&'a str);
#[derive(Serialize, Deserialize)]
#[serde(remote = "Str")]
struct StrDef<'a>(&'a str);
#[derive(Serialize, Deserialize)]
struct Remote<'a> {
#[serde(with = "OrDef")]
or: Or<u8, bool>,
#[serde(borrow, with = "StrDef")]
s: Str<'a>,
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
+138
View File
@@ -695,6 +695,59 @@ fn test_internally_tagged_enum() {
); );
} }
#[test]
fn test_internally_tagged_struct_variant_containing_unit_variant() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum Level {
Info,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "action")]
pub enum Message {
Log { level: Level },
}
assert_de_tokens(
&Message::Log { level: Level::Info },
&[
Token::Struct { name: "Message", len: 2 },
Token::Str("action"),
Token::Str("Log"),
Token::Str("level"),
Token::BorrowedStr("Info"),
Token::StructEnd,
],
);
}
#[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 +804,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 +938,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)]
-1
View File
@@ -46,7 +46,6 @@ else
channel build channel build
channel build --no-default-features channel build --no-default-features
channel build --no-default-features --features alloc channel build --no-default-features --features alloc
channel build --no-default-features --features collections
channel test --features 'rc unstable' channel test --features 'rc unstable'
cd "$DIR/test_suite/deps" cd "$DIR/test_suite/deps"
channel build channel build