mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-26 03:57:56 +00:00
Compare commits
224 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| 9cfcd78c87 | |||
| 4751627f1c | |||
| ae59c6b6d2 | |||
| 4973d7a62d | |||
| ed6a1de311 | |||
| ab234be025 | |||
| ee75e6c0e9 | |||
| c2b390fe63 | |||
| 56d5d7f761 | |||
| 0b89bc920e | |||
| 0dac13e4db | |||
| 0c2e91f28a | |||
| 13e7bee0e6 | |||
| 65104aca9c | |||
| 9360094ba7 | |||
| 3700779bfa | |||
| d9e894911f | |||
| 85e3ddc2b8 | |||
| ccae35d92a | |||
| 61ca928325 | |||
| a93f2ebff0 | |||
| a45f1ae915 | |||
| 9641978481 | |||
| ffd2017c6f | |||
| b7eb42aa6b | |||
| 750f8ba299 | |||
| 49cdef074d | |||
| aa86b04714 | |||
| c887a0b472 | |||
| 34936be574 | |||
| e354dd0c7f | |||
| bc221abb04 | |||
| ab5e8780ab | |||
| 0c34e06e51 | |||
| 4a0c4e0c25 | |||
| 8c34e0940f | |||
| eb6bf16a51 | |||
| 797d049db5 | |||
| d61a373f12 | |||
| e0eea551b4 | |||
| c650a92bf7 |
@@ -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
|
[Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master
|
||||||
[travis]: https://travis-ci.org/serde-rs/serde
|
[travis]: https://travis-ci.org/serde-rs/serde
|
||||||
[Latest Version]: https://img.shields.io/crates/v/serde.svg
|
[Latest Version]: https://img.shields.io/crates/v/serde.svg
|
||||||
[crates.io]: https://crates.io/crates/serde
|
[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.**
|
**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:
|
||||||
# Install rust, x86_64-pc-windows-msvc host
|
# 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%
|
- 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
|
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
|
||||||
- rustc -vV
|
- rustc -vV
|
||||||
|
|||||||
+1
-5
@@ -1,5 +1 @@
|
|||||||
fn_args_layout = "Block"
|
error_on_line_overflow = false
|
||||||
array_layout = "Block"
|
|
||||||
where_style = "Rfc"
|
|
||||||
generics_indent = "Block"
|
|
||||||
fn_call_style = "Block"
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.21" # remember to update html_root_url
|
version = "1.0.43" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A generic serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
|
|||||||
+135
-45
@@ -9,33 +9,33 @@
|
|||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
macro_rules! int_to_int {
|
macro_rules! int_to_int {
|
||||||
($dst:ident, $n:ident) => (
|
($dst:ident, $n:ident) => {
|
||||||
if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 {
|
if $dst::min_value() as i64 <= $n as i64 && $n as i64 <= $dst::max_value() as i64 {
|
||||||
Some($n as $dst)
|
Some($n as $dst)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! int_to_uint {
|
macro_rules! int_to_uint {
|
||||||
($dst:ident, $n:ident) => (
|
($dst:ident, $n:ident) => {
|
||||||
if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
|
if 0 <= $n && $n as u64 <= $dst::max_value() as u64 {
|
||||||
Some($n as $dst)
|
Some($n as $dst)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! uint_to {
|
macro_rules! uint_to {
|
||||||
($dst:ident, $n:ident) => (
|
($dst:ident, $n:ident) => {
|
||||||
if $n as u64 <= $dst::MAX as u64 {
|
if $n as u64 <= $dst::max_value() as u64 {
|
||||||
Some($n as $dst)
|
Some($n as $dst)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
)
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromPrimitive: Sized {
|
pub trait FromPrimitive: Sized {
|
||||||
@@ -52,54 +52,144 @@ pub trait FromPrimitive: Sized {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_from_primitive_for_int {
|
macro_rules! impl_from_primitive_for_int {
|
||||||
($t:ident) => (
|
($t:ident) => {
|
||||||
impl FromPrimitive for $t {
|
impl FromPrimitive for $t {
|
||||||
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!($t, n) }
|
#[inline]
|
||||||
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!($t, n) }
|
fn from_isize(n: isize) -> Option<Self> {
|
||||||
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) }
|
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]
|
||||||
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
|
fn from_i8(n: i8) -> Option<Self> {
|
||||||
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
|
int_to_int!($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]
|
||||||
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
|
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 {
|
macro_rules! impl_from_primitive_for_uint {
|
||||||
($t:ident) => (
|
($t:ident) => {
|
||||||
impl FromPrimitive for $t {
|
impl FromPrimitive for $t {
|
||||||
#[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!($t, n) }
|
#[inline]
|
||||||
#[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!($t, n) }
|
fn from_isize(n: isize) -> Option<Self> {
|
||||||
#[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) }
|
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]
|
||||||
#[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
|
fn from_i8(n: i8) -> Option<Self> {
|
||||||
#[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
|
int_to_uint!($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]
|
||||||
#[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
|
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 {
|
macro_rules! impl_from_primitive_for_float {
|
||||||
($t:ident) => (
|
($t:ident) => {
|
||||||
impl FromPrimitive for $t {
|
impl FromPrimitive for $t {
|
||||||
#[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
|
#[inline]
|
||||||
#[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
|
fn from_isize(n: isize) -> Option<Self> {
|
||||||
#[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as 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]
|
||||||
#[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
|
fn from_i8(n: i8) -> Option<Self> {
|
||||||
#[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as 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]
|
||||||
#[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
|
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);
|
impl_from_primitive_for_int!(isize);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use de::{Deserialize, Deserializer, Visitor, SeqAccess, MapAccess, Error};
|
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
||||||
|
|
||||||
/// An efficient way of discarding data from a deserializer.
|
/// An efficient way of discarding data from a deserializer.
|
||||||
///
|
///
|
||||||
|
|||||||
+385
-94
@@ -15,6 +15,7 @@ use de::{Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, Va
|
|||||||
use de::MapAccess;
|
use de::MapAccess;
|
||||||
|
|
||||||
use de::from_primitive::FromPrimitive;
|
use de::from_primitive::FromPrimitive;
|
||||||
|
use private::de::InPlaceSeed;
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
use private::de::size_hint;
|
use private::de::size_hint;
|
||||||
@@ -210,6 +211,8 @@ impl<'de> Deserialize<'de> for char {
|
|||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
struct StringVisitor;
|
struct StringVisitor;
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
struct StringInPlaceVisitor<'a>(&'a mut String);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<'de> Visitor<'de> for StringVisitor {
|
impl<'de> Visitor<'de> for StringVisitor {
|
||||||
@@ -249,7 +252,66 @@ impl<'de> Visitor<'de> for StringVisitor {
|
|||||||
{
|
{
|
||||||
match String::from_utf8(v) {
|
match String::from_utf8(v) {
|
||||||
Ok(s) => Ok(s),
|
Ok(s) => Ok(s),
|
||||||
Err(e) => Err(Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self),),
|
Err(e) => Err(Error::invalid_value(
|
||||||
|
Unexpected::Bytes(&e.into_bytes()),
|
||||||
|
&self,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> {
|
||||||
|
type Value = ();
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a string")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<(), E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
self.0.clear();
|
||||||
|
self.0.push_str(v);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E>(self, v: String) -> Result<(), E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
*self.0 = v;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<(), E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
match str::from_utf8(v) {
|
||||||
|
Ok(s) => {
|
||||||
|
self.0.clear();
|
||||||
|
self.0.push_str(s);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<(), E>
|
||||||
|
where
|
||||||
|
E: Error,
|
||||||
|
{
|
||||||
|
match String::from_utf8(v) {
|
||||||
|
Ok(s) => {
|
||||||
|
*self.0 = s;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => Err(Error::invalid_value(
|
||||||
|
Unexpected::Bytes(&e.into_bytes()),
|
||||||
|
&self,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,6 +324,13 @@ impl<'de> Deserialize<'de> for String {
|
|||||||
{
|
{
|
||||||
deserializer.deserialize_string(StringVisitor)
|
deserializer.deserialize_string(StringVisitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_string(StringInPlaceVisitor(place))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -401,7 +470,11 @@ impl<'de> Deserialize<'de> for CString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! forwarded_impl {
|
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 {
|
impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -465,17 +538,25 @@ where
|
|||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
deserializer.deserialize_option(OptionVisitor { marker: PhantomData })
|
deserializer.deserialize_option(OptionVisitor {
|
||||||
|
marker: PhantomData,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The Some variant's repr is opaque, so we can't play cute tricks with its
|
||||||
|
// tag to have deserialize_in_place build the content in place unconditionally.
|
||||||
|
//
|
||||||
|
// FIXME: investigate whether branching on the old value being Some to
|
||||||
|
// deserialize_in_place the value is profitable (probably data-dependent?)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct PhantomDataVisitor<T> {
|
struct PhantomDataVisitor<T: ?Sized> {
|
||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, T> Visitor<'de> for PhantomDataVisitor<T> {
|
impl<'de, T: ?Sized> Visitor<'de> for PhantomDataVisitor<T> {
|
||||||
type Value = PhantomData<T>;
|
type Value = PhantomData<T>;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
@@ -491,12 +572,14 @@ impl<'de, T> Visitor<'de> for PhantomDataVisitor<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, T> Deserialize<'de> for PhantomData<T> {
|
impl<'de, T: ?Sized> Deserialize<'de> for PhantomData<T> {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<PhantomData<T>, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let visitor = PhantomDataVisitor { marker: PhantomData };
|
let visitor = PhantomDataVisitor {
|
||||||
|
marker: PhantomData,
|
||||||
|
};
|
||||||
deserializer.deserialize_unit_struct("PhantomData", visitor)
|
deserializer.deserialize_unit_struct("PhantomData", visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -509,7 +592,9 @@ macro_rules! seq_impl {
|
|||||||
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
|
$ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound1:ident $(+ $bound2:ident)*)* >,
|
||||||
$access:ident,
|
$access:ident,
|
||||||
$ctor:expr,
|
$ctor:expr,
|
||||||
|
$clear:expr,
|
||||||
$with_capacity:expr,
|
$with_capacity:expr,
|
||||||
|
$reserve:expr,
|
||||||
$insert:expr
|
$insert:expr
|
||||||
) => {
|
) => {
|
||||||
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
|
impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty<T $(, $typaram)*>
|
||||||
@@ -554,16 +639,59 @@ macro_rules! seq_impl {
|
|||||||
let visitor = SeqVisitor { marker: PhantomData };
|
let visitor = SeqVisitor { marker: PhantomData };
|
||||||
deserializer.deserialize_seq(visitor)
|
deserializer.deserialize_seq(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct SeqInPlaceVisitor<'a, T: 'a $(, $typaram: 'a)*>(&'a mut $ty<T $(, $typaram)*>);
|
||||||
|
|
||||||
|
impl<'a, 'de, T $(, $typaram)*> Visitor<'de> for SeqInPlaceVisitor<'a, T $(, $typaram)*>
|
||||||
|
where
|
||||||
|
T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*,
|
||||||
|
$($typaram: $bound1 $(+ $bound2)*,)*
|
||||||
|
{
|
||||||
|
type Value = ();
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("a sequence")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<A>(mut self, mut $access: A) -> Result<(), A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
$clear(&mut self.0);
|
||||||
|
$reserve(&mut self.0, size_hint::cautious($access.size_hint()));
|
||||||
|
|
||||||
|
// FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList)
|
||||||
|
while let Some(value) = try!($access.next_element()) {
|
||||||
|
$insert(&mut self.0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_seq(SeqInPlaceVisitor(place))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dummy impl of reserve
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
fn nop_reserve<T>(_seq: T, _n: usize) {}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
BinaryHeap<T: Ord>,
|
BinaryHeap<T: Ord>,
|
||||||
seq,
|
seq,
|
||||||
BinaryHeap::new(),
|
BinaryHeap::new(),
|
||||||
|
BinaryHeap::clear,
|
||||||
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
|
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
|
||||||
|
BinaryHeap::reserve,
|
||||||
BinaryHeap::push);
|
BinaryHeap::push);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
@@ -571,7 +699,9 @@ seq_impl!(
|
|||||||
BTreeSet<T: Eq + Ord>,
|
BTreeSet<T: Eq + Ord>,
|
||||||
seq,
|
seq,
|
||||||
BTreeSet::new(),
|
BTreeSet::new(),
|
||||||
|
BTreeSet::clear,
|
||||||
BTreeSet::new(),
|
BTreeSet::new(),
|
||||||
|
nop_reserve,
|
||||||
BTreeSet::insert);
|
BTreeSet::insert);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
@@ -579,15 +709,20 @@ seq_impl!(
|
|||||||
LinkedList<T>,
|
LinkedList<T>,
|
||||||
seq,
|
seq,
|
||||||
LinkedList::new(),
|
LinkedList::new(),
|
||||||
|
LinkedList::clear,
|
||||||
LinkedList::new(),
|
LinkedList::new(),
|
||||||
LinkedList::push_back);
|
nop_reserve,
|
||||||
|
LinkedList::push_back
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
HashSet<T: Eq + Hash, S: BuildHasher + Default>,
|
HashSet<T: Eq + Hash, S: BuildHasher + Default>,
|
||||||
seq,
|
seq,
|
||||||
HashSet::with_hasher(S::default()),
|
HashSet::with_hasher(S::default()),
|
||||||
|
HashSet::clear,
|
||||||
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
|
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
|
||||||
|
HashSet::reserve,
|
||||||
HashSet::insert);
|
HashSet::insert);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
@@ -595,26 +730,35 @@ seq_impl!(
|
|||||||
Vec<T>,
|
Vec<T>,
|
||||||
seq,
|
seq,
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
|
Vec::clear,
|
||||||
Vec::with_capacity(size_hint::cautious(seq.size_hint())),
|
Vec::with_capacity(size_hint::cautious(seq.size_hint())),
|
||||||
Vec::push);
|
Vec::reserve,
|
||||||
|
Vec::push
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
seq_impl!(
|
seq_impl!(
|
||||||
VecDeque<T>,
|
VecDeque<T>,
|
||||||
seq,
|
seq,
|
||||||
VecDeque::new(),
|
VecDeque::new(),
|
||||||
|
VecDeque::clear,
|
||||||
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
|
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
|
||||||
VecDeque::push_back);
|
VecDeque::reserve,
|
||||||
|
VecDeque::push_back
|
||||||
|
);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct ArrayVisitor<A> {
|
struct ArrayVisitor<A> {
|
||||||
marker: PhantomData<A>,
|
marker: PhantomData<A>,
|
||||||
}
|
}
|
||||||
|
struct ArrayInPlaceVisitor<'a, A: 'a>(&'a mut A);
|
||||||
|
|
||||||
impl<A> ArrayVisitor<A> {
|
impl<A> ArrayVisitor<A> {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
ArrayVisitor { marker: PhantomData }
|
ArrayVisitor {
|
||||||
|
marker: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,6 +817,35 @@ macro_rules! array_impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'de, T> Visitor<'de> for ArrayInPlaceVisitor<'a, [T; $len]>
|
||||||
|
where
|
||||||
|
T: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
type Value = ();
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str(concat!("an array of length ", $len))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut fail_idx = None;
|
||||||
|
for (idx, dest) in self.0[..].iter_mut().enumerate() {
|
||||||
|
if try!(seq.next_element_seed(InPlaceSeed(dest))).is_none() {
|
||||||
|
fail_idx = Some(idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(idx) = fail_idx {
|
||||||
|
return Err(Error::invalid_length(idx, &self));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de, T> Deserialize<'de> for [T; $len]
|
impl<'de, T> Deserialize<'de> for [T; $len]
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>,
|
T: Deserialize<'de>,
|
||||||
@@ -683,6 +856,13 @@ macro_rules! array_impls {
|
|||||||
{
|
{
|
||||||
deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new())
|
deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_tuple($len, ArrayInPlaceVisitor(place))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
@@ -726,49 +906,76 @@ array_impls! {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! tuple_impls {
|
macro_rules! tuple_impls {
|
||||||
($($len:tt $visitor:ident => ($($n:tt $name:ident)+))+) => {
|
($($len:tt => ($($n:tt $name:ident)+))+) => {
|
||||||
$(
|
$(
|
||||||
struct $visitor<$($name,)+> {
|
|
||||||
marker: PhantomData<($($name,)+)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<$($name,)+> $visitor<$($name,)+> {
|
|
||||||
fn new() -> Self {
|
|
||||||
$visitor { marker: PhantomData }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for $visitor<$($name,)+> {
|
|
||||||
type Value = ($($name,)+);
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str(concat!("a tuple of size ", $len))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
|
|
||||||
where
|
|
||||||
A: SeqAccess<'de>,
|
|
||||||
{
|
|
||||||
$(
|
|
||||||
let $name = match try!(seq.next_element()) {
|
|
||||||
Some(value) => value,
|
|
||||||
None => return Err(Error::invalid_length($n, &self)),
|
|
||||||
};
|
|
||||||
)+
|
|
||||||
|
|
||||||
Ok(($($name,)+))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
|
impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<($($name,)+), D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
deserializer.deserialize_tuple($len, $visitor::new())
|
struct TupleVisitor<$($name,)+> {
|
||||||
|
marker: PhantomData<($($name,)+)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> {
|
||||||
|
type Value = ($($name,)+);
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str(concat!("a tuple of size ", $len))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<($($name,)+), A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
$(
|
||||||
|
let $name = match try!(seq.next_element()) {
|
||||||
|
Some(value) => value,
|
||||||
|
None => return Err(Error::invalid_length($n, &self)),
|
||||||
|
};
|
||||||
|
)+
|
||||||
|
|
||||||
|
Ok(($($name,)+))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct TupleInPlaceVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+));
|
||||||
|
|
||||||
|
impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleInPlaceVisitor<'a, $($name,)+> {
|
||||||
|
type Value = ();
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str(concat!("a tuple of size ", $len))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<(), A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
$(
|
||||||
|
if try!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() {
|
||||||
|
return Err(Error::invalid_length($n, &self));
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
@@ -776,22 +983,22 @@ macro_rules! tuple_impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tuple_impls! {
|
tuple_impls! {
|
||||||
1 TupleVisitor1 => (0 T0)
|
1 => (0 T0)
|
||||||
2 TupleVisitor2 => (0 T0 1 T1)
|
2 => (0 T0 1 T1)
|
||||||
3 TupleVisitor3 => (0 T0 1 T1 2 T2)
|
3 => (0 T0 1 T1 2 T2)
|
||||||
4 TupleVisitor4 => (0 T0 1 T1 2 T2 3 T3)
|
4 => (0 T0 1 T1 2 T2 3 T3)
|
||||||
5 TupleVisitor5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
|
5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
|
||||||
6 TupleVisitor6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
|
6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
|
||||||
7 TupleVisitor7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
|
7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
|
||||||
8 TupleVisitor8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
|
8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
|
||||||
9 TupleVisitor9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
|
9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
|
||||||
10 TupleVisitor10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
|
10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
|
||||||
11 TupleVisitor11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
|
11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
|
||||||
12 TupleVisitor12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
|
12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
|
||||||
13 TupleVisitor13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
|
13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
|
||||||
14 TupleVisitor14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
|
14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
|
||||||
15 TupleVisitor15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
|
15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
|
||||||
16 TupleVisitor16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
|
16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -870,7 +1077,7 @@ map_impl!(
|
|||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
macro_rules! parse_ip_impl {
|
macro_rules! parse_ip_impl {
|
||||||
($ty:ty; $size: expr) => {
|
($ty:ty; $size:expr) => {
|
||||||
impl<'de> Deserialize<'de> for $ty {
|
impl<'de> Deserialize<'de> for $ty {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -884,7 +1091,7 @@ macro_rules! parse_ip_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@@ -1027,7 +1234,7 @@ parse_ip_impl!(net::Ipv6Addr; 16);
|
|||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
macro_rules! parse_socket_impl {
|
macro_rules! parse_socket_impl {
|
||||||
($ty:ty, $new: expr) => {
|
($ty:ty, $new:expr) => {
|
||||||
impl<'de> Deserialize<'de> for $ty {
|
impl<'de> Deserialize<'de> for $ty {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
@@ -1041,7 +1248,7 @@ macro_rules! parse_socket_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@@ -1068,7 +1275,9 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
|
|||||||
parse_socket_impl!(net::SocketAddrV4, net::SocketAddrV4::new);
|
parse_socket_impl!(net::SocketAddrV4, net::SocketAddrV4::new);
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(ip, port, 0, 0));
|
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(
|
||||||
|
ip, port, 0, 0
|
||||||
|
));
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -1179,7 +1388,9 @@ impl<'de> Visitor<'de> for OsStringVisitor {
|
|||||||
|
|
||||||
match try!(data.variant()) {
|
match try!(data.variant()) {
|
||||||
(OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec),
|
(OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec),
|
||||||
(OsStringKind::Windows, _) => Err(Error::custom("cannot deserialize Windows OS string on Unix",),),
|
(OsStringKind::Windows, _) => Err(Error::custom(
|
||||||
|
"cannot deserialize Windows OS string on Unix",
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1191,11 +1402,11 @@ impl<'de> Visitor<'de> for OsStringVisitor {
|
|||||||
use std::os::windows::ffi::OsStringExt;
|
use std::os::windows::ffi::OsStringExt;
|
||||||
|
|
||||||
match try!(data.variant()) {
|
match try!(data.variant()) {
|
||||||
(OsStringKind::Windows, v) => {
|
(OsStringKind::Windows, v) => v.newtype_variant::<Vec<u16>>()
|
||||||
v.newtype_variant::<Vec<u16>>()
|
.map(|vec| OsString::from_wide(&vec)),
|
||||||
.map(|vec| OsString::from_wide(&vec))
|
(OsStringKind::Unix, _) => Err(Error::custom(
|
||||||
}
|
"cannot deserialize Unix OS string on Windows",
|
||||||
(OsStringKind::Unix, _) => Err(Error::custom("cannot deserialize Unix OS string on Windows",),),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1222,10 +1433,28 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
|
|||||||
forwarded_impl!((), Box<str>, String::into_boxed_str);
|
forwarded_impl!((), Box<str>, String::into_boxed_str);
|
||||||
|
|
||||||
#[cfg(all(not(feature = "unstable"), feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[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")))]
|
#[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"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
|
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
|
||||||
@@ -1246,7 +1475,11 @@ where
|
|||||||
|
|
||||||
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
|
||||||
macro_rules! box_forwarded_impl {
|
macro_rules! box_forwarded_impl {
|
||||||
($t:ident) => {
|
(
|
||||||
|
$(#[doc = $doc:tt])*
|
||||||
|
$t:ident
|
||||||
|
) => {
|
||||||
|
$(#[doc = $doc])*
|
||||||
impl<'de, T: ?Sized> Deserialize<'de> for $t<T>
|
impl<'de, T: ?Sized> Deserialize<'de> for $t<T>
|
||||||
where
|
where
|
||||||
Box<T>: Deserialize<'de>,
|
Box<T>: Deserialize<'de>,
|
||||||
@@ -1258,14 +1491,32 @@ macro_rules! box_forwarded_impl {
|
|||||||
Box::deserialize(deserializer).map(Into::into)
|
Box::deserialize(deserializer).map(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "unstable", feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[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")))]
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -1521,13 +1772,17 @@ impl<'de> Deserialize<'de> for SystemTime {
|
|||||||
match key {
|
match key {
|
||||||
Field::Secs => {
|
Field::Secs => {
|
||||||
if secs.is_some() {
|
if secs.is_some() {
|
||||||
return Err(<A::Error as Error>::duplicate_field("secs_since_epoch"));
|
return Err(<A::Error as Error>::duplicate_field(
|
||||||
|
"secs_since_epoch",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
secs = Some(try!(map.next_value()));
|
secs = Some(try!(map.next_value()));
|
||||||
}
|
}
|
||||||
Field::Nanos => {
|
Field::Nanos => {
|
||||||
if nanos.is_some() {
|
if nanos.is_some() {
|
||||||
return Err(<A::Error as Error>::duplicate_field("nanos_since_epoch"));
|
return Err(<A::Error as Error>::duplicate_field(
|
||||||
|
"nanos_since_epoch",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
nanos = Some(try!(map.next_value()));
|
nanos = Some(try!(map.next_value()));
|
||||||
}
|
}
|
||||||
@@ -1691,13 +1946,20 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
const FIELDS: &'static [&'static str] = &["start", "end"];
|
const FIELDS: &'static [&'static str] = &["start", "end"];
|
||||||
deserializer.deserialize_struct("Range", FIELDS, RangeVisitor { phantom: PhantomData })
|
deserializer.deserialize_struct(
|
||||||
|
"Range",
|
||||||
|
FIELDS,
|
||||||
|
RangeVisitor {
|
||||||
|
phantom: PhantomData,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[allow(deprecated)]
|
||||||
impl<'de, T> Deserialize<'de> for NonZero<T>
|
impl<'de, T> Deserialize<'de> for NonZero<T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de> + Zeroable,
|
T: Deserialize<'de> + Zeroable,
|
||||||
@@ -1714,6 +1976,36 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! nonzero_integers {
|
||||||
|
( $( $T: ty, )+ ) => {
|
||||||
|
$(
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
impl<'de> Deserialize<'de> for $T {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<$T, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let value = try!(Deserialize::deserialize(deserializer));
|
||||||
|
match <$T>::new(value) {
|
||||||
|
Some(nonzero) => Ok(nonzero),
|
||||||
|
None => Err(Error::custom("expected a non-zero value")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
nonzero_integers! {
|
||||||
|
// Not including signed NonZeroI* since they might be removed
|
||||||
|
NonZeroU8,
|
||||||
|
NonZeroU16,
|
||||||
|
NonZeroU32,
|
||||||
|
NonZeroU64,
|
||||||
|
// FIXME: https://github.com/serde-rs/serde/issues/1136 NonZeroU128,
|
||||||
|
NonZeroUsize,
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<'de, T, E> Deserialize<'de> for Result<T, E>
|
impl<'de, T, E> Deserialize<'de> for Result<T, E>
|
||||||
@@ -1756,9 +2048,10 @@ where
|
|||||||
match value {
|
match value {
|
||||||
0 => Ok(Field::Ok),
|
0 => Ok(Field::Ok),
|
||||||
1 => Ok(Field::Err),
|
1 => Ok(Field::Err),
|
||||||
_ => {
|
_ => Err(Error::invalid_value(
|
||||||
Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),)
|
Unexpected::Unsigned(value as u64),
|
||||||
}
|
&self,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1780,14 +2073,12 @@ where
|
|||||||
match value {
|
match value {
|
||||||
b"Ok" => Ok(Field::Ok),
|
b"Ok" => Ok(Field::Ok),
|
||||||
b"Err" => Ok(Field::Err),
|
b"Err" => Ok(Field::Err),
|
||||||
_ => {
|
_ => match str::from_utf8(value) {
|
||||||
match str::from_utf8(value) {
|
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
|
||||||
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
|
Err(_) => {
|
||||||
Err(_) => {
|
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
|
||||||
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1831,7 +2122,7 @@ where
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<'de, T> Deserialize<'de> for Wrapping<T>
|
impl<'de, T> Deserialize<'de> for Wrapping<T>
|
||||||
where
|
where
|
||||||
T: Deserialize<'de>
|
T: Deserialize<'de>,
|
||||||
{
|
{
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Wrapping<T>, D::Error>
|
||||||
where
|
where
|
||||||
|
|||||||
+41
-2
@@ -98,7 +98,8 @@
|
|||||||
//! - Path
|
//! - Path
|
||||||
//! - PathBuf
|
//! - PathBuf
|
||||||
//! - Range\<T\>
|
//! - Range\<T\>
|
||||||
//! - NonZero\<T\> (unstable)
|
//! - NonZero\<T\> (unstable, deprecated)
|
||||||
|
//! - num::NonZero* (unstable)
|
||||||
//! - **Net types**:
|
//! - **Net types**:
|
||||||
//! - IpAddr
|
//! - IpAddr
|
||||||
//! - Ipv4Addr
|
//! - Ipv4Addr
|
||||||
@@ -195,6 +196,7 @@ macro_rules! declare_error_trait {
|
|||||||
/// For example if we try to deserialize a String out of a JSON file
|
/// 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
|
/// containing an integer, the unexpected type is the integer and the
|
||||||
/// expected type is the string.
|
/// expected type is the string.
|
||||||
|
#[cold]
|
||||||
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
|
fn invalid_type(unexp: Unexpected, exp: &Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
|
Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp))
|
||||||
}
|
}
|
||||||
@@ -212,6 +214,7 @@ macro_rules! declare_error_trait {
|
|||||||
/// For example if we try to deserialize a String out of some binary data
|
/// 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
|
/// that is not valid UTF-8, the unexpected value is the bytes and the
|
||||||
/// expected value is a string.
|
/// expected value is a string.
|
||||||
|
#[cold]
|
||||||
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
|
fn invalid_value(unexp: Unexpected, exp: &Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
|
Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp))
|
||||||
}
|
}
|
||||||
@@ -225,12 +228,14 @@ macro_rules! declare_error_trait {
|
|||||||
/// The `exp` argument provides information about what data was being
|
/// The `exp` argument provides information about what data was being
|
||||||
/// expected. For example `exp` might say that a tuple of size 6 was
|
/// expected. For example `exp` might say that a tuple of size 6 was
|
||||||
/// expected.
|
/// expected.
|
||||||
|
#[cold]
|
||||||
fn invalid_length(len: usize, exp: &Expected) -> Self {
|
fn invalid_length(len: usize, exp: &Expected) -> Self {
|
||||||
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
|
Error::custom(format_args!("invalid length {}, expected {}", len, exp))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raised when a `Deserialize` enum type received a variant with an
|
/// Raised when a `Deserialize` enum type received a variant with an
|
||||||
/// unrecognized name.
|
/// unrecognized name.
|
||||||
|
#[cold]
|
||||||
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
|
fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
|
||||||
if expected.is_empty() {
|
if expected.is_empty() {
|
||||||
Error::custom(format_args!("unknown variant `{}`, there are no variants",
|
Error::custom(format_args!("unknown variant `{}`, there are no variants",
|
||||||
@@ -244,6 +249,7 @@ macro_rules! declare_error_trait {
|
|||||||
|
|
||||||
/// Raised when a `Deserialize` struct type received a field with an
|
/// Raised when a `Deserialize` struct type received a field with an
|
||||||
/// unrecognized name.
|
/// unrecognized name.
|
||||||
|
#[cold]
|
||||||
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
|
fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
|
||||||
if expected.is_empty() {
|
if expected.is_empty() {
|
||||||
Error::custom(format_args!("unknown field `{}`, there are no fields",
|
Error::custom(format_args!("unknown field `{}`, there are no fields",
|
||||||
@@ -258,12 +264,14 @@ macro_rules! declare_error_trait {
|
|||||||
/// Raised when a `Deserialize` struct type expected to receive a required
|
/// Raised when a `Deserialize` struct type expected to receive a required
|
||||||
/// field with a particular name but that field was not present in the
|
/// field with a particular name but that field was not present in the
|
||||||
/// input.
|
/// input.
|
||||||
|
#[cold]
|
||||||
fn missing_field(field: &'static str) -> Self {
|
fn missing_field(field: &'static str) -> Self {
|
||||||
Error::custom(format_args!("missing field `{}`", field))
|
Error::custom(format_args!("missing field `{}`", field))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raised when a `Deserialize` struct type received more than one of the
|
/// Raised when a `Deserialize` struct type received more than one of the
|
||||||
/// same field.
|
/// same field.
|
||||||
|
#[cold]
|
||||||
fn duplicate_field(field: &'static str) -> Self {
|
fn duplicate_field(field: &'static str) -> Self {
|
||||||
Error::custom(format_args!("duplicate field `{}`", field))
|
Error::custom(format_args!("duplicate field `{}`", field))
|
||||||
}
|
}
|
||||||
@@ -504,6 +512,35 @@ pub trait Deserialize<'de>: Sized {
|
|||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>;
|
D: Deserializer<'de>;
|
||||||
|
|
||||||
|
/// Deserializes a value into `self` from the given Deserializer.
|
||||||
|
///
|
||||||
|
/// The purpose of this method is to allow the deserializer to reuse
|
||||||
|
/// resources and avoid copies. As such, if this method returns an error,
|
||||||
|
/// `self` will be in an indeterminate state where some parts of the struct
|
||||||
|
/// have been overwritten. Although whatever state that is will be
|
||||||
|
/// memory-safe.
|
||||||
|
///
|
||||||
|
/// This is generally useful when repeatedly deserializing values that
|
||||||
|
/// are processed one at a time, where the value of `self` doesn't matter
|
||||||
|
/// when the next deserialization occurs.
|
||||||
|
///
|
||||||
|
/// If you manually implement this, your recursive deserializations should
|
||||||
|
/// use `deserialize_in_place`.
|
||||||
|
///
|
||||||
|
/// This method is stable and an official public API, but hidden from the
|
||||||
|
/// documentation because it is almost never what newbies are looking for.
|
||||||
|
/// Showing it in rustdoc would cause it to be featured more prominently
|
||||||
|
/// than it deserves.
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
// Default implementation just delegates to `deserialize` impl.
|
||||||
|
*place = Deserialize::deserialize(deserializer)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A data structure that can be deserialized without borrowing any data from
|
/// A data structure that can be deserialized without borrowing any data from
|
||||||
@@ -1078,7 +1115,9 @@ pub trait Deserializer<'de>: Sized {
|
|||||||
/// change, as a value serialized in human-readable mode is not required to
|
/// change, as a value serialized in human-readable mode is not required to
|
||||||
/// deserialize from the same data in compact mode.
|
/// deserialize from the same data in compact mode.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_human_readable(&self) -> bool { true }
|
fn is_human_readable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
+42
-25
@@ -37,10 +37,10 @@
|
|||||||
|
|
||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use de::{self, IntoDeserializer, Expected, SeqAccess};
|
use self::private::{First, Second};
|
||||||
|
use de::{self, Expected, IntoDeserializer, SeqAccess};
|
||||||
use private::de::size_hint;
|
use private::de::size_hint;
|
||||||
use ser;
|
use ser;
|
||||||
use self::private::{First, Second};
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -58,14 +58,18 @@ type ErrorImpl = ();
|
|||||||
|
|
||||||
impl de::Error for Error {
|
impl de::Error for Error {
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
#[cold]
|
||||||
fn custom<T>(msg: T) -> Self
|
fn custom<T>(msg: T) -> Self
|
||||||
where
|
where
|
||||||
T: Display,
|
T: Display,
|
||||||
{
|
{
|
||||||
Error { err: msg.to_string().into_boxed_str() }
|
Error {
|
||||||
|
err: msg.to_string().into_boxed_str(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||||
|
#[cold]
|
||||||
fn custom<T>(msg: T) -> Self
|
fn custom<T>(msg: T) -> Self
|
||||||
where
|
where
|
||||||
T: Display,
|
T: Display,
|
||||||
@@ -76,6 +80,7 @@ impl de::Error for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ser::Error for Error {
|
impl ser::Error for Error {
|
||||||
|
#[cold]
|
||||||
fn custom<T>(msg: T) -> Self
|
fn custom<T>(msg: T) -> Self
|
||||||
where
|
where
|
||||||
T: Display,
|
T: Display,
|
||||||
@@ -112,7 +117,9 @@ where
|
|||||||
type Deserializer = UnitDeserializer<E>;
|
type Deserializer = UnitDeserializer<E>;
|
||||||
|
|
||||||
fn into_deserializer(self) -> UnitDeserializer<E> {
|
fn into_deserializer(self) -> UnitDeserializer<E> {
|
||||||
UnitDeserializer { marker: PhantomData }
|
UnitDeserializer {
|
||||||
|
marker: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,17 +655,17 @@ where
|
|||||||
{
|
{
|
||||||
/// Check for remaining elements after passing a `SeqDeserializer` to
|
/// Check for remaining elements after passing a `SeqDeserializer` to
|
||||||
/// `Visitor::visit_seq`.
|
/// `Visitor::visit_seq`.
|
||||||
pub fn end(mut self) -> Result<(), E> {
|
pub fn end(self) -> Result<(), E> {
|
||||||
let mut remaining = 0;
|
let remaining = self.iter.count();
|
||||||
while self.iter.next().is_some() {
|
|
||||||
remaining += 1;
|
|
||||||
}
|
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
// First argument is the number of elements in the data, second
|
// First argument is the number of elements in the data, second
|
||||||
// argument is the number of elements expected by the Deserialize.
|
// argument is the number of elements expected by the Deserialize.
|
||||||
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInSeq(self.count)),)
|
Err(de::Error::invalid_length(
|
||||||
|
self.count + remaining,
|
||||||
|
&ExpectedInSeq(self.count),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -842,17 +849,17 @@ where
|
|||||||
{
|
{
|
||||||
/// Check for remaining elements after passing a `MapDeserializer` to
|
/// Check for remaining elements after passing a `MapDeserializer` to
|
||||||
/// `Visitor::visit_map`.
|
/// `Visitor::visit_map`.
|
||||||
pub fn end(mut self) -> Result<(), E> {
|
pub fn end(self) -> Result<(), E> {
|
||||||
let mut remaining = 0;
|
let remaining = self.iter.count();
|
||||||
while self.iter.next().is_some() {
|
|
||||||
remaining += 1;
|
|
||||||
}
|
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
// First argument is the number of elements in the data, second
|
// First argument is the number of elements in the data, second
|
||||||
// argument is the number of elements expected by the Deserialize.
|
// argument is the number of elements expected by the Deserialize.
|
||||||
Err(de::Error::invalid_length(self.count + remaining, &ExpectedInMap(self.count)),)
|
Err(de::Error::invalid_length(
|
||||||
|
self.count + remaining,
|
||||||
|
&ExpectedInMap(self.count),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -901,11 +908,7 @@ where
|
|||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_tuple<V>(
|
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
self,
|
|
||||||
len: usize,
|
|
||||||
visitor: V,
|
|
||||||
) -> Result<V::Value, Self::Error>
|
|
||||||
where
|
where
|
||||||
V: de::Visitor<'de>,
|
V: de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
@@ -1223,7 +1226,12 @@ mod private {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
|
pub fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) {
|
||||||
(t, UnitOnly { marker: PhantomData })
|
(
|
||||||
|
t,
|
||||||
|
UnitOnly {
|
||||||
|
marker: PhantomData,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> de::VariantAccess<'de> for UnitOnly<E>
|
impl<'de, E> de::VariantAccess<'de> for UnitOnly<E>
|
||||||
@@ -1240,14 +1248,20 @@ mod private {
|
|||||||
where
|
where
|
||||||
T: de::DeserializeSeed<'de>,
|
T: de::DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"newtype variant"),)
|
Err(de::Error::invalid_type(
|
||||||
|
Unexpected::UnitVariant,
|
||||||
|
&"newtype variant",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
|
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
|
||||||
where
|
where
|
||||||
V: de::Visitor<'de>,
|
V: de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"tuple variant"),)
|
Err(de::Error::invalid_type(
|
||||||
|
Unexpected::UnitVariant,
|
||||||
|
&"tuple variant",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_variant<V>(
|
fn struct_variant<V>(
|
||||||
@@ -1258,7 +1272,10 @@ mod private {
|
|||||||
where
|
where
|
||||||
V: de::Visitor<'de>,
|
V: de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
Err(de::Error::invalid_type(Unexpected::UnitVariant, &"struct variant"),)
|
Err(de::Error::invalid_type(
|
||||||
|
Unexpected::UnitVariant,
|
||||||
|
&"struct variant",
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ pub use lib::default::Default;
|
|||||||
pub use lib::fmt::{self, Formatter};
|
pub use lib::fmt::{self, Formatter};
|
||||||
pub use lib::marker::PhantomData;
|
pub use lib::marker::PhantomData;
|
||||||
pub use lib::option::Option::{self, None, Some};
|
pub use lib::option::Option::{self, None, Some};
|
||||||
pub use lib::result::Result::{self, Ok, Err};
|
pub use lib::result::Result::{self, Err, Ok};
|
||||||
|
|
||||||
pub use self::string::from_utf8_lossy;
|
pub use self::string::from_utf8_lossy;
|
||||||
|
|
||||||
|
|||||||
+41
-41
@@ -79,30 +79,24 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Serde types in rustdoc of other crates get linked to here.
|
// Serde types in rustdoc of other crates get linked to here.
|
||||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.21")]
|
#![doc(html_root_url = "https://docs.rs/serde/1.0.43")]
|
||||||
|
|
||||||
// Support using Serde without the standard library!
|
// Support using Serde without the standard library!
|
||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
|
|
||||||
// Unstable functionality only if the user asks for it. For tracking and
|
// Unstable functionality only if the user asks for it. For tracking and
|
||||||
// discussion of these features please refer to this issue:
|
// discussion of these features please refer to this issue:
|
||||||
//
|
//
|
||||||
// https://github.com/serde-rs/serde/issues/812
|
// https://github.com/serde-rs/serde/issues/812
|
||||||
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
|
#![cfg_attr(feature = "unstable", feature(nonzero, specialization))]
|
||||||
#![cfg_attr(feature = "alloc", feature(alloc))]
|
#![cfg_attr(feature = "alloc", feature(alloc))]
|
||||||
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
#![cfg_attr(
|
||||||
cast_lossless,
|
feature = "cargo-clippy",
|
||||||
const_static_lifetime,
|
allow(
|
||||||
doc_markdown,
|
cast_lossless, const_static_lifetime, doc_markdown, linkedlist, needless_pass_by_value,
|
||||||
linkedlist,
|
redundant_field_names, type_complexity, unreadable_literal, zero_prefixed_literal
|
||||||
needless_pass_by_value,
|
)
|
||||||
type_complexity,
|
)]
|
||||||
unreadable_literal,
|
|
||||||
zero_prefixed_literal,
|
|
||||||
))]
|
|
||||||
// Whitelisted clippy_pedantic lints
|
// Whitelisted clippy_pedantic lints
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
#![cfg_attr(feature = "cargo-clippy", allow(
|
||||||
// integer and float ser/de requires these sorts of casts
|
// integer and float ser/de requires these sorts of casts
|
||||||
@@ -113,6 +107,7 @@
|
|||||||
// simplifies some macros
|
// simplifies some macros
|
||||||
invalid_upcast_comparisons,
|
invalid_upcast_comparisons,
|
||||||
// things are often more readable this way
|
// things are often more readable this way
|
||||||
|
decimal_literal_representation,
|
||||||
option_unwrap_used,
|
option_unwrap_used,
|
||||||
result_unwrap_used,
|
result_unwrap_used,
|
||||||
shadow_reuse,
|
shadow_reuse,
|
||||||
@@ -120,12 +115,13 @@
|
|||||||
stutter,
|
stutter,
|
||||||
use_self,
|
use_self,
|
||||||
// not practical
|
// not practical
|
||||||
|
many_single_char_names,
|
||||||
missing_docs_in_private_items,
|
missing_docs_in_private_items,
|
||||||
|
similar_names,
|
||||||
// alternative is not stable
|
// alternative is not stable
|
||||||
empty_enum,
|
empty_enum,
|
||||||
use_debug,
|
use_debug,
|
||||||
))]
|
))]
|
||||||
|
|
||||||
// Blacklisted Rust lints.
|
// Blacklisted Rust lints.
|
||||||
#![deny(missing_docs, unused_imports)]
|
#![deny(missing_docs, unused_imports)]
|
||||||
|
|
||||||
@@ -142,16 +138,16 @@ extern crate core;
|
|||||||
/// module.
|
/// module.
|
||||||
mod lib {
|
mod lib {
|
||||||
mod core {
|
mod core {
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::*;
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
pub use core::*;
|
pub use core::*;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::core::{cmp, iter, mem, ops, slice, str};
|
pub use self::core::{cmp, iter, mem, ops, slice, str};
|
||||||
pub use self::core::{i8, i16, i32, i64, isize};
|
|
||||||
pub use self::core::{u8, u16, u32, u64, usize};
|
|
||||||
pub use self::core::{f32, f64};
|
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::cell::{Cell, RefCell};
|
||||||
pub use self::core::clone::{self, Clone};
|
pub use self::core::clone::{self, Clone};
|
||||||
@@ -162,40 +158,40 @@ mod lib {
|
|||||||
pub use self::core::option::{self, Option};
|
pub use self::core::option::{self, Option};
|
||||||
pub use self::core::result::{self, Result};
|
pub use self::core::result::{self, Result};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::borrow::{Cow, ToOwned};
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
pub use alloc::borrow::{Cow, ToOwned};
|
pub use alloc::borrow::{Cow, ToOwned};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::string::String;
|
pub use std::borrow::{Cow, ToOwned};
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
pub use alloc::string::{String, ToString};
|
pub use alloc::string::{String, ToString};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::vec::Vec;
|
pub use std::string::String;
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
pub use alloc::vec::Vec;
|
pub use alloc::vec::Vec;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::boxed::Box;
|
pub use std::vec::Vec;
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
pub use alloc::boxed::Box;
|
pub use alloc::boxed::Box;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::boxed::Box;
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", feature = "std"))]
|
|
||||||
pub use std::rc::Rc;
|
|
||||||
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
||||||
pub use alloc::rc::Rc;
|
pub use alloc::rc::Rc;
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", feature = "std"))]
|
#[cfg(all(feature = "rc", feature = "std"))]
|
||||||
pub use std::sync::Arc;
|
pub use std::rc::Rc;
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
|
||||||
pub use alloc::arc::Arc;
|
pub use alloc::arc::Arc;
|
||||||
|
#[cfg(all(feature = "rc", feature = "std"))]
|
||||||
|
pub use std::sync::Arc;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::collections::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
pub use alloc::{BinaryHeap, BTreeMap, BTreeSet, LinkedList, VecDeque};
|
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::{error, net};
|
pub use std::{error, net};
|
||||||
@@ -203,9 +199,9 @@ mod lib {
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::collections::{HashMap, HashSet};
|
pub use std::collections::{HashMap, HashSet};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::ffi::{CString, CStr, OsString, OsStr};
|
pub use std::ffi::{CStr, CString, OsStr, OsString};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::hash::{Hash, BuildHasher};
|
pub use std::hash::{BuildHasher, Hash};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::io::Write;
|
pub use std::io::Write;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@@ -213,12 +209,16 @@ mod lib {
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::path::{Path, PathBuf};
|
pub use std::path::{Path, PathBuf};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use std::sync::{Mutex, RwLock};
|
pub use std::sync::{Mutex, RwLock};
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[allow(deprecated)]
|
||||||
pub use core::nonzero::{NonZero, Zeroable};
|
pub use core::nonzero::{NonZero, Zeroable};
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
pub use core::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -226,13 +226,13 @@ mod lib {
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
pub mod ser;
|
|
||||||
pub mod de;
|
pub mod de;
|
||||||
|
pub mod ser;
|
||||||
|
|
||||||
#[doc(inline)]
|
|
||||||
pub use ser::{Serialize, Serializer};
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use de::{Deserialize, Deserializer};
|
pub use de::{Deserialize, Deserializer};
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use ser::{Serialize, Serializer};
|
||||||
|
|
||||||
// Generated code uses these to support no_std. Not public API.
|
// Generated code uses these to support no_std. Not public API.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|||||||
+953
-176
File diff suppressed because it is too large
Load Diff
@@ -8,5 +8,5 @@
|
|||||||
|
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
pub mod ser;
|
|
||||||
pub mod de;
|
pub mod de;
|
||||||
|
pub mod ser;
|
||||||
|
|||||||
+412
-96
@@ -8,10 +8,11 @@
|
|||||||
|
|
||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use ser::{self, Serialize, Serializer, SerializeMap, SerializeStruct, Impossible};
|
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
use self::content::{SerializeTupleVariantAsMapValue, SerializeStructVariantAsMapValue};
|
use self::content::{Content, ContentSerializer, SerializeStructVariantAsMapValue,
|
||||||
|
SerializeTupleVariantAsMapValue};
|
||||||
|
|
||||||
/// Used to check that serde(getter) attributes return the expected type.
|
/// Used to check that serde(getter) attributes return the expected type.
|
||||||
/// Not public API.
|
/// Not public API.
|
||||||
@@ -32,15 +33,13 @@ where
|
|||||||
S: Serializer,
|
S: Serializer,
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
value.serialize(
|
value.serialize(TaggedSerializer {
|
||||||
TaggedSerializer {
|
type_ident: type_ident,
|
||||||
type_ident: type_ident,
|
variant_ident: variant_ident,
|
||||||
variant_ident: variant_ident,
|
tag: tag,
|
||||||
tag: tag,
|
variant_name: variant_name,
|
||||||
variant_name: variant_name,
|
delegate: serializer,
|
||||||
delegate: serializer,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaggedSerializer<S> {
|
struct TaggedSerializer<S> {
|
||||||
@@ -60,10 +59,11 @@ enum Unsupported {
|
|||||||
ByteArray,
|
ByteArray,
|
||||||
Optional,
|
Optional,
|
||||||
Unit,
|
Unit,
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
UnitStruct,
|
||||||
Sequence,
|
Sequence,
|
||||||
Tuple,
|
Tuple,
|
||||||
TupleStruct,
|
TupleStruct,
|
||||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
|
||||||
Enum,
|
Enum,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,10 +78,11 @@ impl Display for Unsupported {
|
|||||||
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
Unsupported::ByteArray => formatter.write_str("a byte array"),
|
||||||
Unsupported::Optional => formatter.write_str("an optional"),
|
Unsupported::Optional => formatter.write_str("an optional"),
|
||||||
Unsupported::Unit => formatter.write_str("unit"),
|
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::Sequence => formatter.write_str("a sequence"),
|
||||||
Unsupported::Tuple => formatter.write_str("a tuple"),
|
Unsupported::Tuple => formatter.write_str("a tuple"),
|
||||||
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
Unsupported::TupleStruct => formatter.write_str("a tuple struct"),
|
||||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
|
||||||
Unsupported::Enum => formatter.write_str("an enum"),
|
Unsupported::Enum => formatter.write_str("an enum"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,13 +93,10 @@ where
|
|||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
fn bad_type(self, what: Unsupported) -> S::Error {
|
fn bad_type(self, what: Unsupported) -> S::Error {
|
||||||
ser::Error::custom(
|
ser::Error::custom(format_args!(
|
||||||
format_args!(
|
|
||||||
"cannot serialize tagged newtype variant {}::{} containing {}",
|
"cannot serialize tagged newtype variant {}::{} containing {}",
|
||||||
self.type_ident,
|
self.type_ident, self.variant_ident, what
|
||||||
self.variant_ident,
|
))
|
||||||
what),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +279,11 @@ where
|
|||||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
try!(map.serialize_key(inner_variant));
|
try!(map.serialize_key(inner_variant));
|
||||||
Ok(SerializeTupleVariantAsMapValue::new(map, inner_variant, len),)
|
Ok(SerializeTupleVariantAsMapValue::new(
|
||||||
|
map,
|
||||||
|
inner_variant,
|
||||||
|
len,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
||||||
@@ -324,7 +326,11 @@ where
|
|||||||
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
let mut map = try!(self.delegate.serialize_map(Some(2)));
|
||||||
try!(map.serialize_entry(self.tag, self.variant_name));
|
try!(map.serialize_entry(self.tag, self.variant_name));
|
||||||
try!(map.serialize_key(inner_variant));
|
try!(map.serialize_key(inner_variant));
|
||||||
Ok(SerializeStructVariantAsMapValue::new(map, inner_variant, len),)
|
Ok(SerializeStructVariantAsMapValue::new(
|
||||||
|
map,
|
||||||
|
inner_variant,
|
||||||
|
len,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
#[cfg(not(any(feature = "std", feature = "alloc")))]
|
||||||
@@ -402,7 +408,10 @@ mod content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||||
try!(self.map.serialize_value(&Content::TupleStruct(self.name, self.fields)));
|
try!(
|
||||||
|
self.map
|
||||||
|
.serialize_value(&Content::TupleStruct(self.name, self.fields))
|
||||||
|
);
|
||||||
self.map.end()
|
self.map.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,13 +453,16 @@ mod content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn end(mut self) -> Result<M::Ok, M::Error> {
|
fn end(mut self) -> Result<M::Ok, M::Error> {
|
||||||
try!(self.map.serialize_value(&Content::Struct(self.name, self.fields)));
|
try!(
|
||||||
|
self.map
|
||||||
|
.serialize_value(&Content::Struct(self.name, self.fields))
|
||||||
|
);
|
||||||
self.map.end()
|
self.map.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Content {
|
pub enum Content {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
|
|
||||||
U8(u8),
|
U8(u8),
|
||||||
@@ -485,7 +497,12 @@ mod content {
|
|||||||
TupleVariant(&'static str, u32, &'static str, Vec<Content>),
|
TupleVariant(&'static str, u32, &'static str, Vec<Content>),
|
||||||
Map(Vec<(Content, Content)>),
|
Map(Vec<(Content, Content)>),
|
||||||
Struct(&'static str, Vec<(&'static str, Content)>),
|
Struct(&'static str, Vec<(&'static str, Content)>),
|
||||||
StructVariant(&'static str, u32, &'static str, Vec<(&'static str, Content)>),
|
StructVariant(
|
||||||
|
&'static str,
|
||||||
|
u32,
|
||||||
|
&'static str,
|
||||||
|
Vec<(&'static str, Content)>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for Content {
|
impl Serialize for Content {
|
||||||
@@ -570,12 +587,12 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContentSerializer<E> {
|
pub struct ContentSerializer<E> {
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> ContentSerializer<E> {
|
impl<E> ContentSerializer<E> {
|
||||||
fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ContentSerializer { error: PhantomData }
|
ContentSerializer { error: PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -687,7 +704,10 @@ mod content {
|
|||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
Ok(Content::NewtypeStruct(name, Box::new(try!(value.serialize(self)))),)
|
Ok(Content::NewtypeStruct(
|
||||||
|
name,
|
||||||
|
Box::new(try!(value.serialize(self))),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(
|
fn serialize_newtype_variant<T: ?Sized>(
|
||||||
@@ -700,32 +720,26 @@ mod content {
|
|||||||
where
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
Ok(
|
Ok(Content::NewtypeVariant(
|
||||||
Content::NewtypeVariant(
|
name,
|
||||||
name,
|
variant_index,
|
||||||
variant_index,
|
variant,
|
||||||
variant,
|
Box::new(try!(value.serialize(self))),
|
||||||
Box::new(try!(value.serialize(self))),
|
))
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
|
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, E> {
|
||||||
Ok(
|
Ok(SerializeSeq {
|
||||||
SerializeSeq {
|
elements: Vec::with_capacity(len.unwrap_or(0)),
|
||||||
elements: Vec::with_capacity(len.unwrap_or(0)),
|
error: PhantomData,
|
||||||
error: PhantomData,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
|
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, E> {
|
||||||
Ok(
|
Ok(SerializeTuple {
|
||||||
SerializeTuple {
|
elements: Vec::with_capacity(len),
|
||||||
elements: Vec::with_capacity(len),
|
error: PhantomData,
|
||||||
error: PhantomData,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple_struct(
|
fn serialize_tuple_struct(
|
||||||
@@ -733,13 +747,11 @@ mod content {
|
|||||||
name: &'static str,
|
name: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeTupleStruct, E> {
|
) -> Result<Self::SerializeTupleStruct, E> {
|
||||||
Ok(
|
Ok(SerializeTupleStruct {
|
||||||
SerializeTupleStruct {
|
name: name,
|
||||||
name: name,
|
fields: Vec::with_capacity(len),
|
||||||
fields: Vec::with_capacity(len),
|
error: PhantomData,
|
||||||
error: PhantomData,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple_variant(
|
fn serialize_tuple_variant(
|
||||||
@@ -749,25 +761,21 @@ mod content {
|
|||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeTupleVariant, E> {
|
) -> Result<Self::SerializeTupleVariant, E> {
|
||||||
Ok(
|
Ok(SerializeTupleVariant {
|
||||||
SerializeTupleVariant {
|
name: name,
|
||||||
name: name,
|
variant_index: variant_index,
|
||||||
variant_index: variant_index,
|
variant: variant,
|
||||||
variant: variant,
|
fields: Vec::with_capacity(len),
|
||||||
fields: Vec::with_capacity(len),
|
error: PhantomData,
|
||||||
error: PhantomData,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
|
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, E> {
|
||||||
Ok(
|
Ok(SerializeMap {
|
||||||
SerializeMap {
|
entries: Vec::with_capacity(len.unwrap_or(0)),
|
||||||
entries: Vec::with_capacity(len.unwrap_or(0)),
|
key: None,
|
||||||
key: None,
|
error: PhantomData,
|
||||||
error: PhantomData,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_struct(
|
fn serialize_struct(
|
||||||
@@ -775,13 +783,11 @@ mod content {
|
|||||||
name: &'static str,
|
name: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeStruct, E> {
|
) -> Result<Self::SerializeStruct, E> {
|
||||||
Ok(
|
Ok(SerializeStruct {
|
||||||
SerializeStruct {
|
name: name,
|
||||||
name: name,
|
fields: Vec::with_capacity(len),
|
||||||
fields: Vec::with_capacity(len),
|
error: PhantomData,
|
||||||
error: PhantomData,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_struct_variant(
|
fn serialize_struct_variant(
|
||||||
@@ -791,19 +797,17 @@ mod content {
|
|||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
len: usize,
|
len: usize,
|
||||||
) -> Result<Self::SerializeStructVariant, E> {
|
) -> Result<Self::SerializeStructVariant, E> {
|
||||||
Ok(
|
Ok(SerializeStructVariant {
|
||||||
SerializeStructVariant {
|
name: name,
|
||||||
name: name,
|
variant_index: variant_index,
|
||||||
variant_index: variant_index,
|
variant: variant,
|
||||||
variant: variant,
|
fields: Vec::with_capacity(len),
|
||||||
fields: Vec::with_capacity(len),
|
error: PhantomData,
|
||||||
error: PhantomData,
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeSeq<E> {
|
pub struct SerializeSeq<E> {
|
||||||
elements: Vec<Content>,
|
elements: Vec<Content>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
@@ -829,7 +833,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeTuple<E> {
|
pub struct SerializeTuple<E> {
|
||||||
elements: Vec<Content>,
|
elements: Vec<Content>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
}
|
}
|
||||||
@@ -855,7 +859,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeTupleStruct<E> {
|
pub struct SerializeTupleStruct<E> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
fields: Vec<Content>,
|
fields: Vec<Content>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
@@ -882,7 +886,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeTupleVariant<E> {
|
pub struct SerializeTupleVariant<E> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
@@ -907,11 +911,16 @@ mod content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn end(self) -> Result<Content, E> {
|
fn end(self) -> Result<Content, E> {
|
||||||
Ok(Content::TupleVariant(self.name, self.variant_index, self.variant, self.fields),)
|
Ok(Content::TupleVariant(
|
||||||
|
self.name,
|
||||||
|
self.variant_index,
|
||||||
|
self.variant,
|
||||||
|
self.fields,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeMap<E> {
|
pub struct SerializeMap<E> {
|
||||||
entries: Vec<(Content, Content)>,
|
entries: Vec<(Content, Content)>,
|
||||||
key: Option<Content>,
|
key: Option<Content>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
@@ -961,7 +970,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeStruct<E> {
|
pub struct SerializeStruct<E> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
fields: Vec<(&'static str, Content)>,
|
fields: Vec<(&'static str, Content)>,
|
||||||
error: PhantomData<E>,
|
error: PhantomData<E>,
|
||||||
@@ -988,7 +997,7 @@ mod content {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeStructVariant<E> {
|
pub struct SerializeStructVariant<E> {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
variant_index: u32,
|
variant_index: u32,
|
||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
@@ -1013,7 +1022,314 @@ mod content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn end(self) -> Result<Content, E> {
|
fn end(self) -> Result<Content, E> {
|
||||||
Ok(Content::StructVariant(self.name, self.variant_index, self.variant, self.fields),)
|
Ok(Content::StructVariant(
|
||||||
|
self.name,
|
||||||
|
self.variant_index,
|
||||||
|
self.variant,
|
||||||
|
self.fields,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+76
-19
@@ -111,7 +111,7 @@ where
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<T> Serialize for PhantomData<T> {
|
impl<T: ?Sized> Serialize for PhantomData<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -320,8 +320,12 @@ map_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! deref_impl {
|
macro_rules! deref_impl {
|
||||||
($($desc:tt)+) => {
|
(
|
||||||
impl $($desc)+ {
|
$(#[doc = $doc:tt])*
|
||||||
|
<$($desc:tt)+
|
||||||
|
) => {
|
||||||
|
$(#[doc = $doc])*
|
||||||
|
impl <$($desc)+ {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@@ -340,10 +344,30 @@ deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize);
|
|||||||
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
||||||
|
|
||||||
#[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
|
#[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")))]
|
#[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"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwned);
|
||||||
@@ -351,6 +375,7 @@ deref_impl!(<'a, T: ?Sized> Serialize for Cow<'a, T> where T: Serialize + ToOwne
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
|
#[allow(deprecated)]
|
||||||
impl<T> Serialize for NonZero<T>
|
impl<T> Serialize for NonZero<T>
|
||||||
where
|
where
|
||||||
T: Serialize + Zeroable + Clone,
|
T: Serialize + Zeroable + Clone,
|
||||||
@@ -363,6 +388,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>
|
impl<T> Serialize for Cell<T>
|
||||||
where
|
where
|
||||||
T: Serialize + Copy,
|
T: Serialize + Copy,
|
||||||
@@ -464,7 +515,8 @@ impl Serialize for SystemTime {
|
|||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
use super::SerializeStruct;
|
use super::SerializeStruct;
|
||||||
let duration_since_epoch = self.duration_since(UNIX_EPOCH).expect("SystemTime must be later than UNIX_EPOCH");
|
let duration_since_epoch = self.duration_since(UNIX_EPOCH)
|
||||||
|
.expect("SystemTime must be later than UNIX_EPOCH");
|
||||||
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
|
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
|
||||||
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
|
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
|
||||||
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
|
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
|
||||||
@@ -493,11 +545,9 @@ macro_rules! serialize_display_bounded_length {
|
|||||||
// write! only provides fmt::Formatter to Display implementations, which
|
// write! only provides fmt::Formatter to Display implementations, which
|
||||||
// has methods write_str and write_char but no method to write arbitrary
|
// has methods write_str and write_char but no method to write arbitrary
|
||||||
// bytes. Therefore `written` must be valid UTF-8.
|
// bytes. Therefore `written` must be valid UTF-8.
|
||||||
let written_str = unsafe {
|
let written_str = unsafe { str::from_utf8_unchecked(written) };
|
||||||
str::from_utf8_unchecked(written)
|
|
||||||
};
|
|
||||||
$serializer.serialize_str(written_str)
|
$serializer.serialize_str(written_str)
|
||||||
}}
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@@ -513,10 +563,12 @@ impl Serialize for net::IpAddr {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match *self {
|
match *self {
|
||||||
net::IpAddr::V4(ref a) =>
|
net::IpAddr::V4(ref a) => {
|
||||||
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a),
|
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a)
|
||||||
net::IpAddr::V6(ref a) =>
|
}
|
||||||
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a),
|
net::IpAddr::V6(ref a) => {
|
||||||
|
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -567,10 +619,12 @@ impl Serialize for net::SocketAddr {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match *self {
|
match *self {
|
||||||
net::SocketAddr::V4(ref addr) =>
|
net::SocketAddr::V4(ref addr) => {
|
||||||
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr),
|
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr)
|
||||||
net::SocketAddr::V6(ref addr) =>
|
}
|
||||||
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr),
|
net::SocketAddr::V6(ref addr) => {
|
||||||
|
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -600,7 +654,10 @@ impl Serialize for net::SocketAddrV6 {
|
|||||||
{
|
{
|
||||||
if serializer.is_human_readable() {
|
if serializer.is_human_readable() {
|
||||||
const MAX_LEN: usize = 47;
|
const MAX_LEN: usize = 47;
|
||||||
debug_assert_eq!(MAX_LEN, "[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len());
|
debug_assert_eq!(
|
||||||
|
MAX_LEN,
|
||||||
|
"[1001:1002:1003:1004:1005:1006:1007:1008]:65000".len()
|
||||||
|
);
|
||||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||||
} else {
|
} else {
|
||||||
(self.ip(), self.port()).serialize(serializer)
|
(self.ip(), self.port()).serialize(serializer)
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use ser::{self, Serialize, SerializeSeq, SerializeTuple, SerializeTupleStruct,
|
use ser::{self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
|
||||||
SerializeTupleVariant, SerializeMap, SerializeStruct, SerializeStructVariant};
|
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant};
|
||||||
|
|
||||||
/// Helper type for implementing a `Serializer` that does not support
|
/// Helper type for implementing a `Serializer` that does not support
|
||||||
/// serializing one of the compound types.
|
/// serializing one of the compound types.
|
||||||
|
|||||||
@@ -93,7 +93,8 @@
|
|||||||
//! - Path
|
//! - Path
|
||||||
//! - PathBuf
|
//! - PathBuf
|
||||||
//! - Range\<T\>
|
//! - Range\<T\>
|
||||||
//! - NonZero\<T\> (unstable)
|
//! - NonZero\<T\> (unstable, deprecated)
|
||||||
|
//! - num::NonZero* (unstable)
|
||||||
//! - **Net types**:
|
//! - **Net types**:
|
||||||
//! - IpAddr
|
//! - IpAddr
|
||||||
//! - Ipv4Addr
|
//! - Ipv4Addr
|
||||||
@@ -1412,7 +1413,9 @@ pub trait Serializer: Sized {
|
|||||||
/// change, as a value serialized in human-readable mode is not required to
|
/// change, as a value serialized in human-readable mode is not required to
|
||||||
/// deserialize from the same data in compact mode.
|
/// deserialize from the same data in compact mode.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_human_readable(&self) -> bool { true }
|
fn is_human_readable(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returned from `Serializer::serialize_seq`.
|
/// Returned from `Serializer::serialize_seq`.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.21" # remember to update html_root_url
|
version = "1.0.43" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||||
@@ -14,14 +14,19 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-
|
|||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "serde-rs/serde" }
|
travis-ci = { repository = "serde-rs/serde" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
deserialize_in_place = []
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = "0.3.8"
|
proc-macro2 = "0.3"
|
||||||
serde_derive_internals = { version = "=0.17.0", default-features = false, path = "../serde_derive_internals" }
|
quote = "0.5.2"
|
||||||
syn = { version = "0.11", features = ["visit"] }
|
serde_derive_internals = { version = "=0.23.1", default-features = false, path = "../serde_derive_internals" }
|
||||||
|
syn = { version = "0.13", features = ["visit"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde = { version = "1.0", path = "../serde" }
|
serde = { version = "1.0", path = "../serde" }
|
||||||
|
|||||||
+174
-158
@@ -8,33 +8,31 @@
|
|||||||
|
|
||||||
use std::collections::HashSet;
|
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;
|
use internals::attr;
|
||||||
|
|
||||||
macro_rules! path {
|
use proc_macro2::Span;
|
||||||
($($path:tt)+) => {
|
|
||||||
syn::parse_path(quote!($($path)+).as_str()).unwrap()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the default from every type parameter because in the generated impls
|
// Remove the default from every type parameter because in the generated impls
|
||||||
// they look like associated types: "error: associated type bindings are not
|
// they look like associated types: "error: associated type bindings are not
|
||||||
// allowed here".
|
// allowed here".
|
||||||
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
|
pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
|
||||||
syn::Generics {
|
syn::Generics {
|
||||||
ty_params: generics
|
params: generics
|
||||||
.ty_params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.map(
|
.map(|param| match *param {
|
||||||
|ty_param| {
|
syn::GenericParam::Type(ref param) => syn::GenericParam::Type(syn::TypeParam {
|
||||||
syn::TyParam {
|
eq_token: None,
|
||||||
default: None,
|
default: None,
|
||||||
..ty_param.clone()
|
..param.clone()
|
||||||
}
|
}),
|
||||||
},
|
_ => param.clone(),
|
||||||
)
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
..generics.clone()
|
..generics.clone()
|
||||||
}
|
}
|
||||||
@@ -46,27 +44,24 @@ pub fn with_where_predicates(
|
|||||||
) -> syn::Generics {
|
) -> syn::Generics {
|
||||||
let mut generics = generics.clone();
|
let mut generics = generics.clone();
|
||||||
generics
|
generics
|
||||||
.where_clause
|
.make_where_clause()
|
||||||
.predicates
|
.predicates
|
||||||
.extend_from_slice(predicates);
|
.extend(predicates.into_iter().cloned());
|
||||||
generics
|
generics
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_where_predicates_from_fields<F>(
|
pub fn with_where_predicates_from_fields(
|
||||||
cont: &Container,
|
cont: &Container,
|
||||||
generics: &syn::Generics,
|
generics: &syn::Generics,
|
||||||
from_field: F,
|
from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
|
||||||
) -> syn::Generics
|
) -> syn::Generics {
|
||||||
where
|
let predicates = cont.data
|
||||||
F: Fn(&attr::Field) -> Option<&[syn::WherePredicate]>,
|
|
||||||
{
|
|
||||||
let predicates = cont.body
|
|
||||||
.all_fields()
|
.all_fields()
|
||||||
.flat_map(|field| from_field(&field.attrs))
|
.flat_map(|field| from_field(&field.attrs))
|
||||||
.flat_map(|predicates| predicates.to_vec());
|
.flat_map(|predicates| predicates.to_vec());
|
||||||
|
|
||||||
let mut generics = generics.clone();
|
let mut generics = generics.clone();
|
||||||
generics.where_clause.predicates.extend(predicates);
|
generics.make_where_clause().predicates.extend(predicates);
|
||||||
generics
|
generics
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,40 +76,53 @@ where
|
|||||||
// #[serde(skip_serializing)]
|
// #[serde(skip_serializing)]
|
||||||
// c: C,
|
// c: C,
|
||||||
// }
|
// }
|
||||||
pub fn with_bound<F>(
|
pub fn with_bound(
|
||||||
cont: &Container,
|
cont: &Container,
|
||||||
generics: &syn::Generics,
|
generics: &syn::Generics,
|
||||||
filter: F,
|
filter: fn(&attr::Field, Option<&attr::Variant>) -> bool,
|
||||||
bound: &syn::Path,
|
bound: &syn::Path,
|
||||||
) -> syn::Generics
|
) -> syn::Generics {
|
||||||
where
|
struct FindTyParams<'ast> {
|
||||||
F: Fn(&attr::Field, Option<&attr::Variant>) -> bool,
|
|
||||||
{
|
|
||||||
struct FindTyParams {
|
|
||||||
// Set of all generic type parameters on the current struct (A, B, C in
|
// Set of all generic type parameters on the current struct (A, B, C in
|
||||||
// the example). Initialized up front.
|
// 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
|
// 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
|
// returns true (A and B in the example). Filled in as the visitor sees
|
||||||
// them.
|
// 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 {
|
impl<'ast> Visit<'ast> for FindTyParams<'ast> {
|
||||||
fn visit_path(&mut self, path: &syn::Path) {
|
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 let Some(seg) = path.segments.last() {
|
||||||
if seg.ident == "PhantomData" {
|
if seg.into_value().ident == "PhantomData" {
|
||||||
// Hardcoded exception, because PhantomData<T> implements
|
// Hardcoded exception, because PhantomData<T> implements
|
||||||
// Serialize and Deserialize whether or not T implements it.
|
// Serialize and Deserialize whether or not T implements it.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !path.global && path.segments.len() == 1 {
|
if path.leading_colon.is_none() && path.segments.len() == 1 {
|
||||||
let id = path.segments[0].ident.clone();
|
let id = path.segments[0].ident;
|
||||||
if self.all_ty_params.contains(&id) {
|
if self.all_type_params.contains(&id) {
|
||||||
self.relevant_ty_params.insert(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.
|
// Type parameter should not be considered used by a macro path.
|
||||||
@@ -123,67 +131,66 @@ where
|
|||||||
// mac: T!(),
|
// mac: T!(),
|
||||||
// marker: PhantomData<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
|
let all_type_params = generics.type_params().map(|param| param.ident).collect();
|
||||||
.ty_params
|
|
||||||
.iter()
|
|
||||||
.map(|ty_param| ty_param.ident.clone())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut visitor = FindTyParams {
|
let mut visitor = FindTyParams {
|
||||||
all_ty_params: all_ty_params,
|
all_type_params: all_type_params,
|
||||||
relevant_ty_params: HashSet::new(),
|
relevant_type_params: HashSet::new(),
|
||||||
|
associated_type_usage: Vec::new(),
|
||||||
};
|
};
|
||||||
match cont.body {
|
match cont.data {
|
||||||
Body::Enum(ref variants) => {
|
Data::Enum(ref variants) => for variant in variants.iter() {
|
||||||
for variant in variants.iter() {
|
let relevant_fields = variant
|
||||||
let relevant_fields = variant
|
.fields
|
||||||
.fields
|
.iter()
|
||||||
.iter()
|
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
|
||||||
.filter(|field| filter(&field.attrs, Some(&variant.attrs)));
|
for field in relevant_fields {
|
||||||
for field in relevant_fields {
|
visitor.visit_field(field.original);
|
||||||
visit::walk_ty(&mut visitor, field.ty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Body::Struct(_, ref fields) => {
|
Data::Struct(_, ref fields) => {
|
||||||
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
|
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
|
||||||
visit::walk_ty(&mut visitor, field.ty);
|
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
|
let new_predicates = generics
|
||||||
.ty_params
|
.type_params()
|
||||||
.iter()
|
.map(|param| param.ident)
|
||||||
.map(|ty_param| ty_param.ident.clone())
|
.filter(|id| relevant_type_params.contains(id))
|
||||||
.filter(|id| visitor.relevant_ty_params.contains(id))
|
.map(|id| syn::TypePath {
|
||||||
.map(
|
qself: None,
|
||||||
|id| {
|
path: id.into(),
|
||||||
syn::WherePredicate::BoundPredicate(
|
})
|
||||||
syn::WhereBoundPredicate {
|
.chain(associated_type_usage.into_iter().cloned())
|
||||||
bound_lifetimes: Vec::new(),
|
.map(|bounded_ty| {
|
||||||
// the type parameter that is being bounded e.g. T
|
syn::WherePredicate::Type(syn::PredicateType {
|
||||||
bounded_ty: syn::Ty::Path(None, id.into()),
|
lifetimes: None,
|
||||||
// the bound e.g. Serialize
|
// the type parameter that is being bounded e.g. T
|
||||||
bounds: vec![
|
bounded_ty: syn::Type::Path(bounded_ty),
|
||||||
syn::TyParamBound::Trait(
|
colon_token: Default::default(),
|
||||||
syn::PolyTraitRef {
|
// the bound e.g. Serialize
|
||||||
bound_lifetimes: Vec::new(),
|
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
|
||||||
trait_ref: bound.clone(),
|
paren_token: None,
|
||||||
},
|
modifier: syn::TraitBoundModifier::None,
|
||||||
syn::TraitBoundModifier::None,
|
lifetimes: None,
|
||||||
),
|
path: bound.clone(),
|
||||||
],
|
})].into_iter()
|
||||||
},
|
.collect(),
|
||||||
)
|
})
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
let mut generics = generics.clone();
|
let mut generics = generics.clone();
|
||||||
generics.where_clause.predicates.extend(new_predicates);
|
generics
|
||||||
|
.make_where_clause()
|
||||||
|
.predicates
|
||||||
|
.extend(new_predicates);
|
||||||
generics
|
generics
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,81 +201,90 @@ pub fn with_self_bound(
|
|||||||
) -> syn::Generics {
|
) -> syn::Generics {
|
||||||
let mut generics = generics.clone();
|
let mut generics = generics.clone();
|
||||||
generics
|
generics
|
||||||
.where_clause
|
.make_where_clause()
|
||||||
.predicates
|
.predicates
|
||||||
.push(
|
.push(syn::WherePredicate::Type(syn::PredicateType {
|
||||||
syn::WherePredicate::BoundPredicate(
|
lifetimes: None,
|
||||||
syn::WhereBoundPredicate {
|
// the type that is being bounded e.g. MyStruct<'a, T>
|
||||||
bound_lifetimes: Vec::new(),
|
bounded_ty: type_of_item(cont),
|
||||||
// the type that is being bounded e.g. MyStruct<'a, T>
|
colon_token: Default::default(),
|
||||||
bounded_ty: type_of_item(cont),
|
// the bound e.g. Default
|
||||||
// the bound e.g. Default
|
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
|
||||||
bounds: vec![
|
paren_token: None,
|
||||||
syn::TyParamBound::Trait(
|
modifier: syn::TraitBoundModifier::None,
|
||||||
syn::PolyTraitRef {
|
lifetimes: None,
|
||||||
bound_lifetimes: Vec::new(),
|
path: bound.clone(),
|
||||||
trait_ref: bound.clone(),
|
})].into_iter()
|
||||||
},
|
.collect(),
|
||||||
syn::TraitBoundModifier::None,
|
}));
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
generics
|
generics
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
|
pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics {
|
||||||
let mut generics = generics.clone();
|
let bound = syn::Lifetime::new(lifetime, Span::call_site());
|
||||||
|
let def = syn::LifetimeDef {
|
||||||
|
attrs: Vec::new(),
|
||||||
|
lifetime: bound,
|
||||||
|
colon_token: None,
|
||||||
|
bounds: Punctuated::new(),
|
||||||
|
};
|
||||||
|
|
||||||
for lifetime_def in &mut generics.lifetimes {
|
let params = Some(syn::GenericParam::Lifetime(def))
|
||||||
lifetime_def.bounds.push(syn::Lifetime::new(lifetime));
|
.into_iter()
|
||||||
|
.chain(generics.params.iter().cloned().map(|mut param| {
|
||||||
|
match param {
|
||||||
|
syn::GenericParam::Lifetime(ref mut param) => {
|
||||||
|
param.bounds.push(bound);
|
||||||
|
}
|
||||||
|
syn::GenericParam::Type(ref mut param) => {
|
||||||
|
param.bounds.push(syn::TypeParamBound::Lifetime(bound));
|
||||||
|
}
|
||||||
|
syn::GenericParam::Const(_) => {}
|
||||||
|
}
|
||||||
|
param
|
||||||
|
}))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
syn::Generics {
|
||||||
|
params: params,
|
||||||
|
..generics.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
for ty_param in &mut generics.ty_params {
|
|
||||||
ty_param
|
|
||||||
.bounds
|
|
||||||
.push(syn::TyParamBound::Region(syn::Lifetime::new(lifetime)));
|
|
||||||
}
|
|
||||||
|
|
||||||
generics
|
|
||||||
.lifetimes
|
|
||||||
.push(
|
|
||||||
syn::LifetimeDef {
|
|
||||||
attrs: Vec::new(),
|
|
||||||
lifetime: syn::Lifetime::new(lifetime),
|
|
||||||
bounds: Vec::new(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
generics
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_of_item(cont: &Container) -> syn::Ty {
|
fn type_of_item(cont: &Container) -> syn::Type {
|
||||||
syn::Ty::Path(
|
syn::Type::Path(syn::TypePath {
|
||||||
None,
|
qself: None,
|
||||||
syn::Path {
|
path: syn::Path {
|
||||||
global: false,
|
leading_colon: None,
|
||||||
segments: vec![
|
segments: vec![syn::PathSegment {
|
||||||
syn::PathSegment {
|
ident: cont.ident,
|
||||||
ident: cont.ident.clone(),
|
arguments: syn::PathArguments::AngleBracketed(
|
||||||
parameters: syn::PathParameters::AngleBracketed(
|
syn::AngleBracketedGenericArguments {
|
||||||
syn::AngleBracketedParameterData {
|
colon2_token: None,
|
||||||
lifetimes: cont.generics
|
lt_token: Default::default(),
|
||||||
.lifetimes
|
args: cont.generics
|
||||||
.iter()
|
.params
|
||||||
.map(|def| def.lifetime.clone())
|
.iter()
|
||||||
.collect(),
|
.map(|param| match *param {
|
||||||
types: cont.generics
|
syn::GenericParam::Type(ref param) => {
|
||||||
.ty_params
|
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
|
||||||
.iter()
|
qself: None,
|
||||||
.map(|param| syn::Ty::Path(None, param.ident.clone().into()))
|
path: param.ident.into(),
|
||||||
.collect(),
|
}))
|
||||||
bindings: Vec::new(),
|
}
|
||||||
},
|
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(),
|
||||||
},
|
},
|
||||||
)
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+1312
-419
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use quote::{Tokens, ToTokens};
|
use quote::{ToTokens, Tokens};
|
||||||
|
use syn::token;
|
||||||
|
|
||||||
pub enum Fragment {
|
pub enum Fragment {
|
||||||
/// Tokens that can be used as an expression.
|
/// Tokens that can be used as an expression.
|
||||||
@@ -36,9 +37,7 @@ impl ToTokens for Expr {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
Fragment::Expr(ref expr) => expr.to_tokens(out),
|
Fragment::Expr(ref expr) => expr.to_tokens(out),
|
||||||
Fragment::Block(ref block) => {
|
Fragment::Block(ref block) => {
|
||||||
out.append("{");
|
token::Brace::default().surround(out, |out| block.to_tokens(out));
|
||||||
block.to_tokens(out);
|
|
||||||
out.append("}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,13 +62,20 @@ impl ToTokens for Match {
|
|||||||
match self.0 {
|
match self.0 {
|
||||||
Fragment::Expr(ref expr) => {
|
Fragment::Expr(ref expr) => {
|
||||||
expr.to_tokens(out);
|
expr.to_tokens(out);
|
||||||
out.append(",");
|
<Token![,]>::default().to_tokens(out);
|
||||||
}
|
}
|
||||||
Fragment::Block(ref block) => {
|
Fragment::Block(ref block) => {
|
||||||
out.append("{");
|
token::Brace::default().surround(out, |out| block.to_tokens(out));
|
||||||
block.to_tokens(out);
|
|
||||||
out.append("}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<Tokens> for Fragment {
|
||||||
|
fn as_ref(&self) -> &Tokens {
|
||||||
|
match *self {
|
||||||
|
Fragment::Expr(ref expr) => expr,
|
||||||
|
Fragment::Block(ref block) => block,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+17
-12
@@ -22,45 +22,50 @@
|
|||||||
//!
|
//!
|
||||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.21")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.43")]
|
||||||
|
#![cfg_attr(
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
feature = "cargo-clippy",
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
|
allow(enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding)
|
||||||
|
)]
|
||||||
// The `quote!` macro requires deep recursion.
|
// The `quote!` macro requires deep recursion.
|
||||||
#![recursion_limit = "192"]
|
#![recursion_limit = "512"]
|
||||||
|
|
||||||
extern crate syn;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate quote;
|
extern crate quote;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate syn;
|
||||||
|
|
||||||
extern crate serde_derive_internals as internals;
|
extern crate serde_derive_internals as internals;
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
extern crate proc_macro2;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
use syn::DeriveInput;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod bound;
|
mod bound;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod fragment;
|
mod fragment;
|
||||||
|
|
||||||
mod ser;
|
|
||||||
mod de;
|
mod de;
|
||||||
|
mod ser;
|
||||||
|
mod try;
|
||||||
|
|
||||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
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) {
|
match ser::expand_derive_serialize(&input) {
|
||||||
Ok(expanded) => expanded.parse().unwrap(),
|
Ok(expanded) => expanded.into(),
|
||||||
Err(msg) => panic!(msg),
|
Err(msg) => panic!(msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
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) {
|
match de::expand_derive_deserialize(&input) {
|
||||||
Ok(expanded) => expanded.parse().unwrap(),
|
Ok(expanded) => expanded.into(),
|
||||||
Err(msg) => panic!(msg),
|
Err(msg) => panic!(msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+393
-299
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
|||||||
|
use quote::Tokens;
|
||||||
|
use proc_macro2::{Op, Spacing};
|
||||||
|
|
||||||
|
// 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]
|
[package]
|
||||||
name = "serde_derive_internals"
|
name = "serde_derive_internals"
|
||||||
version = "0.17.0" # 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>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "AST representation used by Serde derive macros. Unstable."
|
description = "AST representation used by Serde derive macros. Unstable."
|
||||||
@@ -12,8 +12,8 @@ readme = "README.md"
|
|||||||
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn = { version = "0.11.10", default-features = false, features = ["parsing"] }
|
proc-macro2 = "0.3"
|
||||||
synom = "0.11"
|
syn = { version = "0.13", default-features = false, features = ["derive", "parsing", "clone-impls"] }
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "serde-rs/serde" }
|
travis-ci = { repository = "serde-rs/serde" }
|
||||||
|
|||||||
@@ -6,19 +6,20 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use syn;
|
|
||||||
use attr;
|
use attr;
|
||||||
use check;
|
use check;
|
||||||
|
use syn;
|
||||||
|
use syn::punctuated::Punctuated;
|
||||||
use Ctxt;
|
use Ctxt;
|
||||||
|
|
||||||
pub struct Container<'a> {
|
pub struct Container<'a> {
|
||||||
pub ident: syn::Ident,
|
pub ident: syn::Ident,
|
||||||
pub attrs: attr::Container,
|
pub attrs: attr::Container,
|
||||||
pub body: Body<'a>,
|
pub data: Data<'a>,
|
||||||
pub generics: &'a syn::Generics,
|
pub generics: &'a syn::Generics,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Body<'a> {
|
pub enum Data<'a> {
|
||||||
Enum(Vec<Variant<'a>>),
|
Enum(Vec<Variant<'a>>),
|
||||||
Struct(Style, Vec<Field<'a>>),
|
Struct(Style, Vec<Field<'a>>),
|
||||||
}
|
}
|
||||||
@@ -33,7 +34,8 @@ pub struct Variant<'a> {
|
|||||||
pub struct Field<'a> {
|
pub struct Field<'a> {
|
||||||
pub ident: Option<syn::Ident>,
|
pub ident: Option<syn::Ident>,
|
||||||
pub attrs: attr::Field,
|
pub attrs: attr::Field,
|
||||||
pub ty: &'a syn::Ty,
|
pub ty: &'a syn::Type,
|
||||||
|
pub original: &'a syn::Field,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@@ -46,36 +48,48 @@ pub enum Style {
|
|||||||
|
|
||||||
impl<'a> Container<'a> {
|
impl<'a> Container<'a> {
|
||||||
pub fn from_ast(cx: &Ctxt, item: &'a syn::DeriveInput) -> 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 {
|
let mut data = match item.data {
|
||||||
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
|
syn::Data::Enum(ref data) => {
|
||||||
syn::Body::Struct(ref variant_data) => {
|
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
|
||||||
let (style, fields) = struct_from_ast(cx, variant_data, None);
|
}
|
||||||
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 {
|
let mut has_flatten = false;
|
||||||
Body::Enum(ref mut variants) => {
|
match data {
|
||||||
for ref mut variant in variants {
|
Data::Enum(ref mut variants) => for variant in variants {
|
||||||
variant.attrs.rename_by_rule(attrs.rename_all());
|
variant.attrs.rename_by_rule(attrs.rename_all());
|
||||||
for ref mut field in &mut variant.fields {
|
for field in &mut variant.fields {
|
||||||
field.attrs.rename_by_rule(variant.attrs.rename_all());
|
if field.attrs.flatten() {
|
||||||
|
has_flatten = true;
|
||||||
}
|
}
|
||||||
|
field.attrs.rename_by_rule(variant.attrs.rename_all());
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Body::Struct(_, ref mut fields) => {
|
Data::Struct(_, ref mut fields) => for field in fields {
|
||||||
for field in fields {
|
if field.attrs.flatten() {
|
||||||
field.attrs.rename_by_rule(attrs.rename_all());
|
has_flatten = true;
|
||||||
}
|
}
|
||||||
}
|
field.attrs.rename_by_rule(attrs.rename_all());
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if has_flatten {
|
||||||
|
attrs.mark_has_flatten();
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = Container {
|
let item = Container {
|
||||||
ident: item.ident.clone(),
|
ident: item.ident,
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
body: body,
|
data: data,
|
||||||
generics: &item.generics,
|
generics: &item.generics,
|
||||||
};
|
};
|
||||||
check::check(cx, &item);
|
check::check(cx, &item);
|
||||||
@@ -83,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> {
|
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
|
||||||
match *self {
|
match *self {
|
||||||
Body::Enum(ref variants) => {
|
Data::Enum(ref variants) => {
|
||||||
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
|
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
|
||||||
}
|
}
|
||||||
Body::Struct(_, ref fields) => Box::new(fields.iter()),
|
Data::Struct(_, ref fields) => Box::new(fields.iter()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,47 +112,64 @@ impl<'a> Body<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>> {
|
fn enum_from_ast<'a>(
|
||||||
|
cx: &Ctxt,
|
||||||
|
variants: &'a Punctuated<syn::Variant, Token![,]>,
|
||||||
|
container_default: &attr::Default,
|
||||||
|
) -> Vec<Variant<'a>> {
|
||||||
variants
|
variants
|
||||||
.iter()
|
.iter()
|
||||||
.map(
|
.map(|variant| {
|
||||||
|variant| {
|
let attrs = attr::Variant::from_ast(cx, variant);
|
||||||
let attrs = attr::Variant::from_ast(cx, variant);
|
let (style, fields) =
|
||||||
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
|
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
|
||||||
Variant {
|
Variant {
|
||||||
ident: variant.ident.clone(),
|
ident: variant.ident,
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
style: style,
|
style: style,
|
||||||
fields: fields,
|
fields: fields,
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
)
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
|
fn struct_from_ast<'a>(
|
||||||
match *data {
|
cx: &Ctxt,
|
||||||
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
|
fields: &'a syn::Fields,
|
||||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
attrs: Option<&attr::Variant>,
|
||||||
(Style::Newtype, fields_from_ast(cx, fields, attrs))
|
container_default: &attr::Default,
|
||||||
}
|
) -> (Style, Vec<Field<'a>>) {
|
||||||
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
|
match *fields {
|
||||||
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
syn::Fields::Named(ref fields) => (
|
||||||
|
Style::Struct,
|
||||||
|
fields_from_ast(cx, &fields.named, attrs, container_default),
|
||||||
|
),
|
||||||
|
syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
|
||||||
|
Style::Newtype,
|
||||||
|
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
|
||||||
|
),
|
||||||
|
syn::Fields::Unnamed(ref fields) => (
|
||||||
|
Style::Tuple,
|
||||||
|
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
|
||||||
|
),
|
||||||
|
syn::Fields::Unit => (Style::Unit, Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr::Variant>) -> Vec<Field<'a>> {
|
fn fields_from_ast<'a>(
|
||||||
|
cx: &Ctxt,
|
||||||
|
fields: &'a Punctuated<syn::Field, Token![,]>,
|
||||||
|
attrs: Option<&attr::Variant>,
|
||||||
|
container_default: &attr::Default,
|
||||||
|
) -> Vec<Field<'a>> {
|
||||||
fields
|
fields
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(
|
.map(|(i, field)| Field {
|
||||||
|(i, field)| {
|
ident: field.ident,
|
||||||
Field {
|
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
|
||||||
ident: field.ident.clone(),
|
ty: &field.ty,
|
||||||
attrs: attr::Field::from_ast(cx, i, field, attrs),
|
original: field,
|
||||||
ty: &field.ty,
|
})
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
+541
-359
File diff suppressed because it is too large
Load Diff
@@ -7,19 +7,21 @@
|
|||||||
// except according to those terms.
|
// 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
|
// 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::ascii::AsciiExt;
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use self::RenameRule::*;
|
use self::RenameRule::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum RenameRule {
|
pub enum RenameRule {
|
||||||
/// Don't apply a default rename rule.
|
/// Don't apply a default rename rule.
|
||||||
None,
|
None,
|
||||||
/// Rename direct children to "lowercase" style.
|
/// Rename direct children to "lowercase" style.
|
||||||
LowerCase,
|
LowerCase,
|
||||||
|
/// Rename direct children to "UPPERCASE" style.
|
||||||
|
UPPERCASE,
|
||||||
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
|
/// Rename direct children to "PascalCase" style, as typically used for enum variants.
|
||||||
PascalCase,
|
PascalCase,
|
||||||
/// Rename direct children to "camelCase" style.
|
/// Rename direct children to "camelCase" style.
|
||||||
@@ -31,7 +33,7 @@ pub enum RenameRule {
|
|||||||
/// Rename direct children to "kebab-case" style.
|
/// Rename direct children to "kebab-case" style.
|
||||||
KebabCase,
|
KebabCase,
|
||||||
/// Rename direct children to "SCREAMING-KEBAB-CASE" style.
|
/// Rename direct children to "SCREAMING-KEBAB-CASE" style.
|
||||||
ScreamingKebabCase
|
ScreamingKebabCase,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenameRule {
|
impl RenameRule {
|
||||||
@@ -39,6 +41,7 @@ impl RenameRule {
|
|||||||
match *self {
|
match *self {
|
||||||
None | PascalCase => variant.to_owned(),
|
None | PascalCase => variant.to_owned(),
|
||||||
LowerCase => variant.to_ascii_lowercase(),
|
LowerCase => variant.to_ascii_lowercase(),
|
||||||
|
UPPERCASE => variant.to_ascii_uppercase(),
|
||||||
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
|
CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..],
|
||||||
SnakeCase => {
|
SnakeCase => {
|
||||||
let mut snake = String::new();
|
let mut snake = String::new();
|
||||||
@@ -52,13 +55,16 @@ impl RenameRule {
|
|||||||
}
|
}
|
||||||
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
|
ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(),
|
||||||
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
|
KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"),
|
||||||
ScreamingKebabCase => ScreamingSnakeCase.apply_to_variant(variant).replace('_', "-")
|
ScreamingKebabCase => ScreamingSnakeCase
|
||||||
|
.apply_to_variant(variant)
|
||||||
|
.replace('_', "-"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_to_field(&self, field: &str) -> String {
|
pub fn apply_to_field(&self, field: &str) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
None | LowerCase | SnakeCase => field.to_owned(),
|
None | LowerCase | SnakeCase => field.to_owned(),
|
||||||
|
UPPERCASE => field.to_ascii_uppercase(),
|
||||||
PascalCase => {
|
PascalCase => {
|
||||||
let mut pascal = String::new();
|
let mut pascal = String::new();
|
||||||
let mut capitalize = true;
|
let mut capitalize = true;
|
||||||
@@ -80,7 +86,7 @@ impl RenameRule {
|
|||||||
}
|
}
|
||||||
ScreamingSnakeCase => field.to_ascii_uppercase(),
|
ScreamingSnakeCase => field.to_ascii_uppercase(),
|
||||||
KebabCase => field.replace('_', "-"),
|
KebabCase => field.replace('_', "-"),
|
||||||
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-")
|
ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,6 +97,7 @@ impl FromStr for RenameRule {
|
|||||||
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
|
fn from_str(rename_all_str: &str) -> Result<Self, Self::Err> {
|
||||||
match rename_all_str {
|
match rename_all_str {
|
||||||
"lowercase" => Ok(LowerCase),
|
"lowercase" => Ok(LowerCase),
|
||||||
|
"UPPERCASE" => Ok(UPPERCASE),
|
||||||
"PascalCase" => Ok(PascalCase),
|
"PascalCase" => Ok(PascalCase),
|
||||||
"camelCase" => Ok(CamelCase),
|
"camelCase" => Ok(CamelCase),
|
||||||
"snake_case" => Ok(SnakeCase),
|
"snake_case" => Ok(SnakeCase),
|
||||||
@@ -104,34 +111,58 @@ impl FromStr for RenameRule {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rename_variants() {
|
fn rename_variants() {
|
||||||
for &(original, lower, camel, snake, screaming, kebab, screaming_kebab) in
|
for &(original, lower, 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", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
|
),
|
||||||
("A", "a", "a", "a", "A", "a", "A"),
|
(
|
||||||
("Z42", "z42", "z42", "z42", "Z42", "z42", "Z42"),
|
"VeryTasty",
|
||||||
] {
|
"verytasty",
|
||||||
|
"VERYTASTY",
|
||||||
|
"veryTasty",
|
||||||
|
"very_tasty",
|
||||||
|
"VERY_TASTY",
|
||||||
|
"very-tasty",
|
||||||
|
"VERY-TASTY",
|
||||||
|
),
|
||||||
|
("A", "a", "A", "a", "a", "A", "a", "A"),
|
||||||
|
("Z42", "z42", "Z42", "z42", "z42", "Z42", "z42", "Z42"),
|
||||||
|
] {
|
||||||
assert_eq!(None.apply_to_variant(original), original);
|
assert_eq!(None.apply_to_variant(original), original);
|
||||||
assert_eq!(LowerCase.apply_to_variant(original), lower);
|
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!(PascalCase.apply_to_variant(original), original);
|
||||||
assert_eq!(CamelCase.apply_to_variant(original), camel);
|
assert_eq!(CamelCase.apply_to_variant(original), camel);
|
||||||
assert_eq!(SnakeCase.apply_to_variant(original), snake);
|
assert_eq!(SnakeCase.apply_to_variant(original), snake);
|
||||||
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
|
assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming);
|
||||||
assert_eq!(KebabCase.apply_to_variant(original), kebab);
|
assert_eq!(KebabCase.apply_to_variant(original), kebab);
|
||||||
assert_eq!(ScreamingKebabCase.apply_to_variant(original), screaming_kebab);
|
assert_eq!(
|
||||||
|
ScreamingKebabCase.apply_to_variant(original),
|
||||||
|
screaming_kebab
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rename_fields() {
|
fn rename_fields() {
|
||||||
for &(original, pascal, camel, screaming, kebab, screaming_kebab) in
|
for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[
|
||||||
&[
|
(
|
||||||
("outcome", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME"),
|
"outcome", "OUTCOME", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME",
|
||||||
("very_tasty", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY"),
|
),
|
||||||
("a", "A", "a", "A", "a", "A"),
|
(
|
||||||
("z42", "Z42", "z42", "Z42", "z42", "Z42"),
|
"very_tasty",
|
||||||
] {
|
"VERY_TASTY",
|
||||||
|
"VeryTasty",
|
||||||
|
"veryTasty",
|
||||||
|
"VERY_TASTY",
|
||||||
|
"very-tasty",
|
||||||
|
"VERY-TASTY",
|
||||||
|
),
|
||||||
|
("a", "A", "A", "a", "A", "a", "A"),
|
||||||
|
("z42", "Z42", "Z42", "z42", "Z42", "z42", "Z42"),
|
||||||
|
] {
|
||||||
assert_eq!(None.apply_to_field(original), original);
|
assert_eq!(None.apply_to_field(original), original);
|
||||||
|
assert_eq!(UPPERCASE.apply_to_field(original), upper);
|
||||||
assert_eq!(PascalCase.apply_to_field(original), pascal);
|
assert_eq!(PascalCase.apply_to_field(original), pascal);
|
||||||
assert_eq!(CamelCase.apply_to_field(original), camel);
|
assert_eq!(CamelCase.apply_to_field(original), camel);
|
||||||
assert_eq!(SnakeCase.apply_to_field(original), original);
|
assert_eq!(SnakeCase.apply_to_field(original), original);
|
||||||
|
|||||||
@@ -6,38 +6,84 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use ast::{Body, Container, Style};
|
use ast::{Container, Data, Style};
|
||||||
use attr::Identifier;
|
use attr::{EnumTag, Identifier};
|
||||||
use Ctxt;
|
use Ctxt;
|
||||||
|
|
||||||
/// Cross-cutting checks that require looking at more than a single attrs
|
/// Cross-cutting checks that require looking at more than a single attrs
|
||||||
/// object. Simpler checks should happen when parsing and building the attrs.
|
/// object. Simpler checks should happen when parsing and building the attrs.
|
||||||
pub fn check(cx: &Ctxt, cont: &Container) {
|
pub fn check(cx: &Ctxt, cont: &Container) {
|
||||||
check_getter(cx, cont);
|
check_getter(cx, cont);
|
||||||
|
check_flatten(cx, cont);
|
||||||
check_identifier(cx, cont);
|
check_identifier(cx, cont);
|
||||||
check_variant_skip_attrs(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`
|
/// Getters are only allowed inside structs (not enums) with the `remote`
|
||||||
/// attribute.
|
/// attribute.
|
||||||
fn check_getter(cx: &Ctxt, cont: &Container) {
|
fn check_getter(cx: &Ctxt, cont: &Container) {
|
||||||
match cont.body {
|
match cont.data {
|
||||||
Body::Enum(_) => {
|
Data::Enum(_) => {
|
||||||
if cont.body.has_getter() {
|
if cont.data.has_getter() {
|
||||||
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
|
cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Body::Struct(_, _) => {
|
Data::Struct(_, _) => {
|
||||||
if cont.body.has_getter() && cont.attrs.remote().is_none() {
|
if cont.data.has_getter() && cont.attrs.remote().is_none() {
|
||||||
cx.error(
|
cx.error(
|
||||||
"#[serde(getter = \"...\")] can only be used in structs \
|
"#[serde(getter = \"...\")] can only be used in structs \
|
||||||
that have #[serde(remote = \"...\")]",
|
that have #[serde(remote = \"...\")]",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flattening has some restrictions we can test.
|
||||||
|
fn check_flatten(cx: &Ctxt, cont: &Container) {
|
||||||
|
match cont.data {
|
||||||
|
Data::Enum(_) => {
|
||||||
|
if cont.attrs.has_flatten() {
|
||||||
|
cx.error("#[serde(flatten)] cannot be used within enums");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data::Struct(style, _) => {
|
||||||
|
for field in cont.data.all_fields() {
|
||||||
|
if !field.attrs.flatten() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
match style {
|
||||||
|
Style::Tuple => {
|
||||||
|
cx.error("#[serde(flatten)] cannot be used on tuple structs");
|
||||||
|
}
|
||||||
|
Style::Newtype => {
|
||||||
|
cx.error("#[serde(flatten)] cannot be used on newtype structs");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if field.attrs.skip_serializing() {
|
||||||
|
cx.error(
|
||||||
|
"#[serde(flatten] can not be combined with \
|
||||||
|
#[serde(skip_serializing)]",
|
||||||
|
);
|
||||||
|
} else if field.attrs.skip_serializing_if().is_some() {
|
||||||
|
cx.error(
|
||||||
|
"#[serde(flatten] can not be combined with \
|
||||||
|
#[serde(skip_serializing_if = \"...\")]",
|
||||||
|
);
|
||||||
|
} else if field.attrs.skip_deserializing() {
|
||||||
|
cx.error(
|
||||||
|
"#[serde(flatten] can not be combined with \
|
||||||
|
#[serde(skip_deserializing)]",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The `other` attribute must be used at most once and it must be the last
|
/// 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.
|
/// variant of an enum that has the `field_identifier` attribute.
|
||||||
///
|
///
|
||||||
@@ -45,18 +91,21 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
|
|||||||
/// `field_identifier` all but possibly one variant must be unit variants. The
|
/// `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.
|
/// last variant may be a newtype variant which is an implicit "other" case.
|
||||||
fn check_identifier(cx: &Ctxt, cont: &Container) {
|
fn check_identifier(cx: &Ctxt, cont: &Container) {
|
||||||
let variants = match cont.body {
|
let variants = match cont.data {
|
||||||
Body::Enum(ref variants) => variants,
|
Data::Enum(ref variants) => variants,
|
||||||
Body::Struct(_, _) => {
|
Data::Struct(_, _) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, variant) in variants.iter().enumerate() {
|
for (i, variant) in variants.iter().enumerate() {
|
||||||
match (variant.style, cont.attrs.identifier(), variant.attrs.other()) {
|
match (
|
||||||
|
variant.style,
|
||||||
|
cont.attrs.identifier(),
|
||||||
|
variant.attrs.other(),
|
||||||
|
) {
|
||||||
// The `other` attribute may only be used in a field_identifier.
|
// The `other` attribute may only be used in a field_identifier.
|
||||||
(_, Identifier::Variant, true) |
|
(_, Identifier::Variant, true) | (_, Identifier::No, true) => {
|
||||||
(_, Identifier::No, true) => {
|
|
||||||
cx.error("#[serde(other)] may only be used inside a field_identifier");
|
cx.error("#[serde(other)] may only be used inside a field_identifier");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,9 +148,9 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
|
|||||||
/// Skip-(de)serializing attributes are not allowed on variants marked
|
/// Skip-(de)serializing attributes are not allowed on variants marked
|
||||||
/// (de)serialize_with.
|
/// (de)serialize_with.
|
||||||
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
||||||
let variants = match cont.body {
|
let variants = match cont.data {
|
||||||
Body::Enum(ref variants) => variants,
|
Data::Enum(ref variants) => variants,
|
||||||
Body::Struct(_, _) => {
|
Data::Struct(_, _) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -109,44 +158,121 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
|||||||
for variant in variants.iter() {
|
for variant in variants.iter() {
|
||||||
if variant.attrs.serialize_with().is_some() {
|
if variant.attrs.serialize_with().is_some() {
|
||||||
if variant.attrs.skip_serializing() {
|
if variant.attrs.skip_serializing() {
|
||||||
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
|
cx.error(format!(
|
||||||
#[serde(skip_serializing)]", variant.ident));
|
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||||
|
#[serde(skip_serializing)]",
|
||||||
|
variant.ident
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, field) in variant.fields.iter().enumerate() {
|
for (i, field) in variant.fields.iter().enumerate() {
|
||||||
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|
let ident = field
|
||||||
|ident| format!("`{}`", ident));
|
.ident
|
||||||
|
.as_ref()
|
||||||
|
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
|
||||||
|
|
||||||
if field.attrs.skip_serializing() {
|
if field.attrs.skip_serializing() {
|
||||||
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
|
cx.error(format!(
|
||||||
a field {} marked with #[serde(skip_serializing)]",
|
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||||
variant.ident, ident));
|
a field {} marked with #[serde(skip_serializing)]",
|
||||||
|
variant.ident, ident
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if field.attrs.skip_serializing_if().is_some() {
|
if field.attrs.skip_serializing_if().is_some() {
|
||||||
cx.error(format!("variant `{}` cannot have both #[serde(serialize_with)] and \
|
cx.error(format!(
|
||||||
a field {} marked with #[serde(skip_serializing_if)]",
|
"variant `{}` cannot have both #[serde(serialize_with)] and \
|
||||||
variant.ident, ident));
|
a field {} marked with #[serde(skip_serializing_if)]",
|
||||||
|
variant.ident, ident
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if variant.attrs.deserialize_with().is_some() {
|
if variant.attrs.deserialize_with().is_some() {
|
||||||
if variant.attrs.skip_deserializing() {
|
if variant.attrs.skip_deserializing() {
|
||||||
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] and \
|
cx.error(format!(
|
||||||
#[serde(skip_deserializing)]", variant.ident));
|
"variant `{}` cannot have both #[serde(deserialize_with)] and \
|
||||||
|
#[serde(skip_deserializing)]",
|
||||||
|
variant.ident
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, field) in variant.fields.iter().enumerate() {
|
for (i, field) in variant.fields.iter().enumerate() {
|
||||||
if field.attrs.skip_deserializing() {
|
if field.attrs.skip_deserializing() {
|
||||||
let ident = field.ident.as_ref().map_or_else(|| format!("{}", i),
|
let ident = field
|
||||||
|ident| format!("`{}`", ident));
|
.ident
|
||||||
|
.as_ref()
|
||||||
|
.map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));
|
||||||
|
|
||||||
cx.error(format!("variant `{}` cannot have both #[serde(deserialize_with)] \
|
cx.error(format!(
|
||||||
and a field {} marked with #[serde(skip_deserializing)]",
|
"variant `{}` cannot have both #[serde(deserialize_with)] \
|
||||||
variant.ident, ident));
|
and a field {} marked with #[serde(skip_deserializing)]",
|
||||||
|
variant.ident, ident
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Ctxt {
|
pub struct Ctxt {
|
||||||
@@ -16,7 +17,9 @@ pub struct Ctxt {
|
|||||||
|
|
||||||
impl Ctxt {
|
impl Ctxt {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Ctxt { errors: RefCell::new(Some(Vec::new())) }
|
Ctxt {
|
||||||
|
errors: RefCell::new(Some(Vec::new())),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error<T: Display>(&self, msg: T) {
|
pub fn error<T: Display>(&self, msg: T) {
|
||||||
@@ -46,7 +49,7 @@ impl Ctxt {
|
|||||||
|
|
||||||
impl Drop for Ctxt {
|
impl Drop for Ctxt {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.errors.borrow().is_some() {
|
if !thread::panicking() && self.errors.borrow().is_some() {
|
||||||
panic!("forgot to check for errors");
|
panic!("forgot to check for errors");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,16 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.17.0")]
|
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.23.1")]
|
||||||
|
#![cfg_attr(
|
||||||
|
feature = "cargo-clippy",
|
||||||
|
allow(cyclomatic_complexity, doc_markdown, match_same_arms, redundant_field_names)
|
||||||
|
)]
|
||||||
|
|
||||||
extern crate syn;
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate synom;
|
extern crate syn;
|
||||||
|
|
||||||
|
extern crate proc_macro2;
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_test"
|
name = "serde_test"
|
||||||
version = "1.0.21" # remember to update html_root_url
|
version = "1.0.43" # remember to update html_root_url
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||||
|
|||||||
@@ -184,11 +184,27 @@ where
|
|||||||
T: Deserialize<'de> + PartialEq + Debug,
|
T: Deserialize<'de> + PartialEq + Debug,
|
||||||
{
|
{
|
||||||
let mut de = Deserializer::new(tokens);
|
let mut de = Deserializer::new(tokens);
|
||||||
match T::deserialize(&mut de) {
|
let mut deserialized_val = match T::deserialize(&mut de) {
|
||||||
Ok(v) => assert_eq!(v, *value),
|
Ok(v) => {
|
||||||
|
assert_eq!(v, *value);
|
||||||
|
v
|
||||||
|
}
|
||||||
Err(e) => panic!("tokens failed to deserialize: {}", e),
|
Err(e) => panic!("tokens failed to deserialize: {}", e),
|
||||||
|
};
|
||||||
|
if de.remaining() > 0 {
|
||||||
|
panic!("{} remaining tokens", de.remaining());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do the same thing for deserialize_in_place. This isn't *great* because a
|
||||||
|
// no-op impl of deserialize_in_place can technically succeed here. Still,
|
||||||
|
// this should catch a lot of junk.
|
||||||
|
let mut de = Deserializer::new(tokens);
|
||||||
|
match T::deserialize_in_place(&mut de, &mut deserialized_val) {
|
||||||
|
Ok(()) => {
|
||||||
|
assert_eq!(deserialized_val, *value);
|
||||||
|
}
|
||||||
|
Err(e) => panic!("tokens failed to deserialize_in_place: {}", e),
|
||||||
|
}
|
||||||
if de.remaining() > 0 {
|
if de.remaining() > 0 {
|
||||||
panic!("{} remaining tokens", de.remaining());
|
panic!("{} remaining tokens", de.remaining());
|
||||||
}
|
}
|
||||||
|
|||||||
+605
-429
File diff suppressed because it is too large
Load Diff
+78
-64
@@ -6,9 +6,9 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
|
||||||
use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
|
use serde::de::{self, Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess,
|
||||||
SeqAccess, VariantAccess, Visitor};
|
SeqAccess, VariantAccess, Visitor};
|
||||||
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
|
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use token::Token;
|
use token::Token;
|
||||||
@@ -22,28 +22,28 @@ macro_rules! assert_next_token {
|
|||||||
($de:expr, $expected:expr) => {
|
($de:expr, $expected:expr) => {
|
||||||
match $de.next_token_opt() {
|
match $de.next_token_opt() {
|
||||||
Some(token) if token == $expected => {}
|
Some(token) if token == $expected => {}
|
||||||
Some(other) => {
|
Some(other) => panic!(
|
||||||
panic!("expected Token::{} but deserialization wants Token::{}",
|
"expected Token::{} but deserialization wants Token::{}",
|
||||||
other, $expected)
|
other, $expected
|
||||||
}
|
),
|
||||||
None => {
|
None => panic!(
|
||||||
panic!("end of tokens but deserialization wants Token::{}",
|
"end of tokens but deserialization wants Token::{}",
|
||||||
$expected)
|
$expected
|
||||||
}
|
),
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! unexpected {
|
macro_rules! unexpected {
|
||||||
($token:expr) => {
|
($token:expr) => {
|
||||||
panic!("deserialization did not expect this token: {}", $token)
|
panic!("deserialization did not expect this token: {}", $token)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! end_of_tokens {
|
macro_rules! end_of_tokens {
|
||||||
() => {
|
() => {
|
||||||
panic!("ran out of tokens to deserialize")
|
panic!("ran out of tokens to deserialize")
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de> Deserializer<'de> {
|
impl<'de> Deserializer<'de> {
|
||||||
@@ -95,15 +95,11 @@ impl<'de> Deserializer<'de> {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
let value = try!(
|
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
|
||||||
visitor.visit_seq(
|
de: self,
|
||||||
DeserializerSeqVisitor {
|
len: len,
|
||||||
de: self,
|
end: end,
|
||||||
len: len,
|
},));
|
||||||
end: end,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_next_token!(self, end);
|
assert_next_token!(self, end);
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
@@ -117,15 +113,11 @@ impl<'de> Deserializer<'de> {
|
|||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
let value = try!(
|
let value = try!(visitor.visit_map(DeserializerMapVisitor {
|
||||||
visitor.visit_map(
|
de: self,
|
||||||
DeserializerMapVisitor {
|
len: len,
|
||||||
de: self,
|
end: end,
|
||||||
len: len,
|
},));
|
||||||
end: end,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_next_token!(self, end);
|
assert_next_token!(self, end);
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
@@ -169,7 +161,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
|
Token::NewtypeStruct { .. } => visitor.visit_newtype_struct(self),
|
||||||
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
|
Token::Seq { len } => self.visit_seq(len, Token::SeqEnd, visitor),
|
||||||
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
|
Token::Tuple { len } => self.visit_seq(Some(len), Token::TupleEnd, visitor),
|
||||||
Token::TupleStruct { len, .. } => self.visit_seq(Some(len), Token::TupleStructEnd, visitor),
|
Token::TupleStruct { len, .. } => {
|
||||||
|
self.visit_seq(Some(len), Token::TupleStructEnd, visitor)
|
||||||
|
}
|
||||||
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
|
Token::Map { len } => self.visit_map(len, Token::MapEnd, visitor),
|
||||||
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
|
Token::Struct { len, .. } => self.visit_map(Some(len), Token::StructEnd, visitor),
|
||||||
Token::Enum { .. } => {
|
Token::Enum { .. } => {
|
||||||
@@ -195,17 +189,28 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
|
Token::UnitVariant { variant, .. } => visitor.visit_str(variant),
|
||||||
Token::NewtypeVariant { variant, .. } => {
|
Token::NewtypeVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
||||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Any),)
|
self,
|
||||||
}
|
Token::Str(variant),
|
||||||
Token::TupleVariant { variant, .. } => {
|
EnumFormat::Any,
|
||||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Seq),)
|
)),
|
||||||
}
|
Token::TupleVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
||||||
Token::StructVariant { variant, .. } => {
|
self,
|
||||||
visitor.visit_map(EnumMapVisitor::new(self, Token::Str(variant), EnumFormat::Map),)
|
Token::Str(variant),
|
||||||
}
|
EnumFormat::Seq,
|
||||||
Token::SeqEnd | Token::TupleEnd | Token::TupleStructEnd | Token::MapEnd |
|
)),
|
||||||
Token::StructEnd | Token::TupleVariantEnd | Token::StructVariantEnd => {
|
Token::StructVariant { variant, .. } => visitor.visit_map(EnumMapVisitor::new(
|
||||||
|
self,
|
||||||
|
Token::Str(variant),
|
||||||
|
EnumFormat::Map,
|
||||||
|
)),
|
||||||
|
Token::SeqEnd
|
||||||
|
| Token::TupleEnd
|
||||||
|
| Token::TupleStructEnd
|
||||||
|
| Token::MapEnd
|
||||||
|
| Token::StructEnd
|
||||||
|
| Token::TupleVariantEnd
|
||||||
|
| Token::StructVariantEnd => {
|
||||||
unexpected!(token);
|
unexpected!(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,8 +221,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.peek_token() {
|
match self.peek_token() {
|
||||||
Token::Unit |
|
Token::Unit | Token::None => {
|
||||||
Token::None => {
|
|
||||||
self.next_token();
|
self.next_token();
|
||||||
visitor.visit_none()
|
visitor.visit_none()
|
||||||
}
|
}
|
||||||
@@ -244,10 +248,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
|
|
||||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
||||||
}
|
}
|
||||||
Token::UnitVariant { name: n, .. } |
|
Token::UnitVariant { name: n, .. }
|
||||||
Token::NewtypeVariant { name: n, .. } |
|
| Token::NewtypeVariant { name: n, .. }
|
||||||
Token::TupleVariant { name: n, .. } |
|
| Token::TupleVariant { name: n, .. }
|
||||||
Token::StructVariant { name: n, .. } if name == n => {
|
| Token::StructVariant { name: n, .. } if name == n =>
|
||||||
|
{
|
||||||
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
visitor.visit_enum(DeserializerEnumVisitor { de: self })
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -269,7 +274,11 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Error>
|
fn deserialize_newtype_struct<V>(
|
||||||
|
self,
|
||||||
|
name: &'static str,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Error>
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
@@ -287,8 +296,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.peek_token() {
|
match self.peek_token() {
|
||||||
Token::Unit |
|
Token::Unit | Token::UnitStruct { .. } => {
|
||||||
Token::UnitStruct { .. } => {
|
|
||||||
self.next_token();
|
self.next_token();
|
||||||
visitor.visit_unit()
|
visitor.visit_unit()
|
||||||
}
|
}
|
||||||
@@ -352,8 +360,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
match self.peek_token() {
|
match self.peek_token() {
|
||||||
Token::Struct { .. } => {
|
Token::Struct { len: n, .. } => {
|
||||||
assert_next_token!(self, Token::Struct { name: name, len: fields.len() });
|
assert_next_token!(self, Token::Struct { name: name, len: n });
|
||||||
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
|
self.visit_map(Some(fields.len()), Token::StructEnd, visitor)
|
||||||
}
|
}
|
||||||
Token::Map { .. } => {
|
Token::Map { .. } => {
|
||||||
@@ -448,10 +456,10 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
|||||||
V: DeserializeSeed<'de>,
|
V: DeserializeSeed<'de>,
|
||||||
{
|
{
|
||||||
match self.de.peek_token() {
|
match self.de.peek_token() {
|
||||||
Token::UnitVariant { variant: v, .. } |
|
Token::UnitVariant { variant: v, .. }
|
||||||
Token::NewtypeVariant { variant: v, .. } |
|
| Token::NewtypeVariant { variant: v, .. }
|
||||||
Token::TupleVariant { variant: v, .. } |
|
| Token::TupleVariant { variant: v, .. }
|
||||||
Token::StructVariant { variant: v, .. } => {
|
| Token::StructVariant { variant: v, .. } => {
|
||||||
let de = v.into_deserializer();
|
let de = v.into_deserializer();
|
||||||
let value = try!(seed.deserialize(de));
|
let value = try!(seed.deserialize(de));
|
||||||
Ok((value, self))
|
Ok((value, self))
|
||||||
@@ -505,7 +513,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
|||||||
unexpected!(token);
|
unexpected!(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token::Seq { len: Some(enum_len) } => {
|
Token::Seq {
|
||||||
|
len: Some(enum_len),
|
||||||
|
} => {
|
||||||
let token = self.de.next_token();
|
let token = self.de.next_token();
|
||||||
|
|
||||||
if len == enum_len {
|
if len == enum_len {
|
||||||
@@ -518,7 +528,11 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Error>
|
fn struct_variant<V>(
|
||||||
|
self,
|
||||||
|
fields: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Error>
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
@@ -533,7 +547,9 @@ impl<'de, 'a> VariantAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
|
|||||||
unexpected!(token);
|
unexpected!(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token::Map { len: Some(enum_len) } => {
|
Token::Map {
|
||||||
|
len: Some(enum_len),
|
||||||
|
} => {
|
||||||
let token = self.de.next_token();
|
let token = self.de.next_token();
|
||||||
|
|
||||||
if fields.len() == enum_len {
|
if fields.len() == enum_len {
|
||||||
@@ -581,10 +597,8 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
|
|||||||
{
|
{
|
||||||
match self.variant.take() {
|
match self.variant.take() {
|
||||||
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
Some(Token::Str(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
||||||
Some(Token::Bytes(variant)) => {
|
Some(Token::Bytes(variant)) => seed.deserialize(BytesDeserializer { value: variant })
|
||||||
seed.deserialize(BytesDeserializer { value: variant })
|
.map(Some),
|
||||||
.map(Some)
|
|
||||||
}
|
|
||||||
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
Some(Token::U32(variant)) => seed.deserialize(variant.into_deserializer()).map(Some),
|
||||||
Some(other) => unexpected!(other),
|
Some(other) => unexpected!(other),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
use serde::{ser, de};
|
use serde::{de, ser};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
@@ -18,13 +18,17 @@ pub struct Error {
|
|||||||
|
|
||||||
impl ser::Error for Error {
|
impl ser::Error for Error {
|
||||||
fn custom<T: Display>(msg: T) -> Self {
|
fn custom<T: Display>(msg: T) -> Self {
|
||||||
Error { msg: msg.to_string() }
|
Error {
|
||||||
|
msg: msg.to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl de::Error for Error {
|
impl de::Error for Error {
|
||||||
fn custom<T: Display>(msg: T) -> Self {
|
fn custom<T: Display>(msg: T) -> Self {
|
||||||
Error { msg: msg.to_string() }
|
Error {
|
||||||
|
msg: msg.to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-12
@@ -53,7 +53,7 @@
|
|||||||
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
|
//! # use serde::ser::{Serialize, Serializer, SerializeMap};
|
||||||
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
|
//! # use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};
|
||||||
//! #
|
//! #
|
||||||
//! # // Dumb immitation of LinkedHashMap.
|
//! # // Dumb imitation of LinkedHashMap.
|
||||||
//! # #[derive(PartialEq, Debug)]
|
//! # #[derive(PartialEq, Debug)]
|
||||||
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
|
//! # struct LinkedHashMap<K, V>(Vec<(K, V)>);
|
||||||
//! #
|
//! #
|
||||||
@@ -155,33 +155,33 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.21")]
|
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.43")]
|
||||||
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||||
// Whitelisted clippy lints
|
// Whitelisted clippy lints
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
|
||||||
// Whitelisted clippy_pedantic lints
|
// Whitelisted clippy_pedantic lints
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(
|
#![cfg_attr(
|
||||||
missing_docs_in_private_items,
|
feature = "cargo-clippy",
|
||||||
stutter,
|
allow(
|
||||||
use_debug,
|
empty_line_after_outer_attr, missing_docs_in_private_items, redundant_field_names, stutter,
|
||||||
use_self,
|
use_debug, use_self
|
||||||
))]
|
)
|
||||||
|
)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
mod ser;
|
|
||||||
mod de;
|
mod de;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod ser;
|
||||||
|
|
||||||
|
mod assert;
|
||||||
mod configure;
|
mod configure;
|
||||||
mod token;
|
mod token;
|
||||||
mod assert;
|
|
||||||
|
|
||||||
pub use token::Token;
|
|
||||||
pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
|
pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens,
|
||||||
assert_ser_tokens_error, assert_tokens};
|
assert_ser_tokens_error, assert_tokens};
|
||||||
|
pub use token::Token;
|
||||||
|
|
||||||
pub use configure::{Compact, Configure, Readable};
|
pub use configure::{Compact, Configure, Readable};
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ macro_rules! assert_next_token {
|
|||||||
($ser:expr, $expected:ident($v:expr)) => {
|
($ser:expr, $expected:ident($v:expr)) => {
|
||||||
assert_next_token!(
|
assert_next_token!(
|
||||||
$ser,
|
$ser,
|
||||||
format_args!("{}({:?})", stringify!($expected), $v),
|
format_args!(concat!(stringify!($expected), "({:?})"), $v),
|
||||||
Token::$expected(v),
|
Token::$expected(v),
|
||||||
v == $v
|
v == $v
|
||||||
);
|
);
|
||||||
@@ -56,13 +56,13 @@ macro_rules! assert_next_token {
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
$(
|
$(
|
||||||
write!(&mut buffer, "{}: {:?}, ", stringify!($k), $k).unwrap();
|
write!(&mut buffer, concat!(stringify!($k), ": {:?}, "), $k).unwrap();
|
||||||
)*
|
)*
|
||||||
buffer
|
buffer
|
||||||
};
|
};
|
||||||
assert_next_token!(
|
assert_next_token!(
|
||||||
$ser,
|
$ser,
|
||||||
format_args!("{} {{ {}}}", stringify!($expected), field_format()),
|
format_args!(concat!(stringify!($expected), " {{ {}}}"), field_format()),
|
||||||
Token::$expected { $($k),* },
|
Token::$expected { $($k),* },
|
||||||
($($k,)*) == compare
|
($($k,)*) == compare
|
||||||
);
|
);
|
||||||
|
|||||||
+18
-12
@@ -232,7 +232,10 @@ pub enum Token {
|
|||||||
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]);
|
/// assert_tokens(&a, &[Token::UnitVariant { name: "E", variant: "A" }]);
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
UnitVariant { name: &'static str, variant: &'static str },
|
UnitVariant {
|
||||||
|
name: &'static str,
|
||||||
|
variant: &'static str,
|
||||||
|
},
|
||||||
|
|
||||||
/// The header to a serialized newtype struct of the given name.
|
/// The header to a serialized newtype struct of the given name.
|
||||||
///
|
///
|
||||||
@@ -286,7 +289,10 @@ pub enum Token {
|
|||||||
/// ]);
|
/// ]);
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
NewtypeVariant { name: &'static str, variant: &'static str },
|
NewtypeVariant {
|
||||||
|
name: &'static str,
|
||||||
|
variant: &'static str,
|
||||||
|
},
|
||||||
|
|
||||||
/// The header to a sequence.
|
/// The header to a sequence.
|
||||||
///
|
///
|
||||||
@@ -391,7 +397,11 @@ pub enum Token {
|
|||||||
/// ]);
|
/// ]);
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
TupleVariant { name: &'static str, variant: &'static str, len: usize },
|
TupleVariant {
|
||||||
|
name: &'static str,
|
||||||
|
variant: &'static str,
|
||||||
|
len: usize,
|
||||||
|
},
|
||||||
|
|
||||||
/// An indicator of the end of a tuple variant.
|
/// An indicator of the end of a tuple variant.
|
||||||
TupleVariantEnd,
|
TupleVariantEnd,
|
||||||
@@ -425,10 +435,6 @@ pub enum Token {
|
|||||||
|
|
||||||
/// The header of a struct.
|
/// The header of a struct.
|
||||||
///
|
///
|
||||||
/// When testing deserialization, the `len` field must match the number of
|
|
||||||
/// fields that the struct expects to deserialize. This may be different
|
|
||||||
/// from the number of fields contained in the input tokens.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the struct, followed by `StructEnd`.
|
/// After this header are the fields of the struct, followed by `StructEnd`.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
@@ -465,10 +471,6 @@ pub enum Token {
|
|||||||
|
|
||||||
/// The header of a struct variant of an enum.
|
/// The header of a struct variant of an enum.
|
||||||
///
|
///
|
||||||
/// When testing deserialization, the `len` field must match the number of
|
|
||||||
/// fields that the struct variant expects to deserialize. This may be
|
|
||||||
/// different from the number of fields contained in the input tokens.
|
|
||||||
///
|
|
||||||
/// After this header are the fields of the struct variant, followed by
|
/// After this header are the fields of the struct variant, followed by
|
||||||
/// `StructVariantEnd`.
|
/// `StructVariantEnd`.
|
||||||
///
|
///
|
||||||
@@ -496,7 +498,11 @@ pub enum Token {
|
|||||||
/// ]);
|
/// ]);
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
StructVariant { name: &'static str, variant: &'static str, len: usize },
|
StructVariant {
|
||||||
|
name: &'static str,
|
||||||
|
variant: &'static str,
|
||||||
|
len: usize,
|
||||||
|
},
|
||||||
|
|
||||||
/// An indicator of the end of a struct variant.
|
/// An indicator of the end of a struct variant.
|
||||||
StructVariantEnd,
|
StructVariantEnd,
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ unstable = ["serde/unstable", "compiletest_rs"]
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
|
proc-macro2 = "0.3"
|
||||||
rustc-serialize = "0.3.16"
|
rustc-serialize = "0.3.16"
|
||||||
serde = { path = "../serde", features = ["rc"] }
|
serde = { path = "../serde", features = ["rc"] }
|
||||||
serde_derive = { path = "../serde_derive" }
|
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
|
||||||
serde_test = { path = "../serde_test" }
|
serde_test = { path = "../serde_test" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
compiletest_rs = { version = "0.2", optional = true }
|
compiletest_rs = { version = "0.3", optional = true }
|
||||||
|
|||||||
@@ -6,11 +6,10 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#![feature(lang_items, start, compiler_builtins_lib)]
|
#![feature(lang_items, start)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate compiler_builtins;
|
|
||||||
|
|
||||||
#[start]
|
#[start]
|
||||||
fn start(_argc: isize, _argv: *const *const u8) -> isize {
|
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"]
|
#[lang = "eh_personality"]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn rust_eh_personality() {}
|
pub extern "C" fn rust_eh_personality() {}
|
||||||
|
|
||||||
#[lang = "eh_unwind_resume"]
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern fn rust_eh_unwind_resume() {}
|
|
||||||
|
|
||||||
#[lang = "panic_fmt"]
|
#[lang = "panic_fmt"]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
|
pub extern "C" fn rust_begin_panic(
|
||||||
_file: &'static str,
|
_msg: core::fmt::Arguments,
|
||||||
_line: u32) -> ! {
|
_file: &'static str,
|
||||||
|
_line: u32,
|
||||||
|
) -> ! {
|
||||||
unsafe {
|
unsafe {
|
||||||
libc::abort()
|
libc::abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +47,9 @@ struct Newtype(u8);
|
|||||||
struct Tuple(u8, u8);
|
struct Tuple(u8, u8);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Struct { f: u8 }
|
struct Struct {
|
||||||
|
f: u8,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum Enum {
|
enum Enum {
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
use serde::de::{Deserializer, Visitor, SeqAccess, Error};
|
||||||
|
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,21 @@
|
|||||||
|
// 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 within enums
|
||||||
|
enum Foo {
|
||||||
|
A {
|
||||||
|
#[serde(flatten)]
|
||||||
|
fields: 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() {}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@ extern crate serde;
|
|||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
extern crate serde_test;
|
extern crate serde_test;
|
||||||
use serde_test::{Token, assert_de_tokens, assert_de_tokens_error};
|
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
@@ -87,18 +87,18 @@ fn test_struct() {
|
|||||||
|
|
||||||
assert_de_tokens(
|
assert_de_tokens(
|
||||||
&Borrowing {
|
&Borrowing {
|
||||||
bs: "str",
|
bs: "str",
|
||||||
bb: b"bytes",
|
bb: b"bytes",
|
||||||
},
|
},
|
||||||
&[
|
&[
|
||||||
Token::Struct { name: "Borrowing", len: 2 },
|
Token::Struct {
|
||||||
|
name: "Borrowing",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
Token::BorrowedStr("bs"),
|
Token::BorrowedStr("bs"),
|
||||||
Token::BorrowedStr("str"),
|
Token::BorrowedStr("str"),
|
||||||
|
|
||||||
Token::BorrowedStr("bb"),
|
Token::BorrowedStr("bb"),
|
||||||
Token::BorrowedBytes(b"bytes"),
|
Token::BorrowedBytes(b"bytes"),
|
||||||
|
|
||||||
Token::StructEnd,
|
Token::StructEnd,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -115,14 +115,14 @@ fn test_cow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tokens = &[
|
let tokens = &[
|
||||||
Token::Struct { name: "Cows", len: 2 },
|
Token::Struct {
|
||||||
|
name: "Cows",
|
||||||
|
len: 2,
|
||||||
|
},
|
||||||
Token::Str("copied"),
|
Token::Str("copied"),
|
||||||
Token::BorrowedStr("copied"),
|
Token::BorrowedStr("copied"),
|
||||||
|
|
||||||
Token::Str("borrowed"),
|
Token::Str("borrowed"),
|
||||||
Token::BorrowedStr("borrowed"),
|
Token::BorrowedStr("borrowed"),
|
||||||
|
|
||||||
Token::StructEnd,
|
Token::StructEnd,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(decimal_literal_representation))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
@@ -49,14 +51,16 @@ struct TupleStruct(i32, i32, i32);
|
|||||||
struct Struct {
|
struct Struct {
|
||||||
a: i32,
|
a: i32,
|
||||||
b: i32,
|
b: i32,
|
||||||
#[serde(skip_deserializing)] c: i32,
|
#[serde(skip_deserializing)]
|
||||||
|
c: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct StructDenyUnknown {
|
struct StructDenyUnknown {
|
||||||
a: i32,
|
a: i32,
|
||||||
#[serde(skip_deserializing)] b: i32,
|
#[serde(skip_deserializing)]
|
||||||
|
b: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
@@ -77,13 +81,35 @@ impl Default for StructDefault<String> {
|
|||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
struct StructSkipAll {
|
struct StructSkipAll {
|
||||||
#[serde(skip_deserializing)] a: i32,
|
#[serde(skip_deserializing)]
|
||||||
|
a: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct StructSkipDefault {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
a: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct StructSkipDefaultGeneric<T> {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
t: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StructSkipDefault {
|
||||||
|
fn default() -> Self {
|
||||||
|
StructSkipDefault { a: 16 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct StructSkipAllDenyUnknown {
|
struct StructSkipAllDenyUnknown {
|
||||||
#[serde(skip_deserializing)] a: i32,
|
#[serde(skip_deserializing)]
|
||||||
|
a: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
@@ -94,7 +120,11 @@ enum Enum {
|
|||||||
Unit,
|
Unit,
|
||||||
Simple(i32),
|
Simple(i32),
|
||||||
Seq(i32, i32, i32),
|
Seq(i32, i32, i32),
|
||||||
Map { a: i32, b: i32, c: i32 },
|
Map {
|
||||||
|
a: i32,
|
||||||
|
b: i32,
|
||||||
|
c: i32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Deserialize)]
|
#[derive(PartialEq, Debug, Deserialize)]
|
||||||
@@ -600,6 +630,12 @@ declare_tests! {
|
|||||||
Token::StructEnd,
|
Token::StructEnd,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
test_struct_skip_default {
|
||||||
|
StructSkipDefault { a: 16 } => &[
|
||||||
|
Token::Struct { name: "StructSkipDefault", len: 0 },
|
||||||
|
Token::StructEnd,
|
||||||
|
],
|
||||||
|
}
|
||||||
test_struct_skip_all_deny_unknown {
|
test_struct_skip_all_deny_unknown {
|
||||||
StructSkipAllDenyUnknown { a: 0 } => &[
|
StructSkipAllDenyUnknown { a: 0 } => &[
|
||||||
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
|
Token::Struct { name: "StructSkipAllDenyUnknown", len: 0 },
|
||||||
|
|||||||
+116
-75
@@ -11,7 +11,6 @@
|
|||||||
// types involved.
|
// types involved.
|
||||||
|
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
|
||||||
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
|
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -23,6 +22,7 @@ use self::serde::de::{DeserializeOwned, Deserializer};
|
|||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::option::Option as StdOption;
|
||||||
use std::result::Result as StdResult;
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
// Try to trip up the generated code if it fails to use fully qualified paths.
|
// Try to trip up the generated code if it fails to use fully qualified paths.
|
||||||
@@ -32,6 +32,12 @@ struct Result;
|
|||||||
struct Ok;
|
struct Ok;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct Err;
|
struct Err;
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct Option;
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct Some;
|
||||||
|
#[allow(dead_code)]
|
||||||
|
struct None;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -40,7 +46,7 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct With<T> {
|
struct With<T> {
|
||||||
t: T,
|
t: T,
|
||||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||||
x: X,
|
x: X,
|
||||||
}
|
}
|
||||||
assert::<With<i32>>();
|
assert::<With<i32>>();
|
||||||
@@ -48,7 +54,7 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct WithTogether<T> {
|
struct WithTogether<T> {
|
||||||
t: T,
|
t: T,
|
||||||
#[serde(with="both_x")]
|
#[serde(with = "both_x")]
|
||||||
x: X,
|
x: X,
|
||||||
}
|
}
|
||||||
assert::<WithTogether<i32>>();
|
assert::<WithTogether<i32>>();
|
||||||
@@ -56,8 +62,8 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct WithRef<'a, T: 'a> {
|
struct WithRef<'a, T: 'a> {
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
t: Option<&'a T>,
|
t: StdOption<&'a T>,
|
||||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||||
x: X,
|
x: X,
|
||||||
}
|
}
|
||||||
assert::<WithRef<i32>>();
|
assert::<WithRef<i32>>();
|
||||||
@@ -77,9 +83,9 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct NoBounds<T> {
|
struct NoBounds<T> {
|
||||||
t: T,
|
t: T,
|
||||||
option: Option<T>,
|
option: StdOption<T>,
|
||||||
boxed: Box<T>,
|
boxed: Box<T>,
|
||||||
option_boxed: Option<Box<T>>,
|
option_boxed: StdOption<Box<T>>,
|
||||||
}
|
}
|
||||||
assert::<NoBounds<i32>>();
|
assert::<NoBounds<i32>>();
|
||||||
|
|
||||||
@@ -87,17 +93,17 @@ fn test_gen() {
|
|||||||
enum EnumWith<T> {
|
enum EnumWith<T> {
|
||||||
Unit,
|
Unit,
|
||||||
Newtype(
|
Newtype(
|
||||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||||
X
|
X,
|
||||||
),
|
),
|
||||||
Tuple(
|
Tuple(
|
||||||
T,
|
T,
|
||||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||||
X
|
X,
|
||||||
),
|
),
|
||||||
Struct {
|
Struct {
|
||||||
t: T,
|
t: T,
|
||||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||||
x: X,
|
x: X,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -117,16 +123,16 @@ fn test_gen() {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Newtype(
|
struct Newtype(
|
||||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||||
X
|
X,
|
||||||
);
|
);
|
||||||
assert::<Newtype>();
|
assert::<Newtype>();
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Tuple<T>(
|
struct Tuple<T>(
|
||||||
T,
|
T,
|
||||||
#[serde(serialize_with="ser_x", deserialize_with="de_x")]
|
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||||
X
|
X,
|
||||||
);
|
);
|
||||||
assert::<Tuple<i32>>();
|
assert::<Tuple<i32>>();
|
||||||
|
|
||||||
@@ -136,7 +142,9 @@ fn test_gen() {
|
|||||||
left: Box<TreeNode<D>>,
|
left: Box<TreeNode<D>>,
|
||||||
right: Box<TreeNode<D>>,
|
right: Box<TreeNode<D>>,
|
||||||
},
|
},
|
||||||
Leaf { data: D },
|
Leaf {
|
||||||
|
data: D,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
assert::<TreeNode<i32>>();
|
assert::<TreeNode<i32>>();
|
||||||
|
|
||||||
@@ -175,35 +183,34 @@ fn test_gen() {
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct OptionStatic<'a> {
|
struct OptionStatic<'a> {
|
||||||
a: Option<&'a str>,
|
a: StdOption<&'a str>,
|
||||||
b: Option<&'static str>,
|
b: StdOption<&'static str>,
|
||||||
}
|
}
|
||||||
assert_ser::<OptionStatic>();
|
assert_ser::<OptionStatic>();
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(bound="D: SerializeWith + DeserializeWith")]
|
#[serde(bound = "D: SerializeWith + DeserializeWith")]
|
||||||
struct WithTraits1<D, E> {
|
struct WithTraits1<D, E> {
|
||||||
#[serde(serialize_with="SerializeWith::serialize_with",
|
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||||
deserialize_with="DeserializeWith::deserialize_with")]
|
deserialize_with = "DeserializeWith::deserialize_with")]
|
||||||
d: D,
|
d: D,
|
||||||
#[serde(serialize_with="SerializeWith::serialize_with",
|
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||||
deserialize_with="DeserializeWith::deserialize_with",
|
deserialize_with = "DeserializeWith::deserialize_with",
|
||||||
bound="E: SerializeWith + DeserializeWith")]
|
bound = "E: SerializeWith + DeserializeWith")]
|
||||||
e: E,
|
e: E,
|
||||||
}
|
}
|
||||||
assert::<WithTraits1<X, X>>();
|
assert::<WithTraits1<X, X>>();
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(bound(serialize="D: SerializeWith",
|
#[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))]
|
||||||
deserialize="D: DeserializeWith"))]
|
|
||||||
struct WithTraits2<D, E> {
|
struct WithTraits2<D, E> {
|
||||||
#[serde(serialize_with="SerializeWith::serialize_with",
|
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||||
deserialize_with="DeserializeWith::deserialize_with")]
|
deserialize_with = "DeserializeWith::deserialize_with")]
|
||||||
d: D,
|
d: D,
|
||||||
#[serde(serialize_with="SerializeWith::serialize_with",
|
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||||
bound(serialize="E: SerializeWith"))]
|
bound(serialize = "E: SerializeWith"))]
|
||||||
#[serde(deserialize_with="DeserializeWith::deserialize_with",
|
#[serde(deserialize_with = "DeserializeWith::deserialize_with",
|
||||||
bound(deserialize="E: DeserializeWith"))]
|
bound(deserialize = "E: DeserializeWith"))]
|
||||||
e: E,
|
e: E,
|
||||||
}
|
}
|
||||||
assert::<WithTraits2<X, X>>();
|
assert::<WithTraits2<X, X>>();
|
||||||
@@ -265,14 +272,14 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct TupleSkipAll(
|
struct TupleSkipAll(
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
u8
|
u8,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct TupleSkipAllDenyUnknown(
|
struct TupleSkipAllDenyUnknown(
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
u8
|
u8,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@@ -300,7 +307,7 @@ fn test_gen() {
|
|||||||
},
|
},
|
||||||
TupleSkip(
|
TupleSkip(
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
u8
|
u8,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +323,7 @@ fn test_gen() {
|
|||||||
},
|
},
|
||||||
TupleSkip(
|
TupleSkip(
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
u8
|
u8,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,10 +386,11 @@ fn test_gen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum ExternallyTaggedVariantWith {
|
#[serde(remote = "Self")]
|
||||||
#[allow(dead_code)]
|
struct RemoteSelf;
|
||||||
Normal { f1: String },
|
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
enum ExternallyTaggedVariantWith {
|
||||||
#[serde(serialize_with = "ser_x")]
|
#[serde(serialize_with = "ser_x")]
|
||||||
#[serde(deserialize_with = "de_x")]
|
#[serde(deserialize_with = "de_x")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -393,13 +401,15 @@ fn test_gen() {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Tuple(String, u8),
|
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(serialize_with = "serialize_some_other_variant")]
|
||||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Struct {
|
Struct { f1: String, f2: u8 },
|
||||||
f1: String,
|
|
||||||
f2: u8,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||||
@@ -411,21 +421,20 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(tag = "t")]
|
#[serde(tag = "t")]
|
||||||
enum InternallyTaggedVariantWith {
|
enum InternallyTaggedVariantWith {
|
||||||
#[allow(dead_code)]
|
|
||||||
Normal { f1: String },
|
|
||||||
|
|
||||||
#[serde(serialize_with = "ser_x")]
|
#[serde(serialize_with = "ser_x")]
|
||||||
#[serde(deserialize_with = "de_x")]
|
#[serde(deserialize_with = "de_x")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Newtype(X),
|
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(serialize_with = "serialize_some_other_variant")]
|
||||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Struct {
|
Struct { f1: String, f2: u8 },
|
||||||
f1: String,
|
|
||||||
f2: u8,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||||
@@ -437,9 +446,6 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(tag = "t", content = "c")]
|
#[serde(tag = "t", content = "c")]
|
||||||
enum AdjacentlyTaggedVariantWith {
|
enum AdjacentlyTaggedVariantWith {
|
||||||
#[allow(dead_code)]
|
|
||||||
Normal { f1: String },
|
|
||||||
|
|
||||||
#[serde(serialize_with = "ser_x")]
|
#[serde(serialize_with = "ser_x")]
|
||||||
#[serde(deserialize_with = "de_x")]
|
#[serde(deserialize_with = "de_x")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -450,13 +456,15 @@ fn test_gen() {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Tuple(String, u8),
|
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(serialize_with = "serialize_some_other_variant")]
|
||||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Struct {
|
Struct { f1: String, f2: u8 },
|
||||||
f1: String,
|
|
||||||
f2: u8,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||||
@@ -468,9 +476,6 @@ fn test_gen() {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
enum UntaggedVariantWith {
|
enum UntaggedVariantWith {
|
||||||
#[allow(dead_code)]
|
|
||||||
Normal { f1: String },
|
|
||||||
|
|
||||||
#[serde(serialize_with = "ser_x")]
|
#[serde(serialize_with = "ser_x")]
|
||||||
#[serde(deserialize_with = "de_x")]
|
#[serde(deserialize_with = "de_x")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -481,13 +486,15 @@ fn test_gen() {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Tuple(String, u8),
|
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(serialize_with = "serialize_some_other_variant")]
|
||||||
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
#[serde(deserialize_with = "deserialize_some_other_variant")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Struct {
|
Struct { f1: String, f2: u8 },
|
||||||
f1: String,
|
|
||||||
f2: u8,
|
|
||||||
},
|
|
||||||
|
|
||||||
#[serde(serialize_with = "serialize_some_unit_variant")]
|
#[serde(serialize_with = "serialize_some_unit_variant")]
|
||||||
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
#[serde(deserialize_with = "deserialize_some_unit_variant")]
|
||||||
@@ -510,10 +517,7 @@ fn test_gen() {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum StaticStrEnum<'a> {
|
enum StaticStrEnum<'a> {
|
||||||
Struct {
|
Struct { a: &'a str, b: &'static str },
|
||||||
a: &'a str,
|
|
||||||
b: &'static str,
|
|
||||||
},
|
|
||||||
Tuple(&'a str, &'static str),
|
Tuple(&'a str, &'static str),
|
||||||
Newtype(&'static str),
|
Newtype(&'static str),
|
||||||
}
|
}
|
||||||
@@ -536,6 +540,37 @@ fn test_gen() {
|
|||||||
marker: PhantomData<T>,
|
marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
assert::<TypeMacro<X>>();
|
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>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -563,7 +598,7 @@ pub fn de_x<'de, D: Deserializer<'de>>(_: D) -> StdResult<X, D::Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod both_x {
|
mod both_x {
|
||||||
pub use super::{ser_x as serialize, de_x as deserialize};
|
pub use super::{de_x as deserialize, ser_x as serialize};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SerializeWith for X {
|
impl SerializeWith for X {
|
||||||
@@ -579,27 +614,33 @@ impl DeserializeWith for X {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize_some_unit_variant<S>(_: S) -> StdResult<S::Ok, S::Error>
|
pub fn serialize_some_unit_variant<S>(_: S) -> StdResult<S::Ok, S::Error>
|
||||||
where S: Serializer,
|
where
|
||||||
|
S: Serializer,
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error>
|
pub fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error>
|
||||||
where D: Deserializer<'de>,
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize_some_other_variant<S>(_: &str, _: &u8, _: S) -> StdResult<S::Ok, S::Error>
|
pub fn serialize_some_other_variant<S>(_: &str, _: &u8, _: S) -> StdResult<S::Ok, S::Error>
|
||||||
where S: Serializer,
|
where
|
||||||
|
S: Serializer,
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error>
|
pub fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error>
|
||||||
where D: Deserializer<'de>,
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_zero(n: &u8) -> bool { *n == 0 }
|
pub fn is_zero(n: &u8) -> bool {
|
||||||
|
*n == 0
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ fn test_unit_fallthrough() {
|
|||||||
enum F {
|
enum F {
|
||||||
Aaa,
|
Aaa,
|
||||||
Bbb,
|
Bbb,
|
||||||
#[serde(other)] Other,
|
#[serde(other)]
|
||||||
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_de_tokens(&F::Other, &[Token::Str("x")]);
|
assert_de_tokens(&F::Other, &[Token::Str("x")]);
|
||||||
|
|||||||
+648
-223
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,8 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
||||||
@@ -85,23 +87,32 @@ mod remote {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Test {
|
struct Test {
|
||||||
#[serde(with = "UnitDef")] unit: remote::Unit,
|
#[serde(with = "UnitDef")]
|
||||||
|
unit: remote::Unit,
|
||||||
|
|
||||||
#[serde(with = "PrimitivePrivDef")] primitive_priv: remote::PrimitivePriv,
|
#[serde(with = "PrimitivePrivDef")]
|
||||||
|
primitive_priv: remote::PrimitivePriv,
|
||||||
|
|
||||||
#[serde(with = "PrimitivePubDef")] primitive_pub: remote::PrimitivePub,
|
#[serde(with = "PrimitivePubDef")]
|
||||||
|
primitive_pub: remote::PrimitivePub,
|
||||||
|
|
||||||
#[serde(with = "NewtypePrivDef")] newtype_priv: remote::NewtypePriv,
|
#[serde(with = "NewtypePrivDef")]
|
||||||
|
newtype_priv: remote::NewtypePriv,
|
||||||
|
|
||||||
#[serde(with = "NewtypePubDef")] newtype_pub: remote::NewtypePub,
|
#[serde(with = "NewtypePubDef")]
|
||||||
|
newtype_pub: remote::NewtypePub,
|
||||||
|
|
||||||
#[serde(with = "TuplePrivDef")] tuple_priv: remote::TuplePriv,
|
#[serde(with = "TuplePrivDef")]
|
||||||
|
tuple_priv: remote::TuplePriv,
|
||||||
|
|
||||||
#[serde(with = "TuplePubDef")] tuple_pub: remote::TuplePub,
|
#[serde(with = "TuplePubDef")]
|
||||||
|
tuple_pub: remote::TuplePub,
|
||||||
|
|
||||||
#[serde(with = "StructPrivDef")] struct_priv: remote::StructPriv,
|
#[serde(with = "StructPrivDef")]
|
||||||
|
struct_priv: remote::StructPriv,
|
||||||
|
|
||||||
#[serde(with = "StructPubDef")] struct_pub: remote::StructPub,
|
#[serde(with = "StructPubDef")]
|
||||||
|
struct_pub: remote::StructPub,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@@ -110,7 +121,10 @@ struct UnitDef;
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::PrimitivePriv")]
|
#[serde(remote = "remote::PrimitivePriv")]
|
||||||
struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8);
|
struct PrimitivePrivDef(
|
||||||
|
#[serde(getter = "remote::PrimitivePriv::get")]
|
||||||
|
u8,
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::PrimitivePub")]
|
#[serde(remote = "remote::PrimitivePub")]
|
||||||
@@ -119,28 +133,39 @@ struct PrimitivePubDef(u8);
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::NewtypePriv")]
|
#[serde(remote = "remote::NewtypePriv")]
|
||||||
struct NewtypePrivDef(
|
struct NewtypePrivDef(
|
||||||
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit,
|
#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")]
|
||||||
|
remote::Unit,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::NewtypePub")]
|
#[serde(remote = "remote::NewtypePub")]
|
||||||
struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit);
|
struct NewtypePubDef(
|
||||||
|
#[serde(with = "UnitDef")]
|
||||||
|
remote::Unit,
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::TuplePriv")]
|
#[serde(remote = "remote::TuplePriv")]
|
||||||
struct TuplePrivDef(
|
struct TuplePrivDef(
|
||||||
#[serde(getter = "remote::TuplePriv::first")] u8,
|
#[serde(getter = "remote::TuplePriv::first")]
|
||||||
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit,
|
u8,
|
||||||
|
#[serde(getter = "remote::TuplePriv::second", with = "UnitDef")]
|
||||||
|
remote::Unit,
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::TuplePub")]
|
#[serde(remote = "remote::TuplePub")]
|
||||||
struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit);
|
struct TuplePubDef(
|
||||||
|
u8,
|
||||||
|
#[serde(with = "UnitDef")]
|
||||||
|
remote::Unit,
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::StructPriv")]
|
#[serde(remote = "remote::StructPriv")]
|
||||||
struct StructPrivDef {
|
struct StructPrivDef {
|
||||||
#[serde(getter = "remote::StructPriv::a")] a: u8,
|
#[serde(getter = "remote::StructPriv::a")]
|
||||||
|
a: u8,
|
||||||
|
|
||||||
#[serde(getter = "remote::StructPriv::b")]
|
#[serde(getter = "remote::StructPriv::b")]
|
||||||
#[serde(with = "UnitDef")]
|
#[serde(with = "UnitDef")]
|
||||||
@@ -150,7 +175,8 @@ struct StructPrivDef {
|
|||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "remote::StructPub")]
|
#[serde(remote = "remote::StructPub")]
|
||||||
struct StructPubDef {
|
struct StructPubDef {
|
||||||
#[allow(dead_code)] a: u8,
|
#[allow(dead_code)]
|
||||||
|
a: u8,
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[serde(with = "UnitDef")]
|
#[serde(with = "UnitDef")]
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ fn ip_addr_roundtrip() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn socked_addr_roundtrip() {
|
fn socket_addr_roundtrip() {
|
||||||
assert_tokens(
|
assert_tokens(
|
||||||
&net::SocketAddr::from((*b"1234567890123456", 1234)).compact(),
|
&net::SocketAddr::from((*b"1234567890123456", 1234)).compact(),
|
||||||
&seq![
|
&seq![
|
||||||
|
|||||||
@@ -50,11 +50,21 @@ enum Enum {
|
|||||||
Unit,
|
Unit,
|
||||||
One(i32),
|
One(i32),
|
||||||
Seq(i32, i32),
|
Seq(i32, i32),
|
||||||
Map { a: i32, b: i32 },
|
Map {
|
||||||
#[serde(skip_serializing)] SkippedUnit,
|
a: i32,
|
||||||
#[serde(skip_serializing)] SkippedOne(i32),
|
b: i32,
|
||||||
#[serde(skip_serializing)] SkippedSeq(i32, i32),
|
},
|
||||||
#[serde(skip_serializing)] SkippedMap { _a: i32, _b: i32 },
|
#[serde(skip_serializing)]
|
||||||
|
SkippedUnit,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
SkippedOne(i32),
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
SkippedSeq(i32, i32),
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
SkippedMap {
|
||||||
|
_a: i32,
|
||||||
|
_b: i32,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ else
|
|||||||
channel build
|
channel build
|
||||||
cd "$DIR/test_suite"
|
cd "$DIR/test_suite"
|
||||||
channel test --features unstable
|
channel test --features unstable
|
||||||
|
channel build --tests --features proc-macro2/nightly
|
||||||
if [ -z "${APPVEYOR}" ]; then
|
if [ -z "${APPVEYOR}" ]; then
|
||||||
cd "$DIR/test_suite/no_std"
|
cd "$DIR/test_suite/no_std"
|
||||||
channel build
|
channel build
|
||||||
|
|||||||
Reference in New Issue
Block a user