Compare commits

...

80 Commits

Author SHA1 Message Date
David Tolnay 24c4df7831 Release 1.0.71 2018-08-06 23:55:55 -07:00
David Tolnay a077ae039e Merge pull request #1349 from dtolnay/range
Share some code between the Range and RangeInclusive impls
2018-08-06 23:30:03 -07:00
David Tolnay 20b34d3b43 Share some code between the Range and RangeInclusive impls 2018-08-06 23:16:47 -07:00
David Tolnay b5451d1905 Merge pull request #1348 from dtolnay/range
Provide ops::Range impls whether or not std is used
2018-08-06 23:04:26 -07:00
David Tolnay e26960f7f8 Remove useless run-pass test
When originally added, this test used to contain a `#![plugin(clippy)]`.
This was removed at some point along the way, at which point this test
no longer tests anything. It prints:

    warning: unknown lint: `identity_op`
     --> src/main.rs:1:9
      |
    1 | #![deny(identity_op)]
      |         ^^^^^^^^^^^
      |
      = note: #[warn(unknown_lints)] on by default

which is swallowed and ignored by compiletest.

Nowadays Clippy handles warnings inside of macro expanded code
intelligently and this is something they would be responsible for
testing.
2018-08-06 22:57:46 -07:00
David Tolnay 228b5a4a63 Provide ops::Range impls whether or not std is used 2018-08-06 22:49:09 -07:00
David Tolnay 28db9d4989 Format with rustfmt 0.99.1 2018-08-06 22:40:28 -07:00
David Tolnay 5fff0d936d Merge pull request #1347 from c410-f3r/master
Implement Serialize and Deserialize for RangeInclusive
2018-08-06 22:36:12 -07:00
Caio 8eb195edf0 Fix tests 2018-08-05 17:38:41 -03:00
Caio 8b2e6baf78 Implement Serialize and Deserialize for RangeInclusive 2018-08-05 10:45:50 -03:00
David Tolnay 4e54aaf796 Format with rustfmt 0.8.2 2018-07-08 19:02:44 -07:00
David Tolnay 4cddcbe194 Release 1.0.70 2018-07-06 20:21:26 -07:00
David Tolnay 54b6798ef6 Merge pull request #1336 from dtolnay/collections
Update path to alloc::collections for nightly-2018-07-07
2018-07-06 20:19:59 -07:00
David Tolnay 229a9d90ba Update path to alloc::collections for nightly-2018-07-07 2018-07-06 20:04:23 -07:00
David Tolnay 3bcd568c86 Release 1.0.69 2018-06-30 23:40:28 -07:00
David Tolnay dc56077aac Local inner macros 2018-06-30 23:38:14 -07:00
David Tolnay 46bd36e17c Link to issue picker 2018-06-30 10:30:14 -07:00
David Tolnay 5dee9118c7 Factor out the getting help links 2018-06-30 10:29:36 -07:00
David Tolnay a916aa9420 Release 1.0.68 2018-06-28 09:31:12 -07:00
David Tolnay d9c63d0784 Merge pull request #1324 from jechase/suppress_2018_warning
Suppress 'extern crate' warning for rust 2018
2018-06-28 09:30:40 -07:00
Josh Chase 41dcb969e8 Shut clippy up 2018-06-28 11:12:27 -04:00
Josh Chase 6dbaea34ba Suppress 'extern crate' warning for rust 2018 2018-06-28 10:51:57 -04:00
David Tolnay ce17301b8b Release 1.0.67 2018-06-27 00:18:03 -07:00
David Tolnay b0e78c6be4 Format with rustfmt 0.8.2 2018-06-27 00:16:06 -07:00
David Tolnay 898f65fa46 Merge pull request #1323 from dtolnay/format-args
Implement Serialize for core::fmt::Arguments
2018-06-27 00:15:55 -07:00
David Tolnay 84e384196d Implement Serialize for core::fmt::Arguments 2018-06-26 23:58:16 -07:00
David Tolnay d827b101d9 Resolve default_trait_access lint 2018-06-26 23:58:02 -07:00
David Tolnay c45ab6b304 Ignore indexing_slicing pedantic lint 2018-06-26 23:56:39 -07:00
David Tolnay cc9d85b293 Work around unused_imports rustdoc bug 2018-06-26 23:54:32 -07:00
David Tolnay 02493d83be Ignore indexing_slicing pedantic lint 2018-06-26 23:39:26 -07:00
David Tolnay a1280c672a Switch no-std panic to #[panic_implementation] 2018-06-04 10:13:29 -07:00
David Tolnay a740f76772 Update no-std panic signature for nightly-2018-06-03 2018-06-03 23:15:16 -07:00
David Tolnay a887db398b Release 1.0.66 2018-06-03 11:45:20 -07:00
Oliver Schneider e1ae3c71f3 Merge pull request #1304 from dtolnay/ci
CI builders for all versions mentioned in the build script
2018-06-03 10:44:32 +02:00
David Tolnay d094209774 CI builders for all versions mentioned in the build script
This should prevent accidentally inserting something under one of these
cfgs that is available only on a newer rustc. For example if something
is changed in the Duration serialization, but that change works only on
a recent rustc, our test suite will not have caught it before.
2018-06-03 01:26:58 -07:00
David Tolnay 485a64aaf9 Visitor for types that parse from a string 2018-06-03 01:19:46 -07:00
David Tolnay 3e57cd5917 Merge pull request #1303 from dtolnay/duration
Support Duration in no-std mode on new compilers
2018-06-03 01:05:39 -07:00
David Tolnay b6c4cfec37 Support Duration in no-std mode on new compilers 2018-06-03 00:55:58 -07:00
David Tolnay 94853752a1 Stabilize some unstable tests in test suite 2018-06-03 00:31:20 -07:00
David Tolnay bd366f675e Merge pull request #1302 from dtolnay/never
Implement traits for `!`
2018-06-03 00:30:19 -07:00
David Tolnay 22b1af7eb3 Test never_type 2018-06-03 00:22:11 -07:00
David Tolnay fd6178cad6 IntoDeserializer for ! 2018-06-03 00:12:02 -07:00
David Tolnay 338fb67853 Implement traits for ! 2018-06-03 00:02:29 -07:00
David Tolnay 0a71fe329c Format the compile-test sources with rustfmt 0.8.2 2018-06-02 22:30:55 -07:00
David Tolnay a4acc83282 Place compile-fail expected errors on their own line 2018-06-02 22:28:05 -07:00
David Tolnay 57de28744c These match-expressions are implementing unwrap_or_else 2018-06-02 22:09:04 -07:00
David Tolnay 6d31ec521b Remove leftover import from compile_error change 2018-06-02 22:01:45 -07:00
David Tolnay 7ad3d17e59 Merge pull request #1297 from adamcrume/master
Use compile_error! instead of panicking
2018-06-02 22:00:24 -07:00
Adam Crume 05e931b9a5 Update tests and use quote! macro 2018-06-02 21:11:42 -07:00
David Tolnay 2db2b53bbf Release 1.0.65 2018-06-01 13:00:58 -07:00
David Tolnay d5ec3efe49 Merge pull request #1299 from dtolnay/flattenmap
Allow multiple flattened maps to see the same fields
2018-06-01 13:00:45 -07:00
David Tolnay 71fc318474 Merge pull request #1300 from dtolnay/refcell
Use try_borrow for serializing RefCell
2018-06-01 12:58:03 -07:00
David Tolnay 5ee2fc0562 Allow multiple flattened maps to see the same fields
Before this change, flattening anything after a flattened map was
nonsensical because the later flattened field would always observe no
input fields.

    #[derive(Deserialize)]
    struct S {
        #[serde(flatten)]
        map: Map<K, V>,
        #[serde(flatten)]
        other: Other, // always empty
    }

This change makes a flattened map not consume any of the input fields,
leaving them available to later flattened fields in the same struct. The
new behavior is useful when two flattened fields that both use
deserialize_map care about disjoint subsets of the fields in the input.

    #[derive(Deserialize)]
    struct S {
        // Looks at fields with a "player1_" prefix.
        #[serde(flatten, with = "prefix_player1")]
        player1: Player,
        // Looks at fields with a "player2_" prefix.
        #[serde(flatten, with = "prefix_player2")]
        player2: Player,
    }
2018-06-01 12:50:23 -07:00
David Tolnay ca53daf697 Fix RefCell serialize impl to work with no-std 2018-06-01 12:47:10 -07:00
Konrad Borowski c3b9ee314b Use try_borrow for serializing RefCell 2018-06-01 09:09:40 +02:00
Adam Crume 993710eb16 Use compile_error! instead of panicking
Fixes #1168
2018-05-31 19:57:23 -07:00
David Tolnay dbaf2893e3 Release 1.0.64 2018-05-30 00:17:45 -07:00
David Tolnay 34a7108b73 Second attempt at workaround for docs.rs compiler 2018-05-30 00:17:02 -07:00
David Tolnay db2bafd3f3 Revert "Work around docs.rs using an old 1.26-dev compiler"
This reverts commit c81bab18ad.
2018-05-30 00:13:20 -07:00
David Tolnay 1b6fbf1023 Release 1.0.63 2018-05-28 20:12:08 -07:00
David Tolnay c81bab18ad Work around docs.rs using an old 1.26-dev compiler 2018-05-28 19:58:27 -07:00
David Tolnay a39199e9f7 Reword Avro blurb
- Emphasize the association with Apache Hadoop,

- Rephrase "schematized data" because that term returns not many Google
  results, doesn't seem widely recognized.
2018-05-27 19:39:50 -07:00
David Tolnay b0ad1e56e8 Move Avro above deserialization-only formats 2018-05-27 19:31:05 -07:00
David Tolnay ab53448bc3 Merge pull request #1260 from flavray/master
Add Avro to the list of supported data formats
2018-05-27 19:29:19 -07:00
David Tolnay c50c9d8862 Simplify readme as rendered on crates.io 2018-05-27 19:18:30 -07:00
David Tolnay cc4f289758 Link from readme to new playground 2018-05-27 19:07:46 -07:00
David Tolnay a2a9041549 Fix warning about unresolved [u8] and [T] links 2018-05-27 14:35:55 -07:00
David Tolnay a65950acca Link to more complete explanation of the data model 2018-05-27 14:11:02 -07:00
David Tolnay 0fbf4d0c5d Link to example data format from trait rustdocs 2018-05-27 14:05:50 -07:00
David Tolnay 983bf8c090 Release 1.0.62 2018-05-26 18:59:03 -07:00
David Tolnay f2afa89ff1 Explain the pattern for optional Serde derives 2018-05-26 17:59:53 -07:00
David Tolnay 8b4f9c47c4 Build script rustc-cfg strings are not public API 2018-05-26 17:23:09 -07:00
David Tolnay 06d8a44f18 Move unimportant code out of build script main 2018-05-26 17:18:14 -07:00
David Tolnay fffdceca95 Link to "Understanding deserializer lifetimes" 2018-05-26 17:08:46 -07:00
David Tolnay 794b769e6b Merge pull request #1288 from dtolnay/copy
Implement Copy for value deserializers of primitive types
2018-05-26 16:05:12 -07:00
David Tolnay 927ec7d38e Implement Copy for value deserializers of primitive types 2018-05-26 15:56:57 -07:00
David Tolnay cd0b2d312c Merge pull request #1286 from dtolnay/into128
Implement IntoDeserializer for i128 and u128
2018-05-26 15:36:46 -07:00
David Tolnay ea118e11a0 Test the 128-bit IntoDeserializer impls 2018-05-26 15:21:37 -07:00
David Tolnay 0ff4882cab Implement IntoDeserializer for i128 and u128 2018-05-26 15:15:07 -07:00
Flavien Raynaud 38d4f0e06c Add Avro to the list of supported data formats 2018-05-16 16:22:25 +01:00
106 changed files with 1405 additions and 575 deletions
+6 -2
View File
@@ -4,11 +4,15 @@ cache: cargo
# run builds for all the trains (and more) # run builds for all the trains (and more)
rust: rust:
- 1.13.0
- 1.15.0
- stable - stable
- beta - beta
- nightly - nightly
- 1.13.0
- 1.15.0
- 1.20.0
- 1.21.0
- 1.25.0
- 1.26.0
matrix: matrix:
include: include:
+8 -7
View File
@@ -25,7 +25,7 @@ You may be looking for:
<details> <details>
<summary> <summary>
Click to show Cargo.toml. Click to show Cargo.toml.
<a href="http://play.integer32.com/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">Run this code in the playground.</a> <a href="https://play.rust-lang.org/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">Run this code in the playground.</a>
</summary> </summary>
```toml ```toml
@@ -79,12 +79,13 @@ fn main() {
## Getting help ## Getting help
Serde developers live in the #serde channel on Serde developers live in the #serde channel on [`irc.mozilla.org`][irc]. The
[`irc.mozilla.org`](https://wiki.mozilla.org/IRC). The #rust channel is also a \#rust channel is also a good resource with generally faster response time but
good resource with generally faster response time but less specific knowledge less specific knowledge about Serde. If IRC is not your thing or you don't get a
about Serde. If IRC is not your thing or you don't get a good response, we are good response, we are happy to respond to [GitHub issues][issues] as well.
happy to respond to [GitHub issues](https://github.com/serde-rs/serde/issues/new)
as well. [irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose
## License ## License
+56
View File
@@ -0,0 +1,56 @@
<!-- Serde readme rendered on crates.io -->
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
---
You may be looking for:
- [An overview of Serde](https://serde.rs/)
- [Data formats supported by Serde](https://serde.rs/#data-formats)
- [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/codegen.html)
- [Examples](https://serde.rs/examples.html)
- [API documentation](https://docs.serde.rs/serde/)
- [Release notes](https://github.com/serde-rs/serde/releases)
## Serde in action
```rust
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let point = Point { x: 1, y: 2 };
// Convert the Point to a JSON string.
let serialized = serde_json::to_string(&point).unwrap();
// Prints serialized = {"x":1,"y":2}
println!("serialized = {}", serialized);
// Convert the JSON string back to a Point.
let deserialized: Point = serde_json::from_str(&serialized).unwrap();
// Prints deserialized = Point { x: 1, y: 2 }
println!("deserialized = {:?}", deserialized);
}
```
## Getting help
Serde developers live in the #serde channel on [`irc.mozilla.org`][irc]. The
\#rust channel is also a good resource with generally faster response time but
less specific knowledge about Serde. If IRC is not your thing or you don't get a
good response, we are happy to respond to [GitHub issues][issues] as well.
[irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose
+26 -10
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.61" # remember to update html_root_url version = "1.0.71" # 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"
@@ -9,8 +9,8 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde/" documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"] keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"] categories = ["encoding"]
readme = "README.md" readme = "crates-io.md"
include = ["Cargo.toml", "build.rs", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
build = "build.rs" build = "build.rs"
[badges] [badges]
@@ -29,14 +29,30 @@ serde_derive = { version = "1.0", path = "../serde_derive" }
[features] [features]
default = ["std"] default = ["std"]
# Re-export the derive(Serialize, Deserialize) macros. This is specifically # Re-export the derive(Serialize, Deserialize) macros. This is intended for
# intended for library crates that provide optional Serde impls behind a Cargo # library crates that provide optional Serde impls behind a Cargo cfg of their
# cfg of their own. All other crates should depend on serde_derive directly. # own.
#
# Mainly this is a workaround for limitations associated with
# rust-lang/cargo#1286 in which a library crate cannot use one "serde" cfg in
# Cargo to enable dependencies on both serde and serde_derive crates.
#
# The recommended way to provide optional Serde support that requires derive is
# as follows. In particular, please do not name your library's Serde feature
# anything other than "serde".
#
# [dependencies]
# serde = { version = "1.0", optional = true, features = ["derive"] }
#
# Within the library, these optional Serde derives would be written like this.
#
# #[cfg(feature = "serde")]
# #[macro_use]
# extern crate serde;
#
# #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
# struct ...
# #
# Please refer to the long comment above the line `pub use serde_derive::*` in
# src/lib.rs before enabling this feature. If you think you need this feature
# and your use case does not precisely match the one described in the comment,
# please open an issue to let us know about your use case.
derive = ["serde_derive"] derive = ["serde_derive"]
# Provide impls for common standard library types like Vec<T> and HashMap<K, V>. # Provide impls for common standard library types like Vec<T> and HashMap<K, V>.
+51 -27
View File
@@ -2,37 +2,15 @@ use std::env;
use std::process::Command; use std::process::Command;
use std::str::{self, FromStr}; use std::str::{self, FromStr};
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() { fn main() {
let rustc = match env::var_os("RUSTC") { let minor = match rustc_minor_version() {
Some(rustc) => rustc, Some(minor) => minor,
None => return, None => return,
}; };
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return,
};
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return;
}
let next = match pieces.next() {
Some(next) => next,
None => return,
};
let minor = match u32::from_str(next) {
Ok(minor) => minor,
Err(_) => return,
};
// CString::into_boxed_c_str stabilized in Rust 1.20: // CString::into_boxed_c_str stabilized in Rust 1.20:
// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
if minor >= 20 { if minor >= 20 {
@@ -46,15 +24,61 @@ fn main() {
println!("cargo:rustc-cfg=de_rc_dst"); println!("cargo:rustc-cfg=de_rc_dst");
} }
// Duration available in core since Rust 1.25:
// https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
if minor >= 25 {
println!("cargo:rustc-cfg=core_duration");
}
// 128-bit integers stabilized in Rust 1.26: // 128-bit integers stabilized in Rust 1.26:
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
if minor >= 26 { if minor >= 26 {
println!("cargo:rustc-cfg=integer128"); println!("cargo:rustc-cfg=integer128");
} }
// Inclusive ranges methods stabilized in Rust 1.27:
// https://github.com/rust-lang/rust/pull/50758
if minor >= 27 {
println!("cargo:rustc-cfg=range_inclusive");
}
// Non-zero integers stabilized in Rust 1.28: // Non-zero integers stabilized in Rust 1.28:
// https://github.com/rust-lang/rust/pull/50808 // https://github.com/rust-lang/rust/pull/50808
if minor >= 28 { if minor >= 28 {
println!("cargo:rustc-cfg=num_nonzero"); println!("cargo:rustc-cfg=num_nonzero");
} }
} }
fn rustc_minor_version() -> Option<u32> {
let rustc = match env::var_os("RUSTC") {
Some(rustc) => rustc,
None => return None,
};
let output = match Command::new(rustc).arg("--version").output() {
Ok(output) => output,
Err(_) => return None,
};
let version = match str::from_utf8(&output.stdout) {
Ok(version) => version,
Err(_) => return None,
};
// Temporary workaround to support the old 1.26-dev compiler on docs.rs.
if version.contains("0eb87c9bf") {
return Some(25);
}
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
let next = match pieces.next() {
Some(next) => next,
None => return None,
};
u32::from_str(next).ok()
}
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+283 -149
View File
@@ -12,7 +12,7 @@ use de::{
Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor, Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor,
}; };
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(core_duration, feature = "std", feature = "alloc"))]
use de::MapAccess; use de::MapAccess;
use de::from_primitive::FromPrimitive; use de::from_primitive::FromPrimitive;
@@ -49,6 +49,16 @@ impl<'de> Deserialize<'de> for () {
} }
} }
#[cfg(feature = "unstable")]
impl<'de> Deserialize<'de> for ! {
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Err(Error::custom("cannot deserialize `!`"))
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct BoolVisitor; struct BoolVisitor;
@@ -1172,15 +1182,31 @@ map_impl!(
#[cfg(feature = "std")] #[cfg(feature = "std")]
macro_rules! parse_ip_impl { macro_rules! parse_ip_impl {
($ty:ty; $size:expr) => { ($expecting:tt $ty:ty; $size:tt) => {
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
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
let s = try!(String::deserialize(deserializer)); struct IpAddrVisitor;
s.parse().map_err(Error::custom)
impl<'de> Visitor<'de> for IpAddrVisitor {
type Value = $ty;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str($expecting)
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
deserializer.deserialize_str(IpAddrVisitor)
} else { } else {
<[u8; $size]>::deserialize(deserializer).map(<$ty>::from) <[u8; $size]>::deserialize(deserializer).map(<$ty>::from)
} }
@@ -1308,8 +1334,24 @@ impl<'de> Deserialize<'de> for net::IpAddr {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
let s = try!(String::deserialize(deserializer)); struct IpAddrVisitor;
s.parse().map_err(Error::custom)
impl<'de> Visitor<'de> for IpAddrVisitor {
type Value = net::IpAddr;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("IP address")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
deserializer.deserialize_str(IpAddrVisitor)
} else { } else {
use lib::net::IpAddr; use lib::net::IpAddr;
deserialize_enum!{ deserialize_enum!{
@@ -1322,22 +1364,38 @@ impl<'de> Deserialize<'de> for net::IpAddr {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
parse_ip_impl!(net::Ipv4Addr; 4); parse_ip_impl!("IPv4 address" net::Ipv4Addr; 4);
#[cfg(feature = "std")] #[cfg(feature = "std")]
parse_ip_impl!(net::Ipv6Addr; 16); parse_ip_impl!("IPv6 address" net::Ipv6Addr; 16);
#[cfg(feature = "std")] #[cfg(feature = "std")]
macro_rules! parse_socket_impl { macro_rules! parse_socket_impl {
($ty:ty, $new:expr) => { ($expecting:tt $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
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
let s = try!(String::deserialize(deserializer)); struct SocketAddrVisitor;
s.parse().map_err(Error::custom)
impl<'de> Visitor<'de> for SocketAddrVisitor {
type Value = $ty;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str($expecting)
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
deserializer.deserialize_str(SocketAddrVisitor)
} else { } else {
<(_, u16)>::deserialize(deserializer).map(|(ip, port)| $new(ip, port)) <(_, u16)>::deserialize(deserializer).map(|(ip, port)| $new(ip, port))
} }
@@ -1353,8 +1411,24 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
let s = try!(String::deserialize(deserializer)); struct SocketAddrVisitor;
s.parse().map_err(Error::custom)
impl<'de> Visitor<'de> for SocketAddrVisitor {
type Value = net::SocketAddr;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("socket address")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
s.parse().map_err(Error::custom)
}
}
deserializer.deserialize_str(SocketAddrVisitor)
} else { } else {
use lib::net::SocketAddr; use lib::net::SocketAddr;
deserialize_enum!{ deserialize_enum!{
@@ -1367,10 +1441,10 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
parse_socket_impl!(net::SocketAddrV4, net::SocketAddrV4::new); parse_socket_impl!("IPv4 socket address" net::SocketAddrV4, net::SocketAddrV4::new);
#[cfg(feature = "std")] #[cfg(feature = "std")]
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new( parse_socket_impl!("IPv6 socket address" net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(
ip, port, 0, 0 ip, port, 0, 0
)); ));
@@ -1528,7 +1602,13 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
forwarded_impl!((), Box<str>, String::into_boxed_str); forwarded_impl!((), Box<str>, String::into_boxed_str);
#[cfg(all(not(de_rc_dst), feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(
all(
not(de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
)
)]
forwarded_impl! { forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1540,7 +1620,13 @@ forwarded_impl! {
(T), Arc<T>, Arc::new (T), Arc<T>, Arc::new
} }
#[cfg(all(not(de_rc_dst), feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(
all(
not(de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
)
)]
forwarded_impl! { forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1607,7 +1693,13 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(all(de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(
all(
de_rc_dst,
feature = "rc",
any(feature = "std", feature = "alloc")
)
)]
macro_rules! box_forwarded_impl { macro_rules! box_forwarded_impl {
( (
$(#[doc = $doc:tt])* $(#[doc = $doc:tt])*
@@ -1628,7 +1720,13 @@ macro_rules! box_forwarded_impl {
}; };
} }
#[cfg(all(de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(
all(
de_rc_dst,
feature = "rc",
any(feature = "std", feature = "alloc")
)
)]
box_forwarded_impl! { box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1640,7 +1738,13 @@ box_forwarded_impl! {
Rc Rc
} }
#[cfg(all(de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(
all(
de_rc_dst,
feature = "rc",
any(feature = "std", feature = "alloc")
)
)]
box_forwarded_impl! { box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1684,7 +1788,7 @@ forwarded_impl!((T), RwLock<T>, RwLock::new);
// secs: u64, // secs: u64,
// nanos: u32, // nanos: u32,
// } // }
#[cfg(feature = "std")] #[cfg(any(core_duration, feature = "std"))]
impl<'de> Deserialize<'de> for Duration { impl<'de> Deserialize<'de> for Duration {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -1732,7 +1836,7 @@ impl<'de> Deserialize<'de> for Duration {
b"secs" => Ok(Field::Secs), b"secs" => Ok(Field::Secs),
b"nanos" => Ok(Field::Nanos), b"nanos" => Ok(Field::Nanos),
_ => { _ => {
let value = String::from_utf8_lossy(value); let value = ::export::from_utf8_lossy(value);
Err(Error::unknown_field(&value, FIELDS)) Err(Error::unknown_field(&value, FIELDS))
} }
} }
@@ -1950,8 +2054,7 @@ impl<'de> Deserialize<'de> for SystemTime {
// start: u64, // start: u64,
// end: u32, // end: u32,
// } // }
#[cfg(feature = "std")] impl<'de, Idx> Deserialize<'de> for Range<Idx>
impl<'de, Idx> Deserialize<'de> for ops::Range<Idx>
where where
Idx: Deserialize<'de>, Idx: Deserialize<'de>,
{ {
@@ -1959,134 +2062,165 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
// If this were outside of the serde crate, it would just use: let (start, end) = deserializer.deserialize_struct(
//
// #[derive(Deserialize)]
// #[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Start,
End,
};
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`start` or `end`")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"start" => Ok(Field::Start),
"end" => Ok(Field::End),
_ => Err(Error::unknown_field(value, FIELDS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
match value {
b"start" => Ok(Field::Start),
b"end" => Ok(Field::End),
_ => {
let value = String::from_utf8_lossy(value);
Err(Error::unknown_field(&value, FIELDS))
}
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct RangeVisitor<Idx> {
phantom: PhantomData<Idx>,
}
impl<'de, Idx> Visitor<'de> for RangeVisitor<Idx>
where
Idx: Deserialize<'de>,
{
type Value = ops::Range<Idx>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct Range")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let start: Idx = match try!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
let end: Idx = match try!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(1, &self));
}
};
Ok(start..end)
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut start: Option<Idx> = None;
let mut end: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) {
match key {
Field::Start => {
if start.is_some() {
return Err(<A::Error as Error>::duplicate_field("start"));
}
start = Some(try!(map.next_value()));
}
Field::End => {
if end.is_some() {
return Err(<A::Error as Error>::duplicate_field("end"));
}
end = Some(try!(map.next_value()));
}
}
}
let start = match start {
Some(start) => start,
None => return Err(<A::Error as Error>::missing_field("start")),
};
let end = match end {
Some(end) => end,
None => return Err(<A::Error as Error>::missing_field("end")),
};
Ok(start..end)
}
}
const FIELDS: &'static [&'static str] = &["start", "end"];
deserializer.deserialize_struct(
"Range", "Range",
FIELDS, range::FIELDS,
RangeVisitor { range::RangeVisitor {
expecting: "struct Range",
phantom: PhantomData, phantom: PhantomData,
}, },
) )?;
Ok(start..end)
}
}
#[cfg(range_inclusive)]
impl<'de, Idx> Deserialize<'de> for RangeInclusive<Idx>
where
Idx: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let (start, end) = deserializer.deserialize_struct(
"RangeInclusive",
range::FIELDS,
range::RangeVisitor {
expecting: "struct RangeInclusive",
phantom: PhantomData,
},
)?;
Ok(RangeInclusive::new(start, end))
}
}
mod range {
use lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &'static [&'static str] = &["start", "end"];
// If this were outside of the serde crate, it would just use:
//
// #[derive(Deserialize)]
// #[serde(field_identifier, rename_all = "lowercase")]
enum Field {
Start,
End,
}
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`start` or `end`")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"start" => Ok(Field::Start),
"end" => Ok(Field::End),
_ => Err(Error::unknown_field(value, FIELDS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
match value {
b"start" => Ok(Field::Start),
b"end" => Ok(Field::End),
_ => {
let value = ::export::from_utf8_lossy(value);
Err(Error::unknown_field(&value, FIELDS))
}
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
pub struct RangeVisitor<Idx> {
pub expecting: &'static str,
pub phantom: PhantomData<Idx>,
}
impl<'de, Idx> Visitor<'de> for RangeVisitor<Idx>
where
Idx: Deserialize<'de>,
{
type Value = (Idx, Idx);
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.expecting)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let start: Idx = match try!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(0, &self));
}
};
let end: Idx = match try!(seq.next_element()) {
Some(value) => value,
None => {
return Err(Error::invalid_length(1, &self));
}
};
Ok((start, end))
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
let mut start: Option<Idx> = None;
let mut end: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) {
match key {
Field::Start => {
if start.is_some() {
return Err(<A::Error as Error>::duplicate_field("start"));
}
start = Some(try!(map.next_value()));
}
Field::End => {
if end.is_some() {
return Err(<A::Error as Error>::duplicate_field("end"));
}
end = Some(try!(map.next_value()));
}
}
}
let start = match start {
Some(start) => start,
None => return Err(<A::Error as Error>::missing_field("start")),
};
let end = match end {
Some(end) => end,
None => return Err(<A::Error as Error>::missing_field("end")),
};
Ok((start, end))
}
} }
} }
+139 -13
View File
@@ -57,7 +57,7 @@
//! - f32, f64 //! - f32, f64
//! - char //! - char
//! - **Compound types**: //! - **Compound types**:
//! - [T; 0] through [T; 32] //! - \[T; 0\] through \[T; 32\]
//! - tuples up to size 16 //! - tuples up to size 16
//! - **Common standard library types**: //! - **Common standard library types**:
//! - String //! - String
@@ -66,7 +66,7 @@
//! - PhantomData\<T\> //! - PhantomData\<T\>
//! - **Wrapper types**: //! - **Wrapper types**:
//! - Box\<T\> //! - Box\<T\>
//! - Box\<[T]\> //! - Box\<\[T\]\>
//! - Box\<str\> //! - Box\<str\>
//! - Rc\<T\> //! - Rc\<T\>
//! - Arc\<T\> //! - Arc\<T\>
@@ -86,7 +86,7 @@
//! - Vec\<T\> //! - Vec\<T\>
//! - **Zero-copy types**: //! - **Zero-copy types**:
//! - &str //! - &str
//! - &[u8] //! - &\[u8\]
//! - **FFI types**: //! - **FFI types**:
//! - CString //! - CString
//! - Box\<CStr\> //! - Box\<CStr\>
@@ -97,7 +97,9 @@
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - RangeInclusive\<T\>
//! - num::NonZero* //! - num::NonZero*
//! - `!` *(unstable)*
//! - **Net types**: //! - **Net types**:
//! - IpAddr //! - IpAddr
//! - Ipv4Addr //! - Ipv4Addr
@@ -148,6 +150,13 @@ macro_rules! declare_error_trait {
/// ///
/// Most deserializers should only need to provide the `Error::custom` method /// Most deserializers should only need to provide the `Error::custom` method
/// and inherit the default behavior for the other methods. /// and inherit the default behavior for the other methods.
///
/// # Example implementation
///
/// The [example data format] presented on the website shows an error
/// type appropriate for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait Error: Sized $(+ $($supertrait)::+)* { pub trait Error: Sized $(+ $($supertrait)::+)* {
/// Raised when there is general error when deserializing a type. /// Raised when there is general error when deserializing a type.
/// ///
@@ -504,6 +513,14 @@ impl<'a> Display for Expected + 'a {
/// [de]: https://docs.serde.rs/serde/de/index.html /// [de]: https://docs.serde.rs/serde/de/index.html
/// [codegen]: https://serde.rs/codegen.html /// [codegen]: https://serde.rs/codegen.html
/// [impl-deserialize]: https://serde.rs/impl-deserialize.html /// [impl-deserialize]: https://serde.rs/impl-deserialize.html
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by `Self` when deserialized. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
pub trait Deserialize<'de>: Sized { pub trait Deserialize<'de>: Sized {
/// Deserialize this value from the given Serde deserializer. /// Deserialize this value from the given Serde deserializer.
/// ///
@@ -568,12 +585,16 @@ pub trait Deserialize<'de>: Sized {
/// T: DeserializeOwned; /// T: DeserializeOwned;
/// # } /// # }
/// ``` /// ```
///
/// # Lifetime
///
/// The relationship between `Deserialize` and `DeserializeOwned` in trait
/// bounds is explained in more detail on the page [Understanding deserializer
/// lifetimes].
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
pub trait DeserializeOwned: for<'de> Deserialize<'de> {} pub trait DeserializeOwned: for<'de> Deserialize<'de> {}
impl<T> DeserializeOwned for T impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
where
T: for<'de> Deserialize<'de>,
{
}
/// `DeserializeSeed` is the stateful form of the `Deserialize` trait. If you /// `DeserializeSeed` is the stateful form of the `Deserialize` trait. If you
/// ever find yourself looking for a way to pass data into a `Deserialize` impl, /// ever find yourself looking for a way to pass data into a `Deserialize` impl,
@@ -618,6 +639,14 @@ where
/// seed can be appeased by passing `std::marker::PhantomData` as a seed in the /// seed can be appeased by passing `std::marker::PhantomData` as a seed in the
/// case of stateless deserialization. /// case of stateless deserialization.
/// ///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by `Self::Value` when deserialized. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example /// # Example
/// ///
/// Suppose we have JSON that looks like `[[1, 2], [3, 4, 5], [6]]` and we need /// Suppose we have JSON that looks like `[[1, 2], [3, 4, 5], [6]]` and we need
@@ -756,10 +785,10 @@ where
/// A **data format** that can deserialize any data structure supported by /// A **data format** that can deserialize any data structure supported by
/// Serde. /// Serde.
/// ///
/// The role of this trait is to define the deserialization half of the Serde /// The role of this trait is to define the deserialization half of the [Serde
/// data model, which is a way to categorize every Rust data type into one of 29 /// data model], which is a way to categorize every Rust data type into one of
/// possible types. Each method of the `Serializer` trait corresponds to one of /// 29 possible types. Each method of the `Serializer` trait corresponds to one
/// the types of the data model. /// of the types of the data model.
/// ///
/// Implementations of `Deserialize` map themselves into this data model by /// Implementations of `Deserialize` map themselves into this data model by
/// passing to the `Deserializer` a `Visitor` implementation that can receive /// passing to the `Deserializer` a `Visitor` implementation that can receive
@@ -777,7 +806,7 @@ where
/// - UTF-8 bytes with a length and no null terminator. /// - UTF-8 bytes with a length and no null terminator.
/// - When serializing, all strings are handled equally. When deserializing, /// - When serializing, all strings are handled equally. When deserializing,
/// there are three flavors of strings: transient, owned, and borrowed. /// there are three flavors of strings: transient, owned, and borrowed.
/// - **byte array** - [u8] /// - **byte array** - \[u8\]
/// - Similar to strings, during deserialization byte arrays can be transient, /// - Similar to strings, during deserialization byte arrays can be transient,
/// owned, or borrowed. /// owned, or borrowed.
/// - **option** /// - **option**
@@ -841,6 +870,23 @@ where
/// what type is in the input. Know that relying on `Deserializer::deserialize_any` /// what type is in the input. Know that relying on `Deserializer::deserialize_any`
/// means your data type will be able to deserialize from self-describing /// means your data type will be able to deserialize from self-describing
/// formats only, ruling out Bincode and many others. /// formats only, ruling out Bincode and many others.
///
/// [Serde data model]: https://serde.rs/data-model.html
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed from the input when deserializing. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website contains example code for
/// a basic JSON `Deserializer`.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait Deserializer<'de>: Sized { pub trait Deserializer<'de>: Sized {
/// The error type that can be returned if some error occurs during /// The error type that can be returned if some error occurs during
/// deserialization. /// deserialization.
@@ -1164,6 +1210,16 @@ pub trait Deserializer<'de>: Sized {
/// This trait represents a visitor that walks through a deserializer. /// This trait represents a visitor that walks through a deserializer.
/// ///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the requirement for lifetime of data
/// that may be borrowed by `Self::Value`. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example
///
/// ```rust /// ```rust
/// # use std::fmt; /// # use std::fmt;
/// # /// #
@@ -1600,6 +1656,21 @@ pub trait Visitor<'de>: Sized {
/// ///
/// This is a trait that a `Deserializer` passes to a `Visitor` implementation, /// This is a trait that a `Deserializer` passes to a `Visitor` implementation,
/// which deserializes each item in a sequence. /// which deserializes each item in a sequence.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by deserialized sequence elements. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SeqAccess` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SeqAccess<'de> { pub trait SeqAccess<'de> {
/// The error type that can be returned if some error occurs during /// The error type that can be returned if some error occurs during
/// deserialization. /// deserialization.
@@ -1667,6 +1738,21 @@ where
/// Provides a `Visitor` access to each entry of a map in the input. /// Provides a `Visitor` access to each entry of a map in the input.
/// ///
/// This is a trait that a `Deserializer` passes to a `Visitor` implementation. /// This is a trait that a `Deserializer` passes to a `Visitor` implementation.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by deserialized map entries. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `MapAccess` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait MapAccess<'de> { pub trait MapAccess<'de> {
/// The error type that can be returned if some error occurs during /// The error type that can be returned if some error occurs during
/// deserialization. /// deserialization.
@@ -1844,6 +1930,21 @@ where
/// ///
/// `EnumAccess` is created by the `Deserializer` and passed to the /// `EnumAccess` is created by the `Deserializer` and passed to the
/// `Visitor` in order to identify which variant of an enum to deserialize. /// `Visitor` in order to identify which variant of an enum to deserialize.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by the deserialized enum variant. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `EnumAccess` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait EnumAccess<'de>: Sized { pub trait EnumAccess<'de>: Sized {
/// The error type that can be returned if some error occurs during /// The error type that can be returned if some error occurs during
/// deserialization. /// deserialization.
@@ -1876,6 +1977,21 @@ pub trait EnumAccess<'de>: Sized {
/// `VariantAccess` is a visitor that is created by the `Deserializer` and /// `VariantAccess` is a visitor that is created by the `Deserializer` and
/// passed to the `Deserialize` to deserialize the content of a particular enum /// passed to the `Deserialize` to deserialize the content of a particular enum
/// variant. /// variant.
///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed by the deserialized enum variant. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `VariantAccess` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait VariantAccess<'de>: Sized { pub trait VariantAccess<'de>: Sized {
/// The error type that can be returned if some error occurs during /// The error type that can be returned if some error occurs during
/// deserialization. Must match the error type of our `EnumAccess`. /// deserialization. Must match the error type of our `EnumAccess`.
@@ -2079,6 +2195,16 @@ pub trait VariantAccess<'de>: Sized {
/// Converts an existing value into a `Deserializer` from which other values can /// Converts an existing value into a `Deserializer` from which other values can
/// be deserialized. /// be deserialized.
/// ///
/// # Lifetime
///
/// The `'de` lifetime of this trait is the lifetime of data that may be
/// borrowed from the resulting `Deserializer`. See the page [Understanding
/// deserializer lifetimes] for a more detailed explanation of these lifetimes.
///
/// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html
///
/// # Example
///
/// ```rust /// ```rust
/// #[macro_use] /// #[macro_use]
/// extern crate serde_derive; /// extern crate serde_derive;
+103 -8
View File
@@ -44,6 +44,22 @@ use ser;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// For structs that contain a PhantomData. We do not want the trait
// bound `E: Clone` inferred by derive(Clone).
macro_rules! impl_copy_clone {
($ty:ident $(<$lifetime:tt>)*) => {
impl<$($lifetime,)* E> Copy for $ty<$($lifetime,)* E> {}
impl<$($lifetime,)* E> Clone for $ty<$($lifetime,)* E> {
fn clone(&self) -> Self {
*self
}
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// A minimal representation of all possible errors that can occur using the /// A minimal representation of all possible errors that can occur using the
/// `IntoDeserializer` trait. /// `IntoDeserializer` trait.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@@ -124,11 +140,13 @@ where
} }
/// A deserializer holding a `()`. /// A deserializer holding a `()`.
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct UnitDeserializer<E> { pub struct UnitDeserializer<E> {
marker: PhantomData<E>, marker: PhantomData<E>,
} }
impl_copy_clone!(UnitDeserializer);
impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E> impl<'de, E> de::Deserializer<'de> for UnitDeserializer<E>
where where
E: de::Error, E: de::Error,
@@ -158,16 +176,60 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer that cannot be instantiated.
#[cfg(feature = "unstable")]
pub struct NeverDeserializer<E> {
never: !,
marker: PhantomData<E>,
}
#[cfg(feature = "unstable")]
impl<'de, E> IntoDeserializer<'de, E> for !
where
E: de::Error,
{
type Deserializer = NeverDeserializer<E>;
fn into_deserializer(self) -> Self::Deserializer {
self
}
}
#[cfg(feature = "unstable")]
impl<'de, E> de::Deserializer<'de> for NeverDeserializer<E>
where
E: de::Error,
{
type Error = E;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
self.never
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! primitive_deserializer { macro_rules! primitive_deserializer {
($ty:ty, $doc:tt, $name:ident, $method:ident $($cast:tt)*) => { ($ty:ty, $doc:tt, $name:ident, $method:ident $($cast:tt)*) => {
#[doc = "A deserializer holding"] #[doc = "A deserializer holding"]
#[doc = $doc] #[doc = $doc]
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct $name<E> { pub struct $name<E> {
value: $ty, value: $ty,
marker: PhantomData<E> marker: PhantomData<E>
} }
impl_copy_clone!($name);
impl<'de, E> IntoDeserializer<'de, E> for $ty impl<'de, E> IntoDeserializer<'de, E> for $ty
where where
E: de::Error, E: de::Error,
@@ -218,13 +280,20 @@ primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32);
primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64); primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64);
primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char); primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char);
serde_if_integer128! {
primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128);
primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128);
}
/// A deserializer holding a `u32`. /// A deserializer holding a `u32`.
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct U32Deserializer<E> { pub struct U32Deserializer<E> {
value: u32, value: u32,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
impl_copy_clone!(U32Deserializer);
impl<'de, E> IntoDeserializer<'de, E> for u32 impl<'de, E> IntoDeserializer<'de, E> for u32
where where
E: de::Error, E: de::Error,
@@ -291,12 +360,14 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// A deserializer holding a `&str`. /// A deserializer holding a `&str`.
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct StrDeserializer<'a, E> { pub struct StrDeserializer<'a, E> {
value: &'a str, value: &'a str,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
impl_copy_clone!(StrDeserializer<'de>);
impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a str impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a str
where where
E: de::Error, E: de::Error,
@@ -364,12 +435,14 @@ where
/// A deserializer holding a `&str` with a lifetime tied to another /// A deserializer holding a `&str` with a lifetime tied to another
/// deserializer. /// deserializer.
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct BorrowedStrDeserializer<'de, E> { pub struct BorrowedStrDeserializer<'de, E> {
value: &'de str, value: &'de str,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
impl_copy_clone!(BorrowedStrDeserializer<'de>);
impl<'de, E> BorrowedStrDeserializer<'de, E> { impl<'de, E> BorrowedStrDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given string. /// Create a new borrowed deserializer from the given string.
pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> { pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> {
@@ -433,12 +506,22 @@ where
/// A deserializer holding a `String`. /// A deserializer holding a `String`.
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct StringDeserializer<E> { pub struct StringDeserializer<E> {
value: String, value: String,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
#[cfg(any(feature = "std", feature = "alloc"))]
impl<E> Clone for StringDeserializer<E> {
fn clone(&self) -> Self {
StringDeserializer {
value: self.value.clone(),
marker: PhantomData,
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, E> IntoDeserializer<'de, E> for String impl<'de, E> IntoDeserializer<'de, E> for String
where where
@@ -509,12 +592,22 @@ where
/// A deserializer holding a `Cow<str>`. /// A deserializer holding a `Cow<str>`.
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct CowStrDeserializer<'a, E> { pub struct CowStrDeserializer<'a, E> {
value: Cow<'a, str>, value: Cow<'a, str>,
marker: PhantomData<E>, marker: PhantomData<E>,
} }
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, E> Clone for CowStrDeserializer<'a, E> {
fn clone(&self) -> Self {
CowStrDeserializer {
value: self.value.clone(),
marker: PhantomData,
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str>
where where
@@ -588,12 +681,14 @@ where
/// A deserializer holding a `&[u8]` with a lifetime tied to another /// A deserializer holding a `&[u8]` with a lifetime tied to another
/// deserializer. /// deserializer.
#[derive(Clone, Debug)] #[derive(Debug)]
pub struct BorrowedBytesDeserializer<'de, E> { pub struct BorrowedBytesDeserializer<'de, E> {
value: &'de [u8], value: &'de [u8],
marker: PhantomData<E>, marker: PhantomData<E>,
} }
impl_copy_clone!(BorrowedBytesDeserializer<'de>);
impl<'de, E> BorrowedBytesDeserializer<'de, E> { impl<'de, E> BorrowedBytesDeserializer<'de, E> {
/// Create a new borrowed deserializer from the given byte slice. /// Create a new borrowed deserializer from the given byte slice.
pub fn new(value: &'de [u8]) -> BorrowedBytesDeserializer<'de, E> { pub fn new(value: &'de [u8]) -> BorrowedBytesDeserializer<'de, E> {
+29 -8
View File
@@ -52,6 +52,8 @@
//! - [Pickle], a format common in the Python world. //! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans. //! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB. //! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//! definition.
//! - [URL], the x-www-form-urlencoded format. //! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard. //! - [XML], the flexible machine-friendly W3C standard.
//! *(deserialization only)* //! *(deserialization only)*
@@ -69,6 +71,7 @@
//! [Pickle]: https://github.com/birkenfeld/serde-pickle //! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust //! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs //! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [URL]: https://github.com/nox/serde_urlencoded //! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs //! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy //! [Envy]: https://github.com/softprops/envy
@@ -79,22 +82,29 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// 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.61")] #![doc(html_root_url = "https://docs.rs/serde/1.0.71")]
// 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(specialization))] #![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![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( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
cast_lossless, const_static_lifetime, doc_markdown, linkedlist, needless_pass_by_value, cast_lossless,
redundant_field_names, type_complexity, unreadable_literal, zero_prefixed_literal const_static_lifetime,
doc_markdown,
linkedlist,
needless_pass_by_value,
redundant_field_names,
type_complexity,
unreadable_literal,
zero_prefixed_literal
) )
)] )]
// Whitelisted clippy_pedantic lints // Whitelisted clippy_pedantic lints
@@ -115,6 +125,7 @@
stutter, stutter,
use_self, use_self,
// not practical // not practical
indexing_slicing,
many_single_char_names, many_single_char_names,
missing_docs_in_private_items, missing_docs_in_private_items,
similar_names, similar_names,
@@ -123,7 +134,10 @@
use_debug, use_debug,
))] ))]
// Blacklisted Rust lints. // Blacklisted Rust lints.
#![deny(missing_docs, unused_imports)] //
// Compiler bug involving unused_imports:
// https://github.com/rust-lang/rust/issues/51661
#![deny(missing_docs, /*unused_imports*/)]
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -141,7 +155,7 @@ mod lib {
pub use std::*; pub use std::*;
} }
pub use self::core::{cmp, iter, mem, num, ops, slice, str}; pub use self::core::{cmp, iter, mem, num, slice, str};
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::{i16, i32, i64, i8, isize};
pub use self::core::{u16, u32, u64, u8, usize}; pub use self::core::{u16, u32, u64, u8, usize};
@@ -152,6 +166,7 @@ mod lib {
pub use self::core::default::{self, Default}; pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display}; pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData}; pub use self::core::marker::{self, PhantomData};
pub use self::core::ops::Range;
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};
@@ -186,7 +201,7 @@ mod lib {
pub use std::sync::{Arc, Weak as ArcWeak}; pub use std::sync::{Arc, Weak as ArcWeak};
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
@@ -208,7 +223,13 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::sync::{Mutex, RwLock}; pub use std::sync::{Mutex, RwLock};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::time::{Duration, SystemTime, UNIX_EPOCH}; pub use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(any(core_duration, feature = "std"))]
pub use self::core::time::Duration;
#[cfg(range_inclusive)]
pub use self::core::ops::RangeInclusive;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
+2 -2
View File
@@ -128,7 +128,7 @@
/// [`Deserializer`]: trait.Deserializer.html /// [`Deserializer`]: trait.Deserializer.html
/// [`Visitor`]: de/trait.Visitor.html /// [`Visitor`]: de/trait.Visitor.html
/// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any /// [`Deserializer::deserialize_any`]: trait.Deserializer.html#tymethod.deserialize_any
#[macro_export] #[macro_export(local_inner_macros)]
macro_rules! forward_to_deserialize_any { macro_rules! forward_to_deserialize_any {
(<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => { (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => {
$(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})* $(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})*
@@ -157,7 +157,7 @@ macro_rules! forward_to_deserialize_any_method {
} }
#[doc(hidden)] #[doc(hidden)]
#[macro_export] #[macro_export(local_inner_macros)]
macro_rules! forward_to_deserialize_any_helper { macro_rules! forward_to_deserialize_any_helper {
(bool<$l:tt, $v:ident>) => { (bool<$l:tt, $v:ident>) => {
forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()} forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()}
+61 -15
View File
@@ -2723,7 +2723,7 @@ where
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
visitor.visit_map(FlatMapAccess::new(self.0.iter_mut(), None)) visitor.visit_map(FlatMapAccess::new(self.0.iter()))
} }
fn deserialize_struct<V>( fn deserialize_struct<V>(
@@ -2735,7 +2735,7 @@ where
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
visitor.visit_map(FlatMapAccess::new(self.0.iter_mut(), Some(fields))) visitor.visit_map(FlatStructAccess::new(self.0.iter_mut(), fields))
} }
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error> fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
@@ -2784,22 +2784,19 @@ where
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapAccess<'a, 'de: 'a, E> { pub struct FlatMapAccess<'a, 'de: 'a, E> {
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>, iter: slice::Iter<'a, Option<(Content<'de>, Content<'de>)>>,
pending_content: Option<Content<'de>>, pending_content: Option<&'a Content<'de>>,
fields: Option<&'static [&'static str]>,
_marker: PhantomData<E>, _marker: PhantomData<E>,
} }
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de, E> FlatMapAccess<'a, 'de, E> { impl<'a, 'de, E> FlatMapAccess<'a, 'de, E> {
fn new( fn new(
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>, iter: slice::Iter<'a, Option<(Content<'de>, Content<'de>)>>,
fields: Option<&'static [&'static str]>,
) -> FlatMapAccess<'a, 'de, E> { ) -> FlatMapAccess<'a, 'de, E> {
FlatMapAccess { FlatMapAccess {
iter: iter, iter: iter,
pending_content: None, pending_content: None,
fields: fields,
_marker: PhantomData, _marker: PhantomData,
} }
} }
@@ -2812,6 +2809,61 @@ where
{ {
type Error = E; type Error = E;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: DeserializeSeed<'de>,
{
while let Some(item) = self.iter.next() {
// Items in the vector are nulled out when used by a struct.
if let Some((ref key, ref content)) = *item {
self.pending_content = Some(content);
return seed.deserialize(ContentRefDeserializer::new(key)).map(Some);
}
}
Ok(None)
}
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
match self.pending_content.take() {
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
None => Err(Error::custom("value is missing")),
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatStructAccess<'a, 'de: 'a, E> {
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
pending_content: Option<Content<'de>>,
fields: &'static [&'static str],
_marker: PhantomData<E>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de, E> FlatStructAccess<'a, 'de, E> {
fn new(
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
fields: &'static [&'static str],
) -> FlatStructAccess<'a, 'de, E> {
FlatStructAccess {
iter: iter,
pending_content: None,
fields: fields,
_marker: PhantomData,
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, 'de, E> MapAccess<'de> for FlatStructAccess<'a, 'de, E>
where
E: Error,
{
type Error = E;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where where
T: DeserializeSeed<'de>, T: DeserializeSeed<'de>,
@@ -2822,13 +2874,7 @@ where
// about. In case we do not know which fields we want, we take them all. // about. In case we do not know which fields we want, we take them all.
let use_item = match *item { let use_item = match *item {
None => false, None => false,
Some((ref c, _)) => c.as_str().map_or(self.fields.is_none(), |key| { Some((ref c, _)) => c.as_str().map_or(false, |key| self.fields.contains(&key)),
match self.fields {
None => true,
Some(fields) if fields.contains(&key) => true,
_ => false,
}
}),
}; };
if use_item { if use_item {
+2 -2
View File
@@ -32,7 +32,7 @@ macro_rules! __private_deserialize {
/// Used only by Serde doc tests. Not public API. /// Used only by Serde doc tests. Not public API.
#[doc(hidden)] #[doc(hidden)]
#[macro_export] #[macro_export(local_inner_macros)]
macro_rules! __serialize_unimplemented { macro_rules! __serialize_unimplemented {
($($func:ident)*) => { ($($func:ident)*) => {
$( $(
@@ -52,7 +52,7 @@ macro_rules! __serialize_unimplemented_method {
} }
#[doc(hidden)] #[doc(hidden)]
#[macro_export] #[macro_export(local_inner_macros)]
macro_rules! __serialize_unimplemented_helper { macro_rules! __serialize_unimplemented_helper {
(bool) => { (bool) => {
__serialize_unimplemented_method!(serialize_bool(bool) -> Ok); __serialize_unimplemented_method!(serialize_bool(bool) -> Ok);
+45 -8
View File
@@ -8,10 +8,7 @@
use lib::*; use lib::*;
use ser::{Serialize, SerializeTuple, Serializer}; use ser::{Error, Serialize, SerializeTuple, Serializer};
#[cfg(feature = "std")]
use ser::Error;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -72,6 +69,15 @@ impl Serialize for String {
} }
} }
impl<'a> Serialize for fmt::Arguments<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(self)
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -221,8 +227,7 @@ seq_impl!(VecDeque<T>);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")] impl<Idx> Serialize for Range<Idx>
impl<Idx> Serialize for ops::Range<Idx>
where where
Idx: Serialize, Idx: Serialize,
{ {
@@ -240,6 +245,25 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(range_inclusive)]
impl<Idx> Serialize for RangeInclusive<Idx>
where
Idx: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2));
try!(state.serialize_field("start", &self.start()));
try!(state.serialize_field("end", &self.end()));
state.end()
}
}
////////////////////////////////////////////////////////////////////////////////
impl Serialize for () { impl Serialize for () {
#[inline] #[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -250,6 +274,16 @@ impl Serialize for () {
} }
} }
#[cfg(feature = "unstable")]
impl Serialize for ! {
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
*self
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! tuple_impls { macro_rules! tuple_impls {
@@ -459,7 +493,10 @@ where
where where
S: Serializer, S: Serializer,
{ {
self.borrow().serialize(serializer) match self.try_borrow() {
Ok(value) => value.serialize(serializer),
Err(_) => Err(S::Error::custom("already mutably borrowed")),
}
} }
} }
@@ -517,7 +554,7 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")] #[cfg(any(core_duration, feature = "std"))]
impl Serialize for Duration { impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
+88 -7
View File
@@ -55,8 +55,8 @@
//! - str //! - str
//! - &T and &mut T //! - &T and &mut T
//! - **Compound types**: //! - **Compound types**:
//! - [T] //! - \[T\]
//! - [T; 0] through [T; 32] //! - \[T; 0\] through \[T; 32\]
//! - tuples up to size 16 //! - tuples up to size 16
//! - **Common standard library types**: //! - **Common standard library types**:
//! - String //! - String
@@ -92,7 +92,9 @@
//! - Path //! - Path
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - RangeInclusive\<T\>
//! - num::NonZero* //! - num::NonZero*
//! - `!` *(unstable)*
//! - **Net types**: //! - **Net types**:
//! - IpAddr //! - IpAddr
//! - Ipv4Addr //! - Ipv4Addr
@@ -127,6 +129,13 @@ macro_rules! declare_error_trait {
/// Trait used by `Serialize` implementations to generically construct /// Trait used by `Serialize` implementations to generically construct
/// errors belonging to the `Serializer` against which they are /// errors belonging to the `Serializer` against which they are
/// currently running. /// currently running.
///
/// # Example implementation
///
/// The [example data format] presented on the website shows an error
/// type appropriate for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait Error: Sized $(+ $($supertrait)::+)* { pub trait Error: Sized $(+ $($supertrait)::+)* {
/// Used when a [`Serialize`] implementation encounters any error /// Used when a [`Serialize`] implementation encounters any error
/// while serializing a type. /// while serializing a type.
@@ -244,10 +253,10 @@ pub trait Serialize {
/// A **data format** that can serialize any data structure supported by Serde. /// A **data format** that can serialize any data structure supported by Serde.
/// ///
/// The role of this trait is to define the serialization half of the Serde data /// The role of this trait is to define the serialization half of the [Serde
/// model, which is a way to categorize every Rust data structure into one of 29 /// data model], which is a way to categorize every Rust data structure into one
/// possible types. Each method of the `Serializer` trait corresponds to one of /// of 29 possible types. Each method of the `Serializer` trait corresponds to
/// the types of the data model. /// one of the types of the data model.
/// ///
/// Implementations of `Serialize` map themselves into this data model by /// Implementations of `Serialize` map themselves into this data model by
/// invoking exactly one of the `Serializer` methods. /// invoking exactly one of the `Serializer` methods.
@@ -264,7 +273,7 @@ pub trait Serialize {
/// - UTF-8 bytes with a length and no null terminator. /// - UTF-8 bytes with a length and no null terminator.
/// - When serializing, all strings are handled equally. When deserializing, /// - When serializing, all strings are handled equally. When deserializing,
/// there are three flavors of strings: transient, owned, and borrowed. /// there are three flavors of strings: transient, owned, and borrowed.
/// - **byte array** - [u8] /// - **byte array** - \[u8\]
/// - Similar to strings, during deserialization byte arrays can be transient, /// - Similar to strings, during deserialization byte arrays can be transient,
/// owned, or borrowed. /// owned, or borrowed.
/// - **option** /// - **option**
@@ -309,6 +318,15 @@ pub trait Serialize {
/// is the `serde_json::value::Serializer` (distinct from the main `serde_json` /// is the `serde_json::value::Serializer` (distinct from the main `serde_json`
/// serializer) that produces a `serde_json::Value` data structure in memory as /// serializer) that produces a `serde_json::Value` data structure in memory as
/// output. /// output.
///
/// [Serde data model]: https://serde.rs/data-model.html
///
/// # Example implementation
///
/// The [example data format] presented on the website contains example code for
/// a basic JSON `Serializer`.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait Serializer: Sized { pub trait Serializer: Sized {
/// The output type produced by this `Serializer` during successful /// The output type produced by this `Serializer` during successful
/// serialization. Most serializers that produce text or binary output /// serialization. Most serializers that produce text or binary output
@@ -1520,6 +1538,8 @@ pub trait Serializer: Sized {
/// Returned from `Serializer::serialize_seq`. /// Returned from `Serializer::serialize_seq`.
/// ///
/// # Example use
///
/// ```rust /// ```rust
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// # /// #
@@ -1557,6 +1577,13 @@ pub trait Serializer: Sized {
/// } /// }
/// } /// }
/// ``` /// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeSeq` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeSeq { pub trait SerializeSeq {
/// Must match the `Ok` type of our `Serializer`. /// Must match the `Ok` type of our `Serializer`.
type Ok; type Ok;
@@ -1575,6 +1602,8 @@ pub trait SerializeSeq {
/// Returned from `Serializer::serialize_tuple`. /// Returned from `Serializer::serialize_tuple`.
/// ///
/// # Example use
///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTuple}; /// use serde::ser::{Serialize, Serializer, SerializeTuple};
/// ///
@@ -1648,6 +1677,13 @@ pub trait SerializeSeq {
/// } /// }
/// } /// }
/// ``` /// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeTuple` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeTuple { pub trait SerializeTuple {
/// Must match the `Ok` type of our `Serializer`. /// Must match the `Ok` type of our `Serializer`.
type Ok; type Ok;
@@ -1666,6 +1702,8 @@ pub trait SerializeTuple {
/// Returned from `Serializer::serialize_tuple_struct`. /// Returned from `Serializer::serialize_tuple_struct`.
/// ///
/// # Example use
///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleStruct}; /// use serde::ser::{Serialize, Serializer, SerializeTupleStruct};
/// ///
@@ -1684,6 +1722,13 @@ pub trait SerializeTuple {
/// } /// }
/// } /// }
/// ``` /// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeTupleStruct` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeTupleStruct { pub trait SerializeTupleStruct {
/// Must match the `Ok` type of our `Serializer`. /// Must match the `Ok` type of our `Serializer`.
type Ok; type Ok;
@@ -1702,6 +1747,8 @@ pub trait SerializeTupleStruct {
/// Returned from `Serializer::serialize_tuple_variant`. /// Returned from `Serializer::serialize_tuple_variant`.
/// ///
/// # Example use
///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeTupleVariant}; /// use serde::ser::{Serialize, Serializer, SerializeTupleVariant};
/// ///
@@ -1733,6 +1780,13 @@ pub trait SerializeTupleStruct {
/// } /// }
/// } /// }
/// ``` /// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeTupleVariant` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeTupleVariant { pub trait SerializeTupleVariant {
/// Must match the `Ok` type of our `Serializer`. /// Must match the `Ok` type of our `Serializer`.
type Ok; type Ok;
@@ -1751,6 +1805,8 @@ pub trait SerializeTupleVariant {
/// Returned from `Serializer::serialize_map`. /// Returned from `Serializer::serialize_map`.
/// ///
/// # Example use
///
/// ```rust /// ```rust
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// # /// #
@@ -1790,6 +1846,13 @@ pub trait SerializeTupleVariant {
/// } /// }
/// } /// }
/// ``` /// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeMap` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeMap { pub trait SerializeMap {
/// Must match the `Ok` type of our `Serializer`. /// Must match the `Ok` type of our `Serializer`.
type Ok; type Ok;
@@ -1853,6 +1916,8 @@ pub trait SerializeMap {
/// Returned from `Serializer::serialize_struct`. /// Returned from `Serializer::serialize_struct`.
/// ///
/// # Example use
///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStruct}; /// use serde::ser::{Serialize, Serializer, SerializeStruct};
/// ///
@@ -1875,6 +1940,13 @@ pub trait SerializeMap {
/// } /// }
/// } /// }
/// ``` /// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeStruct` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeStruct { pub trait SerializeStruct {
/// Must match the `Ok` type of our `Serializer`. /// Must match the `Ok` type of our `Serializer`.
type Ok; type Ok;
@@ -1904,6 +1976,8 @@ pub trait SerializeStruct {
/// Returned from `Serializer::serialize_struct_variant`. /// Returned from `Serializer::serialize_struct_variant`.
/// ///
/// # Example use
///
/// ```rust /// ```rust
/// use serde::ser::{Serialize, Serializer, SerializeStructVariant}; /// use serde::ser::{Serialize, Serializer, SerializeStructVariant};
/// ///
@@ -1928,6 +2002,13 @@ pub trait SerializeStruct {
/// } /// }
/// } /// }
/// ``` /// ```
///
/// # Example implementation
///
/// The [example data format] presented on the website demonstrates an
/// implementation of `SerializeStructVariant` for a basic JSON data format.
///
/// [example data format]: https://serde.rs/data-format.html
pub trait SerializeStructVariant { pub trait SerializeStructVariant {
/// Must match the `Ok` type of our `Serializer`. /// Must match the `Ok` type of our `Serializer`.
type Ok; type Ok;
+3 -3
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.61" # remember to update html_root_url version = "1.0.71" # 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)]"
@@ -8,8 +8,8 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/codegen.html" documentation = "https://serde.rs/codegen.html"
keywords = ["serde", "serialization", "no_std"] keywords = ["serde", "serialization", "no_std"]
readme = "README.md" readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+11 -15
View File
@@ -32,8 +32,7 @@ pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
..param.clone() ..param.clone()
}), }),
_ => param.clone(), _ => param.clone(),
}) }).collect(),
.collect(),
..generics.clone() ..generics.clone()
} }
} }
@@ -193,14 +192,13 @@ pub fn with_bound(
.map(|id| syn::TypePath { .map(|id| syn::TypePath {
qself: None, qself: None,
path: id.into(), path: id.into(),
}) }).chain(associated_type_usage.into_iter().cloned())
.chain(associated_type_usage.into_iter().cloned())
.map(|bounded_ty| { .map(|bounded_ty| {
syn::WherePredicate::Type(syn::PredicateType { syn::WherePredicate::Type(syn::PredicateType {
lifetimes: None, lifetimes: None,
// the type parameter that is being bounded e.g. T // the type parameter that is being bounded e.g. T
bounded_ty: syn::Type::Path(bounded_ty), bounded_ty: syn::Type::Path(bounded_ty),
colon_token: Default::default(), colon_token: <Token![:]>::default(),
// the bound e.g. Serialize // the bound e.g. Serialize
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound { bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
paren_token: None, paren_token: None,
@@ -208,7 +206,7 @@ pub fn with_bound(
lifetimes: None, lifetimes: None,
path: bound.clone(), path: bound.clone(),
})].into_iter() })].into_iter()
.collect(), .collect(),
}) })
}); });
@@ -233,7 +231,7 @@ pub fn with_self_bound(
lifetimes: None, lifetimes: None,
// the type that is being bounded e.g. MyStruct<'a, T> // the type that is being bounded e.g. MyStruct<'a, T>
bounded_ty: type_of_item(cont), bounded_ty: type_of_item(cont),
colon_token: Default::default(), colon_token: <Token![:]>::default(),
// the bound e.g. Default // the bound e.g. Default
bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound { bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound {
paren_token: None, paren_token: None,
@@ -241,7 +239,7 @@ pub fn with_self_bound(
lifetimes: None, lifetimes: None,
path: bound.clone(), path: bound.clone(),
})].into_iter() })].into_iter()
.collect(), .collect(),
})); }));
generics generics
} }
@@ -270,8 +268,7 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
syn::GenericParam::Const(_) => {} syn::GenericParam::Const(_) => {}
} }
param param
})) })).collect();
.collect();
syn::Generics { syn::Generics {
params: params, params: params,
@@ -289,7 +286,7 @@ fn type_of_item(cont: &Container) -> syn::Type {
arguments: syn::PathArguments::AngleBracketed( arguments: syn::PathArguments::AngleBracketed(
syn::AngleBracketedGenericArguments { syn::AngleBracketedGenericArguments {
colon2_token: None, colon2_token: None,
lt_token: Default::default(), lt_token: <Token![<]>::default(),
args: cont args: cont
.generics .generics
.params .params
@@ -307,13 +304,12 @@ fn type_of_item(cont: &Container) -> syn::Type {
syn::GenericParam::Const(_) => { syn::GenericParam::Const(_) => {
panic!("Serde does not support const generics yet"); panic!("Serde does not support const generics yet");
} }
}) }).collect(),
.collect(), gt_token: <Token![>]>::default(),
gt_token: Default::default(),
}, },
), ),
}].into_iter() }].into_iter()
.collect(), .collect(),
}, },
}) })
} }
+8 -5
View File
@@ -73,6 +73,9 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<TokenStream
let generated = quote! { let generated = quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = { const #dummy_const: () = {
#[allow(unknown_lints)]
#[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
#[allow(rust_2018_idioms)]
extern crate serde as _serde; extern crate serde as _serde;
#try_replacement #try_replacement
#impl_block #impl_block
@@ -201,7 +204,9 @@ fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generi
// All other fields may need a `T: Deserialize` bound where T is the type of the // All other fields may need a `T: Deserialize` bound where T is the type of the
// field. // field.
fn needs_deserialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { fn needs_deserialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_deserializing() && field.deserialize_with().is_none() && field.de_bound().is_none() !field.skip_deserializing()
&& field.deserialize_with().is_none()
&& field.de_bound().is_none()
&& variant.map_or(true, |variant| { && variant.map_or(true, |variant| {
!variant.skip_deserializing() !variant.skip_deserializing()
&& variant.deserialize_with().is_none() && variant.deserialize_with().is_none()
@@ -1347,8 +1352,7 @@ fn deserialize_adjacently_tagged_enum(
quote! { quote! {
__Field::#variant_index => #block __Field::#variant_index => #block
} }
}) }).collect();
.collect();
let expecting = format!("adjacently tagged enum {}", params.type_name()); let expecting = format!("adjacently tagged enum {}", params.type_name());
let type_name = cattrs.name().deserialize_name(); let type_name = cattrs.name().deserialize_name();
@@ -1936,8 +1940,7 @@ fn deserialize_custom_identifier(
variant.attrs.name().deserialize_name(), variant.attrs.name().deserialize_name(),
variant.ident.clone(), variant.ident.clone(),
) )
}) }).collect();
.collect();
let names = names_idents.iter().map(|&(ref name, _)| name); let names = names_idents.iter().map(|&(ref name, _)| name);
+2 -4
View File
@@ -129,8 +129,7 @@ fn enum_from_ast<'a>(
style: style, style: style,
fields: fields, fields: fields,
} }
}) }).collect()
.collect()
} }
fn struct_from_ast<'a>( fn struct_from_ast<'a>(
@@ -173,6 +172,5 @@ fn fields_from_ast<'a>(
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default), attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
ty: &field.ty, ty: &field.ty,
original: field, original: field,
}) }).collect()
.collect()
} }
+29 -12
View File
@@ -22,22 +22,35 @@
//! //!
//! [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.61")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.71")]
#![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( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
enum_variant_names, redundant_field_names, too_many_arguments, used_underscore_binding, enum_variant_names,
cyclomatic_complexity redundant_field_names,
too_many_arguments,
used_underscore_binding,
cyclomatic_complexity,
needless_pass_by_value
) )
)] )]
// Whitelisted clippy_pedantic lints // Whitelisted clippy_pedantic lints
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
items_after_statements, doc_markdown, stutter, similar_names, use_self, single_match_else, items_after_statements,
enum_glob_use, match_same_arms, filter_map, cast_possible_truncation doc_markdown,
stutter,
similar_names,
use_self,
single_match_else,
enum_glob_use,
match_same_arms,
filter_map,
cast_possible_truncation,
indexing_slicing,
) )
)] )]
// The `quote!` macro requires deep recursion. // The `quote!` macro requires deep recursion.
@@ -69,17 +82,21 @@ 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: DeriveInput = syn::parse(input).unwrap(); let input: DeriveInput = syn::parse(input).unwrap();
match ser::expand_derive_serialize(&input) { ser::expand_derive_serialize(&input)
Ok(expanded) => expanded.into(), .unwrap_or_else(compile_error)
Err(msg) => panic!(msg), .into()
}
} }
#[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: DeriveInput = syn::parse(input).unwrap(); let input: DeriveInput = syn::parse(input).unwrap();
match de::expand_derive_deserialize(&input) { de::expand_derive_deserialize(&input)
Ok(expanded) => expanded.into(), .unwrap_or_else(compile_error)
Err(msg) => panic!(msg), .into()
}
fn compile_error(message: String) -> proc_macro2::TokenStream {
quote! {
compile_error!(#message);
} }
} }
+1 -2
View File
@@ -62,8 +62,7 @@ fn pretend_fields_used(cont: &Container) -> TokenStream {
Some(quote!(#type_ident::#variant_ident #pat)) Some(quote!(#type_ident::#variant_ident #pat))
} }
_ => None, _ => None,
}) }).collect::<Vec<_>>(),
.collect::<Vec<_>>(),
Data::Struct(Style::Struct, ref fields) => { Data::Struct(Style::Struct, ref fields) => {
let pat = struct_pattern(fields); let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)] vec![quote!(#type_ident #pat)]
+14 -17
View File
@@ -61,6 +61,9 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream,
let generated = quote! { let generated = quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = { const #dummy_const: () = {
#[allow(unknown_lints)]
#[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
#[allow(rust_2018_idioms)]
extern crate serde as _serde; extern crate serde as _serde;
#try_replacement #try_replacement
#impl_block #impl_block
@@ -157,7 +160,9 @@ fn build_generics(cont: &Container) -> syn::Generics {
// attribute specify their own bound so we do not generate one. All other fields // attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Serialize` bound where T is the type of the field. // may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool {
!field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none() !field.skip_serializing()
&& field.serialize_with().is_none()
&& field.ser_bound().is_none()
&& variant.map_or(true, |variant| { && variant.map_or(true, |variant| {
!variant.skip_serializing() !variant.skip_serializing()
&& variant.serialize_with().is_none() && variant.serialize_with().is_none()
@@ -279,8 +284,7 @@ fn serialize_tuple_struct(
let field_expr = get_member(params, field, &Member::Unnamed(index)); let field_expr = get_member(params, field, &Member::Unnamed(index));
quote!(if #path(#field_expr) { 0 } else { 1 }) quote!(if #path(#field_expr) { 0 } else { 1 })
} }
}) }).fold(quote!(0), |sum, expr| quote!(#sum + #expr));
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! { quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)); let #let_mut __serde_state = try!(_serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len));
@@ -323,8 +327,7 @@ fn serialize_struct_as_struct(
let field_expr = get_member(params, field, &field.member); let field_expr = get_member(params, field, &field.member);
quote!(if #path(#field_expr) { 0 } else { 1 }) quote!(if #path(#field_expr) { 0 } else { 1 })
} }
}) }).fold(quote!(0), |sum, expr| quote!(#sum + #expr));
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote_block! { quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len)); let #let_mut __serde_state = try!(_serde::Serializer::serialize_struct(__serializer, #type_name, #len));
@@ -358,8 +361,7 @@ fn serialize_struct_as_map(
let field_expr = get_member(params, field, &field.member); let field_expr = get_member(params, field, &field.member);
quote!(if #path(#field_expr) { 0 } else { 1 }) quote!(if #path(#field_expr) { 0 } else { 1 })
} }
}) }).fold(quote!(0), |sum, expr| quote!(#sum + #expr));
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
quote!(_serde::export::Some(#len)) quote!(_serde::export::Some(#len))
}; };
@@ -380,8 +382,7 @@ fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Cont
.enumerate() .enumerate()
.map(|(variant_index, variant)| { .map(|(variant_index, variant)| {
serialize_variant(params, variant, variant_index as u32, cattrs) serialize_variant(params, variant, variant_index as u32, cattrs)
}) }).collect();
.collect();
quote_expr! { quote_expr! {
match *#self_var { match *#self_var {
@@ -785,8 +786,7 @@ fn serialize_tuple_variant(
let field_expr = Ident::new(&format!("__field{}", i), Span::call_site()); let field_expr = Ident::new(&format!("__field{}", i), Span::call_site());
quote!(if #path(#field_expr) { 0 } else { 1 }) quote!(if #path(#field_expr) { 0 } else { 1 })
} }
}) }).fold(quote!(0), |sum, expr| quote!(#sum + #expr));
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context { match context {
TupleVariant::ExternallyTagged { TupleVariant::ExternallyTagged {
@@ -863,8 +863,7 @@ fn serialize_struct_variant<'a>(
Some(path) => quote!(if #path(#member) { 0 } else { 1 }), Some(path) => quote!(if #path(#member) { 0 } else { 1 }),
None => quote!(1), None => quote!(1),
} }
}) }).fold(quote!(0), |sum, expr| quote!(#sum + #expr));
.fold(quote!(0), |sum, expr| quote!(#sum + #expr));
match context { match context {
StructVariant::ExternallyTagged { StructVariant::ExternallyTagged {
@@ -1043,8 +1042,7 @@ fn serialize_tuple_struct_visitor(
None => ser, None => ser,
Some(skip) => quote!(if !#skip { #ser }), Some(skip) => quote!(if !#skip { #ser }),
} }
}) }).collect()
.collect()
} }
fn serialize_struct_visitor( fn serialize_struct_visitor(
@@ -1138,8 +1136,7 @@ fn wrap_serialize_variant_with(
} }
}; };
quote!(#id) quote!(#id)
}) }).collect();
.collect();
wrap_serialize_with( wrap_serialize_with(
params, params,
serialize_with, serialize_with,
+2 -2
View File
@@ -8,8 +8,8 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_derive_internals/" documentation = "https://docs.serde.rs/serde_derive_internals/"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
readme = "README.md" readme = "crates-io.md"
include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[lib] [lib]
path = "lib.rs" path = "lib.rs"
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+6 -1
View File
@@ -9,7 +9,12 @@
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.23.1")] #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.23.1")]
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow(cyclomatic_complexity, doc_markdown, match_same_arms, redundant_field_names) allow(
cyclomatic_complexity,
doc_markdown,
match_same_arms,
redundant_field_names
)
)] )]
#[macro_use] #[macro_use]
+3 -3
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.61" # remember to update html_root_url version = "1.0.71" # 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"
@@ -8,8 +8,8 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/" documentation = "https://docs.serde.rs/serde_test/"
keywords = ["serde", "serialization"] keywords = ["serde", "serialization"]
readme = "README.md" readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-MIT"] include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies] [dependencies]
serde = { version = "1.0.60", path = "../serde" } serde = { version = "1.0.60", path = "../serde" }
+1
View File
@@ -0,0 +1 @@
../crates-io.md
+2 -1
View File
@@ -253,7 +253,8 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
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 })
} }
+7 -3
View File
@@ -161,7 +161,7 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.61")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.71")]
#![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))]
@@ -169,8 +169,12 @@
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
empty_line_after_outer_attr, missing_docs_in_private_items, redundant_field_names, stutter, empty_line_after_outer_attr,
use_debug, use_self missing_docs_in_private_items,
redundant_field_names,
stutter,
use_debug,
use_self
) )
)] )]
+3 -8
View File
@@ -6,7 +6,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![feature(lang_items, start)] #![feature(lang_items, start, panic_implementation)]
#![no_std] #![no_std]
extern crate libc; extern crate libc;
@@ -20,13 +20,8 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
#[no_mangle] #[no_mangle]
pub extern "C" fn rust_eh_personality() {} pub extern "C" fn rust_eh_personality() {}
#[lang = "panic_fmt"] #[panic_implementation]
#[no_mangle] fn panic(_info: &core::panic::PanicInfo) -> ! {
pub extern "C" fn rust_begin_panic(
_msg: core::fmt::Arguments,
_file: &'static str,
_line: u32,
) -> ! {
unsafe { unsafe {
libc::abort(); libc::abort();
} }
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
struct Test<'a> { struct Test<'a> {
#[serde(borrow = "zzz")] //~^^ HELP: failed to parse borrowed lifetimes: "zzz" #[serde(borrow = "zzz")]
//~^^^ ERROR: failed to parse borrowed lifetimes: "zzz"
s: &'a str, s: &'a str,
} }
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
struct Test<'a> { struct Test<'a> {
#[serde(borrow = "'a + 'a")] //~^^ HELP: duplicate borrowed lifetime `'a` #[serde(borrow = "'a + 'a")]
//~^^^ ERROR: duplicate borrowed lifetime `'a`
s: &'a str, s: &'a str,
} }
@@ -12,10 +12,11 @@ extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Str<'a>(&'a str); struct Str<'a>(&'a str);
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
enum Test<'a> { enum Test<'a> {
#[serde(borrow)] //~^^ HELP: duplicate serde attribute `borrow` #[serde(borrow)]
S(#[serde(borrow)] Str<'a>) //~^^^ ERROR: duplicate serde attribute `borrow`
S(#[serde(borrow)] Str<'a>),
} }
fn main() {} fn main() {}
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
struct Test<'a> { struct Test<'a> {
#[serde(borrow = "")] //~^^ HELP: at least one lifetime must be borrowed #[serde(borrow = "")]
//~^^^ ERROR: at least one lifetime must be borrowed
s: &'a str, s: &'a str,
} }
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
struct Test { struct Test {
#[serde(borrow)] //~^^ HELP: field `s` has no lifetimes to borrow #[serde(borrow)]
//~^^^ ERROR: field `s` has no lifetimes to borrow
s: String, s: String,
} }
@@ -12,10 +12,11 @@ extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Str<'a>(&'a str); struct Str<'a>(&'a str);
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
enum Test<'a> { enum Test<'a> {
#[serde(borrow)] //~^^ HELP: #[serde(borrow)] may only be used on newtype variants #[serde(borrow)]
S { s: Str<'a> } //~^^^ ERROR: #[serde(borrow)] may only be used on newtype variants
S { s: Str<'a> },
} }
fn main() {} fn main() {}
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
struct Test<'a> { struct Test<'a> {
#[serde(borrow = "'b")] //~^^ HELP: field `s` does not have lifetime 'b #[serde(borrow = "'b")]
//~^^^ ERROR: field `s` does not have lifetime 'b
s: &'a str, s: &'a str,
} }
@@ -9,9 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(tag = "conflict", content = "conflict")] #[serde(tag = "conflict", content = "conflict")]
//~^^ HELP: enum tags `conflict` for type and content conflict with each other //~^^ ERROR: enum tags `conflict` for type and content conflict with each other
enum E { enum E {
A, A,
B, B,
@@ -9,8 +9,8 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: #[serde(flatten)] cannot be used on newtype structs
struct Foo(#[serde(flatten)] HashMap<String, String>); struct Foo(#[serde(flatten)] HashMap<String, String>);
//~^^ ERROR: #[serde(flatten)] cannot be used on newtype structs
fn main() {} fn main() {}
@@ -9,16 +9,16 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_deserializing)]
struct Foo { struct Foo {
#[serde(flatten, skip_deserializing)] #[serde(flatten, skip_deserializing)]
//~^^^ ERROR: #[serde(flatten] can not be combined with #[serde(skip_deserializing)]
other: Other, other: Other,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
struct Other { struct Other {
x: u32 x: u32,
} }
fn main() {} fn main() {}
@@ -9,16 +9,16 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_serializing_if = "...")]
struct Foo { struct Foo {
#[serde(flatten, skip_serializing_if="Option::is_none")] #[serde(flatten, skip_serializing_if = "Option::is_none")]
//~^^^ ERROR: #[serde(flatten] can not be combined with #[serde(skip_serializing_if = "...")]
other: Option<Other>, other: Option<Other>,
} }
#[derive(Serialize)] #[derive(Serialize)]
struct Other { struct Other {
x: u32 x: u32,
} }
fn main() {} fn main() {}
@@ -9,16 +9,16 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: #[serde(flatten] can not be combined with #[serde(skip_serializing)]
struct Foo { struct Foo {
#[serde(flatten, skip_serializing)] #[serde(flatten, skip_serializing)]
//~^^^ ERROR: #[serde(flatten] can not be combined with #[serde(skip_serializing)]
other: Other, other: Other,
} }
#[derive(Serialize)] #[derive(Serialize)]
struct Other { struct Other {
x: u32 x: u32,
} }
fn main() {} fn main() {}
@@ -9,8 +9,8 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: #[serde(flatten)] cannot be used on tuple structs
struct Foo(u32, #[serde(flatten)] HashMap<String, String>); struct Foo(u32, #[serde(flatten)] HashMap<String, String>);
//~^^ ERROR: #[serde(flatten)] cannot be used on tuple structs
fn main() {} fn main() {}
@@ -9,9 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(tag = "conflict")] #[serde(tag = "conflict")]
//~^^ HELP: variant field name `conflict` conflicts with internal tag //~^^ ERROR: variant field name `conflict` conflicts with internal tag
enum E { enum E {
A { A {
#[serde(rename = "conflict")] #[serde(rename = "conflict")]
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(default)] //~^ HELP: #[serde(default)] can only be used on structs #[serde(default)]
//~^^ ERROR: #[serde(default)] can only be used on structs
enum E { enum E {
S { f: u8 }, S { f: u8 },
} }
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(default)] //~^ HELP: #[serde(default)] can only be used on structs #[serde(default)]
//~^^ ERROR: #[serde(default)] can only be used on structs
struct T(u8, u8); struct T(u8, u8);
fn main() { } fn main() {}
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct S { struct S {
#[serde(rename="x", serialize="y")] //~^^ HELP: unknown serde field attribute `serialize` #[serde(rename = "x", serialize = "y")]
//~^^^ ERROR: unknown serde field attribute `serialize`
x: (), x: (),
} }
@@ -9,10 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct S { struct S {
#[serde(rename="x")] #[serde(rename = "x")]
#[serde(rename(deserialize="y"))] //~^^^ HELP: duplicate serde attribute `rename` #[serde(rename(deserialize = "y"))]
//~^^^^ ERROR: duplicate serde attribute `rename`
x: (), x: (),
} }
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct S { struct S {
#[serde(rename(serialize="x"), rename(serialize="y"))] //~^^ HELP: duplicate serde attribute `rename` #[serde(rename(serialize = "x"), rename(serialize = "y"))]
//~^^^ ERROR: duplicate serde attribute `rename`
x: (), x: (),
} }
@@ -9,10 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct S { struct S {
#[serde(rename(serialize="x"))] #[serde(rename(serialize = "x"))]
#[serde(rename="y")] //~^^^ HELP: duplicate serde attribute `rename` #[serde(rename = "y")]
//~^^^^ ERROR: duplicate serde attribute `rename`
x: (), x: (),
} }
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct S { struct S {
#[serde(rename(serialize="x", serialize="y"))] //~^^ HELP: duplicate serde attribute `rename` #[serde(rename(serialize = "x", serialize = "y"))]
//~^^^ ERROR: duplicate serde attribute `rename`
x: (), x: (),
} }
@@ -9,10 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct S { struct S {
#[serde(rename(serialize="x"))] #[serde(rename(serialize = "x"))]
#[serde(rename(serialize="y"))] //~^^^ HELP: duplicate serde attribute `rename` #[serde(rename(serialize = "y"))]
//~^^^^ ERROR: duplicate serde attribute `rename`
x: (), x: (),
} }
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct S { struct S {
#[serde(with = "w", serialize_with = "s")] //~^^ HELP: duplicate serde attribute `serialize_with` #[serde(with = "w", serialize_with = "s")]
//~^^^ ERROR: duplicate serde attribute `serialize_with`
x: (), x: (),
} }
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] cannot be used with tuple variants #[serde(tag = "type")]
//~^^ ERROR: #[serde(tag = "...")] cannot be used with tuple variants
enum E { enum E {
Tuple(u8, u8), Tuple(u8, u8),
} }
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(tag = "type")] //~^ HELP: #[serde(tag = "...")] can only be used on enums #[serde(tag = "type")]
//~^^ ERROR: #[serde(tag = "...")] can only be used on enums
struct S; struct S;
fn main() {} fn main() {}
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(untagged)] #[serde(untagged)]
#[serde(tag = "type")] //~^^ HELP: enum cannot be both untagged and internally tagged #[serde(tag = "type")]
//~^^^ ERROR: enum cannot be both untagged and internally tagged
enum E { enum E {
A(u8), A(u8),
B(String), B(String),
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(untagged)] //~^ HELP: #[serde(untagged)] can only be used on enums #[serde(untagged)]
//~^^ ERROR: #[serde(untagged)] can only be used on enums
struct S; struct S;
fn main() {} fn main() {}
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(field_identifier, variant_identifier)] //~^ HELP: `field_identifier` and `variant_identifier` cannot both be set #[serde(field_identifier, variant_identifier)]
//~^^ ERROR: `field_identifier` and `variant_identifier` cannot both be set
enum F { enum F {
A, A,
B, B,
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(field_identifier)] #[serde(field_identifier)]
struct S; //~^^ HELP: `field_identifier` can only be used on an enum //~^^ ERROR: `field_identifier` can only be used on an enum
struct S;
fn main() {} fn main() {}
@@ -9,11 +9,12 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(field_identifier)] #[serde(field_identifier)]
enum F { enum F {
A, A,
B(u8, u8), //~^^^^ HELP: field_identifier may only contain unit variants B(u8, u8),
//~^^^^^ ERROR: field_identifier may only contain unit variants
} }
fn main() {} fn main() {}
@@ -9,11 +9,12 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(field_identifier)] #[serde(field_identifier)]
enum F { enum F {
A, A,
Other(String), //~^^^^ HELP: `Other` must be the last variant Other(String),
//~^^^^^ ERROR: `Other` must be the last variant
B, B,
} }
@@ -9,10 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
enum F { enum F {
A, A,
#[serde(other)] //~^^^ HELP: #[serde(other)] may only be used inside a field_identifier #[serde(other)]
//~^^^^ ERROR: #[serde(other)] may only be used inside a field_identifier
B, B,
} }
@@ -9,11 +9,12 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(field_identifier)] #[serde(field_identifier)]
enum F { enum F {
A, A,
#[serde(other)] //~^^^^ HELP: #[serde(other)] must be on a unit variant #[serde(other)]
//~^^^^^ ERROR: #[serde(other)] must be on a unit variant
Other(u8, u8), Other(u8, u8),
} }
@@ -9,11 +9,12 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(field_identifier)] #[serde(field_identifier)]
enum F { enum F {
A, A,
#[serde(other)] //~^^^^ HELP: #[serde(other)] must be the last variant #[serde(other)]
//~^^^^^ ERROR: #[serde(other)] must be the last variant
Other, Other,
B, B,
} }
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(field_identifier)] //~^ HELP: field identifiers cannot be serialized #[serde(field_identifier)]
//~^^ ERROR: field identifiers cannot be serialized
enum F { enum F {
A, A,
B, B,
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(variant_identifier)] #[serde(variant_identifier)]
struct S; //~^^ HELP: `variant_identifier` can only be used on an enum //~^^ ERROR: `variant_identifier` can only be used on an enum
struct S;
fn main() {} fn main() {}
@@ -9,11 +9,12 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(variant_identifier)] #[serde(variant_identifier)]
enum F { enum F {
A, A,
B(u8, u8), //~^^^^ HELP: variant_identifier may only contain unit variants B(u8, u8),
//~^^^^^ ERROR: variant_identifier may only contain unit variants
} }
fn main() {} fn main() {}
@@ -9,7 +9,8 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
struct S<'de> { struct S<'de> {
s: &'de str, //~^^ HELP: cannot deserialize when there is a lifetime parameter called 'de //~^^ ERROR: cannot deserialize when there is a lifetime parameter called 'de
s: &'de str,
} }
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
struct S { struct S {
string: String, string: String,
slice: [u8], //~^^^ HELP: cannot deserialize a dynamically sized struct slice: [u8],
//~^^^^ ERROR: cannot deserialize a dynamically sized struct
} }
@@ -15,10 +15,11 @@ mod remote {
} }
} }
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(remote = "remote::S")] #[serde(remote = "remote::S")]
struct S { struct S {
#[serde(getter = "~~~")] //~^^^ HELP: failed to parse path: "~~~" #[serde(getter = "~~~")]
//~^^^^ ERROR: failed to parse path: "~~~"
a: u8, a: u8,
} }
@@ -15,8 +15,9 @@ mod remote {
} }
} }
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(remote = "~~~")] //~^ HELP: failed to parse path: "~~~" #[serde(remote = "~~~")]
//~^^ ERROR: failed to parse path: "~~~"
struct S { struct S {
a: u8, a: u8,
} }
@@ -11,17 +11,18 @@ extern crate serde_derive;
mod remote { mod remote {
pub enum E { pub enum E {
A { a: u8 } A { a: u8 },
} }
} }
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(remote = "remote::E")] #[serde(remote = "remote::E")]
pub enum E { pub enum E {
A { A {
#[serde(getter = "get_a")] //~^^^^ HELP: #[serde(getter = "...")] is not allowed in an enum #[serde(getter = "get_a")]
//~^^^^^ ERROR: #[serde(getter = "...")] is not allowed in an enum
a: u8, a: u8,
} },
} }
fn main() {} fn main() {}
@@ -19,7 +19,8 @@ mod remote {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(remote = "remote::S")] #[serde(remote = "remote::S")]
struct S { struct S {
a: u8, //~^^^ ERROR: missing field `b` in initializer of `remote::S` a: u8,
//~^^^^ ERROR: missing field `b` in initializer of `remote::S`
} }
fn main() {} fn main() {}
@@ -9,9 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct S { struct S {
#[serde(getter = "S::get")] //~^^ HELP: #[serde(getter = "...")] can only be used in structs that have #[serde(remote = "...")] #[serde(getter = "S::get")]
//~^^^ ERROR: #[serde(getter = "...")] can only be used in structs that have #[serde(remote = "...")]
a: u8, a: u8,
} }
@@ -19,7 +19,8 @@ mod remote {
#[serde(remote = "remote::S")] #[serde(remote = "remote::S")]
struct S { struct S {
//~^^^ ERROR: struct `remote::S` has no field named `b` //~^^^ ERROR: struct `remote::S` has no field named `b`
b: u8, //~^^^^ ERROR: no field `b` on type `&remote::S` b: u8,
//~^^^^^ ERROR: no field `b` on type `&remote::S`
} }
fn main() {} fn main() {}
@@ -13,8 +13,10 @@ mod remote {
pub struct S(pub u16); pub struct S(pub u16);
} }
#[derive(Deserialize)] //~ ERROR: mismatched types #[derive(Deserialize)]
#[serde(remote = "remote::S")] #[serde(remote = "remote::S")]
struct S(u8); //~^^ expected u16, found u8 struct S(u8);
//~^^^ ERROR: mismatched types
//~^^^^ expected u16, found u8
fn main() {} fn main() {}
@@ -21,11 +21,13 @@ mod remote {
} }
} }
#[derive(Serialize)] //~ ERROR: mismatched types #[derive(Serialize)]
#[serde(remote = "remote::S")] #[serde(remote = "remote::S")]
struct S { struct S {
#[serde(getter = "remote::S::get")] #[serde(getter = "remote::S::get")]
a: u8, //~^^^^ expected u8, found u16 //~^^^^ ERROR: mismatched types
a: u8,
//~^^^^^^ expected u8, found u16
} }
fn main() {} fn main() {}
@@ -15,10 +15,12 @@ mod remote {
} }
} }
#[derive(Serialize)] //~ ERROR: mismatched types #[derive(Serialize)]
#[serde(remote = "remote::S")] #[serde(remote = "remote::S")]
struct S { struct S {
a: u8, //~^^^ expected u8, found u16 a: u8,
//~^^^^ ERROR: mismatched types
//~^^^^^ expected u8, found u16
} }
fn main() {} fn main() {}
@@ -9,10 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(transparent)] #[serde(transparent)]
//~^^ ERROR: #[serde(transparent)] requires struct to have at most one transparent field
struct S { struct S {
//~^^^ HELP: #[serde(transparent)] requires struct to have at most one transparent field
a: u8, a: u8,
b: u8, b: u8,
} }
@@ -9,10 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(transparent)] #[serde(transparent)]
//~^^ ERROR: #[serde(transparent)] requires at least one field that is neither skipped nor has a default
struct S { struct S {
//~^^^ HELP: #[serde(transparent)] requires at least one field that is neither skipped nor has a default
#[serde(skip)] #[serde(skip)]
a: u8, a: u8,
#[serde(default)] #[serde(default)]
@@ -9,10 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(transparent)] #[serde(transparent)]
//~^^ ERROR: #[serde(transparent)] requires at least one field that is not skipped
struct S { struct S {
//~^^^ HELP: #[serde(transparent)] requires at least one field that is not skipped
#[serde(skip)] #[serde(skip)]
a: u8, a: u8,
} }
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
#[serde(from = "Option<T")] //~^ HELP: failed to parse type: from = "Option<T" #[serde(from = "Option<T")]
//~^^ ERROR: failed to parse type: from = "Option<T"
enum TestOne { enum TestOne {
Testing, Testing,
One, One,
@@ -9,8 +9,9 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(into = "Option<T")] //~^ HELP: failed to parse type: into = "Option<T" #[serde(into = "Option<T")]
//~^^ ERROR: failed to parse type: into = "Option<T"
enum TestOne { enum TestOne {
Testing, Testing,
One, One,
@@ -9,10 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
#[serde(abc="xyz")] //~^ HELP: unknown serde container attribute `abc` #[serde(abc = "xyz")]
//~^^ ERROR: unknown serde container attribute `abc`
struct A { struct A {
x: u32, x: u32,
} }
fn main() { } fn main() {}
@@ -9,10 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
struct C { struct C {
#[serde(abc="xyz")] //~^^ HELP: unknown serde field attribute `abc` #[serde(abc = "xyz")]
//~^^^ ERROR: unknown serde field attribute `abc`
x: u32, x: u32,
} }
fn main() { } fn main() {}
@@ -9,10 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
enum E { enum E {
#[serde(abc="xyz")] //~^^ HELP: unknown serde variant attribute `abc` #[serde(abc = "xyz")]
//~^^^ ERROR: unknown serde variant attribute `abc`
V, V,
} }
fn main() { } fn main() {}
@@ -9,11 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
//~^ HELP: variant `Newtype` cannot have both #[serde(deserialize_with)] and a field 0 marked with #[serde(skip_deserializing)]
enum Enum { enum Enum {
#[serde(deserialize_with = "deserialize_some_newtype_variant")] #[serde(deserialize_with = "deserialize_some_newtype_variant")]
//~^^^ ERROR: variant `Newtype` cannot have both #[serde(deserialize_with)] and a field 0 marked with #[serde(skip_deserializing)]
Newtype(#[serde(skip_deserializing)] String), Newtype(#[serde(skip_deserializing)] String),
} }
fn main() { } fn main() {}
@@ -9,10 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
//~^ HELP: variant `Struct` cannot have both #[serde(deserialize_with)] and a field `f1` marked with #[serde(skip_deserializing)]
enum Enum { enum Enum {
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
//~^^^ ERROR: variant `Struct` cannot have both #[serde(deserialize_with)] and a field `f1` marked with #[serde(skip_deserializing)]
Struct { Struct {
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
f1: String, f1: String,
@@ -20,4 +20,4 @@ enum Enum {
}, },
} }
fn main() { } fn main() {}
@@ -9,11 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
//~^ HELP: variant `Tuple` cannot have both #[serde(deserialize_with)] and a field 0 marked with #[serde(skip_deserializing)]
enum Enum { enum Enum {
#[serde(deserialize_with = "deserialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")]
//~^^^ ERROR: variant `Tuple` cannot have both #[serde(deserialize_with)] and a field 0 marked with #[serde(skip_deserializing)]
Tuple(#[serde(skip_deserializing)] String, u8), Tuple(#[serde(skip_deserializing)] String, u8),
} }
fn main() { } fn main() {}
@@ -9,12 +9,12 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked #[derive(Deserialize)]
//~^ HELP: variant `Unit` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)]
enum Enum { enum Enum {
#[serde(deserialize_with = "deserialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")]
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
//~^^^^ ERROR: variant `Unit` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)]
Unit, Unit,
} }
fn main() { } fn main() {}
@@ -9,11 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: variant `Newtype` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing)]
enum Enum { enum Enum {
#[serde(serialize_with = "serialize_some_newtype_variant")] #[serde(serialize_with = "serialize_some_newtype_variant")]
//~^^^ ERROR: variant `Newtype` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing)]
Newtype(#[serde(skip_serializing)] String), Newtype(#[serde(skip_serializing)] String),
} }
fn main() { } fn main() {}
@@ -9,11 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: variant `Newtype` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing_if)]
enum Enum { enum Enum {
#[serde(serialize_with = "serialize_some_newtype_variant")] #[serde(serialize_with = "serialize_some_newtype_variant")]
//~^^^ ERROR: variant `Newtype` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing_if)]
Newtype(#[serde(skip_serializing_if = "always")] String), Newtype(#[serde(skip_serializing_if = "always")] String),
} }
fn main() { } fn main() {}
@@ -9,10 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: variant `Struct` cannot have both #[serde(serialize_with)] and a field `f1` marked with #[serde(skip_serializing)]
enum Enum { enum Enum {
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
//~^^^ ERROR: variant `Struct` cannot have both #[serde(serialize_with)] and a field `f1` marked with #[serde(skip_serializing)]
Struct { Struct {
#[serde(skip_serializing)] #[serde(skip_serializing)]
f1: String, f1: String,
@@ -20,4 +20,4 @@ enum Enum {
}, },
} }
fn main() { } fn main() {}
@@ -9,10 +9,10 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: variant `Struct` cannot have both #[serde(serialize_with)] and a field `f1` marked with #[serde(skip_serializing_if)]
enum Enum { enum Enum {
#[serde(serialize_with = "serialize_some_newtype_variant")] #[serde(serialize_with = "serialize_some_newtype_variant")]
//~^^^ ERROR: variant `Struct` cannot have both #[serde(serialize_with)] and a field `f1` marked with #[serde(skip_serializing_if)]
Struct { Struct {
#[serde(skip_serializing_if = "always")] #[serde(skip_serializing_if = "always")]
f1: String, f1: String,
@@ -20,4 +20,4 @@ enum Enum {
}, },
} }
fn main() { } fn main() {}
@@ -9,11 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: variant `Tuple` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing)]
enum Enum { enum Enum {
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
//~^^^ ERROR: variant `Tuple` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing)]
Tuple(#[serde(skip_serializing)] String, u8), Tuple(#[serde(skip_serializing)] String, u8),
} }
fn main() { } fn main() {}
@@ -9,11 +9,11 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: variant `Tuple` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing_if)]
enum Enum { enum Enum {
#[serde(serialize_with = "serialize_some_other_variant")] #[serde(serialize_with = "serialize_some_other_variant")]
//~^^^ ERROR: variant `Tuple` cannot have both #[serde(serialize_with)] and a field 0 marked with #[serde(skip_serializing_if)]
Tuple(#[serde(skip_serializing_if = "always")] String, u8), Tuple(#[serde(skip_serializing_if = "always")] String, u8),
} }
fn main() { } fn main() {}
@@ -9,12 +9,12 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[derive(Serialize)] //~ ERROR: proc-macro derive panicked #[derive(Serialize)]
//~^ HELP: variant `Unit` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)]
enum Enum { enum Enum {
#[serde(serialize_with = "serialize_some_unit_variant")] #[serde(serialize_with = "serialize_some_unit_variant")]
#[serde(skip_serializing)] #[serde(skip_serializing)]
//~^^^^ ERROR: variant `Unit` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)]
Unit, Unit,
} }
fn main() { } fn main() {}
-5
View File
@@ -29,8 +29,3 @@ fn run_mode(mode: &'static str) {
fn compile_fail() { fn compile_fail() {
run_mode("compile-fail"); run_mode("compile-fail");
} }
#[test]
fn run_pass() {
run_mode("run-pass");
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deny(identity_op)]
#[macro_use]
extern crate serde_derive;
// The derived implementation uses 0+1 to add up the number of fields
// serialized, which Clippy warns about. If the expansion info is registered
// correctly, the Clippy lint is not triggered.
#[derive(Serialize)]
struct A { b: u8 }
fn main() {}

Some files were not shown because too many files have changed in this diff Show More