mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 07:08:02 +00:00
Compare commits
247 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9c6f0ab62 | |||
| b2b36e1764 | |||
| 4ad140ea70 | |||
| 67777eb585 | |||
| b4e51fcc77 | |||
| be7fe2a5eb | |||
| b4076f4577 | |||
| c4181f46be | |||
| 8c0efc3d77 | |||
| 7e3efaf6c5 | |||
| 12fe42ed45 | |||
| 7cd4f49c76 | |||
| ff9c85d47f | |||
| 0025ef9aba | |||
| 536bdd77a0 | |||
| 6993b983d2 | |||
| 4bfeb05f22 | |||
| 4687c1b52b | |||
| a58abae193 | |||
| 0bc9c729b3 | |||
| dc921892be | |||
| 62557731c3 | |||
| ab62cd3b28 | |||
| 30824e9f61 | |||
| eecc0870fc | |||
| 6475e73b05 | |||
| 697234517d | |||
| 3cd9d071c2 | |||
| 9dc05c36f0 | |||
| 972cc06fed | |||
| 20013464f8 | |||
| 2009b4da5f | |||
| 0b72c86a35 | |||
| 94b857057b | |||
| 979df3427b | |||
| 978d64993e | |||
| 5098609935 | |||
| 6374467f02 | |||
| 1f9fc61b98 | |||
| 3859f58d9b | |||
| aac1c65033 | |||
| d8120e19bc | |||
| ed425b3a6f | |||
| d1297deb36 | |||
| f263e3fcec | |||
| 40479336c1 | |||
| 6ca4dd2c4a | |||
| c04c233838 | |||
| 175c638fdc | |||
| 97eff8e875 | |||
| 47676cdb49 | |||
| 93bddb361e | |||
| adb1c9540d | |||
| 0e1d065402 | |||
| 8c3b52e308 | |||
| 3f0d3453d8 | |||
| b27a27ce22 | |||
| 80c0600657 | |||
| 77f9e63661 | |||
| b78f434086 | |||
| 893c0578dd | |||
| cb2b92f828 | |||
| 47a4ffbd31 | |||
| d82d1707d6 | |||
| 89278996c5 | |||
| ecef937e26 | |||
| bceda5fb18 | |||
| f46a08b04e | |||
| f3cb7c7a32 | |||
| af795e2e54 | |||
| 6aa07fe0d6 | |||
| c455720f81 | |||
| b07a208716 | |||
| df93fab5fa | |||
| 1a972d2105 | |||
| 6d1807bb4a | |||
| b37cf858ce | |||
| 5f8fa33756 | |||
| f3f006f411 | |||
| 607966dcf7 | |||
| 6a8c39b2aa | |||
| 382f3c2771 | |||
| 85ca12a8c3 | |||
| 541f9180cf | |||
| 3c4961c48e | |||
| 184264ee92 | |||
| 6050229e7e | |||
| e1db820c9f | |||
| 0081cc961d | |||
| 9bc05803fe | |||
| 8d113e67d6 | |||
| 6e206ce053 | |||
| 47fc9af472 | |||
| 1651f86d56 | |||
| 1157ac0118 | |||
| 202c10147e | |||
| 9f38ca032e | |||
| 00178ba795 | |||
| 24700ebeb6 | |||
| f06001c086 | |||
| ec773fb7db | |||
| da8b457f66 | |||
| a6e94e7122 | |||
| 629bf7b354 | |||
| 4415d10c61 | |||
| def8d6e8af | |||
| 2e824e9aba | |||
| fd14332729 | |||
| c413775574 | |||
| 5efb22ebee | |||
| 3e535325e1 | |||
| 5653e5b15c | |||
| 8d85860064 | |||
| eed18ffab2 | |||
| f8e1fa8ebc | |||
| 860241aa88 | |||
| 6f6c60867d | |||
| 77376f39ea | |||
| 302fac91a3 | |||
| 9c659d9d86 | |||
| 21698f264a | |||
| ba002e1119 | |||
| 8b44eb8bfc | |||
| d82a0cc5ff | |||
| 801fd1dc19 | |||
| 222779d46c | |||
| b1c1d964e1 | |||
| b77cfb635d | |||
| c42c08a25b | |||
| 48997cbb5b | |||
| d8ccd8809e | |||
| d2b65e0a5d | |||
| 7c04c98e0e | |||
| a2fa4c2570 | |||
| 42430902e2 | |||
| 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 |
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Problem
|
||||
about: Something does not seem right
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Share how Serde could support your use case better
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Documentation
|
||||
about: Certainly there is room for improvement
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Help or discussion
|
||||
about: This is the right place
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ cache: cargo
|
||||
# run builds for all the trains (and more)
|
||||
rust:
|
||||
- 1.13.0
|
||||
- 1.15.0
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# Serde   [![Build Status]][travis] [![Latest Version]][crates.io]
|
||||
# Serde   [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.13+]][rustc]
|
||||
|
||||
[Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master
|
||||
[travis]: https://travis-ci.org/serde-rs/serde
|
||||
[Latest Version]: https://img.shields.io/crates/v/serde.svg
|
||||
[crates.io]: https://crates.io/crates/serde
|
||||
[Rustc Version 1.13+]: https://img.shields.io/badge/rustc-1.13+-lightgray.svg
|
||||
[rustc]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
|
||||
|
||||
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
|
||||
|
||||
|
||||
+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
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
error_on_line_overflow = false
|
||||
same_line_attributes = false
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.26" # remember to update html_root_url
|
||||
version = "1.0.52" # 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"
|
||||
|
||||
+135
-45
@@ -9,33 +9,33 @@
|
||||
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 {
|
||||
($dst:ident, $n:ident) => {
|
||||
if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! int_to_uint {
|
||||
($dst:ident, $n:ident) => (
|
||||
if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
|
||||
($dst:ident, $n:ident) => {
|
||||
if 0 <= $n && $n as u64 <= $dst::max_value() as u64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! uint_to {
|
||||
($dst:ident, $n:ident) => (
|
||||
if $n as u64 <= $dst::MAX as u64 {
|
||||
($dst:ident, $n:ident) => {
|
||||
if $n as u64 <= $dst::max_value() as u64 {
|
||||
Some($n as $dst)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
pub trait FromPrimitive: Sized {
|
||||
@@ -52,54 +52,144 @@ pub trait FromPrimitive: Sized {
|
||||
}
|
||||
|
||||
macro_rules! impl_from_primitive_for_int {
|
||||
($t:ident) => (
|
||||
($t:ident) => {
|
||||
impl FromPrimitive for $t {
|
||||
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!($t, n) }
|
||||
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!($t, n) }
|
||||
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) }
|
||||
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!($t, n) }
|
||||
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!($t, n) }
|
||||
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline]
|
||||
fn from_isize(n: isize) -> Option<Self> {
|
||||
int_to_int!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i8(n: i8) -> Option<Self> {
|
||||
int_to_int!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i16(n: i16) -> Option<Self> {
|
||||
int_to_int!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i32(n: i32) -> Option<Self> {
|
||||
int_to_int!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i64(n: i64) -> Option<Self> {
|
||||
int_to_int!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u8(n: u8) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u16(n: u16) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u32(n: u32) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u64(n: u64) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_from_primitive_for_uint {
|
||||
($t:ident) => (
|
||||
($t:ident) => {
|
||||
impl FromPrimitive for $t {
|
||||
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!($t, n) }
|
||||
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
|
||||
#[inline]
|
||||
fn from_isize(n: isize) -> Option<Self> {
|
||||
int_to_uint!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i8(n: i8) -> Option<Self> {
|
||||
int_to_uint!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i16(n: i16) -> Option<Self> {
|
||||
int_to_uint!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i32(n: i32) -> Option<Self> {
|
||||
int_to_uint!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i64(n: i64) -> Option<Self> {
|
||||
int_to_uint!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u8(n: u8) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u16(n: u16) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u32(n: u32) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u64(n: u64) -> Option<Self> {
|
||||
uint_to!($t, n)
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_from_primitive_for_float {
|
||||
($t:ident) => (
|
||||
($t:ident) => {
|
||||
impl FromPrimitive for $t {
|
||||
#[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) }
|
||||
#[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
|
||||
#[inline]
|
||||
fn from_isize(n: isize) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i8(n: i8) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i16(n: i16) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i32(n: i32) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_i64(n: i64) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_usize(n: usize) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u8(n: u8) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u16(n: u16) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u32(n: u32) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn from_u64(n: u64) -> Option<Self> {
|
||||
Some(n as Self)
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
impl_from_primitive_for_int!(isize);
|
||||
|
||||
@@ -45,7 +45,8 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
||||
/// }
|
||||
///
|
||||
/// impl<'de, T> Visitor<'de> for NthElement<T>
|
||||
/// where T: Deserialize<'de>
|
||||
/// where
|
||||
/// T: Deserialize<'de>,
|
||||
/// {
|
||||
/// type Value = T;
|
||||
///
|
||||
@@ -54,7 +55,8 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
||||
/// }
|
||||
///
|
||||
/// fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
/// where A: SeqAccess<'de>
|
||||
/// where
|
||||
/// A: SeqAccess<'de>,
|
||||
/// {
|
||||
/// // Skip over the first `n` elements.
|
||||
/// for i in 0..self.n {
|
||||
@@ -82,19 +84,22 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
||||
/// }
|
||||
///
|
||||
/// impl<'de, T> DeserializeSeed<'de> for NthElement<T>
|
||||
/// where T: Deserialize<'de>
|
||||
/// where
|
||||
/// T: Deserialize<'de>,
|
||||
/// {
|
||||
/// type Value = T;
|
||||
///
|
||||
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
/// where D: Deserializer<'de>
|
||||
/// where
|
||||
/// D: Deserializer<'de>,
|
||||
/// {
|
||||
/// deserializer.deserialize_seq(self)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
|
||||
/// # where D: Deserializer<'de>
|
||||
/// # where
|
||||
/// # D: Deserializer<'de>,
|
||||
/// # {
|
||||
/// // Deserialize only the sequence element at index 3 from this deserializer.
|
||||
/// // The element at index 3 is required to be a string. Elements before and
|
||||
|
||||
+197
-86
@@ -8,8 +8,9 @@
|
||||
|
||||
use lib::*;
|
||||
|
||||
use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess,
|
||||
Visitor};
|
||||
use de::{
|
||||
Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use de::MapAccess;
|
||||
@@ -31,7 +32,7 @@ impl<'de> Visitor<'de> for UnitVisitor {
|
||||
formatter.write_str("unit")
|
||||
}
|
||||
|
||||
fn visit_unit<E>(self) -> Result<(), E>
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -40,7 +41,7 @@ impl<'de> Visitor<'de> for UnitVisitor {
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for () {
|
||||
fn deserialize<D>(deserializer: D) -> Result<(), D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -59,7 +60,7 @@ impl<'de> Visitor<'de> for BoolVisitor {
|
||||
formatter.write_str("a boolean")
|
||||
}
|
||||
|
||||
fn visit_bool<E>(self, v: bool) -> Result<bool, E>
|
||||
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -68,7 +69,7 @@ impl<'de> Visitor<'de> for BoolVisitor {
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for bool {
|
||||
fn deserialize<D>(deserializer: D) -> Result<bool, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -109,7 +110,7 @@ macro_rules! impl_deserialize_num {
|
||||
($ty:ident, $method:ident, $($visit:ident),*) => {
|
||||
impl<'de> Deserialize<'de> for $ty {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -177,7 +178,7 @@ impl<'de> Visitor<'de> for CharVisitor {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_char<E>(self, v: char) -> Result<char, E>
|
||||
fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -185,7 +186,7 @@ impl<'de> Visitor<'de> for CharVisitor {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_str<E>(self, v: &str) -> Result<char, E>
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -199,7 +200,7 @@ impl<'de> Visitor<'de> for CharVisitor {
|
||||
|
||||
impl<'de> Deserialize<'de> for char {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<char, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -222,21 +223,21 @@ impl<'de> Visitor<'de> for StringVisitor {
|
||||
formatter.write_str("a string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<String, E>
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
Ok(v.to_owned())
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<String, E>
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<String, E>
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -246,7 +247,7 @@ impl<'de> Visitor<'de> for StringVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<String, E>
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -268,7 +269,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
|
||||
formatter.write_str("a string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<(), E>
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -277,7 +278,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<(), E>
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -285,7 +286,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<(), E>
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -299,7 +300,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<(), E>
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -318,7 +319,7 @@ impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de> Deserialize<'de> for String {
|
||||
fn deserialize<D>(deserializer: D) -> Result<String, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -416,7 +417,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
|
||||
formatter.write_str("byte array")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<CString, A::Error>
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -430,28 +431,28 @@ impl<'de> Visitor<'de> for CStringVisitor {
|
||||
CString::new(values).map_err(Error::custom)
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<CString, E>
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
CString::new(v).map_err(Error::custom)
|
||||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<CString, E>
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
CString::new(v).map_err(Error::custom)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<CString, E>
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
CString::new(v).map_err(Error::custom)
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<CString, E>
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -461,7 +462,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de> Deserialize<'de> for CString {
|
||||
fn deserialize<D>(deserializer: D) -> Result<CString, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -470,7 +471,11 @@ impl<'de> Deserialize<'de> for CString {
|
||||
}
|
||||
|
||||
macro_rules! forwarded_impl {
|
||||
(( $($id: ident),* ), $ty: ty, $func: expr) => {
|
||||
(
|
||||
$(#[doc = $doc:tt])*
|
||||
( $($id: ident),* ), $ty: ty, $func: expr
|
||||
) => {
|
||||
$(#[doc = $doc])*
|
||||
impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -502,7 +507,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_unit<E>(self) -> Result<Option<T>, E>
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -510,7 +515,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_none<E>(self) -> Result<Option<T>, E>
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -518,7 +523,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Option<T>, D::Error>
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -530,7 +535,7 @@ impl<'de, T> Deserialize<'de> for Option<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Option<T>, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -560,7 +565,7 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_unit<E>(self) -> Result<PhantomData<T>, E>
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -569,7 +574,7 @@ impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
|
||||
}
|
||||
|
||||
impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -654,7 +659,7 @@ macro_rules! seq_impl {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<A>(mut self, mut $access: A) -> Result<(), A::Error>
|
||||
fn visit_seq<A>(mut self, mut $access: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -766,7 +771,7 @@ impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<A>(self, _: A) -> Result<[T; 0], A::Error>
|
||||
fn visit_seq<A>(self, _: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -776,7 +781,7 @@ impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> {
|
||||
|
||||
// Does not require T: Deserialize<'de>.
|
||||
impl<'de, T> Deserialize<'de> for [T; 0] {
|
||||
fn deserialize<D>(deserializer: D) -> Result<[T; 0], D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -798,7 +803,7 @@ macro_rules! array_impls {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<[T; $len], A::Error>
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -824,7 +829,7 @@ macro_rules! array_impls {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -846,7 +851,7 @@ macro_rules! array_impls {
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<[T; $len], D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -906,7 +911,7 @@ macro_rules! tuple_impls {
|
||||
$(
|
||||
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -923,7 +928,7 @@ macro_rules! tuple_impls {
|
||||
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -957,7 +962,7 @@ macro_rules! tuple_impls {
|
||||
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -1073,7 +1078,7 @@ map_impl!(
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
macro_rules! parse_ip_impl {
|
||||
($ty:ty; $size: expr) => {
|
||||
($ty:ty; $size:expr) => {
|
||||
impl<'de> Deserialize<'de> for $ty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -1087,7 +1092,7 @@ macro_rules! parse_ip_impl {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@@ -1230,7 +1235,7 @@ parse_ip_impl!(net::Ipv6Addr; 16);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
macro_rules! parse_socket_impl {
|
||||
($ty:ty, $new: expr) => {
|
||||
($ty:ty, $new:expr) => {
|
||||
impl<'de> Deserialize<'de> for $ty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -1244,7 +1249,7 @@ macro_rules! parse_socket_impl {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@@ -1272,10 +1277,7 @@ 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
|
||||
ip, port, 0, 0
|
||||
));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1329,14 +1331,14 @@ impl<'de> Visitor<'de> for PathBufVisitor {
|
||||
formatter.write_str("path string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<PathBuf, E>
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
Ok(From::from(v))
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<PathBuf, E>
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1346,7 +1348,7 @@ impl<'de> Visitor<'de> for PathBufVisitor {
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de> Deserialize<'de> for PathBuf {
|
||||
fn deserialize<D>(deserializer: D) -> Result<PathBuf, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1379,7 +1381,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn visit_enum<A>(self, data: A) -> Result<OsString, A::Error>
|
||||
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: EnumAccess<'de>,
|
||||
{
|
||||
@@ -1394,7 +1396,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn visit_enum<A>(self, data: A) -> Result<OsString, A::Error>
|
||||
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: EnumAccess<'de>,
|
||||
{
|
||||
@@ -1412,7 +1414,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
|
||||
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
impl<'de> Deserialize<'de> for OsString {
|
||||
fn deserialize<D>(deserializer: D) -> Result<OsString, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1432,10 +1434,28 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
|
||||
forwarded_impl!((), Box<str>, String::into_boxed_str);
|
||||
|
||||
#[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
forwarded_impl!((T), Arc<T>, Arc::new);
|
||||
forwarded_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
/// Deserializing a data structure containing `Arc` will not attempt to
|
||||
/// deduplicate `Arc` references to the same data. Every deserialized `Arc`
|
||||
/// will end up with a strong count of 1.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
(T), Arc<T>, Arc::new
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
forwarded_impl!((T), Rc<T>, Rc::new);
|
||||
forwarded_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
/// Deserializing a data structure containing `Rc` will not attempt to
|
||||
/// deduplicate `Rc` references to the same data. Every deserialized `Rc`
|
||||
/// will end up with a strong count of 1.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
(T), Rc<T>, Rc::new
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
|
||||
@@ -1444,7 +1464,7 @@ where
|
||||
T::Owned: Deserialize<'de>,
|
||||
{
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<Cow<'a, T>, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1454,9 +1474,51 @@ where
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting
|
||||
/// `Weak<T>` has a reference count of 0 and cannot be upgraded.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
impl<'de, T: ?Sized> Deserialize<'de> for RcWeak<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
try!(Option::<T>::deserialize(deserializer));
|
||||
Ok(RcWeak::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting
|
||||
/// `Weak<T>` has a reference count of 0 and cannot be upgraded.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
impl<'de, T: ?Sized> Deserialize<'de> for ArcWeak<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
try!(Option::<T>::deserialize(deserializer));
|
||||
Ok(ArcWeak::new())
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
macro_rules! box_forwarded_impl {
|
||||
($t:ident) => {
|
||||
(
|
||||
$(#[doc = $doc:tt])*
|
||||
$t:ident
|
||||
) => {
|
||||
$(#[doc = $doc])*
|
||||
impl<'de, T: ?Sized> Deserialize<'de> for $t<T>
|
||||
where
|
||||
Box<T>: Deserialize<'de>,
|
||||
@@ -1468,14 +1530,32 @@ macro_rules! box_forwarded_impl {
|
||||
Box::deserialize(deserializer).map(Into::into)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
box_forwarded_impl!(Rc);
|
||||
box_forwarded_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
/// Deserializing a data structure containing `Rc` will not attempt to
|
||||
/// deduplicate `Rc` references to the same data. Every deserialized `Rc`
|
||||
/// will end up with a strong count of 1.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
Rc
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
box_forwarded_impl!(Arc);
|
||||
box_forwarded_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
/// Deserializing a data structure containing `Arc` will not attempt to
|
||||
/// deduplicate `Arc` references to the same data. Every deserialized `Arc`
|
||||
/// will end up with a strong count of 1.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
Arc
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1483,7 +1563,7 @@ impl<'de, T> Deserialize<'de> for Cell<T>
|
||||
where
|
||||
T: Deserialize<'de> + Copy,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Cell<T>, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1525,7 +1605,7 @@ impl<'de> Deserialize<'de> for Duration {
|
||||
};
|
||||
|
||||
impl<'de> Deserialize<'de> for Field {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1538,7 +1618,7 @@ impl<'de> Deserialize<'de> for Duration {
|
||||
formatter.write_str("`secs` or `nanos`")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E>
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1549,7 +1629,7 @@ impl<'de> Deserialize<'de> for Duration {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1577,7 +1657,7 @@ impl<'de> Deserialize<'de> for Duration {
|
||||
formatter.write_str("struct Duration")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error>
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -1596,7 +1676,7 @@ impl<'de> Deserialize<'de> for Duration {
|
||||
Ok(Duration::new(secs, nanos))
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error>
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
@@ -1650,7 +1730,7 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
};
|
||||
|
||||
impl<'de> Deserialize<'de> for Field {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1663,7 +1743,7 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E>
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1674,7 +1754,7 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1702,7 +1782,7 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
formatter.write_str("struct SystemTime")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Duration, A::Error>
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -1721,7 +1801,7 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
Ok(Duration::new(secs, nanos))
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Duration, A::Error>
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
@@ -1794,7 +1874,7 @@ where
|
||||
};
|
||||
|
||||
impl<'de> Deserialize<'de> for Field {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1807,7 +1887,7 @@ where
|
||||
formatter.write_str("`start` or `end`")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E>
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1818,7 +1898,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1851,7 +1931,7 @@ where
|
||||
formatter.write_str("struct Range")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<ops::Range<Idx>, A::Error>
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
@@ -1870,7 +1950,7 @@ where
|
||||
Ok(start..end)
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<ops::Range<Idx>, A::Error>
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: MapAccess<'de>,
|
||||
{
|
||||
@@ -1918,11 +1998,12 @@ where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[allow(deprecated)]
|
||||
impl<'de, T> Deserialize<'de> for NonZero<T>
|
||||
where
|
||||
T: Deserialize<'de> + Zeroable,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<NonZero<T>, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1934,6 +2015,36 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! nonzero_integers {
|
||||
( $( $T: ty, )+ ) => {
|
||||
$(
|
||||
#[cfg(feature = "unstable")]
|
||||
impl<'de> Deserialize<'de> for $T {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, 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>
|
||||
@@ -1941,7 +2052,7 @@ where
|
||||
T: Deserialize<'de>,
|
||||
E: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Result<T, E>, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1956,7 +2067,7 @@ where
|
||||
|
||||
impl<'de> Deserialize<'de> for Field {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
@@ -1969,7 +2080,7 @@ where
|
||||
formatter.write_str("`Ok` or `Err`")
|
||||
}
|
||||
|
||||
fn visit_u32<E>(self, value: u32) -> Result<Field, E>
|
||||
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1983,7 +2094,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Field, E>
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -1994,7 +2105,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Field, E>
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
@@ -2028,7 +2139,7 @@ where
|
||||
formatter.write_str("enum Result")
|
||||
}
|
||||
|
||||
fn visit_enum<A>(self, data: A) -> Result<Result<T, E>, A::Error>
|
||||
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: EnumAccess<'de>,
|
||||
{
|
||||
@@ -2052,7 +2163,7 @@ impl<'de, T> Deserialize<'de> for Wrapping<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
|
||||
+87
-36
@@ -98,7 +98,8 @@
|
||||
//! - Path
|
||||
//! - PathBuf
|
||||
//! - Range\<T\>
|
||||
//! - NonZero\<T\> (unstable)
|
||||
//! - NonZero\<T\> (unstable, deprecated)
|
||||
//! - num::NonZero* (unstable)
|
||||
//! - **Net types**:
|
||||
//! - IpAddr
|
||||
//! - Ipv4Addr
|
||||
@@ -171,7 +172,8 @@ macro_rules! declare_error_trait {
|
||||
///
|
||||
/// impl<'de> Deserialize<'de> for IpAddr {
|
||||
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
/// where D: Deserializer<'de>
|
||||
/// where
|
||||
/// D: Deserializer<'de>,
|
||||
/// {
|
||||
/// let s = try!(String::deserialize(deserializer));
|
||||
/// s.parse().map_err(de::Error::custom)
|
||||
@@ -195,6 +197,7 @@ macro_rules! declare_error_trait {
|
||||
/// For example if we try to deserialize a String out of a JSON file
|
||||
/// containing an integer, the unexpected type is the integer and the
|
||||
/// expected type is the string.
|
||||
#[cold]
|
||||
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
|
||||
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
|
||||
}
|
||||
@@ -212,6 +215,7 @@ macro_rules! declare_error_trait {
|
||||
/// For example if we try to deserialize a String out of some binary data
|
||||
/// that is not valid UTF-8, the unexpected value is the bytes and the
|
||||
/// expected value is a string.
|
||||
#[cold]
|
||||
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
|
||||
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
|
||||
}
|
||||
@@ -225,12 +229,14 @@ macro_rules! declare_error_trait {
|
||||
/// The `exp` argument provides information about what data was being
|
||||
/// expected. For example `exp` might say that a tuple of size 6 was
|
||||
/// expected.
|
||||
#[cold]
|
||||
fn invalid_length(len: usize, exp: &Expected) -> Self {
|
||||
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
|
||||
}
|
||||
|
||||
/// Raised when a `Deserialize` enum type received a variant with an
|
||||
/// unrecognized name.
|
||||
#[cold]
|
||||
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
|
||||
if expected.is_empty() {
|
||||
Error::custom(format_args!("unknown variant `{}`, there are no variants",
|
||||
@@ -244,6 +250,7 @@ macro_rules! declare_error_trait {
|
||||
|
||||
/// Raised when a `Deserialize` struct type received a field with an
|
||||
/// unrecognized name.
|
||||
#[cold]
|
||||
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
|
||||
if expected.is_empty() {
|
||||
Error::custom(format_args!("unknown field `{}`, there are no fields",
|
||||
@@ -258,12 +265,14 @@ macro_rules! declare_error_trait {
|
||||
/// Raised when a `Deserialize` struct type expected to receive a required
|
||||
/// field with a particular name but that field was not present in the
|
||||
/// input.
|
||||
#[cold]
|
||||
fn missing_field(field: &'static str) -> Self {
|
||||
Error::custom(format_args!("missing field `{}`", field))
|
||||
}
|
||||
|
||||
/// Raised when a `Deserialize` struct type received more than one of the
|
||||
/// same field.
|
||||
#[cold]
|
||||
fn duplicate_field(field: &'static str) -> Self {
|
||||
Error::custom(format_args!("duplicate field `{}`", field))
|
||||
}
|
||||
@@ -298,7 +307,8 @@ declare_error_trait!(Error: Sized + Debug + Display);
|
||||
/// # }
|
||||
/// #
|
||||
/// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
/// where E: de::Error
|
||||
/// where
|
||||
/// E: de::Error,
|
||||
/// {
|
||||
/// Err(de::Error::invalid_type(Unexpected::Bool(v), &self))
|
||||
/// }
|
||||
@@ -422,7 +432,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
||||
/// # }
|
||||
/// #
|
||||
/// fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
||||
/// where E: de::Error
|
||||
/// where
|
||||
/// E: de::Error,
|
||||
/// {
|
||||
/// Err(de::Error::invalid_type(Unexpected::Bool(v), &self))
|
||||
/// }
|
||||
@@ -435,7 +446,8 @@ impl<'a> fmt::Display for Unexpected<'a> {
|
||||
/// # use serde::de::{self, Unexpected};
|
||||
/// #
|
||||
/// # fn example<E>() -> Result<(), E>
|
||||
/// # where E: de::Error
|
||||
/// # where
|
||||
/// # E: de::Error,
|
||||
/// # {
|
||||
/// # let v = true;
|
||||
/// return Err(de::Error::invalid_type(Unexpected::Bool(v), &"a negative integer"));
|
||||
@@ -513,7 +525,7 @@ pub trait Deserialize<'de>: Sized {
|
||||
/// have been overwritten. Although whatever state that is will be
|
||||
/// memory-safe.
|
||||
///
|
||||
/// This is generally useful when repeateadly deserializing values that
|
||||
/// 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.
|
||||
///
|
||||
@@ -549,11 +561,13 @@ pub trait Deserialize<'de>: Sized {
|
||||
/// #
|
||||
/// # trait Ignore {
|
||||
/// fn from_str<'a, T>(s: &'a str) -> Result<T>
|
||||
/// where T: Deserialize<'a>;
|
||||
/// where
|
||||
/// T: Deserialize<'a>;
|
||||
///
|
||||
/// fn from_reader<R, T>(rdr: R) -> Result<T>
|
||||
/// where R: Read,
|
||||
/// T: DeserializeOwned;
|
||||
/// where
|
||||
/// R: Read,
|
||||
/// T: DeserializeOwned;
|
||||
/// # }
|
||||
/// ```
|
||||
pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
|
||||
@@ -629,7 +643,8 @@ where
|
||||
/// struct ExtendVec<'a, T: 'a>(&'a mut Vec<T>);
|
||||
///
|
||||
/// impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T>
|
||||
/// where T: Deserialize<'de>
|
||||
/// where
|
||||
/// T: Deserialize<'de>,
|
||||
/// {
|
||||
/// // The return type of the `deserialize` method. This implementation
|
||||
/// // appends onto an existing vector but does not create any new data
|
||||
@@ -637,14 +652,16 @@ where
|
||||
/// type Value = ();
|
||||
///
|
||||
/// fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
/// where D: Deserializer<'de>
|
||||
/// where
|
||||
/// D: Deserializer<'de>,
|
||||
/// {
|
||||
/// // Visitor implementation that will walk an inner array of the JSON
|
||||
/// // input.
|
||||
/// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec<T>);
|
||||
///
|
||||
/// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T>
|
||||
/// where T: Deserialize<'de>
|
||||
/// where
|
||||
/// T: Deserialize<'de>,
|
||||
/// {
|
||||
/// type Value = ();
|
||||
///
|
||||
@@ -653,7 +670,8 @@ where
|
||||
/// }
|
||||
///
|
||||
/// fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
|
||||
/// where A: SeqAccess<'de>
|
||||
/// where
|
||||
/// A: SeqAccess<'de>,
|
||||
/// {
|
||||
/// // Visit each element in the inner array and push it onto
|
||||
/// // the existing vector.
|
||||
@@ -672,7 +690,8 @@ where
|
||||
/// struct FlattenedVecVisitor<T>(PhantomData<T>);
|
||||
///
|
||||
/// impl<'de, T> Visitor<'de> for FlattenedVecVisitor<T>
|
||||
/// where T: Deserialize<'de>
|
||||
/// where
|
||||
/// T: Deserialize<'de>,
|
||||
/// {
|
||||
/// // This Visitor constructs a single Vec<T> to hold the flattened
|
||||
/// // contents of the inner arrays.
|
||||
@@ -683,7 +702,8 @@ where
|
||||
/// }
|
||||
///
|
||||
/// fn visit_seq<A>(self, mut seq: A) -> Result<Vec<T>, A::Error>
|
||||
/// where A: SeqAccess<'de>
|
||||
/// where
|
||||
/// A: SeqAccess<'de>,
|
||||
/// {
|
||||
/// // Create a single Vec to hold the flattened contents.
|
||||
/// let mut vec = Vec::new();
|
||||
@@ -699,7 +719,8 @@ where
|
||||
/// }
|
||||
///
|
||||
/// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error>
|
||||
/// # where D: Deserializer<'de>
|
||||
/// # where
|
||||
/// # D: Deserializer<'de>,
|
||||
/// # {
|
||||
/// let visitor = FlattenedVecVisitor(PhantomData);
|
||||
/// let flattened: Vec<u64> = deserializer.deserialize_seq(visitor)?;
|
||||
@@ -1084,7 +1105,8 @@ pub trait Deserializer<'de>: Sized {
|
||||
///
|
||||
/// impl<'de> Deserialize<'de> for Timestamp {
|
||||
/// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
/// where D: Deserializer<'de>
|
||||
/// where
|
||||
/// D: Deserializer<'de>,
|
||||
/// {
|
||||
/// if deserializer.is_human_readable() {
|
||||
/// // Deserialize from a human-readable string like "2015-05-15T17:01:00Z".
|
||||
@@ -1110,6 +1132,18 @@ pub trait Deserializer<'de>: Sized {
|
||||
fn is_human_readable(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
fn private_deserialize_internally_tagged_enum<V>(
|
||||
self,
|
||||
visitor: V,
|
||||
) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1135,7 +1169,8 @@ pub trait Deserializer<'de>: Sized {
|
||||
/// }
|
||||
///
|
||||
/// fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
/// where E: de::Error
|
||||
/// where
|
||||
/// E: de::Error,
|
||||
/// {
|
||||
/// if s.len() >= self.min {
|
||||
/// Ok(s.to_owned())
|
||||
@@ -1815,15 +1850,18 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// }
|
||||
/// #
|
||||
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
|
||||
/// # where T: DeserializeSeed<'de>
|
||||
/// # where
|
||||
/// # T: DeserializeSeed<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// #
|
||||
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor<'de>
|
||||
/// # where
|
||||
/// # V: Visitor<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// #
|
||||
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor<'de>
|
||||
/// # where
|
||||
/// # V: Visitor<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// # }
|
||||
/// ```
|
||||
@@ -1850,7 +1888,8 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// # }
|
||||
/// #
|
||||
/// fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
|
||||
/// where T: DeserializeSeed<'de>
|
||||
/// where
|
||||
/// T: DeserializeSeed<'de>,
|
||||
/// {
|
||||
/// // What the data actually contained; suppose it is a unit variant.
|
||||
/// let unexp = Unexpected::UnitVariant;
|
||||
@@ -1858,11 +1897,13 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// }
|
||||
/// #
|
||||
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor<'de>
|
||||
/// # where
|
||||
/// # V: Visitor<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// #
|
||||
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor<'de>
|
||||
/// # where
|
||||
/// # V: Visitor<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// # }
|
||||
/// ```
|
||||
@@ -1903,13 +1944,17 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// # }
|
||||
/// #
|
||||
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
|
||||
/// # where T: DeserializeSeed<'de>
|
||||
/// # where
|
||||
/// # T: DeserializeSeed<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// #
|
||||
/// fn tuple_variant<V>(self,
|
||||
/// _len: usize,
|
||||
/// _visitor: V) -> Result<V::Value, Self::Error>
|
||||
/// where V: Visitor<'de>
|
||||
/// fn tuple_variant<V>(
|
||||
/// self,
|
||||
/// _len: usize,
|
||||
/// _visitor: V,
|
||||
/// ) -> Result<V::Value, Self::Error>
|
||||
/// where
|
||||
/// V: Visitor<'de>,
|
||||
/// {
|
||||
/// // What the data actually contained; suppose it is a unit variant.
|
||||
/// let unexp = Unexpected::UnitVariant;
|
||||
@@ -1917,7 +1962,8 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// }
|
||||
/// #
|
||||
/// # fn struct_variant<V>(self, _: &[&str], _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor<'de>
|
||||
/// # where
|
||||
/// # V: Visitor<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// # }
|
||||
/// ```
|
||||
@@ -1945,17 +1991,22 @@ pub trait VariantAccess<'de>: Sized {
|
||||
/// # }
|
||||
/// #
|
||||
/// # fn newtype_variant_seed<T>(self, _: T) -> Result<T::Value, Self::Error>
|
||||
/// # where T: DeserializeSeed<'de>
|
||||
/// # where
|
||||
/// # T: DeserializeSeed<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// #
|
||||
/// # fn tuple_variant<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor<'de>
|
||||
/// # where
|
||||
/// # V: Visitor<'de>,
|
||||
/// # { unimplemented!() }
|
||||
/// #
|
||||
/// fn struct_variant<V>(self,
|
||||
/// _fields: &'static [&'static str],
|
||||
/// _visitor: V) -> Result<V::Value, Self::Error>
|
||||
/// where V: Visitor<'de>
|
||||
/// fn struct_variant<V>(
|
||||
/// self,
|
||||
/// _fields: &'static [&'static str],
|
||||
/// _visitor: V,
|
||||
/// ) -> Result<V::Value, Self::Error>
|
||||
/// where
|
||||
/// V: Visitor<'de>,
|
||||
/// {
|
||||
/// // What the data actually contained; suppose it is a unit variant.
|
||||
/// let unexp = Unexpected::UnitVariant;
|
||||
|
||||
+8
-11
@@ -37,10 +37,10 @@
|
||||
|
||||
use lib::*;
|
||||
|
||||
use self::private::{First, Second};
|
||||
use de::{self, Expected, IntoDeserializer, SeqAccess};
|
||||
use private::de::size_hint;
|
||||
use ser;
|
||||
use self::private::{First, Second};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -58,6 +58,7 @@ type ErrorImpl = ();
|
||||
|
||||
impl de::Error for Error {
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
#[cold]
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
T: Display,
|
||||
@@ -68,6 +69,7 @@ impl de::Error for Error {
|
||||
}
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
#[cold]
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
T: Display,
|
||||
@@ -78,6 +80,7 @@ impl de::Error for Error {
|
||||
}
|
||||
|
||||
impl ser::Error for Error {
|
||||
#[cold]
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
T: Display,
|
||||
@@ -652,11 +655,8 @@ where
|
||||
{
|
||||
/// Check for remaining elements after passing a `SeqDeserializer` to
|
||||
/// `Visitor::visit_seq`.
|
||||
pub fn end(mut self) -> Result<(), E> {
|
||||
let mut remaining = 0;
|
||||
while self.iter.next().is_some() {
|
||||
remaining += 1;
|
||||
}
|
||||
pub fn end(self) -> Result<(), E> {
|
||||
let remaining = self.iter.count();
|
||||
if remaining == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -849,11 +849,8 @@ where
|
||||
{
|
||||
/// Check for remaining elements after passing a `MapDeserializer` to
|
||||
/// `Visitor::visit_map`.
|
||||
pub fn end(mut self) -> Result<(), E> {
|
||||
let mut remaining = 0;
|
||||
while self.iter.next().is_some() {
|
||||
remaining += 1;
|
||||
}
|
||||
pub fn end(self) -> Result<(), E> {
|
||||
let remaining = self.iter.count();
|
||||
if remaining == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
|
||||
@@ -16,6 +16,9 @@ pub use lib::result::Result::{self, Err, Ok};
|
||||
|
||||
pub use self::string::from_utf8_lossy;
|
||||
|
||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||
pub use lib::Vec;
|
||||
|
||||
mod string {
|
||||
use lib::*;
|
||||
|
||||
|
||||
+44
-34
@@ -79,7 +79,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.26")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.52")]
|
||||
// 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
|
||||
@@ -90,10 +90,13 @@
|
||||
#![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
|
||||
@@ -104,6 +107,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,
|
||||
@@ -111,7 +115,9 @@
|
||||
stutter,
|
||||
use_self,
|
||||
// not practical
|
||||
many_single_char_names,
|
||||
missing_docs_in_private_items,
|
||||
similar_names,
|
||||
// alternative is not stable
|
||||
empty_enum,
|
||||
use_debug,
|
||||
@@ -132,16 +138,16 @@ extern crate core;
|
||||
/// module.
|
||||
mod lib {
|
||||
mod core {
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::*;
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub use core::*;
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::*;
|
||||
}
|
||||
|
||||
pub use self::core::{cmp, iter, mem, ops, slice, str};
|
||||
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::{i16, i32, i64, i8, isize};
|
||||
pub use self::core::{u16, u32, u64, u8, usize};
|
||||
|
||||
pub use self::core::cell::{Cell, RefCell};
|
||||
pub use self::core::clone::{self, Clone};
|
||||
@@ -152,40 +158,40 @@ mod lib {
|
||||
pub use self::core::option::{self, Option};
|
||||
pub use self::core::result::{self, Result};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::borrow::{Cow, ToOwned};
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::borrow::{Cow, ToOwned};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::string::String;
|
||||
pub use std::borrow::{Cow, ToOwned};
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::string::{String, ToString};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::vec::Vec;
|
||||
pub use std::string::String;
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::vec::Vec;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::boxed::Box;
|
||||
pub use std::vec::Vec;
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::boxed::Box;
|
||||
|
||||
#[cfg(all(feature = "rc", feature = "std"))]
|
||||
pub use std::rc::Rc;
|
||||
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::rc::Rc;
|
||||
|
||||
#[cfg(all(feature = "rc", feature = "std"))]
|
||||
pub use std::sync::Arc;
|
||||
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::arc::Arc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||
pub use std::boxed::Box;
|
||||
|
||||
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::rc::{Rc, Weak as RcWeak};
|
||||
#[cfg(all(feature = "rc", feature = "std"))]
|
||||
pub use std::rc::{Rc, Weak as RcWeak};
|
||||
|
||||
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::arc::{Arc, Weak as ArcWeak};
|
||||
#[cfg(all(feature = "rc", feature = "std"))]
|
||||
pub use std::sync::{Arc, Weak as ArcWeak};
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::{error, net};
|
||||
@@ -203,12 +209,16 @@ mod lib {
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::path::{Path, PathBuf};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::sync::{Mutex, RwLock};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[allow(deprecated)]
|
||||
pub use core::nonzero::{NonZero, Zeroable};
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
pub use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -216,13 +226,13 @@ mod lib {
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
pub mod ser;
|
||||
pub mod de;
|
||||
pub mod ser;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ser::{Serialize, Serializer};
|
||||
#[doc(inline)]
|
||||
pub use de::{Deserialize, Deserializer};
|
||||
#[doc(inline)]
|
||||
pub use ser::{Serialize, Serializer};
|
||||
|
||||
// Generated code uses these to support no_std. Not public API.
|
||||
#[doc(hidden)]
|
||||
|
||||
+8
-4
@@ -31,14 +31,16 @@
|
||||
/// # type Error = value::Error;
|
||||
/// #
|
||||
/// # fn deserialize_any<V>(self, _: V) -> Result<V::Value, Self::Error>
|
||||
/// # where V: Visitor<'de>
|
||||
/// # where
|
||||
/// # V: Visitor<'de>,
|
||||
/// # {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
/// #
|
||||
/// #[inline]
|
||||
/// fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
/// where V: Visitor<'de>
|
||||
/// where
|
||||
/// V: Visitor<'de>,
|
||||
/// {
|
||||
/// self.deserialize_any(visitor)
|
||||
/// }
|
||||
@@ -69,7 +71,8 @@
|
||||
/// # type Error = value::Error;
|
||||
/// #
|
||||
/// fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
/// where V: Visitor<'de>
|
||||
/// where
|
||||
/// V: Visitor<'de>,
|
||||
/// {
|
||||
/// /* ... */
|
||||
/// # let _ = visitor;
|
||||
@@ -105,7 +108,8 @@
|
||||
/// # type Error = value::Error;
|
||||
/// #
|
||||
/// # fn deserialize_any<W>(self, visitor: W) -> Result<W::Value, Self::Error>
|
||||
/// # where W: Visitor<'q>
|
||||
/// # where
|
||||
/// # W: Visitor<'q>,
|
||||
/// # {
|
||||
/// # unimplemented!()
|
||||
/// # }
|
||||
|
||||
+861
-80
File diff suppressed because it is too large
Load Diff
@@ -8,5 +8,5 @@
|
||||
|
||||
mod macros;
|
||||
|
||||
pub mod ser;
|
||||
pub mod de;
|
||||
pub mod ser;
|
||||
|
||||
+319
-13
@@ -11,7 +11,9 @@ use lib::*;
|
||||
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
use self::content::{SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue};
|
||||
use self::content::{
|
||||
Content, ContentSerializer, SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue,
|
||||
};
|
||||
|
||||
/// Used to check that serde(getter) attributes return the expected type.
|
||||
/// Not public API.
|
||||
@@ -58,10 +60,11 @@ enum Unsupported {
|
||||
ByteArray,
|
||||
Optional,
|
||||
Unit,
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
UnitStruct,
|
||||
Sequence,
|
||||
Tuple,
|
||||
TupleStruct,
|
||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||
Enum,
|
||||
}
|
||||
|
||||
@@ -76,10 +79,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"),
|
||||
}
|
||||
}
|
||||
@@ -459,7 +463,7 @@ mod content {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Content {
|
||||
pub enum Content {
|
||||
Bool(bool),
|
||||
|
||||
U8(u8),
|
||||
@@ -584,12 +588,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 }
|
||||
}
|
||||
}
|
||||
@@ -804,7 +808,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeSeq<E> {
|
||||
pub struct SerializeSeq<E> {
|
||||
elements: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
@@ -830,7 +834,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTuple<E> {
|
||||
pub struct SerializeTuple<E> {
|
||||
elements: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
}
|
||||
@@ -856,7 +860,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTupleStruct<E> {
|
||||
pub struct SerializeTupleStruct<E> {
|
||||
name: &'static str,
|
||||
fields: Vec<Content>,
|
||||
error: PhantomData<E>,
|
||||
@@ -883,7 +887,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeTupleVariant<E> {
|
||||
pub struct SerializeTupleVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
@@ -917,7 +921,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeMap<E> {
|
||||
pub struct SerializeMap<E> {
|
||||
entries: Vec<(Content, Content)>,
|
||||
key: Option<Content>,
|
||||
error: PhantomData<E>,
|
||||
@@ -967,7 +971,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeStruct<E> {
|
||||
pub struct SerializeStruct<E> {
|
||||
name: &'static str,
|
||||
fields: Vec<(&'static str, Content)>,
|
||||
error: PhantomData<E>,
|
||||
@@ -994,7 +998,7 @@ mod content {
|
||||
}
|
||||
}
|
||||
|
||||
struct SerializeStructVariant<E> {
|
||||
pub struct SerializeStructVariant<E> {
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
@@ -1028,3 +1032,305 @@ mod content {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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(())
|
||||
}
|
||||
}
|
||||
|
||||
+91
-8
@@ -320,8 +320,12 @@ map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
macro_rules! deref_impl {
|
||||
($($desc:tt)+) => {
|
||||
impl $($desc)+ {
|
||||
(
|
||||
$(#[doc = $doc:tt])*
|
||||
<$($desc:tt)+
|
||||
) => {
|
||||
$(#[doc = $doc])*
|
||||
impl <$($desc)+ {
|
||||
#[inline]
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -340,17 +344,72 @@ deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
|
||||
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
||||
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
deref_impl!(<T: ?Sized> Serialize for Rc<T> where T: Serialize);
|
||||
deref_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
/// Serializing a data structure containing `Rc` will serialize a copy of
|
||||
/// the contents of the `Rc` each time the `Rc` is referenced within the
|
||||
/// data structure. Serialization will not attempt to deduplicate these
|
||||
/// repeated data.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
<T: ?Sized> Serialize for Rc<T> where T: Serialize
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
deref_impl!(<T: ?Sized> Serialize for Arc<T> where T: Serialize);
|
||||
deref_impl! {
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
/// Serializing a data structure containing `Arc` will serialize a copy of
|
||||
/// the contents of the `Arc` each time the `Arc` is referenced within the
|
||||
/// data structure. Serialization will not attempt to deduplicate these
|
||||
/// repeated data.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
<T: ?Sized> Serialize for Arc<T> where T: Serialize
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
impl<T: ?Sized> Serialize for RcWeak<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.upgrade().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
/// This impl requires the [`"rc"`] Cargo feature of Serde.
|
||||
///
|
||||
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
|
||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||
impl<T: ?Sized> Serialize for ArcWeak<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.upgrade().serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
#[allow(deprecated)]
|
||||
impl<T> Serialize for NonZero<T>
|
||||
where
|
||||
T: Serialize + Zeroable + Clone,
|
||||
@@ -363,6 +422,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,
|
||||
@@ -494,11 +579,9 @@ macro_rules! serialize_display_bounded_length {
|
||||
// write! only provides fmt::Formatter to Display implementations, which
|
||||
// has methods write_str and write_char but no method to write arbitrary
|
||||
// bytes. Therefore `written` must be valid UTF-8.
|
||||
let written_str = unsafe {
|
||||
str::from_utf8_unchecked(written)
|
||||
};
|
||||
let written_str = unsafe { str::from_utf8_unchecked(written) };
|
||||
$serializer.serialize_str(written_str)
|
||||
}}
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
|
||||
use lib::*;
|
||||
|
||||
use ser::{self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
||||
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
|
||||
use ser::{
|
||||
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
||||
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
|
||||
};
|
||||
|
||||
/// Helper type for implementing a `Serializer` that does not support
|
||||
/// serializing one of the compound types.
|
||||
|
||||
+112
-59
@@ -93,7 +93,8 @@
|
||||
//! - Path
|
||||
//! - PathBuf
|
||||
//! - Range\<T\>
|
||||
//! - NonZero\<T\> (unstable)
|
||||
//! - NonZero\<T\> (unstable, deprecated)
|
||||
//! - num::NonZero* (unstable)
|
||||
//! - **Net types**:
|
||||
//! - IpAddr
|
||||
//! - Ipv4Addr
|
||||
@@ -151,7 +152,8 @@ macro_rules! declare_error_trait {
|
||||
///
|
||||
/// impl Serialize for Path {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match self.to_str() {
|
||||
/// Some(s) => serializer.serialize_str(s),
|
||||
@@ -222,7 +224,8 @@ pub trait Serialize {
|
||||
/// // This is what #[derive(Serialize)] would generate.
|
||||
/// impl Serialize for Person {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut s = serializer.serialize_struct("Person", 3)?;
|
||||
/// s.serialize_field("name", &self.name)?;
|
||||
@@ -376,7 +379,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for bool {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_bool(*self)
|
||||
/// }
|
||||
@@ -402,7 +406,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for i8 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_i8(*self)
|
||||
/// }
|
||||
@@ -428,7 +433,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for i16 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_i16(*self)
|
||||
/// }
|
||||
@@ -454,7 +460,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for i32 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_i32(*self)
|
||||
/// }
|
||||
@@ -476,7 +483,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for i64 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_i64(*self)
|
||||
/// }
|
||||
@@ -502,7 +510,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for u8 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_u8(*self)
|
||||
/// }
|
||||
@@ -528,7 +537,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for u16 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_u16(*self)
|
||||
/// }
|
||||
@@ -554,7 +564,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for u32 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_u32(*self)
|
||||
/// }
|
||||
@@ -576,7 +587,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for u64 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_u64(*self)
|
||||
/// }
|
||||
@@ -602,7 +614,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for f32 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_f32(*self)
|
||||
/// }
|
||||
@@ -624,7 +637,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for f64 {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_f64(*self)
|
||||
/// }
|
||||
@@ -649,7 +663,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for char {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_char(*self)
|
||||
/// }
|
||||
@@ -671,7 +686,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for str {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_str(self)
|
||||
/// }
|
||||
@@ -736,10 +752,12 @@ pub trait Serializer: Sized {
|
||||
/// # use Option::{Some, None};
|
||||
/// #
|
||||
/// impl<T> Serialize for Option<T>
|
||||
/// where T: Serialize
|
||||
/// where
|
||||
/// T: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match *self {
|
||||
/// Some(ref value) => serializer.serialize_some(value),
|
||||
@@ -769,10 +787,12 @@ pub trait Serializer: Sized {
|
||||
/// # use Option::{Some, None};
|
||||
/// #
|
||||
/// impl<T> Serialize for Option<T>
|
||||
/// where T: Serialize
|
||||
/// where
|
||||
/// T: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match *self {
|
||||
/// Some(ref value) => serializer.serialize_some(value),
|
||||
@@ -801,7 +821,8 @@ pub trait Serializer: Sized {
|
||||
/// #
|
||||
/// impl Serialize for () {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_unit()
|
||||
/// }
|
||||
@@ -822,7 +843,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for Nothing {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_unit_struct("Nothing")
|
||||
/// }
|
||||
@@ -846,7 +868,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for E {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match *self {
|
||||
/// E::A => serializer.serialize_unit_variant("E", 0, "A"),
|
||||
@@ -875,7 +898,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for Millimeters {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.serialize_newtype_struct("Millimeters", &self.0)
|
||||
/// }
|
||||
@@ -905,7 +929,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for E {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match *self {
|
||||
/// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s),
|
||||
@@ -955,10 +980,12 @@ pub trait Serializer: Sized {
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
|
||||
///
|
||||
/// impl<T> Serialize for Vec<T>
|
||||
/// where T: Serialize
|
||||
/// where
|
||||
/// T: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut seq = serializer.serialize_seq(Some(self.len()))?;
|
||||
/// for element in self {
|
||||
@@ -987,12 +1014,14 @@ pub trait Serializer: Sized {
|
||||
/// # struct Tuple3<A, B, C>(A, B, C);
|
||||
/// #
|
||||
/// # impl<A, B, C> Serialize for Tuple3<A, B, C>
|
||||
/// where A: Serialize,
|
||||
/// B: Serialize,
|
||||
/// C: Serialize
|
||||
/// where
|
||||
/// A: Serialize,
|
||||
/// B: Serialize,
|
||||
/// C: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut tup = serializer.serialize_tuple(3)?;
|
||||
/// tup.serialize_element(&self.0)?;
|
||||
@@ -1011,7 +1040,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for Vram {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut seq = serializer.serialize_tuple(VRAM_SIZE)?;
|
||||
/// for element in &self.0[..] {
|
||||
@@ -1037,7 +1067,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for Rgb {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
|
||||
/// ts.serialize_field(&self.0)?;
|
||||
@@ -1071,7 +1102,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for E {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match *self {
|
||||
/// E::T(ref a, ref b) => {
|
||||
@@ -1129,11 +1161,13 @@ pub trait Serializer: Sized {
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeMap};
|
||||
///
|
||||
/// impl<K, V> Serialize for HashMap<K, V>
|
||||
/// where K: Serialize,
|
||||
/// V: Serialize
|
||||
/// where
|
||||
/// K: Serialize,
|
||||
/// V: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut map = serializer.serialize_map(Some(self.len()))?;
|
||||
/// for (k, v) in self {
|
||||
@@ -1163,7 +1197,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for Rgb {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut rgb = serializer.serialize_struct("Rgb", 3)?;
|
||||
/// rgb.serialize_field("r", &self.r)?;
|
||||
@@ -1196,7 +1231,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for E {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match *self {
|
||||
/// E::S { ref r, ref g, ref b } => {
|
||||
@@ -1233,7 +1269,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for SecretlyOneHigher {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.collect_seq(self.data.iter().map(|x| x + 1))
|
||||
/// }
|
||||
@@ -1271,7 +1308,8 @@ pub trait Serializer: Sized {
|
||||
/// // Serializes as a map in which the values are all unit.
|
||||
/// impl Serialize for MapToUnit {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.collect_map(self.keys.iter().map(|k| (k, ())))
|
||||
/// }
|
||||
@@ -1311,7 +1349,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for DateTime {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.collect_str(&format_args!("{:?}{:?}",
|
||||
/// self.naive_local(),
|
||||
@@ -1351,7 +1390,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for DateTime {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// serializer.collect_str(&format_args!("{:?}{:?}",
|
||||
/// self.naive_local(),
|
||||
@@ -1392,7 +1432,8 @@ pub trait Serializer: Sized {
|
||||
///
|
||||
/// impl Serialize for Timestamp {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// if serializer.is_human_readable() {
|
||||
/// // Serialize to a human-readable string "2015-05-15T17:01:00Z".
|
||||
@@ -1441,10 +1482,12 @@ pub trait Serializer: Sized {
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeSeq};
|
||||
///
|
||||
/// impl<T> Serialize for Vec<T>
|
||||
/// where T: Serialize
|
||||
/// where
|
||||
/// T: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut seq = serializer.serialize_seq(Some(self.len()))?;
|
||||
/// for element in self {
|
||||
@@ -1484,12 +1527,14 @@ pub trait SerializeSeq {
|
||||
/// # struct Tuple3<A, B, C>(A, B, C);
|
||||
/// #
|
||||
/// # impl<A, B, C> Serialize for Tuple3<A, B, C>
|
||||
/// where A: Serialize,
|
||||
/// B: Serialize,
|
||||
/// C: Serialize
|
||||
/// where
|
||||
/// A: Serialize,
|
||||
/// B: Serialize,
|
||||
/// C: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut tup = serializer.serialize_tuple(3)?;
|
||||
/// tup.serialize_element(&self.0)?;
|
||||
@@ -1528,10 +1573,12 @@ pub trait SerializeSeq {
|
||||
/// # }
|
||||
/// #
|
||||
/// # impl<T> Serialize for Array<T>
|
||||
/// where T: Serialize
|
||||
/// where
|
||||
/// T: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut seq = serializer.serialize_tuple(16)?;
|
||||
/// for element in self {
|
||||
@@ -1566,7 +1613,8 @@ pub trait SerializeTuple {
|
||||
///
|
||||
/// impl Serialize for Rgb {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?;
|
||||
/// ts.serialize_field(&self.0)?;
|
||||
@@ -1604,7 +1652,8 @@ pub trait SerializeTupleStruct {
|
||||
///
|
||||
/// impl Serialize for E {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match *self {
|
||||
/// E::T(ref a, ref b) => {
|
||||
@@ -1665,11 +1714,13 @@ pub trait SerializeTupleVariant {
|
||||
/// use serde::ser::{Serialize, Serializer, SerializeMap};
|
||||
///
|
||||
/// impl<K, V> Serialize for HashMap<K, V>
|
||||
/// where K: Serialize,
|
||||
/// V: Serialize
|
||||
/// where
|
||||
/// K: Serialize,
|
||||
/// V: Serialize,
|
||||
/// {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut map = serializer.serialize_map(Some(self.len()))?;
|
||||
/// for (k, v) in self {
|
||||
@@ -1753,7 +1804,8 @@ pub trait SerializeMap {
|
||||
///
|
||||
/// impl Serialize for Rgb {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// let mut rgb = serializer.serialize_struct("Rgb", 3)?;
|
||||
/// rgb.serialize_field("r", &self.r)?;
|
||||
@@ -1801,7 +1853,8 @@ pub trait SerializeStruct {
|
||||
///
|
||||
/// impl Serialize for E {
|
||||
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
/// where S: Serializer
|
||||
/// where
|
||||
/// S: Serializer,
|
||||
/// {
|
||||
/// match *self {
|
||||
/// E::S { ref r, ref g, ref b } => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.26" # remember to update html_root_url
|
||||
version = "1.0.52" # 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)]"
|
||||
@@ -23,9 +23,9 @@ name = "serde_derive"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "0.3.8"
|
||||
serde_derive_internals = { version = "=0.18.1", default-features = false, path = "../serde_derive_internals" }
|
||||
syn = { version = "0.11", features = ["visit"] }
|
||||
proc-macro2 = "0.3"
|
||||
quote = "0.5.2"
|
||||
syn = { version = "0.13", features = ["visit"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1.0", path = "../serde" }
|
||||
|
||||
+185
-131
@@ -8,28 +8,30 @@
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use syn::{self, visit};
|
||||
use syn;
|
||||
use syn::punctuated::{Pair, Punctuated};
|
||||
use syn::visit::{self, Visit};
|
||||
|
||||
use internals::ast::{Body, Container};
|
||||
use internals::ast::{Container, Data};
|
||||
use internals::attr;
|
||||
|
||||
macro_rules! path {
|
||||
($($path:tt)+) => {
|
||||
syn::parse_path(quote!($($path)+).as_str()).unwrap()
|
||||
};
|
||||
}
|
||||
use proc_macro2::Span;
|
||||
|
||||
// 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 {
|
||||
default: None,
|
||||
..ty_param.clone()
|
||||
.map(|param| match *param {
|
||||
syn::GenericParam::Type(ref param) => syn::GenericParam::Type(syn::TypeParam {
|
||||
eq_token: None,
|
||||
default: None,
|
||||
..param.clone()
|
||||
}),
|
||||
_ => param.clone(),
|
||||
})
|
||||
.collect(),
|
||||
..generics.clone()
|
||||
@@ -42,27 +44,46 @@ pub fn with_where_predicates(
|
||||
) -> syn::Generics {
|
||||
let mut generics = generics.clone();
|
||||
generics
|
||||
.where_clause
|
||||
.make_where_clause()
|
||||
.predicates
|
||||
.extend_from_slice(predicates);
|
||||
.extend(predicates.into_iter().cloned());
|
||||
generics
|
||||
}
|
||||
|
||||
pub fn with_where_predicates_from_fields<F>(
|
||||
pub fn with_where_predicates_from_fields(
|
||||
cont: &Container,
|
||||
generics: &syn::Generics,
|
||||
from_field: F,
|
||||
) -> syn::Generics
|
||||
where
|
||||
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
|
||||
{
|
||||
let predicates = cont.body
|
||||
from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
|
||||
) -> syn::Generics {
|
||||
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);
|
||||
generics.make_where_clause().predicates.extend(predicates);
|
||||
generics
|
||||
}
|
||||
|
||||
pub fn with_where_predicates_from_variants(
|
||||
cont: &Container,
|
||||
generics: &syn::Generics,
|
||||
from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>,
|
||||
) -> syn::Generics {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Struct(_, _) => {
|
||||
return generics.clone();
|
||||
}
|
||||
};
|
||||
|
||||
let predicates = variants
|
||||
.iter()
|
||||
.flat_map(|variant| from_variant(&variant.attrs))
|
||||
.flat_map(|predicates| predicates.to_vec());
|
||||
|
||||
let mut generics = generics.clone();
|
||||
generics.make_where_clause().predicates.extend(predicates);
|
||||
generics
|
||||
}
|
||||
|
||||
@@ -77,40 +98,53 @@ where
|
||||
// #[serde(skip_serializing)]
|
||||
// c: C,
|
||||
// }
|
||||
pub fn with_bound<F>(
|
||||
pub fn with_bound(
|
||||
cont: &Container,
|
||||
generics: &syn::Generics,
|
||||
filter: F,
|
||||
filter: fn(&attr::Field, Option<&attr::Variant>) -> bool,
|
||||
bound: &syn::Path,
|
||||
) -> syn::Generics
|
||||
where
|
||||
F: Fn(&attr::Field, Option<&attr::Variant>) -> bool,
|
||||
{
|
||||
struct FindTyParams {
|
||||
) -> syn::Generics {
|
||||
struct FindTyParams<'ast> {
|
||||
// Set of all generic type parameters on the current struct (A, B, C in
|
||||
// the example). Initialized up front.
|
||||
all_ty_params: HashSet<syn::Ident>,
|
||||
all_type_params: HashSet<syn::Ident>,
|
||||
|
||||
// Set of generic type parameters used in fields for which filter
|
||||
// returns true (A and B in the example). Filled in as the visitor sees
|
||||
// them.
|
||||
relevant_ty_params: HashSet<syn::Ident>,
|
||||
relevant_type_params: HashSet<syn::Ident>,
|
||||
|
||||
// Fields whose type is an associated type of one of the generic type
|
||||
// parameters.
|
||||
associated_type_usage: Vec<&'ast syn::TypePath>,
|
||||
}
|
||||
impl visit::Visitor for FindTyParams {
|
||||
fn visit_path(&mut self, path: &syn::Path) {
|
||||
impl<'ast> Visit<'ast> for FindTyParams<'ast> {
|
||||
fn visit_field(&mut self, field: &'ast syn::Field) {
|
||||
if let syn::Type::Path(ref ty) = field.ty {
|
||||
if let Some(Pair::Punctuated(ref t, _)) = ty.path.segments.first() {
|
||||
if self.all_type_params.contains(&t.ident) {
|
||||
self.associated_type_usage.push(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.visit_type(&field.ty);
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, path: &'ast 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 self.all_ty_params.contains(&id) {
|
||||
self.relevant_ty_params.insert(id);
|
||||
if path.leading_colon.is_none() && path.segments.len() == 1 {
|
||||
let id = path.segments[0].ident;
|
||||
if self.all_type_params.contains(&id) {
|
||||
self.relevant_type_params.insert(id);
|
||||
}
|
||||
}
|
||||
visit::walk_path(self, path);
|
||||
visit::visit_path(self, path);
|
||||
}
|
||||
|
||||
// Type parameter should not be considered used by a macro path.
|
||||
@@ -119,61 +153,66 @@ where
|
||||
// mac: T!(),
|
||||
// marker: PhantomData<T>,
|
||||
// }
|
||||
fn visit_mac(&mut self, _mac: &syn::Mac) {}
|
||||
fn visit_macro(&mut self, _mac: &'ast syn::Macro) {}
|
||||
}
|
||||
|
||||
let all_ty_params: HashSet<_> = generics
|
||||
.ty_params
|
||||
.iter()
|
||||
.map(|ty_param| ty_param.ident.clone())
|
||||
.collect();
|
||||
let all_type_params = generics.type_params().map(|param| param.ident).collect();
|
||||
|
||||
let mut visitor = FindTyParams {
|
||||
all_ty_params: all_ty_params,
|
||||
relevant_ty_params: HashSet::new(),
|
||||
all_type_params: all_type_params,
|
||||
relevant_type_params: HashSet::new(),
|
||||
associated_type_usage: Vec::new(),
|
||||
};
|
||||
match cont.body {
|
||||
Body::Enum(ref variants) => for variant in variants.iter() {
|
||||
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::walk_ty(&mut visitor, field.ty);
|
||||
visitor.visit_field(field.original);
|
||||
}
|
||||
},
|
||||
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);
|
||||
visitor.visit_field(field.original);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let relevant_type_params = visitor.relevant_type_params;
|
||||
let associated_type_usage = visitor.associated_type_usage;
|
||||
let new_predicates = generics
|
||||
.ty_params
|
||||
.iter()
|
||||
.map(|ty_param| ty_param.ident.clone())
|
||||
.filter(|id| visitor.relevant_ty_params.contains(id))
|
||||
.map(|id| {
|
||||
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
|
||||
bound_lifetimes: Vec::new(),
|
||||
.type_params()
|
||||
.map(|param| param.ident)
|
||||
.filter(|id| relevant_type_params.contains(id))
|
||||
.map(|id| syn::TypePath {
|
||||
qself: None,
|
||||
path: id.into(),
|
||||
})
|
||||
.chain(associated_type_usage.into_iter().cloned())
|
||||
.map(|bounded_ty| {
|
||||
syn::WherePredicate::Type(syn::PredicateType {
|
||||
lifetimes: None,
|
||||
// the type parameter that is being bounded e.g. T
|
||||
bounded_ty: syn::Ty::Path(None, id.into()),
|
||||
bounded_ty: syn::Type::Path(bounded_ty),
|
||||
colon_token: Default::default(),
|
||||
// the bound e.g. Serialize
|
||||
bounds: vec![
|
||||
syn::TyParamBound::Trait(
|
||||
syn::PolyTraitRef {
|
||||
bound_lifetimes: Vec::new(),
|
||||
trait_ref: bound.clone(),
|
||||
},
|
||||
syn::TraitBoundModifier::None,
|
||||
),
|
||||
],
|
||||
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
|
||||
paren_token: None,
|
||||
modifier: syn::TraitBoundModifier::None,
|
||||
lifetimes: None,
|
||||
path: bound.clone(),
|
||||
})].into_iter()
|
||||
.collect(),
|
||||
})
|
||||
});
|
||||
|
||||
let mut generics = generics.clone();
|
||||
generics.where_clause.predicates.extend(new_predicates);
|
||||
generics
|
||||
.make_where_clause()
|
||||
.predicates
|
||||
.extend(new_predicates);
|
||||
generics
|
||||
}
|
||||
|
||||
@@ -184,75 +223,90 @@ pub fn with_self_bound(
|
||||
) -> syn::Generics {
|
||||
let mut generics = generics.clone();
|
||||
generics
|
||||
.where_clause
|
||||
.make_where_clause()
|
||||
.predicates
|
||||
.push(syn::WherePredicate::BoundPredicate(
|
||||
syn::WhereBoundPredicate {
|
||||
bound_lifetimes: Vec::new(),
|
||||
// the type that is being bounded e.g. MyStruct<'a, T>
|
||||
bounded_ty: type_of_item(cont),
|
||||
// the bound e.g. Default
|
||||
bounds: vec![
|
||||
syn::TyParamBound::Trait(
|
||||
syn::PolyTraitRef {
|
||||
bound_lifetimes: Vec::new(),
|
||||
trait_ref: bound.clone(),
|
||||
},
|
||||
syn::TraitBoundModifier::None,
|
||||
),
|
||||
],
|
||||
},
|
||||
));
|
||||
.push(syn::WherePredicate::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 {
|
||||
paren_token: None,
|
||||
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();
|
||||
|
||||
for lifetime_def in &mut generics.lifetimes {
|
||||
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
|
||||
}
|
||||
|
||||
for ty_param in &mut generics.ty_params {
|
||||
ty_param
|
||||
.bounds
|
||||
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
|
||||
}
|
||||
|
||||
generics.lifetimes.push(syn::LifetimeDef {
|
||||
let bound = syn::Lifetime::new(lifetime, Span::call_site());
|
||||
let def = syn::LifetimeDef {
|
||||
attrs: Vec::new(),
|
||||
lifetime: syn::Lifetime::new(lifetime),
|
||||
bounds: Vec::new(),
|
||||
});
|
||||
lifetime: bound,
|
||||
colon_token: None,
|
||||
bounds: Punctuated::new(),
|
||||
};
|
||||
|
||||
generics
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
fn type_of_item(cont: &Container) -> syn::Ty {
|
||||
syn::Ty::Path(
|
||||
None,
|
||||
syn::Path {
|
||||
global: false,
|
||||
segments: vec![
|
||||
syn::PathSegment {
|
||||
ident: cont.ident.clone(),
|
||||
parameters: syn::PathParameters::AngleBracketed(
|
||||
syn::AngleBracketedParameterData {
|
||||
lifetimes: cont.generics
|
||||
.lifetimes
|
||||
.iter()
|
||||
.map(|def| def.lifetime.clone())
|
||||
.collect(),
|
||||
types: cont.generics
|
||||
.ty_params
|
||||
.iter()
|
||||
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
|
||||
.collect(),
|
||||
bindings: Vec::new(),
|
||||
},
|
||||
),
|
||||
},
|
||||
],
|
||||
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,
|
||||
arguments: syn::PathArguments::AngleBracketed(
|
||||
syn::AngleBracketedGenericArguments {
|
||||
colon2_token: None,
|
||||
lt_token: Default::default(),
|
||||
args: cont.generics
|
||||
.params
|
||||
.iter()
|
||||
.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(),
|
||||
gt_token: Default::default(),
|
||||
},
|
||||
),
|
||||
}].into_iter()
|
||||
.collect(),
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
+741
-298
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
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,12 +62,10 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,19 +6,20 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use internals::attr;
|
||||
use internals::check;
|
||||
use internals::Ctxt;
|
||||
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,34 +48,48 @@ 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, &attrs.default()))
|
||||
let mut data = match item.data {
|
||||
syn::Data::Enum(ref data) => {
|
||||
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
|
||||
}
|
||||
syn::Body::Struct(ref variant_data) => {
|
||||
let (style, fields) = struct_from_ast(cx, variant_data, None, &attrs.default());
|
||||
Body::Struct(style, fields)
|
||||
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 {
|
||||
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 ref mut field in &mut variant.fields {
|
||||
for field in &mut variant.fields {
|
||||
if field.attrs.flatten() {
|
||||
has_flatten = true;
|
||||
}
|
||||
field.attrs.rename_by_rule(variant.attrs.rename_all());
|
||||
}
|
||||
},
|
||||
Body::Struct(_, ref mut fields) => for field in fields {
|
||||
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);
|
||||
@@ -81,13 +97,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,7 +114,7 @@ impl<'a> Body<'a> {
|
||||
|
||||
fn enum_from_ast<'a>(
|
||||
cx: &Ctxt,
|
||||
variants: &'a [syn::Variant],
|
||||
variants: &'a Punctuated<syn::Variant, Token![,]>,
|
||||
container_default: &attr::Default,
|
||||
) -> Vec<Variant<'a>> {
|
||||
variants
|
||||
@@ -106,9 +122,9 @@ fn enum_from_ast<'a>(
|
||||
.map(|variant| {
|
||||
let attrs = attr::Variant::from_ast(cx, variant);
|
||||
let (style, fields) =
|
||||
struct_from_ast(cx, &variant.data, Some(&attrs), container_default);
|
||||
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
|
||||
Variant {
|
||||
ident: variant.ident.clone(),
|
||||
ident: variant.ident,
|
||||
attrs: attrs,
|
||||
style: style,
|
||||
fields: fields,
|
||||
@@ -119,30 +135,30 @@ fn enum_from_ast<'a>(
|
||||
|
||||
fn struct_from_ast<'a>(
|
||||
cx: &Ctxt,
|
||||
data: &'a syn::VariantData,
|
||||
fields: &'a syn::Fields,
|
||||
attrs: Option<&attr::Variant>,
|
||||
container_default: &attr::Default,
|
||||
) -> (Style, Vec<Field<'a>>) {
|
||||
match *data {
|
||||
syn::VariantData::Struct(ref fields) => (
|
||||
match *fields {
|
||||
syn::Fields::Named(ref fields) => (
|
||||
Style::Struct,
|
||||
fields_from_ast(cx, fields, attrs, container_default),
|
||||
fields_from_ast(cx, &fields.named, attrs, container_default),
|
||||
),
|
||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => (
|
||||
syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
|
||||
Style::Newtype,
|
||||
fields_from_ast(cx, fields, attrs, container_default),
|
||||
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
|
||||
),
|
||||
syn::VariantData::Tuple(ref fields) => (
|
||||
syn::Fields::Unnamed(ref fields) => (
|
||||
Style::Tuple,
|
||||
fields_from_ast(cx, fields, attrs, container_default),
|
||||
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
|
||||
),
|
||||
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
||||
syn::Fields::Unit => (Style::Unit, Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn fields_from_ast<'a>(
|
||||
cx: &Ctxt,
|
||||
fields: &'a [syn::Field],
|
||||
fields: &'a Punctuated<syn::Field, Token![,]>,
|
||||
attrs: Option<&attr::Variant>,
|
||||
container_default: &attr::Default,
|
||||
) -> Vec<Field<'a>> {
|
||||
@@ -150,9 +166,10 @@ fn fields_from_ast<'a>(
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, field)| Field {
|
||||
ident: field.ident.clone(),
|
||||
ident: field.ident,
|
||||
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
|
||||
ty: &field.ty,
|
||||
original: field,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
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.
|
||||
@@ -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();
|
||||
@@ -61,6 +64,7 @@ impl RenameRule {
|
||||
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;
|
||||
@@ -93,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),
|
||||
@@ -106,30 +111,26 @@ impl FromStr for RenameRule {
|
||||
|
||||
#[test]
|
||||
fn rename_variants() {
|
||||
for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in &[
|
||||
for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[
|
||||
(
|
||||
"Outcome",
|
||||
"outcome",
|
||||
"outcome",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
"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"),
|
||||
("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
|
||||
("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);
|
||||
@@ -144,27 +145,24 @@ fn rename_variants() {
|
||||
|
||||
#[test]
|
||||
fn rename_fields() {
|
||||
for &(original, pascal, camel, screaming, kebab, screaming_kebab) in &[
|
||||
for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[
|
||||
(
|
||||
"outcome",
|
||||
"Outcome",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
"outcome",
|
||||
"OUTCOME",
|
||||
"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"),
|
||||
("z42", "Z42", "z42", "Z42", "z42", "Z42"),
|
||||
("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,29 +6,32 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ast::{Body, Container, Style};
|
||||
use attr::Identifier;
|
||||
use Ctxt;
|
||||
use internals::ast::{Container, Data, Field, Style};
|
||||
use internals::attr::{EnumTag, Identifier};
|
||||
use internals::Ctxt;
|
||||
|
||||
/// Cross-cutting checks that require looking at more than a single attrs
|
||||
/// object. Simpler checks should happen when parsing and building the attrs.
|
||||
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 = \"...\")]",
|
||||
@@ -38,6 +41,55 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Flattening has some restrictions we can test.
|
||||
fn check_flatten(cx: &Ctxt, cont: &Container) {
|
||||
match cont.data {
|
||||
Data::Enum(ref variants) => {
|
||||
for variant in variants {
|
||||
for field in &variant.fields {
|
||||
check_flatten_field(cx, variant.style, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
Data::Struct(style, ref fields) => {
|
||||
for field in fields {
|
||||
check_flatten_field(cx, style, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
|
||||
if !field.attrs.flatten() {
|
||||
return;
|
||||
}
|
||||
match style {
|
||||
Style::Tuple => {
|
||||
cx.error("#[serde(flatten)] cannot be used on tuple structs");
|
||||
}
|
||||
Style::Newtype => {
|
||||
cx.error("#[serde(flatten)] cannot be used on newtype structs");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if field.attrs.skip_serializing() {
|
||||
cx.error(
|
||||
"#[serde(flatten] can not be combined with \
|
||||
#[serde(skip_serializing)]",
|
||||
);
|
||||
} else if field.attrs.skip_serializing_if().is_some() {
|
||||
cx.error(
|
||||
"#[serde(flatten] can not be combined with \
|
||||
#[serde(skip_serializing_if = \"...\")]",
|
||||
);
|
||||
} else if field.attrs.skip_deserializing() {
|
||||
cx.error(
|
||||
"#[serde(flatten] can not be combined with \
|
||||
#[serde(skip_deserializing)]",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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,9 +97,9 @@ 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;
|
||||
}
|
||||
};
|
||||
@@ -102,9 +154,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;
|
||||
}
|
||||
};
|
||||
@@ -169,3 +221,64 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::fmt::Display;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Display;
|
||||
use std::thread;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Ctxt {
|
||||
@@ -48,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,17 +6,11 @@
|
||||
// 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.18.1")]
|
||||
|
||||
extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate synom;
|
||||
|
||||
pub mod ast;
|
||||
pub mod attr;
|
||||
|
||||
mod ctxt;
|
||||
pub use ctxt::Ctxt;
|
||||
pub use self::ctxt::Ctxt;
|
||||
|
||||
mod case;
|
||||
mod check;
|
||||
+32
-11
@@ -22,43 +22,64 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.26")]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.52")]
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// Whitelisted clippy lints
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(
|
||||
enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding,
|
||||
cyclomatic_complexity
|
||||
)
|
||||
)]
|
||||
// Whitelisted clippy_pedantic lints
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(
|
||||
items_after_statements, doc_markdown, stutter, similar_names, use_self, single_match_else,
|
||||
enum_glob_use, match_same_arms, filter_map, cast_possible_truncation
|
||||
)
|
||||
)]
|
||||
// The `quote!` macro requires deep recursion.
|
||||
#![recursion_limit = "192"]
|
||||
#![recursion_limit = "512"]
|
||||
|
||||
#[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;
|
||||
|
||||
mod internals;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use syn::DeriveInput;
|
||||
|
||||
#[macro_use]
|
||||
mod bound;
|
||||
#[macro_use]
|
||||
mod fragment;
|
||||
|
||||
mod ser;
|
||||
mod de;
|
||||
mod pretend;
|
||||
mod ser;
|
||||
mod try;
|
||||
|
||||
#[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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
use proc_macro2::Span;
|
||||
use quote::Tokens;
|
||||
use syn::Ident;
|
||||
|
||||
use internals::ast::{Container, Data, Field, Style};
|
||||
|
||||
// Suppress dead_code warnings that would otherwise appear when using a remote
|
||||
// derive. Other than this pretend code, a struct annotated with remote derive
|
||||
// never has its fields referenced and an enum annotated with remote derive
|
||||
// never has its variants constructed.
|
||||
//
|
||||
// warning: field is never used: `i`
|
||||
// --> src/main.rs:4:20
|
||||
// |
|
||||
// 4 | struct StructDef { i: i32 }
|
||||
// | ^^^^^^
|
||||
//
|
||||
// warning: variant is never constructed: `V`
|
||||
// --> src/main.rs:8:16
|
||||
// |
|
||||
// 8 | enum EnumDef { V }
|
||||
// | ^
|
||||
//
|
||||
pub fn pretend_used(cont: &Container) -> Tokens {
|
||||
let pretend_fields = pretend_fields_used(cont);
|
||||
let pretend_variants = pretend_variants_used(cont);
|
||||
|
||||
quote! {
|
||||
#pretend_fields
|
||||
#pretend_variants
|
||||
}
|
||||
}
|
||||
|
||||
// For structs with named fields, expands to:
|
||||
//
|
||||
// match None::<T> {
|
||||
// Some(T { a: ref __v0, b: ref __v1 }) => {}
|
||||
// _ => {}
|
||||
// }
|
||||
//
|
||||
// For enums, expands to the following but only including struct variants:
|
||||
//
|
||||
// match None::<T> {
|
||||
// Some(T::A { a: ref __v0 }) => {}
|
||||
// Some(T::B { b: ref __v0 }) => {}
|
||||
// _ => {}
|
||||
// }
|
||||
//
|
||||
// The `ref` is important in case the user has written a Drop impl on their
|
||||
// type. Rust does not allow destructuring a struct or enum that has a Drop
|
||||
// impl.
|
||||
fn pretend_fields_used(cont: &Container) -> Tokens {
|
||||
let type_ident = cont.ident;
|
||||
let (_, ty_generics, _) = cont.generics.split_for_impl();
|
||||
|
||||
let patterns = match cont.data {
|
||||
Data::Enum(ref variants) => variants
|
||||
.iter()
|
||||
.filter_map(|variant| match variant.style {
|
||||
Style::Struct => {
|
||||
let variant_ident = variant.ident;
|
||||
let pat = struct_pattern(&variant.fields);
|
||||
Some(quote!(#type_ident::#variant_ident #pat))
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
Data::Struct(Style::Struct, ref fields) => {
|
||||
let pat = struct_pattern(fields);
|
||||
vec![quote!(#type_ident #pat)]
|
||||
}
|
||||
Data::Struct(_, _) => {
|
||||
return quote!();
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
match _serde::export::None::<#type_ident #ty_generics> {
|
||||
#(
|
||||
_serde::export::Some(#patterns) => {}
|
||||
)*
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expands to one of these per enum variant:
|
||||
//
|
||||
// match None {
|
||||
// Some((__v0, __v1,)) => {
|
||||
// let _ = E::V { a: __v0, b: __v1 };
|
||||
// }
|
||||
// _ => {}
|
||||
// }
|
||||
//
|
||||
fn pretend_variants_used(cont: &Container) -> Tokens {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Struct(_, _) => {
|
||||
return quote!();
|
||||
}
|
||||
};
|
||||
|
||||
let type_ident = cont.ident;
|
||||
let (_, ty_generics, _) = cont.generics.split_for_impl();
|
||||
let turbofish = ty_generics.as_turbofish();
|
||||
|
||||
let cases = variants.iter().map(|variant| {
|
||||
let variant_ident = variant.ident;
|
||||
let placeholders = &(0..variant.fields.len())
|
||||
.map(|i| Ident::new(&format!("__v{}", i), Span::call_site()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let pat = match variant.style {
|
||||
Style::Struct => {
|
||||
let names = variant.fields.iter().map(|field| field.ident);
|
||||
quote!({ #(#names: #placeholders),* })
|
||||
}
|
||||
Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )),
|
||||
Style::Unit => quote!(),
|
||||
};
|
||||
|
||||
quote! {
|
||||
match _serde::export::None {
|
||||
_serde::export::Some((#(#placeholders,)*)) => {
|
||||
let _ = #type_ident::#variant_ident #turbofish #pat;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote!(#(#cases)*)
|
||||
}
|
||||
|
||||
fn struct_pattern(fields: &[Field]) -> Tokens {
|
||||
let names = fields.iter().map(|field| field.ident);
|
||||
let placeholders =
|
||||
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
|
||||
quote!({ #(#names: ref #placeholders),* })
|
||||
}
|
||||
+399
-131
@@ -6,15 +6,17 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use syn::{self, Ident};
|
||||
use proc_macro2::Span;
|
||||
use quote::Tokens;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{self, Ident, Index, Member};
|
||||
|
||||
use bound;
|
||||
use fragment::{Fragment, Match, Stmts};
|
||||
use internals::ast::{Body, Container, Field, Style, Variant};
|
||||
use internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use internals::{attr, Ctxt};
|
||||
|
||||
use std::u32;
|
||||
use pretend;
|
||||
use try;
|
||||
|
||||
pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, String> {
|
||||
let ctxt = Ctxt::new();
|
||||
@@ -22,19 +24,22 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
||||
precondition(&ctxt, &cont);
|
||||
try!(ctxt.check());
|
||||
|
||||
let ident = &cont.ident;
|
||||
let ident = cont.ident;
|
||||
let params = Parameters::new(&cont);
|
||||
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
let dummy_const = Ident::new(format!("_IMPL_SERIALIZE_FOR_{}", ident));
|
||||
let dummy_const = Ident::new(&format!("_IMPL_SERIALIZE_FOR_{}", ident), Span::call_site());
|
||||
let body = Stmts(serialize_body(&cont, ¶ms));
|
||||
|
||||
let impl_block = if let Some(remote) = cont.attrs.remote() {
|
||||
let vis = &input.vis;
|
||||
let used = pretend::pretend_used(&cont);
|
||||
quote! {
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
where __S: _serde::Serializer
|
||||
where
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
#used
|
||||
#body
|
||||
}
|
||||
}
|
||||
@@ -44,7 +49,8 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
||||
#[automatically_derived]
|
||||
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause {
|
||||
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
where __S: _serde::Serializer
|
||||
where
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
#body
|
||||
}
|
||||
@@ -52,10 +58,12 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<Tokens, Strin
|
||||
}
|
||||
};
|
||||
|
||||
let try_replacement = try::replacement();
|
||||
let generated = quote! {
|
||||
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||
const #dummy_const: () = {
|
||||
extern crate serde as _serde;
|
||||
#try_replacement
|
||||
#impl_block
|
||||
};
|
||||
};
|
||||
@@ -95,14 +103,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::call_site())
|
||||
} else {
|
||||
Ident::new("self")
|
||||
Ident::new("self", Span::call_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 +126,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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,58 +138,64 @@ fn build_generics(cont: &Container) -> syn::Generics {
|
||||
let generics =
|
||||
bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound);
|
||||
|
||||
let generics =
|
||||
bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::ser_bound);
|
||||
|
||||
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),
|
||||
&parse_quote!(_serde::Serialize),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Fields with a `skip_serializing` or `serialize_with` attribute, or which
|
||||
// belong to a variant with a `serialize_with` attribute, are not serialized by
|
||||
// us so we do not generate a bound. Fields with a `bound` attribute specify
|
||||
// their own bound so we do not generate one. All other fields may need a `T:
|
||||
// Serialize` bound where T is the type of the field.
|
||||
// belong to a variant with a 'skip_serializing` or `serialize_with` attribute,
|
||||
// are not serialized by us so we do not generate a bound. Fields with a `bound`
|
||||
// attribute specify their own bound so we do not generate one. All other fields
|
||||
// may need a `T: Serialize` bound where T is the type of the field.
|
||||
fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
|
||||
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none()
|
||||
&& variant.map_or(true, |variant| variant.serialize_with().is_none())
|
||||
&& variant.map_or(true, |variant| {
|
||||
!variant.skip_serializing() && variant.serialize_with().is_none()
|
||||
&& variant.ser_bound().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 {
|
||||
let self_var = ¶ms.self_var;
|
||||
fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment {
|
||||
let self_var = params.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)
|
||||
}
|
||||
}
|
||||
@@ -201,13 +215,22 @@ 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 = 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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,16 +239,29 @@ fn serialize_tuple_struct(
|
||||
fields: &[Field],
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
let serialize_stmts = serialize_tuple_struct_visitor(
|
||||
fields,
|
||||
params,
|
||||
false,
|
||||
quote!(_serde::ser::SerializeTupleStruct::serialize_field),
|
||||
);
|
||||
let serialize_stmts =
|
||||
serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct);
|
||||
|
||||
let type_name = cattrs.name().serialize_name();
|
||||
let len = serialize_stmts.len();
|
||||
let let_mut = mut_if(len > 0);
|
||||
|
||||
let mut serialized_fields = fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
|
||||
.peekable();
|
||||
|
||||
let let_mut = mut_if(serialized_fields.peek().is_some());
|
||||
|
||||
let len = serialized_fields
|
||||
.map(|(i, field)| match field.attrs.skip_serializing_if() {
|
||||
None => quote!(1),
|
||||
Some(path) => {
|
||||
let index = syn::Index { index: i as u32, span: Span::call_site() };
|
||||
let field_expr = get_member(params, field, &Member::Unnamed(index));
|
||||
quote!(if #path(#field_expr) { 0 } else { 1 })
|
||||
}
|
||||
})
|
||||
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
||||
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
|
||||
@@ -235,15 +271,22 @@ 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_value()));
|
||||
|
||||
let serialize_fields = serialize_struct_visitor(
|
||||
fields,
|
||||
params,
|
||||
false,
|
||||
quote!(_serde::ser::SerializeStruct::serialize_field),
|
||||
quote!(_serde::ser::SerializeStruct::skip_field),
|
||||
);
|
||||
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, &StructTrait::SerializeStruct);
|
||||
|
||||
let type_name = cattrs.name().serialize_name();
|
||||
|
||||
@@ -258,8 +301,8 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
|
||||
.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);
|
||||
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 })
|
||||
}
|
||||
})
|
||||
@@ -272,10 +315,48 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment {
|
||||
assert!(variants.len() as u64 <= u32::MAX as u64);
|
||||
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 self_var = ¶ms.self_var;
|
||||
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 <= u64::from(u32::max_value()));
|
||||
|
||||
let self_var = params.self_var;
|
||||
|
||||
let arms: Vec<_> = variants
|
||||
.iter()
|
||||
@@ -299,7 +380,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!(
|
||||
@@ -332,8 +413,8 @@ fn serialize_variant(
|
||||
}
|
||||
}
|
||||
Style::Tuple => {
|
||||
let field_names =
|
||||
(0..variant.fields.len()).map(|i| Ident::new(format!("__field{}", i)));
|
||||
let field_names = (0..variant.fields.len())
|
||||
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site()));
|
||||
quote! {
|
||||
#this::#variant_ident(#(ref #field_names),*)
|
||||
}
|
||||
@@ -342,7 +423,7 @@ 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),* }
|
||||
}
|
||||
@@ -379,7 +460,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,
|
||||
@@ -406,7 +487,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! {
|
||||
@@ -453,7 +534,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,
|
||||
@@ -480,7 +561,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! {
|
||||
@@ -519,7 +600,7 @@ fn serialize_adjacently_tagged_variant(
|
||||
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);
|
||||
let ser = wrap_serialize_variant_with(params, path, variant);
|
||||
quote_expr! {
|
||||
_serde::Serialize::serialize(#ser, __serializer)
|
||||
}
|
||||
@@ -538,12 +619,18 @@ fn serialize_adjacently_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! {
|
||||
_serde::Serialize::serialize(#field_expr, __serializer)
|
||||
}
|
||||
return quote_block! {
|
||||
let mut __struct = try!(_serde::Serializer::serialize_struct(
|
||||
__serializer, #type_name, 2));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #tag, #variant_name));
|
||||
try!(_serde::ser::SerializeStruct::serialize_field(
|
||||
&mut __struct, #content, #field_expr));
|
||||
_serde::ser::SerializeStruct::end(__struct)
|
||||
};
|
||||
}
|
||||
Style::Tuple => {
|
||||
serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields)
|
||||
@@ -558,7 +645,7 @@ fn serialize_adjacently_tagged_variant(
|
||||
});
|
||||
|
||||
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![]
|
||||
@@ -566,20 +653,20 @@ fn serialize_adjacently_tagged_variant(
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Style::Newtype => vec![Ident::new("__field0")],
|
||||
Style::Newtype => vec![Ident::new("__field0", Span::call_site())],
|
||||
Style::Tuple => (0..variant.fields.len())
|
||||
.map(|i| Ident::new(format!("__field{}", i)))
|
||||
.map(|i| Ident::new(&format!("__field{}", i), Span::call_site()))
|
||||
.collect(),
|
||||
Style::Struct => variant
|
||||
.fields
|
||||
.iter()
|
||||
.map(|f| f.ident.clone().expect("struct variant has unnamed fields"))
|
||||
.map(|f| f.ident.expect("struct variant has unnamed fields"))
|
||||
.collect(),
|
||||
};
|
||||
|
||||
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
|
||||
let wrapper_generics = if let Style::Unit = variant.style {
|
||||
let wrapper_generics = if fields_ident.is_empty() {
|
||||
params.generics.clone()
|
||||
} else {
|
||||
bound::with_lifetime_bound(¶ms.generics, "'__a")
|
||||
@@ -594,7 +681,8 @@ fn serialize_adjacently_tagged_variant(
|
||||
|
||||
impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause {
|
||||
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
where __S: _serde::Serializer
|
||||
where
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
let (#(#fields_ident,)*) = self.data;
|
||||
#inner
|
||||
@@ -620,7 +708,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)
|
||||
};
|
||||
@@ -636,7 +724,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! {
|
||||
@@ -665,17 +753,30 @@ 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);
|
||||
let mut serialized_fields = fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
|
||||
.peekable();
|
||||
|
||||
let let_mut = mut_if(serialized_fields.peek().is_some());
|
||||
|
||||
let len = serialized_fields
|
||||
.map(|(i, field)| match field.attrs.skip_serializing_if() {
|
||||
None => quote!(1),
|
||||
Some(path) => {
|
||||
let field_expr = Ident::new(&format!("__field{}", i), Span::call_site());
|
||||
quote!(if #path(#field_expr) { 0 } else { 1 })
|
||||
}
|
||||
})
|
||||
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
|
||||
|
||||
match context {
|
||||
TupleVariant::ExternallyTagged {
|
||||
@@ -724,18 +825,18 @@ 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),
|
||||
),
|
||||
if fields.iter().any(|field| field.attrs.flatten()) {
|
||||
return serialize_struct_variant_with_flatten(context, params, fields, name);
|
||||
}
|
||||
|
||||
let struct_trait = match context {
|
||||
StructVariant::ExternallyTagged { .. } => (StructTrait::SerializeStructVariant),
|
||||
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
|
||||
(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()
|
||||
@@ -746,7 +847,7 @@ fn serialize_struct_variant<'a>(
|
||||
|
||||
let len = serialized_fields
|
||||
.map(|field| {
|
||||
let ident = field.ident.clone().expect("struct has unnamed fields");
|
||||
let ident = field.ident.expect("struct has unnamed fields");
|
||||
|
||||
match field.attrs.skip_serializing_if() {
|
||||
Some(path) => quote!(if #path(#ident) { 0 } else { 1 }),
|
||||
@@ -802,21 +903,115 @@ fn serialize_struct_variant<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_struct_variant_with_flatten<'a>(
|
||||
context: StructVariant<'a>,
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
name: &str,
|
||||
) -> Fragment {
|
||||
let struct_trait = StructTrait::SerializeMap;
|
||||
let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait);
|
||||
|
||||
let mut serialized_fields = fields
|
||||
.iter()
|
||||
.filter(|&field| !field.attrs.skip_serializing())
|
||||
.peekable();
|
||||
|
||||
let let_mut = mut_if(serialized_fields.peek().is_some());
|
||||
|
||||
match context {
|
||||
StructVariant::ExternallyTagged {
|
||||
variant_index,
|
||||
variant_name,
|
||||
} => {
|
||||
let this = ¶ms.this;
|
||||
let fields_ty = fields.iter().map(|f| &f.ty);
|
||||
let fields_ident = &fields.iter().map(|f| f.ident).collect::<Vec<_>>();
|
||||
|
||||
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
let wrapper_generics = bound::with_lifetime_bound(¶ms.generics, "'__a");
|
||||
let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl();
|
||||
|
||||
quote_block! {
|
||||
struct __EnumFlatten #wrapper_generics #where_clause {
|
||||
data: (#(&'__a #fields_ty,)*),
|
||||
phantom: _serde::export::PhantomData<#this #ty_generics>,
|
||||
}
|
||||
|
||||
impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause {
|
||||
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
where
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
let (#(#fields_ident,)*) = self.data;
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::export::None));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
}
|
||||
|
||||
_serde::Serializer::serialize_newtype_variant(
|
||||
__serializer,
|
||||
#name,
|
||||
#variant_index,
|
||||
#variant_name,
|
||||
&__EnumFlatten {
|
||||
data: (#(#fields_ident,)*),
|
||||
phantom: _serde::export::PhantomData::<#this #ty_generics>,
|
||||
})
|
||||
}
|
||||
}
|
||||
StructVariant::InternallyTagged { tag, variant_name } => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::export::None));
|
||||
try!(_serde::ser::SerializeMap::serialize_entry(
|
||||
&mut __serde_state,
|
||||
#tag,
|
||||
#variant_name,
|
||||
));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
}
|
||||
StructVariant::Untagged => {
|
||||
quote_block! {
|
||||
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(
|
||||
__serializer,
|
||||
_serde::export::None));
|
||||
#(#serialize_fields)*
|
||||
_serde::ser::SerializeMap::end(__serde_state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_tuple_struct_visitor(
|
||||
fields: &[Field],
|
||||
params: &Parameters,
|
||||
is_enum: bool,
|
||||
func: Tokens,
|
||||
tuple_trait: &TupleTrait,
|
||||
) -> Vec<Tokens> {
|
||||
fields
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
|
||||
.map(|(i, field)| {
|
||||
let mut field_expr = if is_enum {
|
||||
let id = Ident::new(format!("__field{}", i));
|
||||
let id = Ident::new(&format!("__field{}", i), Span::call_site());
|
||||
quote!(#id)
|
||||
} else {
|
||||
get_field(params, field, i)
|
||||
get_member(
|
||||
params,
|
||||
field,
|
||||
&Member::Unnamed(Index {
|
||||
index: i as u32,
|
||||
span: Span::call_site(),
|
||||
}),
|
||||
)
|
||||
};
|
||||
|
||||
let skip = field
|
||||
@@ -825,9 +1020,11 @@ fn serialize_tuple_struct_visitor(
|
||||
.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);
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
|
||||
let span = field.original.span();
|
||||
let func = tuple_trait.serialize_element(span);
|
||||
let ser = quote! {
|
||||
try!(#func(&mut __serde_state, #field_expr));
|
||||
};
|
||||
@@ -844,18 +1041,18 @@ 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 field_ident = field.ident.expect("struct has unnamed field");
|
||||
|
||||
let mut field_expr = if is_enum {
|
||||
quote!(#field_ident)
|
||||
} else {
|
||||
get_field(params, field, field_ident)
|
||||
get_member(params, field, &Member::Named(field_ident))
|
||||
};
|
||||
|
||||
let key_expr = field.attrs.name().serialize_name();
|
||||
@@ -866,21 +1063,37 @@ fn serialize_struct_visitor(
|
||||
.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);
|
||||
field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr);
|
||||
}
|
||||
|
||||
let ser = quote! {
|
||||
try!(#func(&mut __serde_state, #key_expr, #field_expr));
|
||||
let span = field.original.span();
|
||||
let ser = if field.attrs.flatten() {
|
||||
quote! {
|
||||
try!(_serde::Serialize::serialize(&#field_expr, _serde::private::ser::FlatMapSerializer(&mut __serde_state)));
|
||||
}
|
||||
} else {
|
||||
let func = struct_trait.serialize_field(span);
|
||||
quote! {
|
||||
try!(#func(&mut __serde_state, #key_expr, #field_expr));
|
||||
}
|
||||
};
|
||||
|
||||
match skip {
|
||||
None => ser,
|
||||
Some(skip) => {
|
||||
quote! {
|
||||
if !#skip {
|
||||
#ser
|
||||
} else {
|
||||
try!(#skip_func(&mut __serde_state, #key_expr));
|
||||
if let Some(skip_func) = struct_trait.skip_field(span) {
|
||||
quote! {
|
||||
if !#skip {
|
||||
#ser
|
||||
} else {
|
||||
try!(#skip_func(&mut __serde_state, #key_expr));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
if !#skip {
|
||||
#ser
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -891,16 +1104,16 @@ fn serialize_struct_visitor(
|
||||
|
||||
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)])
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -911,8 +1124,7 @@ fn wrap_serialize_variant_with(
|
||||
.map(|(i, field)| {
|
||||
let id = field
|
||||
.ident
|
||||
.as_ref()
|
||||
.map_or_else(|| Ident::new(format!("__field{}", i)), |id| id.clone());
|
||||
.unwrap_or_else(|| Ident::new(&format!("__field{}", i), Span::call_site()));
|
||||
quote!(#id)
|
||||
})
|
||||
.collect();
|
||||
@@ -926,21 +1138,26 @@ fn wrap_serialize_variant_with(
|
||||
|
||||
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 {
|
||||
@@ -950,7 +1167,8 @@ fn wrap_serialize_with(
|
||||
|
||||
impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause {
|
||||
fn serialize<__S>(&self, __s: __S) -> _serde::export::Result<__S::Ok, __S::Error>
|
||||
where __S: _serde::Serializer
|
||||
where
|
||||
__S: _serde::Serializer,
|
||||
{
|
||||
#serialize_with(#(self.values.#field_access, )* __s)
|
||||
}
|
||||
@@ -977,20 +1195,14 @@ fn mut_if(is_mut: bool) -> Option<Tokens> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_field<I>(params: &Parameters, field: &Field, ident: I) -> Tokens
|
||||
where
|
||||
I: Into<Ident>,
|
||||
{
|
||||
let self_var = ¶ms.self_var;
|
||||
fn get_member(params: &Parameters, field: &Field, member: &Member) -> Tokens {
|
||||
let self_var = params.self_var;
|
||||
match (params.is_remote, field.attrs.getter()) {
|
||||
(false, None) => {
|
||||
let ident = ident.into();
|
||||
quote!(&#self_var.#ident)
|
||||
}
|
||||
(false, None) => quote!(&#self_var.#member),
|
||||
(true, None) => {
|
||||
let inner = quote!(&#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;
|
||||
@@ -1001,3 +1213,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use proc_macro2::{Op, Spacing};
|
||||
use quote::Tokens;
|
||||
|
||||
// None of our generated code requires the `From::from` error conversion
|
||||
// performed by the standard library's `try!` macro. With this simplified macro
|
||||
// we see a significant improvement in type checking and borrow checking time of
|
||||
// the generated code and a slight improvement in binary size.
|
||||
pub fn replacement() -> Tokens {
|
||||
// Cannot pass `$expr` to `quote!` prior to Rust 1.17.0 so interpolate it.
|
||||
let dollar = Op::new('$', Spacing::Alone);
|
||||
|
||||
quote! {
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! try {
|
||||
(#dollar __expr:expr) => {
|
||||
match #dollar __expr {
|
||||
_serde::export::Ok(__val) => __val,
|
||||
_serde::export::Err(__err) => {
|
||||
return _serde::export::Err(__err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.18.1" # remember to update html_root_url
|
||||
version = "0.23.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."
|
||||
@@ -9,11 +9,14 @@ repository = "https://github.com/serde-rs/serde"
|
||||
documentation = "https://docs.serde.rs/serde_derive_internals/"
|
||||
keywords = ["serde", "serialization"]
|
||||
readme = "README.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
|
||||
synom = "0.11"
|
||||
proc-macro2 = "0.3"
|
||||
syn = { version = "0.13", default-features = false, features = ["derive", "parsing", "clone-impls"] }
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "serde-rs/serde" }
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2017 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.23.1")]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(cyclomatic_complexity, doc_markdown, match_same_arms, redundant_field_names)
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate syn;
|
||||
|
||||
extern crate proc_macro2;
|
||||
|
||||
#[path = "src/mod.rs"]
|
||||
mod internals;
|
||||
|
||||
pub use internals::*;
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../serde_derive/src/internals/
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.26" # remember to update html_root_url
|
||||
version = "1.0.52" # 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"
|
||||
|
||||
+601
-421
File diff suppressed because it is too large
Load Diff
+15
-13
@@ -6,9 +6,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
|
||||
SeqAccess, VariantAccess, Visitor};
|
||||
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
|
||||
use serde::de::{
|
||||
self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
|
||||
VariantAccess, Visitor,
|
||||
};
|
||||
|
||||
use error::Error;
|
||||
use token::Token;
|
||||
@@ -22,28 +24,28 @@ macro_rules! assert_next_token {
|
||||
($de:expr, $expected:expr) => {
|
||||
match $de.next_token_opt() {
|
||||
Some(token) if token == $expected => {}
|
||||
Some(other) => {
|
||||
panic!("expected Token::{} but deserialization wants Token::{}",
|
||||
other, $expected)
|
||||
}
|
||||
None => {
|
||||
panic!("end of tokens but deserialization wants Token::{}",
|
||||
$expected)
|
||||
}
|
||||
Some(other) => panic!(
|
||||
"expected Token::{} but deserialization wants Token::{}",
|
||||
other, $expected
|
||||
),
|
||||
None => panic!(
|
||||
"end of tokens but deserialization wants Token::{}",
|
||||
$expected
|
||||
),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! unexpected {
|
||||
($token:expr) => {
|
||||
panic!("deserialization did not expect this token: {}", $token)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! end_of_tokens {
|
||||
() => {
|
||||
panic!("ran out of tokens to deserialize")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<'de> Deserializer<'de> {
|
||||
|
||||
+30
-17
@@ -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)>);
|
||||
//! #
|
||||
@@ -68,11 +68,13 @@
|
||||
//! # }
|
||||
//! #
|
||||
//! # impl<K, V> Serialize for LinkedHashMap<K, V>
|
||||
//! # where K: Serialize,
|
||||
//! # V: Serialize
|
||||
//! # where
|
||||
//! # K: Serialize,
|
||||
//! # V: Serialize,
|
||||
//! # {
|
||||
//! # fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
//! # where S: Serializer
|
||||
//! # where
|
||||
//! # S: Serializer,
|
||||
//! # {
|
||||
//! # let mut map = serializer.serialize_map(Some(self.0.len()))?;
|
||||
//! # for &(ref k, ref v) in &self.0 {
|
||||
@@ -85,8 +87,9 @@
|
||||
//! # struct LinkedHashMapVisitor<K, V>(PhantomData<(K, V)>);
|
||||
//! #
|
||||
//! # impl<'de, K, V> Visitor<'de> for LinkedHashMapVisitor<K, V>
|
||||
//! # where K: Deserialize<'de>,
|
||||
//! # V: Deserialize<'de>
|
||||
//! # where
|
||||
//! # K: Deserialize<'de>,
|
||||
//! # V: Deserialize<'de>,
|
||||
//! # {
|
||||
//! # type Value = LinkedHashMap<K, V>;
|
||||
//! #
|
||||
@@ -95,7 +98,8 @@
|
||||
//! # }
|
||||
//! #
|
||||
//! # fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||
//! # where M: MapAccess<'de>
|
||||
//! # where
|
||||
//! # M: MapAccess<'de>,
|
||||
//! # {
|
||||
//! # let mut map = LinkedHashMap::new();
|
||||
//! # while let Some((key, value)) = access.next_entry()? {
|
||||
@@ -106,11 +110,13 @@
|
||||
//! # }
|
||||
//! #
|
||||
//! # impl<'de, K, V> Deserialize<'de> for LinkedHashMap<K, V>
|
||||
//! # where K: Deserialize<'de>,
|
||||
//! # V: Deserialize<'de>
|
||||
//! # where
|
||||
//! # K: Deserialize<'de>,
|
||||
//! # V: Deserialize<'de>,
|
||||
//! # {
|
||||
//! # fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
//! # where D: Deserializer<'de>
|
||||
//! # where
|
||||
//! # D: Deserializer<'de>,
|
||||
//! # {
|
||||
//! # deserializer.deserialize_map(LinkedHashMapVisitor(PhantomData))
|
||||
//! # }
|
||||
@@ -155,28 +161,35 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.26")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.52")]
|
||||
#![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;
|
||||
|
||||
mod ser;
|
||||
mod de;
|
||||
mod error;
|
||||
mod ser;
|
||||
|
||||
mod assert;
|
||||
mod configure;
|
||||
mod token;
|
||||
mod assert;
|
||||
|
||||
pub use assert::{
|
||||
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
|
||||
assert_tokens,
|
||||
};
|
||||
pub use token::Token;
|
||||
pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
|
||||
assert_ser_tokens_error, assert_tokens};
|
||||
|
||||
pub use configure::{Compact, Configure, Readable};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ macro_rules! assert_next_token {
|
||||
($ser:expr, $expected:ident($v:expr)) => {
|
||||
assert_next_token!(
|
||||
$ser,
|
||||
format_args!("{}({:?})", stringify!($expected), $v),
|
||||
format_args!(concat!(stringify!($expected), "({:?})"), $v),
|
||||
Token::$expected(v),
|
||||
v == $v
|
||||
);
|
||||
@@ -56,13 +56,13 @@ macro_rules! assert_next_token {
|
||||
use std::fmt::Write;
|
||||
let mut buffer = String::new();
|
||||
$(
|
||||
write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap();
|
||||
write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
|
||||
)*
|
||||
buffer
|
||||
};
|
||||
assert_next_token!(
|
||||
$ser,
|
||||
format_args!("{} {{ {}}}", stringify!($expected), field_format()),
|
||||
format_args!(concat!(stringify!($expected), " {{ {}}}"), field_format()),
|
||||
Token::$expected { $($k),* },
|
||||
($($k,)*) == compare
|
||||
);
|
||||
|
||||
@@ -9,6 +9,7 @@ unstable = ["serde/unstable", "compiletest_rs"]
|
||||
|
||||
[dev-dependencies]
|
||||
fnv = "1.0"
|
||||
proc-macro2 = "0.3"
|
||||
rustc-serialize = "0.3.16"
|
||||
serde = { path = "../serde", features = ["rc"] }
|
||||
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||
|
||||
@@ -6,11 +6,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(lang_items, start, compiler_builtins_lib)]
|
||||
#![feature(lang_items, start)]
|
||||
#![no_std]
|
||||
|
||||
extern crate libc;
|
||||
extern crate compiler_builtins;
|
||||
|
||||
#[start]
|
||||
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
@@ -19,19 +18,17 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
#[no_mangle]
|
||||
pub extern fn rust_eh_personality() {}
|
||||
|
||||
#[lang = "eh_unwind_resume"]
|
||||
#[no_mangle]
|
||||
pub extern fn rust_eh_unwind_resume() {}
|
||||
pub extern "C" fn rust_eh_personality() {}
|
||||
|
||||
#[lang = "panic_fmt"]
|
||||
#[no_mangle]
|
||||
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
|
||||
_file: &'static str,
|
||||
_line: u32) -> ! {
|
||||
pub extern "C" fn rust_begin_panic(
|
||||
_msg: core::fmt::Arguments,
|
||||
_file: &'static str,
|
||||
_line: u32,
|
||||
) -> ! {
|
||||
unsafe {
|
||||
libc::abort()
|
||||
libc::abort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +47,9 @@ struct Newtype(u8);
|
||||
struct Tuple(u8, u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Struct { f: u8 }
|
||||
struct Struct {
|
||||
f: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum Enum {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
use serde::de::{Deserializer, Error, SeqAccess, Visitor};
|
||||
use std::fmt;
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_byte_buf(ByteBufVisitor)
|
||||
}
|
||||
|
||||
struct ByteBufVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for ByteBufVisitor {
|
||||
type Value = Vec<u8>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("byte array")
|
||||
}
|
||||
|
||||
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
|
||||
where
|
||||
V: SeqAccess<'de>,
|
||||
{
|
||||
let mut values = Vec::new();
|
||||
while let Some(value) = try!(visitor.next_element()) {
|
||||
values.push(value);
|
||||
}
|
||||
Ok(values)
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
Ok(v.to_vec())
|
||||
}
|
||||
|
||||
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
Ok(v.as_bytes().to_vec())
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
Ok(v.into_bytes())
|
||||
}
|
||||
}
|
||||
@@ -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,16 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: #[serde(flatten)] cannot be used on newtype structs
|
||||
struct Foo(#[serde(flatten)] HashMap<String, String>);
|
||||
|
||||
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,16 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked
|
||||
//~^ HELP: #[serde(flatten)] cannot be used on tuple structs
|
||||
struct Foo(u32, #[serde(flatten)] HashMap<String, String>);
|
||||
|
||||
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() {}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||
struct S<'de> {
|
||||
s: &'de str, //~^^ HELP: cannot deserialize when there is a lifetime parameter called 'de
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2018 Serde Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||
struct S {
|
||||
string: String,
|
||||
slice: [u8], //~^^^ HELP: cannot deserialize a dynamically sized struct
|
||||
}
|
||||
@@ -12,12 +12,15 @@
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate serde;
|
||||
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use self::serde::de::{self, Unexpected};
|
||||
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::collections::HashMap;
|
||||
|
||||
extern crate serde_test;
|
||||
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens,
|
||||
Token};
|
||||
use self::serde_test::{
|
||||
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
|
||||
assert_tokens, Token,
|
||||
};
|
||||
|
||||
trait MyDefault: Sized {
|
||||
fn my_default() -> Self;
|
||||
@@ -94,6 +97,50 @@ where
|
||||
a5: E,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct CollectOther {
|
||||
a: u32,
|
||||
b: u32,
|
||||
#[serde(flatten)]
|
||||
extra: HashMap<String, u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct FlattenStructEnumWrapper {
|
||||
#[serde(flatten)]
|
||||
data: FlattenStructEnum,
|
||||
#[serde(flatten)]
|
||||
extra: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
enum FlattenStructEnum {
|
||||
InsertInteger { index: u32, value: u32 },
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct FlattenStructTagContentEnumWrapper {
|
||||
outer: u32,
|
||||
#[serde(flatten)]
|
||||
data: FlattenStructTagContentEnumNewtype,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct FlattenStructTagContentEnumNewtype(pub FlattenStructTagContentEnum);
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
|
||||
enum FlattenStructTagContentEnum {
|
||||
InsertInteger { index: u32, value: u32 },
|
||||
NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct FlattenStructTagContentEnumNewtypeVariant {
|
||||
value: u32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_struct() {
|
||||
assert_de_tokens(
|
||||
@@ -478,12 +525,10 @@ enum RenameEnumSerializeDeserialize<A> {
|
||||
fn test_rename_enum() {
|
||||
assert_tokens(
|
||||
&RenameEnum::Batman,
|
||||
&[
|
||||
Token::UnitVariant {
|
||||
name: "Superhero",
|
||||
variant: "bruce_wayne",
|
||||
},
|
||||
],
|
||||
&[Token::UnitVariant {
|
||||
name: "Superhero",
|
||||
variant: "bruce_wayne",
|
||||
}],
|
||||
);
|
||||
|
||||
assert_tokens(
|
||||
@@ -612,6 +657,44 @@ fn test_skip_serializing_struct() {
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize)]
|
||||
struct SkipSerializingTupleStruct<'a, B, C>(
|
||||
&'a i8,
|
||||
#[serde(skip_serializing)] B,
|
||||
#[serde(skip_serializing_if = "ShouldSkip::should_skip")] C,
|
||||
)
|
||||
where
|
||||
C: ShouldSkip;
|
||||
|
||||
#[test]
|
||||
fn test_skip_serializing_tuple_struct() {
|
||||
let a = 1;
|
||||
assert_ser_tokens(
|
||||
&SkipSerializingTupleStruct(&a, 2, 3),
|
||||
&[
|
||||
Token::TupleStruct {
|
||||
name: "SkipSerializingTupleStruct",
|
||||
len: 2,
|
||||
},
|
||||
Token::I8(1),
|
||||
Token::I32(3),
|
||||
Token::TupleStructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_ser_tokens(
|
||||
&SkipSerializingTupleStruct(&a, 2, 123),
|
||||
&[
|
||||
Token::TupleStruct {
|
||||
name: "SkipSerializingTupleStruct",
|
||||
len: 1,
|
||||
},
|
||||
Token::I8(1),
|
||||
Token::TupleStructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct SkipStruct<B> {
|
||||
a: i8,
|
||||
@@ -660,6 +743,11 @@ where
|
||||
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
|
||||
c: C,
|
||||
},
|
||||
Tuple(
|
||||
&'a i8,
|
||||
#[serde(skip_serializing)] B,
|
||||
#[serde(skip_serializing_if = "ShouldSkip::should_skip")] C,
|
||||
),
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -698,6 +786,33 @@ fn test_skip_serializing_enum() {
|
||||
Token::StructVariantEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_ser_tokens(
|
||||
&SkipSerializingEnum::Tuple(&a, 2, 3),
|
||||
&[
|
||||
Token::TupleVariant {
|
||||
name: "SkipSerializingEnum",
|
||||
variant: "Tuple",
|
||||
len: 2,
|
||||
},
|
||||
Token::I8(1),
|
||||
Token::I32(3),
|
||||
Token::TupleVariantEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_ser_tokens(
|
||||
&SkipSerializingEnum::Tuple(&a, 2, 123),
|
||||
&[
|
||||
Token::TupleVariant {
|
||||
name: "SkipSerializingEnum",
|
||||
variant: "Tuple",
|
||||
len: 1,
|
||||
},
|
||||
Token::I8(1),
|
||||
Token::TupleVariantEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -1170,12 +1285,7 @@ fn test_missing_renamed_field_enum() {
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
enum InvalidLengthEnum {
|
||||
A(i32, i32, i32),
|
||||
B(
|
||||
#[serde(skip_deserializing)]
|
||||
i32,
|
||||
i32,
|
||||
i32,
|
||||
),
|
||||
B(#[serde(skip_deserializing)] i32, i32, i32),
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1190,7 +1300,7 @@ fn test_invalid_length_enum() {
|
||||
Token::I32(1),
|
||||
Token::TupleVariantEnd,
|
||||
],
|
||||
"invalid length 1, expected tuple of 3 elements",
|
||||
"invalid length 1, expected tuple variant InvalidLengthEnum::A with 3 elements",
|
||||
);
|
||||
assert_de_tokens_error::<InvalidLengthEnum>(
|
||||
&[
|
||||
@@ -1202,7 +1312,7 @@ fn test_invalid_length_enum() {
|
||||
Token::I32(1),
|
||||
Token::TupleVariantEnd,
|
||||
],
|
||||
"invalid length 1, expected tuple of 2 elements",
|
||||
"invalid length 1, expected tuple variant InvalidLengthEnum::B with 2 elements",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1267,3 +1377,688 @@ fn test_from_into_traits() {
|
||||
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(None), &[Token::None]);
|
||||
assert_de_tokens::<StructFromEnum>(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collect_other() {
|
||||
let mut extra = HashMap::new();
|
||||
extra.insert("c".into(), 3);
|
||||
assert_tokens(
|
||||
&CollectOther { a: 1, b: 2, extra },
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::U32(1),
|
||||
Token::Str("b"),
|
||||
Token::U32(2),
|
||||
Token::Str("c"),
|
||||
Token::U32(3),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_struct_enum() {
|
||||
let mut extra = HashMap::new();
|
||||
extra.insert("extra_key".into(), "extra value".into());
|
||||
let change_request = FlattenStructEnumWrapper {
|
||||
data: FlattenStructEnum::InsertInteger {
|
||||
index: 0,
|
||||
value: 42,
|
||||
},
|
||||
extra,
|
||||
};
|
||||
assert_de_tokens(
|
||||
&change_request,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("insert_integer"),
|
||||
Token::Map { len: None },
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_ser_tokens(
|
||||
&change_request,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("insert_integer"),
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
name: "insert_integer",
|
||||
},
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
Token::Str("extra_key"),
|
||||
Token::Str("extra value"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_struct_tag_content_enum() {
|
||||
let change_request = FlattenStructTagContentEnumWrapper {
|
||||
outer: 42,
|
||||
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::InsertInteger {
|
||||
index: 0,
|
||||
value: 42,
|
||||
}),
|
||||
};
|
||||
assert_de_tokens(
|
||||
&change_request,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::Str("type"),
|
||||
Token::Str("insert_integer"),
|
||||
Token::Str("value"),
|
||||
Token::Map { len: None },
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_ser_tokens(
|
||||
&change_request,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::Str("type"),
|
||||
Token::Str("insert_integer"),
|
||||
Token::Str("value"),
|
||||
Token::Struct {
|
||||
len: 2,
|
||||
name: "insert_integer",
|
||||
},
|
||||
Token::Str("index"),
|
||||
Token::U32(0),
|
||||
Token::Str("value"),
|
||||
Token::U32(42),
|
||||
Token::StructEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_struct_tag_content_enum_newtype() {
|
||||
let change_request = FlattenStructTagContentEnumWrapper {
|
||||
outer: 42,
|
||||
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::NewtypeVariant(
|
||||
FlattenStructTagContentEnumNewtypeVariant { value: 23 },
|
||||
)),
|
||||
};
|
||||
assert_de_tokens(
|
||||
&change_request,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::Str("type"),
|
||||
Token::Str("newtype_variant"),
|
||||
Token::Str("value"),
|
||||
Token::Map { len: None },
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::MapEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
assert_ser_tokens(
|
||||
&change_request,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("outer"),
|
||||
Token::U32(42),
|
||||
Token::Str("type"),
|
||||
Token::Str("newtype_variant"),
|
||||
Token::Str("value"),
|
||||
Token::Struct {
|
||||
len: 1,
|
||||
name: "FlattenStructTagContentEnumNewtypeVariant",
|
||||
},
|
||||
Token::Str("value"),
|
||||
Token::U32(23),
|
||||
Token::StructEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unknown_field_in_flatten() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct Outer {
|
||||
dummy: String,
|
||||
#[serde(flatten)]
|
||||
inner: Inner,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Inner {
|
||||
foo: HashMap<String, u32>,
|
||||
}
|
||||
|
||||
assert_de_tokens_error::<Outer>(
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Outer",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("dummy"),
|
||||
Token::Str("23"),
|
||||
Token::Str("foo"),
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::U32(1),
|
||||
Token::Str("b"),
|
||||
Token::U32(2),
|
||||
Token::MapEnd,
|
||||
Token::Str("bar"),
|
||||
Token::U32(23),
|
||||
Token::StructEnd,
|
||||
],
|
||||
"unknown field `bar`",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complex_flatten() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Outer {
|
||||
y: u32,
|
||||
#[serde(flatten)]
|
||||
first: First,
|
||||
#[serde(flatten)]
|
||||
second: Second,
|
||||
z: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct First {
|
||||
a: u32,
|
||||
b: bool,
|
||||
c: Vec<String>,
|
||||
d: String,
|
||||
e: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Second {
|
||||
f: u32,
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&Outer {
|
||||
y: 0,
|
||||
first: First {
|
||||
a: 1,
|
||||
b: true,
|
||||
c: vec!["a".into(), "b".into()],
|
||||
d: "c".into(),
|
||||
e: Some(2),
|
||||
},
|
||||
second: Second { f: 3 },
|
||||
z: 4,
|
||||
},
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("y"),
|
||||
Token::U32(0),
|
||||
Token::Str("a"),
|
||||
Token::U32(1),
|
||||
Token::Str("b"),
|
||||
Token::Bool(true),
|
||||
Token::Str("c"),
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::Str("a"),
|
||||
Token::Str("b"),
|
||||
Token::SeqEnd,
|
||||
Token::Str("d"),
|
||||
Token::Str("c"),
|
||||
Token::Str("e"),
|
||||
Token::U64(2),
|
||||
Token::Str("f"),
|
||||
Token::U32(3),
|
||||
Token::Str("z"),
|
||||
Token::U32(4),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_ser_tokens(
|
||||
&Outer {
|
||||
y: 0,
|
||||
first: First {
|
||||
a: 1,
|
||||
b: true,
|
||||
c: vec!["a".into(), "b".into()],
|
||||
d: "c".into(),
|
||||
e: Some(2),
|
||||
},
|
||||
second: Second { f: 3 },
|
||||
z: 4,
|
||||
},
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("y"),
|
||||
Token::U32(0),
|
||||
Token::Str("a"),
|
||||
Token::U32(1),
|
||||
Token::Str("b"),
|
||||
Token::Bool(true),
|
||||
Token::Str("c"),
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::Str("a"),
|
||||
Token::Str("b"),
|
||||
Token::SeqEnd,
|
||||
Token::Str("d"),
|
||||
Token::Str("c"),
|
||||
Token::Str("e"),
|
||||
Token::Some,
|
||||
Token::U64(2),
|
||||
Token::Str("f"),
|
||||
Token::U32(3),
|
||||
Token::Str("z"),
|
||||
Token::U32(4),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_unsupported_type() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct Outer {
|
||||
outer: String,
|
||||
#[serde(flatten)]
|
||||
inner: String,
|
||||
}
|
||||
|
||||
assert_ser_tokens_error(
|
||||
&Outer {
|
||||
outer: "foo".into(),
|
||||
inner: "bar".into(),
|
||||
},
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("outer"),
|
||||
Token::Str("foo"),
|
||||
],
|
||||
"can only flatten structs and maps (got a string)",
|
||||
);
|
||||
assert_de_tokens_error::<Outer>(
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("outer"),
|
||||
Token::Str("foo"),
|
||||
Token::Str("a"),
|
||||
Token::Str("b"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
"can only flatten structs and maps",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_non_string_keys() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
struct TestStruct {
|
||||
name: String,
|
||||
age: u32,
|
||||
#[serde(flatten)]
|
||||
mapping: HashMap<u32, u32>,
|
||||
}
|
||||
|
||||
let mut mapping = HashMap::new();
|
||||
mapping.insert(0, 42);
|
||||
assert_tokens(
|
||||
&TestStruct {
|
||||
name: "peter".into(),
|
||||
age: 3,
|
||||
mapping,
|
||||
},
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("name"),
|
||||
Token::Str("peter"),
|
||||
Token::Str("age"),
|
||||
Token::U32(3),
|
||||
Token::U32(0),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lifetime_propagation_for_flatten() {
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq)]
|
||||
struct A<T> {
|
||||
#[serde(flatten)]
|
||||
t: T,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq)]
|
||||
struct B<'a> {
|
||||
#[serde(flatten, borrow)]
|
||||
t: HashMap<&'a str, u32>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq)]
|
||||
struct C<'a> {
|
||||
#[serde(flatten, borrow)]
|
||||
t: HashMap<&'a [u8], u32>,
|
||||
}
|
||||
|
||||
let mut owned_map = HashMap::new();
|
||||
owned_map.insert("x".to_string(), 42u32);
|
||||
assert_tokens(
|
||||
&A { t: owned_map },
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("x"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
let mut borrowed_map = HashMap::new();
|
||||
borrowed_map.insert("x", 42u32);
|
||||
assert_ser_tokens(
|
||||
&B {
|
||||
t: borrowed_map.clone(),
|
||||
},
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::BorrowedStr("x"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&B { t: borrowed_map },
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::BorrowedStr("x"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
let mut borrowed_map = HashMap::new();
|
||||
borrowed_map.insert(&b"x"[..], 42u32);
|
||||
assert_ser_tokens(
|
||||
&C {
|
||||
t: borrowed_map.clone(),
|
||||
},
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Seq { len: Some(1) },
|
||||
Token::U8(120),
|
||||
Token::SeqEnd,
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&C { t: borrowed_map },
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::BorrowedBytes(b"x"),
|
||||
Token::U32(42),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_enum_newtype() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct S {
|
||||
#[serde(flatten)]
|
||||
flat: E,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
enum E {
|
||||
Q(HashMap<String, String>),
|
||||
}
|
||||
|
||||
let e = E::Q({
|
||||
let mut map = HashMap::new();
|
||||
map.insert("k".to_owned(), "v".to_owned());
|
||||
map
|
||||
});
|
||||
let s = S { flat: e };
|
||||
|
||||
assert_tokens(
|
||||
&s,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("Q"),
|
||||
Token::Map { len: Some(1) },
|
||||
Token::Str("k"),
|
||||
Token::Str("v"),
|
||||
Token::MapEnd,
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten_internally_tagged() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct S {
|
||||
#[serde(flatten)]
|
||||
x: X,
|
||||
#[serde(flatten)]
|
||||
y: Y,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(tag = "typeX")]
|
||||
enum X {
|
||||
A { a: i32 },
|
||||
B { b: i32 },
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(tag = "typeY")]
|
||||
enum Y {
|
||||
C { c: i32 },
|
||||
D { d: i32 },
|
||||
}
|
||||
|
||||
let s = S {
|
||||
x: X::B { b: 1 },
|
||||
y: Y::D { d: 2 },
|
||||
};
|
||||
|
||||
assert_tokens(
|
||||
&s,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("typeX"),
|
||||
Token::Str("B"),
|
||||
Token::Str("b"),
|
||||
Token::I32(1),
|
||||
Token::Str("typeY"),
|
||||
Token::Str("D"),
|
||||
Token::Str("d"),
|
||||
Token::I32(2),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_externally_tagged_enum_containing_flatten() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
enum Data {
|
||||
A {
|
||||
a: i32,
|
||||
#[serde(flatten)]
|
||||
flat: Flat,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Flat {
|
||||
b: i32,
|
||||
}
|
||||
|
||||
let data = Data::A {
|
||||
a: 0,
|
||||
flat: Flat { b: 0 },
|
||||
};
|
||||
|
||||
assert_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::NewtypeVariant {
|
||||
name: "Data",
|
||||
variant: "A",
|
||||
},
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(0),
|
||||
Token::Str("b"),
|
||||
Token::I32(0),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_internally_tagged_enum_containing_flatten() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(tag = "t")]
|
||||
enum Data {
|
||||
A {
|
||||
a: i32,
|
||||
#[serde(flatten)]
|
||||
flat: Flat,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Flat {
|
||||
b: i32,
|
||||
}
|
||||
|
||||
let data = Data::A {
|
||||
a: 0,
|
||||
flat: Flat { b: 0 },
|
||||
};
|
||||
|
||||
assert_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("t"),
|
||||
Token::Str("A"),
|
||||
Token::Str("a"),
|
||||
Token::I32(0),
|
||||
Token::Str("b"),
|
||||
Token::I32(0),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_adjacently_tagged_enum_containing_flatten() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum Data {
|
||||
A {
|
||||
a: i32,
|
||||
#[serde(flatten)]
|
||||
flat: Flat,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Flat {
|
||||
b: i32,
|
||||
}
|
||||
|
||||
let data = Data::A {
|
||||
a: 0,
|
||||
flat: Flat { b: 0 },
|
||||
};
|
||||
|
||||
assert_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Data",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("t"),
|
||||
Token::Str("A"),
|
||||
Token::Str("c"),
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(0),
|
||||
Token::Str("b"),
|
||||
Token::I32(0),
|
||||
Token::MapEnd,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_untagged_enum_containing_flatten() {
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
#[serde(untagged)]
|
||||
enum Data {
|
||||
A {
|
||||
a: i32,
|
||||
#[serde(flatten)]
|
||||
flat: Flat,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||
struct Flat {
|
||||
b: i32,
|
||||
}
|
||||
|
||||
let data = Data::A {
|
||||
a: 0,
|
||||
flat: Flat { b: 0 },
|
||||
};
|
||||
|
||||
assert_tokens(
|
||||
&data,
|
||||
&[
|
||||
Token::Map { len: None },
|
||||
Token::Str("a"),
|
||||
Token::I32(0),
|
||||
Token::Str("b"),
|
||||
Token::I32(0),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,24 +6,26 @@
|
||||
// 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;
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::net;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
use std::default::Default;
|
||||
use std::ffi::{CString, OsString};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::net;
|
||||
use std::num::Wrapping;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::{Rc, Weak as RcWeak};
|
||||
use std::sync::{Arc, Weak as ArcWeak};
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
use std::ffi::CStr;
|
||||
|
||||
extern crate serde;
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
extern crate fnv;
|
||||
use self::fnv::FnvHasher;
|
||||
@@ -180,6 +182,27 @@ macro_rules! declare_error_tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SkipPartialEq<T>(T);
|
||||
|
||||
impl<'de, T> Deserialize<'de> for SkipPartialEq<T>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
T::deserialize(deserializer).map(SkipPartialEq)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for SkipPartialEq<T> {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) {
|
||||
#[derive(PartialEq, Debug, Deserialize)]
|
||||
struct IgnoreBase {
|
||||
@@ -786,11 +809,33 @@ declare_tests! {
|
||||
Token::Bool(true),
|
||||
],
|
||||
}
|
||||
test_rc_weak_some {
|
||||
SkipPartialEq(RcWeak::<bool>::new()) => &[
|
||||
Token::Some,
|
||||
Token::Bool(true),
|
||||
],
|
||||
}
|
||||
test_rc_weak_none {
|
||||
SkipPartialEq(RcWeak::<bool>::new()) => &[
|
||||
Token::None,
|
||||
],
|
||||
}
|
||||
test_arc {
|
||||
Arc::new(true) => &[
|
||||
Token::Bool(true),
|
||||
],
|
||||
}
|
||||
test_arc_weak_some {
|
||||
SkipPartialEq(ArcWeak::<bool>::new()) => &[
|
||||
Token::Some,
|
||||
Token::Bool(true),
|
||||
],
|
||||
}
|
||||
test_arc_weak_none {
|
||||
SkipPartialEq(ArcWeak::<bool>::new()) => &[
|
||||
Token::None,
|
||||
],
|
||||
}
|
||||
test_wrapping {
|
||||
Wrapping(1usize) => &[
|
||||
Token::U32(1),
|
||||
|
||||
+170
-55
@@ -17,8 +17,8 @@
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate serde;
|
||||
use self::serde::ser::{Serialize, Serializer};
|
||||
use self::serde::de::{DeserializeOwned, Deserializer};
|
||||
use self::serde::ser::{Serialize, Serializer};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::marker::PhantomData;
|
||||
@@ -92,14 +92,10 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum EnumWith<T> {
|
||||
Unit,
|
||||
Newtype(
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X,
|
||||
),
|
||||
Newtype(#[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,
|
||||
@@ -122,17 +118,13 @@ fn test_gen() {
|
||||
assert_ser::<MultipleRef<i32>>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Newtype(
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X,
|
||||
);
|
||||
struct Newtype(#[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>>();
|
||||
|
||||
@@ -191,12 +183,16 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[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>>();
|
||||
@@ -204,17 +200,58 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[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>>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(bound = "D: SerializeWith + DeserializeWith")]
|
||||
enum VariantWithTraits1<D, E> {
|
||||
#[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"
|
||||
)]
|
||||
E(E),
|
||||
}
|
||||
assert::<VariantWithTraits1<X, X>>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
|
||||
enum VariantWithTraits2<D, E> {
|
||||
#[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")
|
||||
)]
|
||||
E(E),
|
||||
}
|
||||
assert::<VariantWithTraits2<X, X>>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct CowStr<'a>(Cow<'a, str>);
|
||||
assert::<CowStr>();
|
||||
@@ -270,17 +307,11 @@ fn test_gen() {
|
||||
struct EmptyTupleDenyUnknown();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct TupleSkipAll(
|
||||
#[serde(skip_deserializing)]
|
||||
u8,
|
||||
);
|
||||
struct TupleSkipAll(#[serde(skip_deserializing)] u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct TupleSkipAllDenyUnknown(
|
||||
#[serde(skip_deserializing)]
|
||||
u8,
|
||||
);
|
||||
struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum EmptyEnum {}
|
||||
@@ -305,10 +336,7 @@ fn test_gen() {
|
||||
#[serde(skip_deserializing)]
|
||||
f: u8,
|
||||
},
|
||||
TupleSkip(
|
||||
#[serde(skip_deserializing)]
|
||||
u8,
|
||||
),
|
||||
TupleSkip(#[serde(skip_deserializing)] u8),
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
@@ -321,10 +349,7 @@ fn test_gen() {
|
||||
#[serde(skip_deserializing)]
|
||||
f: u8,
|
||||
},
|
||||
TupleSkip(
|
||||
#[serde(skip_deserializing)]
|
||||
u8,
|
||||
),
|
||||
TupleSkip(#[serde(skip_deserializing)] u8),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -344,9 +369,7 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged, remote = "Or")]
|
||||
enum OrDef<A, B> {
|
||||
#[allow(dead_code)]
|
||||
A(A),
|
||||
#[allow(dead_code)]
|
||||
B(B),
|
||||
}
|
||||
|
||||
@@ -386,10 +409,11 @@ fn test_gen() {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum ExternallyTaggedVariantWith {
|
||||
#[allow(dead_code)]
|
||||
Normal { f1: String },
|
||||
#[serde(remote = "Self")]
|
||||
struct RemoteSelf;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum ExternallyTaggedVariantWith {
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
@@ -400,6 +424,11 @@ fn test_gen() {
|
||||
#[allow(dead_code)]
|
||||
Tuple(String, u8),
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Struct1 { x: X },
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
@@ -415,14 +444,16 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(tag = "t")]
|
||||
enum InternallyTaggedVariantWith {
|
||||
#[allow(dead_code)]
|
||||
Normal { f1: String },
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Newtype(X),
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Struct1 { x: X },
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
@@ -438,9 +469,6 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum AdjacentlyTaggedVariantWith {
|
||||
#[allow(dead_code)]
|
||||
Normal { f1: String },
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
@@ -451,6 +479,11 @@ fn test_gen() {
|
||||
#[allow(dead_code)]
|
||||
Tuple(String, u8),
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Struct1 { x: X },
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
@@ -466,9 +499,6 @@ fn test_gen() {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum UntaggedVariantWith {
|
||||
#[allow(dead_code)]
|
||||
Normal { f1: String },
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
@@ -479,6 +509,11 @@ fn test_gen() {
|
||||
#[allow(dead_code)]
|
||||
Tuple(String, u8),
|
||||
|
||||
#[serde(serialize_with = "ser_x")]
|
||||
#[serde(deserialize_with = "de_x")]
|
||||
#[allow(dead_code)]
|
||||
Struct1 { x: X },
|
||||
|
||||
#[serde(serialize_with = "serialize_some_other_variant")]
|
||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||
#[allow(dead_code)]
|
||||
@@ -491,6 +526,13 @@ fn test_gen() {
|
||||
}
|
||||
assert_ser::<UntaggedVariantWith>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct FlattenWith {
|
||||
#[serde(flatten, serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
}
|
||||
assert::<FlattenWith>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct StaticStrStruct<'a> {
|
||||
a: &'a str,
|
||||
@@ -519,7 +561,9 @@ fn test_gen() {
|
||||
assert::<SkippedStaticStr>();
|
||||
|
||||
macro_rules! T {
|
||||
() => { () }
|
||||
() => {
|
||||
()
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@@ -528,6 +572,77 @@ fn test_gen() {
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
assert::<TypeMacro<X>>();
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct BigArray {
|
||||
#[serde(serialize_with = "<[_]>::serialize")]
|
||||
array: [u8; 256],
|
||||
}
|
||||
assert_ser::<BigArray>();
|
||||
|
||||
trait AssocSerde {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
struct NoSerdeImpl;
|
||||
impl AssocSerde for NoSerdeImpl {
|
||||
type Assoc = u32;
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct AssocDerive<T: AssocSerde> {
|
||||
assoc: T::Assoc,
|
||||
}
|
||||
|
||||
assert::<AssocDerive<NoSerdeImpl>>();
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct AssocDeriveMulti<S, T: AssocSerde> {
|
||||
s: S,
|
||||
assoc: T::Assoc,
|
||||
}
|
||||
|
||||
assert::<AssocDeriveMulti<i32, NoSerdeImpl>>();
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum EmptyAdjacentlyTagged {
|
||||
#[allow(dead_code)]
|
||||
Struct {},
|
||||
#[allow(dead_code)]
|
||||
Tuple(),
|
||||
}
|
||||
|
||||
assert_ser::<EmptyAdjacentlyTagged>();
|
||||
|
||||
mod restricted {
|
||||
mod inner {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Restricted {
|
||||
pub(super) a: usize,
|
||||
pub(in super::inner) b: usize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum AdjacentlyTaggedVoid {}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum SkippedVariant<T> {
|
||||
#[serde(skip)]
|
||||
#[allow(dead_code)]
|
||||
T(T),
|
||||
Unit,
|
||||
}
|
||||
|
||||
assert::<SkippedVariant<X>>();
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ImpliciltyBorrowedOption<'a> {
|
||||
option: std::option::Option<&'a str>,
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+371
-26
@@ -7,13 +7,19 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(trivial_numeric_casts)]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate serde;
|
||||
extern crate serde_test;
|
||||
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens,
|
||||
Token};
|
||||
|
||||
mod bytes;
|
||||
|
||||
use self::serde_test::{
|
||||
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token,
|
||||
};
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::marker::PhantomData;
|
||||
@@ -220,12 +226,10 @@ fn test_de_named_map() {
|
||||
fn test_ser_enum_unit() {
|
||||
assert_ser_tokens(
|
||||
&SerEnum::Unit::<u32, u32, u32>,
|
||||
&[
|
||||
Token::UnitVariant {
|
||||
name: "SerEnum",
|
||||
variant: "Unit",
|
||||
},
|
||||
],
|
||||
&[Token::UnitVariant {
|
||||
name: "SerEnum",
|
||||
variant: "Unit",
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -290,12 +294,10 @@ fn test_ser_enum_map() {
|
||||
fn test_de_enum_unit() {
|
||||
assert_tokens(
|
||||
&DeEnum::Unit::<u32, u32, u32>,
|
||||
&[
|
||||
Token::UnitVariant {
|
||||
name: "DeEnum",
|
||||
variant: "Unit",
|
||||
},
|
||||
],
|
||||
&[Token::UnitVariant {
|
||||
name: "DeEnum",
|
||||
variant: "Unit",
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -440,6 +442,51 @@ fn test_generic_newtype_struct() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_untagged_newtype_struct() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum E {
|
||||
Newtype(GenericNewTypeStruct<u32>),
|
||||
Null,
|
||||
}
|
||||
|
||||
assert_tokens(
|
||||
&E::Newtype(GenericNewTypeStruct(5u32)),
|
||||
&[
|
||||
Token::NewtypeStruct {
|
||||
name: "GenericNewTypeStruct",
|
||||
},
|
||||
Token::U32(5),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_adjacently_tagged_newtype_struct() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "t", content = "c")]
|
||||
enum E {
|
||||
Newtype(GenericNewTypeStruct<u32>),
|
||||
Null,
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&E::Newtype(GenericNewTypeStruct(5u32)),
|
||||
&[
|
||||
Token::Struct { name: "E", len: 2 },
|
||||
Token::Str("c"),
|
||||
Token::NewtypeStruct {
|
||||
name: "GenericNewTypeStruct",
|
||||
},
|
||||
Token::U32(5),
|
||||
Token::Str("t"),
|
||||
Token::Str("Newtype"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generic_tuple_struct() {
|
||||
assert_tokens(
|
||||
@@ -460,12 +507,10 @@ fn test_generic_tuple_struct() {
|
||||
fn test_generic_enum_unit() {
|
||||
assert_tokens(
|
||||
&GenericEnum::Unit::<u32, u32>,
|
||||
&[
|
||||
Token::UnitVariant {
|
||||
name: "GenericEnum",
|
||||
variant: "Unit",
|
||||
},
|
||||
],
|
||||
&[Token::UnitVariant {
|
||||
name: "GenericEnum",
|
||||
variant: "Unit",
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -777,6 +822,166 @@ fn test_internally_tagged_enum() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_internally_tagged_bytes() {
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
enum InternallyTagged {
|
||||
String {
|
||||
string: String,
|
||||
},
|
||||
Bytes {
|
||||
#[serde(with = "bytes")]
|
||||
bytes: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "String",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("String"),
|
||||
Token::Str("string"),
|
||||
Token::Str("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "String",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("String"),
|
||||
Token::Str("string"),
|
||||
Token::String("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "String",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("String"),
|
||||
Token::Str("string"),
|
||||
Token::Bytes(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "String",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("String"),
|
||||
Token::Str("string"),
|
||||
Token::ByteBuf(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Bytes",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("Bytes"),
|
||||
Token::Str("bytes"),
|
||||
Token::Str("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Bytes",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("Bytes"),
|
||||
Token::Str("bytes"),
|
||||
Token::String("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Bytes",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("Bytes"),
|
||||
Token::Str("bytes"),
|
||||
Token::Bytes(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Bytes",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("Bytes"),
|
||||
Token::Str("bytes"),
|
||||
Token::ByteBuf(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&InternallyTagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Bytes",
|
||||
len: 2,
|
||||
},
|
||||
Token::Str("type"),
|
||||
Token::Str("Bytes"),
|
||||
Token::Str("bytes"),
|
||||
Token::Seq { len: Some(1) },
|
||||
Token::U8(0),
|
||||
Token::SeqEnd,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
@@ -1196,12 +1401,10 @@ fn test_enum_in_untagged_enum() {
|
||||
|
||||
assert_tokens(
|
||||
&Outer::Inner(Inner::Unit),
|
||||
&[
|
||||
Token::UnitVariant {
|
||||
name: "Inner",
|
||||
variant: "Unit",
|
||||
},
|
||||
],
|
||||
&[Token::UnitVariant {
|
||||
name: "Inner",
|
||||
variant: "Unit",
|
||||
}],
|
||||
);
|
||||
|
||||
assert_tokens(
|
||||
@@ -1244,6 +1447,148 @@ fn test_enum_in_untagged_enum() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_untagged_bytes() {
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum Untagged {
|
||||
String {
|
||||
string: String,
|
||||
},
|
||||
Bytes {
|
||||
#[serde(with = "bytes")]
|
||||
bytes: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("string"),
|
||||
Token::Str("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("string"),
|
||||
Token::String("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("string"),
|
||||
Token::Bytes(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::String {
|
||||
string: "\0".to_owned(),
|
||||
},
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("string"),
|
||||
Token::ByteBuf(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::Str("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::String("\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::Bytes(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::ByteBuf(b"\0"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Untagged::Bytes { bytes: vec![0] },
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Untagged",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("bytes"),
|
||||
Token::Seq { len: Some(1) },
|
||||
Token::U8(0),
|
||||
Token::SeqEnd,
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rename_all() {
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -119,10 +121,7 @@ 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")]
|
||||
@@ -130,34 +129,22 @@ struct PrimitivePubDef(u8);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::NewtypePriv")]
|
||||
struct NewtypePrivDef(
|
||||
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")]
|
||||
remote::Unit,
|
||||
);
|
||||
struct NewtypePrivDef(#[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")]
|
||||
@@ -173,10 +160,8 @@ struct StructPrivDef {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(remote = "remote::StructPub")]
|
||||
struct StructPubDef {
|
||||
#[allow(dead_code)]
|
||||
a: u8,
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[serde(with = "UnitDef")]
|
||||
b: remote::Unit,
|
||||
}
|
||||
|
||||
@@ -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![
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
extern crate serde_derive;
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::net;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
use std::ffi::CString;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::mem;
|
||||
use std::net;
|
||||
use std::num::Wrapping;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::{Rc, Weak as RcWeak};
|
||||
use std::sync::{Arc, Weak as ArcWeak};
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::str;
|
||||
@@ -398,11 +399,41 @@ declare_tests! {
|
||||
Token::Bool(true),
|
||||
],
|
||||
}
|
||||
test_rc_weak_some {
|
||||
{
|
||||
let rc = Rc::new(true);
|
||||
mem::forget(rc.clone());
|
||||
Rc::downgrade(&rc)
|
||||
} => &[
|
||||
Token::Some,
|
||||
Token::Bool(true),
|
||||
],
|
||||
}
|
||||
test_rc_weak_none {
|
||||
RcWeak::<bool>::new() => &[
|
||||
Token::None,
|
||||
],
|
||||
}
|
||||
test_arc {
|
||||
Arc::new(true) => &[
|
||||
Token::Bool(true),
|
||||
],
|
||||
}
|
||||
test_arc_weak_some {
|
||||
{
|
||||
let arc = Arc::new(true);
|
||||
mem::forget(arc.clone());
|
||||
Arc::downgrade(&arc)
|
||||
} => &[
|
||||
Token::Some,
|
||||
Token::Bool(true),
|
||||
],
|
||||
}
|
||||
test_arc_weak_none {
|
||||
ArcWeak::<bool>::new() => &[
|
||||
Token::None,
|
||||
],
|
||||
}
|
||||
test_wrapping {
|
||||
Wrapping(1usize) => &[
|
||||
Token::U64(1),
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
extern crate serde_derive;
|
||||
|
||||
extern crate serde;
|
||||
use serde::Deserialize;
|
||||
use serde::de::{value, IntoDeserializer};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[test]
|
||||
fn test_u32_to_enum() {
|
||||
|
||||
@@ -55,6 +55,7 @@ else
|
||||
channel build
|
||||
cd "$DIR/test_suite"
|
||||
channel test --features unstable
|
||||
channel build --tests --features proc-macro2/nightly
|
||||
if [ -z "${APPVEYOR}" ]; then
|
||||
cd "$DIR/test_suite/no_std"
|
||||
channel build
|
||||
@@ -86,4 +87,10 @@ else
|
||||
channel build --no-default-features
|
||||
cd "$DIR/serde_test"
|
||||
channel build
|
||||
|
||||
CHANNEL=1.15.0
|
||||
cd "$DIR"
|
||||
cargo clean
|
||||
cd "$DIR/serde_derive"
|
||||
channel build
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user