Compare commits

...

49 Commits

Author SHA1 Message Date
David Tolnay b4076f4577 Release 1.0.51 2018-05-08 10:07:45 -07:00
David Tolnay c4181f46be Respect variant skip attribute in inferred bounds 2018-05-07 21:30:00 -07:00
David Tolnay 8c0efc3d77 Add a variant skip attribute 2018-05-07 21:27:34 -07:00
David Tolnay 7e3efaf6c5 Improve error when a 'de lifetime parameter already exists 2018-05-07 21:15:44 -07:00
David Tolnay 12fe42ed45 Support empty adjacently tagged enum 2018-05-07 21:02:42 -07:00
David Tolnay 7cd4f49c76 Release 1.0.50 2018-05-07 13:51:32 -07:00
David Tolnay ff9c85d47f Merge pull request #1252 from serde-rs/precondition
Detect deserialize on a struct ending in dynamically sized slice
2018-05-07 13:50:48 -07:00
David Tolnay 0025ef9aba Detect deserialize on a struct ending in dynamically sized slice 2018-05-07 11:52:59 -07:00
David Tolnay 536bdd77a0 Release 1.0.49 2018-05-07 11:51:15 -07:00
David Tolnay 6993b983d2 Merge pull request #1251 from serde-rs/weak
Add impls for Weak
2018-05-07 11:50:35 -07:00
David Tolnay 4bfeb05f22 Prefer Self and associated types in de impls 2018-05-07 11:36:41 -07:00
David Tolnay 4687c1b52b Test Weak deserialize impls 2018-05-07 11:23:18 -07:00
David Tolnay a58abae193 Test Weak serialize impls 2018-05-07 11:23:17 -07:00
David Tolnay 0bc9c729b3 Add impls for Weak 2018-05-07 11:23:16 -07:00
David Tolnay dc921892be Eliminate map_or(None, f) 2018-05-07 11:23:04 -07:00
David Tolnay 62557731c3 Enable pedantic clippy lints in serde_derive 2018-05-07 11:03:09 -07:00
David Tolnay ab62cd3b28 Eliminate loop that does not loop 2018-05-07 10:46:54 -07:00
David Tolnay 30824e9f61 Release 1.0.48 2018-05-07 10:22:26 -07:00
David Tolnay eecc0870fc Test for pub(restricted) 2018-05-06 23:22:27 -07:00
David Tolnay 6475e73b05 Less horrible logic for missing fields that unconditionally return error 2018-05-06 22:20:35 -07:00
David Tolnay 697234517d Merge pull request #1249 from serde-rs/empty
Fix adjacently tagged empty tuple variant or struct variant
2018-05-06 22:20:27 -07:00
David Tolnay 3cd9d071c2 Fix adjacently tagged empty tuple variant or struct variant 2018-05-06 21:50:40 -07:00
David Tolnay 9dc05c36f0 Release 1.0.47 2018-05-06 21:39:21 -07:00
David Tolnay 972cc06fed Format the flatten tests using rustfmt 0.6.1 2018-05-06 21:38:41 -07:00
David Tolnay 20013464f8 Merge pull request #1248 from serde-rs/flatten
Support flatten in enums
2018-05-06 21:37:32 -07:00
David Tolnay 2009b4da5f Remove old flatten in enum compile-fail test 2018-05-06 21:26:40 -07:00
David Tolnay 0b72c86a35 Add tests for flatten in enums 2018-05-06 21:23:20 -07:00
David Tolnay 94b857057b Support deserializing enums containing flatten 2018-05-06 20:41:02 -07:00
David Tolnay 979df3427b Support serializing enums containing flatten 2018-05-06 20:14:35 -07:00
David Tolnay 978d64993e Allow flatten attribute in enums 2018-05-06 20:14:28 -07:00
David Tolnay 5098609935 Release 1.0.46 2018-05-06 13:44:55 -07:00
David Tolnay 6374467f02 Merge pull request #1245 from serde-rs/flat
Support deserializing a flattened internally tagged enum
2018-05-06 13:43:44 -07:00
David Tolnay 1f9fc61b98 Merge pull request #1246 from serde-rs/internals
Move derive internals into serde_derive crate
2018-05-05 23:58:41 -07:00
David Tolnay 3859f58d9b Move derive internals into serde_derive crate
We can continue to publish serde_derive_internals independently but
serde_derive no longer has a dependency on it. This improves compile
time of serde_derive by 7%.
2018-05-05 23:46:30 -07:00
David Tolnay aac1c65033 Simplify implementation of flattened internally tagged enum
The fact that the tag entry is consumed was only observable if there is
a later flattened map field, at which point the behavior is already
confusing anyway.

    #[derive(Deserialize)]
    struct Example {
        #[serde(flatten)]
        a: InternallyTagged,
        #[serde(flatten)]
        rest: BTreeMap<String, Value>,
    }

Before this simplification the map would receive all the fields of the
internally tagged enum but not its tag, after it receives all the fields
including the tag.
2018-05-05 22:30:46 -07:00
David Tolnay d8120e19bc Support deserializing a flattened internally tagged enum 2018-05-05 21:52:16 -07:00
David Tolnay ed425b3a6f Clean up indentation in VariantAccess doc 2018-05-05 18:40:28 -07:00
David Tolnay d1297deb36 Format where-clauses in serde docs like rustfmt 2018-05-05 18:33:33 -07:00
David Tolnay f263e3fcec Format serde_derive generated where-clauses 2018-05-05 18:24:16 -07:00
David Tolnay 40479336c1 Format serde_test doc where-clauses in the style of rustfmt 2018-05-05 18:20:26 -07:00
David Tolnay 6ca4dd2c4a Add an issue suggestion for documentation improvements 2018-05-05 10:01:54 -07:00
David Tolnay c04c233838 Generalize the help issue type 2018-05-05 10:00:17 -07:00
David Tolnay 175c638fdc Set up some issue templates 2018-05-05 01:45:24 -07:00
David Tolnay 97eff8e875 Format with rustfmt 0.6.1 2018-05-05 00:56:12 -07:00
David Tolnay 47676cdb49 Clean up references to Ident 2018-05-05 00:45:30 -07:00
David Tolnay 93bddb361e Fix toplevel_ref_arg lint 2018-05-05 00:39:26 -07:00
David Tolnay adb1c9540d Remove a layer of wrapping in deserialize_with untagged newtype variant 2018-05-05 00:25:27 -07:00
David Tolnay 0e1d065402 Format with rustfmt 0.6.1 2018-05-05 00:18:21 -07:00
David Tolnay 8c3b52e308 Remove a layer of wrapping in deserialize_with newtype struct 2018-05-05 00:17:00 -07:00
40 changed files with 1281 additions and 444 deletions
+7
View File
@@ -0,0 +1,7 @@
---
name: Problem
about: Something does not seem right
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Feature request
about: Share how Serde could support your use case better
---
@@ -0,0 +1,7 @@
---
name: Documentation
about: Certainly there is room for improvement
---
+7
View File
@@ -0,0 +1,7 @@
---
name: Help or discussion
about: This is the right place
---
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.45" # remember to update html_root_url
version = "1.0.51" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
+10 -5
View File
@@ -45,7 +45,8 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// }
///
/// impl<'de, T> Visitor<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// type Value = T;
///
@@ -54,7 +55,8 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// }
///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
/// where A: SeqAccess<'de>
/// where
/// A: SeqAccess<'de>,
/// {
/// // Skip over the first `n` elements.
/// for i in 0..self.n {
@@ -82,19 +84,22 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// }
///
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// type Value = T;
///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de>
/// where
/// D: Deserializer<'de>,
/// {
/// deserializer.deserialize_seq(self)
/// }
/// }
///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de>
/// # where
/// # D: Deserializer<'de>,
/// # {
/// // Deserialize only the sequence element at index 3 from this deserializer.
/// // The element at index 3 is required to be a string. Elements before and
+111 -72
View File
@@ -8,8 +8,9 @@
use lib::*;
use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess,
Visitor};
use de::{
Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor,
};
#[cfg(any(feature = "std", feature = "alloc"))]
use de::MapAccess;
@@ -31,7 +32,7 @@ impl<'de> Visitor<'de> for UnitVisitor {
formatter.write_str("unit")
}
fn visit_unit<E>(self) -> Result<(), E>
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
@@ -40,7 +41,7 @@ impl<'de> Visitor<'de> for UnitVisitor {
}
impl<'de> Deserialize<'de> for () {
fn deserialize<D>(deserializer: D) -> Result<(), D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -59,7 +60,7 @@ impl<'de> Visitor<'de> for BoolVisitor {
formatter.write_str("a boolean")
}
fn visit_bool<E>(self, v: bool) -> Result<bool, E>
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where
E: Error,
{
@@ -68,7 +69,7 @@ impl<'de> Visitor<'de> for BoolVisitor {
}
impl<'de> Deserialize<'de> for bool {
fn deserialize<D>(deserializer: D) -> Result<bool, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -109,7 +110,7 @@ macro_rules! impl_deserialize_num {
($ty:ident, $method:ident, $($visit:ident),*) => {
impl<'de> Deserialize<'de> for $ty {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -177,7 +178,7 @@ impl<'de> Visitor<'de> for CharVisitor {
}
#[inline]
fn visit_char<E>(self, v: char) -> Result<char, E>
fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
where
E: Error,
{
@@ -185,7 +186,7 @@ impl<'de> Visitor<'de> for CharVisitor {
}
#[inline]
fn visit_str<E>(self, v: &str) -> Result<char, E>
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
@@ -199,7 +200,7 @@ impl<'de> Visitor<'de> for CharVisitor {
impl<'de> Deserialize<'de> for char {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<char, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -222,21 +223,21 @@ impl<'de> Visitor<'de> for StringVisitor {
formatter.write_str("a string")
}
fn visit_str<E>(self, v: &str) -> Result<String, E>
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v.to_owned())
}
fn visit_string<E>(self, v: String) -> Result<String, E>
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
Ok(v)
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<String, E>
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
@@ -246,7 +247,7 @@ impl<'de> Visitor<'de> for StringVisitor {
}
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<String, E>
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
{
@@ -268,7 +269,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
formatter.write_str("a string")
}
fn visit_str<E>(self, v: &str) -> Result<(), E>
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
@@ -277,7 +278,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
Ok(())
}
fn visit_string<E>(self, v: String) -> Result<(), E>
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
@@ -285,7 +286,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
Ok(())
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<(), E>
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
@@ -299,7 +300,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
}
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<(), E>
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
{
@@ -318,7 +319,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Deserialize<'de> for String {
fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -416,7 +417,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
formatter.write_str("byte array")
}
fn visit_seq<A>(self, mut seq: A) -> Result<CString, A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -430,28 +431,28 @@ impl<'de> Visitor<'de> for CStringVisitor {
CString::new(values).map_err(Error::custom)
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<CString, E>
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
CString::new(v).map_err(Error::custom)
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<CString, E>
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
{
CString::new(v).map_err(Error::custom)
}
fn visit_str<E>(self, v: &str) -> Result<CString, E>
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
CString::new(v).map_err(Error::custom)
}
fn visit_string<E>(self, v: String) -> Result<CString, E>
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
@@ -461,7 +462,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for CString {
fn deserialize<D>(deserializer: D) -> Result<CString, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -506,7 +507,7 @@ where
}
#[inline]
fn visit_unit<E>(self) -> Result<Option<T>, E>
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
@@ -514,7 +515,7 @@ where
}
#[inline]
fn visit_none<E>(self) -> Result<Option<T>, E>
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
@@ -522,7 +523,7 @@ where
}
#[inline]
fn visit_some<D>(self, deserializer: D) -> Result<Option<T>, D::Error>
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
@@ -534,7 +535,7 @@ impl<'de, T> Deserialize<'de> for Option<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Option<T>, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -564,7 +565,7 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
}
#[inline]
fn visit_unit<E>(self) -> Result<PhantomData<T>, E>
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: Error,
{
@@ -573,7 +574,7 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
}
impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -658,7 +659,7 @@ macro_rules! seq_impl {
}
#[inline]
fn visit_seq<A>(mut self, mut $access: A) -> Result<(), A::Error>
fn visit_seq<A>(mut self, mut $access: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -770,7 +771,7 @@ impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> {
}
#[inline]
fn visit_seq<A>(self, _: A) -> Result<[T; 0], A::Error>
fn visit_seq<A>(self, _: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -780,7 +781,7 @@ impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> {
// Does not require T: Deserialize<'de>.
impl<'de, T> Deserialize<'de> for [T; 0] {
fn deserialize<D>(deserializer: D) -> Result<[T; 0], D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -802,7 +803,7 @@ macro_rules! array_impls {
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<[T; $len], A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -828,7 +829,7 @@ macro_rules! array_impls {
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -850,7 +851,7 @@ macro_rules! array_impls {
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<[T; $len], D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -910,7 +911,7 @@ macro_rules! tuple_impls {
$(
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -927,7 +928,7 @@ macro_rules! tuple_impls {
#[inline]
#[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -961,7 +962,7 @@ macro_rules! tuple_impls {
#[inline]
#[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -1330,14 +1331,14 @@ impl<'de> Visitor<'de> for PathBufVisitor {
formatter.write_str("path string")
}
fn visit_str<E>(self, v: &str) -> Result<PathBuf, E>
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(From::from(v))
}
fn visit_string<E>(self, v: String) -> Result<PathBuf, E>
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: Error,
{
@@ -1347,7 +1348,7 @@ impl<'de> Visitor<'de> for PathBufVisitor {
#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for PathBuf {
fn deserialize<D>(deserializer: D) -> Result<PathBuf, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -1380,7 +1381,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
}
#[cfg(unix)]
fn visit_enum<A>(self, data: A) -> Result<OsString, A::Error>
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
@@ -1395,7 +1396,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
}
#[cfg(windows)]
fn visit_enum<A>(self, data: A) -> Result<OsString, A::Error>
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
@@ -1413,7 +1414,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
#[cfg(all(feature = "std", any(unix, windows)))]
impl<'de> Deserialize<'de> for OsString {
fn deserialize<D>(deserializer: D) -> Result<OsString, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -1463,7 +1464,7 @@ where
T::Owned: Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Cow<'a, T>, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -1473,6 +1474,44 @@ where
////////////////////////////////////////////////////////////////////////////////
/// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting
/// `Weak<T>` has a reference count of 0 and cannot be upgraded.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<'de, T: ?Sized> Deserialize<'de> for RcWeak<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
try!(Option::<T>::deserialize(deserializer));
Ok(RcWeak::new())
}
}
/// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting
/// `Weak<T>` has a reference count of 0 and cannot be upgraded.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
try!(Option::<T>::deserialize(deserializer));
Ok(ArcWeak::new())
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
macro_rules! box_forwarded_impl {
(
@@ -1524,7 +1563,7 @@ impl<'de, T> Deserialize<'de> for Cell<T>
where
T: Deserialize<'de> + Copy,
{
fn deserialize<D>(deserializer: D) -> Result<Cell<T>, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -1566,7 +1605,7 @@ impl<'de> Deserialize<'de> for Duration {
};
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -1579,7 +1618,7 @@ impl<'de> Deserialize<'de> for Duration {
formatter.write_str("`secs` or `nanos`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
@@ -1590,7 +1629,7 @@ impl<'de> Deserialize<'de> for Duration {
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
@@ -1618,7 +1657,7 @@ impl<'de> Deserialize<'de> for Duration {
formatter.write_str("struct Duration")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -1637,7 +1676,7 @@ impl<'de> Deserialize<'de> for Duration {
Ok(Duration::new(secs, nanos))
}
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error>
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
@@ -1691,7 +1730,7 @@ impl<'de> Deserialize<'de> for SystemTime {
};
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -1704,7 +1743,7 @@ impl<'de> Deserialize<'de> for SystemTime {
formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
@@ -1715,7 +1754,7 @@ impl<'de> Deserialize<'de> for SystemTime {
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
@@ -1743,7 +1782,7 @@ impl<'de> Deserialize<'de> for SystemTime {
formatter.write_str("struct SystemTime")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -1762,7 +1801,7 @@ impl<'de> Deserialize<'de> for SystemTime {
Ok(Duration::new(secs, nanos))
}
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error>
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
@@ -1835,7 +1874,7 @@ where
};
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -1848,7 +1887,7 @@ where
formatter.write_str("`start` or `end`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
@@ -1859,7 +1898,7 @@ where
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
@@ -1892,7 +1931,7 @@ where
formatter.write_str("struct Range")
}
fn visit_seq<A>(self, mut seq: A) -> Result<ops::Range<Idx>, A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
@@ -1911,7 +1950,7 @@ where
Ok(start..end)
}
fn visit_map<A>(self, mut map: A) -> Result<ops::Range<Idx>, A::Error>
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
@@ -1964,7 +2003,7 @@ impl<'de, T> Deserialize<'de> for NonZero<T>
where
T: Deserialize<'de> + Zeroable,
{
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -1981,7 +2020,7 @@ macro_rules! nonzero_integers {
$(
#[cfg(feature = "unstable")]
impl<'de> Deserialize<'de> for $T {
fn deserialize<D>(deserializer: D) -> Result<$T, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -2013,7 +2052,7 @@ where
T: Deserialize<'de>,
E: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Result<T, E>, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -2028,7 +2067,7 @@ where
impl<'de> Deserialize<'de> for Field {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
@@ -2041,7 +2080,7 @@ where
formatter.write_str("`Ok` or `Err`")
}
fn visit_u32<E>(self, value: u32) -> Result<Field, E>
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
where
E: Error,
{
@@ -2055,7 +2094,7 @@ where
}
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
@@ -2066,7 +2105,7 @@ where
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
@@ -2100,7 +2139,7 @@ where
formatter.write_str("enum Result")
}
fn visit_enum<A>(self, data: A) -> Result<Result<T, E>, A::Error>
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
@@ -2124,7 +2163,7 @@ impl<'de, T> Deserialize<'de> for Wrapping<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
+77 -34
View File
@@ -172,7 +172,8 @@ macro_rules! declare_error_trait {
///
/// impl<'de> Deserialize<'de> for IpAddr {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de>
/// where
/// D: Deserializer<'de>,
/// {
/// let s = try!(String::deserialize(deserializer));
/// s.parse().map_err(de::Error::custom)
@@ -306,7 +307,8 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// # }
/// #
/// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
/// where E: de::Error
/// where
/// E: de::Error,
/// {
/// Err(de::Error::invalid_type(Unexpected::Bool(v), &self))
/// }
@@ -430,7 +432,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # }
/// #
/// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
/// where E: de::Error
/// where
/// E: de::Error,
/// {
/// Err(de::Error::invalid_type(Unexpected::Bool(v), &self))
/// }
@@ -443,7 +446,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// # use serde::de::{self, Unexpected};
/// #
/// # fn example<E>() -> Result<(), E>
/// # where E: de::Error
/// # where
/// # E: de::Error,
/// # {
/// # let v = true;
/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer"));
@@ -557,11 +561,13 @@ pub trait Deserialize<'de>: Sized {
/// #
/// # trait Ignore {
/// fn from_str<'a, T>(s: &'a str) -> Result<T>
/// where T: Deserialize<'a>;
/// where
/// T: Deserialize<'a>;
///
/// fn from_reader<R, T>(rdr: R) -> Result<T>
/// where R: Read,
/// T: DeserializeOwned;
/// where
/// R: Read,
/// T: DeserializeOwned;
/// # }
/// ```
pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
@@ -637,7 +643,8 @@ where
/// struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>);
///
/// impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// // The return type of the `deserialize` method. This implementation
/// // appends onto an existing vector but does not create any new data
@@ -645,14 +652,16 @@ where
/// type Value = ();
///
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
/// where D: Deserializer<'de>
/// where
/// D: Deserializer<'de>,
/// {
/// // Visitor implementation that will walk an inner array of the JSON
/// // input.
/// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);
///
/// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// type Value = ();
///
@@ -661,7 +670,8 @@ where
/// }
///
/// fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
/// where A: SeqAccess<'de>
/// where
/// A: SeqAccess<'de>,
/// {
/// // Visit each element in the inner array and push it onto
/// // the existing vector.
@@ -680,7 +690,8 @@ where
/// struct FlattenedVecVisitor<T>(PhantomData<T>);
///
/// impl<'de, T> Visitor<'de> for FlattenedVecVisitor<T>
/// where T: Deserialize<'de>
/// where
/// T: Deserialize<'de>,
/// {
/// // This Visitor constructs a single Vec<T> to hold the flattened
/// // contents of the inner arrays.
@@ -691,7 +702,8 @@ where
/// }
///
/// fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error>
/// where A: SeqAccess<'de>
/// where
/// A: SeqAccess<'de>,
/// {
/// // Create a single Vec to hold the flattened contents.
/// let mut vec = Vec::new();
@@ -707,7 +719,8 @@ where
/// }
///
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
/// # where D: Deserializer<'de>
/// # where
/// # D: Deserializer<'de>,
/// # {
/// let visitor = FlattenedVecVisitor(PhantomData);
/// let flattened: Vec<u64> = deserializer.deserialize_seq(visitor)?;
@@ -1092,7 +1105,8 @@ pub trait Deserializer<'de>: Sized {
///
/// impl<'de> Deserialize<'de> for Timestamp {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de>
/// where
/// D: Deserializer<'de>,
/// {
/// if deserializer.is_human_readable() {
/// // Deserialize from a human-readable string like "2015-05-15T17:01:00Z".
@@ -1118,6 +1132,18 @@ pub trait Deserializer<'de>: Sized {
fn is_human_readable(&self) -> bool {
true
}
// Not public API.
#[doc(hidden)]
fn private_deserialize_internally_tagged_enum<V>(
self,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.deserialize_any(visitor)
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -1143,7 +1169,8 @@ pub trait Deserializer<'de>: Sized {
/// }
///
/// fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
/// where E: de::Error
/// where
/// E: de::Error,
/// {
/// if s.len() >= self.min {
/// Ok(s.to_owned())
@@ -1823,15 +1850,18 @@ pub trait VariantAccess<'de>: Sized {
/// }
/// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de>
/// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() }
/// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// # }
/// ```
@@ -1858,7 +1888,8 @@ pub trait VariantAccess<'de>: Sized {
/// # }
/// #
/// fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
/// where T: DeserializeSeed<'de>
/// where
/// T: DeserializeSeed<'de>,
/// {
/// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant;
@@ -1866,11 +1897,13 @@ pub trait VariantAccess<'de>: Sized {
/// }
/// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// # }
/// ```
@@ -1911,13 +1944,17 @@ pub trait VariantAccess<'de>: Sized {
/// # }
/// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de>
/// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() }
/// #
/// fn tuple_variant<V>(self,
/// _len: usize,
/// _visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// fn tuple_variant<V>(
/// self,
/// _len: usize,
/// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// {
/// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant;
@@ -1925,7 +1962,8 @@ pub trait VariantAccess<'de>: Sized {
/// }
/// #
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// # }
/// ```
@@ -1953,17 +1991,22 @@ pub trait VariantAccess<'de>: Sized {
/// # }
/// #
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
/// # where T: DeserializeSeed<'de>
/// # where
/// # T: DeserializeSeed<'de>,
/// # { unimplemented!() }
/// #
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # { unimplemented!() }
/// #
/// fn struct_variant<V>(self,
/// _fields: &'static [&'static str],
/// _visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// fn struct_variant<V>(
/// self,
/// _fields: &'static [&'static str],
/// _visitor: V,
/// ) -> Result<V::Value, Self::Error>
/// where
/// V: Visitor<'de>,
/// {
/// // What the data actually contained; suppose it is a unit variant.
/// let unexp = Unexpected::UnitVariant;
+5 -5
View File
@@ -79,7 +79,7 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.45")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.51")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
@@ -179,14 +179,14 @@ mod lib {
pub use std::boxed::Box;
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::rc::Rc;
pub use alloc::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::rc::Rc;
pub use std::rc::{Rc, Weak as RcWeak};
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
pub use alloc::arc::Arc;
pub use alloc::arc::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "rc", feature = "std"))]
pub use std::sync::Arc;
pub use std::sync::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
+8 -4
View File
@@ -31,14 +31,16 @@
/// # type Error = value::Error;
/// #
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
/// # where V: Visitor<'de>
/// # where
/// # V: Visitor<'de>,
/// # {
/// # unimplemented!()
/// # }
/// #
/// #[inline]
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// where
/// V: Visitor<'de>,
/// {
/// self.deserialize_any(visitor)
/// }
@@ -69,7 +71,8 @@
/// # type Error = value::Error;
/// #
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
/// where V: Visitor<'de>
/// where
/// V: Visitor<'de>,
/// {
/// /* ... */
/// # let _ = visitor;
@@ -105,7 +108,8 @@
/// # type Error = value::Error;
/// #
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
/// # where W: Visitor<'q>
/// # where
/// # W: Visitor<'q>,
/// # {
/// # unimplemented!()
/// # }
+66 -6
View File
@@ -14,10 +14,11 @@ use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Vi
use de::{MapAccess, Unexpected};
#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{Content, ContentDeserializer, ContentRefDeserializer, EnumDeserializer,
InternallyTaggedUnitVisitor, TagContentOtherField,
TagContentOtherFieldVisitor, TagOrContentField, TagOrContentFieldVisitor,
TaggedContentVisitor, UntaggedUnitVisitor};
pub use self::content::{
Content, ContentDeserializer, ContentRefDeserializer, EnumDeserializer,
InternallyTaggedUnitVisitor, TagContentOtherField, TagContentOtherFieldVisitor,
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
};
/// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error.
@@ -229,8 +230,10 @@ mod content {
use lib::*;
use super::size_hint;
use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, MapAccess,
SeqAccess, Unexpected, Visitor};
use de::{
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, MapAccess,
SeqAccess, Unexpected, Visitor,
};
/// Used from generated code to buffer the contents of the Deserializer when
/// deserializing untagged enums and internally tagged enums.
@@ -2712,6 +2715,20 @@ where
byte_buf option unit unit_struct seq tuple tuple_struct identifier
ignored_any
}
fn private_deserialize_internally_tagged_enum<V>(
self,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_map(FlatInternallyTaggedAccess {
iter: self.0.iter_mut(),
pending: None,
_marker: PhantomData,
})
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -2783,3 +2800,46 @@ where
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatInternallyTaggedAccess<'a, 'de: 'a, E> {
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
pending: Option<&'a Content<'de>>,
_marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de, E> MapAccess<'de> for FlatInternallyTaggedAccess<'a, 'de, E>
where
E: Error,
{
type Error = E;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: DeserializeSeed<'de>,
{
match self.iter.next() {
Some(item) => {
// Do not take(), instead borrow this entry. The internally tagged
// enum does its own buffering so we can't tell whether this entry
// is going to be consumed. Borrowing here leaves the entry
// available for later flattened fields.
let (ref key, ref content) = *item.as_ref().unwrap();
self.pending = Some(content);
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
}
None => Ok(None),
}
}
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
match self.pending.take() {
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
None => panic!("value is missing"),
}
}
}
+3 -2
View File
@@ -11,8 +11,9 @@ use lib::*;
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{Content, ContentSerializer, SerializeStructVariantAsMapValue,
SerializeTupleVariantAsMapValue};
use self::content::{
Content, ContentSerializer, SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue,
};
/// Used to check that serde(getter) attributes return the expected type.
/// Not public API.
+34
View File
@@ -374,6 +374,40 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
////////////////////////////////////////////////////////////////////////////////
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<T: ?Sized> Serialize for RcWeak<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.upgrade().serialize(serializer)
}
}
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
impl<T: ?Sized> Serialize for ArcWeak<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.upgrade().serialize(serializer)
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "unstable")]
#[allow(deprecated)]
impl<T> Serialize for NonZero<T>
+4 -2
View File
@@ -10,8 +10,10 @@
use lib::*;
use ser::{self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
use ser::{
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
};
/// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types.
+110 -58
View File
@@ -152,7 +152,8 @@ macro_rules! declare_error_trait {
///
/// impl Serialize for Path {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match self.to_str() {
/// Some(s) => serializer.serialize_str(s),
@@ -223,7 +224,8 @@ pub trait Serialize {
/// // This is what #[derive(Serialize)] would generate.
/// impl Serialize for Person {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut s = serializer.serialize_struct("Person", 3)?;
/// s.serialize_field("name", &self.name)?;
@@ -377,7 +379,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for bool {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_bool(*self)
/// }
@@ -403,7 +406,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for i8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i8(*self)
/// }
@@ -429,7 +433,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for i16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i16(*self)
/// }
@@ -455,7 +460,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for i32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i32(*self)
/// }
@@ -477,7 +483,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for i64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_i64(*self)
/// }
@@ -503,7 +510,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for u8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u8(*self)
/// }
@@ -529,7 +537,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for u16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u16(*self)
/// }
@@ -555,7 +564,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for u32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u32(*self)
/// }
@@ -577,7 +587,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for u64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_u64(*self)
/// }
@@ -603,7 +614,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for f32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_f32(*self)
/// }
@@ -625,7 +637,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for f64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_f64(*self)
/// }
@@ -650,7 +663,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for char {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_char(*self)
/// }
@@ -672,7 +686,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for str {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_str(self)
/// }
@@ -737,10 +752,12 @@ pub trait Serializer: Sized {
/// # use Option::{Some, None};
/// #
/// impl<T> Serialize for Option<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// Some(ref value) => serializer.serialize_some(value),
@@ -770,10 +787,12 @@ pub trait Serializer: Sized {
/// # use Option::{Some, None};
/// #
/// impl<T> Serialize for Option<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// Some(ref value) => serializer.serialize_some(value),
@@ -802,7 +821,8 @@ pub trait Serializer: Sized {
/// #
/// impl Serialize for () {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_unit()
/// }
@@ -823,7 +843,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Nothing {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_unit_struct("Nothing")
/// }
@@ -847,7 +868,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::A => serializer.serialize_unit_variant("E", 0, "A"),
@@ -876,7 +898,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Millimeters {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.serialize_newtype_struct("Millimeters", &self.0)
/// }
@@ -906,7 +929,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s),
@@ -956,10 +980,12 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
///
/// impl<T> Serialize for Vec<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self {
@@ -988,12 +1014,14 @@ pub trait Serializer: Sized {
/// # struct Tuple3<A, B, C>(A, B, C);
/// #
/// # impl<A, B, C> Serialize for Tuple3<A, B, C>
/// where A: Serialize,
/// B: Serialize,
/// C: Serialize
/// where
/// A: Serialize,
/// B: Serialize,
/// C: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?;
@@ -1012,7 +1040,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Vram {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut seq = serializer.serialize_tuple(VRAM_SIZE)?;
/// for element in &self.0[..] {
@@ -1038,7 +1067,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?;
@@ -1072,7 +1102,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::T(ref a, ref b) => {
@@ -1130,11 +1161,13 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeMap};
///
/// impl<K, V> Serialize for HashMap<K, V>
/// where K: Serialize,
/// V: Serialize
/// where
/// K: Serialize,
/// V: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self {
@@ -1164,7 +1197,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut rgb = serializer.serialize_struct("Rgb", 3)?;
/// rgb.serialize_field("r", &self.r)?;
@@ -1197,7 +1231,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::S { ref r, ref g, ref b } => {
@@ -1234,7 +1269,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for SecretlyOneHigher {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.collect_seq(self.data.iter().map(|x| x + 1))
/// }
@@ -1272,7 +1308,8 @@ pub trait Serializer: Sized {
/// // Serializes as a map in which the values are all unit.
/// impl Serialize for MapToUnit {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.collect_map(self.keys.iter().map(|k| (k, ())))
/// }
@@ -1312,7 +1349,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
@@ -1352,7 +1390,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for DateTime {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// serializer.collect_str(&format_args!("{:?}{:?}",
/// self.naive_local(),
@@ -1393,7 +1432,8 @@ pub trait Serializer: Sized {
///
/// impl Serialize for Timestamp {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// if serializer.is_human_readable() {
/// // Serialize to a human-readable string "2015-05-15T17:01:00Z".
@@ -1442,10 +1482,12 @@ pub trait Serializer: Sized {
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
///
/// impl<T> Serialize for Vec<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut seq = serializer.serialize_seq(Some(self.len()))?;
/// for element in self {
@@ -1485,12 +1527,14 @@ pub trait SerializeSeq {
/// # struct Tuple3<A, B, C>(A, B, C);
/// #
/// # impl<A, B, C> Serialize for Tuple3<A, B, C>
/// where A: Serialize,
/// B: Serialize,
/// C: Serialize
/// where
/// A: Serialize,
/// B: Serialize,
/// C: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut tup = serializer.serialize_tuple(3)?;
/// tup.serialize_element(&self.0)?;
@@ -1529,10 +1573,12 @@ pub trait SerializeSeq {
/// # }
/// #
/// # impl<T> Serialize for Array<T>
/// where T: Serialize
/// where
/// T: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut seq = serializer.serialize_tuple(16)?;
/// for element in self {
@@ -1567,7 +1613,8 @@ pub trait SerializeTuple {
///
/// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
/// ts.serialize_field(&self.0)?;
@@ -1605,7 +1652,8 @@ pub trait SerializeTupleStruct {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::T(ref a, ref b) => {
@@ -1666,11 +1714,13 @@ pub trait SerializeTupleVariant {
/// use serde::ser::{Serialize, Serializer, SerializeMap};
///
/// impl<K, V> Serialize for HashMap<K, V>
/// where K: Serialize,
/// V: Serialize
/// where
/// K: Serialize,
/// V: Serialize,
/// {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut map = serializer.serialize_map(Some(self.len()))?;
/// for (k, v) in self {
@@ -1754,7 +1804,8 @@ pub trait SerializeMap {
///
/// impl Serialize for Rgb {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// let mut rgb = serializer.serialize_struct("Rgb", 3)?;
/// rgb.serialize_field("r", &self.r)?;
@@ -1802,7 +1853,8 @@ pub trait SerializeStruct {
///
/// impl Serialize for E {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer
/// where
/// S: Serializer,
/// {
/// match *self {
/// E::S { ref r, ref g, ref b } => {
+1 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.45" # remember to update html_root_url
version = "1.0.51" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -25,7 +25,6 @@ proc-macro = true
[dependencies]
proc-macro2 = "0.3"
quote = "0.5.2"
serde_derive_internals = { version = "=0.23.1", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.13", features = ["visit"] }
[dev-dependencies]
+193 -101
View File
@@ -15,18 +15,19 @@ use syn::{self, Ident, Index, Member};
use bound;
use fragment::{Expr, Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{self, attr};
use internals::{attr, Ctxt};
use pretend;
use try;
use std::collections::BTreeSet;
pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = internals::Ctxt::new();
let ctxt = Ctxt::new();
let cont = Container::from_ast(&ctxt, input);
precondition(&ctxt, &cont);
try!(ctxt.check());
let ident = &cont.ident;
let ident = cont.ident;
let params = Parameters::new(&cont);
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
let dummy_const = Ident::new(
@@ -42,7 +43,8 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
quote! {
impl #de_impl_generics #ident #ty_generics #where_clause {
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error>
where __D: _serde::Deserializer<#delife>
where
__D: _serde::Deserializer<#delife>,
{
#used
#body
@@ -56,7 +58,8 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
#[automatically_derived]
impl #de_impl_generics _serde::Deserialize<#delife> for #ident #ty_generics #where_clause {
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where __D: _serde::Deserializer<#delife>
where
__D: _serde::Deserializer<#delife>,
{
#body
}
@@ -78,6 +81,32 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<Tokens, Str
Ok(generated)
}
fn precondition(cx: &Ctxt, cont: &Container) {
precondition_sized(cx, cont);
precondition_no_de_lifetime(cx, cont);
}
fn precondition_sized(cx: &Ctxt, cont: &Container) {
if let Data::Struct(_, ref fields) = cont.data {
if let Some(last) = fields.last() {
if let syn::Type::Slice(_) = *last.ty {
cx.error("cannot deserialize a dynamically sized struct");
}
}
}
}
fn precondition_no_de_lifetime(cx: &Ctxt, cont: &Container) {
if let BorrowedLifetimes::Borrowed(_) = borrowed_lifetimes(cont) {
for param in cont.generics.lifetimes() {
if param.lifetime.to_string() == "'de" {
cx.error("cannot deserialize when there is a lifetime parameter called 'de");
return;
}
}
}
}
struct Parameters {
/// Name of the type the `derive` is on.
local: syn::Ident,
@@ -162,13 +191,17 @@ fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generi
}
}
// Fields with a `skip_deserializing` or `deserialize_with` attribute are not
// deserialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Deserialize` bound where T is the type of the field.
// Fields with a `skip_deserializing` or `deserialize_with` attribute, or which
// belong to a variant with a `skip_deserializing` or `deserialize_with`
// attribute, are not deserialized by us so we do not generate a bound. Fields
// with a `bound` attribute specify their own bound so we do not generate one.
// All other fields may need a `T: Deserialize` bound where T is the type of the
// field.
fn needs_deserialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_deserializing() && field.deserialize_with().is_none() && field.de_bound().is_none()
&& variant.map_or(true, |variant| variant.deserialize_with().is_none())
&& variant.map_or(true, |variant| {
!variant.skip_deserializing() && variant.deserialize_with().is_none()
})
}
// Fields with a `default` attribute (not `default=...`), and fields with a
@@ -296,7 +329,8 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<St
let fn_deserialize_in_place = quote_block! {
fn deserialize_in_place<__D>(__deserializer: __D, __place: &mut Self) -> _serde::export::Result<(), __D::Error>
where __D: _serde::Deserializer<#delife>
where
__D: _serde::Deserializer<#delife>,
{
#stmts
}
@@ -336,7 +370,8 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
#[inline]
fn visit_unit<__E>(self) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(#this)
}
@@ -347,7 +382,7 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
}
fn deserialize_tuple(
variant_ident: Option<&syn::Ident>,
variant_ident: Option<syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
@@ -364,7 +399,7 @@ fn deserialize_tuple(
// and use an `Into` conversion to get the remote type. If there are no
// getters then construct the target type directly.
let construct = if params.has_getter {
let local = &params.local;
let local = params.local;
quote!(#local)
} else {
quote!(#this)
@@ -432,7 +467,8 @@ fn deserialize_tuple(
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<#delife>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
@@ -444,7 +480,7 @@ fn deserialize_tuple(
#[cfg(feature = "deserialize_in_place")]
fn deserialize_tuple_in_place(
variant_ident: Option<&syn::Ident>,
variant_ident: Option<syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
@@ -520,7 +556,8 @@ fn deserialize_tuple_in_place(
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<#delife>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
@@ -547,7 +584,7 @@ fn deserialize_seq(
.count();
let expecting = format!("tuple of {} elements", deserialized_count);
let mut index_in_seq = 0usize;
let mut index_in_seq = 0_usize;
let let_values = vars.clone().zip(fields).map(|(var, field)| {
if field.attrs.skip_deserializing() {
let default = Expr(expr_is_missing(field, cattrs));
@@ -557,7 +594,7 @@ fn deserialize_seq(
} else {
let visit = match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
let field_ty = field.ty;
let span = field.original.span();
let func =
quote_spanned!(span=> _serde::de::SeqAccess::next_element::<#field_ty>);
@@ -719,20 +756,18 @@ fn deserialize_seq_in_place(
fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &Field) -> Tokens {
let delife = params.borrowed.de_lifetime();
let field_ty = field.ty;
let value = match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
quote! {
try!(<#field_ty as _serde::Deserialize>::deserialize(__e))
}
}
Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({
#wrapper
try!(<#wrapper_ty as _serde::Deserialize>::deserialize(__e)).value
})
quote! {
try!(#path(__e))
}
}
};
@@ -747,9 +782,10 @@ fn deserialize_newtype_struct(type_path: &Tokens, params: &Parameters, field: &F
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer<#delife>
where
__E: _serde::Deserializer<#delife>,
{
let __field0 = #value;
let __field0: #field_ty = #value;
_serde::export::Ok(#result)
}
}
@@ -765,7 +801,8 @@ fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> To
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::export::Result<Self::Value, __E::Error>
where __E: _serde::Deserializer<#delife>
where
__E: _serde::Deserializer<#delife>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
@@ -778,7 +815,7 @@ enum Untagged {
}
fn deserialize_struct(
variant_ident: Option<&syn::Ident>,
variant_ident: Option<syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
@@ -796,7 +833,7 @@ fn deserialize_struct(
// and use an `Into` conversion to get the remote type. If there are no
// getters then construct the target type directly.
let construct = if params.has_getter {
let local = &params.local;
let local = params.local;
quote!(#local)
} else {
quote!(#this)
@@ -832,6 +869,10 @@ fn deserialize_struct(
quote! {
_serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
}
} else if is_enum && cattrs.has_flatten() {
quote! {
_serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr)
}
} else if is_enum {
quote! {
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
@@ -860,7 +901,8 @@ fn deserialize_struct(
Untagged::No if !cattrs.has_flatten() => Some(quote! {
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<#delife>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
@@ -868,6 +910,23 @@ fn deserialize_struct(
_ => None,
};
let visitor_seed = if is_enum && cattrs.has_flatten() {
Some(quote! {
impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause {
type Value = #this #ty_generics;
fn deserialize<__D>(self, __deserializer: __D) -> _serde::export::Result<Self::Value, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_map(__deserializer, self)
}
}
})
} else {
None
};
quote_block! {
#field_visitor
@@ -887,12 +946,15 @@ fn deserialize_struct(
#[inline]
fn visit_map<__A>(self, mut __map: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<#delife>
where
__A: _serde::de::MapAccess<#delife>,
{
#visit_map
}
}
#visitor_seed
#fields_stmt
#dispatch
@@ -901,7 +963,7 @@ fn deserialize_struct(
#[cfg(feature = "deserialize_in_place")]
fn deserialize_struct_in_place(
variant_ident: Option<&syn::Ident>,
variant_ident: Option<syn::Ident>,
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
@@ -965,7 +1027,8 @@ fn deserialize_struct_in_place(
let visit_seq = quote! {
#[inline]
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<#delife>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
@@ -994,7 +1057,8 @@ fn deserialize_struct_in_place(
#[inline]
fn visit_map<__A>(self, mut __map: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<#delife>
where
__A: _serde::de::MapAccess<#delife>,
{
#visit_map
}
@@ -1113,7 +1177,8 @@ fn deserialize_externally_tagged_enum(
}
fn visit_enum<__A>(self, __data: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::EnumAccess<#delife>
where
__A: _serde::de::EnumAccess<#delife>,
{
#match_variant
}
@@ -1182,7 +1247,7 @@ fn deserialize_internally_tagged_enum(
#variants_stmt
let __tagged = try!(_serde::Deserializer::deserialize_any(
let __tagged = try!(_serde::Deserializer::private_deserialize_internally_tagged_enum(
__deserializer,
_serde::private::de::TaggedContentVisitor::<__Field>::new(#tag)));
@@ -1287,7 +1352,7 @@ fn deserialize_adjacently_tagged_enum(
.filter(|&(_, variant)| !variant.attrs.skip_deserializing() && is_unit(variant))
.map(|(i, variant)| {
let variant_index = field_i(i);
let variant_ident = &variant.ident;
let variant_ident = variant.ident;
quote! {
__Field::#variant_index => _serde::export::Ok(#this::#variant_ident),
}
@@ -1348,6 +1413,21 @@ fn deserialize_adjacently_tagged_enum(
}
};
let finish_content_then_tag = if variant_arms.is_empty() {
quote! {
match try!(_serde::de::MapAccess::next_value::<__Field>(&mut __map)) {}
}
} else {
quote! {
let __ret = try!(match try!(_serde::de::MapAccess::next_value(&mut __map)) {
// Deserialize the buffered content now that we know the variant.
#(#variant_arms)*
});
// Visit remaining keys, looking for duplicates.
#visit_remaining_keys
}
};
quote_block! {
#variant_visitor
@@ -1363,7 +1443,8 @@ fn deserialize_adjacently_tagged_enum(
type Value = #this #ty_generics;
fn deserialize<__D>(self, __deserializer: __D) -> _serde::export::Result<Self::Value, __D::Error>
where __D: _serde::Deserializer<#delife>
where
__D: _serde::Deserializer<#delife>,
{
match self.field {
#(#variant_arms)*
@@ -1384,7 +1465,8 @@ fn deserialize_adjacently_tagged_enum(
}
fn visit_map<__A>(self, mut __map: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<#delife>
where
__A: _serde::de::MapAccess<#delife>,
{
// Visit the first relevant key.
match #next_relevant_key {
@@ -1422,13 +1504,7 @@ fn deserialize_adjacently_tagged_enum(
// Second key is the tag.
_serde::export::Some(_serde::private::de::TagOrContentField::Tag) => {
let __deserializer = _serde::private::de::ContentDeserializer::<__A::Error>::new(__content);
// Parse the tag.
let __ret = try!(match try!(_serde::de::MapAccess::next_value(&mut __map)) {
// Deserialize the buffered content now that we know the variant.
#(#variant_arms)*
});
// Visit remaining keys, looking for duplicates.
#visit_remaining_keys
#finish_content_then_tag
}
// Second key is a duplicate of the content.
_serde::export::Some(_serde::private::de::TagOrContentField::Content) => {
@@ -1448,7 +1524,8 @@ fn deserialize_adjacently_tagged_enum(
}
fn visit_seq<__A>(self, mut __seq: __A) -> _serde::export::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<#delife>
where
__A: _serde::de::SeqAccess<#delife>,
{
// Visit the first element - the tag.
match try!(_serde::de::SeqAccess::next_element(&mut __seq)) {
@@ -1539,7 +1616,7 @@ fn deserialize_externally_tagged_variant(
};
}
let variant_ident = &variant.ident;
let variant_ident = variant.ident;
match variant.style {
Style::Unit => {
@@ -1576,7 +1653,7 @@ fn deserialize_internally_tagged_variant(
return deserialize_untagged_variant(params, variant, cattrs, deserializer);
}
let variant_ident = &variant.ident;
let variant_ident = variant.ident;
match variant.style {
Style::Unit => {
@@ -1621,7 +1698,7 @@ fn deserialize_untagged_variant(
};
}
let variant_ident = &variant.ident;
let variant_ident = variant.ident;
match variant.style {
Style::Unit => {
@@ -1663,14 +1740,14 @@ fn deserialize_untagged_variant(
}
fn deserialize_externally_tagged_newtype_variant(
variant_ident: &syn::Ident,
variant_ident: syn::Ident,
params: &Parameters,
field: &Field,
) -> Fragment {
let this = &params.this;
match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
let field_ty = field.ty;
quote_expr! {
_serde::export::Result::map(
_serde::de::VariantAccess::newtype_variant::<#field_ty>(__variant),
@@ -1690,15 +1767,15 @@ fn deserialize_externally_tagged_newtype_variant(
}
fn deserialize_untagged_newtype_variant(
variant_ident: &syn::Ident,
variant_ident: syn::Ident,
params: &Parameters,
field: &Field,
deserializer: &Tokens,
) -> Fragment {
let this = &params.this;
let field_ty = field.ty;
match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
quote_expr! {
_serde::export::Result::map(
<#field_ty as _serde::Deserialize>::deserialize(#deserializer),
@@ -1706,12 +1783,11 @@ fn deserialize_untagged_newtype_variant(
}
}
Some(path) => {
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote_block! {
#wrapper
_serde::export::Result::map(
<#wrapper_ty as _serde::Deserialize>::deserialize(#deserializer),
|__wrapper| #this::#variant_ident(__wrapper.value))
let __value: #field_ty = _serde::export::Result::map(
#path(#deserializer),
#this::#variant_ident);
__value
}
}
}
@@ -1725,7 +1801,7 @@ fn deserialize_generated_identifier(
let this = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect();
let (ignore_variant, fallthrough) = if cattrs.has_flatten() {
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),);
let fallthrough = quote!(_serde::export::Ok(__Field::__other(__value)));
(Some(ignore_variant), Some(fallthrough))
@@ -1742,10 +1818,10 @@ fn deserialize_generated_identifier(
fields,
is_variant,
fallthrough,
cattrs.has_flatten(),
!is_variant && cattrs.has_flatten(),
));
let lifetime = if cattrs.has_flatten() {
let lifetime = if !is_variant && cattrs.has_flatten() {
Some(quote!(<'de>))
} else {
None
@@ -1769,7 +1845,8 @@ fn deserialize_generated_identifier(
impl<'de> _serde::Deserialize<'de> for __Field #lifetime {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where __D: _serde::Deserializer<'de>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
@@ -1792,7 +1869,7 @@ fn deserialize_custom_identifier(
let this = quote!(#this);
let (ordinary, fallthrough) = if let Some(last) = variants.last() {
let last_ident = &last.ident;
let last_ident = last.ident;
if last.attrs.other() {
let ordinary = &variants[..variants.len() - 1];
let fallthrough = quote!(_serde::export::Ok(#this::#last_ident));
@@ -1909,9 +1986,7 @@ fn deserialize_identifier(
value_as_borrowed_str_content,
value_as_bytes_content,
value_as_borrowed_bytes_content,
) = if !collect_other_fields {
(None, None, None, None)
} else {
) = if collect_other_fields {
(
Some(quote! {
let __value = _serde::private::de::Content::String(__value.to_string());
@@ -1926,6 +2001,8 @@ fn deserialize_identifier(
let __value = _serde::private::de::Content::Bytes(__value);
}),
)
} else {
(None, None, None, None)
};
let fallthrough_arm = if let Some(fallthrough) = fallthrough {
@@ -1940,90 +2017,104 @@ fn deserialize_identifier(
}
};
let variant_indices = 0u64..;
let variant_indices = 0_u64..;
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
let visit_other = if collect_other_fields {
quote! {
fn visit_bool<__E>(self, __value: bool) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::Bool(__value)))
}
fn visit_i8<__E>(self, __value: i8) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::I8(__value)))
}
fn visit_i16<__E>(self, __value: i16) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::I16(__value)))
}
fn visit_i32<__E>(self, __value: i32) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::I32(__value)))
}
fn visit_i64<__E>(self, __value: i64) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::I64(__value)))
}
fn visit_u8<__E>(self, __value: u8) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::U8(__value)))
}
fn visit_u16<__E>(self, __value: u16) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::U16(__value)))
}
fn visit_u32<__E>(self, __value: u32) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::U32(__value)))
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::U64(__value)))
}
fn visit_f32<__E>(self, __value: f32) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::F32(__value)))
}
fn visit_f64<__E>(self, __value: f64) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::F64(__value)))
}
fn visit_char<__E>(self, __value: char) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::Char(__value)))
}
fn visit_unit<__E>(self) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
_serde::export::Ok(__Field::__other(_serde::private::de::Content::Unit))
}
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
match __value {
#(
@@ -2037,7 +2128,8 @@ fn deserialize_identifier(
}
fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
match __value {
#(
@@ -2054,7 +2146,8 @@ fn deserialize_identifier(
} else {
quote! {
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
match __value {
#(
@@ -2076,7 +2169,8 @@ fn deserialize_identifier(
#visit_other
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
match __value {
#(
@@ -2090,7 +2184,8 @@ fn deserialize_identifier(
}
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::export::Result<Self::Value, __E>
where __E: _serde::de::Error
where
__E: _serde::de::Error,
{
match __value {
#(
@@ -2173,7 +2268,7 @@ fn deserialize_map(
.iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|&(field, ref name)| {
let field_ty = &field.ty;
let field_ty = field.ty;
quote! {
let mut #name: _serde::export::Option<#field_ty> = _serde::export::None;
}
@@ -2200,7 +2295,7 @@ fn deserialize_map(
let visit = match field.attrs.deserialize_with() {
None => {
let field_ty = &field.ty;
let field_ty = field.ty;
let span = field.original.span();
let func =
quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>);
@@ -2421,7 +2516,7 @@ fn deserialize_map_in_place(
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
.map(|&(field, ref name)| {
let deser_name = field.attrs.name().deserialize_name();
let field_name = &field.ident;
let field_name = field.ident;
let visit = match field.attrs.deserialize_with() {
None => {
@@ -2484,13 +2579,9 @@ fn deserialize_map_in_place(
.map(|&(field, ref name)| {
let missing_expr = expr_is_missing(field, cattrs);
// If missing_expr unconditionally returns an error, don't try
// to assign its value to self.place. Maybe this could be handled
// more elegantly.
if missing_expr
.as_ref()
.into_tokens()
.to_string()
.starts_with("return ")
// to assign its value to self.place.
if field.attrs.default().is_none() && cattrs.default().is_none()
&& field.attrs.deserialize_with().is_some()
{
let missing_expr = Stmts(missing_expr);
quote! {
@@ -2499,7 +2590,7 @@ fn deserialize_map_in_place(
}
}
} else {
let field_name = &field.ident;
let field_name = field.ident;
let missing_expr = Expr(missing_expr);
quote! {
if !#name {
@@ -2564,7 +2655,8 @@ fn wrap_deserialize_with(
impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause {
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where __D: _serde::Deserializer<#delife>
where
__D: _serde::Deserializer<#delife>,
{
_serde::export::Ok(__DeserializeWith {
value: try!(#deserialize_with(__deserializer)),
@@ -2594,7 +2686,7 @@ fn wrap_deserialize_variant_with(
deserialize_with: &syn::ExprPath,
) -> (Tokens, Tokens, Tokens) {
let this = &params.this;
let variant_ident = &variant.ident;
let variant_ident = variant.ident;
let field_tys = variant.fields.iter().map(|field| field.ty);
let (wrapper, wrapper_ty) =
@@ -2649,7 +2741,7 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
match *cattrs.default() {
attr::Default::Default | attr::Default::Path(_) => {
let ident = &field.ident;
let ident = field.ident;
return quote_expr!(__default.#ident);
}
attr::Default::None => { /* below */ }
@@ -6,11 +6,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use attr;
use check;
use internals::attr;
use internals::check;
use internals::Ctxt;
use syn;
use syn::punctuated::Punctuated;
use Ctxt;
pub struct Container<'a> {
pub ident: syn::Ident,
@@ -6,6 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use internals::Ctxt;
use proc_macro2::{Group, Span, TokenStream, TokenTree};
use std::collections::BTreeSet;
use std::str::FromStr;
@@ -15,7 +16,6 @@ use syn::synom::{ParseError, Synom};
use syn::Ident;
use syn::Meta::{List, NameValue, Word};
use syn::NestedMeta::{Literal, Meta};
use Ctxt;
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Container::from_ast`, `attr::Variant::from_ast`, and
@@ -25,7 +25,7 @@ use Ctxt;
// user will see errors simultaneously for all bad attributes in the crate
// rather than just the first.
pub use case::RenameRule;
pub use internals::case::RenameRule;
#[derive(Copy, Clone)]
struct Attr<'c, T> {
@@ -167,6 +167,7 @@ pub enum Identifier {
}
impl Identifier {
#[cfg(feature = "deserialize_in_place")]
pub fn is_some(self) -> bool {
match self {
Identifier::No => false,
@@ -579,6 +580,12 @@ impl Variant {
}
}
// Parse `#[serde(skip)]`
Meta(Word(word)) if word == "skip" => {
skip_serializing.set_true();
skip_deserializing.set_true();
}
// Parse `#[serde(skip_deserializing)]`
Meta(Word(word)) if word == "skip_deserializing" => {
skip_deserializing.set_true();
@@ -737,6 +744,16 @@ pub enum Default {
Path(syn::ExprPath),
}
impl Default {
#[cfg(feature = "deserialize_in_place")]
pub fn is_none(&self) -> bool {
match *self {
Default::None => true,
Default::Default | Default::Path(_) => false,
}
}
}
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(
@@ -766,9 +783,7 @@ impl Field {
};
let variant_borrow = attrs
.map(|variant| &variant.borrow)
.unwrap_or(&None)
.as_ref()
.and_then(|variant| variant.borrow.as_ref())
.map(|borrow| vec![Meta(borrow.clone())]);
for meta_items in field
@@ -6,9 +6,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ast::{Container, Data, Style};
use attr::{EnumTag, Identifier};
use Ctxt;
use internals::ast::{Container, Data, Field, Style};
use internals::attr::{EnumTag, Identifier};
use internals::Ctxt;
/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
@@ -44,43 +44,49 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
/// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) {
match cont.data {
Data::Enum(_) => {
if cont.attrs.has_flatten() {
cx.error("#[serde(flatten)] cannot be used within enums");
}
}
Data::Struct(style, _) => {
for field in cont.data.all_fields() {
if !field.attrs.flatten() {
continue;
}
match style {
Style::Tuple => {
cx.error("#[serde(flatten)] cannot be used on tuple structs");
}
Style::Newtype => {
cx.error("#[serde(flatten)] cannot be used on newtype structs");
}
_ => {}
}
if field.attrs.skip_serializing() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_serializing)]",
);
} else if field.attrs.skip_serializing_if().is_some() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_serializing_if = \"...\")]",
);
} else if field.attrs.skip_deserializing() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_deserializing)]",
);
Data::Enum(ref variants) => {
for variant in variants {
for field in &variant.fields {
check_flatten_field(cx, variant.style, field);
}
}
}
Data::Struct(style, ref fields) => {
for field in fields {
check_flatten_field(cx, style, field);
}
}
}
}
fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
if !field.attrs.flatten() {
return;
}
match style {
Style::Tuple => {
cx.error("#[serde(flatten)] cannot be used on tuple structs");
}
Style::Newtype => {
cx.error("#[serde(flatten)] cannot be used on newtype structs");
}
_ => {}
}
if field.attrs.skip_serializing() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_serializing)]",
);
} else if field.attrs.skip_serializing_if().is_some() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_serializing_if = \"...\")]",
);
} else if field.attrs.skip_deserializing() {
cx.error(
"#[serde(flatten] can not be combined with \
#[serde(skip_deserializing)]",
);
}
}
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub mod ast;
pub mod attr;
mod ctxt;
pub use self::ctxt::Ctxt;
mod case;
mod check;
+17 -4
View File
@@ -22,10 +22,23 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.45")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.51")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
feature = "cargo-clippy",
allow(enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding)
allow(
enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding,
cyclomatic_complexity
)
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
items_after_statements, doc_markdown, stutter, similar_names, use_self, single_match_else,
enum_glob_use, match_same_arms, filter_map, cast_possible_truncation
)
)]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "512"]
@@ -35,11 +48,11 @@ extern crate quote;
#[macro_use]
extern crate syn;
extern crate serde_derive_internals as internals;
extern crate proc_macro;
extern crate proc_macro2;
mod internals;
use proc_macro::TokenStream;
use syn::DeriveInput;
+35 -39
View File
@@ -54,18 +54,17 @@ fn pretend_fields_used(cont: &Container) -> Tokens {
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = match cont.data {
Data::Enum(ref variants) => {
variants.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = variant.ident;
let pat = struct_pattern(&variant.fields);
Some(quote!(#type_ident::#variant_ident #pat))
}
_ => None,
})
.collect::<Vec<_>>()
}
Data::Enum(ref variants) => variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
let variant_ident = variant.ident;
let pat = struct_pattern(&variant.fields);
Some(quote!(#type_ident::#variant_ident #pat))
}
_ => None,
})
.collect::<Vec<_>>(),
Data::Struct(Style::Struct, ref fields) => {
let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)]
@@ -106,40 +105,37 @@ fn pretend_variants_used(cont: &Container) -> Tokens {
let (_, ty_generics, _) = cont.generics.split_for_impl();
let turbofish = ty_generics.as_turbofish();
let cases = variants.iter()
.map(|variant| {
let variant_ident = variant.ident;
let ref placeholders = (0..variant.fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
.collect::<Vec<_>>();
let cases = variants.iter().map(|variant| {
let variant_ident = variant.ident;
let placeholders = &(0..variant.fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
.collect::<Vec<_>>();
let pat = match variant.style {
Style::Struct => {
let names = variant.fields.iter().map(|field| field.ident);
quote!({ #(#names: #placeholders),* })
}
Style::Tuple | Style::Newtype => {
quote!(( #(#placeholders),* ))
}
Style::Unit => quote!(),
};
quote! {
match _serde::export::None {
_serde::export::Some((#(#placeholders,)*)) => {
let _ = #type_ident::#variant_ident #turbofish #pat;
}
_ => {}
}
let pat = match variant.style {
Style::Struct => {
let names = variant.fields.iter().map(|field| field.ident);
quote!({ #(#names: #placeholders),* })
}
});
Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
Style::Unit => quote!(),
};
quote! {
match _serde::export::None {
_serde::export::Some((#(#placeholders,)*)) => {
let _ = #type_ident::#variant_ident #turbofish #pat;
}
_ => {}
}
}
});
quote!(#(#cases)*)
}
fn struct_pattern(fields: &[Field]) -> Tokens {
let names = fields.iter().map(|field| field.ident);
let placeholders = (0..fields.len())
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
let placeholders =
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
quote!({ #(#names: ref #placeholders),* })
}
+112 -18
View File
@@ -18,15 +18,13 @@ use internals::{attr, Ctxt};
use pretend;
use try;
use std::u32;
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
let ctxt = Ctxt::new();
let cont = Container::from_ast(&ctxt, input);
precondition(&ctxt, &cont);
try!(ctxt.check());
let ident = &cont.ident;
let ident = cont.ident;
let params = Parameters::new(&cont);
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
let dummy_const = Ident::new(&format!("_IMPL_SERIALIZE_FOR_{}", ident), Span::call_site());
@@ -38,7 +36,8 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
quote! {
impl #impl_generics #ident #ty_generics #where_clause {
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
where
__S: _serde::Serializer,
{
#used
#body
@@ -50,7 +49,8 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
#[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
where
__S: _serde::Serializer,
{
#body
}
@@ -150,13 +150,15 @@ fn build_generics(cont: &Container) -> syn::Generics {
}
// Fields with a `skip_serializing` or `serialize_with` attribute, or which
// belong to a variant with a `serialize_with` attribute, are not serialized by
// us so we do not generate a bound. Fields with a `bound` attribute specify
// their own bound so we do not generate one. All other fields may need a `T:
// Serialize` bound where T is the type of the field.
// belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
// are not serialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
&& variant.map_or(true, |variant| variant.serialize_with().is_none())
&& variant.map_or(true, |variant| {
!variant.skip_serializing() && variant.serialize_with().is_none()
})
}
fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
@@ -186,7 +188,7 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
}
fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
let self_var = &params.self_var;
let self_var = params.self_var;
quote_block! {
_serde::Serialize::serialize(
&_serde::export::Into::<#type_into>::into(_serde::export::Clone::clone(#self_var)),
@@ -248,7 +250,7 @@ fn serialize_tuple_struct(
}
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
assert!(fields.len() as u64 <= u64::from(u32::MAX));
assert!(fields.len() as u64 <= u64::from(u32::max_value()));
if cattrs.has_flatten() {
serialize_struct_as_map(params, fields, cattrs)
@@ -331,9 +333,9 @@ fn serialize_struct_as_map(
}
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
assert!(variants.len() as u64 <= u64::from(u32::MAX));
assert!(variants.len() as u64 <= u64::from(u32::max_value()));
let self_var = &params.self_var;
let self_var = params.self_var;
let arms: Vec<_> = variants
.iter()
@@ -643,7 +645,7 @@ fn serialize_adjacently_tagged_variant(
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = if let Style::Unit = variant.style {
let wrapper_generics = if fields_ident.is_empty() {
params.generics.clone()
} else {
bound::with_lifetime_bound(&params.generics, "'__a")
@@ -658,7 +660,8 @@ fn serialize_adjacently_tagged_variant(
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
where
__S: _serde::Serializer,
{
let (#(#fields_ident,)*) = self.data;
#inner
@@ -786,6 +789,10 @@ fn serialize_struct_variant<'a>(
fields: &[Field],
name: &str,
) -> Fragment {
if fields.iter().any(|field| field.attrs.flatten()) {
return serialize_struct_variant_with_flatten(context, params, fields, name);
}
let struct_trait = match context {
StructVariant::ExternallyTagged { .. } => (StructTrait::SerializeStructVariant),
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
@@ -860,6 +867,92 @@ fn serialize_struct_variant<'a>(
}
}
fn serialize_struct_variant_with_flatten<'a>(
context: StructVariant<'a>,
params: &Parameters,
fields: &[Field],
name: &str,
) -> Fragment {
let struct_trait = StructTrait::SerializeMap;
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
let mut serialized_fields = fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
match context {
StructVariant::ExternallyTagged {
variant_index,
variant_name,
} => {
let this = &params.this;
let fields_ty = fields.iter().map(|f| &f.ty);
let fields_ident = &fields.iter().map(|f| f.ident).collect::<Vec<_>>();
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
let wrapper_generics = bound::with_lifetime_bound(&params.generics, "'__a");
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
quote_block! {
struct __EnumFlatten #wrapper_generics #where_clause {
data: (#(&'__a #fields_ty,)*),
phantom: _serde::export::PhantomData<#this #ty_generics>,
}
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let (#(#fields_ident,)*) = self.data;
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
_serde::Serializer::serialize_newtype_variant(
__serializer,
#name,
#variant_index,
#variant_name,
&__EnumFlatten {
data: (#(#fields_ident,)*),
phantom: _serde::export::PhantomData::<#this #ty_generics>,
})
}
}
StructVariant::InternallyTagged { tag, variant_name } => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
try!(_serde::ser::SerializeMap::serialize_entry(
&mut __serde_state,
#tag,
#variant_name,
));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
StructVariant::Untagged => {
quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
__serializer,
_serde::export::None));
#(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state)
}
}
}
}
fn serialize_tuple_struct_visitor(
fields: &[Field],
params: &Parameters,
@@ -1037,7 +1130,8 @@ fn wrap_serialize_with(
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where __S: _serde::Serializer
where
__S: _serde::Serializer,
{
#serialize_with(#(self.values.#field_access, )* __s)
}
@@ -1065,7 +1159,7 @@ fn mut_if(is_mut: bool) -> Option<Tokens> {
}
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
let self_var = &params.self_var;
let self_var = params.self_var;
match (params.is_remote, field.attrs.getter()) {
(false, None) => quote!(&#self_var.#member),
(true, None) => {
+4 -1
View File
@@ -9,7 +9,10 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_derive_internals/"
keywords = ["serde", "serialization"]
readme = "README.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[lib]
path = "lib.rs"
[dependencies]
proc-macro2 = "0.3"
@@ -17,11 +17,7 @@ extern crate syn;
extern crate proc_macro2;
pub mod ast;
pub mod attr;
#[path = "src/mod.rs"]
mod internals;
mod ctxt;
pub use ctxt::Ctxt;
mod case;
mod check;
pub use internals::*;
+1
View File
@@ -0,0 +1 @@
../serde_derive/src/internals/
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.45" # remember to update html_root_url
version = "1.0.51" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
+12 -5
View File
@@ -1,7 +1,9 @@
use std::fmt;
use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
use serde::ser::{
SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple,
SerializeTupleStruct, SerializeTupleVariant,
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
@@ -24,7 +26,8 @@ pub struct Compact<T: ?Sized>(T);
///
/// impl Serialize for Example {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer,
/// where
/// S: Serializer,
/// {
/// if serializer.is_human_readable() {
/// format!("{}.{}", self.0, self.1).serialize(serializer)
@@ -36,7 +39,8 @@ pub struct Compact<T: ?Sized>(T);
///
/// impl<'de> Deserialize<'de> for Example {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de>,
/// where
/// D: Deserializer<'de>,
/// {
/// use serde::de::Error;
/// if deserializer.is_human_readable() {
@@ -476,7 +480,10 @@ use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, Varian
macro_rules! forward_deserialize_methods {
( $wrapper : ident ( $( $name: ident ),* ) ) => {
$(
fn $name<V>(self, visitor: V) -> Result<V::Value, D::Error> where V: Visitor<'de> {
fn $name<V>(self, visitor: V) -> Result<V::Value, D::Error>
where
V: Visitor<'de>,
{
(self.0).$name($wrapper(visitor))
}
)*
+4 -2
View File
@@ -7,8 +7,10 @@
// except according to those terms.
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
SeqAccess, VariantAccess, Visitor};
use serde::de::{
self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
VariantAccess, Visitor,
};
use error::Error;
use token::Token;
+20 -12
View File
@@ -68,11 +68,13 @@
//! # }
//! #
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
//! # where K: Serialize,
//! # V: Serialize
//! # where
//! # K: Serialize,
//! # V: Serialize,
//! # {
//! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
//! # where S: Serializer
//! # where
//! # S: Serializer,
//! # {
//! # let mut map = serializer.serialize_map(Some(self.0.len()))?;
//! # for &(ref k, ref v) in &self.0 {
@@ -85,8 +87,9 @@
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
//! #
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
//! # where K: Deserialize<'de>,
//! # V: Deserialize<'de>
//! # where
//! # K: Deserialize<'de>,
//! # V: Deserialize<'de>,
//! # {
//! # type Value = LinkedHashMap<K, V>;
//! #
@@ -95,7 +98,8 @@
//! # }
//! #
//! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
//! # where M: MapAccess<'de>
//! # where
//! # M: MapAccess<'de>,
//! # {
//! # let mut map = LinkedHashMap::new();
//! # while let Some((key, value)) = access.next_entry()? {
@@ -106,11 +110,13 @@
//! # }
//! #
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
//! # where K: Deserialize<'de>,
//! # V: Deserialize<'de>
//! # where
//! # K: Deserialize<'de>,
//! # V: Deserialize<'de>,
//! # {
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
//! # where D: Deserializer<'de>
//! # where
//! # D: Deserializer<'de>,
//! # {
//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
//! # }
@@ -155,7 +161,7 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.45")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.51")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
@@ -179,8 +185,10 @@ mod assert;
mod configure;
mod token;
pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
assert_ser_tokens_error, assert_tokens};
pub use assert::{
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
assert_tokens,
};
pub use token::Token;
pub use configure::{Compact, Configure, Readable};
@@ -9,13 +9,7 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
//~^ HELP: #[serde(flatten)] cannot be used within enums
enum Foo {
A {
#[serde(flatten)]
fields: HashMap<String, String>,
}
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct S<'de> {
s: &'de str, //~^^ HELP: cannot deserialize when there is a lifetime parameter called 'de
}
fn main() {}
@@ -0,0 +1,16 @@
// Copyright 2018 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
struct S {
string: String,
slice: [u8], //~^^^ HELP: cannot deserialize a dynamically sized struct
}
+203 -2
View File
@@ -17,8 +17,10 @@ use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
extern crate serde_test;
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
assert_ser_tokens_error, assert_tokens, Token};
use self::serde_test::{
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
assert_tokens, Token,
};
trait MyDefault: Sized {
fn my_default() -> Self;
@@ -1791,3 +1793,202 @@ fn test_flatten_enum_newtype() {
],
);
}
#[test]
fn test_flatten_internally_tagged() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeX")]
enum X {
A { a: i32 },
B { b: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeY")]
enum Y {
C { c: i32 },
D { d: i32 },
}
let s = S {
x: X::B { b: 1 },
y: Y::D { d: 2 },
};
assert_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("B"),
Token::Str("b"),
Token::I32(1),
Token::Str("typeY"),
Token::Str("D"),
Token::Str("d"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test]
fn test_externally_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum Data {
A {
a: i32,
#[serde(flatten)]
flat: Flat,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Flat {
b: i32,
}
let data = Data::A {
a: 0,
flat: Flat { b: 0 },
};
assert_tokens(
&data,
&[
Token::NewtypeVariant {
name: "Data",
variant: "A",
},
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::Str("b"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test]
fn test_internally_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t")]
enum Data {
A {
a: i32,
#[serde(flatten)]
flat: Flat,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Flat {
b: i32,
}
let data = Data::A {
a: 0,
flat: Flat { b: 0 },
};
assert_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("t"),
Token::Str("A"),
Token::Str("a"),
Token::I32(0),
Token::Str("b"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test]
fn test_adjacently_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "t", content = "c")]
enum Data {
A {
a: i32,
#[serde(flatten)]
flat: Flat,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Flat {
b: i32,
}
let data = Data::A {
a: 0,
flat: Flat { b: 0 },
};
assert_tokens(
&data,
&[
Token::Struct {
name: "Data",
len: 2,
},
Token::Str("t"),
Token::Str("A"),
Token::Str("c"),
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::Str("b"),
Token::I32(0),
Token::MapEnd,
Token::StructEnd,
],
);
}
#[test]
fn test_untagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(untagged)]
enum Data {
A {
a: i32,
#[serde(flatten)]
flat: Flat,
},
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Flat {
b: i32,
}
let data = Data::A {
a: 0,
flat: Flat { b: 0 },
};
assert_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::Str("b"),
Token::I32(0),
Token::MapEnd,
],
);
}
+46 -3
View File
@@ -17,15 +17,15 @@ use std::ffi::{CString, OsString};
use std::net;
use std::num::Wrapping;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::Arc;
use std::rc::{Rc, Weak as RcWeak};
use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[cfg(feature = "unstable")]
use std::ffi::CStr;
extern crate serde;
use serde::Deserialize;
use serde::{Deserialize, Deserializer};
extern crate fnv;
use self::fnv::FnvHasher;
@@ -182,6 +182,27 @@ macro_rules! declare_error_tests {
}
}
#[derive(Debug)]
struct SkipPartialEq<T>(T);
impl<'de, T> Deserialize<'de> for SkipPartialEq<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize(deserializer).map(SkipPartialEq)
}
}
impl<T> PartialEq for SkipPartialEq<T> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) {
#[derive(PartialEq, Debug, Deserialize)]
struct IgnoreBase {
@@ -788,11 +809,33 @@ declare_tests! {
Token::Bool(true),
],
}
test_rc_weak_some {
SkipPartialEq(RcWeak::<bool>::new()) => &[
Token::Some,
Token::Bool(true),
],
}
test_rc_weak_none {
SkipPartialEq(RcWeak::<bool>::new()) => &[
Token::None,
],
}
test_arc {
Arc::new(true) => &[
Token::Bool(true),
],
}
test_arc_weak_some {
SkipPartialEq(ArcWeak::<bool>::new()) => &[
Token::Some,
Token::Bool(true),
],
}
test_arc_weak_none {
SkipPartialEq(ArcWeak::<bool>::new()) => &[
Token::None,
],
}
test_wrapping {
Wrapping(1usize) => &[
Token::U32(1),
+35
View File
@@ -567,6 +567,41 @@ fn test_gen() {
}
assert::<AssocDeriveMulti<i32, NoSerdeImpl>>();
#[derive(Serialize)]
#[serde(tag = "t", content = "c")]
enum EmptyAdjacentlyTagged {
#[allow(dead_code)]
Struct {},
#[allow(dead_code)]
Tuple(),
}
assert_ser::<EmptyAdjacentlyTagged>();
mod restricted {
mod inner {
#[derive(Serialize, Deserialize)]
struct Restricted {
pub(super) a: usize,
pub(in super::inner) b: usize,
}
}
}
#[derive(Deserialize)]
#[serde(tag = "t", content = "c")]
enum AdjacentlyTaggedVoid {}
#[derive(Serialize, Deserialize)]
enum SkippedVariant<T> {
#[serde(skip)]
#[allow(dead_code)]
T(T),
Unit,
}
assert::<SkippedVariant<X>>();
}
//////////////////////////////////////////////////////////////////////////
+3 -2
View File
@@ -17,8 +17,9 @@ extern crate serde_test;
mod bytes;
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens,
Token};
use self::serde_test::{
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token,
};
use std::collections::BTreeMap;
use std::marker::PhantomData;
+33 -2
View File
@@ -11,11 +11,12 @@ extern crate serde_derive;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::ffi::CString;
use std::mem;
use std::net;
use std::num::Wrapping;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::Arc;
use std::rc::{Rc, Weak as RcWeak};
use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH};
#[cfg(unix)]
@@ -398,11 +399,41 @@ declare_tests! {
Token::Bool(true),
],
}
test_rc_weak_some {
{
let rc = Rc::new(true);
mem::forget(rc.clone());
Rc::downgrade(&rc)
} => &[
Token::Some,
Token::Bool(true),
],
}
test_rc_weak_none {
RcWeak::<bool>::new() => &[
Token::None,
],
}
test_arc {
Arc::new(true) => &[
Token::Bool(true),
],
}
test_arc_weak_some {
{
let arc = Arc::new(true);
mem::forget(arc.clone());
Arc::downgrade(&arc)
} => &[
Token::Some,
Token::Bool(true),
],
}
test_arc_weak_none {
ArcWeak::<bool>::new() => &[
Token::None,
],
}
test_wrapping {
Wrapping(1usize) => &[
Token::U64(1),