Compare commits

...

33 Commits

Author SHA1 Message Date
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
42 changed files with 2992 additions and 1793 deletions
+2 -5
View File
@@ -1,5 +1,2 @@
fn_args_layout = "Block" error_on_line_overflow = false
array_layout = "Block" same_line_attributes = false
where_style = "Rfc"
generics_indent = "Block"
fn_call_style = "Block"
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.23" # remember to update html_root_url version = "1.0.25" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
+1 -1
View File
@@ -8,7 +8,7 @@
use lib::*; 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. /// An efficient way of discarding data from a deserializer.
/// ///
+299 -80
View File
@@ -15,6 +15,7 @@ use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, Va
use de::MapAccess; use de::MapAccess;
use de::from_primitive::FromPrimitive; use de::from_primitive::FromPrimitive;
use private::de::InPlaceSeed;
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use private::de::size_hint; use private::de::size_hint;
@@ -210,6 +211,8 @@ impl<'de> Deserialize<'de> for char {
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
struct StringVisitor; struct StringVisitor;
#[cfg(any(feature = "std", feature = "alloc"))]
struct StringInPlaceVisitor<'a>(&'a mut String);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de> Visitor<'de> for StringVisitor { impl<'de> Visitor<'de> for StringVisitor {
@@ -249,7 +252,66 @@ impl<'de> Visitor<'de> for StringVisitor {
{ {
match String::from_utf8(v) { match String::from_utf8(v) {
Ok(s) => Ok(s), 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) 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,8 +534,16 @@ where
where where
D: Deserializer<'de>, 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?)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -496,7 +573,9 @@ impl<'de, T> Deserialize<'de> for PhantomData<T> {
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let visitor = PhantomDataVisitor { marker: PhantomData }; let visitor = PhantomDataVisitor {
marker: PhantomData,
};
deserializer.deserialize_unit_struct("PhantomData", visitor) 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)*)* >, $ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
$access:ident, $access:ident,
$ctor:expr, $ctor:expr,
$clear:expr,
$with_capacity:expr, $with_capacity:expr,
$reserve:expr,
$insert:expr $insert:expr
) => { ) => {
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*> impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
@@ -554,16 +635,59 @@ macro_rules! seq_impl {
let visitor = SeqVisitor { marker: PhantomData }; let visitor = SeqVisitor { marker: PhantomData };
deserializer.deserialize_seq(visitor) 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"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
BinaryHeap<T: Ord>, BinaryHeap<T: Ord>,
seq, seq,
BinaryHeap::new(), BinaryHeap::new(),
BinaryHeap::clear,
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
BinaryHeap::reserve,
BinaryHeap::push); BinaryHeap::push);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
@@ -571,7 +695,9 @@ seq_impl!(
BTreeSet<T: Eq + Ord>, BTreeSet<T: Eq + Ord>,
seq, seq,
BTreeSet::new(), BTreeSet::new(),
BTreeSet::clear,
BTreeSet::new(), BTreeSet::new(),
nop_reserve,
BTreeSet::insert); BTreeSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
@@ -579,15 +705,20 @@ seq_impl!(
LinkedList<T>, LinkedList<T>,
seq, seq,
LinkedList::new(), LinkedList::new(),
LinkedList::clear,
LinkedList::new(), LinkedList::new(),
LinkedList::push_back); nop_reserve,
LinkedList::push_back
);
#[cfg(feature = "std")] #[cfg(feature = "std")]
seq_impl!( seq_impl!(
HashSet<T: Eq + Hash, S: BuildHasher + Default>, HashSet<T: Eq + Hash, S: BuildHasher + Default>,
seq, seq,
HashSet::with_hasher(S::default()), HashSet::with_hasher(S::default()),
HashSet::clear,
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
HashSet::reserve,
HashSet::insert); HashSet::insert);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
@@ -595,26 +726,35 @@ seq_impl!(
Vec<T>, Vec<T>,
seq, seq,
Vec::new(), Vec::new(),
Vec::clear,
Vec::with_capacity(size_hint::cautious(seq.size_hint())), Vec::with_capacity(size_hint::cautious(seq.size_hint())),
Vec::push); Vec::reserve,
Vec::push
);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
VecDeque<T>, VecDeque<T>,
seq, seq,
VecDeque::new(), VecDeque::new(),
VecDeque::clear,
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())), VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
VecDeque::push_back); VecDeque::reserve,
VecDeque::push_back
);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct ArrayVisitor<A> { struct ArrayVisitor<A> {
marker: PhantomData<A>, marker: PhantomData<A>,
} }
struct ArrayInPlaceVisitor<'a, A: 'a>(&'a mut A);
impl<A> ArrayVisitor<A> { impl<A> ArrayVisitor<A> {
fn new() -> Self { 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] impl<'de, T> Deserialize<'de> for [T; $len]
where where
T: Deserialize<'de>, T: Deserialize<'de>,
@@ -683,6 +852,13 @@ macro_rules! array_impls {
{ {
deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new()) 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 { 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,)+) { impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
#[inline] #[inline]
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error> fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
where where
D: Deserializer<'de>, 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! { tuple_impls! {
1 TupleVisitor1 => (0 T0) 1 => (0 T0)
2 TupleVisitor2 => (0 T0 1 T1) 2 => (0 T0 1 T1)
3 TupleVisitor3 => (0 T0 1 T1 2 T2) 3 => (0 T0 1 T1 2 T2)
4 TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3) 4 => (0 T0 1 T1 2 T2 3 T3)
5 TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4) 5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5) 6 => (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) 7 => (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) 8 => (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) 9 => (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) 10 => (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) 11 => (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) 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 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) 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 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) 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 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) 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 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) 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); parse_socket_impl!(net::SocketAddrV4, net::SocketAddrV4::new);
#[cfg(feature = "std")] #[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()) { match try!(data.variant()) {
(OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec), (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; use std::os::windows::ffi::OsStringExt;
match try!(data.variant()) { match try!(data.variant()) {
(OsStringKind::Windows, v) => { (OsStringKind::Windows, v) => v.newtype_variant::<Vec<u16>>()
v.newtype_variant::<Vec<u16>>() .map(|vec| OsString::from_wide(&vec)),
.map(|vec| OsString::from_wide(&vec)) (OsStringKind::Unix, _) => Err(Error::custom(
} "cannot deserialize Unix OS string on Windows",
(OsStringKind::Unix, _) => Err(Error::custom("cannot deserialize Unix OS string on Windows",),), )),
} }
} }
} }
@@ -1521,13 +1731,17 @@ impl<'de> Deserialize<'de> for SystemTime {
match key { match key {
Field::Secs => { Field::Secs => {
if secs.is_some() { 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())); secs = Some(try!(map.next_value()));
} }
Field::Nanos => { Field::Nanos => {
if nanos.is_some() { 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())); nanos = Some(try!(map.next_value()));
} }
@@ -1691,7 +1905,13 @@ where
} }
const FIELDS: &'static [&'static str] = &["start", "end"]; 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 { match value {
0 => Ok(Field::Ok), 0 => Ok(Field::Ok),
1 => Ok(Field::Err), 1 => Ok(Field::Err),
_ => { _ => Err(Error::invalid_value(
Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),) Unexpected::Unsigned(value as u64),
} &self,
)),
} }
} }
@@ -1780,14 +2001,12 @@ where
match value { match value {
b"Ok" => Ok(Field::Ok), b"Ok" => Ok(Field::Ok),
b"Err" => Ok(Field::Err), b"Err" => Ok(Field::Err),
_ => { _ => match str::from_utf8(value) {
match str::from_utf8(value) { Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)), Err(_) => {
Err(_) => { Err(Error::invalid_value(Unexpected::Bytes(value), &self))
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
}
} }
} },
} }
} }
} }
@@ -1831,7 +2050,7 @@ where
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<'de, T> Deserialize<'de> for Wrapping<T> impl<'de, T> Deserialize<'de> for Wrapping<T>
where where
T: Deserialize<'de> T: Deserialize<'de>,
{ {
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error> fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error>
where where
+32 -1
View File
@@ -504,6 +504,35 @@ pub trait Deserialize<'de>: Sized {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>; D: Deserializer<'de>;
/// 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 /// 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 /// change, as a value serialized in human-readable mode is not required to
/// deserialize from the same data in compact mode. /// deserialize from the same data in compact mode.
#[inline] #[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 lib::*;
use de::{self, IntoDeserializer, Expected, SeqAccess}; use de::{self, Expected, IntoDeserializer, SeqAccess};
use private::de::size_hint; use private::de::size_hint;
use ser; use ser;
use self::private::{First, Second}; use self::private::{First, Second};
@@ -62,7 +62,9 @@ impl de::Error for Error {
where where
T: Display, 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")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
@@ -112,7 +114,9 @@ where
type Deserializer = UnitDeserializer<E>; type Deserializer = UnitDeserializer<E>;
fn into_deserializer(self) -> UnitDeserializer<E> { fn into_deserializer(self) -> UnitDeserializer<E> {
UnitDeserializer { marker: PhantomData } UnitDeserializer {
marker: PhantomData,
}
} }
} }
@@ -658,7 +662,10 @@ where
} else { } else {
// First argument is the number of elements in the data, second // First argument is the number of elements in the data, second
// argument is the number of elements expected by the Deserialize. // 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 { } else {
// First argument is the number of elements in the data, second // First argument is the number of elements in the data, second
// argument is the number of elements expected by the Deserialize. // 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) Ok(value)
} }
fn deserialize_tuple<V>( fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
self,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
where where
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
@@ -1223,7 +1229,12 @@ mod private {
} }
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) { 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> impl<'de, E> de::VariantAccess<'de> for UnitOnly<E>
@@ -1240,14 +1251,20 @@ mod private {
where where
T: de::DeserializeSeed<'de>, 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> fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
where where
V: de::Visitor<'de>, 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>( fn struct_variant<V>(
@@ -1258,7 +1275,10 @@ mod private {
where where
V: de::Visitor<'de>, 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::fmt::{self, Formatter};
pub use lib::marker::PhantomData; pub use lib::marker::PhantomData;
pub use lib::option::Option::{self, None, Some}; 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; 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. // Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.23")] #![doc(html_root_url = "https://docs.rs/serde/1.0.25")]
// Support using Serde without the standard library! // Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and // Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue: // discussion of these features please refer to this issue:
// //
// https://github.com/serde-rs/serde/issues/812 // https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))] #![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
#![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints // Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow( #![cfg_attr(feature = "cargo-clippy",
cast_lossless, allow(cast_lossless, const_static_lifetime, doc_markdown, linkedlist,
const_static_lifetime, needless_pass_by_value, type_complexity, unreadable_literal,
doc_markdown, zero_prefixed_literal))]
linkedlist,
needless_pass_by_value,
type_complexity,
unreadable_literal,
zero_prefixed_literal,
))]
// Whitelisted clippy_pedantic lints // Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow( #![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts // integer and float ser/de requires these sorts of casts
@@ -125,7 +116,6 @@
empty_enum, empty_enum,
use_debug, use_debug,
))] ))]
// Blacklisted Rust lints. // Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)] #![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::{cmp, iter, mem, ops, slice, str};
pub use self::core::{i8, i16, i32, i64, isize}; pub use self::core::{isize, i16, i32, i64, i8};
pub use self::core::{u8, u16, u32, u64, usize}; pub use self::core::{usize, u16, u32, u64, u8};
pub use self::core::{f32, f64}; pub use self::core::{f32, f64};
pub use self::core::cell::{Cell, RefCell}; pub use self::core::cell::{Cell, RefCell};
@@ -193,9 +183,9 @@ mod lib {
pub use alloc::arc::Arc; pub use alloc::arc::Arc;
#[cfg(feature = "std")] #[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")))] #[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")] #[cfg(feature = "std")]
pub use std::{error, net}; pub use std::{error, net};
@@ -203,9 +193,9 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::collections::{HashMap, HashSet}; pub use std::collections::{HashMap, HashSet};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::ffi::{CString, CStr, OsString, OsStr}; pub use std::ffi::{CStr, CString, OsStr, OsString};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::hash::{Hash, BuildHasher}; pub use std::hash::{BuildHasher, Hash};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::io::Write; pub use std::io::Write;
#[cfg(feature = "std")] #[cfg(feature = "std")]
+156 -102
View File
@@ -8,16 +8,16 @@
use lib::*; use lib::*;
use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor}; use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::Unexpected; use de::Unexpected;
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer, pub use self::content::{Content, ContentDeserializer, ContentRefDeserializer,
TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor, InternallyTaggedUnitVisitor, TagContentOtherField,
TagContentOtherField, TagContentOtherFieldVisitor, TagContentOtherFieldVisitor, TagOrContentField, TagOrContentFieldVisitor,
InternallyTaggedUnitVisitor, UntaggedUnitVisitor}; TaggedContentVisitor, UntaggedUnitVisitor};
/// If the missing field is of type `Option<T>` then treat is as `None`, /// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error. /// otherwise it is an error.
@@ -120,7 +120,10 @@ where
{ {
match String::from_utf8(v) { match String::from_utf8(v) {
Ok(s) => Ok(Cow::Owned(s)), 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()) helper(iter.size_hint())
} }
#[inline]
pub fn cautious(hint: Option<usize>) -> usize { pub fn cautious(hint: Option<usize>) -> usize {
cmp::min(hint.unwrap_or(0), 4096) cmp::min(hint.unwrap_or(0), 4096)
} }
@@ -224,8 +228,8 @@ mod content {
use lib::*; use lib::*;
use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, MapAccess, use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, MapAccess, SeqAccess,
EnumAccess, Unexpected}; Unexpected, Visitor};
use super::size_hint; use super::size_hint;
/// Used from generated code to buffer the contents of the Deserializer when /// Used from generated code to buffer the contents of the Deserializer when
@@ -501,7 +505,9 @@ mod content {
where where
V: EnumAccess<'de>, 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> { impl<'de> TagOrContentVisitor<'de> {
fn new(name: &'static str) -> Self { fn new(name: &'static str) -> Self {
TagOrContentVisitor { name: name, value: PhantomData } TagOrContentVisitor {
name: name,
value: PhantomData,
}
} }
} }
@@ -557,7 +566,9 @@ mod content {
where where
F: de::Error, 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> fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
@@ -591,7 +602,9 @@ mod content {
where where
F: de::Error, 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> fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
@@ -730,14 +743,18 @@ mod content {
where where
F: de::Error, 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> fn visit_none<F>(self) -> Result<Self::Value, F>
where where
F: de::Error, 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> fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
@@ -860,8 +877,7 @@ mod content {
{ {
let mut tag = None; let mut tag = None;
let mut vec = Vec::with_capacity(size_hint::cautious(map.size_hint())); let mut vec = Vec::with_capacity(size_hint::cautious(map.size_hint()));
while let Some(k) = while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
match k { match k {
TagOrContent::Tag => { TagOrContent::Tag => {
if tag.is_some() { if tag.is_some() {
@@ -877,14 +893,10 @@ mod content {
} }
match tag { match tag {
None => Err(de::Error::missing_field(self.tag_name)), None => Err(de::Error::missing_field(self.tag_name)),
Some(tag) => { Some(tag) => Ok(TaggedContent {
Ok( tag: tag,
TaggedContent { content: Content::Map(vec),
tag: tag, }),
content: Content::Map(vec),
},
)
}
} }
} }
} }
@@ -966,7 +978,11 @@ mod content {
type Value = TagContentOtherField; type Value = TagContentOtherField;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 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> fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
@@ -1030,10 +1046,8 @@ mod content {
Ok(value) Ok(value)
} }
Content::Map(v) => { Content::Map(v) => {
let map = v.into_iter().map(|(k, v)| { let map = v.into_iter()
(ContentDeserializer::new(k), .map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
ContentDeserializer::new(v))
});
let mut map_visitor = de::value::MapDeserializer::new(map); let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor)); let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end()); try!(map_visitor.end());
@@ -1080,44 +1094,41 @@ mod content {
let (variant, value) = match iter.next() { let (variant, value) = match iter.next() {
Some(v) => v, Some(v) => v,
None => { None => {
return Err( return Err(de::Error::invalid_value(
de::Error::invalid_value( de::Unexpected::Map,
de::Unexpected::Map, &"map with a single key",
&"map with a single key", ));
),
);
} }
}; };
// enums are encoded in json as maps with a single key:value pair // enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() { if iter.next().is_some() {
return Err( return Err(de::Error::invalid_value(
de::Error::invalid_value( de::Unexpected::Map,
de::Unexpected::Map, &"map with a single key",
&"map with a single key", ));
),
);
} }
(variant, Some(value)) (variant, Some(value))
} }
s @ Content::String(_) | s @ Content::Str(_) => (s, None), s @ Content::String(_) | s @ Content::Str(_) => (s, None),
other => { other => {
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),); return Err(de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
} }
}; };
visitor.visit_enum( visitor.visit_enum(EnumDeserializer {
EnumDeserializer { variant: variant,
variant: variant, value: value,
value: value, err: PhantomData,
err: PhantomData, })
},
)
} }
fn deserialize_unit_struct<V>( fn deserialize_unit_struct<V>(
self, self,
_name: &'static str, _name: &'static str,
visitor: V visitor: V,
) -> Result<V::Value, Self::Error> ) -> Result<V::Value, Self::Error>
where where
V: Visitor<'de>, V: Visitor<'de>,
@@ -1215,9 +1226,10 @@ mod content {
{ {
match self.value { match self.value {
Some(value) => seed.deserialize(ContentDeserializer::new(value)), Some(value) => seed.deserialize(ContentDeserializer::new(value)),
None => { None => Err(de::Error::invalid_type(
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"),) de::Unexpected::UnitVariant,
} &"newtype variant",
)),
} }
} }
@@ -1229,8 +1241,14 @@ mod content {
Some(Content::Seq(v)) => { Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
} }
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant"),), Some(other) => Err(de::Error::invalid_type(
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"),), other.unexpected(),
&"tuple variant",
)),
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"tuple variant",
)),
} }
} }
@@ -1249,8 +1267,14 @@ mod content {
Some(Content::Seq(v)) => { Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
} }
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),), Some(other) => Err(de::Error::invalid_type(
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),), other.unexpected(),
&"struct variant",
)),
_ => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"struct variant",
)),
} }
} }
} }
@@ -1318,10 +1342,7 @@ mod content {
T: de::DeserializeSeed<'de>, T: de::DeserializeSeed<'de>,
{ {
match self.iter.next() { match self.iter.next() {
Some(value) => { Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
seed.deserialize(ContentDeserializer::new(value))
.map(Some)
}
None => Ok(None), None => Ok(None),
} }
} }
@@ -1457,12 +1478,12 @@ mod content {
Ok(value) Ok(value)
} }
Content::Map(ref v) => { Content::Map(ref v) => {
let map = v.into_iter() let map = v.into_iter().map(|&(ref k, ref v)| {
.map( (
|&(ref k, ref v)| { ContentRefDeserializer::new(k),
(ContentRefDeserializer::new(k), ContentRefDeserializer::new(v)) ContentRefDeserializer::new(v),
}, )
); });
let mut map_visitor = de::value::MapDeserializer::new(map); let mut map_visitor = de::value::MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor)); let value = try!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end()); try!(map_visitor.end());
@@ -1505,38 +1526,35 @@ mod content {
let &(ref variant, ref value) = match iter.next() { let &(ref variant, ref value) = match iter.next() {
Some(v) => v, Some(v) => v,
None => { None => {
return Err( return Err(de::Error::invalid_value(
de::Error::invalid_value( de::Unexpected::Map,
de::Unexpected::Map, &"map with a single key",
&"map with a single key", ));
),
);
} }
}; };
// enums are encoded in json as maps with a single key:value pair // enums are encoded in json as maps with a single key:value pair
if iter.next().is_some() { if iter.next().is_some() {
return Err( return Err(de::Error::invalid_value(
de::Error::invalid_value( de::Unexpected::Map,
de::Unexpected::Map, &"map with a single key",
&"map with a single key", ));
),
);
} }
(variant, Some(value)) (variant, Some(value))
} }
ref s @ Content::String(_) | ref s @ Content::Str(_) => (s, None), ref s @ Content::String(_) | ref s @ Content::Str(_) => (s, None),
ref other => { ref other => {
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),); return Err(de::Error::invalid_type(
other.unexpected(),
&"string or map",
));
} }
}; };
visitor.visit_enum( visitor.visit_enum(EnumRefDeserializer {
EnumRefDeserializer { variant: variant,
variant: variant, value: value,
value: value, err: PhantomData,
err: PhantomData, })
},
)
} }
forward_to_deserialize_any! { forward_to_deserialize_any! {
@@ -1612,9 +1630,10 @@ mod content {
{ {
match self.value { match self.value {
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
None => { None => Err(de::Error::invalid_type(
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"),) de::Unexpected::UnitVariant,
} &"newtype variant",
)),
} }
} }
@@ -1626,8 +1645,14 @@ mod content {
Some(&Content::Seq(ref v)) => { Some(&Content::Seq(ref v)) => {
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
} }
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant"),), Some(other) => Err(de::Error::invalid_type(
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"),), other.unexpected(),
&"tuple variant",
)),
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"tuple variant",
)),
} }
} }
@@ -1646,8 +1671,14 @@ mod content {
Some(&Content::Seq(ref v)) => { Some(&Content::Seq(ref v)) => {
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
} }
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),), Some(other) => Err(de::Error::invalid_type(
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),), other.unexpected(),
&"struct variant",
)),
_ => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"struct variant",
)),
} }
} }
} }
@@ -1715,10 +1746,8 @@ mod content {
T: de::DeserializeSeed<'de>, T: de::DeserializeSeed<'de>,
{ {
match self.iter.next() { match self.iter.next() {
Some(value) => { Some(value) => seed.deserialize(ContentRefDeserializer::new(value))
seed.deserialize(ContentRefDeserializer::new(value)) .map(Some),
.map(Some)
}
None => Ok(None), None => Ok(None),
} }
} }
@@ -1763,8 +1792,7 @@ mod content {
match self.iter.next() { match self.iter.next() {
Some(&(ref key, ref value)) => { Some(&(ref key, ref value)) => {
self.value = Some(value); self.value = Some(value);
seed.deserialize(ContentRefDeserializer::new(key)) seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
.map(Some)
} }
None => Ok(None), None => Ok(None),
} }
@@ -1850,7 +1878,11 @@ mod content {
type Value = (); type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 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> fn visit_seq<S>(self, _: S) -> Result<(), S::Error>
@@ -1890,7 +1922,11 @@ mod content {
type Value = (); type Value = ();
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 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> fn visit_unit<E>(self) -> Result<(), E>
@@ -2008,3 +2044,21 @@ where
map struct enum identifier ignored_any 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 lib::*;
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible}; use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))] #[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. /// Used to check that serde(getter) attributes return the expected type.
/// Not public API. /// Not public API.
@@ -32,15 +32,13 @@ where
S: Serializer, S: Serializer,
T: Serialize, T: Serialize,
{ {
value.serialize( value.serialize(TaggedSerializer {
TaggedSerializer { type_ident: type_ident,
type_ident: type_ident, variant_ident: variant_ident,
variant_ident: variant_ident, tag: tag,
tag: tag, variant_name: variant_name,
variant_name: variant_name, delegate: serializer,
delegate: serializer, })
},
)
} }
struct TaggedSerializer<S> { struct TaggedSerializer<S> {
@@ -92,13 +90,10 @@ where
S: Serializer, S: Serializer,
{ {
fn bad_type(self, what: Unsupported) -> S::Error { fn bad_type(self, what: Unsupported) -> S::Error {
ser::Error::custom( ser::Error::custom(format_args!(
format_args!(
"cannot serialize tagged newtype variant {}::{} containing {}", "cannot serialize tagged newtype variant {}::{} containing {}",
self.type_ident, self.type_ident, self.variant_ident, what
self.variant_ident, ))
what),
)
} }
} }
@@ -281,7 +276,11 @@ where
let mut map = try!(self.delegate.serialize_map(Some(2))); let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name)); try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant)); 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> { 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))); let mut map = try!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name)); try!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant)); 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")))] #[cfg(not(any(feature = "std", feature = "alloc")))]
@@ -402,7 +405,10 @@ mod content {
} }
fn end(mut self) -> Result<M::Ok, M::Error> { 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() self.map.end()
} }
} }
@@ -444,7 +450,10 @@ mod content {
} }
fn end(mut self) -> Result<M::Ok, M::Error> { 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() self.map.end()
} }
} }
@@ -485,7 +494,12 @@ mod content {
TupleVariant(&'static str, u32, &'static str, Vec<Content>), TupleVariant(&'static str, u32, &'static str, Vec<Content>),
Map(Vec<(Content, Content)>), Map(Vec<(Content, Content)>),
Struct(&'static str, Vec<(&'static str, 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 { impl Serialize for Content {
@@ -687,7 +701,10 @@ mod content {
where where
T: Serialize, 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>( fn serialize_newtype_variant<T: ?Sized>(
@@ -700,32 +717,26 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
Ok( Ok(Content::NewtypeVariant(
Content::NewtypeVariant( name,
name, variant_index,
variant_index, variant,
variant, Box::new(try!(value.serialize(self))),
Box::new(try!(value.serialize(self))), ))
),
)
} }
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> { fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
Ok( Ok(SerializeSeq {
SerializeSeq { elements: Vec::with_capacity(len.unwrap_or(0)),
elements: Vec::with_capacity(len.unwrap_or(0)), error: PhantomData,
error: PhantomData, })
},
)
} }
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> { fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
Ok( Ok(SerializeTuple {
SerializeTuple { elements: Vec::with_capacity(len),
elements: Vec::with_capacity(len), error: PhantomData,
error: PhantomData, })
},
)
} }
fn serialize_tuple_struct( fn serialize_tuple_struct(
@@ -733,13 +744,11 @@ mod content {
name: &'static str, name: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeTupleStruct, E> { ) -> Result<Self::SerializeTupleStruct, E> {
Ok( Ok(SerializeTupleStruct {
SerializeTupleStruct { name: name,
name: name, fields: Vec::with_capacity(len),
fields: Vec::with_capacity(len), error: PhantomData,
error: PhantomData, })
},
)
} }
fn serialize_tuple_variant( fn serialize_tuple_variant(
@@ -749,25 +758,21 @@ mod content {
variant: &'static str, variant: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeTupleVariant, E> { ) -> Result<Self::SerializeTupleVariant, E> {
Ok( Ok(SerializeTupleVariant {
SerializeTupleVariant { name: name,
name: name, variant_index: variant_index,
variant_index: variant_index, variant: variant,
variant: variant, fields: Vec::with_capacity(len),
fields: Vec::with_capacity(len), error: PhantomData,
error: PhantomData, })
},
)
} }
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> { fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
Ok( Ok(SerializeMap {
SerializeMap { entries: Vec::with_capacity(len.unwrap_or(0)),
entries: Vec::with_capacity(len.unwrap_or(0)), key: None,
key: None, error: PhantomData,
error: PhantomData, })
},
)
} }
fn serialize_struct( fn serialize_struct(
@@ -775,13 +780,11 @@ mod content {
name: &'static str, name: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeStruct, E> { ) -> Result<Self::SerializeStruct, E> {
Ok( Ok(SerializeStruct {
SerializeStruct { name: name,
name: name, fields: Vec::with_capacity(len),
fields: Vec::with_capacity(len), error: PhantomData,
error: PhantomData, })
},
)
} }
fn serialize_struct_variant( fn serialize_struct_variant(
@@ -791,15 +794,13 @@ mod content {
variant: &'static str, variant: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeStructVariant, E> { ) -> Result<Self::SerializeStructVariant, E> {
Ok( Ok(SerializeStructVariant {
SerializeStructVariant { name: name,
name: name, variant_index: variant_index,
variant_index: variant_index, variant: variant,
variant: variant, fields: Vec::with_capacity(len),
fields: Vec::with_capacity(len), error: PhantomData,
error: PhantomData, })
},
)
} }
} }
@@ -907,7 +908,12 @@ mod content {
} }
fn end(self) -> Result<Content, E> { 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> { 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,
))
} }
} }
} }
+18 -10
View File
@@ -464,7 +464,8 @@ impl Serialize for SystemTime {
S: Serializer, S: Serializer,
{ {
use super::SerializeStruct; 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)); 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("secs_since_epoch", &duration_since_epoch.as_secs()));
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos())); try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
@@ -513,10 +514,12 @@ impl Serialize for net::IpAddr {
} }
} else { } else {
match *self { match *self {
net::IpAddr::V4(ref a) => net::IpAddr::V4(ref a) => {
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a), serializer.serialize_newtype_variant("IpAddr", 0, "V4", a)
net::IpAddr::V6(ref a) => }
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a), net::IpAddr::V6(ref a) => {
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a)
}
} }
} }
} }
@@ -567,10 +570,12 @@ impl Serialize for net::SocketAddr {
} }
} else { } else {
match *self { match *self {
net::SocketAddr::V4(ref addr) => net::SocketAddr::V4(ref addr) => {
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr), serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr)
net::SocketAddr::V6(ref addr) => }
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", 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() { if serializer.is_human_readable() {
const MAX_LEN: usize = 47; 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) serialize_display_bounded_length!(self, MAX_LEN, serializer)
} else { } else {
(self.ip(), self.port()).serialize(serializer) (self.ip(), self.port()).serialize(serializer)
+2 -2
View File
@@ -10,8 +10,8 @@
use lib::*; use lib::*;
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct, use ser::{self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant}; SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
/// Helper type for implementing a `Serializer` that does not support /// Helper type for implementing a `Serializer` that does not support
/// serializing one of the compound types. /// 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 /// change, as a value serialized in human-readable mode is not required to
/// deserialize from the same data in compact mode. /// deserialize from the same data in compact mode.
#[inline] #[inline]
fn is_human_readable(&self) -> bool { true } fn is_human_readable(&self) -> bool {
true
}
} }
/// Returned from `Serializer::serialize_seq`. /// Returned from `Serializer::serialize_seq`.
+6 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.23" # remember to update html_root_url version = "1.0.25" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -14,13 +14,17 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
[features]
default = []
deserialize_in_place = []
[lib] [lib]
name = "serde_derive" name = "serde_derive"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
quote = "0.3.8" 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"] } syn = { version = "0.11", features = ["visit"] }
[dev-dependencies] [dev-dependencies]
+51 -67
View File
@@ -27,14 +27,10 @@ pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
ty_params: generics ty_params: generics
.ty_params .ty_params
.iter() .iter()
.map( .map(|ty_param| syn::TyParam {
|ty_param| { default: None,
syn::TyParam { ..ty_param.clone()
default: None, })
..ty_param.clone()
}
},
)
.collect(), .collect(),
..generics.clone() ..generics.clone()
} }
@@ -137,17 +133,15 @@ where
relevant_ty_params: HashSet::new(), relevant_ty_params: HashSet::new(),
}; };
match cont.body { match cont.body {
Body::Enum(ref variants) => { Body::Enum(ref variants) => for variant in variants.iter() {
for variant in variants.iter() { let relevant_fields = variant
let relevant_fields = variant .fields
.fields .iter()
.iter() .filter(|field| filter(&field.attrs, Some(&variant.attrs)));
.filter(|field| filter(&field.attrs, Some(&variant.attrs))); for field in relevant_fields {
for field in relevant_fields { visit::walk_ty(&mut visitor, field.ty);
visit::walk_ty(&mut visitor, field.ty);
}
} }
} },
Body::Struct(_, ref fields) => { Body::Struct(_, ref fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) { for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visit::walk_ty(&mut visitor, field.ty); visit::walk_ty(&mut visitor, field.ty);
@@ -160,27 +154,23 @@ where
.iter() .iter()
.map(|ty_param| ty_param.ident.clone()) .map(|ty_param| ty_param.ident.clone())
.filter(|id| visitor.relevant_ty_params.contains(id)) .filter(|id| visitor.relevant_ty_params.contains(id))
.map( .map(|id| {
|id| { syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
syn::WherePredicate::BoundPredicate( bound_lifetimes: Vec::new(),
syn::WhereBoundPredicate { // the type parameter that is being bounded e.g. T
bound_lifetimes: Vec::new(), bounded_ty: syn::Ty::Path(None, id.into()),
// the type parameter that is being bounded e.g. T // the bound e.g. Serialize
bounded_ty: syn::Ty::Path(None, id.into()), bounds: vec![
// the bound e.g. Serialize syn::TyParamBound::Trait(
bounds: vec![ syn::PolyTraitRef {
syn::TyParamBound::Trait( bound_lifetimes: Vec::new(),
syn::PolyTraitRef { trait_ref: bound.clone(),
bound_lifetimes: Vec::new(), },
trait_ref: bound.clone(), syn::TraitBoundModifier::None,
}, ),
syn::TraitBoundModifier::None, ],
), })
], });
},
)
},
);
let mut generics = generics.clone(); let mut generics = generics.clone();
generics.where_clause.predicates.extend(new_predicates); generics.where_clause.predicates.extend(new_predicates);
@@ -196,25 +186,23 @@ pub fn with_self_bound(
generics generics
.where_clause .where_clause
.predicates .predicates
.push( .push(syn::WherePredicate::BoundPredicate(
syn::WherePredicate::BoundPredicate( syn::WhereBoundPredicate {
syn::WhereBoundPredicate { bound_lifetimes: Vec::new(),
bound_lifetimes: Vec::new(), // the type that is being bounded e.g. MyStruct<'a, T>
// the type that is being bounded e.g. MyStruct<'a, T> bounded_ty: type_of_item(cont),
bounded_ty: type_of_item(cont), // the bound e.g. Default
// the bound e.g. Default bounds: vec![
bounds: vec![ syn::TyParamBound::Trait(
syn::TyParamBound::Trait( syn::PolyTraitRef {
syn::PolyTraitRef { bound_lifetimes: Vec::new(),
bound_lifetimes: Vec::new(), trait_ref: bound.clone(),
trait_ref: bound.clone(), },
}, syn::TraitBoundModifier::None,
syn::TraitBoundModifier::None, ),
), ],
], },
}, ));
),
);
generics 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))); .push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
} }
generics generics.lifetimes.push(syn::LifetimeDef {
.lifetimes attrs: Vec::new(),
.push( lifetime: syn::Lifetime::new(lifetime),
syn::LifetimeDef { bounds: Vec::new(),
attrs: Vec::new(), });
lifetime: syn::Lifetime::new(lifetime),
bounds: Vec::new(),
},
);
generics 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 // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use quote::{Tokens, ToTokens}; use quote::{ToTokens, Tokens};
pub enum Fragment { pub enum Fragment {
/// Tokens that can be used as an expression. /// 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 //! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.23")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.25")]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))] #![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
// The `quote!` macro requires deep recursion. // The `quote!` macro requires deep recursion.
#![recursion_limit = "192"] #![recursion_limit = "192"]
extern crate syn;
#[macro_use] #[macro_use]
extern crate quote; extern crate quote;
extern crate syn;
extern crate serde_derive_internals as internals; extern crate serde_derive_internals as internals;
+191 -231
View File
@@ -10,7 +10,7 @@ use syn::{self, Ident};
use quote::Tokens; use quote::Tokens;
use bound; use bound;
use fragment::{Fragment, Stmts, Match}; use fragment::{Fragment, Match, Stmts};
use internals::ast::{Body, Container, Field, Style, Variant}; use internals::ast::{Body, Container, Field, Style, Variant};
use internals::{attr, Ctxt}; use internals::{attr, Ctxt};
@@ -132,14 +132,12 @@ fn build_generics(cont: &Container) -> syn::Generics {
match cont.attrs.ser_bound() { match cont.attrs.ser_bound() {
Some(predicates) => bound::with_where_predicates(&generics, predicates), Some(predicates) => bound::with_where_predicates(&generics, predicates),
None => { None => bound::with_bound(
bound::with_bound( cont,
cont, &generics,
&generics, needs_serialize_bound,
needs_serialize_bound, &path!(_serde::Serialize),
&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: // 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. // Serialize` bound where T is the type of the field.
fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_serializing() && !field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
field.serialize_with().is_none() && && variant.map_or(true, |variant| variant.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 { 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 let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields let len = serialized_fields
.map( .map(|field| match field.attrs.skip_serializing_if() {
|field| match field.attrs.skip_serializing_if() { None => quote!(1),
None => quote!(1), Some(path) => {
Some(path) => { let ident = field.ident.clone().expect("struct has unnamed fields");
let ident = field.ident.clone().expect("struct has unnamed fields"); let field_expr = get_field(params, field, ident);
let field_expr = get_field(params, field, ident); quote!(if #path(#field_expr) { 0 } else { 1 })
quote!(if #path(#field_expr) { 0 } else { 1 }) }
} })
},
)
.fold(quote!(0), |sum, expr| quote!(#sum + #expr)); .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! { quote_block! {
@@ -286,11 +280,9 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
let arms: Vec<_> = variants let arms: Vec<_> = variants
.iter() .iter()
.enumerate() .enumerate()
.map( .map(|(variant_index, variant)| {
|(variant_index, variant)| { serialize_variant(params, variant, variant_index as u32, cattrs)
serialize_variant(params, variant, variant_index as u32, cattrs) })
},
)
.collect(); .collect();
quote_expr! { quote_expr! {
@@ -321,13 +313,7 @@ fn serialize_variant(
let fields_pat = match variant.style { let fields_pat = match variant.style {
Style::Unit => quote!(), Style::Unit => quote!(),
Style::Newtype | Style::Tuple => quote!((..)), Style::Newtype | Style::Tuple => quote!((..)),
Style::Struct => { Style::Struct => quote!({ .. }),
quote!(
{
..
}
)
}
}; };
quote! { quote! {
#this::#variant_ident #fields_pat => #skipped_err, #this::#variant_ident #fields_pat => #skipped_err,
@@ -356,34 +342,26 @@ fn serialize_variant(
let fields = variant let fields = variant
.fields .fields
.iter() .iter()
.map( .map(|f| f.ident.clone().expect("struct variant has unnamed fields"));
|f| {
f.ident
.clone()
.expect("struct variant has unnamed fields")
},
);
quote! { quote! {
#this::#variant_ident { #(ref #fields),* } #this::#variant_ident { #(ref #fields),* }
} }
} }
}; };
let body = Match( let body = Match(match *cattrs.tag() {
match *cattrs.tag() { attr::EnumTag::External => {
attr::EnumTag::External => { serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
serialize_externally_tagged_variant(params, variant, variant_index, cattrs) }
} attr::EnumTag::Internal { ref tag } => {
attr::EnumTag::Internal { ref tag } => { serialize_internally_tagged_variant(params, variant, cattrs, tag)
serialize_internally_tagged_variant(params, variant, cattrs, tag) }
} attr::EnumTag::Adjacent {
attr::EnumTag::Adjacent { ref tag,
ref tag, ref content,
ref content, } => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
} => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content), attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs),
attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs), });
},
);
quote! { quote! {
#case => #body #case => #body
@@ -441,28 +419,24 @@ fn serialize_externally_tagged_variant(
) )
} }
} }
Style::Tuple => { Style::Tuple => serialize_tuple_variant(
serialize_tuple_variant( TupleVariant::ExternallyTagged {
TupleVariant::ExternallyTagged { type_name: type_name,
type_name: type_name, variant_index: variant_index,
variant_index: variant_index, variant_name: variant_name,
variant_name: variant_name, },
}, params,
params, &variant.fields,
&variant.fields, ),
) Style::Struct => serialize_struct_variant(
} StructVariant::ExternallyTagged {
Style::Struct => { variant_index: variant_index,
serialize_struct_variant( variant_name: variant_name,
StructVariant::ExternallyTagged { },
variant_index: variant_index, params,
variant_name: variant_name, &variant.fields,
}, &type_name,
params, ),
&variant.fields,
&type_name,
)
}
} }
} }
@@ -520,17 +494,15 @@ fn serialize_internally_tagged_variant(
) )
} }
} }
Style::Struct => { Style::Struct => serialize_struct_variant(
serialize_struct_variant( StructVariant::InternallyTagged {
StructVariant::InternallyTagged { tag: tag,
tag: tag, variant_name: variant_name,
variant_name: variant_name, },
}, params,
params, &variant.fields,
&variant.fields, &type_name,
&type_name, ),
)
}
Style::Tuple => unreachable!("checked in serde_derive_internals"), 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 type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name();
let inner = Stmts( let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, &variant);
let ser = wrap_serialize_variant_with(params, path, &variant); quote_expr! {
quote_expr! { _serde::Serialize::serialize(#ser, __serializer)
_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 { Style::Newtype => {
match variant.style { let field = &variant.fields[0];
Style::Unit => { let mut field_expr = quote!(__field0);
return quote_block! { if let Some(path) = field.attrs.serialize_with() {
let mut __struct = try!(_serde::Serializer::serialize_struct( field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
__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);
}
quote_expr! { quote_expr! {
_serde::Serialize::serialize(#field_expr, __serializer) _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,
)
} }
} }
}, 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 fields_ty = variant.fields.iter().map(|f| &f.ty);
let ref fields_ident: Vec<_> = match variant.style { let ref fields_ident: Vec<_> = match variant.style {
@@ -599,24 +567,14 @@ fn serialize_adjacently_tagged_variant(
} }
} }
Style::Newtype => vec![Ident::new("__field0")], Style::Newtype => vec![Ident::new("__field0")],
Style::Tuple => { Style::Tuple => (0..variant.fields.len())
(0..variant.fields.len()) .map(|i| Ident::new(format!("__field{}", i)))
.map(|i| Ident::new(format!("__field{}", i))) .collect(),
.collect() Style::Struct => variant
} .fields
Style::Struct => { .iter()
variant .map(|f| f.ident.clone().expect("struct variant has unnamed fields"))
.fields .collect(),
.iter()
.map(
|f| {
f.ident
.clone()
.expect("struct variant has unnamed fields")
},
)
.collect()
}
}; };
let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let (_, ty_generics, where_clause) = params.generics.split_for_impl();
@@ -753,7 +711,10 @@ enum StructVariant<'a> {
variant_index: u32, variant_index: u32,
variant_name: String, variant_name: String,
}, },
InternallyTagged { tag: &'a str, variant_name: String }, InternallyTagged {
tag: &'a str,
variant_name: String,
},
Untagged, Untagged,
} }
@@ -764,19 +725,14 @@ fn serialize_struct_variant<'a>(
name: &str, name: &str,
) -> Fragment { ) -> Fragment {
let (method, skip_method) = match context { let (method, skip_method) = match context {
StructVariant::ExternallyTagged { .. } => { StructVariant::ExternallyTagged { .. } => (
( quote!(_serde::ser::SerializeStructVariant::serialize_field),
quote!(_serde::ser::SerializeStructVariant::serialize_field), quote!(_serde::ser::SerializeStructVariant::skip_field),
quote!(_serde::ser::SerializeStructVariant::skip_field), ),
) StructVariant::InternallyTagged { .. } | StructVariant::Untagged => (
} quote!(_serde::ser::SerializeStruct::serialize_field),
StructVariant::InternallyTagged { .. } | quote!(_serde::ser::SerializeStruct::skip_field),
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); 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 let_mut = mut_if(serialized_fields.peek().is_some());
let len = serialized_fields let len = serialized_fields
.map( .map(|field| {
|field| { let ident = field.ident.clone().expect("struct has unnamed fields");
let ident = field.ident.clone().expect("struct has unnamed fields");
match field.attrs.skip_serializing_if() { match field.attrs.skip_serializing_if() {
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }), Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
None => quote!(1), None => quote!(1),
} }
}, })
)
.fold(quote!(0), |sum, expr| quote!(#sum + #expr)); .fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context { match context {
@@ -857,34 +811,32 @@ fn serialize_tuple_struct_visitor(
fields fields
.iter() .iter()
.enumerate() .enumerate()
.map( .map(|(i, field)| {
|(i, field)| { let mut field_expr = if is_enum {
let mut field_expr = if is_enum { let id = Ident::new(format!("__field{}", i));
let id = Ident::new(format!("__field{}", i)); quote!(#id)
quote!(#id) } else {
} else { get_field(params, field, i)
get_field(params, field, i) };
};
let skip = field let skip = field
.attrs .attrs
.skip_serializing_if() .skip_serializing_if()
.map(|path| quote!(#path(#field_expr))); .map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
} }
let ser = quote! { let ser = quote! {
try!(#func(&mut __serde_state, #field_expr)); try!(#func(&mut __serde_state, #field_expr));
}; };
match skip { match skip {
None => ser, None => ser,
Some(skip) => quote!(if !#skip { #ser }), Some(skip) => quote!(if !#skip { #ser }),
} }
}, })
)
.collect() .collect()
} }
@@ -898,44 +850,42 @@ fn serialize_struct_visitor(
fields fields
.iter() .iter()
.filter(|&field| !field.attrs.skip_serializing()) .filter(|&field| !field.attrs.skip_serializing())
.map( .map(|field| {
|field| { let field_ident = field.ident.clone().expect("struct has unnamed field");
let field_ident = field.ident.clone().expect("struct has unnamed field"); let mut field_expr = if is_enum {
let mut field_expr = if is_enum { quote!(#field_ident)
quote!(#field_ident) } else {
} else { get_field(params, field, field_ident)
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 let skip = field
.attrs .attrs
.skip_serializing_if() .skip_serializing_if()
.map(|path| quote!(#path(#field_expr))); .map(|path| quote!(#path(#field_expr)));
if let Some(path) = field.attrs.serialize_with() { if let Some(path) = field.attrs.serialize_with() {
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr); field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
} }
let ser = quote! { let ser = quote! {
try!(#func(&mut __serde_state, #key_expr, #field_expr)); try!(#func(&mut __serde_state, #key_expr, #field_expr));
}; };
match skip { match skip {
None => ser, None => ser,
Some(skip) => { Some(skip) => {
quote! { quote! {
if !#skip { if !#skip {
#ser #ser
} else { } else {
try!(#skip_func(&mut __serde_state, #key_expr)); try!(#skip_func(&mut __serde_state, #key_expr));
}
} }
} }
} }
}, }
) })
.collect() .collect()
} }
@@ -945,10 +895,7 @@ fn wrap_serialize_field_with(
serialize_with: &syn::Path, serialize_with: &syn::Path,
field_expr: Tokens, field_expr: Tokens,
) -> Tokens { ) -> Tokens {
wrap_serialize_with(params, wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
serialize_with,
&[field_ty],
&[quote!(#field_expr)])
} }
fn wrap_serialize_variant_with( fn wrap_serialize_variant_with(
@@ -957,15 +904,24 @@ fn wrap_serialize_variant_with(
variant: &Variant, variant: &Variant,
) -> Tokens { ) -> Tokens {
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect(); 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() .enumerate()
.map(|(i, field)| { .map(|(i, field)| {
let id = field.ident.as_ref().map_or_else(|| Ident::new(format!("__field{}", i)), let id = field
|id| id.clone()); .ident
.as_ref()
.map_or_else(|| Ident::new(format!("__field{}", i)), |id| id.clone());
quote!(#id) quote!(#id)
}) })
.collect(); .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( fn wrap_serialize_with(
@@ -1014,7 +970,11 @@ fn wrap_serialize_with(
// //
// where we want to omit the `mut` to avoid a warning. // where we want to omit the `mut` to avoid a warning.
fn mut_if(is_mut: bool) -> Option<Tokens> { 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 fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive_internals" 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>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable." description = "AST representation used by Serde derive macros. Unstable."
+57 -43
View File
@@ -49,27 +49,25 @@ impl<'a> Container<'a> {
let attrs = attr::Container::from_ast(cx, item); let attrs = attr::Container::from_ast(cx, item);
let mut body = match item.body { let mut body = match item.body {
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) => { 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) Body::Struct(style, fields)
} }
}; };
match body { match body {
Body::Enum(ref mut variants) => { Body::Enum(ref mut variants) => for ref mut variant in variants {
for ref mut variant in variants { variant.attrs.rename_by_rule(attrs.rename_all());
variant.attrs.rename_by_rule(attrs.rename_all()); for ref mut field in &mut variant.fields {
for ref mut field in &mut variant.fields { field.attrs.rename_by_rule(variant.attrs.rename_all());
field.attrs.rename_by_rule(variant.attrs.rename_all());
}
} }
} },
Body::Struct(_, ref mut fields) => { Body::Struct(_, ref mut fields) => for field in fields {
for field in fields { field.attrs.rename_by_rule(attrs.rename_all());
field.attrs.rename_by_rule(attrs.rename_all()); },
}
}
} }
let item = Container { 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 variants
.iter() .iter()
.map( .map(|variant| {
|variant| { let attrs = attr::Variant::from_ast(cx, variant);
let attrs = attr::Variant::from_ast(cx, variant); let (style, fields) =
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs)); struct_from_ast(cx, &variant.data, Some(&attrs), container_default);
Variant { Variant {
ident: variant.ident.clone(), ident: variant.ident.clone(),
attrs: attrs, attrs: attrs,
style: style, style: style,
fields: fields, fields: fields,
} }
}, })
)
.collect() .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 { match *data {
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)), syn::VariantData::Struct(ref fields) => (
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => { Style::Struct,
(Style::Newtype, fields_from_ast(cx, fields, attrs)) fields_from_ast(cx, fields, attrs, container_default),
} ),
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)), 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()), 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 fields
.iter() .iter()
.enumerate() .enumerate()
.map( .map(|(i, field)| Field {
|(i, field)| { ident: field.ident.clone(),
Field { attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
ident: field.ident.clone(), ty: &field.ty,
attrs: attr::Field::from_ast(cx, i, field, attrs), })
ty: &field.ty,
}
},
)
.collect() .collect()
} }
+127 -122
View File
@@ -164,6 +164,15 @@ pub enum Identifier {
Variant, Variant,
} }
impl Identifier {
pub fn is_some(self) -> bool {
match self {
Identifier::No => false,
Identifier::Field | Identifier::Variant => true,
}
}
}
impl Container { impl Container {
/// Extract out the `#[serde(...)]` attributes from an item. /// Extract out the `#[serde(...)]` attributes from an item.
pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self { 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) { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) { match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule), Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => { Err(()) => cx.error(format!(
cx.error(format!("unknown rename rule for #[serde(rename_all \ "unknown rename rule for #[serde(rename_all \
= {:?})]", = {:?})]",
s)) s
} )),
} }
} }
} }
@@ -222,19 +231,15 @@ impl Container {
} }
// Parse `#[serde(default)]` // Parse `#[serde(default)]`
MetaItem(Word(ref name)) if name == "default" => { MetaItem(Word(ref name)) if name == "default" => match item.body {
match item.body { syn::Body::Struct(syn::VariantData::Struct(_)) => {
syn::Body::Struct(syn::VariantData::Struct(_)) => { default.set(Default::Default);
default.set(Default::Default);
}
_ => {
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",
),
},
// Parse `#[serde(default = "...")]` // Parse `#[serde(default = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "default" => { MetaItem(NameValue(ref name, ref lit)) if name == "default" => {
@@ -243,12 +248,10 @@ impl Container {
syn::Body::Struct(syn::VariantData::Struct(_)) => { syn::Body::Struct(syn::VariantData::Struct(_)) => {
default.set(Default::Path(path)); default.set(Default::Path(path));
} }
_ => { _ => cx.error(
cx.error( "#[serde(default = \"...\")] can only be used \
"#[serde(default = \"...\")] can only be used \ on structs with named fields",
on structs with named fields", ),
)
}
} }
} }
} }
@@ -256,7 +259,8 @@ impl Container {
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => { MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = 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()); ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates); de_bound.set(where_predicates);
} }
@@ -271,16 +275,14 @@ impl Container {
} }
// Parse `#[serde(untagged)]` // Parse `#[serde(untagged)]`
MetaItem(Word(ref name)) if name == "untagged" => { MetaItem(Word(ref name)) if name == "untagged" => match item.body {
match item.body { syn::Body::Enum(_) => {
syn::Body::Enum(_) => { untagged.set_true();
untagged.set_true();
}
syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
} }
} syn::Body::Struct(_) => {
cx.error("#[serde(untagged)] can only be used on enums")
}
},
// Parse `#[serde(tag = "type")]` // Parse `#[serde(tag = "type")]`
MetaItem(NameValue(ref name, ref lit)) if name == "tag" => { MetaItem(NameValue(ref name, ref lit)) if name == "tag" => {
@@ -303,12 +305,10 @@ impl Container {
syn::Body::Enum(_) => { syn::Body::Enum(_) => {
content.set(s); content.set(s);
} }
syn::Body::Struct(_) => { syn::Body::Struct(_) => cx.error(
cx.error( "#[serde(content = \"...\")] can only be used on \
"#[serde(content = \"...\")] can only be used on \ enums",
enums", ),
)
}
} }
} }
} }
@@ -345,8 +345,10 @@ impl Container {
} }
MetaItem(ref meta_item) => { MetaItem(ref meta_item) => {
cx.error(format!("unknown serde container attribute `{}`", cx.error(format!(
meta_item.name())); "unknown serde container attribute `{}`",
meta_item.name()
));
} }
Literal(_) => { Literal(_) => {
@@ -434,13 +436,12 @@ fn decide_tag(
if let syn::Body::Enum(ref variants) = item.body { if let syn::Body::Enum(ref variants) = item.body {
for variant in variants { for variant in variants {
match variant.data { match variant.data {
syn::VariantData::Struct(_) | syn::VariantData::Struct(_) | syn::VariantData::Unit => {}
syn::VariantData::Unit => {}
syn::VariantData::Tuple(ref fields) => { syn::VariantData::Tuple(ref fields) => {
if fields.len() != 1 { if fields.len() != 1 {
cx.error( cx.error(
"#[serde(tag = \"...\")] cannot be used with tuple \ "#[serde(tag = \"...\")] cannot be used with tuple \
variants", variants",
); );
break; break;
} }
@@ -455,21 +456,19 @@ fn decide_tag(
EnumTag::External // doesn't matter, will error EnumTag::External // doesn't matter, will error
} }
(false, None, Some(_)) => { (false, None, Some(_)) => {
cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together",); cx.error("#[serde(tag = \"...\", content = \"...\")] must be used together");
EnumTag::External EnumTag::External
} }
(true, None, Some(_)) => { (true, None, Some(_)) => {
cx.error("untagged enum cannot have #[serde(content = \"...\")]"); cx.error("untagged enum cannot have #[serde(content = \"...\")]");
EnumTag::External EnumTag::External
} }
(false, Some(tag), Some(content)) => { (false, Some(tag), Some(content)) => EnumTag::Adjacent {
EnumTag::Adjacent { tag: tag,
tag: tag, content: content,
content: content, },
}
}
(true, Some(_), Some(_)) => { (true, Some(_), Some(_)) => {
cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]",); cx.error("untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]");
EnumTag::External EnumTag::External
} }
} }
@@ -484,7 +483,7 @@ fn decide_identifier(
match (&item.body, field_identifier.get(), variant_identifier.get()) { match (&item.body, field_identifier.get(), variant_identifier.get()) {
(_, false, false) => Identifier::No, (_, false, false) => Identifier::No,
(_, true, true) => { (_, 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 Identifier::No
} }
(&syn::Body::Struct(_), true, false) => { (&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) { if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
match RenameRule::from_str(&s) { match RenameRule::from_str(&s) {
Ok(rename_rule) => rename_all.set(rename_rule), Ok(rename_rule) => rename_all.set(rename_rule),
Err(()) => { Err(()) => cx.error(format!(
cx.error(format!("unknown rename rule for #[serde(rename_all \ "unknown rename rule for #[serde(rename_all \
= {:?})]", = {:?})]",
s)) s
} )),
} }
} }
} }
@@ -602,19 +601,20 @@ impl Variant {
} }
// Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]` // Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]`
MetaItem(ref mi) if mi.name() == "borrow" => { MetaItem(ref mi) if mi.name() == "borrow" => match variant.data {
match variant.data { syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => { borrow.set(mi.clone());
borrow.set(mi.clone());
}
_ => {
cx.error("#[serde(borrow)] may only be used on newtype variants");
}
} }
} _ => {
cx.error("#[serde(borrow)] may only be used on newtype variants");
}
},
MetaItem(ref meta_item) => { 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(_) => { Literal(_) => {
@@ -714,7 +714,13 @@ pub enum Default {
impl Field { impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct 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 ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename");
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing"); let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
@@ -739,7 +745,12 @@ impl Field {
.as_ref() .as_ref()
.map(|borrow| vec![MetaItem(borrow.clone())]); .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 { for meta_item in meta_items {
match meta_item { match meta_item {
// Parse `#[serde(rename = "foo")]` // Parse `#[serde(rename = "foo")]`
@@ -784,7 +795,7 @@ impl Field {
MetaItem(Word(ref name)) if name == "skip" => { MetaItem(Word(ref name)) if name == "skip" => {
skip_serializing.set_true(); skip_serializing.set_true();
skip_deserializing.set_true(); skip_deserializing.set_true();
}, }
// Parse `#[serde(skip_serializing_if = "...")]` // Parse `#[serde(skip_serializing_if = "...")]`
MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => { MetaItem(NameValue(ref name, ref lit)) if name == "skip_serializing_if" => {
@@ -822,7 +833,8 @@ impl Field {
// Parse `#[serde(bound = "D: Serialize")]` // Parse `#[serde(bound = "D: Serialize")]`
MetaItem(NameValue(ref name, ref lit)) if name == "bound" => { MetaItem(NameValue(ref name, ref lit)) if name == "bound" => {
if let Ok(where_predicates) = 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()); ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates); de_bound.set(where_predicates);
} }
@@ -849,13 +861,10 @@ impl Field {
if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) { if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, &field.ty) {
for lifetime in &lifetimes { for lifetime in &lifetimes {
if !borrowable.contains(lifetime) { if !borrowable.contains(lifetime) {
cx.error( cx.error(format!(
format!( "field `{}` does not have lifetime {}",
"field `{}` does not have lifetime {}", ident, lifetime.ident
ident, ));
lifetime.ident
),
);
} }
} }
borrowed_lifetimes.set(lifetimes); borrowed_lifetimes.set(lifetimes);
@@ -871,7 +880,10 @@ impl Field {
} }
MetaItem(ref meta_item) => { 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(_) => { Literal(_) => {
@@ -881,9 +893,10 @@ impl Field {
} }
} }
// Is skip_deserializing, initialize the field to Default::default() // Is skip_deserializing, initialize the field to Default::default() unless a different
// unless a different default is specified by `#[serde(default = "...")]` // default is specified by `#[serde(default = "...")]` on ourselves or our container (e.g.
if skip_deserializing.0.value.is_some() { // the struct we are in).
if container_default == &Default::None && skip_deserializing.0.value.is_some() {
default.set_if_none(Default::Default); default.set_if_none(Default::Default);
} }
@@ -1018,13 +1031,11 @@ where
} }
_ => { _ => {
cx.error( cx.error(format!(
format!( "malformed {0} attribute, expected `{0}(serialize = ..., \
"malformed {0} attribute, expected `{0}(serialize = ..., \ deserialize = ...)`",
deserialize = ...)`", attr_name
attr_name ));
),
);
return Err(()); return Err(());
} }
} }
@@ -1060,13 +1071,10 @@ fn get_string_from_lit(
if let syn::Lit::Str(ref s, _) = *lit { if let syn::Lit::Str(ref s, _) = *lit {
Ok(s.clone()) Ok(s.clone())
} else { } else {
cx.error( cx.error(format!(
format!( "expected serde {} attribute to be a string: `{} = \"...\"`",
"expected serde {} attribute to be a string: `{} = \"...\"`", attr_name, meta_item_name
attr_name, ));
meta_item_name
),
);
Err(()) 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, ()> { 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)); let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_type(&string).map_err( syn::parse_type(&string).map_err(|_| {
|_| { cx.error(format!(
cx.error(format!("failed to parse type: {} = {:?}", attr_name, string),) "failed to parse type: {} = {:?}",
}, attr_name, string
) ))
})
} }
// Parses a string literal like "'a + 'b + 'c" containing a nonempty list of // 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); 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". // 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; return false;
} }
}; };
seg.ident == "Cow" && params.lifetimes.len() == 1 && seg.ident == "Cow" && params.lifetimes.len() == 1
params.types == vec![syn::parse_type(elem).unwrap()] && params.bindings.is_empty() && 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 // 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 { fn is_rptr(ty: &syn::Ty, elem: &str) -> bool {
match *ty { match *ty {
syn::Ty::Rptr(Some(_), ref mut_ty) => { syn::Ty::Rptr(Some(_), ref mut_ty) => {
mut_ty.mutability == syn::Mutability::Immutable && mut_ty.mutability == syn::Mutability::Immutable
mut_ty.ty == syn::parse_type(elem).unwrap() && mut_ty.ty == syn::parse_type(elem).unwrap()
} }
_ => false, _ => false,
} }
@@ -1225,7 +1234,7 @@ fn borrowable_lifetimes(
let mut lifetimes = BTreeSet::new(); let mut lifetimes = BTreeSet::new();
collect_lifetimes(ty, &mut lifetimes); collect_lifetimes(ty, &mut lifetimes);
if lifetimes.is_empty() { 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 { } else {
Ok(lifetimes) Ok(lifetimes)
} }
@@ -1233,9 +1242,7 @@ fn borrowable_lifetimes(
fn collect_lifetimes(ty: &syn::Ty, out: &mut BTreeSet<syn::Lifetime>) { fn collect_lifetimes(ty: &syn::Ty, out: &mut BTreeSet<syn::Lifetime>) {
match *ty { match *ty {
syn::Ty::Slice(ref elem) | syn::Ty::Slice(ref elem) | syn::Ty::Array(ref elem, _) | syn::Ty::Paren(ref elem) => {
syn::Ty::Array(ref elem, _) |
syn::Ty::Paren(ref elem) => {
collect_lifetimes(elem, out); collect_lifetimes(elem, out);
} }
syn::Ty::Ptr(ref elem) => { 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()); out.extend(lifetime.iter().cloned());
collect_lifetimes(&elem.ty, out); collect_lifetimes(&elem.ty, out);
} }
syn::Ty::Tup(ref elems) => { syn::Ty::Tup(ref elems) => for elem in elems {
for elem in elems { collect_lifetimes(elem, out);
collect_lifetimes(elem, out); },
}
}
syn::Ty::Path(ref qself, ref path) => { syn::Ty::Path(ref qself, ref path) => {
if let Some(ref qself) = *qself { if let Some(ref qself) = *qself {
collect_lifetimes(&qself.ty, out); 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::BareFn(_)
syn::Ty::Never | | syn::Ty::Never
syn::Ty::TraitObject(_) | | syn::Ty::TraitObject(_)
syn::Ty::ImplTrait(_) | | syn::Ty::ImplTrait(_)
syn::Ty::Infer | | syn::Ty::Infer
syn::Ty::Mac(_) => {} | syn::Ty::Mac(_) => {}
} }
} }
+51 -18
View File
@@ -31,7 +31,7 @@ pub enum RenameRule {
/// Rename direct children to "kebab-case" style. /// Rename direct children to "kebab-case" style.
KebabCase, KebabCase,
/// Rename direct children to "SCREAMING-KEBAB-CASE" style. /// Rename direct children to "SCREAMING-KEBAB-CASE" style.
ScreamingKebabCase ScreamingKebabCase,
} }
impl RenameRule { impl RenameRule {
@@ -52,7 +52,9 @@ impl RenameRule {
} }
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(), ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"), 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(), ScreamingSnakeCase => field.to_ascii_uppercase(),
KebabCase => field.replace('_', "-"), 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] #[test]
fn rename_variants() { fn rename_variants() {
for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in &[
&[ (
("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"), "Outcome",
("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"), "outcome",
("A", "a", "a", "a", "A", "a", "A"), "outcome",
("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"), "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!(None.apply_to_variant(original), original);
assert_eq!(LowerCase.apply_to_variant(original), lower); assert_eq!(LowerCase.apply_to_variant(original), lower);
assert_eq!(PascalCase.apply_to_variant(original), original); 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!(SnakeCase.apply_to_variant(original), snake);
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming); assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
assert_eq!(KebabCase.apply_to_variant(original), kebab); 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] #[test]
fn rename_fields() { fn rename_fields() {
for &(original, pascal, camel, screaming, kebab, screaming_kebab) in for &(original, pascal, camel, screaming, kebab, screaming_kebab) in &[
&[ (
("outcome", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"), "outcome",
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"), "Outcome",
("a", "A", "a", "A", "a", "A"), "outcome",
("z42", "Z42", "z42", "Z42", "z42", "Z42"), "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!(None.apply_to_field(original), original);
assert_eq!(PascalCase.apply_to_field(original), pascal); assert_eq!(PascalCase.apply_to_field(original), pascal);
assert_eq!(CamelCase.apply_to_field(original), camel); 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() { if cont.body.has_getter() && cont.attrs.remote().is_none() {
cx.error( cx.error(
"#[serde(getter = \"...\")] can only be used in structs \ "#[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() { 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. // The `other` attribute may only be used in a field_identifier.
(_, Identifier::Variant, true) | (_, Identifier::Variant, true) | (_, Identifier::No, true) => {
(_, Identifier::No, true) => {
cx.error("#[serde(other)] may only be used inside a field_identifier"); 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() { for variant in variants.iter() {
if variant.attrs.serialize_with().is_some() { if variant.attrs.serialize_with().is_some() {
if variant.attrs.skip_serializing() { if variant.attrs.skip_serializing() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \ cx.error(format!(
#[serde(skip_serializing)]", variant.ident)); "variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]",
variant.ident
));
} }
for (i, field) in variant.fields.iter().enumerate() { for (i, field) in variant.fields.iter().enumerate() {
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i), let ident = field
|ident| format!("`{}`", ident)); .ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
if field.attrs.skip_serializing() { if field.attrs.skip_serializing() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \ cx.error(format!(
a field {} marked with #[serde(skip_serializing)]", "variant `{}` cannot have both #[serde(serialize_with)] and \
variant.ident, ident)); a field {} marked with #[serde(skip_serializing)]",
variant.ident, ident
));
} }
if field.attrs.skip_serializing_if().is_some() { if field.attrs.skip_serializing_if().is_some() {
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \ cx.error(format!(
a field {} marked with #[serde(skip_serializing_if)]", "variant `{}` cannot have both #[serde(serialize_with)] and \
variant.ident, ident)); a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, ident
));
} }
} }
} }
if variant.attrs.deserialize_with().is_some() { if variant.attrs.deserialize_with().is_some() {
if variant.attrs.skip_deserializing() { if variant.attrs.skip_deserializing() {
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] and \ cx.error(format!(
#[serde(skip_deserializing)]", variant.ident)); "variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]",
variant.ident
));
} }
for (i, field) in variant.fields.iter().enumerate() { for (i, field) in variant.fields.iter().enumerate() {
if field.attrs.skip_deserializing() { if field.attrs.skip_deserializing() {
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i), let ident = field
|ident| format!("`{}`", ident)); .ident
.as_ref()
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] \ cx.error(format!(
and a field {} marked with #[serde(skip_deserializing)]", "variant `{}` cannot have both #[serde(deserialize_with)] \
variant.ident, ident)); and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, ident
));
} }
} }
} }
+3 -1
View File
@@ -16,7 +16,9 @@ pub struct Ctxt {
impl Ctxt { impl Ctxt {
pub fn new() -> Self { 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) { 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 // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.17.0")] #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.18.1")]
extern crate syn; extern crate syn;
#[macro_use] #[macro_use]
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.23" # remember to update html_root_url version = "1.0.25" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
+18 -2
View File
@@ -184,11 +184,27 @@ where
T: Deserialize<'de> + PartialEq + Debug, T: Deserialize<'de> + PartialEq + Debug,
{ {
let mut de = Deserializer::new(tokens); let mut de = Deserializer::new(tokens);
match T::deserialize(&mut de) { let mut deserialized_val = match T::deserialize(&mut de) {
Ok(v) => assert_eq!(v, *value), Ok(v) => {
assert_eq!(v, *value);
v
}
Err(e) => panic!("tokens failed to deserialize: {}", e), 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 { if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining()); panic!("{} remaining tokens", de.remaining());
} }
+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 /// Trait to determine whether a value is represented in human-readable or
/// compact form. /// compact form.
/// ///
/// ``` /// ```
/// extern crate serde; /// extern crate serde;
/// extern crate serde_test; /// extern crate serde_test;
/// ///
/// use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// use serde_test::{Configure, Token, assert_tokens}; /// use serde_test::{Configure, Token, assert_tokens};
/// ///
/// #[derive(Debug, PartialEq)] /// #[derive(Debug, PartialEq)]
/// struct Example(u8, u8); /// struct Example(u8, u8);
/// ///
/// impl Serialize for Example { /// impl Serialize for Example {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
/// where S: Serializer, /// where S: Serializer,
@@ -33,7 +33,7 @@ pub struct Compact<T: ?Sized>(T);
/// } /// }
/// } /// }
/// } /// }
/// ///
/// impl<'de> Deserialize<'de> for Example { /// impl<'de> Deserialize<'de> for Example {
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> /// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
/// where D: Deserializer<'de>, /// where D: Deserializer<'de>,
@@ -52,7 +52,7 @@ pub struct Compact<T: ?Sized>(T);
/// } /// }
/// } /// }
/// } /// }
/// ///
/// fn main() { /// fn main() {
/// assert_tokens( /// assert_tokens(
/// &Example(1, 0).compact(), /// &Example(1, 0).compact(),
@@ -73,11 +73,17 @@ pub struct Compact<T: ?Sized>(T);
/// ``` /// ```
pub trait Configure { pub trait Configure {
/// Marks `self` as using `is_human_readable == true` /// 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) Readable(self)
} }
/// Marks `self` as using `is_human_readable == false` /// 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) Compact(self)
} }
} }
@@ -158,7 +164,6 @@ where
} }
} }
macro_rules! forward_method { macro_rules! forward_method {
($name: ident (self $(, $arg: ident : $arg_type: ty)* ) -> $return_type: ty) => { ($name: ident (self $(, $arg: ident : $arg_type: ty)* ) -> $return_type: ty) => {
fn $name (self $(, $arg : $arg_type)* ) -> $return_type { fn $name (self $(, $arg : $arg_type)* ) -> $return_type {
@@ -455,8 +460,7 @@ macro_rules! impl_serializer {
impl_serializer!(Readable, true); impl_serializer!(Readable, true);
impl_serializer!(Compact, false); impl_serializer!(Compact, false);
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
use serde::de::{Visitor, EnumAccess, VariantAccess, MapAccess, DeserializeSeed, SeqAccess, Error};
macro_rules! forward_deserialize_methods { macro_rules! forward_deserialize_methods {
( $wrapper : ident ( $( $name: ident ),* ) ) => { ( $wrapper : ident ( $( $name: ident ),* ) ) => {
@@ -468,7 +472,6 @@ macro_rules! forward_deserialize_methods {
}; };
} }
macro_rules! impl_deserializer { macro_rules! impl_deserializer {
($wrapper : ident, $is_human_readable : expr) => { ($wrapper : ident, $is_human_readable : expr) => {
impl <'de, D> Deserializer<'de> for $wrapper<D> where D: Deserializer<'de> { 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 where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let value = try!( let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
visitor.visit_seq( de: self,
DeserializerSeqVisitor { len: len,
de: self, end: end,
len: len, },));
end: end,
},
)
);
assert_next_token!(self, end); assert_next_token!(self, end);
Ok(value) Ok(value)
} }
@@ -117,15 +113,11 @@ impl<'de> Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let value = try!( let value = try!(visitor.visit_map(DeserializerMapVisitor {
visitor.visit_map( de: self,
DeserializerMapVisitor { len: len,
de: self, end: end,
len: len, },));
end: end,
},
)
);
assert_next_token!(self, end); assert_next_token!(self, end);
Ok(value) 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::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor), Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, 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::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor), Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
Token::Enum { .. } => { 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::UnitVariant { variant, .. } => visitor.visit_str(variant),
Token::NewtypeVariant { variant, .. } => { Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),) self,
} Token::Str(variant),
Token::TupleVariant { variant, .. } => { EnumFormat::Any,
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),) )),
} Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
Token::StructVariant { variant, .. } => { self,
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),) Token::Str(variant),
} EnumFormat::Seq,
Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd | )),
Token::StructEnd | Token::TupleVariantEnd | Token::StructVariantEnd => { 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); unexpected!(token);
} }
} }
@@ -216,8 +221,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: Visitor<'de>, V: Visitor<'de>,
{ {
match self.peek_token() { match self.peek_token() {
Token::Unit | Token::Unit | Token::None => {
Token::None => {
self.next_token(); self.next_token();
visitor.visit_none() visitor.visit_none()
} }
@@ -244,10 +248,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
visitor.visit_enum(DeserializerEnumVisitor { de: self }) visitor.visit_enum(DeserializerEnumVisitor { de: self })
} }
Token::UnitVariant { name: n, .. } | Token::UnitVariant { name: n, .. }
Token::NewtypeVariant { name: n, .. } | | Token::NewtypeVariant { name: n, .. }
Token::TupleVariant { name: n, .. } | | Token::TupleVariant { name: n, .. }
Token::StructVariant { name: n, .. } if name == n => { | Token::StructVariant { name: n, .. } if name == n =>
{
visitor.visit_enum(DeserializerEnumVisitor { de: self }) 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 where
V: Visitor<'de>, V: Visitor<'de>,
{ {
@@ -287,8 +296,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
V: Visitor<'de>, V: Visitor<'de>,
{ {
match self.peek_token() { match self.peek_token() {
Token::Unit | Token::Unit | Token::UnitStruct { .. } => {
Token::UnitStruct { .. } => {
self.next_token(); self.next_token();
visitor.visit_unit() visitor.visit_unit()
} }
@@ -448,10 +456,10 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
V: DeserializeSeed<'de>, V: DeserializeSeed<'de>,
{ {
match self.de.peek_token() { match self.de.peek_token() {
Token::UnitVariant { variant: v, .. } | Token::UnitVariant { variant: v, .. }
Token::NewtypeVariant { variant: v, .. } | | Token::NewtypeVariant { variant: v, .. }
Token::TupleVariant { variant: v, .. } | | Token::TupleVariant { variant: v, .. }
Token::StructVariant { variant: v, .. } => { | Token::StructVariant { variant: v, .. } => {
let de = v.into_deserializer(); let de = v.into_deserializer();
let value = try!(seed.deserialize(de)); let value = try!(seed.deserialize(de));
Ok((value, self)) Ok((value, self))
@@ -505,7 +513,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
unexpected!(token); unexpected!(token);
} }
} }
Token::Seq { len: Some(enum_len) } => { Token::Seq {
len: Some(enum_len),
} => {
let token = self.de.next_token(); let token = self.de.next_token();
if len == enum_len { 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 where
V: Visitor<'de>, V: Visitor<'de>,
{ {
@@ -533,7 +547,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
unexpected!(token); unexpected!(token);
} }
} }
Token::Map { len: Some(enum_len) } => { Token::Map {
len: Some(enum_len),
} => {
let token = self.de.next_token(); let token = self.de.next_token();
if fields.len() == enum_len { if fields.len() == enum_len {
@@ -581,10 +597,8 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
{ {
match self.variant.take() { match self.variant.take() {
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(Token::Bytes(variant)) => { Some(Token::Bytes(variant)) => seed.deserialize(BytesDeserializer { value: variant })
seed.deserialize(BytesDeserializer { value: variant }) .map(Some),
.map(Some)
}
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some), Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
Some(other) => unexpected!(other), Some(other) => unexpected!(other),
None => Ok(None), None => Ok(None),
+7 -3
View File
@@ -9,7 +9,7 @@
use std::error; use std::error;
use std::fmt::{self, Display}; use std::fmt::{self, Display};
use serde::{ser, de}; use serde::{de, ser};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Error { pub struct Error {
@@ -18,13 +18,17 @@ pub struct Error {
impl ser::Error for Error { impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self { fn custom<T: Display>(msg: T) -> Self {
Error { msg: msg.to_string() } Error {
msg: msg.to_string(),
}
} }
} }
impl de::Error for Error { impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Self { fn custom<T: Display>(msg: T) -> Self {
Error { msg: msg.to_string() } Error {
msg: msg.to_string(),
}
} }
} }
+3 -8
View File
@@ -155,18 +155,13 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.23")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.25")]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints // Whitelisted clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))] #![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
// Whitelisted clippy_pedantic lints // Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow( #![cfg_attr(feature = "cargo-clippy",
missing_docs_in_private_items, allow(missing_docs_in_private_items, stutter, use_debug, use_self))]
stutter,
use_debug,
use_self,
))]
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
+18 -4
View File
@@ -232,7 +232,10 @@ pub enum Token {
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]); /// 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. /// 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. /// 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. /// An indicator of the end of a tuple variant.
TupleVariantEnd, 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. /// An indicator of the end of a struct variant.
StructVariantEnd, StructVariantEnd,
+1 -1
View File
@@ -11,7 +11,7 @@ unstable = ["serde/unstable", "compiletest_rs"]
fnv = "1.0" fnv = "1.0"
rustc-serialize = "0.3.16" rustc-serialize = "0.3.16"
serde = { path = "../serde", features = ["rc"] } serde = { path = "../serde", features = ["rc"] }
serde_derive = { path = "../serde_derive" } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" } serde_test = { path = "../serde_test" }
[dependencies] [dependencies]
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}; use serde::{Deserialize, Deserializer};
extern crate serde_test; 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; use std::borrow::Cow;
@@ -87,18 +87,18 @@ fn test_struct() {
assert_de_tokens( assert_de_tokens(
&Borrowing { &Borrowing {
bs: "str", bs: "str",
bb: b"bytes", bb: b"bytes",
}, },
&[ &[
Token::Struct { name: "Borrowing", len: 2 }, Token::Struct {
name: "Borrowing",
len: 2,
},
Token::BorrowedStr("bs"), Token::BorrowedStr("bs"),
Token::BorrowedStr("str"), Token::BorrowedStr("str"),
Token::BorrowedStr("bb"), Token::BorrowedStr("bb"),
Token::BorrowedBytes(b"bytes"), Token::BorrowedBytes(b"bytes"),
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -115,14 +115,14 @@ fn test_cow() {
} }
let tokens = &[ let tokens = &[
Token::Struct { name: "Cows", len: 2 }, Token::Struct {
name: "Cows",
len: 2,
},
Token::Str("copied"), Token::Str("copied"),
Token::BorrowedStr("copied"), Token::BorrowedStr("copied"),
Token::Str("borrowed"), Token::Str("borrowed"),
Token::BorrowedStr("borrowed"), Token::BorrowedStr("borrowed"),
Token::StructEnd, Token::StructEnd,
]; ];
+39 -5
View File
@@ -49,14 +49,16 @@ struct TupleStruct(i32, i32, i32);
struct Struct { struct Struct {
a: i32, a: i32,
b: i32, b: i32,
#[serde(skip_deserializing)] c: i32, #[serde(skip_deserializing)]
c: i32,
} }
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
struct StructDenyUnknown { struct StructDenyUnknown {
a: i32, a: i32,
#[serde(skip_deserializing)] b: i32, #[serde(skip_deserializing)]
b: i32,
} }
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
@@ -77,13 +79,35 @@ impl Default for StructDefault<String> {
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
struct StructSkipAll { 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)] #[derive(PartialEq, Debug, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
struct StructSkipAllDenyUnknown { struct StructSkipAllDenyUnknown {
#[serde(skip_deserializing)] a: i32, #[serde(skip_deserializing)]
a: i32,
} }
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
@@ -94,7 +118,11 @@ enum Enum {
Unit, Unit,
Simple(i32), Simple(i32),
Seq(i32, i32, i32), Seq(i32, i32, i32),
Map { a: i32, b: i32, c: i32 }, Map {
a: i32,
b: i32,
c: i32,
},
} }
#[derive(PartialEq, Debug, Deserialize)] #[derive(PartialEq, Debug, Deserialize)]
@@ -600,6 +628,12 @@ declare_tests! {
Token::StructEnd, Token::StructEnd,
], ],
} }
test_struct_skip_default {
StructSkipDefault { a: 16 } => &[
Token::Struct { name: "StructSkipDefault", len: 0 },
Token::StructEnd,
],
}
test_struct_skip_all_deny_unknown { test_struct_skip_all_deny_unknown {
StructSkipAllDenyUnknown { a: 0 } => &[ StructSkipAllDenyUnknown { a: 0 } => &[
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 }, Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
+49 -58
View File
@@ -11,7 +11,6 @@
// types involved. // types involved.
#![deny(warnings)] #![deny(warnings)]
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))] #![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
#[macro_use] #[macro_use]
@@ -47,7 +46,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct With<T> { struct With<T> {
t: T, t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
x: X, x: X,
} }
assert::<With<i32>>(); assert::<With<i32>>();
@@ -55,7 +54,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct WithTogether<T> { struct WithTogether<T> {
t: T, t: T,
#[serde(with="both_x")] #[serde(with = "both_x")]
x: X, x: X,
} }
assert::<WithTogether<i32>>(); assert::<WithTogether<i32>>();
@@ -64,7 +63,7 @@ fn test_gen() {
struct WithRef<'a, T: 'a> { struct WithRef<'a, T: 'a> {
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
t: StdOption<&'a T>, t: StdOption<&'a T>,
#[serde(serialize_with="ser_x", deserialize_with="de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
x: X, x: X,
} }
assert::<WithRef<i32>>(); assert::<WithRef<i32>>();
@@ -94,17 +93,17 @@ fn test_gen() {
enum EnumWith<T> { enum EnumWith<T> {
Unit, Unit,
Newtype( Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X X,
), ),
Tuple( Tuple(
T, T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X X,
), ),
Struct { Struct {
t: T, t: T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
x: X, x: X,
}, },
} }
@@ -124,16 +123,16 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Newtype( struct Newtype(
#[serde(serialize_with="ser_x", deserialize_with="de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X X,
); );
assert::<Newtype>(); assert::<Newtype>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Tuple<T>( struct Tuple<T>(
T, T,
#[serde(serialize_with="ser_x", deserialize_with="de_x")] #[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
X X,
); );
assert::<Tuple<i32>>(); assert::<Tuple<i32>>();
@@ -143,7 +142,9 @@ fn test_gen() {
left: Box<TreeNode<D>>, left: Box<TreeNode<D>>,
right: Box<TreeNode<D>>, right: Box<TreeNode<D>>,
}, },
Leaf { data: D }, Leaf {
data: D,
},
} }
assert::<TreeNode<i32>>(); assert::<TreeNode<i32>>();
@@ -188,29 +189,28 @@ fn test_gen() {
assert_ser::<OptionStatic>(); assert_ser::<OptionStatic>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(bound="D: SerializeWith + DeserializeWith")] #[serde(bound = "D: SerializeWith + DeserializeWith")]
struct WithTraits1<D, E> { struct WithTraits1<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with", #[serde(serialize_with = "SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")] deserialize_with = "DeserializeWith::deserialize_with")]
d: D, d: D,
#[serde(serialize_with="SerializeWith::serialize_with", #[serde(serialize_with = "SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with", deserialize_with = "DeserializeWith::deserialize_with",
bound="E: SerializeWith + DeserializeWith")] bound = "E: SerializeWith + DeserializeWith")]
e: E, e: E,
} }
assert::<WithTraits1<X, X>>(); assert::<WithTraits1<X, X>>();
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(bound(serialize="D: SerializeWith", #[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
deserialize="D: DeserializeWith"))]
struct WithTraits2<D, E> { struct WithTraits2<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with", #[serde(serialize_with = "SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")] deserialize_with = "DeserializeWith::deserialize_with")]
d: D, d: D,
#[serde(serialize_with="SerializeWith::serialize_with", #[serde(serialize_with = "SerializeWith::serialize_with",
bound(serialize="E: SerializeWith"))] bound(serialize = "E: SerializeWith"))]
#[serde(deserialize_with="DeserializeWith::deserialize_with", #[serde(deserialize_with = "DeserializeWith::deserialize_with",
bound(deserialize="E: DeserializeWith"))] bound(deserialize = "E: DeserializeWith"))]
e: E, e: E,
} }
assert::<WithTraits2<X, X>>(); assert::<WithTraits2<X, X>>();
@@ -272,14 +272,14 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct TupleSkipAll( struct TupleSkipAll(
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
u8 u8,
); );
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
struct TupleSkipAllDenyUnknown( struct TupleSkipAllDenyUnknown(
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
u8 u8,
); );
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -307,7 +307,7 @@ fn test_gen() {
}, },
TupleSkip( TupleSkip(
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
u8 u8,
), ),
} }
@@ -323,7 +323,7 @@ fn test_gen() {
}, },
TupleSkip( TupleSkip(
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
u8 u8,
), ),
} }
@@ -403,10 +403,7 @@ fn test_gen() {
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)] #[allow(dead_code)]
Struct { Struct { f1: String, f2: u8 },
f1: String,
f2: u8,
},
#[serde(serialize_with = "serialize_some_unit_variant")] #[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(deserialize_with = "deserialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")]
@@ -429,10 +426,7 @@ fn test_gen() {
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)] #[allow(dead_code)]
Struct { Struct { f1: String, f2: u8 },
f1: String,
f2: u8,
},
#[serde(serialize_with = "serialize_some_unit_variant")] #[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(deserialize_with = "deserialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")]
@@ -460,10 +454,7 @@ fn test_gen() {
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)] #[allow(dead_code)]
Struct { Struct { f1: String, f2: u8 },
f1: String,
f2: u8,
},
#[serde(serialize_with = "serialize_some_unit_variant")] #[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(deserialize_with = "deserialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")]
@@ -491,10 +482,7 @@ fn test_gen() {
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
#[allow(dead_code)] #[allow(dead_code)]
Struct { Struct { f1: String, f2: u8 },
f1: String,
f2: u8,
},
#[serde(serialize_with = "serialize_some_unit_variant")] #[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(deserialize_with = "deserialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")]
@@ -517,10 +505,7 @@ fn test_gen() {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
enum StaticStrEnum<'a> { enum StaticStrEnum<'a> {
Struct { Struct { a: &'a str, b: &'static str },
a: &'a str,
b: &'static str,
},
Tuple(&'a str, &'static str), Tuple(&'a str, &'static str),
Newtype(&'static str), Newtype(&'static str),
} }
@@ -570,7 +555,7 @@ pub fn de_x<'de, D: Deserializer<'de>>(_: D) -> StdResult<X, D::Error> {
} }
mod both_x { 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 { impl SerializeWith for X {
@@ -586,27 +571,33 @@ impl DeserializeWith for X {
} }
pub fn serialize_some_unit_variant<S>(_: S) -> StdResult<S::Ok, S::Error> pub fn serialize_some_unit_variant<S>(_: S) -> StdResult<S::Ok, S::Error>
where S: Serializer, where
S: Serializer,
{ {
unimplemented!() unimplemented!()
} }
pub fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error> pub fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error>
where D: Deserializer<'de>, where
D: Deserializer<'de>,
{ {
unimplemented!() unimplemented!()
} }
pub fn serialize_some_other_variant<S>(_: &str, _: &u8, _: S) -> StdResult<S::Ok, S::Error> pub fn serialize_some_other_variant<S>(_: &str, _: &u8, _: S) -> StdResult<S::Ok, S::Error>
where S: Serializer, where
S: Serializer,
{ {
unimplemented!() unimplemented!()
} }
pub fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error> pub fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error>
where D: Deserializer<'de>, where
D: Deserializer<'de>,
{ {
unimplemented!() 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 { enum F {
Aaa, Aaa,
Bbb, Bbb,
#[serde(other)] Other, #[serde(other)]
Other,
} }
assert_de_tokens(&F::Other, &[Token::Str("x")]); 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)] #[derive(Serialize, Deserialize)]
struct Test { 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)] #[derive(Serialize, Deserialize)]
@@ -110,7 +119,10 @@ struct UnitDef;
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePriv")] #[serde(remote = "remote::PrimitivePriv")]
struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8); struct PrimitivePrivDef(
#[serde(getter = "remote::PrimitivePriv::get")]
u8,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::PrimitivePub")] #[serde(remote = "remote::PrimitivePub")]
@@ -119,28 +131,39 @@ struct PrimitivePubDef(u8);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePriv")] #[serde(remote = "remote::NewtypePriv")]
struct NewtypePrivDef( struct NewtypePrivDef(
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit, #[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")]
remote::Unit,
); );
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::NewtypePub")] #[serde(remote = "remote::NewtypePub")]
struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit); struct NewtypePubDef(
#[serde(with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePriv")] #[serde(remote = "remote::TuplePriv")]
struct TuplePrivDef( struct TuplePrivDef(
#[serde(getter = "remote::TuplePriv::first")] u8, #[serde(getter = "remote::TuplePriv::first")]
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit, u8,
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")]
remote::Unit,
); );
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::TuplePub")] #[serde(remote = "remote::TuplePub")]
struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit); struct TuplePubDef(
u8,
#[serde(with = "UnitDef")]
remote::Unit,
);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPriv")] #[serde(remote = "remote::StructPriv")]
struct StructPrivDef { struct StructPrivDef {
#[serde(getter = "remote::StructPriv::a")] a: u8, #[serde(getter = "remote::StructPriv::a")]
a: u8,
#[serde(getter = "remote::StructPriv::b")] #[serde(getter = "remote::StructPriv::b")]
#[serde(with = "UnitDef")] #[serde(with = "UnitDef")]
@@ -150,7 +173,8 @@ struct StructPrivDef {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::StructPub")] #[serde(remote = "remote::StructPub")]
struct StructPubDef { struct StructPubDef {
#[allow(dead_code)] a: u8, #[allow(dead_code)]
a: u8,
#[allow(dead_code)] #[allow(dead_code)]
#[serde(with = "UnitDef")] #[serde(with = "UnitDef")]
+15 -5
View File
@@ -50,11 +50,21 @@ enum Enum {
Unit, Unit,
One(i32), One(i32),
Seq(i32, i32), Seq(i32, i32),
Map { a: i32, b: i32 }, Map {
#[serde(skip_serializing)] SkippedUnit, a: i32,
#[serde(skip_serializing)] SkippedOne(i32), b: i32,
#[serde(skip_serializing)] SkippedSeq(i32, i32), },
#[serde(skip_serializing)] SkippedMap { _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,
},
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////