mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 10:38:02 +00:00
Compare commits
147 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 23e2e92237 | |||
| 273b2c11c6 | |||
| c1602a4d76 | |||
| c23be3f855 | |||
| 5c9c97c0ce | |||
| e5ed440136 | |||
| d45ca2f5e4 | |||
| d7f9f8209d | |||
| 4a2612ecff | |||
| 05b22a06d7 | |||
| 3145bcc46e | |||
| 2b18b57d84 | |||
| 5520202262 | |||
| 3d647f4063 | |||
| 0fde3c2ee8 | |||
| 27f935f036 | |||
| 99614c7266 | |||
| bb2ecb3bc4 | |||
| 96393bfcc7 | |||
| 1d92569abc | |||
| e4ef087735 | |||
| 695c3eedcb | |||
| 50c636a923 | |||
| 5b884b5bf9 | |||
| 8637dda60f | |||
| abeea89147 | |||
| 6e324e887d | |||
| 7c596c7136 | |||
| f02dbf381b | |||
| 7cf184624a | |||
| c5a3128492 | |||
| 205f606962 | |||
| ad40f976db | |||
| 58d52e784b | |||
| d44f12907b | |||
| 61b167be9a | |||
| f1af2dc5ab | |||
| ebc61baab2 | |||
| ffcde25b6e | |||
| 2f57cecf13 | |||
| bfdcbae9db | |||
| ca41e16e92 | |||
| 352fe7b451 | |||
| 49e302d17d | |||
| b8602a7e43 | |||
| a8c8c2028e | |||
| d1833c5602 | |||
| b4ef7ac323 | |||
| ebf80ac965 | |||
| 112dfd7428 | |||
| b692923321 | |||
| 9e8cda4c37 | |||
| 5457394f5b | |||
| 6627540dd6 | |||
| 5ae06bba49 | |||
| 571bb8caed | |||
| 299cd2dbd0 | |||
| 583c0d8d14 | |||
| 07d07347b3 | |||
| 77b07f3fbf | |||
| 1bd2c6129c | |||
| 39413c8ce7 | |||
| b4dbae250b | |||
| 5a91ac5ba5 | |||
| 7ad836e6a9 | |||
| 72ecb9064c | |||
| 23c6eb3b40 | |||
| b8c9a66d75 | |||
| 56b2e39dda | |||
| 5bc805329e | |||
| 69dd3215f4 | |||
| a7a7a31809 | |||
| af9996aa9a | |||
| 0d4d47c398 | |||
| 30361ac6d0 | |||
| 3f75239bfb | |||
| 8dd5605a40 | |||
| f288a41768 | |||
| f4b78e202a | |||
| 0ddebe0317 | |||
| 9fc526b788 | |||
| a799ea171c | |||
| d6f07f2f47 | |||
| f9946ee0ca | |||
| a164f52315 | |||
| 8bba8447ef | |||
| 9db784bccd | |||
| 9317bc5afa | |||
| a185df1e77 | |||
| 1bdf5ecec4 | |||
| 59017aa19b | |||
| 6b4625dcbb | |||
| 6e01f220b1 | |||
| 64573319f9 | |||
| 3d64df6e87 | |||
| cc2558b0dc | |||
| 5c41661bce | |||
| dd6914a203 | |||
| 63623eb3b3 | |||
| ddc4b50d4d | |||
| b313f947dc | |||
| 16bc9fb99e | |||
| 34eaab00f7 | |||
| 6024e717fb | |||
| ef4dd6c0ec | |||
| f7ed967db1 | |||
| 613e46b0ee | |||
| b2d2e96267 | |||
| ae0373643c | |||
| 7aeabddd2f | |||
| 9df8f5ecc0 | |||
| c4fad2883b | |||
| 9cfcd78c87 | |||
| 4751627f1c | |||
| ae59c6b6d2 | |||
| 4973d7a62d | |||
| ed6a1de311 | |||
| ab234be025 | |||
| ee75e6c0e9 | |||
| c2b390fe63 | |||
| 56d5d7f761 | |||
| 0b89bc920e | |||
| 0dac13e4db | |||
| 0c2e91f28a | |||
| 13e7bee0e6 | |||
| 65104aca9c | |||
| 9360094ba7 | |||
| 3700779bfa | |||
| d9e894911f | |||
| 85e3ddc2b8 | |||
| ccae35d92a | |||
| 61ca928325 | |||
| a93f2ebff0 | |||
| a45f1ae915 | |||
| 9641978481 | |||
| ffd2017c6f | |||
| b7eb42aa6b | |||
| 750f8ba299 | |||
| 49cdef074d | |||
| aa86b04714 | |||
| c887a0b472 | |||
| 34936be574 | |||
| e354dd0c7f | |||
| bc221abb04 | |||
| ab5e8780ab | |||
| 0c34e06e51 | |||
| 4a0c4e0c25 |
+1
-1
@@ -5,7 +5,7 @@ environment:
|
||||
|
||||
install:
|
||||
# Install rust, x86_64-pc-windows-msvc host
|
||||
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %APPVEYOR_RUST_CHANNEL%
|
||||
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
|
||||
- rustc -vV
|
||||
|
||||
+2
-5
@@ -1,5 +1,2 @@
|
||||
fn_args_layout = "Block"
|
||||
array_layout = "Block"
|
||||
where_style = "Rfc"
|
||||
generics_indent = "Block"
|
||||
fn_call_style = "Block"
|
||||
error_on_line_overflow = false
|
||||
same_line_attributes = false
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.23" # remember to update html_root_url
|
||||
version = "1.0.35" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
|
||||
@@ -10,7 +10,7 @@ use lib::*;
|
||||
|
||||
macro_rules! int_to_int {
|
||||
($dst:ident, $n:ident) => (
|
||||
if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 {
|
||||
if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
None
|
||||
@@ -20,7 +20,7 @@ macro_rules! int_to_int {
|
||||
|
||||
macro_rules! int_to_uint {
|
||||
($dst:ident, $n:ident) => (
|
||||
if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
|
||||
if 0 <= $n && $n as u64 <= $dst::max_value() as u64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
None
|
||||
@@ -30,7 +30,7 @@ macro_rules! int_to_uint {
|
||||
|
||||
macro_rules! uint_to {
|
||||
($dst:ident, $n:ident) => (
|
||||
if $n as u64 <= $dst::MAX as u64 {
|
||||
if $n as u64 <= $dst::max_value() as u64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
use lib::*;
|
||||
|
||||
use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
|
||||
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
||||
|
||||
/// An efficient way of discarding data from a deserializer.
|
||||
///
|
||||
|
||||
+333
-83
@@ -15,6 +15,7 @@ use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, Va
|
||||
use de::MapAccess;
|
||||
|
||||
use de::from_primitive::FromPrimitive;
|
||||
use private::de::InPlaceSeed;
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use private::de::size_hint;
|
||||
@@ -210,6 +211,8 @@ impl<'de> Deserialize<'de> for char {
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
struct StringVisitor;
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
struct StringInPlaceVisitor<'a>(&'a mut String);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de> Visitor<'de> for StringVisitor {
|
||||
@@ -249,7 +252,66 @@ impl<'de> Visitor<'de> for StringVisitor {
|
||||
{
|
||||
match String::from_utf8(v) {
|
||||
Ok(s) => Ok(s),
|
||||
Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self),),
|
||||
Err(e) => Err(Error::invalid_value(
|
||||
Unexpected::Bytes(&e.into_bytes()),
|
||||
&self,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
|
||||
type Value = ();
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<(), E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
self.0.clear();
|
||||
self.0.push_str(v);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<(), E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
*self.0 = v;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<(), E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match str::from_utf8(v) {
|
||||
Ok(s) => {
|
||||
self.0.clear();
|
||||
self.0.push_str(s);
|
||||
Ok(())
|
||||
}
|
||||
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<(), E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match String::from_utf8(v) {
|
||||
Ok(s) => {
|
||||
*self.0 = s;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(Error::invalid_value(
|
||||
Unexpected::Bytes(&e.into_bytes()),
|
||||
&self,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,6 +324,13 @@ impl<'de> Deserialize<'de> for String {
|
||||
{
|
||||
deserializer.deserialize_string(StringVisitor)
|
||||
}
|
||||
|
||||
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_string(StringInPlaceVisitor(place))
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -465,17 +534,25 @@ where
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_option(OptionVisitor { marker: PhantomData })
|
||||
deserializer.deserialize_option(OptionVisitor {
|
||||
marker: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
// The Some variant's repr is opaque, so we can't play cute tricks with its
|
||||
// tag to have deserialize_in_place build the content in place unconditionally.
|
||||
//
|
||||
// FIXME: investigate whether branching on the old value being Some to
|
||||
// deserialize_in_place the value is profitable (probably data-dependent?)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct PhantomDataVisitor<T> {
|
||||
struct PhantomDataVisitor<T: ?Sized> {
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'de, T> Visitor<'de> for PhantomDataVisitor<T> {
|
||||
impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
|
||||
type Value = PhantomData<T>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
@@ -491,12 +568,14 @@ impl<'de, T> Visitor<'de> for PhantomDataVisitor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T> Deserialize<'de> for PhantomData<T> {
|
||||
impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let visitor = PhantomDataVisitor { marker: PhantomData };
|
||||
let visitor = PhantomDataVisitor {
|
||||
marker: PhantomData,
|
||||
};
|
||||
deserializer.deserialize_unit_struct("PhantomData", visitor)
|
||||
}
|
||||
}
|
||||
@@ -509,7 +588,9 @@ macro_rules! seq_impl {
|
||||
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
|
||||
$access:ident,
|
||||
$ctor:expr,
|
||||
$clear:expr,
|
||||
$with_capacity:expr,
|
||||
$reserve:expr,
|
||||
$insert:expr
|
||||
) => {
|
||||
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
|
||||
@@ -554,16 +635,59 @@ macro_rules! seq_impl {
|
||||
let visitor = SeqVisitor { marker: PhantomData };
|
||||
deserializer.deserialize_seq(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct SeqInPlaceVisitor<'a, T: 'a $(, $typaram: 'a)*>(&'a mut $ty<T $(, $typaram)*>);
|
||||
|
||||
impl<'a, 'de, T $(, $typaram)*> Visitor<'de> for SeqInPlaceVisitor<'a, T $(, $typaram)*>
|
||||
where
|
||||
T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*,
|
||||
$($typaram: $bound1 $(+ $bound2)*,)*
|
||||
{
|
||||
type Value = ();
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a sequence")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<A>(mut self, mut $access: A) -> Result<(), A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
$clear(&mut self.0);
|
||||
$reserve(&mut self.0, size_hint::cautious($access.size_hint()));
|
||||
|
||||
// FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList)
|
||||
while let Some(value) = try!($access.next_element()) {
|
||||
$insert(&mut self.0, value);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(SeqInPlaceVisitor(place))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dummy impl of reserve
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
fn nop_reserve<T>(_seq: T, _n: usize) {}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(
|
||||
BinaryHeap<T: Ord>,
|
||||
seq,
|
||||
BinaryHeap::new(),
|
||||
BinaryHeap::clear,
|
||||
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
|
||||
BinaryHeap::reserve,
|
||||
BinaryHeap::push);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
@@ -571,7 +695,9 @@ seq_impl!(
|
||||
BTreeSet<T: Eq + Ord>,
|
||||
seq,
|
||||
BTreeSet::new(),
|
||||
BTreeSet::clear,
|
||||
BTreeSet::new(),
|
||||
nop_reserve,
|
||||
BTreeSet::insert);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
@@ -579,15 +705,20 @@ seq_impl!(
|
||||
LinkedList<T>,
|
||||
seq,
|
||||
LinkedList::new(),
|
||||
LinkedList::clear,
|
||||
LinkedList::new(),
|
||||
LinkedList::push_back);
|
||||
nop_reserve,
|
||||
LinkedList::push_back
|
||||
);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
seq_impl!(
|
||||
HashSet<T: Eq + Hash, S: BuildHasher + Default>,
|
||||
seq,
|
||||
HashSet::with_hasher(S::default()),
|
||||
HashSet::clear,
|
||||
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
|
||||
HashSet::reserve,
|
||||
HashSet::insert);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
@@ -595,26 +726,35 @@ seq_impl!(
|
||||
Vec<T>,
|
||||
seq,
|
||||
Vec::new(),
|
||||
Vec::clear,
|
||||
Vec::with_capacity(size_hint::cautious(seq.size_hint())),
|
||||
Vec::push);
|
||||
Vec::reserve,
|
||||
Vec::push
|
||||
);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
seq_impl!(
|
||||
VecDeque<T>,
|
||||
seq,
|
||||
VecDeque::new(),
|
||||
VecDeque::clear,
|
||||
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
|
||||
VecDeque::push_back);
|
||||
VecDeque::reserve,
|
||||
VecDeque::push_back
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ArrayVisitor<A> {
|
||||
marker: PhantomData<A>,
|
||||
}
|
||||
struct ArrayInPlaceVisitor<'a, A: 'a>(&'a mut A);
|
||||
|
||||
impl<A> ArrayVisitor<A> {
|
||||
fn new() -> Self {
|
||||
ArrayVisitor { marker: PhantomData }
|
||||
ArrayVisitor {
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,6 +813,35 @@ macro_rules! array_impls {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'de, T> Visitor<'de> for ArrayInPlaceVisitor<'a, [T; $len]>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
type Value = ();
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(concat!("an array of length ", $len))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut fail_idx = None;
|
||||
for (idx, dest) in self.0[..].iter_mut().enumerate() {
|
||||
if try!(seq.next_element_seed(InPlaceSeed(dest))).is_none() {
|
||||
fail_idx = Some(idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(idx) = fail_idx {
|
||||
return Err(Error::invalid_length(idx, &self));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, T> Deserialize<'de> for [T; $len]
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
@@ -683,6 +852,13 @@ macro_rules! array_impls {
|
||||
{
|
||||
deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new())
|
||||
}
|
||||
|
||||
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_tuple($len, ArrayInPlaceVisitor(place))
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
@@ -726,49 +902,76 @@ array_impls! {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! tuple_impls {
|
||||
($($len:tt $visitor:ident => ($($n:tt $name:ident)+))+) => {
|
||||
($($len:tt => ($($n:tt $name:ident)+))+) => {
|
||||
$(
|
||||
struct $visitor<$($name,)+> {
|
||||
marker: PhantomData<($($name,)+)>,
|
||||
}
|
||||
|
||||
impl<$($name,)+> $visitor<$($name,)+> {
|
||||
fn new() -> Self {
|
||||
$visitor { marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for $visitor<$($name,)+> {
|
||||
type Value = ($($name,)+);
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(concat!("a tuple of size ", $len))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
$(
|
||||
let $name = match try!(seq.next_element()) {
|
||||
Some(value) => value,
|
||||
None => return Err(Error::invalid_length($n, &self)),
|
||||
};
|
||||
)+
|
||||
|
||||
Ok(($($name,)+))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_tuple($len, $visitor::new())
|
||||
struct TupleVisitor<$($name,)+> {
|
||||
marker: PhantomData<($($name,)+)>,
|
||||
}
|
||||
|
||||
impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> {
|
||||
type Value = ($($name,)+);
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(concat!("a tuple of size ", $len))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
$(
|
||||
let $name = match try!(seq.next_element()) {
|
||||
Some(value) => value,
|
||||
None => return Err(Error::invalid_length($n, &self)),
|
||||
};
|
||||
)+
|
||||
|
||||
Ok(($($name,)+))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct TupleInPlaceVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+));
|
||||
|
||||
impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleInPlaceVisitor<'a, $($name,)+> {
|
||||
type Value = ();
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(concat!("a tuple of size ", $len))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
$(
|
||||
if try!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() {
|
||||
return Err(Error::invalid_length($n, &self));
|
||||
}
|
||||
)+
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place))
|
||||
}
|
||||
}
|
||||
)+
|
||||
@@ -776,22 +979,22 @@ macro_rules! tuple_impls {
|
||||
}
|
||||
|
||||
tuple_impls! {
|
||||
1 TupleVisitor1 => (0 T0)
|
||||
2 TupleVisitor2 => (0 T0 1 T1)
|
||||
3 TupleVisitor3 => (0 T0 1 T1 2 T2)
|
||||
4 TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3)
|
||||
5 TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
|
||||
6 TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
|
||||
7 TupleVisitor7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
|
||||
8 TupleVisitor8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
|
||||
9 TupleVisitor9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
|
||||
10 TupleVisitor10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
|
||||
11 TupleVisitor11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
|
||||
12 TupleVisitor12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
|
||||
13 TupleVisitor13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
|
||||
14 TupleVisitor14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
|
||||
15 TupleVisitor15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
|
||||
16 TupleVisitor16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
|
||||
1 => (0 T0)
|
||||
2 => (0 T0 1 T1)
|
||||
3 => (0 T0 1 T1 2 T2)
|
||||
4 => (0 T0 1 T1 2 T2 3 T3)
|
||||
5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
|
||||
6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
|
||||
7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
|
||||
8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
|
||||
9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
|
||||
10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
|
||||
11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
|
||||
12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
|
||||
13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
|
||||
14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
|
||||
15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
|
||||
16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1068,7 +1271,12 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
|
||||
parse_socket_impl!(net::SocketAddrV4, net::SocketAddrV4::new);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(ip, port, 0, 0));
|
||||
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(
|
||||
ip,
|
||||
port,
|
||||
0,
|
||||
0
|
||||
));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1179,7 +1387,9 @@ impl<'de> Visitor<'de> for OsStringVisitor {
|
||||
|
||||
match try!(data.variant()) {
|
||||
(OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec),
|
||||
(OsStringKind::Windows, _) => Err(Error::custom("cannot deserialize Windows OS string on Unix",),),
|
||||
(OsStringKind::Windows, _) => Err(Error::custom(
|
||||
"cannot deserialize Windows OS string on Unix",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1191,11 +1401,11 @@ impl<'de> Visitor<'de> for OsStringVisitor {
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
|
||||
match try!(data.variant()) {
|
||||
(OsStringKind::Windows, v) => {
|
||||
v.newtype_variant::<Vec<u16>>()
|
||||
.map(|vec| OsString::from_wide(&vec))
|
||||
}
|
||||
(OsStringKind::Unix, _) => Err(Error::custom("cannot deserialize Unix OS string on Windows",),),
|
||||
(OsStringKind::Windows, v) => v.newtype_variant::<Vec<u16>>()
|
||||
.map(|vec| OsString::from_wide(&vec)),
|
||||
(OsStringKind::Unix, _) => Err(Error::custom(
|
||||
"cannot deserialize Unix OS string on Windows",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1521,13 +1731,17 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
match key {
|
||||
Field::Secs => {
|
||||
if secs.is_some() {
|
||||
return Err(<A::Error as Error>::duplicate_field("secs_since_epoch"));
|
||||
return Err(<A::Error as Error>::duplicate_field(
|
||||
"secs_since_epoch",
|
||||
));
|
||||
}
|
||||
secs = Some(try!(map.next_value()));
|
||||
}
|
||||
Field::Nanos => {
|
||||
if nanos.is_some() {
|
||||
return Err(<A::Error as Error>::duplicate_field("nanos_since_epoch"));
|
||||
return Err(<A::Error as Error>::duplicate_field(
|
||||
"nanos_since_epoch",
|
||||
));
|
||||
}
|
||||
nanos = Some(try!(map.next_value()));
|
||||
}
|
||||
@@ -1691,13 +1905,20 @@ where
|
||||
}
|
||||
|
||||
const FIELDS: &'static [&'static str] = &["start", "end"];
|
||||
deserializer.deserialize_struct("Range", FIELDS, RangeVisitor { phantom: PhantomData })
|
||||
deserializer.deserialize_struct(
|
||||
"Range",
|
||||
FIELDS,
|
||||
RangeVisitor {
|
||||
phantom: PhantomData,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[allow(deprecated)]
|
||||
impl<'de, T> Deserialize<'de> for NonZero<T>
|
||||
where
|
||||
T: Deserialize<'de> + Zeroable,
|
||||
@@ -1714,6 +1935,36 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! nonzero_integers {
|
||||
( $( $T: ty, )+ ) => {
|
||||
$(
|
||||
#[cfg(feature = "unstable")]
|
||||
impl<'de> Deserialize<'de> for $T {
|
||||
fn deserialize<D>(deserializer: D) -> Result<$T, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value = try!(Deserialize::deserialize(deserializer));
|
||||
match <$T>::new(value) {
|
||||
Some(nonzero) => Ok(nonzero),
|
||||
None => Err(Error::custom("expected a non-zero value")),
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
nonzero_integers! {
|
||||
// Not including signed NonZeroI* since they might be removed
|
||||
NonZeroU8,
|
||||
NonZeroU16,
|
||||
NonZeroU32,
|
||||
NonZeroU64,
|
||||
// FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
|
||||
NonZeroUsize,
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<'de, T, E> Deserialize<'de> for Result<T, E>
|
||||
@@ -1756,9 +2007,10 @@ where
|
||||
match value {
|
||||
0 => Ok(Field::Ok),
|
||||
1 => Ok(Field::Err),
|
||||
_ => {
|
||||
Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),)
|
||||
}
|
||||
_ => Err(Error::invalid_value(
|
||||
Unexpected::Unsigned(value as u64),
|
||||
&self,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1780,14 +2032,12 @@ where
|
||||
match value {
|
||||
b"Ok" => Ok(Field::Ok),
|
||||
b"Err" => Ok(Field::Err),
|
||||
_ => {
|
||||
match str::from_utf8(value) {
|
||||
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
|
||||
Err(_) => {
|
||||
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
|
||||
}
|
||||
_ => match str::from_utf8(value) {
|
||||
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
|
||||
Err(_) => {
|
||||
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1831,7 +2081,7 @@ where
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de, T> Deserialize<'de> for Wrapping<T>
|
||||
where
|
||||
T: Deserialize<'de>
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error>
|
||||
where
|
||||
|
||||
+34
-2
@@ -98,7 +98,8 @@
|
||||
//! - Path
|
||||
//! - PathBuf
|
||||
//! - Range\<T\>
|
||||
//! - NonZero\<T\> (unstable)
|
||||
//! - NonZero\<T\> (unstable, deprecated)
|
||||
//! - num::NonZero* (unstable)
|
||||
//! - **Net types**:
|
||||
//! - IpAddr
|
||||
//! - Ipv4Addr
|
||||
@@ -504,6 +505,35 @@ pub trait Deserialize<'de>: Sized {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>;
|
||||
|
||||
/// Deserializes a value into `self` from the given Deserializer.
|
||||
///
|
||||
/// The purpose of this method is to allow the deserializer to reuse
|
||||
/// resources and avoid copies. As such, if this method returns an error,
|
||||
/// `self` will be in an indeterminate state where some parts of the struct
|
||||
/// have been overwritten. Although whatever state that is will be
|
||||
/// memory-safe.
|
||||
///
|
||||
/// This is generally useful when repeatedly deserializing values that
|
||||
/// are processed one at a time, where the value of `self` doesn't matter
|
||||
/// when the next deserialization occurs.
|
||||
///
|
||||
/// If you manually implement this, your recursive deserializations should
|
||||
/// use `deserialize_in_place`.
|
||||
///
|
||||
/// This method is stable and an official public API, but hidden from the
|
||||
/// documentation because it is almost never what newbies are looking for.
|
||||
/// Showing it in rustdoc would cause it to be featured more prominently
|
||||
/// than it deserves.
|
||||
#[doc(hidden)]
|
||||
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
// Default implementation just delegates to `deserialize` impl.
|
||||
*place = Deserialize::deserialize(deserializer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A data structure that can be deserialized without borrowing any data from
|
||||
@@ -1078,7 +1108,9 @@ pub trait Deserializer<'de>: Sized {
|
||||
/// change, as a value serialized in human-readable mode is not required to
|
||||
/// deserialize from the same data in compact mode.
|
||||
#[inline]
|
||||
fn is_human_readable(&self) -> bool { true }
|
||||
fn is_human_readable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+34
-14
@@ -37,7 +37,7 @@
|
||||
|
||||
use lib::*;
|
||||
|
||||
use de::{self, IntoDeserializer, Expected, SeqAccess};
|
||||
use de::{self, Expected, IntoDeserializer, SeqAccess};
|
||||
use private::de::size_hint;
|
||||
use ser;
|
||||
use self::private::{First, Second};
|
||||
@@ -62,7 +62,9 @@ impl de::Error for Error {
|
||||
where
|
||||
T: Display,
|
||||
{
|
||||
Error { err: msg.to_string().into_boxed_str() }
|
||||
Error {
|
||||
err: msg.to_string().into_boxed_str(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
@@ -112,7 +114,9 @@ where
|
||||
type Deserializer = UnitDeserializer<E>;
|
||||
|
||||
fn into_deserializer(self) -> UnitDeserializer<E> {
|
||||
UnitDeserializer { marker: PhantomData }
|
||||
UnitDeserializer {
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,7 +662,10 @@ where
|
||||
} else {
|
||||
// First argument is the number of elements in the data, second
|
||||
// argument is the number of elements expected by the Deserialize.
|
||||
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInSeq(self.count)),)
|
||||
Err(de::Error::invalid_length(
|
||||
self.count + remaining,
|
||||
&ExpectedInSeq(self.count),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -852,7 +859,10 @@ where
|
||||
} else {
|
||||
// First argument is the number of elements in the data, second
|
||||
// argument is the number of elements expected by the Deserialize.
|
||||
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count)),)
|
||||
Err(de::Error::invalid_length(
|
||||
self.count + remaining,
|
||||
&ExpectedInMap(self.count),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -901,11 +911,7 @@ where
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn deserialize_tuple<V>(
|
||||
self,
|
||||
len: usize,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
@@ -1223,7 +1229,12 @@ mod private {
|
||||
}
|
||||
|
||||
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
|
||||
(t, UnitOnly { marker: PhantomData })
|
||||
(
|
||||
t,
|
||||
UnitOnly {
|
||||
marker: PhantomData,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
impl<'de, E> de::VariantAccess<'de> for UnitOnly<E>
|
||||
@@ -1240,14 +1251,20 @@ mod private {
|
||||
where
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"),)
|
||||
Err(de::Error::invalid_type(
|
||||
Unexpected::UnitVariant,
|
||||
&"newtype variant",
|
||||
))
|
||||
}
|
||||
|
||||
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"),)
|
||||
Err(de::Error::invalid_type(
|
||||
Unexpected::UnitVariant,
|
||||
&"tuple variant",
|
||||
))
|
||||
}
|
||||
|
||||
fn struct_variant<V>(
|
||||
@@ -1258,7 +1275,10 @@ mod private {
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"),)
|
||||
Err(de::Error::invalid_type(
|
||||
Unexpected::UnitVariant,
|
||||
&"struct variant",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ pub use lib::default::Default;
|
||||
pub use lib::fmt::{self, Formatter};
|
||||
pub use lib::marker::PhantomData;
|
||||
pub use lib::option::Option::{self, None, Some};
|
||||
pub use lib::result::Result::{self, Ok, Err};
|
||||
pub use lib::result::Result::{self, Err, Ok};
|
||||
|
||||
pub use self::string::from_utf8_lossy;
|
||||
|
||||
|
||||
+18
-21
@@ -79,30 +79,21 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.23")]
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.35")]
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
// Unstable functionality only if the user asks for it. For tracking and
|
||||
// discussion of these features please refer to this issue:
|
||||
//
|
||||
// https://github.com/serde-rs/serde/issues/812
|
||||
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
|
||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// Whitelisted clippy lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||
cast_lossless,
|
||||
const_static_lifetime,
|
||||
doc_markdown,
|
||||
linkedlist,
|
||||
needless_pass_by_value,
|
||||
type_complexity,
|
||||
unreadable_literal,
|
||||
zero_prefixed_literal,
|
||||
))]
|
||||
#![cfg_attr(feature = "cargo-clippy",
|
||||
allow(cast_lossless, const_static_lifetime, doc_markdown, linkedlist,
|
||||
needless_pass_by_value, redundant_field_names, type_complexity,
|
||||
unreadable_literal, zero_prefixed_literal))]
|
||||
// Whitelisted clippy_pedantic lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||
// integer and float ser/de requires these sorts of casts
|
||||
@@ -113,6 +104,7 @@
|
||||
// simplifies some macros
|
||||
invalid_upcast_comparisons,
|
||||
// things are often more readable this way
|
||||
decimal_literal_representation,
|
||||
option_unwrap_used,
|
||||
result_unwrap_used,
|
||||
shadow_reuse,
|
||||
@@ -120,12 +112,13 @@
|
||||
stutter,
|
||||
use_self,
|
||||
// not practical
|
||||
many_single_char_names,
|
||||
missing_docs_in_private_items,
|
||||
similar_names,
|
||||
// alternative is not stable
|
||||
empty_enum,
|
||||
use_debug,
|
||||
))]
|
||||
|
||||
// Blacklisted Rust lints.
|
||||
#![deny(missing_docs, unused_imports)]
|
||||
|
||||
@@ -149,8 +142,8 @@ mod lib {
|
||||
}
|
||||
|
||||
pub use self::core::{cmp, iter, mem, ops, slice, str};
|
||||
pub use self::core::{i8, i16, i32, i64, isize};
|
||||
pub use self::core::{u8, u16, u32, u64, usize};
|
||||
pub use self::core::{isize, i16, i32, i64, i8};
|
||||
pub use self::core::{usize, u16, u32, u64, u8};
|
||||
pub use self::core::{f32, f64};
|
||||
|
||||
pub use self::core::cell::{Cell, RefCell};
|
||||
@@ -193,9 +186,9 @@ mod lib {
|
||||
pub use alloc::arc::Arc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
|
||||
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
|
||||
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::{error, net};
|
||||
@@ -203,9 +196,9 @@ mod lib {
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::collections::{HashMap, HashSet};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::ffi::{CString, CStr, OsString, OsStr};
|
||||
pub use std::ffi::{CStr, CString, OsStr, OsString};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::hash::{Hash, BuildHasher};
|
||||
pub use std::hash::{BuildHasher, Hash};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::io::Write;
|
||||
#[cfg(feature = "std")]
|
||||
@@ -218,7 +211,11 @@ mod lib {
|
||||
pub use std::sync::{Mutex, RwLock};
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[allow(deprecated)]
|
||||
pub use core::nonzero::{NonZero, Zeroable};
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+335
-106
@@ -8,16 +8,16 @@
|
||||
|
||||
use lib::*;
|
||||
|
||||
use de::{Deserialize, Deserializer, IntoDeserializer, Error, Visitor};
|
||||
use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use de::Unexpected;
|
||||
use de::{Unexpected, MapAccess};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub use self::content::{Content, ContentRefDeserializer, ContentDeserializer,
|
||||
TaggedContentVisitor, TagOrContentField, TagOrContentFieldVisitor,
|
||||
TagContentOtherField, TagContentOtherFieldVisitor,
|
||||
InternallyTaggedUnitVisitor, UntaggedUnitVisitor};
|
||||
pub use self::content::{Content, ContentDeserializer, ContentRefDeserializer,
|
||||
InternallyTaggedUnitVisitor, TagContentOtherField,
|
||||
TagContentOtherFieldVisitor, TagOrContentField, TagOrContentFieldVisitor,
|
||||
TaggedContentVisitor, UntaggedUnitVisitor, EnumDeserializer};
|
||||
|
||||
/// If the missing field is of type `Option<T>` then treat is as `None`,
|
||||
/// otherwise it is an error.
|
||||
@@ -120,7 +120,10 @@ where
|
||||
{
|
||||
match String::from_utf8(v) {
|
||||
Ok(s) => Ok(Cow::Owned(s)),
|
||||
Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self),),
|
||||
Err(e) => Err(Error::invalid_value(
|
||||
Unexpected::Bytes(&e.into_bytes()),
|
||||
&self,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,7 +188,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(CowBytesVisitor)
|
||||
deserializer.deserialize_bytes(CowBytesVisitor)
|
||||
}
|
||||
|
||||
pub mod size_hint {
|
||||
@@ -198,6 +201,7 @@ pub mod size_hint {
|
||||
helper(iter.size_hint())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cautious(hint: Option<usize>) -> usize {
|
||||
cmp::min(hint.unwrap_or(0), 4096)
|
||||
}
|
||||
@@ -224,8 +228,8 @@ mod content {
|
||||
|
||||
use lib::*;
|
||||
|
||||
use de::{self, Deserialize, DeserializeSeed, Deserializer, Visitor, SeqAccess, MapAccess,
|
||||
EnumAccess, Unexpected};
|
||||
use de::{self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, MapAccess, SeqAccess,
|
||||
Unexpected, Visitor};
|
||||
use super::size_hint;
|
||||
|
||||
/// Used from generated code to buffer the contents of the Deserializer when
|
||||
@@ -265,6 +269,14 @@ mod content {
|
||||
}
|
||||
|
||||
impl<'de> Content<'de> {
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
match *self {
|
||||
Content::Str(x) => Some(x),
|
||||
Content::String(ref x) => Some(x),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn unexpected(&self) -> Unexpected {
|
||||
match *self {
|
||||
Content::Bool(b) => Unexpected::Bool(b),
|
||||
@@ -501,7 +513,9 @@ mod content {
|
||||
where
|
||||
V: EnumAccess<'de>,
|
||||
{
|
||||
Err(de::Error::custom("untagged and internally tagged enums do not support enum input",),)
|
||||
Err(de::Error::custom(
|
||||
"untagged and internally tagged enums do not support enum input",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,7 +534,10 @@ mod content {
|
||||
|
||||
impl<'de> TagOrContentVisitor<'de> {
|
||||
fn new(name: &'static str) -> Self {
|
||||
TagOrContentVisitor { name: name, value: PhantomData }
|
||||
TagOrContentVisitor {
|
||||
name: name,
|
||||
value: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,7 +574,9 @@ mod content {
|
||||
where
|
||||
F: de::Error,
|
||||
{
|
||||
ContentVisitor::new().visit_i8(value).map(TagOrContent::Content)
|
||||
ContentVisitor::new()
|
||||
.visit_i8(value)
|
||||
.map(TagOrContent::Content)
|
||||
}
|
||||
|
||||
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
|
||||
@@ -591,7 +610,9 @@ mod content {
|
||||
where
|
||||
F: de::Error,
|
||||
{
|
||||
ContentVisitor::new().visit_u8(value).map(TagOrContent::Content)
|
||||
ContentVisitor::new()
|
||||
.visit_u8(value)
|
||||
.map(TagOrContent::Content)
|
||||
}
|
||||
|
||||
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
|
||||
@@ -730,14 +751,18 @@ mod content {
|
||||
where
|
||||
F: de::Error,
|
||||
{
|
||||
ContentVisitor::new().visit_unit().map(TagOrContent::Content)
|
||||
ContentVisitor::new()
|
||||
.visit_unit()
|
||||
.map(TagOrContent::Content)
|
||||
}
|
||||
|
||||
fn visit_none<F>(self) -> Result<Self::Value, F>
|
||||
where
|
||||
F: de::Error,
|
||||
{
|
||||
ContentVisitor::new().visit_none().map(TagOrContent::Content)
|
||||
ContentVisitor::new()
|
||||
.visit_none()
|
||||
.map(TagOrContent::Content)
|
||||
}
|
||||
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
@@ -860,8 +885,7 @@ mod content {
|
||||
{
|
||||
let mut tag = None;
|
||||
let mut vec = Vec::with_capacity(size_hint::cautious(map.size_hint()));
|
||||
while let Some(k) =
|
||||
try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
|
||||
while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
|
||||
match k {
|
||||
TagOrContent::Tag => {
|
||||
if tag.is_some() {
|
||||
@@ -877,14 +901,10 @@ mod content {
|
||||
}
|
||||
match tag {
|
||||
None => Err(de::Error::missing_field(self.tag_name)),
|
||||
Some(tag) => {
|
||||
Ok(
|
||||
TaggedContent {
|
||||
tag: tag,
|
||||
content: Content::Map(vec),
|
||||
},
|
||||
)
|
||||
}
|
||||
Some(tag) => Ok(TaggedContent {
|
||||
tag: tag,
|
||||
content: Content::Map(vec),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -966,7 +986,11 @@ mod content {
|
||||
type Value = TagContentOtherField;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "{:?}, {:?}, or other ignored fields", self.tag, self.content)
|
||||
write!(
|
||||
formatter,
|
||||
"{:?}, {:?}, or other ignored fields",
|
||||
self.tag, self.content
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, field: &str) -> Result<Self::Value, E>
|
||||
@@ -1030,10 +1054,8 @@ mod content {
|
||||
Ok(value)
|
||||
}
|
||||
Content::Map(v) => {
|
||||
let map = v.into_iter().map(|(k, v)| {
|
||||
(ContentDeserializer::new(k),
|
||||
ContentDeserializer::new(v))
|
||||
});
|
||||
let map = v.into_iter()
|
||||
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
|
||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||
try!(map_visitor.end());
|
||||
@@ -1080,44 +1102,37 @@ mod content {
|
||||
let (variant, value) = match iter.next() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return Err(
|
||||
de::Error::invalid_value(
|
||||
de::Unexpected::Map,
|
||||
&"map with a single key",
|
||||
),
|
||||
);
|
||||
return Err(de::Error::invalid_value(
|
||||
de::Unexpected::Map,
|
||||
&"map with a single key",
|
||||
));
|
||||
}
|
||||
};
|
||||
// enums are encoded in json as maps with a single key:value pair
|
||||
if iter.next().is_some() {
|
||||
return Err(
|
||||
de::Error::invalid_value(
|
||||
de::Unexpected::Map,
|
||||
&"map with a single key",
|
||||
),
|
||||
);
|
||||
return Err(de::Error::invalid_value(
|
||||
de::Unexpected::Map,
|
||||
&"map with a single key",
|
||||
));
|
||||
}
|
||||
(variant, Some(value))
|
||||
}
|
||||
s @ Content::String(_) | s @ Content::Str(_) => (s, None),
|
||||
other => {
|
||||
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),);
|
||||
return Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
&"string or map",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
visitor.visit_enum(
|
||||
EnumDeserializer {
|
||||
variant: variant,
|
||||
value: value,
|
||||
err: PhantomData,
|
||||
},
|
||||
)
|
||||
visitor.visit_enum(EnumDeserializer::new(variant, value))
|
||||
}
|
||||
|
||||
fn deserialize_unit_struct<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
visitor: V
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
@@ -1159,7 +1174,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct EnumDeserializer<'de, E>
|
||||
pub struct EnumDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
@@ -1168,6 +1183,18 @@ mod content {
|
||||
err: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'de, E> EnumDeserializer<'de, E>
|
||||
where E: de::Error
|
||||
{
|
||||
pub fn new(variant: Content<'de>, value: Option<Content<'de>>) -> EnumDeserializer<'de, E> {
|
||||
EnumDeserializer {
|
||||
variant: variant,
|
||||
value: value,
|
||||
err: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
@@ -1188,7 +1215,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct VariantDeserializer<'de, E>
|
||||
pub struct VariantDeserializer<'de, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
@@ -1215,9 +1242,10 @@ mod content {
|
||||
{
|
||||
match self.value {
|
||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
|
||||
None => {
|
||||
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"),)
|
||||
}
|
||||
None => Err(de::Error::invalid_type(
|
||||
de::Unexpected::UnitVariant,
|
||||
&"newtype variant",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1229,8 +1257,14 @@ mod content {
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant"),),
|
||||
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"),),
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
&"tuple variant",
|
||||
)),
|
||||
None => Err(de::Error::invalid_type(
|
||||
de::Unexpected::UnitVariant,
|
||||
&"tuple variant",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1249,8 +1283,14 @@ mod content {
|
||||
Some(Content::Seq(v)) => {
|
||||
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),),
|
||||
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
&"struct variant",
|
||||
)),
|
||||
_ => Err(de::Error::invalid_type(
|
||||
de::Unexpected::UnitVariant,
|
||||
&"struct variant",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1318,10 +1358,7 @@ mod content {
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(value) => {
|
||||
seed.deserialize(ContentDeserializer::new(value))
|
||||
.map(Some)
|
||||
}
|
||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
@@ -1457,12 +1494,12 @@ mod content {
|
||||
Ok(value)
|
||||
}
|
||||
Content::Map(ref v) => {
|
||||
let map = v.into_iter()
|
||||
.map(
|
||||
|&(ref k, ref v)| {
|
||||
(ContentRefDeserializer::new(k), ContentRefDeserializer::new(v))
|
||||
},
|
||||
);
|
||||
let map = v.into_iter().map(|&(ref k, ref v)| {
|
||||
(
|
||||
ContentRefDeserializer::new(k),
|
||||
ContentRefDeserializer::new(v),
|
||||
)
|
||||
});
|
||||
let mut map_visitor = de::value::MapDeserializer::new(map);
|
||||
let value = try!(visitor.visit_map(&mut map_visitor));
|
||||
try!(map_visitor.end());
|
||||
@@ -1505,38 +1542,35 @@ mod content {
|
||||
let &(ref variant, ref value) = match iter.next() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
return Err(
|
||||
de::Error::invalid_value(
|
||||
de::Unexpected::Map,
|
||||
&"map with a single key",
|
||||
),
|
||||
);
|
||||
return Err(de::Error::invalid_value(
|
||||
de::Unexpected::Map,
|
||||
&"map with a single key",
|
||||
));
|
||||
}
|
||||
};
|
||||
// enums are encoded in json as maps with a single key:value pair
|
||||
if iter.next().is_some() {
|
||||
return Err(
|
||||
de::Error::invalid_value(
|
||||
de::Unexpected::Map,
|
||||
&"map with a single key",
|
||||
),
|
||||
);
|
||||
return Err(de::Error::invalid_value(
|
||||
de::Unexpected::Map,
|
||||
&"map with a single key",
|
||||
));
|
||||
}
|
||||
(variant, Some(value))
|
||||
}
|
||||
ref s @ Content::String(_) | ref s @ Content::Str(_) => (s, None),
|
||||
ref other => {
|
||||
return Err(de::Error::invalid_type(other.unexpected(), &"string or map"),);
|
||||
return Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
&"string or map",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
visitor.visit_enum(
|
||||
EnumRefDeserializer {
|
||||
variant: variant,
|
||||
value: value,
|
||||
err: PhantomData,
|
||||
},
|
||||
)
|
||||
visitor.visit_enum(EnumRefDeserializer {
|
||||
variant: variant,
|
||||
value: value,
|
||||
err: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
@@ -1612,9 +1646,10 @@ mod content {
|
||||
{
|
||||
match self.value {
|
||||
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
|
||||
None => {
|
||||
Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"newtype variant"),)
|
||||
}
|
||||
None => Err(de::Error::invalid_type(
|
||||
de::Unexpected::UnitVariant,
|
||||
&"newtype variant",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1626,8 +1661,14 @@ mod content {
|
||||
Some(&Content::Seq(ref v)) => {
|
||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"tuple variant"),),
|
||||
None => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"tuple variant"),),
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
&"tuple variant",
|
||||
)),
|
||||
None => Err(de::Error::invalid_type(
|
||||
de::Unexpected::UnitVariant,
|
||||
&"tuple variant",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1646,8 +1687,14 @@ mod content {
|
||||
Some(&Content::Seq(ref v)) => {
|
||||
de::Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor)
|
||||
}
|
||||
Some(other) => Err(de::Error::invalid_type(other.unexpected(), &"struct variant"),),
|
||||
_ => Err(de::Error::invalid_type(de::Unexpected::UnitVariant, &"struct variant"),),
|
||||
Some(other) => Err(de::Error::invalid_type(
|
||||
other.unexpected(),
|
||||
&"struct variant",
|
||||
)),
|
||||
_ => Err(de::Error::invalid_type(
|
||||
de::Unexpected::UnitVariant,
|
||||
&"struct variant",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1715,10 +1762,8 @@ mod content {
|
||||
T: de::DeserializeSeed<'de>,
|
||||
{
|
||||
match self.iter.next() {
|
||||
Some(value) => {
|
||||
seed.deserialize(ContentRefDeserializer::new(value))
|
||||
.map(Some)
|
||||
}
|
||||
Some(value) => seed.deserialize(ContentRefDeserializer::new(value))
|
||||
.map(Some),
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
@@ -1763,8 +1808,7 @@ mod content {
|
||||
match self.iter.next() {
|
||||
Some(&(ref key, ref value)) => {
|
||||
self.value = Some(value);
|
||||
seed.deserialize(ContentRefDeserializer::new(key))
|
||||
.map(Some)
|
||||
seed.deserialize(ContentRefDeserializer::new(key)).map(Some)
|
||||
}
|
||||
None => Ok(None),
|
||||
}
|
||||
@@ -1850,7 +1894,11 @@ mod content {
|
||||
type Value = ();
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name)
|
||||
write!(
|
||||
formatter,
|
||||
"unit variant {}::{}",
|
||||
self.type_name, self.variant_name
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_seq<S>(self, _: S) -> Result<(), S::Error>
|
||||
@@ -1890,7 +1938,11 @@ mod content {
|
||||
type Value = ();
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "unit variant {}::{}", self.type_name, self.variant_name)
|
||||
write!(
|
||||
formatter,
|
||||
"unit variant {}::{}",
|
||||
self.type_name, self.variant_name
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_unit<E>(self) -> Result<(), E>
|
||||
@@ -2008,3 +2060,180 @@ where
|
||||
map struct enum identifier ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
||||
///
|
||||
/// Wraps a mutable reference and calls deserialize_in_place on it.
|
||||
pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T);
|
||||
|
||||
impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
type Value = ();
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::deserialize_in_place(deserializer, self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub struct FlatMapDeserializer<'a, 'de: 'a, E>(
|
||||
pub &'a mut Vec<Option<(Content<'de>, Content<'de>)>>,
|
||||
pub PhantomData<E>
|
||||
);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, 'de, E> Deserializer<'de> for FlatMapDeserializer<'a, 'de, E>
|
||||
where E: Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
Err(Error::custom("can only flatten structs and maps"))
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variants: &'static [&'static str],
|
||||
visitor: V
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
for item in self.0.iter_mut() {
|
||||
// items in the vector are nulled out when used. So we can only use
|
||||
// an item if it's still filled in and if the field is one we care
|
||||
// about.
|
||||
let use_item = match *item {
|
||||
None => false,
|
||||
Some((ref c, _)) => c.as_str().map_or(false, |x| variants.contains(&x))
|
||||
};
|
||||
|
||||
if use_item {
|
||||
let (key, value) = item.take().unwrap();
|
||||
return visitor.visit_enum(EnumDeserializer::new(
|
||||
key,
|
||||
Some(value)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::custom(format_args!(
|
||||
"no variant of enum {} not found in flattened data",
|
||||
name
|
||||
)))
|
||||
}
|
||||
|
||||
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_map(FlatMapAccess::new(self.0.iter_mut(), None))
|
||||
}
|
||||
|
||||
fn deserialize_struct<V>(
|
||||
self,
|
||||
_: &'static str,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_map(FlatMapAccess::new(self.0.iter_mut(), Some(fields)))
|
||||
}
|
||||
|
||||
fn deserialize_newtype_struct<V>(
|
||||
self,
|
||||
_name: &str,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
|
||||
byte_buf option unit unit_struct seq tuple tuple_struct identifier
|
||||
ignored_any
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub struct FlatMapAccess<'a, 'de: 'a, E> {
|
||||
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
|
||||
pending_content: Option<Content<'de>>,
|
||||
fields: Option<&'static [&'static str]>,
|
||||
_marker: PhantomData<E>,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, 'de, E> FlatMapAccess<'a, 'de, E> {
|
||||
fn new(
|
||||
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
|
||||
fields: Option<&'static [&'static str]>
|
||||
) -> FlatMapAccess<'a, 'de, E> {
|
||||
FlatMapAccess {
|
||||
iter: iter,
|
||||
pending_content: None,
|
||||
fields: fields,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, 'de, E> MapAccess<'de> for FlatMapAccess<'a, 'de, E>
|
||||
where E: Error
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
while let Some(item) = self.iter.next() {
|
||||
// items in the vector are nulled out when used. So we can only use
|
||||
// an item if it's still filled in and if the field is one we care
|
||||
// about. In case we do not know which fields we want, we take them all.
|
||||
let use_item = match *item {
|
||||
None => false,
|
||||
Some((ref c, _)) => {
|
||||
c.as_str().map_or(self.fields.is_none(), |key| {
|
||||
match self.fields {
|
||||
None => true,
|
||||
Some(fields) if fields.contains(&key) => true,
|
||||
_ => false
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
if use_item {
|
||||
let (key, content) = item.take().unwrap();
|
||||
self.pending_content = Some(content);
|
||||
return seed.deserialize(ContentDeserializer::new(key)).map(Some);
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.pending_content.take() {
|
||||
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
|
||||
None => Err(Error::custom("value is missing")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+394
-96
@@ -8,10 +8,15 @@
|
||||
|
||||
use lib::*;
|
||||
|
||||
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
|
||||
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
|
||||
use self::content::{
|
||||
SerializeStructVariantAsMapValue,
|
||||
SerializeTupleVariantAsMapValue,
|
||||
ContentSerializer,
|
||||
Content,
|
||||
};
|
||||
|
||||
/// Used to check that serde(getter) attributes return the expected type.
|
||||
/// Not public API.
|
||||
@@ -32,15 +37,13 @@ where
|
||||
S: Serializer,
|
||||
T: Serialize,
|
||||
{
|
||||
value.serialize(
|
||||
TaggedSerializer {
|
||||
type_ident: type_ident,
|
||||
variant_ident: variant_ident,
|
||||
tag: tag,
|
||||
variant_name: variant_name,
|
||||
delegate: serializer,
|
||||
},
|
||||
)
|
||||
value.serialize(TaggedSerializer {
|
||||
type_ident: type_ident,
|
||||
variant_ident: variant_ident,
|
||||
tag: tag,
|
||||
variant_name: variant_name,
|
||||
delegate: serializer,
|
||||
})
|
||||
}
|
||||
|
||||
struct TaggedSerializer<S> {
|
||||
@@ -60,10 +63,11 @@ enum Unsupported {
|
||||
ByteArray,
|
||||
Optional,
|
||||
Unit,
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
UnitStruct,
|
||||
Sequence,
|
||||
Tuple,
|
||||
TupleStruct,
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
Enum,
|
||||
}
|
||||
|
||||
@@ -78,10 +82,11 @@ impl Display for Unsupported {
|
||||
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
||||
Unsupported::Optional => formatter.write_str("an optional"),
|
||||
Unsupported::Unit => formatter.write_str("unit"),
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
Unsupported::UnitStruct => formatter.write_str("unit struct"),
|
||||
Unsupported::Sequence => formatter.write_str("a sequence"),
|
||||
Unsupported::Tuple => formatter.write_str("a tuple"),
|
||||
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
Unsupported::Enum => formatter.write_str("an enum"),
|
||||
}
|
||||
}
|
||||
@@ -92,13 +97,10 @@ where
|
||||
S: Serializer,
|
||||
{
|
||||
fn bad_type(self, what: Unsupported) -> S::Error {
|
||||
ser::Error::custom(
|
||||
format_args!(
|
||||
ser::Error::custom(format_args!(
|
||||
"cannot serialize tagged newtype variant {}::{} containing {}",
|
||||
self.type_ident,
|
||||
self.variant_ident,
|
||||
what),
|
||||
)
|
||||
self.type_ident, self.variant_ident, what
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +283,11 @@ where
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_key(inner_variant));
|
||||
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len),)
|
||||
Ok(SerializeTupleVariantAsMapValue::new(
|
||||
map,
|
||||
inner_variant,
|
||||
len,
|
||||
))
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
@@ -324,7 +330,11 @@ where
|
||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||
try!(map.serialize_key(inner_variant));
|
||||
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),)
|
||||
Ok(SerializeStructVariantAsMapValue::new(
|
||||
map,
|
||||
inner_variant,
|
||||
len,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
@@ -402,7 +412,10 @@ mod content {
|
||||
}
|
||||
|
||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
|
||||
try!(
|
||||
self.map
|
||||
.serialize_value(&Content::TupleStruct(self.name, self.fields))
|
||||
);
|
||||
self.map.end()
|
||||
}
|
||||
}
|
||||
@@ -444,13 +457,16 @@ mod content {
|
||||
}
|
||||
|
||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
|
||||
try!(
|
||||
self.map
|
||||
.serialize_value(&Content::Struct(self.name, self.fields))
|
||||
);
|
||||
self.map.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Content {
|
||||
pub enum Content {
|
||||
Bool(bool),
|
||||
|
||||
U8(u8),
|
||||
@@ -485,7 +501,12 @@ mod content {
|
||||
TupleVariant(&'static str, u32, &'static str, Vec<Content>),
|
||||
Map(Vec<(Content, Content)>),
|
||||
Struct(&'static str, Vec<(&'static str, Content)>),
|
||||
StructVariant(&'static str, u32, &'static str, Vec<(&'static str, Content)>),
|
||||
StructVariant(
|
||||
&'static str,
|
||||
u32,
|
||||
&'static str,
|
||||
Vec<(&'static str, Content)>,
|
||||
),
|
||||
}
|
||||
|
||||
impl Serialize for Content {
|
||||
@@ -570,12 +591,12 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentSerializer<E> {
|
||||
pub struct ContentSerializer<E> {
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<E> ContentSerializer<E> {
|
||||
fn new() -> Self {
|
||||
pub fn new() -> Self {
|
||||
ContentSerializer { error: PhantomData }
|
||||
}
|
||||
}
|
||||
@@ -687,7 +708,10 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))),)
|
||||
Ok(Content::NewtypeStruct(
|
||||
name,
|
||||
Box::new(try!(value.serialize(self))),
|
||||
))
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
@@ -700,32 +724,26 @@ mod content {
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Ok(
|
||||
Content::NewtypeVariant(
|
||||
name,
|
||||
variant_index,
|
||||
variant,
|
||||
Box::new(try!(value.serialize(self))),
|
||||
),
|
||||
)
|
||||
Ok(Content::NewtypeVariant(
|
||||
name,
|
||||
variant_index,
|
||||
variant,
|
||||
Box::new(try!(value.serialize(self))),
|
||||
))
|
||||
}
|
||||
|
||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
|
||||
Ok(
|
||||
SerializeSeq {
|
||||
elements: Vec::with_capacity(len.unwrap_or(0)),
|
||||
error: PhantomData,
|
||||
},
|
||||
)
|
||||
Ok(SerializeSeq {
|
||||
elements: Vec::with_capacity(len.unwrap_or(0)),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
|
||||
Ok(
|
||||
SerializeTuple {
|
||||
elements: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
},
|
||||
)
|
||||
Ok(SerializeTuple {
|
||||
elements: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(
|
||||
@@ -733,13 +751,11 @@ mod content {
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleStruct, E> {
|
||||
Ok(
|
||||
SerializeTupleStruct {
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
},
|
||||
)
|
||||
Ok(SerializeTupleStruct {
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(
|
||||
@@ -749,25 +765,21 @@ mod content {
|
||||
variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, E> {
|
||||
Ok(
|
||||
SerializeTupleVariant {
|
||||
name: name,
|
||||
variant_index: variant_index,
|
||||
variant: variant,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
},
|
||||
)
|
||||
Ok(SerializeTupleVariant {
|
||||
name: name,
|
||||
variant_index: variant_index,
|
||||
variant: variant,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
|
||||
Ok(
|
||||
SerializeMap {
|
||||
entries: Vec::with_capacity(len.unwrap_or(0)),
|
||||
key: None,
|
||||
error: PhantomData,
|
||||
},
|
||||
)
|
||||
Ok(SerializeMap {
|
||||
entries: Vec::with_capacity(len.unwrap_or(0)),
|
||||
key: None,
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_struct(
|
||||
@@ -775,13 +787,11 @@ mod content {
|
||||
name: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStruct, E> {
|
||||
Ok(
|
||||
SerializeStruct {
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
},
|
||||
)
|
||||
Ok(SerializeStruct {
|
||||
name: name,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(
|
||||
@@ -791,19 +801,17 @@ mod content {
|
||||
variant: &'static str,
|
||||
len: usize,
|
||||
) -> Result<Self::SerializeStructVariant, E> {
|
||||
Ok(
|
||||
SerializeStructVariant {
|
||||
name: name,
|
||||
variant_index: variant_index,
|
||||
variant: variant,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
},
|
||||
)
|
||||
Ok(SerializeStructVariant {
|
||||
name: name,
|
||||
variant_index: variant_index,
|
||||
variant: variant,
|
||||
fields: Vec::with_capacity(len),
|
||||
error: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeSeq<E> {
|
||||
pub struct SerializeSeq<E> {
|
||||
elements: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
@@ -829,7 +837,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTuple<E> {
|
||||
pub struct SerializeTuple<E> {
|
||||
elements: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
@@ -855,7 +863,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTupleStruct<E> {
|
||||
pub struct SerializeTupleStruct<E> {
|
||||
name: &'static str,
|
||||
fields: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
@@ -882,7 +890,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTupleVariant<E> {
|
||||
pub struct SerializeTupleVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
@@ -907,11 +915,16 @@ mod content {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields),)
|
||||
Ok(Content::TupleVariant(
|
||||
self.name,
|
||||
self.variant_index,
|
||||
self.variant,
|
||||
self.fields,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeMap<E> {
|
||||
pub struct SerializeMap<E> {
|
||||
entries: Vec<(Content, Content)>,
|
||||
key: Option<Content>,
|
||||
error: PhantomData<E>,
|
||||
@@ -961,7 +974,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeStruct<E> {
|
||||
pub struct SerializeStruct<E> {
|
||||
name: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
error: PhantomData<E>,
|
||||
@@ -988,7 +1001,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeStructVariant<E> {
|
||||
pub struct SerializeStructVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
@@ -1013,7 +1026,292 @@ mod content {
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Content, E> {
|
||||
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields),)
|
||||
Ok(Content::StructVariant(
|
||||
self.name,
|
||||
self.variant_index,
|
||||
self.variant,
|
||||
self.fields,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub struct FlatMapSerializer<'a, M: 'a>(pub &'a mut M);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, M> FlatMapSerializer<'a, M>
|
||||
where
|
||||
M: SerializeMap + 'a
|
||||
{
|
||||
fn bad_type(self, what: Unsupported) -> M::Error {
|
||||
ser::Error::custom(format_args!("can only flatten structs and maps (got {})", what))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, M> Serializer for FlatMapSerializer<'a, M>
|
||||
where M: SerializeMap + 'a
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
type SerializeSeq = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeTuple = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeMap = FlatMapSerializeMap<'a, M>;
|
||||
type SerializeStruct = FlatMapSerializeStruct<'a, M>;
|
||||
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>;
|
||||
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
|
||||
|
||||
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Boolean))
|
||||
}
|
||||
|
||||
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Integer))
|
||||
}
|
||||
|
||||
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Integer))
|
||||
}
|
||||
|
||||
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Integer))
|
||||
}
|
||||
|
||||
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Integer))
|
||||
}
|
||||
|
||||
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Integer))
|
||||
}
|
||||
|
||||
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Integer))
|
||||
}
|
||||
|
||||
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Integer))
|
||||
}
|
||||
|
||||
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Integer))
|
||||
}
|
||||
|
||||
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Float))
|
||||
}
|
||||
|
||||
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Float))
|
||||
}
|
||||
|
||||
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Char))
|
||||
}
|
||||
|
||||
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::String))
|
||||
}
|
||||
|
||||
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::ByteArray))
|
||||
}
|
||||
|
||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Optional))
|
||||
}
|
||||
|
||||
fn serialize_some<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
Err(self.bad_type(Unsupported::Optional))
|
||||
}
|
||||
|
||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Unit))
|
||||
}
|
||||
|
||||
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::UnitStruct))
|
||||
}
|
||||
|
||||
fn serialize_unit_variant(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
_: &'static str,
|
||||
) -> Result<Self::Ok, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
}
|
||||
|
||||
fn serialize_newtype_struct<T: ?Sized>(
|
||||
self,
|
||||
_: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
value.serialize(self)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T: ?Sized>(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
variant: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
try!(self.0.serialize_key(variant));
|
||||
self.0.serialize_value(value)
|
||||
}
|
||||
|
||||
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Sequence))
|
||||
}
|
||||
|
||||
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Tuple))
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::TupleStruct))
|
||||
}
|
||||
|
||||
fn serialize_tuple_variant(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
||||
Err(self.bad_type(Unsupported::Enum))
|
||||
}
|
||||
|
||||
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||
Ok(FlatMapSerializeMap(self.0))
|
||||
}
|
||||
|
||||
fn serialize_struct(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeStruct, Self::Error> {
|
||||
Ok(FlatMapSerializeStruct(self.0))
|
||||
}
|
||||
|
||||
fn serialize_struct_variant(
|
||||
self,
|
||||
_: &'static str,
|
||||
_: u32,
|
||||
inner_variant: &'static str,
|
||||
_: usize,
|
||||
) -> Result<Self::SerializeStructVariant, Self::Error> {
|
||||
try!(self.0.serialize_key(inner_variant));
|
||||
Ok(FlatMapSerializeStructVariantAsMapValue::new(self.0, inner_variant))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub struct FlatMapSerializeMap<'a, M: 'a>(&'a mut M);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, M> ser::SerializeMap for FlatMapSerializeMap<'a, M>
|
||||
where M: SerializeMap + 'a
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_key(key)
|
||||
}
|
||||
|
||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_value(value)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub struct FlatMapSerializeStruct<'a, M: 'a>(&'a mut M);
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, M> ser::SerializeStruct for FlatMapSerializeStruct<'a, M>
|
||||
where M: SerializeMap + 'a
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
self.0.serialize_entry(key, value)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
|
||||
map: &'a mut M,
|
||||
name: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, M> FlatMapSerializeStructVariantAsMapValue<'a, M>
|
||||
where M: SerializeMap + 'a
|
||||
{
|
||||
fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> {
|
||||
FlatMapSerializeStructVariantAsMapValue {
|
||||
map: map,
|
||||
name: name,
|
||||
fields: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'a, M> ser::SerializeStructVariant for FlatMapSerializeStructVariantAsMapValue<'a, M>
|
||||
where M: SerializeMap + 'a
|
||||
{
|
||||
type Ok = ();
|
||||
type Error = M::Error;
|
||||
|
||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
let value = try!(value.serialize(ContentSerializer::<M::Error>::new()));
|
||||
self.fields.push((key, value));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end(self) -> Result<(), Self::Error> {
|
||||
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
+46
-11
@@ -111,7 +111,7 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
impl<T> Serialize for PhantomData<T> {
|
||||
impl<T: ?Sized> Serialize for PhantomData<T> {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -351,6 +351,7 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[allow(deprecated)]
|
||||
impl<T> Serialize for NonZero<T>
|
||||
where
|
||||
T: Serialize + Zeroable + Clone,
|
||||
@@ -363,6 +364,32 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! nonzero_integers {
|
||||
( $( $T: ident, )+ ) => {
|
||||
$(
|
||||
#[cfg(feature = "unstable")]
|
||||
impl Serialize for $T {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.get().serialize(serializer)
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
nonzero_integers! {
|
||||
// Not including signed NonZeroI* since they might be removed
|
||||
NonZeroU8,
|
||||
NonZeroU16,
|
||||
NonZeroU32,
|
||||
NonZeroU64,
|
||||
// FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
|
||||
NonZeroUsize,
|
||||
}
|
||||
|
||||
impl<T> Serialize for Cell<T>
|
||||
where
|
||||
T: Serialize + Copy,
|
||||
@@ -464,7 +491,8 @@ impl Serialize for SystemTime {
|
||||
S: Serializer,
|
||||
{
|
||||
use super::SerializeStruct;
|
||||
let duration_since_epoch = self.duration_since(UNIX_EPOCH).expect("SystemTime must be later than UNIX_EPOCH");
|
||||
let duration_since_epoch = self.duration_since(UNIX_EPOCH)
|
||||
.expect("SystemTime must be later than UNIX_EPOCH");
|
||||
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
|
||||
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
|
||||
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
|
||||
@@ -513,10 +541,12 @@ impl Serialize for net::IpAddr {
|
||||
}
|
||||
} else {
|
||||
match *self {
|
||||
net::IpAddr::V4(ref a) =>
|
||||
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a),
|
||||
net::IpAddr::V6(ref a) =>
|
||||
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a),
|
||||
net::IpAddr::V4(ref a) => {
|
||||
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a)
|
||||
}
|
||||
net::IpAddr::V6(ref a) => {
|
||||
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -567,10 +597,12 @@ impl Serialize for net::SocketAddr {
|
||||
}
|
||||
} else {
|
||||
match *self {
|
||||
net::SocketAddr::V4(ref addr) =>
|
||||
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr),
|
||||
net::SocketAddr::V6(ref addr) =>
|
||||
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr),
|
||||
net::SocketAddr::V4(ref addr) => {
|
||||
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr)
|
||||
}
|
||||
net::SocketAddr::V6(ref addr) => {
|
||||
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -600,7 +632,10 @@ impl Serialize for net::SocketAddrV6 {
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
const MAX_LEN: usize = 47;
|
||||
debug_assert_eq!(MAX_LEN, "[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len());
|
||||
debug_assert_eq!(
|
||||
MAX_LEN,
|
||||
"[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len()
|
||||
);
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
} else {
|
||||
(self.ip(), self.port()).serialize(serializer)
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
use lib::*;
|
||||
|
||||
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
|
||||
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
|
||||
use ser::{self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
||||
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
|
||||
|
||||
/// Helper type for implementing a `Serializer` that does not support
|
||||
/// serializing one of the compound types.
|
||||
|
||||
@@ -93,7 +93,8 @@
|
||||
//! - Path
|
||||
//! - PathBuf
|
||||
//! - Range\<T\>
|
||||
//! - NonZero\<T\> (unstable)
|
||||
//! - NonZero\<T\> (unstable, deprecated)
|
||||
//! - num::NonZero* (unstable)
|
||||
//! - **Net types**:
|
||||
//! - IpAddr
|
||||
//! - Ipv4Addr
|
||||
@@ -1412,7 +1413,9 @@ pub trait Serializer: Sized {
|
||||
/// change, as a value serialized in human-readable mode is not required to
|
||||
/// deserialize from the same data in compact mode.
|
||||
#[inline]
|
||||
fn is_human_readable(&self) -> bool { true }
|
||||
fn is_human_readable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Returned from `Serializer::serialize_seq`.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.23" # remember to update html_root_url
|
||||
version = "1.0.35" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
@@ -14,14 +14,19 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-
|
||||
[badges]
|
||||
travis-ci = { repository = "serde-rs/serde" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
deserialize_in_place = []
|
||||
|
||||
[lib]
|
||||
name = "serde_derive"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "0.3.8"
|
||||
serde_derive_internals = { version = "=0.17.0", default-features = false, path = "../serde_derive_internals" }
|
||||
syn = { version = "0.11", features = ["visit"] }
|
||||
proc-macro2 = "0.2"
|
||||
quote = "0.4"
|
||||
serde_derive_internals = { version = "=0.22.1", default-features = false, path = "../serde_derive_internals" }
|
||||
syn = { version = "0.12", features = ["visit"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1.0", path = "../serde" }
|
||||
|
||||
+174
-126
@@ -9,32 +9,31 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use syn::{self, visit};
|
||||
use syn::punctuated::Punctuated;
|
||||
|
||||
use internals::ast::{Body, Container};
|
||||
use internals::ast::{Data, Container};
|
||||
use internals::attr;
|
||||
|
||||
macro_rules! path {
|
||||
($($path:tt)+) => {
|
||||
syn::parse_path(quote!($($path)+).as_str()).unwrap()
|
||||
};
|
||||
}
|
||||
use proc_macro2::{Span, Term};
|
||||
|
||||
// Remove the default from every type parameter because in the generated impls
|
||||
// they look like associated types: "error: associated type bindings are not
|
||||
// allowed here".
|
||||
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
|
||||
syn::Generics {
|
||||
ty_params: generics
|
||||
.ty_params
|
||||
params: generics
|
||||
.params
|
||||
.iter()
|
||||
.map(
|
||||
|ty_param| {
|
||||
syn::TyParam {
|
||||
.map(|param| match *param {
|
||||
syn::GenericParam::Type(ref param) => {
|
||||
syn::GenericParam::Type(syn::TypeParam {
|
||||
eq_token: None,
|
||||
default: None,
|
||||
..ty_param.clone()
|
||||
}
|
||||
},
|
||||
)
|
||||
..param.clone()
|
||||
})
|
||||
}
|
||||
_ => param.clone(),
|
||||
})
|
||||
.collect(),
|
||||
..generics.clone()
|
||||
}
|
||||
@@ -45,10 +44,17 @@ pub fn with_where_predicates(
|
||||
predicates: &[syn::WherePredicate],
|
||||
) -> syn::Generics {
|
||||
let mut generics = generics.clone();
|
||||
generics
|
||||
.where_clause
|
||||
if generics.where_clause.is_none() {
|
||||
generics.where_clause = Some(syn::WhereClause {
|
||||
where_token: Default::default(),
|
||||
predicates: Punctuated::new(),
|
||||
});
|
||||
}
|
||||
generics.where_clause
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.predicates
|
||||
.extend_from_slice(predicates);
|
||||
.extend(predicates.into_iter().cloned());
|
||||
generics
|
||||
}
|
||||
|
||||
@@ -60,13 +66,23 @@ pub fn with_where_predicates_from_fields<F>(
|
||||
where
|
||||
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
|
||||
{
|
||||
let predicates = cont.body
|
||||
let predicates = cont.data
|
||||
.all_fields()
|
||||
.flat_map(|field| from_field(&field.attrs))
|
||||
.flat_map(|predicates| predicates.to_vec());
|
||||
|
||||
let mut generics = generics.clone();
|
||||
generics.where_clause.predicates.extend(predicates);
|
||||
if generics.where_clause.is_none() {
|
||||
generics.where_clause = Some(syn::WhereClause {
|
||||
where_token: Default::default(),
|
||||
predicates: Punctuated::new(),
|
||||
});
|
||||
}
|
||||
generics.where_clause
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.predicates
|
||||
.extend(predicates);
|
||||
generics
|
||||
}
|
||||
|
||||
@@ -99,22 +115,22 @@ where
|
||||
// them.
|
||||
relevant_ty_params: HashSet<syn::Ident>,
|
||||
}
|
||||
impl visit::Visitor for FindTyParams {
|
||||
impl<'ast> visit::Visit<'ast> for FindTyParams {
|
||||
fn visit_path(&mut self, path: &syn::Path) {
|
||||
if let Some(seg) = path.segments.last() {
|
||||
if seg.ident == "PhantomData" {
|
||||
if seg.into_value().ident == "PhantomData" {
|
||||
// Hardcoded exception, because PhantomData<T> implements
|
||||
// Serialize and Deserialize whether or not T implements it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
if !path.global && path.segments.len() == 1 {
|
||||
let id = path.segments[0].ident.clone();
|
||||
if path.leading_colon.is_none() && path.segments.len() == 1 {
|
||||
let id = path.segments[0].ident;
|
||||
if self.all_ty_params.contains(&id) {
|
||||
self.relevant_ty_params.insert(id);
|
||||
}
|
||||
}
|
||||
visit::walk_path(self, path);
|
||||
visit::visit_path(self, path);
|
||||
}
|
||||
|
||||
// Type parameter should not be considered used by a macro path.
|
||||
@@ -123,67 +139,79 @@ where
|
||||
// mac: T!(),
|
||||
// marker: PhantomData<T>,
|
||||
// }
|
||||
fn visit_mac(&mut self, _mac: &syn::Mac) {}
|
||||
fn visit_macro(&mut self, _mac: &syn::Macro) {}
|
||||
}
|
||||
|
||||
let all_ty_params: HashSet<_> = generics
|
||||
.ty_params
|
||||
.params
|
||||
.iter()
|
||||
.map(|ty_param| ty_param.ident.clone())
|
||||
.filter_map(|param| match *param {
|
||||
syn::GenericParam::Type(ref param) => Some(param.ident),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut visitor = FindTyParams {
|
||||
all_ty_params: all_ty_params,
|
||||
relevant_ty_params: HashSet::new(),
|
||||
};
|
||||
match cont.body {
|
||||
Body::Enum(ref variants) => {
|
||||
for variant in variants.iter() {
|
||||
let relevant_fields = variant
|
||||
.fields
|
||||
.iter()
|
||||
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
|
||||
for field in relevant_fields {
|
||||
visit::walk_ty(&mut visitor, field.ty);
|
||||
}
|
||||
match cont.data {
|
||||
Data::Enum(ref variants) => for variant in variants.iter() {
|
||||
let relevant_fields = variant
|
||||
.fields
|
||||
.iter()
|
||||
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
|
||||
for field in relevant_fields {
|
||||
visit::visit_type(&mut visitor, field.ty);
|
||||
}
|
||||
}
|
||||
Body::Struct(_, ref fields) => {
|
||||
},
|
||||
Data::Struct(_, ref fields) => {
|
||||
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
|
||||
visit::walk_ty(&mut visitor, field.ty);
|
||||
visit::visit_type(&mut visitor, field.ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let new_predicates = generics
|
||||
.ty_params
|
||||
.params
|
||||
.iter()
|
||||
.map(|ty_param| ty_param.ident.clone())
|
||||
.filter_map(|param| match *param {
|
||||
syn::GenericParam::Type(ref param) => Some(param.ident),
|
||||
_ => None,
|
||||
})
|
||||
.filter(|id| visitor.relevant_ty_params.contains(id))
|
||||
.map(
|
||||
|id| {
|
||||
syn::WherePredicate::BoundPredicate(
|
||||
syn::WhereBoundPredicate {
|
||||
bound_lifetimes: Vec::new(),
|
||||
// the type parameter that is being bounded e.g. T
|
||||
bounded_ty: syn::Ty::Path(None, id.into()),
|
||||
// the bound e.g. Serialize
|
||||
bounds: vec![
|
||||
syn::TyParamBound::Trait(
|
||||
syn::PolyTraitRef {
|
||||
bound_lifetimes: Vec::new(),
|
||||
trait_ref: bound.clone(),
|
||||
},
|
||||
syn::TraitBoundModifier::None,
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
},
|
||||
);
|
||||
.map(|id| {
|
||||
syn::WherePredicate::Type(syn::PredicateType {
|
||||
lifetimes: None,
|
||||
// the type parameter that is being bounded e.g. T
|
||||
bounded_ty: syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
path: id.into(),
|
||||
}),
|
||||
colon_token: Default::default(),
|
||||
// the bound e.g. Serialize
|
||||
bounds: vec![
|
||||
syn::TypeParamBound::Trait(syn::TraitBound {
|
||||
modifier: syn::TraitBoundModifier::None,
|
||||
lifetimes: None,
|
||||
path: bound.clone(),
|
||||
}),
|
||||
].into_iter().collect(),
|
||||
})
|
||||
});
|
||||
|
||||
let mut generics = generics.clone();
|
||||
generics.where_clause.predicates.extend(new_predicates);
|
||||
if generics.where_clause.is_none() {
|
||||
generics.where_clause = Some(syn::WhereClause {
|
||||
where_token: Default::default(),
|
||||
predicates: Punctuated::new(),
|
||||
});
|
||||
}
|
||||
generics.where_clause
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.predicates
|
||||
.extend(new_predicates);
|
||||
generics
|
||||
}
|
||||
|
||||
@@ -193,82 +221,102 @@ pub fn with_self_bound(
|
||||
bound: &syn::Path,
|
||||
) -> syn::Generics {
|
||||
let mut generics = generics.clone();
|
||||
generics
|
||||
.where_clause
|
||||
if generics.where_clause.is_none() {
|
||||
generics.where_clause = Some(syn::WhereClause {
|
||||
where_token: Default::default(),
|
||||
predicates: Punctuated::new(),
|
||||
});
|
||||
}
|
||||
generics.where_clause
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.predicates
|
||||
.push(
|
||||
syn::WherePredicate::BoundPredicate(
|
||||
syn::WhereBoundPredicate {
|
||||
bound_lifetimes: Vec::new(),
|
||||
// the type that is being bounded e.g. MyStruct<'a, T>
|
||||
bounded_ty: type_of_item(cont),
|
||||
// the bound e.g. Default
|
||||
bounds: vec![
|
||||
syn::TyParamBound::Trait(
|
||||
syn::PolyTraitRef {
|
||||
bound_lifetimes: Vec::new(),
|
||||
trait_ref: bound.clone(),
|
||||
},
|
||||
syn::TraitBoundModifier::None,
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
);
|
||||
.push(syn::WherePredicate::Type(syn::PredicateType {
|
||||
lifetimes: None,
|
||||
// the type that is being bounded e.g. MyStruct<'a, T>
|
||||
bounded_ty: type_of_item(cont),
|
||||
colon_token: Default::default(),
|
||||
// the bound e.g. Default
|
||||
bounds: vec![
|
||||
syn::TypeParamBound::Trait(syn::TraitBound {
|
||||
modifier: syn::TraitBoundModifier::None,
|
||||
lifetimes: None,
|
||||
path: bound.clone(),
|
||||
}),
|
||||
].into_iter().collect(),
|
||||
}));
|
||||
generics
|
||||
}
|
||||
|
||||
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
|
||||
let mut generics = generics.clone();
|
||||
let bound = syn::Lifetime::new(Term::intern(lifetime), Span::def_site());
|
||||
let def = syn::LifetimeDef {
|
||||
attrs: Vec::new(),
|
||||
lifetime: bound,
|
||||
colon_token: None,
|
||||
bounds: Punctuated::new(),
|
||||
};
|
||||
|
||||
for lifetime_def in &mut generics.lifetimes {
|
||||
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
|
||||
let params = Some(syn::GenericParam::Lifetime(def))
|
||||
.into_iter()
|
||||
.chain(generics.params
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|mut param| {
|
||||
match param {
|
||||
syn::GenericParam::Lifetime(ref mut param) => {
|
||||
param.bounds.push(bound);
|
||||
}
|
||||
syn::GenericParam::Type(ref mut param) => {
|
||||
param.bounds.push(syn::TypeParamBound::Lifetime(bound));
|
||||
}
|
||||
syn::GenericParam::Const(_) => {}
|
||||
}
|
||||
param
|
||||
}))
|
||||
.collect();
|
||||
|
||||
syn::Generics {
|
||||
params: params,
|
||||
..generics.clone()
|
||||
}
|
||||
|
||||
for ty_param in &mut generics.ty_params {
|
||||
ty_param
|
||||
.bounds
|
||||
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
|
||||
}
|
||||
|
||||
generics
|
||||
.lifetimes
|
||||
.push(
|
||||
syn::LifetimeDef {
|
||||
attrs: Vec::new(),
|
||||
lifetime: syn::Lifetime::new(lifetime),
|
||||
bounds: Vec::new(),
|
||||
},
|
||||
);
|
||||
|
||||
generics
|
||||
}
|
||||
|
||||
fn type_of_item(cont: &Container) -> syn::Ty {
|
||||
syn::Ty::Path(
|
||||
None,
|
||||
syn::Path {
|
||||
global: false,
|
||||
fn type_of_item(cont: &Container) -> syn::Type {
|
||||
syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
path: syn::Path {
|
||||
leading_colon: None,
|
||||
segments: vec![
|
||||
syn::PathSegment {
|
||||
ident: cont.ident.clone(),
|
||||
parameters: syn::PathParameters::AngleBracketed(
|
||||
syn::AngleBracketedParameterData {
|
||||
lifetimes: cont.generics
|
||||
.lifetimes
|
||||
ident: cont.ident,
|
||||
arguments: syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments {
|
||||
colon2_token: None,
|
||||
lt_token: Default::default(),
|
||||
args: cont.generics
|
||||
.params
|
||||
.iter()
|
||||
.map(|def| def.lifetime.clone())
|
||||
.map(|param| match *param {
|
||||
syn::GenericParam::Type(ref param) => {
|
||||
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
|
||||
qself: None,
|
||||
path: param.ident.into(),
|
||||
}))
|
||||
}
|
||||
syn::GenericParam::Lifetime(ref param) => {
|
||||
syn::GenericArgument::Lifetime(param.lifetime)
|
||||
}
|
||||
syn::GenericParam::Const(_) => {
|
||||
panic!("Serde does not support const generics yet");
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
types: cont.generics
|
||||
.ty_params
|
||||
.iter()
|
||||
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
|
||||
.collect(),
|
||||
bindings: Vec::new(),
|
||||
gt_token: Default::default(),
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
].into_iter().collect(),
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
+1273
-394
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use quote::{Tokens, ToTokens};
|
||||
use quote::{ToTokens, Tokens};
|
||||
use syn::token;
|
||||
|
||||
pub enum Fragment {
|
||||
/// Tokens that can be used as an expression.
|
||||
@@ -36,9 +37,7 @@ impl ToTokens for Expr {
|
||||
match self.0 {
|
||||
Fragment::Expr(ref expr) => expr.to_tokens(out),
|
||||
Fragment::Block(ref block) => {
|
||||
out.append("{");
|
||||
block.to_tokens(out);
|
||||
out.append("}");
|
||||
token::Brace::default().surround(out, |out| block.to_tokens(out));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,13 +62,20 @@ impl ToTokens for Match {
|
||||
match self.0 {
|
||||
Fragment::Expr(ref expr) => {
|
||||
expr.to_tokens(out);
|
||||
out.append(",");
|
||||
<Token![,]>::default().to_tokens(out);
|
||||
}
|
||||
Fragment::Block(ref block) => {
|
||||
out.append("{");
|
||||
block.to_tokens(out);
|
||||
out.append("}");
|
||||
token::Brace::default().surround(out, |out| block.to_tokens(out));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Tokens> for Fragment {
|
||||
fn as_ref(&self) -> &Tokens {
|
||||
match *self {
|
||||
Fragment::Expr(ref expr) => expr,
|
||||
Fragment::Block(ref block) => block,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-11
@@ -22,22 +22,24 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.23")]
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.35")]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(enum_variant_names, redundant_field_names,
|
||||
too_many_arguments, used_underscore_binding))]
|
||||
// The `quote!` macro requires deep recursion.
|
||||
#![recursion_limit = "192"]
|
||||
#![recursion_limit = "512"]
|
||||
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
#[macro_use]
|
||||
extern crate syn;
|
||||
|
||||
extern crate serde_derive_internals as internals;
|
||||
|
||||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use syn::DeriveInput;
|
||||
|
||||
#[macro_use]
|
||||
mod bound;
|
||||
@@ -49,18 +51,18 @@ mod de;
|
||||
|
||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
let input = syn::parse_derive_input(&input.to_string()).unwrap();
|
||||
let input: DeriveInput = syn::parse(input).unwrap();
|
||||
match ser::expand_derive_serialize(&input) {
|
||||
Ok(expanded) => expanded.parse().unwrap(),
|
||||
Ok(expanded) => expanded.into(),
|
||||
Err(msg) => panic!(msg),
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||
let input = syn::parse_derive_input(&input.to_string()).unwrap();
|
||||
let input: DeriveInput = syn::parse(input).unwrap();
|
||||
match de::expand_derive_deserialize(&input) {
|
||||
Ok(expanded) => expanded.parse().unwrap(),
|
||||
Ok(expanded) => expanded.into(),
|
||||
Err(msg) => panic!(msg),
|
||||
}
|
||||
}
|
||||
|
||||
+371
-287
@@ -6,12 +6,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use syn::{self, Ident};
|
||||
use syn::{self, Ident, Index, Member};
|
||||
use syn::spanned::Spanned;
|
||||
use quote::Tokens;
|
||||
use proc_macro2::Span;
|
||||
|
||||
use bound;
|
||||
use fragment::{Fragment, Stmts, Match};
|
||||
use internals::ast::{Body, Container, Field, Style, Variant};
|
||||
use fragment::{Fragment, Match, Stmts};
|
||||
use internals::ast::{Data, Container, Field, Style, Variant};
|
||||
use internals::{attr, Ctxt};
|
||||
|
||||
use std::u32;
|
||||
@@ -25,14 +27,15 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
||||
let ident = &cont.ident;
|
||||
let params = Parameters::new(&cont);
|
||||
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
|
||||
let dummy_const = Ident::new(&format!("_IMPL_SERIALIZE_FOR_{}", ident), Span::def_site());
|
||||
let body = Stmts(serialize_body(&cont, ¶ms));
|
||||
|
||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||
let vis = &input.vis;
|
||||
let fun = quote_spanned!(Span::call_site()=> serialize);
|
||||
quote! {
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
#vis fn #fun<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
where __S: _serde::Serializer
|
||||
{
|
||||
#body
|
||||
@@ -95,14 +98,14 @@ impl Parameters {
|
||||
fn new(cont: &Container) -> Self {
|
||||
let is_remote = cont.attrs.remote().is_some();
|
||||
let self_var = if is_remote {
|
||||
Ident::new("__self")
|
||||
Ident::new("__self", Span::def_site())
|
||||
} else {
|
||||
Ident::new("self")
|
||||
Ident::new("self", Span::def_site())
|
||||
};
|
||||
|
||||
let this = match cont.attrs.remote() {
|
||||
Some(remote) => remote.clone(),
|
||||
None => cont.ident.clone().into(),
|
||||
None => cont.ident.into(),
|
||||
};
|
||||
|
||||
let generics = build_generics(cont);
|
||||
@@ -118,7 +121,7 @@ impl Parameters {
|
||||
/// Type name to use in error messages and `&'static str` arguments to
|
||||
/// various Serializer methods.
|
||||
fn type_name(&self) -> &str {
|
||||
self.this.segments.last().unwrap().ident.as_ref()
|
||||
self.this.segments.last().unwrap().value().ident.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,14 +135,12 @@ fn build_generics(cont: &Container) -> syn::Generics {
|
||||
|
||||
match cont.attrs.ser_bound() {
|
||||
Some(predicates) => bound::with_where_predicates(&generics, predicates),
|
||||
None => {
|
||||
bound::with_bound(
|
||||
cont,
|
||||
&generics,
|
||||
needs_serialize_bound,
|
||||
&path!(_serde::Serialize),
|
||||
)
|
||||
}
|
||||
None => bound::with_bound(
|
||||
cont,
|
||||
&generics,
|
||||
needs_serialize_bound,
|
||||
&parse_quote!(_serde::Serialize),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,43 +150,41 @@ fn build_generics(cont: &Container) -> syn::Generics {
|
||||
// their own bound so we do not generate one. All other fields may need a `T:
|
||||
// Serialize` bound where T is the type of the field.
|
||||
fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
|
||||
!field.skip_serializing() &&
|
||||
field.serialize_with().is_none() &&
|
||||
field.ser_bound().is_none() &&
|
||||
variant.map_or(true, |variant| variant.serialize_with().is_none())
|
||||
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
|
||||
&& variant.map_or(true, |variant| variant.serialize_with().is_none())
|
||||
}
|
||||
|
||||
fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
||||
if let Some(into_type) = cont.attrs.into_type() {
|
||||
serialize_into(params, into_type)
|
||||
if let Some(type_into) = cont.attrs.type_into() {
|
||||
serialize_into(params, type_into)
|
||||
} else {
|
||||
match cont.body {
|
||||
Body::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
|
||||
Body::Struct(Style::Struct, ref fields) => {
|
||||
match cont.data {
|
||||
Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
|
||||
Data::Struct(Style::Struct, ref fields) => {
|
||||
if fields.iter().any(|field| field.ident.is_none()) {
|
||||
panic!("struct has unnamed fields");
|
||||
}
|
||||
serialize_struct(params, fields, &cont.attrs)
|
||||
}
|
||||
Body::Struct(Style::Tuple, ref fields) => {
|
||||
Data::Struct(Style::Tuple, ref fields) => {
|
||||
if fields.iter().any(|field| field.ident.is_some()) {
|
||||
panic!("tuple struct has named fields");
|
||||
}
|
||||
serialize_tuple_struct(params, fields, &cont.attrs)
|
||||
}
|
||||
Body::Struct(Style::Newtype, ref fields) => {
|
||||
Data::Struct(Style::Newtype, ref fields) => {
|
||||
serialize_newtype_struct(params, &fields[0], &cont.attrs)
|
||||
}
|
||||
Body::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
|
||||
Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_into(params: &Parameters, into_type: &syn::Ty) -> Fragment {
|
||||
fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
|
||||
let self_var = ¶ms.self_var;
|
||||
quote_block! {
|
||||
_serde::Serialize::serialize(
|
||||
&_serde::export::Into::<#into_type>::into(_serde::export::Clone::clone(#self_var)),
|
||||
&_serde::export::Into::<#type_into>::into(_serde::export::Clone::clone(#self_var)),
|
||||
__serializer)
|
||||
}
|
||||
}
|
||||
@@ -205,13 +204,18 @@ fn serialize_newtype_struct(
|
||||
) -> Fragment {
|
||||
let type_name = cattrs.name().serialize_name();
|
||||
|
||||
let mut field_expr = get_field(params, field, 0);
|
||||
let mut field_expr = get_member(params, field, &Member::Unnamed(Index {
|
||||
index: 0,
|
||||
span: Span::call_site(),
|
||||
}));
|
||||
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 span = Span::def_site().located_at(field.original.span());
|
||||
let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct);
|
||||
quote_expr! {
|
||||
_serde::Serializer::serialize_newtype_struct(__serializer, #type_name, #field_expr)
|
||||
#func(__serializer, #type_name, #field_expr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +228,7 @@ fn serialize_tuple_struct(
|
||||
fields,
|
||||
params,
|
||||
false,
|
||||
quote!(_serde::ser::SerializeTupleStruct::serialize_field),
|
||||
&TupleTrait::SerializeTupleStruct,
|
||||
);
|
||||
|
||||
let type_name = cattrs.name().serialize_name();
|
||||
@@ -239,14 +243,21 @@ fn serialize_tuple_struct(
|
||||
}
|
||||
|
||||
fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
|
||||
assert!(fields.len() as u64 <= u32::MAX as u64);
|
||||
assert!(fields.len() as u64 <= u64::from(u32::MAX));
|
||||
|
||||
if cattrs.has_flatten() {
|
||||
serialize_struct_as_map(params, fields, cattrs)
|
||||
} else {
|
||||
serialize_struct_as_struct(params, fields, cattrs)
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_struct_as_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
|
||||
let serialize_fields = serialize_struct_visitor(
|
||||
fields,
|
||||
params,
|
||||
false,
|
||||
quote!(_serde::ser::SerializeStruct::serialize_field),
|
||||
quote!(_serde::ser::SerializeStruct::skip_field),
|
||||
&StructTrait::SerializeStruct,
|
||||
);
|
||||
|
||||
let type_name = cattrs.name().serialize_name();
|
||||
@@ -259,16 +270,14 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
|
||||
let let_mut = mut_if(serialized_fields.peek().is_some());
|
||||
|
||||
let len = serialized_fields
|
||||
.map(
|
||||
|field| match field.attrs.skip_serializing_if() {
|
||||
None => quote!(1),
|
||||
Some(path) => {
|
||||
let ident = field.ident.clone().expect("struct has unnamed fields");
|
||||
let field_expr = get_field(params, field, ident);
|
||||
quote!(if #path(#field_expr) { 0 } else { 1 })
|
||||
}
|
||||
},
|
||||
)
|
||||
.map(|field| match field.attrs.skip_serializing_if() {
|
||||
None => quote!(1),
|
||||
Some(path) => {
|
||||
let ident = field.ident.expect("struct has unnamed fields");
|
||||
let field_expr = get_member(params, field, &Member::Named(ident));
|
||||
quote!(if #path(#field_expr) { 0 } else { 1 })
|
||||
}
|
||||
})
|
||||
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
||||
|
||||
quote_block! {
|
||||
@@ -278,19 +287,55 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_struct_as_map(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment {
|
||||
let serialize_fields = serialize_struct_visitor(
|
||||
fields,
|
||||
params,
|
||||
false,
|
||||
&StructTrait::SerializeMap,
|
||||
);
|
||||
|
||||
let mut serialized_fields = fields
|
||||
.iter()
|
||||
.filter(|&field| !field.attrs.skip_serializing())
|
||||
.peekable();
|
||||
|
||||
let let_mut = mut_if(serialized_fields.peek().is_some());
|
||||
|
||||
let len = if cattrs.has_flatten() {
|
||||
quote!(_serde::export::None)
|
||||
} else {
|
||||
let len = serialized_fields
|
||||
.map(|field| match field.attrs.skip_serializing_if() {
|
||||
None => quote!(1),
|
||||
Some(path) => {
|
||||
let ident = field.ident.expect("struct has unnamed fields");
|
||||
let field_expr = get_member(params, field, &Member::Named(ident));
|
||||
quote!(if #path(#field_expr) { 0 } else { 1 })
|
||||
}
|
||||
})
|
||||
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
||||
quote!(_serde::export::Some(#len))
|
||||
};
|
||||
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
|
||||
assert!(variants.len() as u64 <= u32::MAX as u64);
|
||||
assert!(variants.len() as u64 <= u64::from(u32::MAX));
|
||||
|
||||
let self_var = ¶ms.self_var;
|
||||
|
||||
let arms: Vec<_> = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(
|
||||
|(variant_index, variant)| {
|
||||
serialize_variant(params, variant, variant_index as u32, cattrs)
|
||||
},
|
||||
)
|
||||
.map(|(variant_index, variant)| {
|
||||
serialize_variant(params, variant, variant_index as u32, cattrs)
|
||||
})
|
||||
.collect();
|
||||
|
||||
quote_expr! {
|
||||
@@ -307,7 +352,7 @@ fn serialize_variant(
|
||||
cattrs: &attr::Container,
|
||||
) -> Tokens {
|
||||
let this = ¶ms.this;
|
||||
let variant_ident = variant.ident.clone();
|
||||
let variant_ident = variant.ident;
|
||||
|
||||
if variant.attrs.skip_serializing() {
|
||||
let skipped_msg = format!(
|
||||
@@ -321,13 +366,7 @@ fn serialize_variant(
|
||||
let fields_pat = match variant.style {
|
||||
Style::Unit => quote!(),
|
||||
Style::Newtype | Style::Tuple => quote!((..)),
|
||||
Style::Struct => {
|
||||
quote!(
|
||||
{
|
||||
..
|
||||
}
|
||||
)
|
||||
}
|
||||
Style::Struct => quote!({ .. }),
|
||||
};
|
||||
quote! {
|
||||
#this::#variant_ident #fields_pat => #skipped_err,
|
||||
@@ -347,7 +386,7 @@ fn serialize_variant(
|
||||
}
|
||||
Style::Tuple => {
|
||||
let field_names =
|
||||
(0..variant.fields.len()).map(|i| Ident::new(format!("__field{}", i)));
|
||||
(0..variant.fields.len()).map(|i| Ident::new(&format!("__field{}", i), Span::def_site()));
|
||||
quote! {
|
||||
#this::#variant_ident(#(ref #field_names),*)
|
||||
}
|
||||
@@ -356,34 +395,26 @@ fn serialize_variant(
|
||||
let fields = variant
|
||||
.fields
|
||||
.iter()
|
||||
.map(
|
||||
|f| {
|
||||
f.ident
|
||||
.clone()
|
||||
.expect("struct variant has unnamed fields")
|
||||
},
|
||||
);
|
||||
.map(|f| f.ident.expect("struct variant has unnamed fields"));
|
||||
quote! {
|
||||
#this::#variant_ident { #(ref #fields),* }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let body = Match(
|
||||
match *cattrs.tag() {
|
||||
attr::EnumTag::External => {
|
||||
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
|
||||
}
|
||||
attr::EnumTag::Internal { ref tag } => {
|
||||
serialize_internally_tagged_variant(params, variant, cattrs, tag)
|
||||
}
|
||||
attr::EnumTag::Adjacent {
|
||||
ref tag,
|
||||
ref content,
|
||||
} => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
|
||||
attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs),
|
||||
},
|
||||
);
|
||||
let body = Match(match *cattrs.tag() {
|
||||
attr::EnumTag::External => {
|
||||
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
|
||||
}
|
||||
attr::EnumTag::Internal { ref tag } => {
|
||||
serialize_internally_tagged_variant(params, variant, cattrs, tag)
|
||||
}
|
||||
attr::EnumTag::Adjacent {
|
||||
ref tag,
|
||||
ref content,
|
||||
} => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
|
||||
attr::EnumTag::None => serialize_untagged_variant(params, variant, cattrs),
|
||||
});
|
||||
|
||||
quote! {
|
||||
#case => #body
|
||||
@@ -401,7 +432,7 @@ fn serialize_externally_tagged_variant(
|
||||
let variant_name = variant.attrs.name().serialize_name();
|
||||
|
||||
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);
|
||||
return quote_expr! {
|
||||
_serde::Serializer::serialize_newtype_variant(
|
||||
__serializer,
|
||||
@@ -428,7 +459,7 @@ fn serialize_externally_tagged_variant(
|
||||
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);
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
|
||||
quote_expr! {
|
||||
@@ -441,28 +472,24 @@ fn serialize_externally_tagged_variant(
|
||||
)
|
||||
}
|
||||
}
|
||||
Style::Tuple => {
|
||||
serialize_tuple_variant(
|
||||
TupleVariant::ExternallyTagged {
|
||||
type_name: type_name,
|
||||
variant_index: variant_index,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
params,
|
||||
&variant.fields,
|
||||
)
|
||||
}
|
||||
Style::Struct => {
|
||||
serialize_struct_variant(
|
||||
StructVariant::ExternallyTagged {
|
||||
variant_index: variant_index,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name,
|
||||
)
|
||||
}
|
||||
Style::Tuple => serialize_tuple_variant(
|
||||
TupleVariant::ExternallyTagged {
|
||||
type_name: type_name,
|
||||
variant_index: variant_index,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
params,
|
||||
&variant.fields,
|
||||
),
|
||||
Style::Struct => serialize_struct_variant(
|
||||
StructVariant::ExternallyTagged {
|
||||
variant_index: variant_index,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +506,7 @@ fn serialize_internally_tagged_variant(
|
||||
let variant_ident_str = variant.ident.as_ref();
|
||||
|
||||
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);
|
||||
return quote_expr! {
|
||||
_serde::private::ser::serialize_tagged_newtype(
|
||||
__serializer,
|
||||
@@ -506,7 +533,7 @@ fn serialize_internally_tagged_variant(
|
||||
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);
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
|
||||
quote_expr! {
|
||||
@@ -520,17 +547,15 @@ fn serialize_internally_tagged_variant(
|
||||
)
|
||||
}
|
||||
}
|
||||
Style::Struct => {
|
||||
serialize_struct_variant(
|
||||
StructVariant::InternallyTagged {
|
||||
tag: tag,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name,
|
||||
)
|
||||
}
|
||||
Style::Struct => serialize_struct_variant(
|
||||
StructVariant::InternallyTagged {
|
||||
tag: tag,
|
||||
variant_name: variant_name,
|
||||
},
|
||||
params,
|
||||
&variant.fields,
|
||||
&type_name,
|
||||
),
|
||||
Style::Tuple => unreachable!("checked in serde_derive_internals"),
|
||||
}
|
||||
}
|
||||
@@ -546,51 +571,47 @@ fn serialize_adjacently_tagged_variant(
|
||||
let type_name = cattrs.name().serialize_name();
|
||||
let variant_name = variant.attrs.name().serialize_name();
|
||||
|
||||
let inner = Stmts(
|
||||
if let Some(path) = variant.attrs.serialize_with() {
|
||||
let ser = wrap_serialize_variant_with(params, path, &variant);
|
||||
quote_expr! {
|
||||
_serde::Serialize::serialize(#ser, __serializer)
|
||||
let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
|
||||
let ser = wrap_serialize_variant_with(params, path, variant);
|
||||
quote_expr! {
|
||||
_serde::Serialize::serialize(#ser, __serializer)
|
||||
}
|
||||
} else {
|
||||
match variant.style {
|
||||
Style::Unit => {
|
||||
return quote_block! {
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
match variant.style {
|
||||
Style::Unit => {
|
||||
return quote_block! {
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 1));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
};
|
||||
Style::Newtype => {
|
||||
let field = &variant.fields[0];
|
||||
let mut field_expr = quote!(__field0);
|
||||
if let Some(path) = field.attrs.serialize_with() {
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
Style::Newtype => {
|
||||
let field = &variant.fields[0];
|
||||
let mut field_expr = quote!(__field0);
|
||||
if let Some(path) = field.attrs.serialize_with() {
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
|
||||
}
|
||||
|
||||
quote_expr! {
|
||||
_serde::Serialize::serialize(#field_expr, __serializer)
|
||||
}
|
||||
}
|
||||
Style::Tuple => {
|
||||
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
|
||||
}
|
||||
Style::Struct => {
|
||||
serialize_struct_variant(
|
||||
StructVariant::Untagged,
|
||||
params,
|
||||
&variant.fields,
|
||||
&variant_name,
|
||||
)
|
||||
quote_expr! {
|
||||
_serde::Serialize::serialize(#field_expr, __serializer)
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
Style::Tuple => {
|
||||
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
|
||||
}
|
||||
Style::Struct => serialize_struct_variant(
|
||||
StructVariant::Untagged,
|
||||
params,
|
||||
&variant.fields,
|
||||
&variant_name,
|
||||
),
|
||||
}
|
||||
});
|
||||
|
||||
let fields_ty = variant.fields.iter().map(|f| &f.ty);
|
||||
let ref fields_ident: Vec<_> = match variant.style {
|
||||
let fields_ident: &Vec<_> = &match variant.style {
|
||||
Style::Unit => {
|
||||
if variant.attrs.serialize_with().is_some() {
|
||||
vec![]
|
||||
@@ -598,25 +619,15 @@ fn serialize_adjacently_tagged_variant(
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Style::Newtype => vec![Ident::new("__field0")],
|
||||
Style::Tuple => {
|
||||
(0..variant.fields.len())
|
||||
.map(|i| Ident::new(format!("__field{}", i)))
|
||||
.collect()
|
||||
}
|
||||
Style::Struct => {
|
||||
variant
|
||||
.fields
|
||||
.iter()
|
||||
.map(
|
||||
|f| {
|
||||
f.ident
|
||||
.clone()
|
||||
.expect("struct variant has unnamed fields")
|
||||
},
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
Style::Newtype => vec![Ident::new("__field0", Span::def_site())],
|
||||
Style::Tuple => (0..variant.fields.len())
|
||||
.map(|i| Ident::new(&format!("__field{}", i), Span::def_site()))
|
||||
.collect(),
|
||||
Style::Struct => variant
|
||||
.fields
|
||||
.iter()
|
||||
.map(|f| f.ident.expect("struct variant has unnamed fields"))
|
||||
.collect(),
|
||||
};
|
||||
|
||||
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
@@ -662,7 +673,7 @@ fn serialize_untagged_variant(
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
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);
|
||||
return quote_expr! {
|
||||
_serde::Serialize::serialize(#ser, __serializer)
|
||||
};
|
||||
@@ -678,7 +689,7 @@ fn serialize_untagged_variant(
|
||||
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);
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
|
||||
quote_expr! {
|
||||
@@ -707,14 +718,12 @@ fn serialize_tuple_variant(
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
) -> Fragment {
|
||||
let method = match context {
|
||||
TupleVariant::ExternallyTagged { .. } => {
|
||||
quote!(_serde::ser::SerializeTupleVariant::serialize_field)
|
||||
}
|
||||
TupleVariant::Untagged => quote!(_serde::ser::SerializeTuple::serialize_element),
|
||||
let tuple_trait = match context {
|
||||
TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant,
|
||||
TupleVariant::Untagged => TupleTrait::SerializeTuple,
|
||||
};
|
||||
|
||||
let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, method);
|
||||
let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait);
|
||||
|
||||
let len = serialize_stmts.len();
|
||||
let let_mut = mut_if(len > 0);
|
||||
@@ -753,7 +762,10 @@ enum StructVariant<'a> {
|
||||
variant_index: u32,
|
||||
variant_name: String,
|
||||
},
|
||||
InternallyTagged { tag: &'a str, variant_name: String },
|
||||
InternallyTagged {
|
||||
tag: &'a str,
|
||||
variant_name: String,
|
||||
},
|
||||
Untagged,
|
||||
}
|
||||
|
||||
@@ -763,23 +775,16 @@ fn serialize_struct_variant<'a>(
|
||||
fields: &[Field],
|
||||
name: &str,
|
||||
) -> Fragment {
|
||||
let (method, skip_method) = match context {
|
||||
StructVariant::ExternallyTagged { .. } => {
|
||||
(
|
||||
quote!(_serde::ser::SerializeStructVariant::serialize_field),
|
||||
quote!(_serde::ser::SerializeStructVariant::skip_field),
|
||||
)
|
||||
}
|
||||
StructVariant::InternallyTagged { .. } |
|
||||
StructVariant::Untagged => {
|
||||
(
|
||||
quote!(_serde::ser::SerializeStruct::serialize_field),
|
||||
quote!(_serde::ser::SerializeStruct::skip_field),
|
||||
)
|
||||
}
|
||||
let struct_trait = match context {
|
||||
StructVariant::ExternallyTagged { .. } => (
|
||||
StructTrait::SerializeStructVariant
|
||||
),
|
||||
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => (
|
||||
StructTrait::SerializeStruct
|
||||
),
|
||||
};
|
||||
|
||||
let serialize_fields = serialize_struct_visitor(fields, params, true, method, skip_method);
|
||||
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
|
||||
|
||||
let mut serialized_fields = fields
|
||||
.iter()
|
||||
@@ -789,16 +794,14 @@ fn serialize_struct_variant<'a>(
|
||||
let let_mut = mut_if(serialized_fields.peek().is_some());
|
||||
|
||||
let len = serialized_fields
|
||||
.map(
|
||||
|field| {
|
||||
let ident = field.ident.clone().expect("struct has unnamed fields");
|
||||
.map(|field| {
|
||||
let ident = field.ident.expect("struct has unnamed fields");
|
||||
|
||||
match field.attrs.skip_serializing_if() {
|
||||
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
|
||||
None => quote!(1),
|
||||
}
|
||||
},
|
||||
)
|
||||
match field.attrs.skip_serializing_if() {
|
||||
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
|
||||
None => quote!(1),
|
||||
}
|
||||
})
|
||||
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
||||
|
||||
match context {
|
||||
@@ -852,39 +855,42 @@ fn serialize_tuple_struct_visitor(
|
||||
fields: &[Field],
|
||||
params: &Parameters,
|
||||
is_enum: bool,
|
||||
func: Tokens,
|
||||
tuple_trait: &TupleTrait,
|
||||
) -> Vec<Tokens> {
|
||||
fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(
|
||||
|(i, field)| {
|
||||
let mut field_expr = if is_enum {
|
||||
let id = Ident::new(format!("__field{}", i));
|
||||
quote!(#id)
|
||||
} else {
|
||||
get_field(params, field, i)
|
||||
};
|
||||
.map(|(i, field)| {
|
||||
let mut field_expr = if is_enum {
|
||||
let id = Ident::new(&format!("__field{}", i), Span::def_site());
|
||||
quote!(#id)
|
||||
} else {
|
||||
get_member(params, field, &Member::Unnamed(Index {
|
||||
index: i as u32,
|
||||
span: Span::call_site(),
|
||||
}))
|
||||
};
|
||||
|
||||
let skip = field
|
||||
.attrs
|
||||
.skip_serializing_if()
|
||||
.map(|path| quote!(#path(#field_expr)));
|
||||
let skip = field
|
||||
.attrs
|
||||
.skip_serializing_if()
|
||||
.map(|path| quote!(#path(#field_expr)));
|
||||
|
||||
if let Some(path) = field.attrs.serialize_with() {
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
|
||||
}
|
||||
if let Some(path) = field.attrs.serialize_with() {
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
|
||||
let ser = quote! {
|
||||
try!(#func(&mut __serde_state, #field_expr));
|
||||
};
|
||||
let span = Span::def_site().located_at(field.original.span());
|
||||
let func = tuple_trait.serialize_element(span);
|
||||
let ser = quote! {
|
||||
try!(#func(&mut __serde_state, #field_expr));
|
||||
};
|
||||
|
||||
match skip {
|
||||
None => ser,
|
||||
Some(skip) => quote!(if !#skip { #ser }),
|
||||
}
|
||||
},
|
||||
)
|
||||
match skip {
|
||||
None => ser,
|
||||
Some(skip) => quote!(if !#skip { #ser }),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -892,39 +898,47 @@ fn serialize_struct_visitor(
|
||||
fields: &[Field],
|
||||
params: &Parameters,
|
||||
is_enum: bool,
|
||||
func: Tokens,
|
||||
skip_func: Tokens,
|
||||
struct_trait: &StructTrait,
|
||||
) -> Vec<Tokens> {
|
||||
fields
|
||||
.iter()
|
||||
.filter(|&field| !field.attrs.skip_serializing())
|
||||
.map(
|
||||
|field| {
|
||||
let field_ident = field.ident.clone().expect("struct has unnamed field");
|
||||
let mut field_expr = if is_enum {
|
||||
quote!(#field_ident)
|
||||
} else {
|
||||
get_field(params, field, field_ident)
|
||||
};
|
||||
.map(|field| {
|
||||
let field_ident = field.ident.expect("struct has unnamed field");
|
||||
|
||||
let key_expr = field.attrs.name().serialize_name();
|
||||
let mut field_expr = if is_enum {
|
||||
quote!(#field_ident)
|
||||
} else {
|
||||
get_member(params, field, &Member::Named(field_ident))
|
||||
};
|
||||
|
||||
let skip = field
|
||||
.attrs
|
||||
.skip_serializing_if()
|
||||
.map(|path| quote!(#path(#field_expr)));
|
||||
let key_expr = field.attrs.name().serialize_name();
|
||||
|
||||
if let Some(path) = field.attrs.serialize_with() {
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, field_expr);
|
||||
let skip = field
|
||||
.attrs
|
||||
.skip_serializing_if()
|
||||
.map(|path| quote!(#path(#field_expr)));
|
||||
|
||||
if let Some(path) = field.attrs.serialize_with() {
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
|
||||
let span = Span::def_site().located_at(field.original.span());
|
||||
let ser = if field.attrs.flatten() {
|
||||
quote! {
|
||||
try!(_serde::Serialize::serialize(&#field_expr, _serde::private::ser::FlatMapSerializer(&mut __serde_state)));
|
||||
}
|
||||
|
||||
let ser = quote! {
|
||||
} else {
|
||||
let func = struct_trait.serialize_field(span);
|
||||
quote! {
|
||||
try!(#func(&mut __serde_state, #key_expr, #field_expr));
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
match skip {
|
||||
None => ser,
|
||||
Some(skip) => {
|
||||
match skip {
|
||||
None => ser,
|
||||
Some(skip) => {
|
||||
if let Some(skip_func) = struct_trait.skip_field(span) {
|
||||
quote! {
|
||||
if !#skip {
|
||||
#ser
|
||||
@@ -932,59 +946,73 @@ fn serialize_struct_visitor(
|
||||
try!(#skip_func(&mut __serde_state, #key_expr));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
if !#skip {
|
||||
#ser
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn wrap_serialize_field_with(
|
||||
params: &Parameters,
|
||||
field_ty: &syn::Ty,
|
||||
serialize_with: &syn::Path,
|
||||
field_expr: Tokens,
|
||||
field_ty: &syn::Type,
|
||||
serialize_with: &syn::ExprPath,
|
||||
field_expr: &Tokens,
|
||||
) -> Tokens {
|
||||
wrap_serialize_with(params,
|
||||
serialize_with,
|
||||
&[field_ty],
|
||||
&[quote!(#field_expr)])
|
||||
wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)])
|
||||
}
|
||||
|
||||
fn wrap_serialize_variant_with(
|
||||
params: &Parameters,
|
||||
serialize_with: &syn::Path,
|
||||
serialize_with: &syn::ExprPath,
|
||||
variant: &Variant,
|
||||
) -> Tokens {
|
||||
let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect();
|
||||
let field_exprs: Vec<_> = variant.fields.iter()
|
||||
let field_exprs: Vec<_> = variant
|
||||
.fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, field)| {
|
||||
let id = field.ident.as_ref().map_or_else(|| Ident::new(format!("__field{}", i)),
|
||||
|id| id.clone());
|
||||
let id = field
|
||||
.ident
|
||||
.unwrap_or_else(|| Ident::new(&format!("__field{}", i), Span::def_site()));
|
||||
quote!(#id)
|
||||
})
|
||||
.collect();
|
||||
wrap_serialize_with(params, serialize_with, field_tys.as_slice(), field_exprs.as_slice())
|
||||
wrap_serialize_with(
|
||||
params,
|
||||
serialize_with,
|
||||
field_tys.as_slice(),
|
||||
field_exprs.as_slice(),
|
||||
)
|
||||
}
|
||||
|
||||
fn wrap_serialize_with(
|
||||
params: &Parameters,
|
||||
serialize_with: &syn::Path,
|
||||
field_tys: &[&syn::Ty],
|
||||
serialize_with: &syn::ExprPath,
|
||||
field_tys: &[&syn::Type],
|
||||
field_exprs: &[Tokens],
|
||||
) -> Tokens {
|
||||
let this = ¶ms.this;
|
||||
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
|
||||
let wrapper_generics = if field_exprs.len() == 0 {
|
||||
let wrapper_generics = if field_exprs.is_empty() {
|
||||
params.generics.clone()
|
||||
} else {
|
||||
bound::with_lifetime_bound(¶ms.generics, "'__a")
|
||||
};
|
||||
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
||||
|
||||
let field_access = (0..field_exprs.len()).map(|n| Ident::new(format!("{}", n)));
|
||||
let field_access = (0..field_exprs.len()).map(|n| Member::Unnamed(Index {
|
||||
index: n as u32,
|
||||
span: Span::call_site(),
|
||||
}));
|
||||
|
||||
quote!({
|
||||
struct __SerializeWith #wrapper_impl_generics #where_clause {
|
||||
@@ -1014,23 +1042,23 @@ fn wrap_serialize_with(
|
||||
//
|
||||
// where we want to omit the `mut` to avoid a warning.
|
||||
fn mut_if(is_mut: bool) -> Option<Tokens> {
|
||||
if is_mut { Some(quote!(mut)) } else { None }
|
||||
if is_mut {
|
||||
Some(quote!(mut))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
|
||||
where
|
||||
I: Into<Ident>,
|
||||
{
|
||||
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
|
||||
let self_var = ¶ms.self_var;
|
||||
match (params.is_remote, field.attrs.getter()) {
|
||||
(false, None) => {
|
||||
let ident = ident.into();
|
||||
quote!(&#self_var.#ident)
|
||||
quote_spanned!(Span::call_site()=> &#self_var.#member)
|
||||
}
|
||||
(true, None) => {
|
||||
let inner = quote_spanned!(Span::call_site()=> &#self_var.#member);
|
||||
let ty = field.ty;
|
||||
let ident = ident.into();
|
||||
quote!(_serde::private::ser::constrain::<#ty>(&#self_var.#ident))
|
||||
quote!(_serde::private::ser::constrain::<#ty>(#inner))
|
||||
}
|
||||
(true, Some(getter)) => {
|
||||
let ty = field.ty;
|
||||
@@ -1041,3 +1069,59 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum StructTrait {
|
||||
SerializeMap,
|
||||
SerializeStruct,
|
||||
SerializeStructVariant,
|
||||
}
|
||||
|
||||
impl StructTrait {
|
||||
fn serialize_field(&self, span: Span) -> Tokens {
|
||||
match *self {
|
||||
StructTrait::SerializeMap => {
|
||||
quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry)
|
||||
}
|
||||
StructTrait::SerializeStruct => {
|
||||
quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
|
||||
}
|
||||
StructTrait::SerializeStructVariant => {
|
||||
quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn skip_field(&self, span: Span) -> Option<Tokens> {
|
||||
match *self {
|
||||
StructTrait::SerializeMap => None,
|
||||
StructTrait::SerializeStruct => Some({
|
||||
quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field)
|
||||
}),
|
||||
StructTrait::SerializeStructVariant => Some({
|
||||
quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum TupleTrait {
|
||||
SerializeTuple,
|
||||
SerializeTupleStruct,
|
||||
SerializeTupleVariant,
|
||||
}
|
||||
|
||||
impl TupleTrait {
|
||||
fn serialize_element(&self, span: Span) -> Tokens {
|
||||
match *self {
|
||||
TupleTrait::SerializeTuple => {
|
||||
quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element)
|
||||
}
|
||||
TupleTrait::SerializeTupleStruct => {
|
||||
quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field)
|
||||
}
|
||||
TupleTrait::SerializeTupleVariant => {
|
||||
quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.17.0" # remember to update html_root_url
|
||||
version = "0.22.1" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "AST representation used by Serde derive macros. Unstable."
|
||||
@@ -12,8 +12,8 @@ readme = "README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
|
||||
synom = "0.11"
|
||||
proc-macro2 = "0.2"
|
||||
syn = { version = "0.12", default-features = false, features = ["derive", "parsing", "clone-impls"] }
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "serde-rs/serde" }
|
||||
|
||||
@@ -10,15 +10,16 @@ use syn;
|
||||
use attr;
|
||||
use check;
|
||||
use Ctxt;
|
||||
use syn::punctuated::Punctuated;
|
||||
|
||||
pub struct Container<'a> {
|
||||
pub ident: syn::Ident,
|
||||
pub attrs: attr::Container,
|
||||
pub body: Body<'a>,
|
||||
pub data: Data<'a>,
|
||||
pub generics: &'a syn::Generics,
|
||||
}
|
||||
|
||||
pub enum Body<'a> {
|
||||
pub enum Data<'a> {
|
||||
Enum(Vec<Variant<'a>>),
|
||||
Struct(Style, Vec<Field<'a>>),
|
||||
}
|
||||
@@ -33,7 +34,8 @@ pub struct Variant<'a> {
|
||||
pub struct Field<'a> {
|
||||
pub ident: Option<syn::Ident>,
|
||||
pub attrs: attr::Field,
|
||||
pub ty: &'a syn::Ty,
|
||||
pub ty: &'a syn::Type,
|
||||
pub original: &'a syn::Field,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@@ -46,36 +48,45 @@ pub enum Style {
|
||||
|
||||
impl<'a> Container<'a> {
|
||||
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> Container<'a> {
|
||||
let attrs = attr::Container::from_ast(cx, item);
|
||||
let mut attrs = attr::Container::from_ast(cx, item);
|
||||
|
||||
let mut body = match item.body {
|
||||
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
|
||||
syn::Body::Struct(ref variant_data) => {
|
||||
let (style, fields) = struct_from_ast(cx, variant_data, None);
|
||||
Body::Struct(style, fields)
|
||||
let mut data = match item.data {
|
||||
syn::Data::Enum(ref data) => {
|
||||
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
|
||||
}
|
||||
syn::Data::Struct(ref data) => {
|
||||
let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
|
||||
Data::Struct(style, fields)
|
||||
}
|
||||
syn::Data::Union(_) => {
|
||||
panic!("Serde does not support derive for unions");
|
||||
}
|
||||
};
|
||||
|
||||
match body {
|
||||
Body::Enum(ref mut variants) => {
|
||||
for ref mut variant in variants {
|
||||
variant.attrs.rename_by_rule(attrs.rename_all());
|
||||
for ref mut field in &mut variant.fields {
|
||||
field.attrs.rename_by_rule(variant.attrs.rename_all());
|
||||
}
|
||||
let mut has_flatten = false;
|
||||
match data {
|
||||
Data::Enum(ref mut variants) => for variant in variants {
|
||||
variant.attrs.rename_by_rule(attrs.rename_all());
|
||||
for field in &mut variant.fields {
|
||||
field.attrs.rename_by_rule(variant.attrs.rename_all());
|
||||
}
|
||||
}
|
||||
Body::Struct(_, ref mut fields) => {
|
||||
for field in fields {
|
||||
field.attrs.rename_by_rule(attrs.rename_all());
|
||||
},
|
||||
Data::Struct(_, ref mut fields) => for field in fields {
|
||||
if field.attrs.flatten() {
|
||||
has_flatten = true;
|
||||
}
|
||||
}
|
||||
field.attrs.rename_by_rule(attrs.rename_all());
|
||||
},
|
||||
}
|
||||
|
||||
if has_flatten {
|
||||
attrs.mark_has_flatten();
|
||||
}
|
||||
|
||||
let item = Container {
|
||||
ident: item.ident.clone(),
|
||||
ident: item.ident,
|
||||
attrs: attrs,
|
||||
body: body,
|
||||
data: data,
|
||||
generics: &item.generics,
|
||||
};
|
||||
check::check(cx, &item);
|
||||
@@ -83,13 +94,13 @@ impl<'a> Container<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Body<'a> {
|
||||
impl<'a> Data<'a> {
|
||||
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
|
||||
match *self {
|
||||
Body::Enum(ref variants) => {
|
||||
Data::Enum(ref variants) => {
|
||||
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
|
||||
}
|
||||
Body::Struct(_, ref fields) => Box::new(fields.iter()),
|
||||
Data::Struct(_, ref fields) => Box::new(fields.iter()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,47 +109,64 @@ 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 Punctuated<syn::Variant, Token![,]>,
|
||||
container_default: &attr::Default,
|
||||
) -> Vec<Variant<'a>> {
|
||||
variants
|
||||
.iter()
|
||||
.map(
|
||||
|variant| {
|
||||
let attrs = attr::Variant::from_ast(cx, variant);
|
||||
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
|
||||
Variant {
|
||||
ident: variant.ident.clone(),
|
||||
attrs: attrs,
|
||||
style: style,
|
||||
fields: fields,
|
||||
}
|
||||
},
|
||||
)
|
||||
.map(|variant| {
|
||||
let attrs = attr::Variant::from_ast(cx, variant);
|
||||
let (style, fields) =
|
||||
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
|
||||
Variant {
|
||||
ident: variant.ident,
|
||||
attrs: attrs,
|
||||
style: style,
|
||||
fields: fields,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
|
||||
match *data {
|
||||
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
|
||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
||||
(Style::Newtype, fields_from_ast(cx, fields, attrs))
|
||||
}
|
||||
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
|
||||
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
||||
fn struct_from_ast<'a>(
|
||||
cx: &Ctxt,
|
||||
fields: &'a syn::Fields,
|
||||
attrs: Option<&attr::Variant>,
|
||||
container_default: &attr::Default,
|
||||
) -> (Style, Vec<Field<'a>>) {
|
||||
match *fields {
|
||||
syn::Fields::Named(ref fields) => (
|
||||
Style::Struct,
|
||||
fields_from_ast(cx, &fields.named, attrs, container_default),
|
||||
),
|
||||
syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
|
||||
Style::Newtype,
|
||||
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
|
||||
),
|
||||
syn::Fields::Unnamed(ref fields) => (
|
||||
Style::Tuple,
|
||||
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
|
||||
),
|
||||
syn::Fields::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 Punctuated<syn::Field, Token![,]>,
|
||||
attrs: Option<&attr::Variant>,
|
||||
container_default: &attr::Default,
|
||||
) -> Vec<Field<'a>> {
|
||||
fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(
|
||||
|(i, field)| {
|
||||
Field {
|
||||
ident: field.ident.clone(),
|
||||
attrs: attr::Field::from_ast(cx, i, field, attrs),
|
||||
ty: &field.ty,
|
||||
}
|
||||
},
|
||||
)
|
||||
.map(|(i, field)| Field {
|
||||
ident: field.ident,
|
||||
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
|
||||
ty: &field.ty,
|
||||
original: field,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
+502
-355
File diff suppressed because it is too large
Load Diff
@@ -7,19 +7,21 @@
|
||||
// except according to those terms.
|
||||
|
||||
// See https://users.rust-lang.org/t/psa-dealing-with-warning-unused-import-std-ascii-asciiext-in-today-s-nightly/13726
|
||||
#[allow(unused_imports)]
|
||||
#[allow(deprecated, unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use self::RenameRule::*;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(PartialEq)]
|
||||
pub enum RenameRule {
|
||||
/// Don't apply a default rename rule.
|
||||
None,
|
||||
/// Rename direct children to "lowercase" style.
|
||||
LowerCase,
|
||||
/// Rename direct children to "UPPERCASE" style.
|
||||
UPPERCASE,
|
||||
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
|
||||
PascalCase,
|
||||
/// Rename direct children to "camelCase" style.
|
||||
@@ -31,7 +33,7 @@ pub enum RenameRule {
|
||||
/// Rename direct children to "kebab-case" style.
|
||||
KebabCase,
|
||||
/// Rename direct children to "SCREAMING-KEBAB-CASE" style.
|
||||
ScreamingKebabCase
|
||||
ScreamingKebabCase,
|
||||
}
|
||||
|
||||
impl RenameRule {
|
||||
@@ -39,6 +41,7 @@ impl RenameRule {
|
||||
match *self {
|
||||
None | PascalCase => variant.to_owned(),
|
||||
LowerCase => variant.to_ascii_lowercase(),
|
||||
UPPERCASE => variant.to_ascii_uppercase(),
|
||||
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
|
||||
SnakeCase => {
|
||||
let mut snake = String::new();
|
||||
@@ -52,13 +55,16 @@ impl RenameRule {
|
||||
}
|
||||
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
|
||||
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
|
||||
ScreamingKebabCase => ScreamingSnakeCase.apply_to_variant(variant).replace('_', "-")
|
||||
ScreamingKebabCase => ScreamingSnakeCase
|
||||
.apply_to_variant(variant)
|
||||
.replace('_', "-"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_to_field(&self, field: &str) -> String {
|
||||
match *self {
|
||||
None | LowerCase | SnakeCase => field.to_owned(),
|
||||
UPPERCASE => field.to_ascii_uppercase(),
|
||||
PascalCase => {
|
||||
let mut pascal = String::new();
|
||||
let mut capitalize = true;
|
||||
@@ -80,7 +86,7 @@ impl RenameRule {
|
||||
}
|
||||
ScreamingSnakeCase => field.to_ascii_uppercase(),
|
||||
KebabCase => field.replace('_', "-"),
|
||||
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-")
|
||||
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,6 +97,7 @@ impl FromStr for RenameRule {
|
||||
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
|
||||
match rename_all_str {
|
||||
"lowercase" => Ok(LowerCase),
|
||||
"UPPERCASE" => Ok(UPPERCASE),
|
||||
"PascalCase" => Ok(PascalCase),
|
||||
"camelCase" => Ok(CamelCase),
|
||||
"snake_case" => Ok(SnakeCase),
|
||||
@@ -104,34 +111,71 @@ impl FromStr for RenameRule {
|
||||
|
||||
#[test]
|
||||
fn rename_variants() {
|
||||
for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in
|
||||
&[
|
||||
("Outcome", "outcome", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
|
||||
("VeryTasty", "verytasty", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
|
||||
("A", "a", "a", "a", "A", "a", "A"),
|
||||
("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
|
||||
] {
|
||||
for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[
|
||||
(
|
||||
"Outcome",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
"outcome",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
),
|
||||
(
|
||||
"VeryTasty",
|
||||
"verytasty",
|
||||
"VERYTASTY",
|
||||
"veryTasty",
|
||||
"very_tasty",
|
||||
"VERY_TASTY",
|
||||
"very-tasty",
|
||||
"VERY-TASTY",
|
||||
),
|
||||
("A", "a", "A", "a", "a", "A", "a", "A"),
|
||||
("Z42", "z42", "Z42", "z42", "z42", "Z42", "z42", "Z42"),
|
||||
] {
|
||||
assert_eq!(None.apply_to_variant(original), original);
|
||||
assert_eq!(LowerCase.apply_to_variant(original), lower);
|
||||
assert_eq!(UPPERCASE.apply_to_variant(original), upper);
|
||||
assert_eq!(PascalCase.apply_to_variant(original), original);
|
||||
assert_eq!(CamelCase.apply_to_variant(original), camel);
|
||||
assert_eq!(SnakeCase.apply_to_variant(original), snake);
|
||||
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
|
||||
assert_eq!(KebabCase.apply_to_variant(original), kebab);
|
||||
assert_eq!(ScreamingKebabCase.apply_to_variant(original), screaming_kebab);
|
||||
assert_eq!(
|
||||
ScreamingKebabCase.apply_to_variant(original),
|
||||
screaming_kebab
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rename_fields() {
|
||||
for &(original, pascal, camel, screaming, kebab, screaming_kebab) in
|
||||
&[
|
||||
("outcome", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
|
||||
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
|
||||
("a", "A", "a", "A", "a", "A"),
|
||||
("z42", "Z42", "z42", "Z42", "z42", "Z42"),
|
||||
] {
|
||||
for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[
|
||||
(
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
"Outcome",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
),
|
||||
(
|
||||
"very_tasty",
|
||||
"VERY_TASTY",
|
||||
"VeryTasty",
|
||||
"veryTasty",
|
||||
"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_field(original), original);
|
||||
assert_eq!(UPPERCASE.apply_to_field(original), upper);
|
||||
assert_eq!(PascalCase.apply_to_field(original), pascal);
|
||||
assert_eq!(CamelCase.apply_to_field(original), camel);
|
||||
assert_eq!(SnakeCase.apply_to_field(original), original);
|
||||
|
||||
@@ -6,38 +6,73 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ast::{Body, Container, Style};
|
||||
use attr::Identifier;
|
||||
use ast::{Data, Container, Style};
|
||||
use attr::{Identifier, EnumTag};
|
||||
use Ctxt;
|
||||
|
||||
/// Cross-cutting checks that require looking at more than a single attrs
|
||||
/// object. Simpler checks should happen when parsing and building the attrs.
|
||||
pub fn check(cx: &Ctxt, cont: &Container) {
|
||||
check_getter(cx, cont);
|
||||
check_flatten(cx, cont);
|
||||
check_identifier(cx, cont);
|
||||
check_variant_skip_attrs(cx, cont);
|
||||
check_internal_tag_field_name_conflict(cx, cont);
|
||||
check_adjacent_tag_conflict(cx, cont);
|
||||
}
|
||||
|
||||
/// Getters are only allowed inside structs (not enums) with the `remote`
|
||||
/// attribute.
|
||||
fn check_getter(cx: &Ctxt, cont: &Container) {
|
||||
match cont.body {
|
||||
Body::Enum(_) => {
|
||||
if cont.body.has_getter() {
|
||||
match cont.data {
|
||||
Data::Enum(_) => {
|
||||
if cont.data.has_getter() {
|
||||
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
|
||||
}
|
||||
}
|
||||
Body::Struct(_, _) => {
|
||||
if cont.body.has_getter() && cont.attrs.remote().is_none() {
|
||||
Data::Struct(_, _) => {
|
||||
if cont.data.has_getter() && cont.attrs.remote().is_none() {
|
||||
cx.error(
|
||||
"#[serde(getter = \"...\")] can only be used in structs \
|
||||
that have #[serde(remote = \"...\")]",
|
||||
that have #[serde(remote = \"...\")]",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Flattening has some restrictions we can test.
|
||||
fn check_flatten(cx: &Ctxt, cont: &Container) {
|
||||
match cont.data {
|
||||
Data::Enum(_) => {
|
||||
assert!(!cont.attrs.has_flatten());
|
||||
}
|
||||
Data::Struct(_, _) => {
|
||||
for field in cont.data.all_fields() {
|
||||
if !field.attrs.flatten() {
|
||||
continue;
|
||||
}
|
||||
if field.attrs.skip_serializing() {
|
||||
cx.error(
|
||||
"#[serde(flatten] can not be combined with \
|
||||
#[serde(skip_serializing)]"
|
||||
);
|
||||
} else if field.attrs.skip_serializing_if().is_some() {
|
||||
cx.error(
|
||||
"#[serde(flatten] can not be combined with \
|
||||
#[serde(skip_serializing_if = \"...\")]"
|
||||
);
|
||||
} else if field.attrs.skip_deserializing() {
|
||||
cx.error(
|
||||
"#[serde(flatten] can not be combined with \
|
||||
#[serde(skip_deserializing)]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The `other` attribute must be used at most once and it must be the last
|
||||
/// variant of an enum that has the `field_identifier` attribute.
|
||||
///
|
||||
@@ -45,18 +80,21 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
|
||||
/// `field_identifier` all but possibly one variant must be unit variants. The
|
||||
/// last variant may be a newtype variant which is an implicit "other" case.
|
||||
fn check_identifier(cx: &Ctxt, cont: &Container) {
|
||||
let variants = match cont.body {
|
||||
Body::Enum(ref variants) => variants,
|
||||
Body::Struct(_, _) => {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Struct(_, _) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
for (i, variant) in variants.iter().enumerate() {
|
||||
match (variant.style, cont.attrs.identifier(), variant.attrs.other()) {
|
||||
match (
|
||||
variant.style,
|
||||
cont.attrs.identifier(),
|
||||
variant.attrs.other(),
|
||||
) {
|
||||
// The `other` attribute may only be used in a field_identifier.
|
||||
(_, Identifier::Variant, true) |
|
||||
(_, Identifier::No, true) => {
|
||||
(_, Identifier::Variant, true) | (_, Identifier::No, true) => {
|
||||
cx.error("#[serde(other)] may only be used inside a field_identifier");
|
||||
}
|
||||
|
||||
@@ -99,9 +137,9 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
|
||||
/// Skip-(de)serializing attributes are not allowed on variants marked
|
||||
/// (de)serialize_with.
|
||||
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
||||
let variants = match cont.body {
|
||||
Body::Enum(ref variants) => variants,
|
||||
Body::Struct(_, _) => {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Struct(_, _) => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -109,44 +147,124 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
||||
for variant in variants.iter() {
|
||||
if variant.attrs.serialize_with().is_some() {
|
||||
if variant.attrs.skip_serializing() {
|
||||
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||
#[serde(skip_serializing)]", variant.ident));
|
||||
cx.error(format!(
|
||||
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||
#[serde(skip_serializing)]",
|
||||
variant.ident
|
||||
));
|
||||
}
|
||||
|
||||
for (i, field) in variant.fields.iter().enumerate() {
|
||||
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|
||||
|ident| format!("`{}`", ident));
|
||||
let ident = field
|
||||
.ident
|
||||
.as_ref()
|
||||
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
|
||||
|
||||
if field.attrs.skip_serializing() {
|
||||
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||
a field {} marked with #[serde(skip_serializing)]",
|
||||
variant.ident, ident));
|
||||
cx.error(format!(
|
||||
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||
a field {} marked with #[serde(skip_serializing)]",
|
||||
variant.ident, ident
|
||||
));
|
||||
}
|
||||
|
||||
if field.attrs.skip_serializing_if().is_some() {
|
||||
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||
a field {} marked with #[serde(skip_serializing_if)]",
|
||||
variant.ident, ident));
|
||||
cx.error(format!(
|
||||
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||
a field {} marked with #[serde(skip_serializing_if)]",
|
||||
variant.ident, ident
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if variant.attrs.deserialize_with().is_some() {
|
||||
if variant.attrs.skip_deserializing() {
|
||||
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] and \
|
||||
#[serde(skip_deserializing)]", variant.ident));
|
||||
cx.error(format!(
|
||||
"variant `{}` cannot have both #[serde(deserialize_with)] and \
|
||||
#[serde(skip_deserializing)]",
|
||||
variant.ident
|
||||
));
|
||||
}
|
||||
|
||||
for (i, field) in variant.fields.iter().enumerate() {
|
||||
if field.attrs.skip_deserializing() {
|
||||
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|
||||
|ident| format!("`{}`", ident));
|
||||
let ident = field
|
||||
.ident
|
||||
.as_ref()
|
||||
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
|
||||
|
||||
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] \
|
||||
and a field {} marked with #[serde(skip_deserializing)]",
|
||||
variant.ident, ident));
|
||||
cx.error(format!(
|
||||
"variant `{}` cannot have both #[serde(deserialize_with)] \
|
||||
and a field {} marked with #[serde(skip_deserializing)]",
|
||||
variant.ident, ident
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The tag of an internally-tagged struct variant must not be
|
||||
/// the same as either one of its fields, as this would result in
|
||||
/// duplicate keys in the serialized output and/or ambiguity in
|
||||
/// the to-be-deserialized input.
|
||||
fn check_internal_tag_field_name_conflict(
|
||||
cx: &Ctxt,
|
||||
cont: &Container,
|
||||
) {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Struct(_, _) => return,
|
||||
};
|
||||
|
||||
let tag = match *cont.attrs.tag() {
|
||||
EnumTag::Internal { ref tag } => tag.as_str(),
|
||||
EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
|
||||
};
|
||||
|
||||
let diagnose_conflict = || {
|
||||
let message = format!(
|
||||
"variant field name `{}` conflicts with internal tag",
|
||||
tag
|
||||
);
|
||||
cx.error(message);
|
||||
};
|
||||
|
||||
for variant in variants {
|
||||
match variant.style {
|
||||
Style::Struct => {
|
||||
for field in &variant.fields {
|
||||
let check_ser = !field.attrs.skip_serializing();
|
||||
let check_de = !field.attrs.skip_deserializing();
|
||||
let name = field.attrs.name();
|
||||
let ser_name = name.serialize_name();
|
||||
let de_name = name.deserialize_name();
|
||||
|
||||
if check_ser && ser_name == tag || check_de && de_name == tag {
|
||||
diagnose_conflict();
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
Style::Unit | Style::Newtype | Style::Tuple => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// In the case of adjacently-tagged enums, the type and the
|
||||
/// contents tag must differ, for the same reason.
|
||||
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
|
||||
let (type_tag, content_tag) = match *cont.attrs.tag() {
|
||||
EnumTag::Adjacent { ref tag, ref content } => (tag, content),
|
||||
EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return,
|
||||
};
|
||||
|
||||
if type_tag == content_tag {
|
||||
let message = format!(
|
||||
"enum tags `{}` for type and content conflict with each other",
|
||||
type_tag
|
||||
);
|
||||
cx.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::cell::RefCell;
|
||||
use std::thread;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Ctxt {
|
||||
@@ -16,7 +17,9 @@ pub struct Ctxt {
|
||||
|
||||
impl Ctxt {
|
||||
pub fn new() -> Self {
|
||||
Ctxt { errors: RefCell::new(Some(Vec::new())) }
|
||||
Ctxt {
|
||||
errors: RefCell::new(Some(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error<T: Display>(&self, msg: T) {
|
||||
@@ -46,7 +49,7 @@ impl Ctxt {
|
||||
|
||||
impl Drop for Ctxt {
|
||||
fn drop(&mut self) {
|
||||
if self.errors.borrow().is_some() {
|
||||
if !thread::panicking() && self.errors.borrow().is_some() {
|
||||
panic!("forgot to check for errors");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.17.0")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.22.1")]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity, doc_markdown, match_same_arms,
|
||||
redundant_field_names))]
|
||||
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate synom;
|
||||
extern crate syn;
|
||||
|
||||
extern crate proc_macro2;
|
||||
|
||||
pub mod ast;
|
||||
pub mod attr;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.23" # remember to update html_root_url
|
||||
version = "1.0.35" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||
|
||||
@@ -184,11 +184,27 @@ where
|
||||
T: Deserialize<'de> + PartialEq + Debug,
|
||||
{
|
||||
let mut de = Deserializer::new(tokens);
|
||||
match T::deserialize(&mut de) {
|
||||
Ok(v) => assert_eq!(v, *value),
|
||||
let mut deserialized_val = match T::deserialize(&mut de) {
|
||||
Ok(v) => {
|
||||
assert_eq!(v, *value);
|
||||
v
|
||||
}
|
||||
Err(e) => panic!("tokens failed to deserialize: {}", e),
|
||||
};
|
||||
if de.remaining() > 0 {
|
||||
panic!("{} remaining tokens", de.remaining());
|
||||
}
|
||||
|
||||
// Do the same thing for deserialize_in_place. This isn't *great* because a
|
||||
// no-op impl of deserialize_in_place can technically succeed here. Still,
|
||||
// this should catch a lot of junk.
|
||||
let mut de = Deserializer::new(tokens);
|
||||
match T::deserialize_in_place(&mut de, &mut deserialized_val) {
|
||||
Ok(()) => {
|
||||
assert_eq!(deserialized_val, *value);
|
||||
}
|
||||
Err(e) => panic!("tokens failed to deserialize_in_place: {}", e),
|
||||
}
|
||||
if de.remaining() > 0 {
|
||||
panic!("{} remaining tokens", de.remaining());
|
||||
}
|
||||
|
||||
+15
-12
@@ -11,17 +11,17 @@ pub struct Compact<T: ?Sized>(T);
|
||||
|
||||
/// Trait to determine whether a value is represented in human-readable or
|
||||
/// compact form.
|
||||
///
|
||||
///
|
||||
/// ```
|
||||
/// extern crate serde;
|
||||
/// extern crate serde_test;
|
||||
///
|
||||
///
|
||||
/// use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
/// use serde_test::{Configure, Token, assert_tokens};
|
||||
///
|
||||
///
|
||||
/// #[derive(Debug, PartialEq)]
|
||||
/// struct Example(u8, u8);
|
||||
///
|
||||
///
|
||||
/// impl Serialize for Example {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer,
|
||||
@@ -33,7 +33,7 @@ pub struct Compact<T: ?Sized>(T);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// impl<'de> Deserialize<'de> for Example {
|
||||
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
/// where D: Deserializer<'de>,
|
||||
@@ -52,7 +52,7 @@ pub struct Compact<T: ?Sized>(T);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// fn main() {
|
||||
/// assert_tokens(
|
||||
/// &Example(1, 0).compact(),
|
||||
@@ -73,11 +73,17 @@ pub struct Compact<T: ?Sized>(T);
|
||||
/// ```
|
||||
pub trait Configure {
|
||||
/// Marks `self` as using `is_human_readable == true`
|
||||
fn readable(self) -> Readable<Self> where Self: Sized {
|
||||
fn readable(self) -> Readable<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Readable(self)
|
||||
}
|
||||
/// Marks `self` as using `is_human_readable == false`
|
||||
fn compact(self) -> Compact<Self> where Self: Sized {
|
||||
fn compact(self) -> Compact<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Compact(self)
|
||||
}
|
||||
}
|
||||
@@ -158,7 +164,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
macro_rules! forward_method {
|
||||
($name: ident (self $(, $arg: ident : $arg_type: ty)* ) -> $return_type: ty) => {
|
||||
fn $name (self $(, $arg : $arg_type)* ) -> $return_type {
|
||||
@@ -455,8 +460,7 @@ macro_rules! impl_serializer {
|
||||
impl_serializer!(Readable, true);
|
||||
impl_serializer!(Compact, false);
|
||||
|
||||
|
||||
use serde::de::{Visitor, EnumAccess, VariantAccess, MapAccess, DeserializeSeed, SeqAccess, Error};
|
||||
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
|
||||
|
||||
macro_rules! forward_deserialize_methods {
|
||||
( $wrapper : ident ( $( $name: ident ),* ) ) => {
|
||||
@@ -468,7 +472,6 @@ macro_rules! forward_deserialize_methods {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
macro_rules! impl_deserializer {
|
||||
($wrapper : ident, $is_human_readable : expr) => {
|
||||
impl <'de, D> Deserializer<'de> for $wrapper<D> where D: Deserializer<'de> {
|
||||
|
||||
+64
-50
@@ -95,15 +95,11 @@ impl<'de> Deserializer<'de> {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let value = try!(
|
||||
visitor.visit_seq(
|
||||
DeserializerSeqVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
end: end,
|
||||
},
|
||||
)
|
||||
);
|
||||
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
end: end,
|
||||
},));
|
||||
assert_next_token!(self, end);
|
||||
Ok(value)
|
||||
}
|
||||
@@ -117,15 +113,11 @@ impl<'de> Deserializer<'de> {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
let value = try!(
|
||||
visitor.visit_map(
|
||||
DeserializerMapVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
end: end,
|
||||
},
|
||||
)
|
||||
);
|
||||
let value = try!(visitor.visit_map(DeserializerMapVisitor {
|
||||
de: self,
|
||||
len: len,
|
||||
end: end,
|
||||
},));
|
||||
assert_next_token!(self, end);
|
||||
Ok(value)
|
||||
}
|
||||
@@ -169,7 +161,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
|
||||
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
|
||||
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
|
||||
Token::TupleStruct { len, .. } => self.visit_seq(Some(len), Token::TupleStructEnd, visitor),
|
||||
Token::TupleStruct { len, .. } => {
|
||||
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
||||
}
|
||||
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
|
||||
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
|
||||
Token::Enum { .. } => {
|
||||
@@ -195,17 +189,28 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
}
|
||||
}
|
||||
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
|
||||
Token::NewtypeVariant { variant, .. } => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),)
|
||||
}
|
||||
Token::TupleVariant { variant, .. } => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),)
|
||||
}
|
||||
Token::StructVariant { variant, .. } => {
|
||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),)
|
||||
}
|
||||
Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd |
|
||||
Token::StructEnd | Token::TupleVariantEnd | Token::StructVariantEnd => {
|
||||
Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
||||
self,
|
||||
Token::Str(variant),
|
||||
EnumFormat::Any,
|
||||
)),
|
||||
Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
||||
self,
|
||||
Token::Str(variant),
|
||||
EnumFormat::Seq,
|
||||
)),
|
||||
Token::StructVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
||||
self,
|
||||
Token::Str(variant),
|
||||
EnumFormat::Map,
|
||||
)),
|
||||
Token::SeqEnd
|
||||
| Token::TupleEnd
|
||||
| Token::TupleStructEnd
|
||||
| Token::MapEnd
|
||||
| Token::StructEnd
|
||||
| Token::TupleVariantEnd
|
||||
| Token::StructVariantEnd => {
|
||||
unexpected!(token);
|
||||
}
|
||||
}
|
||||
@@ -216,8 +221,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.peek_token() {
|
||||
Token::Unit |
|
||||
Token::None => {
|
||||
Token::Unit | Token::None => {
|
||||
self.next_token();
|
||||
visitor.visit_none()
|
||||
}
|
||||
@@ -244,10 +248,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
|
||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
||||
}
|
||||
Token::UnitVariant { name: n, .. } |
|
||||
Token::NewtypeVariant { name: n, .. } |
|
||||
Token::TupleVariant { name: n, .. } |
|
||||
Token::StructVariant { name: n, .. } if name == n => {
|
||||
Token::UnitVariant { name: n, .. }
|
||||
| Token::NewtypeVariant { name: n, .. }
|
||||
| Token::TupleVariant { name: n, .. }
|
||||
| Token::StructVariant { name: n, .. } if name == n =>
|
||||
{
|
||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
||||
}
|
||||
_ => {
|
||||
@@ -269,7 +274,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
|
||||
fn deserialize_newtype_struct<V>(
|
||||
self,
|
||||
name: &'static str,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
@@ -287,8 +296,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.peek_token() {
|
||||
Token::Unit |
|
||||
Token::UnitStruct { .. } => {
|
||||
Token::Unit | Token::UnitStruct { .. } => {
|
||||
self.next_token();
|
||||
visitor.visit_unit()
|
||||
}
|
||||
@@ -448,10 +456,10 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
match self.de.peek_token() {
|
||||
Token::UnitVariant { variant: v, .. } |
|
||||
Token::NewtypeVariant { variant: v, .. } |
|
||||
Token::TupleVariant { variant: v, .. } |
|
||||
Token::StructVariant { variant: v, .. } => {
|
||||
Token::UnitVariant { variant: v, .. }
|
||||
| Token::NewtypeVariant { variant: v, .. }
|
||||
| Token::TupleVariant { variant: v, .. }
|
||||
| Token::StructVariant { variant: v, .. } => {
|
||||
let de = v.into_deserializer();
|
||||
let value = try!(seed.deserialize(de));
|
||||
Ok((value, self))
|
||||
@@ -505,7 +513,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
unexpected!(token);
|
||||
}
|
||||
}
|
||||
Token::Seq { len: Some(enum_len) } => {
|
||||
Token::Seq {
|
||||
len: Some(enum_len),
|
||||
} => {
|
||||
let token = self.de.next_token();
|
||||
|
||||
if len == enum_len {
|
||||
@@ -518,7 +528,11 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
}
|
||||
}
|
||||
|
||||
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
|
||||
fn struct_variant<V>(
|
||||
self,
|
||||
fields: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
@@ -533,7 +547,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
||||
unexpected!(token);
|
||||
}
|
||||
}
|
||||
Token::Map { len: Some(enum_len) } => {
|
||||
Token::Map {
|
||||
len: Some(enum_len),
|
||||
} => {
|
||||
let token = self.de.next_token();
|
||||
|
||||
if fields.len() == enum_len {
|
||||
@@ -581,10 +597,8 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
|
||||
{
|
||||
match self.variant.take() {
|
||||
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
||||
Some(Token::Bytes(variant)) => {
|
||||
seed.deserialize(BytesDeserializer { value: variant })
|
||||
.map(Some)
|
||||
}
|
||||
Some(Token::Bytes(variant)) => seed.deserialize(BytesDeserializer { value: variant })
|
||||
.map(Some),
|
||||
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
||||
Some(other) => unexpected!(other),
|
||||
None => Ok(None),
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
use std::error;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use serde::{ser, de};
|
||||
use serde::{de, ser};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Error {
|
||||
@@ -18,13 +18,17 @@ pub struct Error {
|
||||
|
||||
impl ser::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error { msg: msg.to_string() }
|
||||
Error {
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl de::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error { msg: msg.to_string() }
|
||||
Error {
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
|
||||
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
|
||||
//! #
|
||||
//! # // Dumb immitation of LinkedHashMap.
|
||||
//! # // Dumb imitation of LinkedHashMap.
|
||||
//! # #[derive(PartialEq, Debug)]
|
||||
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
|
||||
//! #
|
||||
@@ -155,18 +155,14 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.23")]
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.35")]
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// Whitelisted clippy lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
||||
// Whitelisted clippy_pedantic lints
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||
missing_docs_in_private_items,
|
||||
stutter,
|
||||
use_debug,
|
||||
use_self,
|
||||
))]
|
||||
#![cfg_attr(feature = "cargo-clippy",
|
||||
allow(empty_line_after_outer_attr, missing_docs_in_private_items,
|
||||
redundant_field_names, stutter, use_debug, use_self))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
+18
-4
@@ -232,7 +232,10 @@ pub enum Token {
|
||||
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]);
|
||||
/// # }
|
||||
/// ```
|
||||
UnitVariant { name: &'static str, variant: &'static str },
|
||||
UnitVariant {
|
||||
name: &'static str,
|
||||
variant: &'static str,
|
||||
},
|
||||
|
||||
/// The header to a serialized newtype struct of the given name.
|
||||
///
|
||||
@@ -286,7 +289,10 @@ pub enum Token {
|
||||
/// ]);
|
||||
/// # }
|
||||
/// ```
|
||||
NewtypeVariant { name: &'static str, variant: &'static str },
|
||||
NewtypeVariant {
|
||||
name: &'static str,
|
||||
variant: &'static str,
|
||||
},
|
||||
|
||||
/// The header to a sequence.
|
||||
///
|
||||
@@ -391,7 +397,11 @@ pub enum Token {
|
||||
/// ]);
|
||||
/// # }
|
||||
/// ```
|
||||
TupleVariant { name: &'static str, variant: &'static str, len: usize },
|
||||
TupleVariant {
|
||||
name: &'static str,
|
||||
variant: &'static str,
|
||||
len: usize,
|
||||
},
|
||||
|
||||
/// An indicator of the end of a tuple variant.
|
||||
TupleVariantEnd,
|
||||
@@ -488,7 +498,11 @@ pub enum Token {
|
||||
/// ]);
|
||||
/// # }
|
||||
/// ```
|
||||
StructVariant { name: &'static str, variant: &'static str, len: usize },
|
||||
StructVariant {
|
||||
name: &'static str,
|
||||
variant: &'static str,
|
||||
len: usize,
|
||||
},
|
||||
|
||||
/// An indicator of the end of a struct variant.
|
||||
StructVariantEnd,
|
||||
|
||||
@@ -9,9 +9,10 @@ unstable = ["serde/unstable", "compiletest_rs"]
|
||||
|
||||
[dev-dependencies]
|
||||
fnv = "1.0"
|
||||
proc-macro2 = "0.2"
|
||||
rustc-serialize = "0.3.16"
|
||||
serde = { path = "../serde", features = ["rc"] }
|
||||
serde_derive = { path = "../serde_derive" }
|
||||
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||
serde_test = { path = "../serde_test" }
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
#[serde(tag = "conflict", content = "conflict")]
|
||||
//~^^ HELP: enum tags `conflict` for type and content conflict with each other
|
||||
enum E {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_deserializing)]
|
||||
struct Foo {
|
||||
#[serde(flatten, skip_deserializing)]
|
||||
other: Other,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Other {
|
||||
x: u32
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_serializing_if = "...")]
|
||||
struct Foo {
|
||||
#[serde(flatten, skip_serializing_if="Option::is_none")]
|
||||
other: Option<Other>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Other {
|
||||
x: u32
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_serializing)]
|
||||
struct Foo {
|
||||
#[serde(flatten, skip_serializing)]
|
||||
other: Other,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Other {
|
||||
x: u32
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
#[serde(tag = "conflict")]
|
||||
//~^^ HELP: variant field name `conflict` conflicts with internal tag
|
||||
enum E {
|
||||
A {
|
||||
#[serde(rename = "conflict")]
|
||||
x: (),
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@ extern crate serde;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
extern crate serde_test;
|
||||
use serde_test::{Token, assert_de_tokens, assert_de_tokens_error};
|
||||
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
@@ -87,18 +87,18 @@ fn test_struct() {
|
||||
|
||||
assert_de_tokens(
|
||||
&Borrowing {
|
||||
bs: "str",
|
||||
bb: b"bytes",
|
||||
},
|
||||
bs: "str",
|
||||
bb: b"bytes",
|
||||
},
|
||||
&[
|
||||
Token::Struct { name: "Borrowing", len: 2 },
|
||||
|
||||
Token::Struct {
|
||||
name: "Borrowing",
|
||||
len: 2,
|
||||
},
|
||||
Token::BorrowedStr("bs"),
|
||||
Token::BorrowedStr("str"),
|
||||
|
||||
Token::BorrowedStr("bb"),
|
||||
Token::BorrowedBytes(b"bytes"),
|
||||
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
@@ -115,14 +115,14 @@ fn test_cow() {
|
||||
}
|
||||
|
||||
let tokens = &[
|
||||
Token::Struct { name: "Cows", len: 2 },
|
||||
|
||||
Token::Struct {
|
||||
name: "Cows",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("copied"),
|
||||
Token::BorrowedStr("copied"),
|
||||
|
||||
Token::Str("borrowed"),
|
||||
Token::BorrowedStr("borrowed"),
|
||||
|
||||
Token::StructEnd,
|
||||
];
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(decimal_literal_representation))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
@@ -49,14 +51,16 @@ struct TupleStruct(i32, i32, i32);
|
||||
struct Struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
#[serde(skip_deserializing)] c: i32,
|
||||
#[serde(skip_deserializing)]
|
||||
c: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct StructDenyUnknown {
|
||||
a: i32,
|
||||
#[serde(skip_deserializing)] b: i32,
|
||||
#[serde(skip_deserializing)]
|
||||
b: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
@@ -77,13 +81,35 @@ impl Default for StructDefault<String> {
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
struct StructSkipAll {
|
||||
#[serde(skip_deserializing)] a: i32,
|
||||
#[serde(skip_deserializing)]
|
||||
a: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(default)]
|
||||
struct StructSkipDefault {
|
||||
#[serde(skip_deserializing)]
|
||||
a: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(default)]
|
||||
struct StructSkipDefaultGeneric<T> {
|
||||
#[serde(skip_deserializing)]
|
||||
t: T,
|
||||
}
|
||||
|
||||
impl Default for StructSkipDefault {
|
||||
fn default() -> Self {
|
||||
StructSkipDefault { a: 16 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct StructSkipAllDenyUnknown {
|
||||
#[serde(skip_deserializing)] a: i32,
|
||||
#[serde(skip_deserializing)]
|
||||
a: i32,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
@@ -94,7 +120,11 @@ enum Enum {
|
||||
Unit,
|
||||
Simple(i32),
|
||||
Seq(i32, i32, i32),
|
||||
Map { a: i32, b: i32, c: i32 },
|
||||
Map {
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
@@ -600,6 +630,12 @@ declare_tests! {
|
||||
Token::StructEnd,
|
||||
],
|
||||
}
|
||||
test_struct_skip_default {
|
||||
StructSkipDefault { a: 16 } => &[
|
||||
Token::Struct { name: "StructSkipDefault", len: 0 },
|
||||
Token::StructEnd,
|
||||
],
|
||||
}
|
||||
test_struct_skip_all_deny_unknown {
|
||||
StructSkipAllDenyUnknown { a: 0 } => &[
|
||||
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
// types involved.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
|
||||
|
||||
#[macro_use]
|
||||
@@ -47,7 +46,7 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct With<T> {
|
||||
t: T,
|
||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
}
|
||||
assert::<With<i32>>();
|
||||
@@ -55,7 +54,7 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct WithTogether<T> {
|
||||
t: T,
|
||||
#[serde(with="both_x")]
|
||||
#[serde(with = "both_x")]
|
||||
x: X,
|
||||
}
|
||||
assert::<WithTogether<i32>>();
|
||||
@@ -64,7 +63,7 @@ fn test_gen() {
|
||||
struct WithRef<'a, T: 'a> {
|
||||
#[serde(skip_deserializing)]
|
||||
t: StdOption<&'a T>,
|
||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
}
|
||||
assert::<WithRef<i32>>();
|
||||
@@ -94,17 +93,17 @@ fn test_gen() {
|
||||
enum EnumWith<T> {
|
||||
Unit,
|
||||
Newtype(
|
||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
||||
X
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X,
|
||||
),
|
||||
Tuple(
|
||||
T,
|
||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
||||
X
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X,
|
||||
),
|
||||
Struct {
|
||||
t: T,
|
||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
},
|
||||
}
|
||||
@@ -124,16 +123,16 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Newtype(
|
||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
||||
X
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X,
|
||||
);
|
||||
assert::<Newtype>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Tuple<T>(
|
||||
T,
|
||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
||||
X
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X,
|
||||
);
|
||||
assert::<Tuple<i32>>();
|
||||
|
||||
@@ -143,7 +142,9 @@ fn test_gen() {
|
||||
left: Box<TreeNode<D>>,
|
||||
right: Box<TreeNode<D>>,
|
||||
},
|
||||
Leaf { data: D },
|
||||
Leaf {
|
||||
data: D,
|
||||
},
|
||||
}
|
||||
assert::<TreeNode<i32>>();
|
||||
|
||||
@@ -188,29 +189,28 @@ fn test_gen() {
|
||||
assert_ser::<OptionStatic>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(bound="D: SerializeWith + DeserializeWith")]
|
||||
#[serde(bound = "D: SerializeWith + DeserializeWith")]
|
||||
struct WithTraits1<D, E> {
|
||||
#[serde(serialize_with="SerializeWith::serialize_with",
|
||||
deserialize_with="DeserializeWith::deserialize_with")]
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
d: D,
|
||||
#[serde(serialize_with="SerializeWith::serialize_with",
|
||||
deserialize_with="DeserializeWith::deserialize_with",
|
||||
bound="E: SerializeWith + DeserializeWith")]
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with",
|
||||
bound = "E: SerializeWith + DeserializeWith")]
|
||||
e: E,
|
||||
}
|
||||
assert::<WithTraits1<X, X>>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(bound(serialize="D: SerializeWith",
|
||||
deserialize="D: DeserializeWith"))]
|
||||
#[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
|
||||
struct WithTraits2<D, E> {
|
||||
#[serde(serialize_with="SerializeWith::serialize_with",
|
||||
deserialize_with="DeserializeWith::deserialize_with")]
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
d: D,
|
||||
#[serde(serialize_with="SerializeWith::serialize_with",
|
||||
bound(serialize="E: SerializeWith"))]
|
||||
#[serde(deserialize_with="DeserializeWith::deserialize_with",
|
||||
bound(deserialize="E: DeserializeWith"))]
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
bound(serialize = "E: SerializeWith"))]
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with",
|
||||
bound(deserialize = "E: DeserializeWith"))]
|
||||
e: E,
|
||||
}
|
||||
assert::<WithTraits2<X, X>>();
|
||||
@@ -272,14 +272,14 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct TupleSkipAll(
|
||||
#[serde(skip_deserializing)]
|
||||
u8
|
||||
u8,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct TupleSkipAllDenyUnknown(
|
||||
#[serde(skip_deserializing)]
|
||||
u8
|
||||
u8,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -307,7 +307,7 @@ fn test_gen() {
|
||||
},
|
||||
TupleSkip(
|
||||
#[serde(skip_deserializing)]
|
||||
u8
|
||||
u8,
|
||||
),
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ fn test_gen() {
|
||||
},
|
||||
TupleSkip(
|
||||
#[serde(skip_deserializing)]
|
||||
u8
|
||||
u8,
|
||||
),
|
||||
}
|
||||
|
||||
@@ -403,10 +403,7 @@ fn test_gen() {
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
Struct { f1: String, f2: u8 },
|
||||
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||
@@ -429,10 +426,7 @@ fn test_gen() {
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
Struct { f1: String, f2: u8 },
|
||||
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||
@@ -460,10 +454,7 @@ fn test_gen() {
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
Struct { f1: String, f2: u8 },
|
||||
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||
@@ -491,10 +482,7 @@ fn test_gen() {
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
Struct {
|
||||
f1: String,
|
||||
f2: u8,
|
||||
},
|
||||
Struct { f1: String, f2: u8 },
|
||||
|
||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||
@@ -517,10 +505,7 @@ fn test_gen() {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum StaticStrEnum<'a> {
|
||||
Struct {
|
||||
a: &'a str,
|
||||
b: &'static str,
|
||||
},
|
||||
Struct { a: &'a str, b: &'static str },
|
||||
Tuple(&'a str, &'static str),
|
||||
Newtype(&'static str),
|
||||
}
|
||||
@@ -543,6 +528,13 @@ fn test_gen() {
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
assert::<TypeMacro<X>>();
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct BigArray {
|
||||
#[serde(serialize_with = "<[_]>::serialize")]
|
||||
array: [u8; 256],
|
||||
}
|
||||
assert_ser::<BigArray>();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -570,7 +562,7 @@ pub fn de_x<'de, D: Deserializer<'de>>(_: D) -> StdResult<X, D::Error> {
|
||||
}
|
||||
|
||||
mod both_x {
|
||||
pub use super::{ser_x as serialize, de_x as deserialize};
|
||||
pub use super::{de_x as deserialize, ser_x as serialize};
|
||||
}
|
||||
|
||||
impl SerializeWith for X {
|
||||
@@ -586,27 +578,33 @@ impl DeserializeWith for X {
|
||||
}
|
||||
|
||||
pub fn serialize_some_unit_variant<S>(_: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error>
|
||||
where D: Deserializer<'de>,
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn serialize_some_other_variant<S>(_: &str, _: &u8, _: S) -> StdResult<S::Ok, S::Error>
|
||||
where S: Serializer,
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error>
|
||||
where D: Deserializer<'de>,
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn is_zero(n: &u8) -> bool { *n == 0 }
|
||||
pub fn is_zero(n: &u8) -> bool {
|
||||
*n == 0
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ fn test_unit_fallthrough() {
|
||||
enum F {
|
||||
Aaa,
|
||||
Bbb,
|
||||
#[serde(other)] Other,
|
||||
#[serde(other)]
|
||||
Other,
|
||||
}
|
||||
|
||||
assert_de_tokens(&F::Other, &[Token::Str("x")]);
|
||||
|
||||
+310
-223
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
@@ -85,23 +87,32 @@ mod remote {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Test {
|
||||
#[serde(with = "UnitDef")] unit: remote::Unit,
|
||||
#[serde(with = "UnitDef")]
|
||||
unit: remote::Unit,
|
||||
|
||||
#[serde(with = "PrimitivePrivDef")] primitive_priv: remote::PrimitivePriv,
|
||||
#[serde(with = "PrimitivePrivDef")]
|
||||
primitive_priv: remote::PrimitivePriv,
|
||||
|
||||
#[serde(with = "PrimitivePubDef")] primitive_pub: remote::PrimitivePub,
|
||||
#[serde(with = "PrimitivePubDef")]
|
||||
primitive_pub: remote::PrimitivePub,
|
||||
|
||||
#[serde(with = "NewtypePrivDef")] newtype_priv: remote::NewtypePriv,
|
||||
#[serde(with = "NewtypePrivDef")]
|
||||
newtype_priv: remote::NewtypePriv,
|
||||
|
||||
#[serde(with = "NewtypePubDef")] newtype_pub: remote::NewtypePub,
|
||||
#[serde(with = "NewtypePubDef")]
|
||||
newtype_pub: remote::NewtypePub,
|
||||
|
||||
#[serde(with = "TuplePrivDef")] tuple_priv: remote::TuplePriv,
|
||||
#[serde(with = "TuplePrivDef")]
|
||||
tuple_priv: remote::TuplePriv,
|
||||
|
||||
#[serde(with = "TuplePubDef")] tuple_pub: remote::TuplePub,
|
||||
#[serde(with = "TuplePubDef")]
|
||||
tuple_pub: remote::TuplePub,
|
||||
|
||||
#[serde(with = "StructPrivDef")] struct_priv: remote::StructPriv,
|
||||
#[serde(with = "StructPrivDef")]
|
||||
struct_priv: remote::StructPriv,
|
||||
|
||||
#[serde(with = "StructPubDef")] struct_pub: remote::StructPub,
|
||||
#[serde(with = "StructPubDef")]
|
||||
struct_pub: remote::StructPub,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -110,7 +121,10 @@ struct UnitDef;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::PrimitivePriv")]
|
||||
struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8);
|
||||
struct PrimitivePrivDef(
|
||||
#[serde(getter = "remote::PrimitivePriv::get")]
|
||||
u8,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::PrimitivePub")]
|
||||
@@ -119,28 +133,39 @@ struct PrimitivePubDef(u8);
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::NewtypePriv")]
|
||||
struct NewtypePrivDef(
|
||||
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit,
|
||||
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")]
|
||||
remote::Unit,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::NewtypePub")]
|
||||
struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
|
||||
struct NewtypePubDef(
|
||||
#[serde(with = "UnitDef")]
|
||||
remote::Unit,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::TuplePriv")]
|
||||
struct TuplePrivDef(
|
||||
#[serde(getter = "remote::TuplePriv::first")] u8,
|
||||
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit,
|
||||
#[serde(getter = "remote::TuplePriv::first")]
|
||||
u8,
|
||||
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")]
|
||||
remote::Unit,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::TuplePub")]
|
||||
struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
|
||||
struct TuplePubDef(
|
||||
u8,
|
||||
#[serde(with = "UnitDef")]
|
||||
remote::Unit,
|
||||
);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::StructPriv")]
|
||||
struct StructPrivDef {
|
||||
#[serde(getter = "remote::StructPriv::a")] a: u8,
|
||||
#[serde(getter = "remote::StructPriv::a")]
|
||||
a: u8,
|
||||
|
||||
#[serde(getter = "remote::StructPriv::b")]
|
||||
#[serde(with = "UnitDef")]
|
||||
@@ -150,7 +175,8 @@ struct StructPrivDef {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::StructPub")]
|
||||
struct StructPubDef {
|
||||
#[allow(dead_code)] a: u8,
|
||||
#[allow(dead_code)]
|
||||
a: u8,
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[serde(with = "UnitDef")]
|
||||
|
||||
@@ -30,7 +30,7 @@ fn ip_addr_roundtrip() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn socked_addr_roundtrip() {
|
||||
fn socket_addr_roundtrip() {
|
||||
assert_tokens(
|
||||
&net::SocketAddr::from((*b"1234567890123456", 1234)).compact(),
|
||||
&seq![
|
||||
|
||||
@@ -50,11 +50,21 @@ enum Enum {
|
||||
Unit,
|
||||
One(i32),
|
||||
Seq(i32, i32),
|
||||
Map { a: i32, b: i32 },
|
||||
#[serde(skip_serializing)] SkippedUnit,
|
||||
#[serde(skip_serializing)] SkippedOne(i32),
|
||||
#[serde(skip_serializing)] SkippedSeq(i32, i32),
|
||||
#[serde(skip_serializing)] SkippedMap { _a: i32, _b: i32 },
|
||||
Map {
|
||||
a: i32,
|
||||
b: i32,
|
||||
},
|
||||
#[serde(skip_serializing)]
|
||||
SkippedUnit,
|
||||
#[serde(skip_serializing)]
|
||||
SkippedOne(i32),
|
||||
#[serde(skip_serializing)]
|
||||
SkippedSeq(i32, i32),
|
||||
#[serde(skip_serializing)]
|
||||
SkippedMap {
|
||||
_a: i32,
|
||||
_b: i32,
|
||||
},
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user