Compare commits

...

49 Commits

Author SHA1 Message Date
David Tolnay 9cfcd78c87 Release 1.0.26 2017-12-27 17:33:32 -05:00
David Tolnay 4751627f1c Implement De/Serialize for PhantomData where T: ?Sized 2017-12-27 17:32:49 -05:00
David Tolnay ae59c6b6d2 Release 1.0.25 2017-12-23 23:33:59 -05:00
David Tolnay 4973d7a62d Suppress errors on rustfmt line overflow
Some of the serde_derive lines inside of quote!(...) are too long. Rustfmt
cannot fix these. Will need to follow up.
2017-12-23 20:27:56 -08:00
David Tolnay ed6a1de311 Auto format attributes on their own line 2017-12-23 20:24:57 -08:00
David Tolnay ab234be025 The rustfmt rfc style is now the default 2017-12-23 20:21:52 -08:00
David Tolnay ee75e6c0e9 Format with rustfmt-nightly 0.3.4 2017-12-23 20:17:52 -08:00
David Tolnay c2b390fe63 Merge pull request #1124 from serde-rs/in-place
Rename deserialize_from to deserialize_in_place
2017-12-23 19:56:29 -08:00
David Tolnay 56d5d7f761 Rename deserialize_from to deserialize_in_place 2017-12-17 10:46:44 -08:00
David Tolnay 0b89bc920e Merge pull request #1094 from Gankro/deserialize_from
Add and derive deserialize_from
2017-12-11 21:29:15 -08:00
David Tolnay 0dac13e4db Resolve conflict with pr 1115 2017-12-11 20:59:54 -08:00
David Tolnay 0c2e91f28a Merge branch serde-rs/master into Gankro/deserialize_from 2017-12-11 20:49:23 -08:00
David Tolnay 13e7bee0e6 Eliminate need for unwrap in deserialize_from_seq 2017-12-11 18:13:13 -08:00
David Tolnay 65104aca9c Remove need for allow(unreachable_code) 2017-12-11 17:55:23 -08:00
David Tolnay 9360094ba7 Revert main_body naming change
The naming here isn't great but no need to change it in this PR.
2017-12-10 23:19:31 -08:00
David Tolnay 3700779bfa More meaningful names and types for nop_reserve 2017-12-10 23:18:08 -08:00
David Tolnay d9e894911f Move all the deserialize_from derive code behind flag 2017-12-10 23:15:14 -08:00
David Tolnay 85e3ddc2b8 Less indentiation in deserialize_from_body 2017-12-10 23:04:44 -08:00
David Tolnay ccae35d92a Do not emit deserialize_from if every field has deserialize_with 2017-12-10 22:55:28 -08:00
David Tolnay 61ca928325 Can never see getters in a deserialize_from 2017-12-10 22:46:46 -08:00
David Tolnay a93f2ebff0 Enable deserialize_from in the test suite 2017-12-10 22:46:25 -08:00
David Tolnay a45f1ae915 Remove unused dev-dependency of serde_test on deserialize_from 2017-12-10 22:02:11 -08:00
David Tolnay 9641978481 Hide deserialize_from 2017-12-10 21:55:07 -08:00
David Tolnay ffd2017c6f Use the default deserialize_from for Option<T>
The custom one was functionally identical to the default implementation given by
the Deserialize trait. If someone has benchmarks that the custom one performs
better, we can put it back.
2017-12-10 21:27:44 -08:00
David Tolnay b7eb42aa6b Release 1.0.24 2017-12-09 14:43:55 -08:00
David Tolnay 750f8ba299 Clean up trailing whitespace 2017-12-09 14:42:59 -08:00
David Tolnay 49cdef074d Merge pull request #1115 from Binero/master
Solved #1105.
2017-12-08 08:57:31 -08:00
Jeroen Bollen aa86b04714 Adressed concerns raised by @oli-obk.
Specifically:
 - Change identation in `de.rs`.
 - Make `attr::Field` take a `attr::Default` as opposed to the entire parent `attr::Container`.
2017-12-08 15:13:05 +01:00
Jeroen Bollen c887a0b472 Solved #1105.
When a field should be skipped during deserialization, it will not use its own Default implementation
when the container structure has `#[serde(default)]` set.
2017-12-06 21:14:02 +01:00
Alexis Beingessner 34936be574 test deserialize_from 2017-12-04 13:29:03 -05:00
Alexis Beingessner e354dd0c7f Derive deserialize_from for tuples and structs
This adds a new "deserialize_from" feature (default off) that opts into
deriving deserialize_from with #[derive(Deserialize)].
2017-12-04 13:23:26 -05:00
Alexis Beingessner bc221abb04 Augment builtin std/core Deserialize impls to implement deserialize_from 2017-12-04 13:23:26 -05:00
Alexis Beingessner ab5e8780ab Add deserialize_from to Deserialize 2017-12-04 13:23:26 -05:00
David Tolnay 0c34e06e51 Merge pull request #1106 from khuey/inlines
Inline various deserialization helper methods.
2017-12-02 15:57:07 -08:00
Kyle Huey 4a0c4e0c25 Mark size_hint::cautious as inline. 2017-12-01 14:31:52 -08:00
David Tolnay 8c34e0940f Release 1.0.23 2017-11-29 22:26:32 -08:00
David Tolnay eb6bf16a51 Revert "Catch wrong field names length in serde_test"
There are at least two reasonable things to expect the len field to
check: the length of the fields array passed to deserialize_struct, or
the number of field tokens. Even beyond these, in some cases it can be
useful to test deserialization with a bogus len to test how the
Deserialize impl reacts to an incorrect size_hint.

This reverts commit 436cafb0a3 which was
released in serde_test 1.0.20.
2017-11-29 22:21:05 -08:00
David Tolnay 797d049db5 Release 1.0.22 2017-11-29 20:01:43 -08:00
David Tolnay d61a373f12 Merge pull request #1104 from serde-rs/abs
Fix missing absolute paths in deserialize_seq
2017-11-29 19:58:21 -08:00
David Tolnay e0eea551b4 Fix missing absolute paths in deserialize_seq 2017-11-29 19:45:22 -08:00
David Tolnay c650a92bf7 Update to compiletest-rs 0.3 to fix "every suggestion should have at least one span" 2017-11-24 17:12:58 -08:00
David Tolnay f218f4d7bf Release 1.0.21 2017-11-15 22:24:18 -08:00
Alex Shapiro 8c0a2015be Fix error when deserializing untagged enum
Serde's `ContentDeserializer` and `ContentRefDeserializer`
cannot deserialize struct enum variant associated data when
that data is encoded as a sequence. This failure leads to
errors when decoding an enum nested in another untagged
enum. For example:

    #[derive(Serialize, Deserialize)]
    #[serde(untagged)]
    enum Foo {
        A(Bar),
    }

    #[derive(Serialize, Deserialize)]
    enum Bar {
        B{f1: String},
    }

    let data1 = Foo::A(Bar::B{f1: "Hello".into()});
    let bytes = rmp_serde::to_vec(&data1).unwrap();
    let data2 = rmp_serde::from_slice::<Foo>(&bytes).unwrap();

Deserializing fails with the error `Syntax("data did not
match any variant of untagged enum Foo")`, but the
underlying failure occurs when decoding the associated data
of `Bar::B`.

This pull request fixes the issue by allowing
`ContentDeserializer` and `ContentRefDeserializer` to
deserialize sequence-encoded struct enum variant data.
2017-11-15 21:56:33 -08:00
David Tolnay 4773863e3a Release 1.0.20 2017-11-12 10:29:08 -08:00
David Tolnay 80cd9c7617 Merge pull request #1091 from serde-rs/fields-len
Catch wrong field names length in serde_test
2017-11-12 10:28:26 -08:00
David Tolnay 436cafb0a3 Catch wrong field names length in serde_test 2017-11-12 10:16:43 -08:00
David Tolnay 98bb02e9b4 Whitelist use of Debug in serde_test 2017-11-07 10:00:18 -08:00
David Tolnay 142439088c Merge pull request #1086 from Marwes/better_errors
Print the contents of the expected token when a serialize assert fails
2017-11-07 09:53:58 -08:00
Markus Westerlind ce81288235 Print the contents of the expected token when a serialize assert fails
Before
```
expected Token::Str but serialized as Str(“F9168C5E-CEB2-4FAA-B6BF-329BF39FA1E4")
```
After
```
expected Token::Str(“f9168c5e-ceb2-4faa-b6bf-329bf39fa1e4”) but serialized as Str(“F9168C5E-CEB2-4FAA-B6BF-329BF39FA1E4")
```
2017-11-07 14:22:42 +01:00
43 changed files with 3058 additions and 1814 deletions
+2 -5
View File
@@ -1,5 +1,2 @@
fn_args_layout = "Block"
array_layout = "Block"
where_style = "Rfc"
generics_indent = "Block"
fn_call_style = "Block"
error_on_line_overflow = false
same_line_attributes = false
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.19" # remember to update html_root_url
version = "1.0.26" # 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"
+1 -1
View File
@@ -8,7 +8,7 @@
use lib::*;
use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// An efficient way of discarding data from a deserializer.
///
+302 -83
View File
@@ -15,6 +15,7 @@ use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, Va
use de::MapAccess;
use de::from_primitive::FromPrimitive;
use private::de::InPlaceSeed;
#[cfg(any(feature = "std", feature = "alloc"))]
use private::de::size_hint;
@@ -210,6 +211,8 @@ impl<'de> Deserialize<'de> for char {
#[cfg(any(feature = "std", feature = "alloc"))]
struct StringVisitor;
#[cfg(any(feature = "std", feature = "alloc"))]
struct StringInPlaceVisitor<'a>(&'a mut String);
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Visitor<'de> for StringVisitor {
@@ -249,7 +252,66 @@ impl<'de> Visitor<'de> for StringVisitor {
{
match String::from_utf8(v) {
Ok(s) => Ok(s),
Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self),),
Err(e) => Err(Error::invalid_value(
Unexpected::Bytes(&e.into_bytes()),
&self,
)),
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_str<E>(self, v: &str) -> Result<(), E>
where
E: Error,
{
self.0.clear();
self.0.push_str(v);
Ok(())
}
fn visit_string<E>(self, v: String) -> Result<(), E>
where
E: Error,
{
*self.0 = v;
Ok(())
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<(), E>
where
E: Error,
{
match str::from_utf8(v) {
Ok(s) => {
self.0.clear();
self.0.push_str(s);
Ok(())
}
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
}
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<(), E>
where
E: Error,
{
match String::from_utf8(v) {
Ok(s) => {
*self.0 = s;
Ok(())
}
Err(e) => Err(Error::invalid_value(
Unexpected::Bytes(&e.into_bytes()),
&self,
)),
}
}
}
@@ -262,6 +324,13 @@ impl<'de> Deserialize<'de> for String {
{
deserializer.deserialize_string(StringVisitor)
}
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_string(StringInPlaceVisitor(place))
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -465,17 +534,25 @@ where
where
D: Deserializer<'de>,
{
deserializer.deserialize_option(OptionVisitor { marker: PhantomData })
deserializer.deserialize_option(OptionVisitor {
marker: PhantomData,
})
}
// The Some variant's repr is opaque, so we can't play cute tricks with its
// tag to have deserialize_in_place build the content in place unconditionally.
//
// FIXME: investigate whether branching on the old value being Some to
// deserialize_in_place the value is profitable (probably data-dependent?)
}
////////////////////////////////////////////////////////////////////////////////
struct PhantomDataVisitor<T> {
struct PhantomDataVisitor<T: ?Sized> {
marker: PhantomData<T>,
}
impl<'de, T> Visitor<'de> for PhantomDataVisitor<T> {
impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
type Value = PhantomData<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
@@ -491,12 +568,14 @@ impl<'de, T> Visitor<'de> for PhantomDataVisitor<T> {
}
}
impl<'de, T> Deserialize<'de> for PhantomData<T> {
impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error>
where
D: Deserializer<'de>,
{
let visitor = PhantomDataVisitor { marker: PhantomData };
let visitor = PhantomDataVisitor {
marker: PhantomData,
};
deserializer.deserialize_unit_struct("PhantomData", visitor)
}
}
@@ -509,7 +588,9 @@ macro_rules! seq_impl {
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
$access:ident,
$ctor:expr,
$clear:expr,
$with_capacity:expr,
$reserve:expr,
$insert:expr
) => {
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
@@ -554,16 +635,59 @@ macro_rules! seq_impl {
let visitor = SeqVisitor { marker: PhantomData };
deserializer.deserialize_seq(visitor)
}
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
struct SeqInPlaceVisitor<'a, T: 'a $(, $typaram: 'a)*>(&'a mut $ty<T $(, $typaram)*>);
impl<'a, 'de, T $(, $typaram)*> Visitor<'de> for SeqInPlaceVisitor<'a, T $(, $typaram)*>
where
T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*,
$($typaram: $bound1 $(+ $bound2)*,)*
{
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}
#[inline]
fn visit_seq<A>(mut self, mut $access: A) -> Result<(), A::Error>
where
A: SeqAccess<'de>,
{
$clear(&mut self.0);
$reserve(&mut self.0, size_hint::cautious($access.size_hint()));
// FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList)
while let Some(value) = try!($access.next_element()) {
$insert(&mut self.0, value);
}
Ok(())
}
}
deserializer.deserialize_seq(SeqInPlaceVisitor(place))
}
}
}
}
// Dummy impl of reserve
#[cfg(any(feature = "std", feature = "alloc"))]
fn nop_reserve<T>(_seq: T, _n: usize) {}
#[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(
BinaryHeap<T: Ord>,
seq,
BinaryHeap::new(),
BinaryHeap::clear,
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
BinaryHeap::reserve,
BinaryHeap::push);
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -571,7 +695,9 @@ seq_impl!(
BTreeSet<T: Eq + Ord>,
seq,
BTreeSet::new(),
BTreeSet::clear,
BTreeSet::new(),
nop_reserve,
BTreeSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -579,15 +705,20 @@ seq_impl!(
LinkedList<T>,
seq,
LinkedList::new(),
LinkedList::clear,
LinkedList::new(),
LinkedList::push_back);
nop_reserve,
LinkedList::push_back
);
#[cfg(feature = "std")]
seq_impl!(
HashSet<T: Eq + Hash, S: BuildHasher + Default>,
seq,
HashSet::with_hasher(S::default()),
HashSet::clear,
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
HashSet::reserve,
HashSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -595,26 +726,35 @@ seq_impl!(
Vec<T>,
seq,
Vec::new(),
Vec::clear,
Vec::with_capacity(size_hint::cautious(seq.size_hint())),
Vec::push);
Vec::reserve,
Vec::push
);
#[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(
VecDeque<T>,
seq,
VecDeque::new(),
VecDeque::clear,
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
VecDeque::push_back);
VecDeque::reserve,
VecDeque::push_back
);
////////////////////////////////////////////////////////////////////////////////
struct ArrayVisitor<A> {
marker: PhantomData<A>,
}
struct ArrayInPlaceVisitor<'a, A: 'a>(&'a mut A);
impl<A> ArrayVisitor<A> {
fn new() -> Self {
ArrayVisitor { marker: PhantomData }
ArrayVisitor {
marker: PhantomData,
}
}
}
@@ -673,6 +813,35 @@ macro_rules! array_impls {
}
}
impl<'a, 'de, T> Visitor<'de> for ArrayInPlaceVisitor<'a, [T; $len]>
where
T: Deserialize<'de>,
{
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("an array of length ", $len))
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
where
A: SeqAccess<'de>,
{
let mut fail_idx = None;
for (idx, dest) in self.0[..].iter_mut().enumerate() {
if try!(seq.next_element_seed(InPlaceSeed(dest))).is_none() {
fail_idx = Some(idx);
break;
}
}
if let Some(idx) = fail_idx {
return Err(Error::invalid_length(idx, &self));
}
Ok(())
}
}
impl<'de, T> Deserialize<'de> for [T; $len]
where
T: Deserialize<'de>,
@@ -683,6 +852,13 @@ macro_rules! array_impls {
{
deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new())
}
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple($len, ArrayInPlaceVisitor(place))
}
}
)+
}
@@ -726,49 +902,76 @@ array_impls! {
////////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls {
($($len:tt $visitor:ident => ($($n:tt $name:ident)+))+) => {
($($len:tt => ($($n:tt $name:ident)+))+) => {
$(
struct $visitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<$($name,)+> $visitor<$($name,)+> {
fn new() -> Self {
$visitor { marker: PhantomData }
}
}
impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for $visitor<$($name,)+> {
type Value = ($($name,)+);
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("a tuple of size ", $len))
}
#[inline]
#[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
where
A: SeqAccess<'de>,
{
$(
let $name = match try!(seq.next_element()) {
Some(value) => value,
None => return Err(Error::invalid_length($n, &self)),
};
)+
Ok(($($name,)+))
}
}
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple($len, $visitor::new())
struct TupleVisitor<$($name,)+> {
marker: PhantomData<($($name,)+)>,
}
impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> {
type Value = ($($name,)+);
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("a tuple of size ", $len))
}
#[inline]
#[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
where
A: SeqAccess<'de>,
{
$(
let $name = match try!(seq.next_element()) {
Some(value) => value,
None => return Err(Error::invalid_length($n, &self)),
};
)+
Ok(($($name,)+))
}
}
deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData })
}
#[inline]
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
struct TupleInPlaceVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+));
impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleInPlaceVisitor<'a, $($name,)+> {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(concat!("a tuple of size ", $len))
}
#[inline]
#[allow(non_snake_case)]
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
where
A: SeqAccess<'de>,
{
$(
if try!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() {
return Err(Error::invalid_length($n, &self));
}
)+
Ok(())
}
}
deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place))
}
}
)+
@@ -776,22 +979,22 @@ macro_rules! tuple_impls {
}
tuple_impls! {
1 TupleVisitor1 => (0 T0)
2 TupleVisitor2 => (0 T0 1 T1)
3 TupleVisitor3 => (0 T0 1 T1 2 T2)
4 TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3)
5 TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 TupleVisitor7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 TupleVisitor8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 TupleVisitor9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 TupleVisitor10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 TupleVisitor11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
12 TupleVisitor12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
13 TupleVisitor13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
14 TupleVisitor14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
15 TupleVisitor15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
16 TupleVisitor16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
1 => (0 T0)
2 => (0 T0 1 T1)
3 => (0 T0 1 T1 2 T2)
4 => (0 T0 1 T1 2 T2 3 T3)
5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
}
////////////////////////////////////////////////////////////////////////////////
@@ -1068,7 +1271,12 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
parse_socket_impl!(net::SocketAddrV4, net::SocketAddrV4::new);
#[cfg(feature = "std")]
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(ip, port, 0, 0));
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(
ip,
port,
0,
0
));
////////////////////////////////////////////////////////////////////////////////
@@ -1179,7 +1387,9 @@ impl<'de> Visitor<'de> for OsStringVisitor {
match try!(data.variant()) {
(OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec),
(OsStringKind::Windows, _) => Err(Error::custom("cannot deserialize Windows OS string on Unix",),),
(OsStringKind::Windows, _) => Err(Error::custom(
"cannot deserialize Windows OS string on Unix",
)),
}
}
@@ -1191,11 +1401,11 @@ impl<'de> Visitor<'de> for OsStringVisitor {
use std::os::windows::ffi::OsStringExt;
match try!(data.variant()) {
(OsStringKind::Windows, v) => {
v.newtype_variant::<Vec<u16>>()
.map(|vec| OsString::from_wide(&vec))
}
(OsStringKind::Unix, _) => Err(Error::custom("cannot deserialize Unix OS string on Windows",),),
(OsStringKind::Windows, v) => v.newtype_variant::<Vec<u16>>()
.map(|vec| OsString::from_wide(&vec)),
(OsStringKind::Unix, _) => Err(Error::custom(
"cannot deserialize Unix OS string on Windows",
)),
}
}
}
@@ -1521,13 +1731,17 @@ impl<'de> Deserialize<'de> for SystemTime {
match key {
Field::Secs => {
if secs.is_some() {
return Err(<A::Error as Error>::duplicate_field("secs_since_epoch"));
return Err(<A::Error as Error>::duplicate_field(
"secs_since_epoch",
));
}
secs = Some(try!(map.next_value()));
}
Field::Nanos => {
if nanos.is_some() {
return Err(<A::Error as Error>::duplicate_field("nanos_since_epoch"));
return Err(<A::Error as Error>::duplicate_field(
"nanos_since_epoch",
));
}
nanos = Some(try!(map.next_value()));
}
@@ -1691,7 +1905,13 @@ where
}
const FIELDS: &'static [&'static str] = &["start", "end"];
deserializer.deserialize_struct("Range", FIELDS, RangeVisitor { phantom: PhantomData })
deserializer.deserialize_struct(
"Range",
FIELDS,
RangeVisitor {
phantom: PhantomData,
},
)
}
}
@@ -1756,9 +1976,10 @@ where
match value {
0 => Ok(Field::Ok),
1 => Ok(Field::Err),
_ => {
Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),)
}
_ => Err(Error::invalid_value(
Unexpected::Unsigned(value as u64),
&self,
)),
}
}
@@ -1780,14 +2001,12 @@ where
match value {
b"Ok" => Ok(Field::Ok),
b"Err" => Ok(Field::Err),
_ => {
match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
Err(_) => {
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
}
_ => match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
Err(_) => {
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
}
}
},
}
}
}
@@ -1831,7 +2050,7 @@ where
#[cfg(feature = "std")]
impl<'de, T> Deserialize<'de> for Wrapping<T>
where
T: Deserialize<'de>
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error>
where
+32 -1
View File
@@ -504,6 +504,35 @@ pub trait Deserialize<'de>: Sized {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>;
/// Deserializes a value into `self` from the given Deserializer.
///
/// The purpose of this method is to allow the deserializer to reuse
/// resources and avoid copies. As such, if this method returns an error,
/// `self` will be in an indeterminate state where some parts of the struct
/// have been overwritten. Although whatever state that is will be
/// memory-safe.
///
/// This is generally useful when repeateadly deserializing values that
/// are processed one at a time, where the value of `self` doesn't matter
/// when the next deserialization occurs.
///
/// If you manually implement this, your recursive deserializations should
/// use `deserialize_in_place`.
///
/// This method is stable and an official public API, but hidden from the
/// documentation because it is almost never what newbies are looking for.
/// Showing it in rustdoc would cause it to be featured more prominently
/// than it deserves.
#[doc(hidden)]
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
// Default implementation just delegates to `deserialize` impl.
*place = Deserialize::deserialize(deserializer)?;
Ok(())
}
}
/// A data structure that can be deserialized without borrowing any data from
@@ -1078,7 +1107,9 @@ pub trait Deserializer<'de>: Sized {
/// change, as a value serialized in human-readable mode is not required to
/// deserialize from the same data in compact mode.
#[inline]
fn is_human_readable(&self) -> bool { true }
fn is_human_readable(&self) -> bool {
true
}
}
////////////////////////////////////////////////////////////////////////////////
+34 -14
View File
@@ -37,7 +37,7 @@
use lib::*;
use de::{self, IntoDeserializer, Expected, SeqAccess};
use de::{self, Expected, IntoDeserializer, SeqAccess};
use private::de::size_hint;
use ser;
use self::private::{First, Second};
@@ -62,7 +62,9 @@ impl de::Error for Error {
where
T: Display,
{
Error { err: msg.to_string().into_boxed_str() }
Error {
err: msg.to_string().into_boxed_str(),
}
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
@@ -112,7 +114,9 @@ where
type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer { marker: PhantomData }
UnitDeserializer {
marker: PhantomData,
}
}
}
@@ -658,7 +662,10 @@ where
} else {
// First argument is the number of elements in the data, second
// argument is the number of elements expected by the Deserialize.
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInSeq(self.count)),)
Err(de::Error::invalid_length(
self.count + remaining,
&ExpectedInSeq(self.count),
))
}
}
}
@@ -852,7 +859,10 @@ where
} else {
// First argument is the number of elements in the data, second
// argument is the number of elements expected by the Deserialize.
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count)),)
Err(de::Error::invalid_length(
self.count + remaining,
&ExpectedInMap(self.count),
))
}
}
}
@@ -901,11 +911,7 @@ where
Ok(value)
}
fn deserialize_tuple<V>(
self,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
@@ -1223,7 +1229,12 @@ mod private {
}
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
(t, UnitOnly { marker: PhantomData })
(
t,
UnitOnly {
marker: PhantomData,
},
)
}
impl<'de, E> de::VariantAccess<'de> for UnitOnly<E>
@@ -1240,14 +1251,20 @@ mod private {
where
T: de::DeserializeSeed<'de>,
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"),)
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"newtype variant",
))
}
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"),)
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"tuple variant",
))
}
fn struct_variant<V>(
@@ -1258,7 +1275,10 @@ mod private {
where
V: de::Visitor<'de>,
{
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"),)
Err(de::Error::invalid_type(
Unexpected::UnitVariant,
&"struct variant",
))
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ pub use lib::default::Default;
pub use lib::fmt::{self, Formatter};
pub use lib::marker::PhantomData;
pub use lib::option::Option::{self, None, Some};
pub use lib::result::Result::{self, Ok, Err};
pub use lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy;
+11 -21
View File
@@ -79,30 +79,21 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.19")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.26")]
// 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
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(
cast_lossless,
const_static_lifetime,
doc_markdown,
linkedlist,
needless_pass_by_value,
type_complexity,
unreadable_literal,
zero_prefixed_literal,
))]
#![cfg_attr(feature = "cargo-clippy",
allow(cast_lossless, const_static_lifetime, doc_markdown, linkedlist,
needless_pass_by_value, type_complexity, unreadable_literal,
zero_prefixed_literal))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
@@ -125,7 +116,6 @@
empty_enum,
use_debug,
))]
// Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)]
@@ -149,8 +139,8 @@ mod lib {
}
pub use self::core::{cmp, iter, mem, ops, slice, str};
pub use self::core::{i8, i16, i32, i64, isize};
pub use self::core::{u8, u16, u32, u64, usize};
pub use self::core::{isize, i16, i32, i64, i8};
pub use self::core::{usize, u16, u32, u64, u8};
pub use self::core::{f32, f64};
pub use self::core::cell::{Cell, RefCell};
@@ -193,9 +183,9 @@ mod lib {
pub use alloc::arc::Arc;
#[cfg(feature = "std")]
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "std")]
pub use std::{error, net};
@@ -203,9 +193,9 @@ mod lib {
#[cfg(feature = "std")]
pub use std::collections::{HashMap, HashSet};
#[cfg(feature = "std")]
pub use std::ffi::{CString, CStr, OsString, OsStr};
pub use std::ffi::{CStr, CString, OsStr, OsString};
#[cfg(feature = "std")]
pub use std::hash::{Hash, BuildHasher};
pub use std::hash::{BuildHasher, Hash};
#[cfg(feature = "std")]
pub use std::io::Write;
#[cfg(feature = "std")]
+162 -102
View File
@@ -8,16 +8,16 @@
use lib::*;
use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor};
use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
#[cfg(any(feature = "std", feature = "alloc"))]
use de::Unexpected;
#[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer,
TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor,
TagContentOtherField, TagContentOtherFieldVisitor,
InternallyTaggedUnitVisitor, UntaggedUnitVisitor};
pub use self::content::{Content, ContentDeserializer, ContentRefDeserializer,
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.
@@ -120,7 +120,10 @@ where
{
match String::from_utf8(v) {
Ok(s) => Ok(Cow::Owned(s)),
Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self),),
Err(e) => Err(Error::invalid_value(
Unexpected::Bytes(&e.into_bytes()),
&self,
)),
}
}
}
@@ -198,6 +201,7 @@ pub mod size_hint {
helper(iter.size_hint())
}
#[inline]
pub fn cautious(hint: Option<usize>) -> usize {
cmp::min(hint.unwrap_or(0), 4096)
}
@@ -224,8 +228,8 @@ mod content {
use lib::*;
use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, MapAccess,
EnumAccess, Unexpected};
use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, MapAccess, SeqAccess,
Unexpected, Visitor};
use super::size_hint;
/// Used from generated code to buffer the contents of the Deserializer when
@@ -501,7 +505,9 @@ mod content {
where
V: EnumAccess<'de>,
{
Err(de::Error::custom("untagged and internally tagged enums do not support enum input",),)
Err(de::Error::custom(
"untagged and internally tagged enums do not support enum input",
))
}
}
@@ -520,7 +526,10 @@ mod content {
impl<'de> TagOrContentVisitor<'de> {
fn new(name: &'static str) -> Self {
TagOrContentVisitor { name: name, value: PhantomData }
TagOrContentVisitor {
name: name,
value: PhantomData,
}
}
}
@@ -557,7 +566,9 @@ mod content {
where
F: de::Error,
{
ContentVisitor::new().visit_i8(value).map(TagOrContent::Content)
ContentVisitor::new()
.visit_i8(value)
.map(TagOrContent::Content)
}
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
@@ -591,7 +602,9 @@ mod content {
where
F: de::Error,
{
ContentVisitor::new().visit_u8(value).map(TagOrContent::Content)
ContentVisitor::new()
.visit_u8(value)
.map(TagOrContent::Content)
}
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
@@ -730,14 +743,18 @@ mod content {
where
F: de::Error,
{
ContentVisitor::new().visit_unit().map(TagOrContent::Content)
ContentVisitor::new()
.visit_unit()
.map(TagOrContent::Content)
}
fn visit_none<F>(self) -> Result<Self::Value, F>
where
F: de::Error,
{
ContentVisitor::new().visit_none().map(TagOrContent::Content)
ContentVisitor::new()
.visit_none()
.map(TagOrContent::Content)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
@@ -860,8 +877,7 @@ mod content {
{
let mut tag = None;
let mut vec = Vec::with_capacity(size_hint::cautious(map.size_hint()));
while let Some(k) =
try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
match k {
TagOrContent::Tag => {
if tag.is_some() {
@@ -877,14 +893,10 @@ mod content {
}
match tag {
None => Err(de::Error::missing_field(self.tag_name)),
Some(tag) => {
Ok(
TaggedContent {
tag: tag,
content: Content::Map(vec),
},
)
}
Some(tag) => Ok(TaggedContent {
tag: tag,
content: Content::Map(vec),
}),
}
}
}
@@ -966,7 +978,11 @@ mod content {
type Value = TagContentOtherField;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{:?}, {:?}, or other ignored fields", self.tag, self.content)
write!(
formatter,
"{:?}, {:?}, or other ignored fields",
self.tag, self.content
)
}
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
@@ -1030,10 +1046,8 @@ mod content {
Ok(value)
}
Content::Map(v) => {
let map = v.into_iter().map(|(k, v)| {
(ContentDeserializer::new(k),
ContentDeserializer::new(v))
});
let map = v.into_iter()
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
@@ -1080,44 +1094,41 @@ mod content {
let (variant, value) = match iter.next() {
Some(v) => v,
None => {
return Err(
de::Error::invalid_value(
de::Unexpected::Map,
&"map with a single key",
),
);
return Err(de::Error::invalid_value(
de::Unexpected::Map,
&"map with a single key",
));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(
de::Error::invalid_value(
de::Unexpected::Map,
&"map with a single key",
),
);
return Err(de::Error::invalid_value(
de::Unexpected::Map,
&"map with a single key",
));
}
(variant, Some(value))
}
s @ Content::String(_) | s @ Content::Str(_) => (s, None),
other => {
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),);
return Err(de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
}
};
visitor.visit_enum(
EnumDeserializer {
variant: variant,
value: value,
err: PhantomData,
},
)
visitor.visit_enum(EnumDeserializer {
variant: variant,
value: value,
err: PhantomData,
})
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
visitor: V
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
@@ -1215,9 +1226,10 @@ mod content {
{
match self.value {
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
None => {
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"),)
}
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"newtype variant",
)),
}
}
@@ -1229,8 +1241,14 @@ mod content {
Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant"),),
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"),),
Some(other) => Err(de::Error::invalid_type(
other.unexpected(),
&"tuple variant",
)),
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"tuple variant",
)),
}
}
@@ -1246,8 +1264,17 @@ mod content {
Some(Content::Map(v)) => {
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),),
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(
other.unexpected(),
&"struct variant",
)),
_ => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"struct variant",
)),
}
}
}
@@ -1315,10 +1342,7 @@ mod content {
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some(value) => {
seed.deserialize(ContentDeserializer::new(value))
.map(Some)
}
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
None => Ok(None),
}
}
@@ -1454,12 +1478,12 @@ mod content {
Ok(value)
}
Content::Map(ref v) => {
let map = v.into_iter()
.map(
|&(ref k, ref v)| {
(ContentRefDeserializer::new(k), ContentRefDeserializer::new(v))
},
);
let map = v.into_iter().map(|&(ref k, ref v)| {
(
ContentRefDeserializer::new(k),
ContentRefDeserializer::new(v),
)
});
let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end());
@@ -1502,38 +1526,35 @@ mod content {
let &(ref variant, ref value) = match iter.next() {
Some(v) => v,
None => {
return Err(
de::Error::invalid_value(
de::Unexpected::Map,
&"map with a single key",
),
);
return Err(de::Error::invalid_value(
de::Unexpected::Map,
&"map with a single key",
));
}
};
// enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() {
return Err(
de::Error::invalid_value(
de::Unexpected::Map,
&"map with a single key",
),
);
return Err(de::Error::invalid_value(
de::Unexpected::Map,
&"map with a single key",
));
}
(variant, Some(value))
}
ref s @ Content::String(_) | ref s @ Content::Str(_) => (s, None),
ref other => {
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),);
return Err(de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
}
};
visitor.visit_enum(
EnumRefDeserializer {
variant: variant,
value: value,
err: PhantomData,
},
)
visitor.visit_enum(EnumRefDeserializer {
variant: variant,
value: value,
err: PhantomData,
})
}
forward_to_deserialize_any! {
@@ -1609,9 +1630,10 @@ mod content {
{
match self.value {
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
None => {
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"),)
}
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"newtype variant",
)),
}
}
@@ -1623,8 +1645,14 @@ mod content {
Some(&Content::Seq(ref v)) => {
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant"),),
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"),),
Some(other) => Err(de::Error::invalid_type(
other.unexpected(),
&"tuple variant",
)),
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"tuple variant",
)),
}
}
@@ -1640,8 +1668,17 @@ mod content {
Some(&Content::Map(ref v)) => {
de::Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),),
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
Some(&Content::Seq(ref v)) => {
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
}
Some(other) => Err(de::Error::invalid_type(
other.unexpected(),
&"struct variant",
)),
_ => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"struct variant",
)),
}
}
}
@@ -1709,10 +1746,8 @@ mod content {
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some(value) => {
seed.deserialize(ContentRefDeserializer::new(value))
.map(Some)
}
Some(value) => seed.deserialize(ContentRefDeserializer::new(value))
.map(Some),
None => Ok(None),
}
}
@@ -1757,8 +1792,7 @@ mod content {
match self.iter.next() {
Some(&(ref key, ref value)) => {
self.value = Some(value);
seed.deserialize(ContentRefDeserializer::new(key))
.map(Some)
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
}
None => Ok(None),
}
@@ -1844,7 +1878,11 @@ mod content {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name)
write!(
formatter,
"unit variant {}::{}",
self.type_name, self.variant_name
)
}
fn visit_seq<S>(self, _: S) -> Result<(), S::Error>
@@ -1884,7 +1922,11 @@ mod content {
type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name)
write!(
formatter,
"unit variant {}::{}",
self.type_name, self.variant_name
)
}
fn visit_unit<E>(self) -> Result<(), E>
@@ -2002,3 +2044,21 @@ where
map struct enum identifier ignored_any
}
}
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
///
/// Wraps a mutable reference and calls deserialize_in_place on it.
pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T);
impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T>
where
T: Deserialize<'de>,
{
type Value = ();
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
T::deserialize_in_place(deserializer, self.0)
}
}
+95 -84
View File
@@ -8,10 +8,10 @@
use lib::*;
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
use self::content::{SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue};
/// Used to check that serde(getter) attributes return the expected type.
/// Not public API.
@@ -32,15 +32,13 @@ where
S: Serializer,
T: Serialize,
{
value.serialize(
TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
},
)
value.serialize(TaggedSerializer {
type_ident: type_ident,
variant_ident: variant_ident,
tag: tag,
variant_name: variant_name,
delegate: serializer,
})
}
struct TaggedSerializer<S> {
@@ -92,13 +90,10 @@ where
S: Serializer,
{
fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom(
format_args!(
ser::Error::custom(format_args!(
"cannot serialize tagged newtype variant {}::{} containing {}",
self.type_ident,
self.variant_ident,
what),
)
self.type_ident, self.variant_ident, what
))
}
}
@@ -281,7 +276,11 @@ where
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len),)
Ok(SerializeTupleVariantAsMapValue::new(
map,
inner_variant,
len,
))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -324,7 +323,11 @@ where
let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant));
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),)
Ok(SerializeStructVariantAsMapValue::new(
map,
inner_variant,
len,
))
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
@@ -402,7 +405,10 @@ mod content {
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
try!(
self.map
.serialize_value(&Content::TupleStruct(self.name, self.fields))
);
self.map.end()
}
}
@@ -444,7 +450,10 @@ mod content {
}
fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
try!(
self.map
.serialize_value(&Content::Struct(self.name, self.fields))
);
self.map.end()
}
}
@@ -485,7 +494,12 @@ mod content {
TupleVariant(&'static str, u32, &'static str, Vec<Content>),
Map(Vec<(Content, Content)>),
Struct(&'static str, Vec<(&'static str, Content)>),
StructVariant(&'static str, u32, &'static str, Vec<(&'static str, Content)>),
StructVariant(
&'static str,
u32,
&'static str,
Vec<(&'static str, Content)>,
),
}
impl Serialize for Content {
@@ -687,7 +701,10 @@ mod content {
where
T: Serialize,
{
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))),)
Ok(Content::NewtypeStruct(
name,
Box::new(try!(value.serialize(self))),
))
}
fn serialize_newtype_variant<T: ?Sized>(
@@ -700,32 +717,26 @@ mod content {
where
T: Serialize,
{
Ok(
Content::NewtypeVariant(
name,
variant_index,
variant,
Box::new(try!(value.serialize(self))),
),
)
Ok(Content::NewtypeVariant(
name,
variant_index,
variant,
Box::new(try!(value.serialize(self))),
))
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
Ok(
SerializeSeq {
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
},
)
Ok(SerializeSeq {
elements: Vec::with_capacity(len.unwrap_or(0)),
error: PhantomData,
})
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
Ok(
SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeTuple {
elements: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_struct(
@@ -733,13 +744,11 @@ mod content {
name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, E> {
Ok(
SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeTupleStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_tuple_variant(
@@ -749,25 +758,21 @@ mod content {
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, E> {
Ok(
SerializeTupleVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeTupleVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
Ok(
SerializeMap {
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
},
)
Ok(SerializeMap {
entries: Vec::with_capacity(len.unwrap_or(0)),
key: None,
error: PhantomData,
})
}
fn serialize_struct(
@@ -775,13 +780,11 @@ mod content {
name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, E> {
Ok(
SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeStruct {
name: name,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
fn serialize_struct_variant(
@@ -791,15 +794,13 @@ mod content {
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, E> {
Ok(
SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
},
)
Ok(SerializeStructVariant {
name: name,
variant_index: variant_index,
variant: variant,
fields: Vec::with_capacity(len),
error: PhantomData,
})
}
}
@@ -907,7 +908,12 @@ mod content {
}
fn end(self) -> Result<Content, E> {
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields),)
Ok(Content::TupleVariant(
self.name,
self.variant_index,
self.variant,
self.fields,
))
}
}
@@ -1013,7 +1019,12 @@ mod content {
}
fn end(self) -> Result<Content, E> {
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields),)
Ok(Content::StructVariant(
self.name,
self.variant_index,
self.variant,
self.fields,
))
}
}
}
+19 -11
View File
@@ -111,7 +111,7 @@ where
////////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for PhantomData<T> {
impl<T: ?Sized> Serialize for PhantomData<T> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -464,7 +464,8 @@ impl Serialize for SystemTime {
S: Serializer,
{
use super::SerializeStruct;
let duration_since_epoch = self.duration_since(UNIX_EPOCH).expect("SystemTime must be later than UNIX_EPOCH");
let duration_since_epoch = self.duration_since(UNIX_EPOCH)
.expect("SystemTime must be later than UNIX_EPOCH");
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
@@ -513,10 +514,12 @@ impl Serialize for net::IpAddr {
}
} else {
match *self {
net::IpAddr::V4(ref a) =>
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a),
net::IpAddr::V6(ref a) =>
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a),
net::IpAddr::V4(ref a) => {
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a)
}
net::IpAddr::V6(ref a) => {
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a)
}
}
}
}
@@ -567,10 +570,12 @@ impl Serialize for net::SocketAddr {
}
} else {
match *self {
net::SocketAddr::V4(ref addr) =>
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr),
net::SocketAddr::V6(ref addr) =>
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr),
net::SocketAddr::V4(ref addr) => {
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr)
}
net::SocketAddr::V6(ref addr) => {
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr)
}
}
}
}
@@ -600,7 +605,10 @@ impl Serialize for net::SocketAddrV6 {
{
if serializer.is_human_readable() {
const MAX_LEN: usize = 47;
debug_assert_eq!(MAX_LEN, "[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len());
debug_assert_eq!(
MAX_LEN,
"[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len()
);
serialize_display_bounded_length!(self, MAX_LEN, serializer)
} else {
(self.ip(), self.port()).serialize(serializer)
+2 -2
View File
@@ -10,8 +10,8 @@
use lib::*;
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
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.
+3 -1
View File
@@ -1412,7 +1412,9 @@ pub trait Serializer: Sized {
/// change, as a value serialized in human-readable mode is not required to
/// deserialize from the same data in compact mode.
#[inline]
fn is_human_readable(&self) -> bool { true }
fn is_human_readable(&self) -> bool {
true
}
}
/// Returned from `Serializer::serialize_seq`.
+6 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.19" # remember to update html_root_url
version = "1.0.26" # 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)]"
@@ -14,13 +14,17 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-
[badges]
travis-ci = { repository = "serde-rs/serde" }
[features]
default = []
deserialize_in_place = []
[lib]
name = "serde_derive"
proc-macro = true
[dependencies]
quote = "0.3.8"
serde_derive_internals = { version = "=0.17.0", default-features = false, path = "../serde_derive_internals" }
serde_derive_internals = { version = "=0.18.1", default-features = false, path = "../serde_derive_internals" }
syn = { version = "0.11", features = ["visit"] }
[dev-dependencies]
+51 -67
View File
@@ -27,14 +27,10 @@ pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
ty_params: generics
.ty_params
.iter()
.map(
|ty_param| {
syn::TyParam {
default: None,
..ty_param.clone()
}
},
)
.map(|ty_param| syn::TyParam {
default: None,
..ty_param.clone()
})
.collect(),
..generics.clone()
}
@@ -137,17 +133,15 @@ where
relevant_ty_params: HashSet::new(),
};
match cont.body {
Body::Enum(ref variants) => {
for variant in variants.iter() {
let relevant_fields = variant
.fields
.iter()
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
for field in relevant_fields {
visit::walk_ty(&mut visitor, field.ty);
}
Body::Enum(ref variants) => for variant in variants.iter() {
let relevant_fields = variant
.fields
.iter()
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
for field in relevant_fields {
visit::walk_ty(&mut visitor, field.ty);
}
}
},
Body::Struct(_, ref fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visit::walk_ty(&mut visitor, field.ty);
@@ -160,27 +154,23 @@ where
.iter()
.map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id))
.map(
|id| {
syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
// the bound e.g. Serialize
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
)
},
);
.map(|id| {
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type parameter that is being bounded e.g. T
bounded_ty: syn::Ty::Path(None, id.into()),
// the bound e.g. Serialize
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
})
});
let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates);
@@ -196,25 +186,23 @@ pub fn with_self_bound(
generics
.where_clause
.predicates
.push(
syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
// the bound e.g. Default
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
),
);
.push(syn::WherePredicate::BoundPredicate(
syn::WhereBoundPredicate {
bound_lifetimes: Vec::new(),
// the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont),
// the bound e.g. Default
bounds: vec![
syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: Vec::new(),
trait_ref: bound.clone(),
},
syn::TraitBoundModifier::None,
),
],
},
));
generics
}
@@ -231,15 +219,11 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
}
generics
.lifetimes
.push(
syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
},
);
generics.lifetimes.push(syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
});
generics
}
+867 -302
View File
File diff suppressed because it is too large Load Diff
+10 -1
View File
@@ -6,7 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use quote::{Tokens, ToTokens};
use quote::{ToTokens, Tokens};
pub enum Fragment {
/// Tokens that can be used as an expression.
@@ -73,3 +73,12 @@ impl ToTokens for Match {
}
}
}
impl AsRef<Tokens> for Fragment {
fn as_ref(&self) -> &Tokens {
match *self {
Fragment::Expr(ref expr) => expr,
Fragment::Block(ref block) => block,
}
}
}
+2 -4
View File
@@ -22,17 +22,15 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.19")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.26")]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "192"]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate syn;
extern crate serde_derive_internals as internals;
+191 -231
View File
@@ -10,7 +10,7 @@ use syn::{self, Ident};
use quote::Tokens;
use bound;
use fragment::{Fragment, Stmts, Match};
use fragment::{Fragment, Match, Stmts};
use internals::ast::{Body, Container, Field, Style, Variant};
use internals::{attr, Ctxt};
@@ -132,14 +132,12 @@ fn build_generics(cont: &Container) -> syn::Generics {
match cont.attrs.ser_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => {
bound::with_bound(
cont,
&generics,
needs_serialize_bound,
&path!(_serde::Serialize),
)
}
None => bound::with_bound(
cont,
&generics,
needs_serialize_bound,
&path!(_serde::Serialize),
),
}
}
@@ -149,10 +147,8 @@ fn build_generics(cont: &Container) -> syn::Generics {
// 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())
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
&& variant.map_or(true, |variant| variant.serialize_with().is_none())
}
fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
@@ -259,16 +255,14 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(
|field| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = get_field(params, field, ident);
quote!(if #path(#field_expr) { 0 } else { 1 })
}
},
)
.map(|field| match field.attrs.skip_serializing_if() {
None => quote!(1),
Some(path) => {
let ident = field.ident.clone().expect("struct has unnamed fields");
let field_expr = get_field(params, field, ident);
quote!(if #path(#field_expr) { 0 } else { 1 })
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! {
@@ -286,11 +280,9 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
let arms: Vec<_> = variants
.iter()
.enumerate()
.map(
|(variant_index, variant)| {
serialize_variant(params, variant, variant_index as u32, cattrs)
},
)
.map(|(variant_index, variant)| {
serialize_variant(params, variant, variant_index as u32, cattrs)
})
.collect();
quote_expr! {
@@ -321,13 +313,7 @@ fn serialize_variant(
let fields_pat = match variant.style {
Style::Unit => quote!(),
Style::Newtype | Style::Tuple => quote!((..)),
Style::Struct => {
quote!(
{
..
}
)
}
Style::Struct => quote!({ .. }),
};
quote! {
#this::#variant_ident #fields_pat => #skipped_err,
@@ -356,34 +342,26 @@ fn serialize_variant(
let fields = variant
.fields
.iter()
.map(
|f| {
f.ident
.clone()
.expect("struct variant has unnamed fields")
},
);
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
quote! {
#this::#variant_ident { #(ref #fields),* }
}
}
};
let body = Match(
match *cattrs.tag() {
attr::EnumTag::External => {
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
}
attr::EnumTag::Internal { ref tag } => {
serialize_internally_tagged_variant(params, variant, cattrs, tag)
}
attr::EnumTag::Adjacent {
ref tag,
ref content,
} => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs),
},
);
let body = Match(match *cattrs.tag() {
attr::EnumTag::External => {
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
}
attr::EnumTag::Internal { ref tag } => {
serialize_internally_tagged_variant(params, variant, cattrs, tag)
}
attr::EnumTag::Adjacent {
ref tag,
ref content,
} => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs),
});
quote! {
#case => #body
@@ -441,28 +419,24 @@ fn serialize_externally_tagged_variant(
)
}
}
Style::Tuple => {
serialize_tuple_variant(
TupleVariant::ExternallyTagged {
type_name: type_name,
variant_index: variant_index,
variant_name: variant_name,
},
params,
&variant.fields,
)
}
Style::Struct => {
serialize_struct_variant(
StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
},
params,
&variant.fields,
&type_name,
)
}
Style::Tuple => serialize_tuple_variant(
TupleVariant::ExternallyTagged {
type_name: type_name,
variant_index: variant_index,
variant_name: variant_name,
},
params,
&variant.fields,
),
Style::Struct => serialize_struct_variant(
StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
},
params,
&variant.fields,
&type_name,
),
}
}
@@ -520,17 +494,15 @@ fn serialize_internally_tagged_variant(
)
}
}
Style::Struct => {
serialize_struct_variant(
StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
},
params,
&variant.fields,
&type_name,
)
}
Style::Struct => serialize_struct_variant(
StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
},
params,
&variant.fields,
&type_name,
),
Style::Tuple => unreachable!("checked in serde_derive_internals"),
}
}
@@ -546,48 +518,44 @@ fn serialize_adjacently_tagged_variant(
let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name();
let inner = Stmts(
if let Some(path) = variant.attrs.serialize_with() {
let ser = wrap_serialize_variant_with(params, path, &variant);
quote_expr! {
_serde::Serialize::serialize(#ser, __serializer)
let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
let ser = wrap_serialize_variant_with(params, path, &variant);
quote_expr! {
_serde::Serialize::serialize(#ser, __serializer)
}
} else {
match variant.style {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
_serde::ser::SerializeStruct::end(__struct)
};
}
} else {
match variant.style {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
__serializer, #type_name, 1));
try!(_serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name));
_serde::ser::SerializeStruct::end(__struct)
};
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
}
Style::Newtype => {
let field = &variant.fields[0];
let mut field_expr = quote!(__field0);
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
}
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
}
Style::Struct => {
serialize_struct_variant(
StructVariant::Untagged,
params,
&variant.fields,
&variant_name,
)
quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer)
}
}
},
);
Style::Tuple => {
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
}
Style::Struct => serialize_struct_variant(
StructVariant::Untagged,
params,
&variant.fields,
&variant_name,
),
}
});
let fields_ty = variant.fields.iter().map(|f| &f.ty);
let ref fields_ident: Vec<_> = match variant.style {
@@ -599,24 +567,14 @@ fn serialize_adjacently_tagged_variant(
}
}
Style::Newtype => vec![Ident::new("__field0")],
Style::Tuple => {
(0..variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)))
.collect()
}
Style::Struct => {
variant
.fields
.iter()
.map(
|f| {
f.ident
.clone()
.expect("struct variant has unnamed fields")
},
)
.collect()
}
Style::Tuple => (0..variant.fields.len())
.map(|i| Ident::new(format!("__field{}", i)))
.collect(),
Style::Struct => variant
.fields
.iter()
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"))
.collect(),
};
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
@@ -753,7 +711,10 @@ enum StructVariant<'a> {
variant_index: u32,
variant_name: String,
},
InternallyTagged { tag: &'a str, variant_name: String },
InternallyTagged {
tag: &'a str,
variant_name: String,
},
Untagged,
}
@@ -764,19 +725,14 @@ fn serialize_struct_variant<'a>(
name: &str,
) -> Fragment {
let (method, skip_method) = match context {
StructVariant::ExternallyTagged { .. } => {
(
quote!(_serde::ser::SerializeStructVariant::serialize_field),
quote!(_serde::ser::SerializeStructVariant::skip_field),
)
}
StructVariant::InternallyTagged { .. } |
StructVariant::Untagged => {
(
quote!(_serde::ser::SerializeStruct::serialize_field),
quote!(_serde::ser::SerializeStruct::skip_field),
)
}
StructVariant::ExternallyTagged { .. } => (
quote!(_serde::ser::SerializeStructVariant::serialize_field),
quote!(_serde::ser::SerializeStructVariant::skip_field),
),
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => (
quote!(_serde::ser::SerializeStruct::serialize_field),
quote!(_serde::ser::SerializeStruct::skip_field),
),
};
let serialize_fields = serialize_struct_visitor(fields, params, true, method, skip_method);
@@ -789,16 +745,14 @@ fn serialize_struct_variant<'a>(
let let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields
.map(
|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
.map(|field| {
let ident = field.ident.clone().expect("struct has unnamed fields");
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1),
}
},
)
match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1),
}
})
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context {
@@ -857,34 +811,32 @@ fn serialize_tuple_struct_visitor(
fields
.iter()
.enumerate()
.map(
|(i, field)| {
let mut field_expr = if is_enum {
let id = Ident::new(format!("__field{}", i));
quote!(#id)
} else {
get_field(params, field, i)
};
.map(|(i, field)| {
let mut field_expr = if is_enum {
let id = Ident::new(format!("__field{}", i));
quote!(#id)
} else {
get_field(params, field, i)
};
let skip = field
.attrs
.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
let skip = field
.attrs
.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
}
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
}
let ser = quote! {
try!(#func(&mut __serde_state, #field_expr));
};
let ser = quote! {
try!(#func(&mut __serde_state, #field_expr));
};
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
},
)
match skip {
None => ser,
Some(skip) => quote!(if !#skip { #ser }),
}
})
.collect()
}
@@ -898,44 +850,42 @@ fn serialize_struct_visitor(
fields
.iter()
.filter(|&field| !field.attrs.skip_serializing())
.map(
|field| {
let field_ident = field.ident.clone().expect("struct has unnamed field");
let mut field_expr = if is_enum {
quote!(#field_ident)
} else {
get_field(params, field, field_ident)
};
.map(|field| {
let field_ident = field.ident.clone().expect("struct has unnamed field");
let mut field_expr = if is_enum {
quote!(#field_ident)
} else {
get_field(params, field, field_ident)
};
let key_expr = field.attrs.name().serialize_name();
let key_expr = field.attrs.name().serialize_name();
let skip = field
.attrs
.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
let skip = field
.attrs
.skip_serializing_if()
.map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
}
if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
}
let ser = quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
};
let ser = quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr));
};
match skip {
None => ser,
Some(skip) => {
quote! {
if !#skip {
#ser
} else {
try!(#skip_func(&mut __serde_state, #key_expr));
}
match skip {
None => ser,
Some(skip) => {
quote! {
if !#skip {
#ser
} else {
try!(#skip_func(&mut __serde_state, #key_expr));
}
}
}
},
)
}
})
.collect()
}
@@ -945,10 +895,7 @@ fn wrap_serialize_field_with(
serialize_with: &syn::Path,
field_expr: Tokens,
) -> Tokens {
wrap_serialize_with(params,
serialize_with,
&[field_ty],
&[quote!(#field_expr)])
wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
}
fn wrap_serialize_variant_with(
@@ -957,15 +904,24 @@ fn wrap_serialize_variant_with(
variant: &Variant,
) -> Tokens {
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
let field_exprs: Vec<_> = variant.fields.iter()
let field_exprs: Vec<_> = variant
.fields
.iter()
.enumerate()
.map(|(i, field)| {
let id = field.ident.as_ref().map_or_else(|| Ident::new(format!("__field{}", i)),
|id| id.clone());
let id = field
.ident
.as_ref()
.map_or_else(|| Ident::new(format!("__field{}", i)), |id| id.clone());
quote!(#id)
})
.collect();
wrap_serialize_with(params, serialize_with, field_tys.as_slice(), field_exprs.as_slice())
wrap_serialize_with(
params,
serialize_with,
field_tys.as_slice(),
field_exprs.as_slice(),
)
}
fn wrap_serialize_with(
@@ -1014,7 +970,11 @@ fn wrap_serialize_with(
//
// where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> {
if is_mut { Some(quote!(mut)) } else { None }
if is_mut {
Some(quote!(mut))
} else {
None
}
}
fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive_internals"
version = "0.17.0" # remember to update html_root_url
version = "0.18.1" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable."
+57 -43
View File
@@ -49,27 +49,25 @@ impl<'a> Container<'a> {
let attrs = attr::Container::from_ast(cx, item);
let mut body = match item.body {
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
syn::Body::Enum(ref variants) => {
Body::Enum(enum_from_ast(cx, variants, &attrs.default()))
}
syn::Body::Struct(ref variant_data) => {
let (style, fields) = struct_from_ast(cx, variant_data, None);
let (style, fields) = struct_from_ast(cx, variant_data, None, &attrs.default());
Body::Struct(style, fields)
}
};
match body {
Body::Enum(ref mut variants) => {
for ref mut variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for ref mut field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
Body::Enum(ref mut variants) => for ref mut variant in variants {
variant.attrs.rename_by_rule(attrs.rename_all());
for ref mut field in &mut variant.fields {
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
}
Body::Struct(_, ref mut fields) => {
for field in fields {
field.attrs.rename_by_rule(attrs.rename_all());
}
}
},
Body::Struct(_, ref mut fields) => for field in fields {
field.attrs.rename_by_rule(attrs.rename_all());
},
}
let item = Container {
@@ -98,47 +96,63 @@ impl<'a> Body<'a> {
}
}
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
fn enum_from_ast<'a>(
cx: &Ctxt,
variants: &'a [syn::Variant],
container_default: &attr::Default,
) -> Vec<Variant<'a>> {
variants
.iter()
.map(
|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
Variant {
ident: variant.ident.clone(),
attrs: attrs,
style: style,
fields: fields,
}
},
)
.map(|variant| {
let attrs = attr::Variant::from_ast(cx, variant);
let (style, fields) =
struct_from_ast(cx, &variant.data, Some(&attrs), container_default);
Variant {
ident: variant.ident.clone(),
attrs: attrs,
style: style,
fields: fields,
}
})
.collect()
}
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
fn struct_from_ast<'a>(
cx: &Ctxt,
data: &'a syn::VariantData,
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> (Style, Vec<Field<'a>>) {
match *data {
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
(Style::Newtype, fields_from_ast(cx, fields, attrs))
}
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
syn::VariantData::Struct(ref fields) => (
Style::Struct,
fields_from_ast(cx, fields, attrs, container_default),
),
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => (
Style::Newtype,
fields_from_ast(cx, fields, attrs, container_default),
),
syn::VariantData::Tuple(ref fields) => (
Style::Tuple,
fields_from_ast(cx, fields, attrs, container_default),
),
syn::VariantData::Unit => (Style::Unit, Vec::new()),
}
}
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr::Variant>) -> Vec<Field<'a>> {
fn fields_from_ast<'a>(
cx: &Ctxt,
fields: &'a [syn::Field],
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> Vec<Field<'a>> {
fields
.iter()
.enumerate()
.map(
|(i, field)| {
Field {
ident: field.ident.clone(),
attrs: attr::Field::from_ast(cx, i, field, attrs),
ty: &field.ty,
}
},
)
.map(|(i, field)| Field {
ident: field.ident.clone(),
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
ty: &field.ty,
})
.collect()
}
+127 -122
View File
@@ -164,6 +164,15 @@ pub enum Identifier {
Variant,
}
impl Identifier {
pub fn is_some(self) -> bool {
match self {
Identifier::No => false,
Identifier::Field | Identifier::Variant => true,
}
}
}
impl Container {
/// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self {
@@ -207,11 +216,11 @@ impl Container {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => {
cx.error(format!("unknown rename rule for #[serde(rename_all \
= {:?})]",
s))
}
Err(()) => cx.error(format!(
"unknown rename rule for #[serde(rename_all \
= {:?})]",
s
)),
}
}
}
@@ -222,19 +231,15 @@ impl Container {
}
// Parse `#[serde(default)]`
MetaItem(Word(ref name)) if name == "default" => {
match item.body {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Default);
}
_ => {
cx.error(
"#[serde(default)] can only be used on structs \
with named fields",
)
}
MetaItem(Word(ref name)) if name == "default" => match item.body {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Default);
}
}
_ => cx.error(
"#[serde(default)] can only be used on structs \
with named fields",
),
},
// Parse `#[serde(default = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
@@ -243,12 +248,10 @@ impl Container {
syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Path(path));
}
_ => {
cx.error(
"#[serde(default = \"...\")] can only be used \
on structs with named fields",
)
}
_ => cx.error(
"#[serde(default = \"...\")] can only be used \
on structs with named fields",
),
}
}
}
@@ -256,7 +259,8 @@ impl Container {
// Parse `#[serde(bound = "D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit)
{
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
@@ -271,16 +275,14 @@ impl Container {
}
// Parse `#[serde(untagged)]`
MetaItem(Word(ref name)) if name == "untagged" => {
match item.body {
syn::Body::Enum(_) => {
untagged.set_true();
}
syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
MetaItem(Word(ref name)) if name == "untagged" => match item.body {
syn::Body::Enum(_) => {
untagged.set_true();
}
}
syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
},
// Parse `#[serde(tag = "type")]`
MetaItem(NameValue(ref name, ref lit)) if name == "tag" => {
@@ -303,12 +305,10 @@ impl Container {
syn::Body::Enum(_) => {
content.set(s);
}
syn::Body::Struct(_) => {
cx.error(
"#[serde(content = \"...\")] can only be used on \
enums",
)
}
syn::Body::Struct(_) => cx.error(
"#[serde(content = \"...\")] can only be used on \
enums",
),
}
}
}
@@ -345,8 +345,10 @@ impl Container {
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
cx.error(format!(
"unknown serde container attribute `{}`",
meta_item.name()
));
}
Literal(_) => {
@@ -434,13 +436,12 @@ fn decide_tag(
if let syn::Body::Enum(ref variants) = item.body {
for variant in variants {
match variant.data {
syn::VariantData::Struct(_) |
syn::VariantData::Unit => {}
syn::VariantData::Struct(_) | syn::VariantData::Unit => {}
syn::VariantData::Tuple(ref fields) => {
if fields.len() != 1 {
cx.error(
"#[serde(tag = \"...\")] cannot be used with tuple \
variants",
variants",
);
break;
}
@@ -455,21 +456,19 @@ fn decide_tag(
EnumTag::External // doesn't matter, will error
}
(false, None, Some(_)) => {
cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together",);
cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together");
EnumTag::External
}
(true, None, Some(_)) => {
cx.error("untagged enum cannot have #[serde(content = \"...\")]");
EnumTag::External
}
(false, Some(tag), Some(content)) => {
EnumTag::Adjacent {
tag: tag,
content: content,
}
}
(false, Some(tag), Some(content)) => EnumTag::Adjacent {
tag: tag,
content: content,
},
(true, Some(_), Some(_)) => {
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]",);
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
EnumTag::External
}
}
@@ -484,7 +483,7 @@ fn decide_identifier(
match (&item.body, field_identifier.get(), variant_identifier.get()) {
(_, false, false) => Identifier::No,
(_, true, true) => {
cx.error("`field_identifier` and `variant_identifier` cannot both be set",);
cx.error("`field_identifier` and `variant_identifier` cannot both be set");
Identifier::No
}
(&syn::Body::Struct(_), true, false) => {
@@ -551,11 +550,11 @@ impl Variant {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => {
cx.error(format!("unknown rename rule for #[serde(rename_all \
= {:?})]",
s))
}
Err(()) => cx.error(format!(
"unknown rename rule for #[serde(rename_all \
= {:?})]",
s
)),
}
}
}
@@ -602,19 +601,20 @@ impl Variant {
}
// Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]`
MetaItem(ref mi) if mi.name() == "borrow" => {
match variant.data {
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
borrow.set(mi.clone());
}
_ => {
cx.error("#[serde(borrow)] may only be used on newtype variants");
}
MetaItem(ref mi) if mi.name() == "borrow" => match variant.data {
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
borrow.set(mi.clone());
}
}
_ => {
cx.error("#[serde(borrow)] may only be used on newtype variants");
}
},
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde variant attribute `{}`", meta_item.name()));
cx.error(format!(
"unknown serde variant attribute `{}`",
meta_item.name()
));
}
Literal(_) => {
@@ -714,7 +714,13 @@ pub enum Default {
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field, attrs: Option<&Variant>) -> Self {
pub fn from_ast(
cx: &Ctxt,
index: usize,
field: &syn::Field,
attrs: Option<&Variant>,
container_default: &Default,
) -> Self {
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
@@ -739,7 +745,12 @@ impl Field {
.as_ref()
.map(|borrow| vec![MetaItem(borrow.clone())]);
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items).chain(variant_borrow) {
for meta_items in field
.attrs
.iter()
.filter_map(get_serde_meta_items)
.chain(variant_borrow)
{
for meta_item in meta_items {
match meta_item {
// Parse `#[serde(rename = "foo")]`
@@ -784,7 +795,7 @@ impl Field {
MetaItem(Word(ref name)) if name == "skip" => {
skip_serializing.set_true();
skip_deserializing.set_true();
},
}
// Parse `#[serde(skip_serializing_if = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
@@ -822,7 +833,8 @@ impl Field {
// Parse `#[serde(bound = "D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) =
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit)
{
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
}
@@ -849,13 +861,10 @@ impl Field {
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
for lifetime in &lifetimes {
if !borrowable.contains(lifetime) {
cx.error(
format!(
"field `{}` does not have lifetime {}",
ident,
lifetime.ident
),
);
cx.error(format!(
"field `{}` does not have lifetime {}",
ident, lifetime.ident
));
}
}
borrowed_lifetimes.set(lifetimes);
@@ -871,7 +880,10 @@ impl Field {
}
MetaItem(ref meta_item) => {
cx.error(format!("unknown serde field attribute `{}`", meta_item.name()),);
cx.error(format!(
"unknown serde field attribute `{}`",
meta_item.name()
));
}
Literal(_) => {
@@ -881,9 +893,10 @@ impl Field {
}
}
// Is skip_deserializing, initialize the field to Default::default()
// unless a different default is specified by `#[serde(default = "...")]`
if skip_deserializing.0.value.is_some() {
// Is skip_deserializing, initialize the field to Default::default() unless a different
// default is specified by `#[serde(default = "...")]` on ourselves or our container (e.g.
// the struct we are in).
if container_default == &Default::None && skip_deserializing.0.value.is_some() {
default.set_if_none(Default::Default);
}
@@ -1018,13 +1031,11 @@ where
}
_ => {
cx.error(
format!(
"malformed {0} attribute, expected `{0}(serialize = ..., \
deserialize = ...)`",
attr_name
),
);
cx.error(format!(
"malformed {0} attribute, expected `{0}(serialize = ..., \
deserialize = ...)`",
attr_name
));
return Err(());
}
}
@@ -1060,13 +1071,10 @@ fn get_string_from_lit(
if let syn::Lit::Str(ref s, _) = *lit {
Ok(s.clone())
} else {
cx.error(
format!(
"expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name,
meta_item_name
),
);
cx.error(format!(
"expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name, meta_item_name
));
Err(())
}
}
@@ -1097,11 +1105,12 @@ fn parse_lit_into_where(
fn parse_lit_into_ty(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Ty, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_type(&string).map_err(
|_| {
cx.error(format!("failed to parse type: {} = {:?}", attr_name, string),)
},
)
syn::parse_type(&string).map_err(|_| {
cx.error(format!(
"failed to parse type: {} = {:?}",
attr_name, string
))
})
}
// Parses a string literal like "'a + 'b + 'c" containing a nonempty list of
@@ -1132,7 +1141,7 @@ fn parse_lit_into_lifetimes(
return Ok(set);
}
}
Err(cx.error(format!("failed to parse borrowed lifetimes: {:?}", string)),)
Err(cx.error(format!("failed to parse borrowed lifetimes: {:?}", string)))
}
// Whether the type looks like it might be `std::borrow::Cow<T>` where elem="T".
@@ -1176,8 +1185,8 @@ fn is_cow(ty: &syn::Ty, elem: &str) -> bool {
return false;
}
};
seg.ident == "Cow" && params.lifetimes.len() == 1 &&
params.types == vec![syn::parse_type(elem).unwrap()] && params.bindings.is_empty()
seg.ident == "Cow" && params.lifetimes.len() == 1
&& params.types == vec![syn::parse_type(elem).unwrap()] && params.bindings.is_empty()
}
// Whether the type looks like it might be `&T` where elem="T". This can have
@@ -1203,8 +1212,8 @@ fn is_cow(ty: &syn::Ty, elem: &str) -> bool {
fn is_rptr(ty: &syn::Ty, elem: &str) -> bool {
match *ty {
syn::Ty::Rptr(Some(_), ref mut_ty) => {
mut_ty.mutability == syn::Mutability::Immutable &&
mut_ty.ty == syn::parse_type(elem).unwrap()
mut_ty.mutability == syn::Mutability::Immutable
&& mut_ty.ty == syn::parse_type(elem).unwrap()
}
_ => false,
}
@@ -1225,7 +1234,7 @@ fn borrowable_lifetimes(
let mut lifetimes = BTreeSet::new();
collect_lifetimes(ty, &mut lifetimes);
if lifetimes.is_empty() {
Err(cx.error(format!("field `{}` has no lifetimes to borrow", name)),)
Err(cx.error(format!("field `{}` has no lifetimes to borrow", name)))
} else {
Ok(lifetimes)
}
@@ -1233,9 +1242,7 @@ fn borrowable_lifetimes(
fn collect_lifetimes(ty: &syn::Ty, out: &mut BTreeSet<syn::Lifetime>) {
match *ty {
syn::Ty::Slice(ref elem) |
syn::Ty::Array(ref elem, _) |
syn::Ty::Paren(ref elem) => {
syn::Ty::Slice(ref elem) | syn::Ty::Array(ref elem, _) | syn::Ty::Paren(ref elem) => {
collect_lifetimes(elem, out);
}
syn::Ty::Ptr(ref elem) => {
@@ -1245,11 +1252,9 @@ fn collect_lifetimes(ty: &syn::Ty, out: &mut BTreeSet<syn::Lifetime>) {
out.extend(lifetime.iter().cloned());
collect_lifetimes(&elem.ty, out);
}
syn::Ty::Tup(ref elems) => {
for elem in elems {
collect_lifetimes(elem, out);
}
}
syn::Ty::Tup(ref elems) => for elem in elems {
collect_lifetimes(elem, out);
},
syn::Ty::Path(ref qself, ref path) => {
if let Some(ref qself) = *qself {
collect_lifetimes(&qself.ty, out);
@@ -1266,11 +1271,11 @@ fn collect_lifetimes(ty: &syn::Ty, out: &mut BTreeSet<syn::Lifetime>) {
}
}
}
syn::Ty::BareFn(_) |
syn::Ty::Never |
syn::Ty::TraitObject(_) |
syn::Ty::ImplTrait(_) |
syn::Ty::Infer |
syn::Ty::Mac(_) => {}
syn::Ty::BareFn(_)
| syn::Ty::Never
| syn::Ty::TraitObject(_)
| syn::Ty::ImplTrait(_)
| syn::Ty::Infer
| syn::Ty::Mac(_) => {}
}
}
+51 -18
View File
@@ -31,7 +31,7 @@ pub enum RenameRule {
/// Rename direct children to "kebab-case" style.
KebabCase,
/// Rename direct children to "SCREAMING-KEBAB-CASE" style.
ScreamingKebabCase
ScreamingKebabCase,
}
impl RenameRule {
@@ -52,7 +52,9 @@ impl RenameRule {
}
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase.apply_to_variant(variant).replace('_', "-")
ScreamingKebabCase => ScreamingSnakeCase
.apply_to_variant(variant)
.replace('_', "-"),
}
}
@@ -80,7 +82,7 @@ impl RenameRule {
}
ScreamingSnakeCase => field.to_ascii_uppercase(),
KebabCase => field.replace('_', "-"),
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-")
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
}
}
}
@@ -104,13 +106,28 @@ impl FromStr for RenameRule {
#[test]
fn rename_variants() {
for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in
&[
("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
("A", "a", "a", "a", "A", "a", "A"),
("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
] {
for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in &[
(
"Outcome",
"outcome",
"outcome",
"outcome",
"OUTCOME",
"outcome",
"OUTCOME",
),
(
"VeryTasty",
"verytasty",
"veryTasty",
"very_tasty",
"VERY_TASTY",
"very-tasty",
"VERY-TASTY",
),
("A", "a", "a", "a", "A", "a", "A"),
("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower);
assert_eq!(PascalCase.apply_to_variant(original), original);
@@ -118,19 +135,35 @@ fn rename_variants() {
assert_eq!(SnakeCase.apply_to_variant(original), snake);
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
assert_eq!(KebabCase.apply_to_variant(original), kebab);
assert_eq!(ScreamingKebabCase.apply_to_variant(original), screaming_kebab);
assert_eq!(
ScreamingKebabCase.apply_to_variant(original),
screaming_kebab
);
}
}
#[test]
fn rename_fields() {
for &(original, pascal, camel, screaming, kebab, screaming_kebab) in
&[
("outcome", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
("a", "A", "a", "A", "a", "A"),
("z42", "Z42", "z42", "Z42", "z42", "Z42"),
] {
for &(original, pascal, camel, screaming, kebab, screaming_kebab) in &[
(
"outcome",
"Outcome",
"outcome",
"OUTCOME",
"outcome",
"OUTCOME",
),
(
"very_tasty",
"VeryTasty",
"veryTasty",
"VERY_TASTY",
"very-tasty",
"VERY-TASTY",
),
("a", "A", "a", "A", "a", "A"),
("z42", "Z42", "z42", "Z42", "z42", "Z42"),
] {
assert_eq!(None.apply_to_field(original), original);
assert_eq!(PascalCase.apply_to_field(original), pascal);
assert_eq!(CamelCase.apply_to_field(original), camel);
+40 -21
View File
@@ -31,7 +31,7 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
if cont.body.has_getter() && cont.attrs.remote().is_none() {
cx.error(
"#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]",
that have #[serde(remote = \"...\")]",
);
}
}
@@ -53,10 +53,13 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
};
for (i, variant) in variants.iter().enumerate() {
match (variant.style, cont.attrs.identifier(), variant.attrs.other()) {
match (
variant.style,
cont.attrs.identifier(),
variant.attrs.other(),
) {
// The `other` attribute may only be used in a field_identifier.
(_, Identifier::Variant, true) |
(_, Identifier::No, true) => {
(_, Identifier::Variant, true) | (_, Identifier::No, true) => {
cx.error("#[serde(other)] may only be used inside a field_identifier");
}
@@ -109,42 +112,58 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
for variant in variants.iter() {
if variant.attrs.serialize_with().is_some() {
if variant.attrs.skip_serializing() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]", variant.ident));
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]",
variant.ident
));
}
for (i, field) in variant.fields.iter().enumerate() {
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|ident| format!("`{}`", ident));
let ident = field
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
if field.attrs.skip_serializing() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]",
variant.ident, ident));
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]",
variant.ident, ident
));
}
if field.attrs.skip_serializing_if().is_some() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, ident));
cx.error(format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, ident
));
}
}
}
if variant.attrs.deserialize_with().is_some() {
if variant.attrs.skip_deserializing() {
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]", variant.ident));
cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]",
variant.ident
));
}
for (i, field) in variant.fields.iter().enumerate() {
if field.attrs.skip_deserializing() {
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|ident| format!("`{}`", ident));
let ident = field
.ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident));
cx.error(format!(
"variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident
));
}
}
}
+3 -1
View File
@@ -16,7 +16,9 @@ pub struct Ctxt {
impl Ctxt {
pub fn new() -> Self {
Ctxt { errors: RefCell::new(Some(Vec::new())) }
Ctxt {
errors: RefCell::new(Some(Vec::new())),
}
}
pub fn error<T: Display>(&self, msg: T) {
+1 -1
View File
@@ -6,7 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.17.0")]
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.18.1")]
extern crate syn;
#[macro_use]
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.19" # remember to update html_root_url
version = "1.0.26" # 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"
+19 -3
View File
@@ -184,11 +184,27 @@ where
T: Deserialize<'de> + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens);
match T::deserialize(&mut de) {
Ok(v) => assert_eq!(v, *value),
let mut deserialized_val = match T::deserialize(&mut de) {
Ok(v) => {
assert_eq!(v, *value);
v
}
Err(e) => panic!("tokens failed to deserialize: {}", e),
};
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
// Do the same thing for deserialize_in_place. This isn't *great* because a
// no-op impl of deserialize_in_place can technically succeed here. Still,
// this should catch a lot of junk.
let mut de = Deserializer::new(tokens);
match T::deserialize_in_place(&mut de, &mut deserialized_val) {
Ok(()) => {
assert_eq!(deserialized_val, *value);
}
Err(e) => panic!("tokens failed to deserialize_in_place: {}", e),
}
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
@@ -215,7 +231,7 @@ where
///
/// assert_de_tokens_error::<S>(
/// &[
/// Token::Struct { name: "S", len: 1 },
/// Token::Struct { name: "S", len: 2 },
/// Token::Str("x"),
/// ],
/// "unknown field `x`, expected `a` or `b`",
+15 -12
View File
@@ -11,17 +11,17 @@ pub struct Compact<T: ?Sized>(T);
/// Trait to determine whether a value is represented in human-readable or
/// compact form.
///
///
/// ```
/// extern crate serde;
/// extern crate serde_test;
///
///
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// use serde_test::{Configure, Token, assert_tokens};
///
///
/// #[derive(Debug, PartialEq)]
/// struct Example(u8, u8);
///
///
/// impl Serialize for Example {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer,
@@ -33,7 +33,7 @@ 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>,
@@ -52,7 +52,7 @@ pub struct Compact<T: ?Sized>(T);
/// }
/// }
/// }
///
///
/// fn main() {
/// assert_tokens(
/// &Example(1, 0).compact(),
@@ -73,11 +73,17 @@ pub struct Compact<T: ?Sized>(T);
/// ```
pub trait Configure {
/// Marks `self` as using `is_human_readable == true`
fn readable(self) -> Readable<Self> where Self: Sized {
fn readable(self) -> Readable<Self>
where
Self: Sized,
{
Readable(self)
}
/// Marks `self` as using `is_human_readable == false`
fn compact(self) -> Compact<Self> where Self: Sized {
fn compact(self) -> Compact<Self>
where
Self: Sized,
{
Compact(self)
}
}
@@ -158,7 +164,6 @@ where
}
}
macro_rules! forward_method {
($name: ident (self $(, $arg: ident : $arg_type: ty)* ) -> $return_type: ty) => {
fn $name (self $(, $arg : $arg_type)* ) -> $return_type {
@@ -455,8 +460,7 @@ macro_rules! impl_serializer {
impl_serializer!(Readable, true);
impl_serializer!(Compact, false);
use serde::de::{Visitor, EnumAccess, VariantAccess, MapAccess, DeserializeSeed, SeqAccess, Error};
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
macro_rules! forward_deserialize_methods {
( $wrapper : ident ( $( $name: ident ),* ) ) => {
@@ -468,7 +472,6 @@ macro_rules! forward_deserialize_methods {
};
}
macro_rules! impl_deserializer {
($wrapper : ident, $is_human_readable : expr) => {
impl <'de, D> Deserializer<'de> for $wrapper<D> where D: Deserializer<'de> {
+64 -50
View File
@@ -95,15 +95,11 @@ impl<'de> Deserializer<'de> {
where
V: Visitor<'de>,
{
let value = try!(
visitor.visit_seq(
DeserializerSeqVisitor {
de: self,
len: len,
end: end,
},
)
);
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
end: end,
},));
assert_next_token!(self, end);
Ok(value)
}
@@ -117,15 +113,11 @@ impl<'de> Deserializer<'de> {
where
V: Visitor<'de>,
{
let value = try!(
visitor.visit_map(
DeserializerMapVisitor {
de: self,
len: len,
end: end,
},
)
);
let value = try!(visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
end: end,
},));
assert_next_token!(self, end);
Ok(value)
}
@@ -169,7 +161,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
Token::TupleStruct { len, .. } => self.visit_seq(Some(len), Token::TupleStructEnd, visitor),
Token::TupleStruct { len, .. } => {
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
}
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
Token::Enum { .. } => {
@@ -195,17 +189,28 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
}
}
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
Token::NewtypeVariant { variant, .. } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),)
}
Token::TupleVariant { variant, .. } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),)
}
Token::StructVariant { variant, .. } => {
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),)
}
Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd |
Token::StructEnd | Token::TupleVariantEnd | Token::StructVariantEnd => {
Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Any,
)),
Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Seq,
)),
Token::StructVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
self,
Token::Str(variant),
EnumFormat::Map,
)),
Token::SeqEnd
| Token::TupleEnd
| Token::TupleStructEnd
| Token::MapEnd
| Token::StructEnd
| Token::TupleVariantEnd
| Token::StructVariantEnd => {
unexpected!(token);
}
}
@@ -216,8 +221,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: Visitor<'de>,
{
match self.peek_token() {
Token::Unit |
Token::None => {
Token::Unit | Token::None => {
self.next_token();
visitor.visit_none()
}
@@ -244,10 +248,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
Token::UnitVariant { name: n, .. } |
Token::NewtypeVariant { name: n, .. } |
Token::TupleVariant { name: n, .. } |
Token::StructVariant { name: n, .. } if name == n => {
Token::UnitVariant { name: n, .. }
| Token::NewtypeVariant { name: n, .. }
| Token::TupleVariant { name: n, .. }
| Token::StructVariant { name: n, .. } if name == n =>
{
visitor.visit_enum(DeserializerEnumVisitor { de: self })
}
_ => {
@@ -269,7 +274,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
}
}
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
fn deserialize_newtype_struct<V>(
self,
name: &'static str,
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
@@ -287,8 +296,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: Visitor<'de>,
{
match self.peek_token() {
Token::Unit |
Token::UnitStruct { .. } => {
Token::Unit | Token::UnitStruct { .. } => {
self.next_token();
visitor.visit_unit()
}
@@ -448,10 +456,10 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
V: DeserializeSeed<'de>,
{
match self.de.peek_token() {
Token::UnitVariant { variant: v, .. } |
Token::NewtypeVariant { variant: v, .. } |
Token::TupleVariant { variant: v, .. } |
Token::StructVariant { variant: v, .. } => {
Token::UnitVariant { variant: v, .. }
| Token::NewtypeVariant { variant: v, .. }
| Token::TupleVariant { variant: v, .. }
| Token::StructVariant { variant: v, .. } => {
let de = v.into_deserializer();
let value = try!(seed.deserialize(de));
Ok((value, self))
@@ -505,7 +513,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
unexpected!(token);
}
}
Token::Seq { len: Some(enum_len) } => {
Token::Seq {
len: Some(enum_len),
} => {
let token = self.de.next_token();
if len == enum_len {
@@ -518,7 +528,11 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
}
}
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
fn struct_variant<V>(
self,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Error>
where
V: Visitor<'de>,
{
@@ -533,7 +547,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
unexpected!(token);
}
}
Token::Map { len: Some(enum_len) } => {
Token::Map {
len: Some(enum_len),
} => {
let token = self.de.next_token();
if fields.len() == enum_len {
@@ -581,10 +597,8 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
{
match self.variant.take() {
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(Token::Bytes(variant)) => {
seed.deserialize(BytesDeserializer { value: variant })
.map(Some)
}
Some(Token::Bytes(variant)) => seed.deserialize(BytesDeserializer { value: variant })
.map(Some),
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(other) => unexpected!(other),
None => Ok(None),
+7 -3
View File
@@ -9,7 +9,7 @@
use std::error;
use std::fmt::{self, Display};
use serde::{ser, de};
use serde::{de, ser};
#[derive(Clone, Debug)]
pub struct Error {
@@ -18,13 +18,17 @@ pub struct Error {
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error { msg: msg.to_string() }
Error {
msg: msg.to_string(),
}
}
}
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error { msg: msg.to_string() }
Error {
msg: msg.to_string(),
}
}
}
+3 -7
View File
@@ -155,17 +155,13 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.19")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.26")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
missing_docs_in_private_items,
stutter,
use_self,
))]
#![cfg_attr(feature = "cargo-clippy",
allow(missing_docs_in_private_items, stutter, use_debug, use_self))]
#[macro_use]
extern crate serde;
+24 -6
View File
@@ -40,25 +40,43 @@ impl<'a> Serializer<'a> {
macro_rules! assert_next_token {
($ser:expr, $expected:ident) => {
assert_next_token!($ser, $expected, Token::$expected, true);
assert_next_token!($ser, stringify!($expected), Token::$expected, true);
};
($ser:expr, $expected:ident($v:expr)) => {
assert_next_token!($ser, $expected, Token::$expected(v), v == $v);
assert_next_token!(
$ser,
format_args!("{}({:?})", stringify!($expected), $v),
Token::$expected(v),
v == $v
);
};
($ser:expr, $expected:ident { $($k:ident),* }) => {
let compare = ($($k,)*);
assert_next_token!($ser, $expected, Token::$expected { $($k),* }, ($($k,)*) == compare);
let field_format = || {
use std::fmt::Write;
let mut buffer = String::new();
$(
write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap();
)*
buffer
};
assert_next_token!(
$ser,
format_args!("{} {{ {}}}", stringify!($expected), field_format()),
Token::$expected { $($k),* },
($($k,)*) == compare
);
};
($ser:expr, $expected:ident, $pat:pat, $guard:expr) => {
($ser:expr, $expected:expr, $pat:pat, $guard:expr) => {
match $ser.next_token() {
Some($pat) if $guard => {}
Some(other) => {
panic!("expected Token::{} but serialized as {}",
stringify!($expected), other);
$expected, other);
}
None => {
panic!("expected Token::{} after end of serialized tokens",
stringify!($expected));
$expected);
}
}
};
+18 -4
View File
@@ -232,7 +232,10 @@ pub enum Token {
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]);
/// # }
/// ```
UnitVariant { name: &'static str, variant: &'static str },
UnitVariant {
name: &'static str,
variant: &'static str,
},
/// The header to a serialized newtype struct of the given name.
///
@@ -286,7 +289,10 @@ pub enum Token {
/// ]);
/// # }
/// ```
NewtypeVariant { name: &'static str, variant: &'static str },
NewtypeVariant {
name: &'static str,
variant: &'static str,
},
/// The header to a sequence.
///
@@ -391,7 +397,11 @@ pub enum Token {
/// ]);
/// # }
/// ```
TupleVariant { name: &'static str, variant: &'static str, len: usize },
TupleVariant {
name: &'static str,
variant: &'static str,
len: usize,
},
/// An indicator of the end of a tuple variant.
TupleVariantEnd,
@@ -488,7 +498,11 @@ pub enum Token {
/// ]);
/// # }
/// ```
StructVariant { name: &'static str, variant: &'static str, len: usize },
StructVariant {
name: &'static str,
variant: &'static str,
len: usize,
},
/// An indicator of the end of a struct variant.
StructVariantEnd,
+2 -2
View File
@@ -11,8 +11,8 @@ unstable = ["serde/unstable", "compiletest_rs"]
fnv = "1.0"
rustc-serialize = "0.3.16"
serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive" }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" }
[dependencies]
compiletest_rs = { version = "0.2", optional = true }
compiletest_rs = { version = "0.3", optional = true }
File diff suppressed because it is too large Load Diff
+12 -12
View File
@@ -13,7 +13,7 @@ extern crate serde;
use serde::{Deserialize, Deserializer};
extern crate serde_test;
use serde_test::{Token, assert_de_tokens, assert_de_tokens_error};
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
use std::borrow::Cow;
@@ -87,18 +87,18 @@ fn test_struct() {
assert_de_tokens(
&Borrowing {
bs: "str",
bb: b"bytes",
},
bs: "str",
bb: b"bytes",
},
&[
Token::Struct { name: "Borrowing", len: 2 },
Token::Struct {
name: "Borrowing",
len: 2,
},
Token::BorrowedStr("bs"),
Token::BorrowedStr("str"),
Token::BorrowedStr("bb"),
Token::BorrowedBytes(b"bytes"),
Token::StructEnd,
],
);
@@ -115,14 +115,14 @@ fn test_cow() {
}
let tokens = &[
Token::Struct { name: "Cows", len: 2 },
Token::Struct {
name: "Cows",
len: 2,
},
Token::Str("copied"),
Token::BorrowedStr("copied"),
Token::Str("borrowed"),
Token::BorrowedStr("borrowed"),
Token::StructEnd,
];
+47 -13
View File
@@ -49,14 +49,16 @@ struct TupleStruct(i32, i32, i32);
struct Struct {
a: i32,
b: i32,
#[serde(skip_deserializing)] c: i32,
#[serde(skip_deserializing)]
c: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct StructDenyUnknown {
a: i32,
#[serde(skip_deserializing)] b: i32,
#[serde(skip_deserializing)]
b: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
@@ -77,13 +79,35 @@ impl Default for StructDefault<String> {
#[derive(PartialEq, Debug, Deserialize)]
struct StructSkipAll {
#[serde(skip_deserializing)] a: i32,
#[serde(skip_deserializing)]
a: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
#[serde(default)]
struct StructSkipDefault {
#[serde(skip_deserializing)]
a: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
#[serde(default)]
struct StructSkipDefaultGeneric<T> {
#[serde(skip_deserializing)]
t: T,
}
impl Default for StructSkipDefault {
fn default() -> Self {
StructSkipDefault { a: 16 }
}
}
#[derive(PartialEq, Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct StructSkipAllDenyUnknown {
#[serde(skip_deserializing)] a: i32,
#[serde(skip_deserializing)]
a: i32,
}
#[derive(PartialEq, Debug, Deserialize)]
@@ -94,7 +118,11 @@ enum Enum {
Unit,
Simple(i32),
Seq(i32, i32, i32),
Map { a: i32, b: i32, c: i32 },
Map {
a: i32,
b: i32,
c: i32,
},
}
#[derive(PartialEq, Debug, Deserialize)]
@@ -538,7 +566,7 @@ declare_tests! {
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 3 },
Token::Struct { name: "Struct", len: 2 },
Token::Str("a"),
Token::I32(1),
@@ -570,7 +598,7 @@ declare_tests! {
Token::MapEnd,
],
Struct { a: 1, b: 2, c: 0 } => &[
Token::Struct { name: "Struct", len: 3 },
Token::Struct { name: "Struct", len: 2 },
Token::Str("a"),
Token::I32(1),
@@ -591,7 +619,7 @@ declare_tests! {
Token::StructEnd,
],
StructSkipAll { a: 0 } => &[
Token::Struct { name: "StructSkipAll", len: 1 },
Token::Struct { name: "StructSkipAll", len: 0 },
Token::Str("a"),
Token::I32(1),
@@ -600,6 +628,12 @@ declare_tests! {
Token::StructEnd,
],
}
test_struct_skip_default {
StructSkipDefault { a: 16 } => &[
Token::Struct { name: "StructSkipDefault", len: 0 },
Token::StructEnd,
],
}
test_struct_skip_all_deny_unknown {
StructSkipAllDenyUnknown { a: 0 } => &[
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
@@ -608,7 +642,7 @@ declare_tests! {
}
test_struct_default {
StructDefault { a: 50, b: "overwritten".to_string() } => &[
Token::Struct { name: "StructDefault", len: 1 },
Token::Struct { name: "StructDefault", len: 2 },
Token::Str("a"),
Token::I32(50),
@@ -617,7 +651,7 @@ declare_tests! {
Token::StructEnd,
],
StructDefault { a: 100, b: "default".to_string() } => &[
Token::Struct { name: "StructDefault", len: 0 },
Token::Struct { name: "StructDefault", len: 2 },
Token::StructEnd,
],
}
@@ -954,7 +988,7 @@ fn test_cstr_internal_null_end() {
declare_error_tests! {
test_unknown_field<StructDenyUnknown> {
&[
Token::Struct { name: "StructDenyUnknown", len: 2 },
Token::Struct { name: "StructDenyUnknown", len: 1 },
Token::Str("a"),
Token::I32(0),
@@ -964,14 +998,14 @@ declare_error_tests! {
}
test_skipped_field_is_unknown<StructDenyUnknown> {
&[
Token::Struct { name: "StructDenyUnknown", len: 2 },
Token::Struct { name: "StructDenyUnknown", len: 1 },
Token::Str("b"),
],
"unknown field `b`, expected `a`",
}
test_skip_all_deny_unknown<StructSkipAllDenyUnknown> {
&[
Token::Struct { name: "StructSkipAllDenyUnknown", len: 1 },
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
Token::Str("a"),
],
"unknown field `a`, there are no fields",
+61 -63
View File
@@ -11,7 +11,6 @@
// types involved.
#![deny(warnings)]
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
#[macro_use]
@@ -23,6 +22,7 @@ use self::serde::de::{DeserializeOwned, Deserializer};
use std::borrow::Cow;
use std::marker::PhantomData;
use std::option::Option as StdOption;
use std::result::Result as StdResult;
// Try to trip up the generated code if it fails to use fully qualified paths.
@@ -32,6 +32,12 @@ struct Result;
struct Ok;
#[allow(dead_code)]
struct Err;
#[allow(dead_code)]
struct Option;
#[allow(dead_code)]
struct Some;
#[allow(dead_code)]
struct None;
//////////////////////////////////////////////////////////////////////////
@@ -40,7 +46,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
struct With<T> {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
x: X,
}
assert::<With<i32>>();
@@ -48,7 +54,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
struct WithTogether<T> {
t: T,
#[serde(with="both_x")]
#[serde(with = "both_x")]
x: X,
}
assert::<WithTogether<i32>>();
@@ -56,8 +62,8 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
struct WithRef<'a, T: 'a> {
#[serde(skip_deserializing)]
t: Option<&'a T>,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
t: StdOption<&'a T>,
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
x: X,
}
assert::<WithRef<i32>>();
@@ -77,9 +83,9 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
struct NoBounds<T> {
t: T,
option: Option<T>,
option: StdOption<T>,
boxed: Box<T>,
option_boxed: Option<Box<T>>,
option_boxed: StdOption<Box<T>>,
}
assert::<NoBounds<i32>>();
@@ -87,17 +93,17 @@ fn test_gen() {
enum EnumWith<T> {
Unit,
Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X,
),
Tuple(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X,
),
Struct {
t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
x: X,
},
}
@@ -117,16 +123,16 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
struct Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X,
);
assert::<Newtype>();
#[derive(Serialize, Deserialize)]
struct Tuple<T>(
T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
X
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X,
);
assert::<Tuple<i32>>();
@@ -136,7 +142,9 @@ fn test_gen() {
left: Box<TreeNode<D>>,
right: Box<TreeNode<D>>,
},
Leaf { data: D },
Leaf {
data: D,
},
}
assert::<TreeNode<i32>>();
@@ -175,35 +183,34 @@ fn test_gen() {
#[derive(Serialize)]
struct OptionStatic<'a> {
a: Option<&'a str>,
b: Option<&'static str>,
a: StdOption<&'a str>,
b: StdOption<&'static str>,
}
assert_ser::<OptionStatic>();
#[derive(Serialize, Deserialize)]
#[serde(bound="D: SerializeWith + DeserializeWith")]
#[serde(bound = "D: SerializeWith + DeserializeWith")]
struct WithTraits1<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
#[serde(serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with",
bound="E: SerializeWith + DeserializeWith")]
#[serde(serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with",
bound = "E: SerializeWith + DeserializeWith")]
e: E,
}
assert::<WithTraits1<X, X>>();
#[derive(Serialize, Deserialize)]
#[serde(bound(serialize="D: SerializeWith",
deserialize="D: DeserializeWith"))]
#[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
struct WithTraits2<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
#[serde(serialize_with = "SerializeWith::serialize_with",
deserialize_with = "DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
bound(serialize="E: SerializeWith"))]
#[serde(deserialize_with="DeserializeWith::deserialize_with",
bound(deserialize="E: DeserializeWith"))]
#[serde(serialize_with = "SerializeWith::serialize_with",
bound(serialize = "E: SerializeWith"))]
#[serde(deserialize_with = "DeserializeWith::deserialize_with",
bound(deserialize = "E: DeserializeWith"))]
e: E,
}
assert::<WithTraits2<X, X>>();
@@ -265,14 +272,14 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
struct TupleSkipAll(
#[serde(skip_deserializing)]
u8
u8,
);
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct TupleSkipAllDenyUnknown(
#[serde(skip_deserializing)]
u8
u8,
);
#[derive(Serialize, Deserialize)]
@@ -300,7 +307,7 @@ fn test_gen() {
},
TupleSkip(
#[serde(skip_deserializing)]
u8
u8,
),
}
@@ -316,7 +323,7 @@ fn test_gen() {
},
TupleSkip(
#[serde(skip_deserializing)]
u8
u8,
),
}
@@ -396,10 +403,7 @@ fn test_gen() {
#[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)]
Struct {
f1: String,
f2: u8,
},
Struct { f1: String, f2: u8 },
#[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(deserialize_with = "deserialize_some_unit_variant")]
@@ -422,10 +426,7 @@ fn test_gen() {
#[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)]
Struct {
f1: String,
f2: u8,
},
Struct { f1: String, f2: u8 },
#[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(deserialize_with = "deserialize_some_unit_variant")]
@@ -453,10 +454,7 @@ fn test_gen() {
#[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)]
Struct {
f1: String,
f2: u8,
},
Struct { f1: String, f2: u8 },
#[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(deserialize_with = "deserialize_some_unit_variant")]
@@ -484,10 +482,7 @@ fn test_gen() {
#[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)]
Struct {
f1: String,
f2: u8,
},
Struct { f1: String, f2: u8 },
#[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(deserialize_with = "deserialize_some_unit_variant")]
@@ -510,10 +505,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)]
enum StaticStrEnum<'a> {
Struct {
a: &'a str,
b: &'static str,
},
Struct { a: &'a str, b: &'static str },
Tuple(&'a str, &'static str),
Newtype(&'static str),
}
@@ -563,7 +555,7 @@ pub fn de_x<'de, D: Deserializer<'de>>(_: D) -> StdResult<X, D::Error> {
}
mod both_x {
pub use super::{ser_x as serialize, de_x as deserialize};
pub use super::{de_x as deserialize, ser_x as serialize};
}
impl SerializeWith for X {
@@ -579,27 +571,33 @@ impl DeserializeWith for X {
}
pub fn serialize_some_unit_variant<S>(_: S) -> StdResult<S::Ok, S::Error>
where S: Serializer,
where
S: Serializer,
{
unimplemented!()
}
pub fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error>
where D: Deserializer<'de>,
where
D: Deserializer<'de>,
{
unimplemented!()
}
pub fn serialize_some_other_variant<S>(_: &str, _: &u8, _: S) -> StdResult<S::Ok, S::Error>
where S: Serializer,
where
S: Serializer,
{
unimplemented!()
}
pub fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error>
where D: Deserializer<'de>,
where
D: Deserializer<'de>,
{
unimplemented!()
}
pub fn is_zero(n: &u8) -> bool { *n == 0 }
pub fn is_zero(n: &u8) -> bool {
*n == 0
}
+2 -1
View File
@@ -49,7 +49,8 @@ fn test_unit_fallthrough() {
enum F {
Aaa,
Bbb,
#[serde(other)] Other,
#[serde(other)]
Other,
}
assert_de_tokens(&F::Other, &[Token::Str("x")]);
File diff suppressed because it is too large Load Diff
+41 -17
View File
@@ -85,23 +85,32 @@ mod remote {
#[derive(Serialize, Deserialize)]
struct Test {
#[serde(with = "UnitDef")] unit: remote::Unit,
#[serde(with = "UnitDef")]
unit: remote::Unit,
#[serde(with = "PrimitivePrivDef")] primitive_priv: remote::PrimitivePriv,
#[serde(with = "PrimitivePrivDef")]
primitive_priv: remote::PrimitivePriv,
#[serde(with = "PrimitivePubDef")] primitive_pub: remote::PrimitivePub,
#[serde(with = "PrimitivePubDef")]
primitive_pub: remote::PrimitivePub,
#[serde(with = "NewtypePrivDef")] newtype_priv: remote::NewtypePriv,
#[serde(with = "NewtypePrivDef")]
newtype_priv: remote::NewtypePriv,
#[serde(with = "NewtypePubDef")] newtype_pub: remote::NewtypePub,
#[serde(with = "NewtypePubDef")]
newtype_pub: remote::NewtypePub,
#[serde(with = "TuplePrivDef")] tuple_priv: remote::TuplePriv,
#[serde(with = "TuplePrivDef")]
tuple_priv: remote::TuplePriv,
#[serde(with = "TuplePubDef")] tuple_pub: remote::TuplePub,
#[serde(with = "TuplePubDef")]
tuple_pub: remote::TuplePub,
#[serde(with = "StructPrivDef")] struct_priv: remote::StructPriv,
#[serde(with = "StructPrivDef")]
struct_priv: remote::StructPriv,
#[serde(with = "StructPubDef")] struct_pub: remote::StructPub,
#[serde(with = "StructPubDef")]
struct_pub: remote::StructPub,
}
#[derive(Serialize, Deserialize)]
@@ -110,7 +119,10 @@ struct UnitDef;
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePriv")]
struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8);
struct PrimitivePrivDef(
#[serde(getter = "remote::PrimitivePriv::get")]
u8,
);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePub")]
@@ -119,28 +131,39 @@ struct PrimitivePubDef(u8);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePriv")]
struct NewtypePrivDef(
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit,
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePub")]
struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
struct NewtypePubDef(
#[serde(with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePriv")]
struct TuplePrivDef(
#[serde(getter = "remote::TuplePriv::first")] u8,
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit,
#[serde(getter = "remote::TuplePriv::first")]
u8,
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePub")]
struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
struct TuplePubDef(
u8,
#[serde(with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPriv")]
struct StructPrivDef {
#[serde(getter = "remote::StructPriv::a")] a: u8,
#[serde(getter = "remote::StructPriv::a")]
a: u8,
#[serde(getter = "remote::StructPriv::b")]
#[serde(with = "UnitDef")]
@@ -150,7 +173,8 @@ struct StructPrivDef {
#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPub")]
struct StructPubDef {
#[allow(dead_code)] a: u8,
#[allow(dead_code)]
a: u8,
#[allow(dead_code)]
#[serde(with = "UnitDef")]
+15 -5
View File
@@ -50,11 +50,21 @@ enum Enum {
Unit,
One(i32),
Seq(i32, i32),
Map { a: i32, b: i32 },
#[serde(skip_serializing)] SkippedUnit,
#[serde(skip_serializing)] SkippedOne(i32),
#[serde(skip_serializing)] SkippedSeq(i32, i32),
#[serde(skip_serializing)] SkippedMap { _a: i32, _b: i32 },
Map {
a: i32,
b: i32,
},
#[serde(skip_serializing)]
SkippedUnit,
#[serde(skip_serializing)]
SkippedOne(i32),
#[serde(skip_serializing)]
SkippedSeq(i32, i32),
#[serde(skip_serializing)]
SkippedMap {
_a: i32,
_b: i32,
},
}
//////////////////////////////////////////////////////////////////////////