Compare commits

...

187 Commits

Author SHA1 Message Date
David Tolnay b6a77c4413 Release 1.0.100 2019-09-07 18:55:50 -07:00
David Tolnay 33438850a6 Merge pull request #1620 from dtolnay/error
Export std error type so no_std data formats don't need a "std" feature
2019-09-07 18:54:34 -07:00
David Tolnay c083cfd65e Export std error type so downstream doesn't need "std" feature 2019-09-04 20:20:36 -07:00
David Tolnay 4cea81f93f Merge pull request #1615 from jamesmunns/patch-1
Add Postcard to the list of Serde Data Formats
2019-08-28 10:17:43 -07:00
James Munns 2d36be753a Add Postcard to the list of Serde Data Formats 2019-08-28 12:23:54 +02:00
David Tolnay 738d29eaa9 Update serde_derive_internals to syn 1.0 2019-08-26 12:29:45 -07:00
David Tolnay b536fb67a4 Merge pull request #1604 from UnHumbleBen/patch-1
Fixed a typo
2019-08-19 03:10:49 -07:00
Benjamin Lee b10c23a950 Fixed a typo 2019-08-18 22:37:28 -07:00
David Tolnay 85a5cf7cb1 Document serde_derive minimum rustc 2019-08-18 18:31:40 -07:00
David Tolnay 192f5cd647 Release 1.0.99 2019-08-16 11:50:19 -07:00
David Tolnay 7dceee64fe Merge pull request #1591 from dtolnay/up
Update to syn/quote 1.0
2019-08-16 11:49:33 -07:00
David Tolnay 8ad6ae71c6 Update serde_derive minimum rustc version to 1.31 2019-08-16 11:31:15 -07:00
David Tolnay 3ea85a28cf Update to syn/quote 1.0 2019-08-16 11:31:15 -07:00
David Tolnay 273ecdb786 Update ui tests on nightly-2019-08-16 2019-08-16 11:30:49 -07:00
David Tolnay de40eb7306 Update serde_derive to use question mark 2019-08-16 11:28:25 -07:00
David Tolnay b9c44073ce Update serde_test to use question mark 2019-08-16 11:25:12 -07:00
David Tolnay d6e5947ad2 Suppress warnings about try! macro 2019-08-16 11:24:22 -07:00
David Tolnay 668651ee01 Format with rustfmt 2019-07-30 2019-07-31 21:19:46 -07:00
David Tolnay fb1cacc10e Update Attr structs to hold symbols 2019-07-31 21:06:36 -07:00
David Tolnay 735e56c26f Use symbols when parsing values out of attribute 2019-07-31 21:06:36 -07:00
David Tolnay 97de3dccbb Factor out attr symbols into constants 2019-07-31 21:06:36 -07:00
David Tolnay 690467cbe2 Release 1.0.98 2019-07-28 10:33:34 -07:00
David Tolnay 71efd8ffda Merge pull request #1590 from dtolnay/manifest
Work around failing to parse manifest in 1.27 and 1.28 builds
2019-07-28 10:32:14 -07:00
David Tolnay 9bb196ae6e Work around failing to parse manifest in 1.27 and 1.28 builds 2019-07-28 10:07:15 -07:00
David Tolnay ce75418e40 Merge pull request #1589 from Flaise/nonzeroi
Add support for NonZeroI* types
2019-07-28 10:02:09 -07:00
Flaise 78c7f09e28 Add build gate for nonzero signed integers so rustc <1.34 still works 2019-07-28 11:44:31 -05:00
David Tolnay e7269ac84e Add travis builds on every version in build.rs 2019-07-28 08:36:06 -07:00
Flaise 34866e20a8 Add support for NonZeroI* types 2019-07-28 09:12:29 -05:00
David Tolnay 3ae2bee272 Release 1.0.97 2019-07-17 14:56:51 -07:00
David Tolnay d0fb958e99 Remove unneeded explicit type parameters in test_from_into_traits 2019-07-17 12:32:34 -07:00
David Tolnay b941c63a53 More typical TryFrom usage for test 2019-07-17 12:31:41 -07:00
David Tolnay cf70c3fb05 Format with rustfmt 2019-06-09 2019-07-17 12:27:26 -07:00
David Tolnay f249e72162 Provide try_from only on 1.34+ 2019-07-17 12:21:18 -07:00
David Tolnay 92e0b62c6b Merge pull request 1526 from fanzeyi/try_from 2019-07-17 12:16:31 -07:00
David Tolnay cf32a5b204 Release 1.0.96 2019-07-17 12:04:19 -07:00
David Tolnay 7b0e06c825 Provide 32 bit atomic impls for emscripten 2019-07-17 11:44:24 -07:00
David Tolnay 3158bf9093 Merge pull request #1581 from Roguelazer/issue-1579
conservatively limit atomic features
2019-07-17 11:01:21 -07:00
James Brown 01fade764c replaced one too many _ with - 2019-07-17 09:57:53 -07:00
James Brown 210c2419be conservatively limit atomic features 2019-07-17 09:19:03 -07:00
David Tolnay da05163d51 Release 1.0.95 2019-07-16 10:08:53 -07:00
David Tolnay f3e2bb5104 Disable 64 bit atomic tests on emscripten 2019-07-16 10:00:44 -07:00
David Tolnay 7a4c1086b5 Emscripten does not have 64 bit atomics 2019-07-16 09:57:00 -07:00
David Tolnay e89feb9635 Test atomics without needing a macro
As a secondary benefit, this avoids a congnitive_complexity lint from
Clippy.
2019-07-16 09:17:36 -07:00
David Tolnay 5f72766c27 Ignore unreadable_literal lint in test code 2019-07-16 09:04:43 -07:00
David Tolnay 85ae57040d One macro to deserialize all atomics 2019-07-16 07:46:44 -07:00
David Tolnay d55a4a279f Deserialize atomics without needing element type 2019-07-16 07:45:41 -07:00
David Tolnay bee9299693 One macro to serialize all atomics 2019-07-16 07:42:42 -07:00
David Tolnay 9529fcec96 Serialize atomics using the primitive's Serialize impl 2019-07-16 07:40:37 -07:00
David Tolnay bcec168e23 Centralize atomic imports 2019-07-16 07:36:16 -07:00
David Tolnay 102a332616 Format with rustfmt 2019-06-09 2019-07-16 07:32:13 -07:00
David Tolnay a280942f02 Add a builder on 1.34 to cover atomic types 2019-07-16 07:29:10 -07:00
David Tolnay 637dba5c2a Merge pull request #1572 from Roguelazer/issue-1496
Implement serialization and deserialization for std::sync::atomic types
2019-07-16 07:28:18 -07:00
David Tolnay 24f292d081 Build alloc feature on 1.36 in travis 2019-07-16 07:22:47 -07:00
David Tolnay fa5c99e48a Alloc crate is no longer unstable 2019-07-16 07:21:09 -07:00
David Tolnay 48f1a2c9b2 Merge pull request #1576 from c410-f3r/alloc-feature
Make `alloc` feature work on stable
2019-07-16 07:19:49 -07:00
Caio 50ebbd63c6 Enable alloc on stable 2019-07-15 14:24:03 -03:00
James Brown 4e5f63ff45 gate atomic serde on rust 1.34 or higher 2019-07-12 13:44:42 -07:00
James Brown de709e72a8 implement deserialization for atomic integer types 2019-07-11 18:18:54 -07:00
James Brown 56d3c8f071 implement serialization for atomic integer types 2019-07-11 17:34:53 -07:00
David Tolnay ce89adecc1 Suppress deprecation warning on mem::uninitialized 2019-07-07 21:19:50 -07:00
David Tolnay bc7a85063d Switch to rustversion 2019-07-07 21:14:11 -07:00
David Tolnay 0574f1e020 Merge pull request #1561 from BurntSushi/ag/update-i128-docs
Update docs for serde_if_integer128
2019-07-01 15:04:54 -07:00
Andrew Gallant f9fdd60e2e Update docs for serde_if_integer128
The docs imply that the only consideration for using the
serde_if_integer128 macro is support for older versions of Rust, but
Serde's build configuration for 128-bit integers is also gated on the
target platform. For example, if Serde is being compiled for an
emscripten target, then it will not provide 128-bit integer APIs.

See also: https://github.com/BurntSushi/rust-csv/issues/158
2019-07-01 10:18:57 -04:00
David Tolnay 1c1eecabc0 Release 1.0.94 2019-06-27 10:55:12 -07:00
David Tolnay abd3fd004e Merge pull request #1559 from dtolnay/ignore-enum
Accept enums in IgnoredAny
2019-06-27 10:54:22 -07:00
David Tolnay 15ee353488 IgnoredAny::visit_enum for old compilers 2019-06-27 10:45:18 -07:00
David Tolnay e75efbfd31 Support ignoring enum with IgnoredAny 2019-06-27 10:29:55 -07:00
David Tolnay 1c97a7ecb3 Add comprehensive test for deserializing IgnoredAny from enum 2019-06-27 10:23:39 -07:00
David Tolnay fccd3e9fba Add deserialization tests for IgnoredAny 2019-06-27 10:07:06 -07:00
David Tolnay 4cb13b33e0 Release 1.0.93 2019-06-23 12:50:17 -07:00
David Tolnay 629802f2ab Merge pull request #1555 from serde-rs/int
Allow integer key in untagged flattened map
2019-06-23 12:49:21 -07:00
David Tolnay afb1754528 Allow integer key in untagged flattened map 2019-06-23 12:09:15 -07:00
David Tolnay dbd67c6c89 Clippy const_static_lifetime lint has been renamed 2019-06-19 01:34:13 -07:00
David Tolnay ed01bdb9dd Remove fixed cast_precision_loss lint 2019-06-15 10:13:05 -07:00
David Tolnay b54821d8ab Alloc feature has been stabilized
warning: the feature `alloc` has been stable since 1.36.0 and no longer requires an attribute to enable
      --> serde/src/lib.rs:84:40
       |
    84 | #![cfg_attr(feature = "alloc", feature(alloc))]
       |                                        ^^^^^
       |
       = note: #[warn(stable_features)] on by default
2019-05-31 21:26:43 -07:00
David Tolnay 89c6a79b6e Suppress a new pedantic lint 2019-05-31 21:25:36 -07:00
David Tolnay cd0412bddc Release 1.0.92 2019-05-31 13:44:01 -07:00
David Tolnay e42262f0f5 Provide ToString for re-export by serde::export 2019-05-31 13:42:22 -07:00
David Tolnay 0a3eeab273 Merge pull request #1543 from jplatte/alloc-de-compile-fix
Fix a compile error in derive(Deserialize) with no_std + alloc
2019-05-31 13:41:07 -07:00
Jonas Platte e4e110e28f Fix a compile error in derive(Deserialize) with no_std + alloc 2019-05-31 22:16:40 +02:00
David Tolnay 0726623389 Ignore bare_trait_objects lint to support old compilers 2019-05-31 11:34:18 -07:00
David Tolnay fd9d334d01 Smaller format for license section 2019-05-18 17:35:47 -07:00
David Tolnay 840eb14121 Merge pull request #1528 from est31/no_variable_names
Don't use variable names
2019-05-17 08:57:14 -07:00
est31 8fef196ee4 Don't use variable names
They aren't needed. This makes the macro a bit simpler
2019-05-17 16:50:41 +02:00
David Tolnay 9c756f1ec0 Disable ui tests on emscripten
These hit a strange error in our Emscripten builder in Travis as well as
locally through cargo web:

    ERROR: failed to execute cargo: Resource temporarily unavailable (os error 11)
2019-05-12 00:28:22 -07:00
Zeyi Fan 4c29eea790 add attribute try_from 2019-05-11 23:31:24 -07:00
David Tolnay 6dd2b4607f Switch to SPDX 2.1 license expression 2019-05-09 15:21:20 -07:00
David Tolnay 1e9ae88f53 Work around "failed to select a version for serde_test_suite"
Without this:

    error: failed to select a version for `serde_test_suite`.
        ... required by package `serde_test_suite-tests v0.0.0`
    versions that meet the requirements `= 0.0.0` are: 0.0.0

    the package `serde_test_suite-tests` depends on `serde_test_suite`, with features: `serde` but `serde_test_suite` does not have these features.

    failed to select a version for `serde_test_suite` which could resolve this conflict

Seems like a Cargo bug -- I will minimize and report.
2019-05-06 22:53:38 -07:00
David Tolnay 5cc3902ab9 Release 1.0.91 2019-05-06 16:27:04 -07:00
David Tolnay c8e09e2d6d Merge pull request #1522 from dtolnay/enum
Support deserializing enum out of MapAccessDeserializer
2019-05-06 16:26:43 -07:00
David Tolnay e2a2ba116c Remove old instructions intended for compiletest 2019-05-06 16:17:30 -07:00
David Tolnay 0a9d24a218 Support deserializing enum out of MapAccessDeserializer 2019-05-06 16:11:28 -07:00
David Tolnay c222183669 Merge pull request #1521 from serde-rs/trybuild
Switch ui tests to trybuild
2019-05-06 10:44:25 -07:00
David Tolnay 140f9beee7 Switch ui tests to trybuild 2019-05-06 10:25:47 -07:00
David Tolnay 28ce892617 Disable compiletest in appveyor
error[E0464]: multiple matching crates for `serde`
      --> $DIR/wrong_getter.rs:15:10
       |
    15 | #[derive(Serialize)]
       |          ^^^^^^^^^
       |
       = note: candidates:
               crate `serde`: /?/C:/projects/serde/test_suite/deps/target/debug/deps/libserde-a1a28acc73b0edde.rlib
               crate `serde`: /?/C:/Users/appveyor/.
2019-04-22 23:18:21 -07:00
David Tolnay 1e6d3ff99b Merge pull request #1512 from dtolnay/off
Temporarily disable compiletest testing in CI
2019-04-22 23:05:54 -07:00
David Tolnay fba1b92cbf Temporarily disable compiletest testing in CI
The nightly compiler just added a dependency on serde so libserde ends
up in the sysroot, breaking crate resolution inside of compiletest. We
will need to figure out how else to run these tests.

    error[E0464]: multiple matching crates for `serde`
      --> $DIR/wrong_ser.rs:9:10
       |
     9 | #[derive(Serialize)]
       |          ^^^^^^^^^
       |
       = note: candidates:
               crate `serde`: /rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libserde-2b75907288aa7c40.rlib
               crate `serde`: /serde/test_suite/deps/target/debug/deps/libserde-33e0a319242344ce.rlib
2019-04-22 22:42:36 -07:00
David Tolnay ce1686379d Update test suite to nightly-2019-04-20 2019-04-19 22:54:59 -07:00
David Tolnay 79a20e9e33 Resolve option_map_unwrap_or_else lint 2019-04-10 22:57:47 -07:00
David Tolnay e9cd73f78e Remove link to hjson
This project has still not been updated to Serde 1.0.
2019-04-08 10:39:55 -07:00
David Tolnay 0be7f36d51 Release 1.0.90 2019-04-03 09:41:38 -07:00
David Tolnay 4c6cb6e359 Match on serde_path to handle Some(path) and None
I find this a bit easier to follow than map + unwrap_or_else.
2019-04-03 09:40:25 -07:00
David Tolnay 82bde8d166 Format with rustfmt 2019-03-27 2019-04-03 09:40:12 -07:00
David Tolnay 465392b618 Merge pull request #1499 from sgrif/sg-custom-serde-path
Allow `#[serde(crate = "...")]` to override `extern crate serde`
2019-04-03 09:32:07 -07:00
David Tolnay f3c6b9f05a Simplify signature of Container::serde_path 2019-04-03 09:18:45 -07:00
David Tolnay 2f1945eaf2 Refer directly to serde_path in Deserialize impl
This makes it not a breaking change if we later want to eliminate
the `use #serde_path as _serde;` line.
2019-04-03 09:16:21 -07:00
Sean Griffin b4d8a55b2a Change serde_path to crate
Also changed the generated code to have at least one thing refer to the
path directly, rather than via `use` -- This shows that the impl *can*
work without `use`, but doesn't actually do all the work to remove the
`use` lines unless we decide we need this feature to work on the 2015
edition
2019-03-28 11:42:50 -06:00
Sean Griffin 0e6ce8fa50 Fix for Rust 1.15 2019-03-20 14:31:49 -06:00
Sean Griffin a295c38ba3 Allow #[serde(serde_path = "...")] to override extern crate serde
This is intended to be used by other crates which provide their own proc
macros and use serde internally. Today there's no consistent way to put
`#[derive(Deserialize)]` on a struct that consistently works, since
crates may be using either `features = ["derive"]` or relying on
`serde_derive` separately.

Even if we assume that everyone is using `features = ["derive"]`,
without this commit, any crate which generates
`#[derive(serde::Deserialize)]` forces its consumers to put `serde` in
their `Cargo.toml`, even if they aren't otherwise using serde for
anything.

Examples of crates which suffer from this in the real world are
tower-web and swirl.

With this feature, it's expected that these crates would have `pub
extern crate serde;` in some accessible path, and add
`#[serde(serde_path = "that_crate::wherever::serde")]` anywhere they
place serde's derives. Those crates would also have to derive
`that_crate::whatever::serde::Deserialize`, or `use` the macros
explicitly beforehand.

The test for this is a little funky, as it's testing this in a way that
is not the intended use case, or even one we want to support. It has its
own module which re-exports all of serde, but defines its own
`Serialize` and `Deserialize` traits. We then test that we generated
impls for those traits, instead of serde's. The only other way to test
this would be to create a new test crate which does not depend on serde,
but instead depends on `serde_derive` and a third crate which publicly
re-exports serde. This feels like way too much overhead for a single
test case, hence the funky test given.

I didn't see anywhere in this repo to document this attribute, so I
assume the docs will have to be done as a separate PR to a separate
repo.

Fixes #1487
2019-03-18 15:20:19 -06:00
David Tolnay 295730ba1e Clippy cyclomatic complexity lint has been renamed 2019-03-09 16:36:51 -08:00
David Tolnay ac0d8f61c5 Use non-preview name of Clippy rustup component 2019-03-01 23:11:06 -08:00
David Tolnay b811588fa0 Release 1.0.89 2019-02-28 17:09:10 -08:00
David Tolnay 5fcdf0ff2b Sort version-conditional imports at the bottom 2019-02-28 16:53:13 -08:00
David Tolnay 650b723da3 Format with rustfmt 2019-02-14 2019-02-28 16:40:54 -08:00
David Tolnay 97920be33a Merge pull request #1486 from vorot93/reverse
impl Serialize and Deserialize for core::cmp::Reverse
2019-02-28 16:39:54 -08:00
David Tolnay 58bbaa9e80 Refer to Option through serde::export in generated code 2019-02-28 16:36:17 -08:00
David Tolnay 94f152730c Merge pull request #1492 from thomaseizinger/1491-clippy-warning
Don't generate code with redundant closures
2019-02-28 16:35:59 -08:00
David Tolnay 535e3d4372 Mention rc feature in list of trait impls in documentation 2019-02-28 01:13:36 -08:00
Thomas Eizinger 2ea43c8986 Don't generate code with redundant closures
Fixes #1491.
2019-02-28 17:30:21 +11:00
Artem Vorotnikov 71fe2a5534 Reverse impls available for Rust >=1.19 2019-02-20 12:56:35 +03:00
Artem Vorotnikov f3ffcfd61e impl Serialize and Deserialize for core::cmp::Reverse 2019-02-20 04:32:55 +03:00
David Tolnay bf27b28554 Simplify running update-references.sh 2019-02-17 10:58:46 -08:00
David Tolnay 344602d27e Make array ser impls macro better fit rustfmt style 2019-02-16 15:22:53 -08:00
David Tolnay 64c483cf80 Release 1.0.88 2019-02-15 19:55:50 -08:00
David Tolnay 19091aacc7 Fix mistaken double negative in flatten error message 2019-02-15 18:56:31 -08:00
David Tolnay ef9028d798 Remove conflict between flatten and skip 2019-02-15 18:39:15 -08:00
David Tolnay 1668cd19d3 Eliminate try!(..).value to improve rustfmt'd code
Rustfmt bails out on the original code, leaving it all on one line.
2019-02-13 09:13:50 -08:00
David Tolnay 134f268cee Release 1.0.87 2019-02-04 07:08:41 +01:00
David Tolnay c473633676 Format with rustfmt 2018-12-10 2019-02-04 00:39:32 +01:00
David Tolnay 6a3a82007c Merge pull request #1474 from jwillbold/master
Fixed #1468, flattened struct fields made structs ignore their tag
2019-02-03 15:37:44 -08:00
Johannes Willbold 1d6ef76cfb Fixed #1468, flattened struct fields made structs ignore their tag 2019-02-03 02:09:37 +01:00
David Tolnay c8e3959435 Release 1.0.86 2019-02-01 21:07:19 -08:00
David Tolnay 796f412a1e Document that Bound<T> impls exist 2019-02-01 21:07:18 -08:00
David Tolnay fa854a2108 Format with rustfmt 2018-12-10 2019-02-01 21:04:08 -08:00
David Tolnay 3a097ff2d2 Deserialize Bound::Unbounded as unit variant 2019-02-01 21:04:07 -08:00
David Tolnay 8463bfc1e5 Remove as yet unrequested range impls 2019-02-01 21:04:06 -08:00
David Tolnay 7a72b4c624 Merge pull request #1466 from 0nkery/master
Impl Serialize/Deserialize for std::ops::{Bound, RangeFrom, RangeTo, RangeToInclusive}
2019-02-01 21:03:55 -08:00
David Tolnay 670c179417 Re-enable deny unused_imports 2019-02-01 17:56:52 -08:00
David Tolnay 1b1d868837 Combine the two clippy lists 2019-02-01 17:56:31 -08:00
David Tolnay d9704d02bb Remove clippy lints that are no longer triggering 2019-02-01 17:53:14 -08:00
David Tolnay 1349548367 Fix indentation of cfg that isn't formatted by rustfmt 2019-02-01 17:48:14 -08:00
Dmitry Shlagoff 18b1604fc8 Fix compatibility issues with syntax and Bound 2019-01-30 00:41:03 +07:00
Dmitry Shlagoff 0def7da5a8 Impl Ser/De for RangeFrom, RangeTo, RangeToInclusive 2019-01-29 20:29:14 +07:00
Dmitry Shlagoff 4bb45c8252 Impl Serialize for Bound<T> 2019-01-29 15:20:27 +07:00
David Tolnay bb99b31eb0 Release 1.0.85 2019-01-18 22:36:49 -08:00
David Tolnay 84397183f3 Fix spelling of alises -> aliases 2019-01-18 22:34:23 -08:00
David Tolnay aeae265777 Simpler way to get single element from vector 2019-01-18 22:33:43 -08:00
David Tolnay a9c5df5da1 Remove unused Clone on attr::Attr 2019-01-18 22:31:25 -08:00
David Tolnay 96576c4de9 Merge pull request #1458 from Lymia/master
Implements alias annotation and allow multiple deserialization renames.
2019-01-18 22:29:57 -08:00
David Tolnay 9ec68e5829 Re-export is no longer just for optional serde cfg 2019-01-18 00:48:05 -08:00
David Tolnay face857d5e Update crates.io readme to 2018 edition 2019-01-18 00:44:17 -08:00
David Tolnay 85a1cc9b4f Merge pull request #1460 from dtolnay/readme
Replace serde_derive with features = ["derive"] in readme
2019-01-18 00:43:25 -08:00
David Tolnay 630501b93d Replace serde_derive with features = ["derive"] in readme 2019-01-18 00:30:01 -08:00
Lymia Aluysia 8bbc2995ca Fix clippy lint in serde_derive 2019-01-15 11:35:26 -06:00
Lymia Aluysia 7d3872df57 Fix compilation on Rust 1.15.x 2019-01-15 11:29:55 -06:00
Lymia Aluysia 1ed228b92b Implements alias annotation and allow multiple deserialization renames. 2019-01-15 11:15:01 -06:00
David Tolnay b605cd1bb9 Make compiletest setup consistent with serde_json 2019-01-12 16:22:23 -08:00
David Tolnay fea4e8e5b6 Release 1.0.84 2018-12-31 23:45:34 -05:00
David Tolnay 1df8b5785b Test with same features in Travis and AppVeyor 2018-12-31 23:31:49 -05:00
David Tolnay 981a75d7c9 Enable extra features in playground 2018-12-31 23:28:10 -05:00
David Tolnay 11cc7014b3 Set all doc tests to 2018 edition 2018-12-31 23:22:13 -05:00
David Tolnay 0b667c88fa Remove unneeded main functions in doc tests
These used to be needed because `#[macro_use] extern crate serde`
couldn't go inside of rustdoc's implicit main function.
2018-12-31 23:22:12 -05:00
David Tolnay 054ab1adaf Update serde documentation to 2018 edition 2018-12-31 23:22:11 -05:00
David Tolnay f1f8386f2e Update serde_derive_internals ignored lints 2018-12-31 22:53:09 -05:00
David Tolnay ba8c3970b0 Use tool lint naming in clippy invocation 2018-12-31 22:51:38 -05:00
David Tolnay 2f36b26a5c Clarify that these lints are ignored 2018-12-31 22:49:38 -05:00
David Tolnay 9b4edb3a1d Address match_ref_pats lint in serde_derive 2018-12-31 22:47:48 -05:00
David Tolnay b8adc5ffa2 Update name of stutter lint in serde_derive 2018-12-31 22:47:18 -05:00
David Tolnay bd90cafda7 Ignore trivially_copy_pass_by_ref lint in serde_derive 2018-12-31 22:47:03 -05:00
David Tolnay 6d43a08a1d Remove dev-dependencies features from serde_test
Apparently Cargo is applying these features to the non-dev dependency on
serde as well. Concluded by running `cargo clean && cargo build` and
observing that serde_derive was getting built.
2018-12-31 22:43:15 -05:00
David Tolnay e71b8598ae Update serde_test examples to 2018 edition 2018-12-31 22:41:23 -05:00
David Tolnay 95d0f437e3 Update ui tests to nightly 2019-01-01 2018-12-31 22:09:07 -05:00
David Tolnay c95ee3968a Format with rustfmt 2018-12-10 2018-12-31 22:09:06 -05:00
David Tolnay c22dd4ada5 Suppress trivially_copy_pass_by_ref lint on fn is_zero 2018-12-31 22:09:05 -05:00
David Tolnay 727a40fc5a Update test suite to use tool attrs 2018-12-31 21:59:40 -05:00
David Tolnay ce84a5f1d3 Update name of deprecated stutter lint 2018-12-31 21:59:39 -05:00
David Tolnay e6fda1c410 Fix clippy command to run against test suite 2018-12-31 21:56:10 -05:00
David Tolnay 294dccc5be Update test suite to 2018 edition 2018-12-31 21:53:37 -05:00
David Tolnay da346a8878 Replace try! macro in test suite 2018-12-31 21:46:14 -05:00
David Tolnay c5ccb995ad Update no_std test to 2018 edition 2018-12-31 21:42:22 -05:00
David Tolnay 05ab569a80 Update ui tests to 2018 edition 2018-12-31 21:38:13 -05:00
David Tolnay ab3f4971f0 Move compiletest out of the unstable feature flag 2018-12-31 21:28:39 -05:00
David Tolnay 47e238aa13 Add missing imports in ui tests
There is a new fallback as of nightly-2018-12-29 that makes these emit a
new error unrelated to Serde.
2018-12-29 00:19:29 -05:00
David Tolnay e49b6c708b Add main function to ui tests without main
These emit a new error not relevant to Serde as of nightly-2018-12-29.
2018-12-29 00:18:55 -05:00
David Tolnay eb7250792b Format with rustfmt 2018-12-10 2018-12-28 12:19:32 -05:00
David Tolnay 7e5066b878 Merge pull request #1450 from motu42/master
Bug fix to support the tag attribute on braced structs with zero fields
2018-12-27 21:48:14 -05:00
Johannes Willbold 889e17816f Bug fix for #1449
Modified serialize_struct_as_struct.
Added test test_internally_tagged_braced_struct_with_zero_fields
2018-12-28 02:50:24 +01:00
256 changed files with 2700 additions and 2070 deletions
+28 -16
View File
@@ -9,7 +9,7 @@ matrix:
- cargo build --no-default-features - cargo build --no-default-features
- cd "${TRAVIS_BUILD_DIR}/serde_test" - cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo build - cargo build
- cargo test - cargo test --features serde/derive,serde/rc
- rust: beta - rust: beta
script: script:
@@ -25,9 +25,7 @@ matrix:
- cargo build --no-default-features - cargo build --no-default-features
- cargo build --no-default-features --features alloc - cargo build --no-default-features --features alloc
- cargo build --no-default-features --features rc,alloc - cargo build --no-default-features --features rc,alloc
- cargo test --features rc,unstable - cargo test --features derive,rc,unstable
- cd "${TRAVIS_BUILD_DIR}/test_suite/deps"
- cargo build
- cd "${TRAVIS_BUILD_DIR}/test_suite" - cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo test --features unstable - cargo test --features unstable
- cd "${TRAVIS_BUILD_DIR}/test_suite/no_std" - cd "${TRAVIS_BUILD_DIR}/test_suite/no_std"
@@ -41,31 +39,45 @@ matrix:
- cd "${TRAVIS_BUILD_DIR}/serde_test" - cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo build - cargo build
- rust: 1.15.0 - rust: 1.19.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo build
- rust: 1.20.0 - rust: 1.20.0
- rust: 1.21.0 - rust: 1.21.0
- rust: 1.25.0 - rust: 1.25.0
- rust: 1.26.0 - rust: 1.26.0
# Work around failing to parse manifest because editions are unstable.
- rust: 1.27.0
before_script: sed -i /test_suite/d Cargo.toml
- rust: 1.28.0
before_script: sed -i /test_suite/d Cargo.toml
- rust: 1.31.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo build
- rust: 1.34.0
- rust: 1.36.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --no-default-features --features alloc
- rust: nightly - rust: nightly
name: Clippy name: Clippy
script: script:
- rustup component add clippy-preview || travis_terminate 0 - rustup component add clippy || travis_terminate 0
- cargo clippy -- -Dclippy - cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde" - cd "${TRAVIS_BUILD_DIR}/serde"
- cargo clippy --features rc,unstable -- -Dclippy - cargo clippy --features rc,unstable -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde_derive" - cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo clippy -- -Dclippy - cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde_test" - cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo clippy -- -Dclippy - cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/test_suite" - cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo clippy --features unstable -- -Dclippy - cargo clippy --tests --features unstable -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/test_suite/no_std" - cd "${TRAVIS_BUILD_DIR}/test_suite/no_std"
- cargo clippy -- -Dclippy - cargo clippy -- -D clippy::all
- rust: nightly - rust: nightly
name: Emscripten name: Emscripten
+20 -24
View File
@@ -1,11 +1,13 @@
# Serde &emsp; [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.13+]][rustc] # Serde &emsp; [![Build Status]][travis] [![Latest Version]][crates.io] [![serde: rustc 1.13+]][Rust 1.13] [![serde_derive: rustc 1.31+]][Rust 1.31]
[Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master [Build Status]: https://api.travis-ci.org/serde-rs/serde.svg?branch=master
[travis]: https://travis-ci.org/serde-rs/serde [travis]: https://travis-ci.org/serde-rs/serde
[Latest Version]: https://img.shields.io/crates/v/serde.svg [Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde [crates.io]: https://crates.io/crates/serde
[Rustc Version 1.13+]: https://img.shields.io/badge/rustc-1.13+-lightgray.svg [serde: rustc 1.13+]: https://img.shields.io/badge/serde-rustc_1.13+-lightgray.svg
[rustc]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html [serde_derive: rustc 1.31+]: https://img.shields.io/badge/serde_derive-rustc_1.31+-lightgray.svg
[Rust 1.13]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
@@ -25,19 +27,17 @@ You may be looking for:
<details> <details>
<summary> <summary>
Click to show Cargo.toml. Click to show Cargo.toml.
<a href="https://play.rust-lang.org/?gist=9003c5b88c1f4989941925d7190c6eec" target="_blank">Run this code in the playground.</a> <a href="https://play.rust-lang.org/?edition=2018&gist=72755f28f99afc95e01d63174b28c1f5" target="_blank">Run this code in the playground.</a>
</summary> </summary>
```toml ```toml
[dependencies] [dependencies]
# The core APIs, including the Serialize and Deserialize traits. Always # The core APIs, including the Serialize and Deserialize traits. Always
# required when using Serde. # required when using Serde. The "derive" feature is only required when
serde = "1.0" # using #[derive(Serialize, Deserialize)] to make Serde work with structs
# and enums defined in your crate.
# Support for #[derive(Serialize, Deserialize)]. Required if you want Serde serde = { version = "1.0", features = ["derive"] }
# to work for structs and enums defined in your crate.
serde_derive = "1.0"
# Each data format lives in its own crate; the sample code below uses JSON # Each data format lives in its own crate; the sample code below uses JSON
# but you may be using a different one. # but you may be using a different one.
@@ -48,11 +48,7 @@ serde_json = "1.0"
<p></p> <p></p>
```rust ```rust
#[macro_use] use serde::{Serialize, Deserialize};
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
struct Point { struct Point {
@@ -87,19 +83,19 @@ good response, we are happy to respond to [GitHub issues][issues] as well.
[irc]: https://wiki.mozilla.org/IRC [irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose [issues]: https://github.com/serde-rs/serde/issues/new/choose
## License <br>
Serde is licensed under either of #### License
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or <sup>
http://www.apache.org/licenses/LICENSE-2.0) Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
* MIT license ([LICENSE-MIT](LICENSE-MIT) or 2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
http://opensource.org/licenses/MIT) </sup>
at your option. <br>
### Contribution
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions. dual licensed as above, without any additional terms or conditions.
</sub>
+2 -4
View File
@@ -23,7 +23,7 @@ for:
- cargo build --no-default-features - cargo build --no-default-features
- cd %APPVEYOR_BUILD_FOLDER%\serde_test - cd %APPVEYOR_BUILD_FOLDER%\serde_test
- cargo build - cargo build
- cargo test - cargo test --features serde/derive,serde/rc
- matrix: - matrix:
only: only:
@@ -34,8 +34,6 @@ for:
- cargo build --no-default-features - cargo build --no-default-features
- cargo build --no-default-features --features alloc - cargo build --no-default-features --features alloc
- cargo build --no-default-features --features rc,alloc - cargo build --no-default-features --features rc,alloc
- cargo test --features rc,unstable - cargo test --features derive,rc,unstable
- cd %APPVEYOR_BUILD_FOLDER%\test_suite\deps
- cargo build
- cd %APPVEYOR_BUILD_FOLDER%\test_suite - cd %APPVEYOR_BUILD_FOLDER%\test_suite
- cargo test --features unstable - cargo test --features unstable
+1 -5
View File
@@ -16,11 +16,7 @@ You may be looking for:
## Serde in action ## Serde in action
```rust ```rust
#[macro_use] use serde::{Serialize, Deserialize};
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
struct Point { struct Point {
+7 -31
View File
@@ -1,8 +1,8 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.83" # remember to update html_root_url version = "1.0.100" # 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 OR Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
homepage = "https://serde.rs" homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
@@ -23,36 +23,16 @@ serde_derive = { version = "1.0", optional = true, path = "../serde_derive" }
[dev-dependencies] [dev-dependencies]
serde_derive = { version = "1.0", path = "../serde_derive" } serde_derive = { version = "1.0", path = "../serde_derive" }
[package.metadata.playground]
features = ["derive", "rc"]
### FEATURES ################################################################# ### FEATURES #################################################################
[features] [features]
default = ["std"] default = ["std"]
# Re-export the derive(Serialize, Deserialize) macros. This is intended for # Provide derive(Serialize, Deserialize) macros.
# library crates that provide optional Serde impls behind a Cargo cfg of their
# 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 ...
#
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>.
@@ -68,11 +48,7 @@ unstable = []
# Provide impls for types in the Rust core allocation and collections library # Provide impls for types in the Rust core allocation and collections library
# including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may # including String, Box<T>, Vec<T>, and Cow<T>. This is a subset of std but may
# be enabled without depending on all of std. # be enabled without depending on all of std.
# alloc = []
# Requires a dependency on the unstable core allocation library:
#
# https://doc.rust-lang.org/alloc/
alloc = ["unstable"]
# Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types # Opt into impls for Rc<T> and Arc<T>. Serializing and deserializing these types
# does not preserve identity and may result in multiple copies of the same data. # does not preserve identity and may result in multiple copies of the same data.
+40
View File
@@ -14,6 +14,21 @@ fn main() {
let target = env::var("TARGET").unwrap(); let target = env::var("TARGET").unwrap();
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten"; let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
// std::collections::Bound was stabilized in Rust 1.17
// but it was moved to core::ops later in Rust 1.26:
// https://doc.rust-lang.org/core/ops/enum.Bound.html
if minor >= 26 {
println!("cargo:rustc-cfg=ops_bound");
} else if minor >= 17 && cfg!(feature = "std") {
println!("cargo:rustc-cfg=collections_bound");
}
// core::cmp::Reverse stabilized in Rust 1.19:
// https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
if minor >= 19 {
println!("cargo:rustc-cfg=core_reverse");
}
// 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 {
@@ -53,6 +68,31 @@ fn main() {
if minor >= 28 { if minor >= 28 {
println!("cargo:rustc-cfg=num_nonzero"); println!("cargo:rustc-cfg=num_nonzero");
} }
// TryFrom, Atomic types, and non-zero signed integers stabilized in Rust 1.34:
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations
if minor >= 34 {
println!("cargo:rustc-cfg=core_try_from");
println!("cargo:rustc-cfg=num_nonzero_signed");
// Whitelist of archs that support std::sync::atomic module. Ideally we
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
// Instead this is based on rustc's src/librustc_target/spec/*.rs.
let has_atomic64 = target.starts_with("x86_64")
|| target.starts_with("i686")
|| target.starts_with("aarch64")
|| target.starts_with("powerpc64")
|| target.starts_with("sparc64")
|| target.starts_with("mips64el");
let has_atomic32 = has_atomic64 || emscripten;
if has_atomic64 {
println!("cargo:rustc-cfg=std_atomic64");
}
if has_atomic32 {
println!("cargo:rustc-cfg=std_atomic");
}
}
} }
fn rustc_minor_version() -> Option<u32> { fn rustc_minor_version() -> Option<u32> {
+12 -3
View File
@@ -1,6 +1,8 @@
use lib::*; use lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; use de::{
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
};
/// An efficient way of discarding data from a deserializer. /// An efficient way of discarding data from a deserializer.
/// ///
@@ -8,7 +10,7 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// any type, except that it does not store any information about the data that /// any type, except that it does not store any information about the data that
/// gets deserialized. /// gets deserialized.
/// ///
/// ```rust /// ```edition2018
/// use std::fmt; /// use std::fmt;
/// use std::marker::PhantomData; /// use std::marker::PhantomData;
/// ///
@@ -21,7 +23,7 @@ use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
/// /// /// ///
/// /// For example to deserialize only the element at index 3: /// /// For example to deserialize only the element at index 3:
/// /// /// ///
/// /// ```rust /// /// ```
/// /// NthElement::new(3).deserialize(deserializer) /// /// NthElement::new(3).deserialize(deserializer)
/// /// ``` /// /// ```
/// pub struct NthElement<T> { /// pub struct NthElement<T> {
@@ -205,6 +207,13 @@ impl<'de> Visitor<'de> for IgnoredAny {
let _ = bytes; let _ = bytes;
Ok(IgnoredAny) Ok(IgnoredAny)
} }
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
data.variant::<IgnoredAny>()?.1.newtype_variant()
}
} }
impl<'de> Deserialize<'de> for IgnoredAny { impl<'de> Deserialize<'de> for IgnoredAny {
+197 -42
View File
@@ -578,6 +578,9 @@ macro_rules! forwarded_impl {
#[cfg(all(feature = "std", de_boxed_c_str))] #[cfg(all(feature = "std", de_boxed_c_str))]
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str); forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
#[cfg(core_reverse)]
forwarded_impl!((T), Reverse<T>, Reverse);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
struct OptionVisitor<T> { struct OptionVisitor<T> {
@@ -787,7 +790,8 @@ seq_impl!(
BinaryHeap::clear, BinaryHeap::clear,
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
BinaryHeap::reserve, BinaryHeap::reserve,
BinaryHeap::push); BinaryHeap::push
);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
@@ -796,7 +800,8 @@ seq_impl!(
BTreeSet::clear, BTreeSet::clear,
BTreeSet::new(), BTreeSet::new(),
nop_reserve, nop_reserve,
BTreeSet::insert); BTreeSet::insert
);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!( seq_impl!(
@@ -962,7 +967,7 @@ impl<'de, T> Deserialize<'de> for [T; 0] {
} }
macro_rules! array_impls { macro_rules! array_impls {
($($len:expr => ($($n:tt $name:ident)+))+) => { ($($len:expr => ($($n:tt)+))+) => {
$( $(
impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]> impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]>
where where
@@ -979,14 +984,12 @@ macro_rules! array_impls {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
$( Ok([$(
let $name = match try!(seq.next_element()) { match try!(seq.next_element()) {
Some(val) => val, Some(val) => val,
None => return Err(Error::invalid_length($n, &self)), None => return Err(Error::invalid_length($n, &self)),
}; }
)+ ),+])
Ok([$($name),+])
} }
} }
@@ -1042,38 +1045,38 @@ macro_rules! array_impls {
} }
array_impls! { array_impls! {
1 => (0 a) 1 => (0)
2 => (0 a 1 b) 2 => (0 1)
3 => (0 a 1 b 2 c) 3 => (0 1 2)
4 => (0 a 1 b 2 c 3 d) 4 => (0 1 2 3)
5 => (0 a 1 b 2 c 3 d 4 e) 5 => (0 1 2 3 4)
6 => (0 a 1 b 2 c 3 d 4 e 5 f) 6 => (0 1 2 3 4 5)
7 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g) 7 => (0 1 2 3 4 5 6)
8 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h) 8 => (0 1 2 3 4 5 6 7)
9 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i) 9 => (0 1 2 3 4 5 6 7 8)
10 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j) 10 => (0 1 2 3 4 5 6 7 8 9)
11 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k) 11 => (0 1 2 3 4 5 6 7 8 9 10)
12 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l) 12 => (0 1 2 3 4 5 6 7 8 9 10 11)
13 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m) 13 => (0 1 2 3 4 5 6 7 8 9 10 11 12)
14 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n) 14 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13)
15 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o) 15 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14)
16 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p) 16 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
17 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q) 17 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16)
18 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r) 18 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17)
19 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s) 19 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
20 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t) 20 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
21 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u) 21 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
22 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v) 22 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21)
23 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w) 23 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22)
24 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x) 24 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23)
25 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y) 25 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24)
26 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z) 26 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25)
27 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa) 27 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26)
28 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab) 28 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27)
29 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac) 29 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28)
30 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad) 30 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29)
31 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae) 31 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30)
32 => (0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 aa 27 ab 28 ac 29 ad 30 ae 31 af) 32 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -2269,6 +2272,117 @@ mod range {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(ops_bound, collections_bound))]
impl<'de, T> Deserialize<'de> for Bound<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
enum Field {
Unbounded,
Included,
Excluded,
}
impl<'de> Deserialize<'de> for Field {
#[inline]
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("`Unbounded`, `Included` or `Excluded`")
}
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
where
E: Error,
{
match value {
0 => Ok(Field::Unbounded),
1 => Ok(Field::Included),
2 => Ok(Field::Excluded),
_ => Err(Error::invalid_value(
Unexpected::Unsigned(value as u64),
&self,
)),
}
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"Unbounded" => Ok(Field::Unbounded),
"Included" => Ok(Field::Included),
"Excluded" => Ok(Field::Excluded),
_ => Err(Error::unknown_variant(value, VARIANTS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
match value {
b"Unbounded" => Ok(Field::Unbounded),
b"Included" => Ok(Field::Included),
b"Excluded" => Ok(Field::Excluded),
_ => match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)),
Err(_) => {
Err(Error::invalid_value(Unexpected::Bytes(value), &self))
}
},
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct BoundVisitor<T>(PhantomData<Bound<T>>);
impl<'de, T> Visitor<'de> for BoundVisitor<T>
where
T: Deserialize<'de>,
{
type Value = Bound<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("enum Bound")
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
match try!(data.variant()) {
(Field::Unbounded, v) => v.unit_variant().map(|()| Bound::Unbounded),
(Field::Included, v) => v.newtype_variant().map(Bound::Included),
(Field::Excluded, v) => v.newtype_variant().map(Bound::Excluded),
}
}
}
const VARIANTS: &'static [&'static str] = &["Unbounded", "Included", "Excluded"];
deserializer.deserialize_enum("Bound", VARIANTS, BoundVisitor(PhantomData))
}
}
////////////////////////////////////////////////////////////////////////////////
macro_rules! nonzero_integers { macro_rules! nonzero_integers {
( $( $T: ident, )+ ) => { ( $( $T: ident, )+ ) => {
$( $(
@@ -2290,7 +2404,6 @@ macro_rules! nonzero_integers {
} }
nonzero_integers! { nonzero_integers! {
// Not including signed NonZeroI* since they might be removed
NonZeroU8, NonZeroU8,
NonZeroU16, NonZeroU16,
NonZeroU32, NonZeroU32,
@@ -2298,12 +2411,26 @@ nonzero_integers! {
NonZeroUsize, NonZeroUsize,
} }
#[cfg(num_nonzero_signed)]
nonzero_integers! {
NonZeroI8,
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroIsize,
}
// Currently 128-bit integers do not work on Emscripten targets so we need an // Currently 128-bit integers do not work on Emscripten targets so we need an
// additional `#[cfg]` // additional `#[cfg]`
serde_if_integer128! { serde_if_integer128! {
nonzero_integers! { nonzero_integers! {
NonZeroU128, NonZeroU128,
} }
#[cfg(num_nonzero_signed)]
nonzero_integers! {
NonZeroI128,
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -2431,3 +2558,31 @@ where
Deserialize::deserialize(deserializer).map(Wrapping) Deserialize::deserialize(deserializer).map(Wrapping)
} }
} }
#[cfg(all(feature = "std", std_atomic))]
macro_rules! atomic_impl {
($($ty:ident)*) => {
$(
impl<'de> Deserialize<'de> for $ty {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Deserialize::deserialize(deserializer).map(Self::new)
}
}
)*
};
}
#[cfg(all(feature = "std", std_atomic))]
atomic_impl! {
AtomicBool
AtomicI8 AtomicI16 AtomicI32 AtomicIsize
AtomicU8 AtomicU16 AtomicU32 AtomicUsize
}
#[cfg(all(feature = "std", std_atomic64))]
atomic_impl! {
AtomicI64 AtomicU64
}
+31 -29
View File
@@ -59,13 +59,13 @@
//! - Box\<T\> //! - Box\<T\>
//! - Box\<\[T\]\> //! - Box\<\[T\]\>
//! - Box\<str\> //! - Box\<str\>
//! - Rc\<T\>
//! - Arc\<T\>
//! - Cow\<'a, T\> //! - Cow\<'a, T\>
//! - Cell\<T\> //! - Cell\<T\>
//! - RefCell\<T\> //! - RefCell\<T\>
//! - Mutex\<T\> //! - Mutex\<T\>
//! - RwLock\<T\> //! - RwLock\<T\>
//! - Rc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - Arc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - **Collection types**: //! - **Collection types**:
//! - BTreeMap\<K, V\> //! - BTreeMap\<K, V\>
//! - BTreeSet\<T\> //! - BTreeSet\<T\>
@@ -89,6 +89,7 @@
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - RangeInclusive\<T\> //! - RangeInclusive\<T\>
//! - Bound\<T\>
//! - num::NonZero* //! - num::NonZero*
//! - `!` *(unstable)* //! - `!` *(unstable)*
//! - **Net types**: //! - **Net types**:
@@ -124,6 +125,13 @@ mod utf8;
pub use self::ignored_any::IgnoredAny; pub use self::ignored_any::IgnoredAny;
#[cfg(feature = "std")]
#[doc(no_inline)]
pub use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! declare_error_trait { macro_rules! declare_error_trait {
@@ -153,7 +161,7 @@ macro_rules! declare_error_trait {
/// ///
/// The message should not be capitalized and should not end with a period. /// The message should not be capitalized and should not end with a period.
/// ///
/// ```rust /// ```edition2018
/// # use std::str::FromStr; /// # use std::str::FromStr;
/// # /// #
/// # struct IpAddr; /// # struct IpAddr;
@@ -173,7 +181,7 @@ macro_rules! declare_error_trait {
/// where /// where
/// D: Deserializer<'de>, /// D: Deserializer<'de>,
/// { /// {
/// let s = try!(String::deserialize(deserializer)); /// let s = String::deserialize(deserializer)?;
/// s.parse().map_err(de::Error::custom) /// s.parse().map_err(de::Error::custom)
/// } /// }
/// } /// }
@@ -287,7 +295,7 @@ macro_rules! declare_error_trait {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
declare_error_trait!(Error: Sized + error::Error); declare_error_trait!(Error: Sized + StdError);
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
declare_error_trait!(Error: Sized + Debug + Display); declare_error_trait!(Error: Sized + Debug + Display);
@@ -298,7 +306,7 @@ declare_error_trait!(Error: Sized + Debug + Display);
/// This is used as an argument to the `invalid_type`, `invalid_value`, and /// This is used as an argument to the `invalid_type`, `invalid_value`, and
/// `invalid_length` methods of the `Error` trait to build error messages. /// `invalid_length` methods of the `Error` trait to build error messages.
/// ///
/// ```rust /// ```edition2018
/// # use std::fmt; /// # use std::fmt;
/// # /// #
/// # use serde::de::{self, Unexpected, Visitor}; /// # use serde::de::{self, Unexpected, Visitor};
@@ -423,7 +431,7 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// Within the context of a `Visitor` implementation, the `Visitor` itself /// Within the context of a `Visitor` implementation, the `Visitor` itself
/// (`&self`) is an implementation of this trait. /// (`&self`) is an implementation of this trait.
/// ///
/// ```rust /// ```edition2018
/// # use std::fmt; /// # use std::fmt;
/// # /// #
/// # use serde::de::{self, Unexpected, Visitor}; /// # use serde::de::{self, Unexpected, Visitor};
@@ -448,7 +456,7 @@ impl<'a> fmt::Display for Unexpected<'a> {
/// ///
/// Outside of a `Visitor`, `&"..."` can be used. /// Outside of a `Visitor`, `&"..."` can be used.
/// ///
/// ```rust /// ```edition2018
/// # use serde::de::{self, Unexpected}; /// # use serde::de::{self, Unexpected};
/// # /// #
/// # fn example<E>() -> Result<(), E> /// # fn example<E>() -> Result<(), E>
@@ -569,7 +577,7 @@ pub trait Deserialize<'de>: Sized {
/// from the input string, but a `from_reader` function may only deserialize /// from the input string, but a `from_reader` function may only deserialize
/// owned data. /// owned data.
/// ///
/// ```rust /// ```edition2018
/// # use serde::de::{Deserialize, DeserializeOwned}; /// # use serde::de::{Deserialize, DeserializeOwned};
/// # use std::io::{Read, Result}; /// # use std::io::{Read, Result};
/// # /// #
@@ -608,7 +616,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// ///
/// The canonical API for stateless deserialization looks like this: /// The canonical API for stateless deserialization looks like this:
/// ///
/// ```rust /// ```edition2018
/// # use serde::Deserialize; /// # use serde::Deserialize;
/// # /// #
/// # enum Error {} /// # enum Error {}
@@ -622,7 +630,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// Adjusting an API like this to support stateful deserialization is a matter /// Adjusting an API like this to support stateful deserialization is a matter
/// of accepting a seed as input: /// of accepting a seed as input:
/// ///
/// ```rust /// ```edition2018
/// # use serde::de::DeserializeSeed; /// # use serde::de::DeserializeSeed;
/// # /// #
/// # enum Error {} /// # enum Error {}
@@ -655,7 +663,7 @@ impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}
/// into it. This requires stateful deserialization using the `DeserializeSeed` /// into it. This requires stateful deserialization using the `DeserializeSeed`
/// trait. /// trait.
/// ///
/// ```rust /// ```edition2018
/// use std::fmt; /// use std::fmt;
/// use std::marker::PhantomData; /// use std::marker::PhantomData;
/// ///
@@ -786,7 +794,7 @@ where
/// ///
/// 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 /// data model], which is a way to categorize every Rust data type into one of
/// 29 possible types. Each method of the `Serializer` trait corresponds to one /// 29 possible types. Each method of the `Deserializer` trait corresponds to one
/// of 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
@@ -1145,7 +1153,7 @@ pub trait Deserializer<'de>: Sized {
/// human-readable one and binary formats like Bincode will prefer the /// human-readable one and binary formats like Bincode will prefer the
/// compact one. /// compact one.
/// ///
/// ``` /// ```edition2018
/// # use std::ops::Add; /// # use std::ops::Add;
/// # use std::str::FromStr; /// # use std::str::FromStr;
/// # /// #
@@ -1222,7 +1230,7 @@ pub trait Deserializer<'de>: Sized {
/// ///
/// # Example /// # Example
/// ///
/// ```rust /// ```edition2018
/// # use std::fmt; /// # use std::fmt;
/// # /// #
/// # use serde::de::{self, Unexpected, Visitor}; /// # use serde::de::{self, Unexpected, Visitor};
@@ -1263,7 +1271,7 @@ pub trait Visitor<'de>: Sized {
/// "an integer between 0 and 64". The message should not be capitalized and /// "an integer between 0 and 64". The message should not be capitalized and
/// should not end with a period. /// should not end with a period.
/// ///
/// ```rust /// ```edition2018
/// # use std::fmt; /// # use std::fmt;
/// # /// #
/// # struct S { /// # struct S {
@@ -2004,7 +2012,7 @@ pub trait VariantAccess<'de>: Sized {
/// If the data contains a different type of variant, the following /// If the data contains a different type of variant, the following
/// `invalid_type` error should be constructed: /// `invalid_type` error should be constructed:
/// ///
/// ```rust /// ```edition2018
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
/// # /// #
/// # struct X; /// # struct X;
@@ -2044,7 +2052,7 @@ pub trait VariantAccess<'de>: Sized {
/// If the data contains a different type of variant, the following /// If the data contains a different type of variant, the following
/// `invalid_type` error should be constructed: /// `invalid_type` error should be constructed:
/// ///
/// ```rust /// ```edition2018
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
/// # /// #
/// # struct X; /// # struct X;
@@ -2100,7 +2108,7 @@ pub trait VariantAccess<'de>: Sized {
/// If the data contains a different type of variant, the following /// If the data contains a different type of variant, the following
/// `invalid_type` error should be constructed: /// `invalid_type` error should be constructed:
/// ///
/// ```rust /// ```edition2018
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
/// # /// #
/// # struct X; /// # struct X;
@@ -2147,7 +2155,7 @@ pub trait VariantAccess<'de>: Sized {
/// If the data contains a different type of variant, the following /// If the data contains a different type of variant, the following
/// `invalid_type` error should be constructed: /// `invalid_type` error should be constructed:
/// ///
/// ```rust /// ```edition2018
/// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected};
/// # /// #
/// # struct X; /// # struct X;
@@ -2207,14 +2215,10 @@ pub trait VariantAccess<'de>: Sized {
/// ///
/// # Example /// # Example
/// ///
/// ```rust /// ```edition2018
/// #[macro_use]
/// extern crate serde_derive;
///
/// extern crate serde;
///
/// use std::str::FromStr; /// use std::str::FromStr;
/// use serde::de::{value, Deserialize, IntoDeserializer}; /// use serde::Deserialize;
/// use serde::de::{value, IntoDeserializer};
/// ///
/// #[derive(Deserialize)] /// #[derive(Deserialize)]
/// enum Setting { /// enum Setting {
@@ -2229,8 +2233,6 @@ pub trait VariantAccess<'de>: Sized {
/// Self::deserialize(s.into_deserializer()) /// Self::deserialize(s.into_deserializer())
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
pub trait IntoDeserializer<'de, E: Error = value::Error> { pub trait IntoDeserializer<'de, E: Error = value::Error> {
/// The type of the deserializer being converted into. /// The type of the deserializer being converted into.
+121 -11
View File
@@ -1,14 +1,10 @@
//! Building blocks for deserializing basic values using the `IntoDeserializer` //! Building blocks for deserializing basic values using the `IntoDeserializer`
//! trait. //! trait.
//! //!
//! ```rust //! ```edition2018
//! #[macro_use]
//! extern crate serde_derive;
//!
//! extern crate serde;
//!
//! use std::str::FromStr; //! use std::str::FromStr;
//! use serde::de::{value, Deserialize, IntoDeserializer}; //! use serde::Deserialize;
//! use serde::de::{value, IntoDeserializer};
//! //!
//! #[derive(Deserialize)] //! #[derive(Deserialize)]
//! enum Setting { //! enum Setting {
@@ -23,8 +19,6 @@
//! Self::deserialize(s.into_deserializer()) //! Self::deserialize(s.into_deserializer())
//! } //! }
//! } //! }
//! #
//! # fn main() {}
//! ``` //! ```
use lib::*; use lib::*;
@@ -1293,10 +1287,40 @@ where
visitor.visit_map(self.map) visitor.visit_map(self.map)
} }
fn deserialize_enum<V>(
self,
_name: &str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_enum(self)
}
forward_to_deserialize_any! { forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string 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 bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any tuple_struct map struct identifier ignored_any
}
}
impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer<A>
where
A: de::MapAccess<'de>,
{
type Error = A::Error;
type Variant = private::MapAsEnum<A>;
fn variant_seed<T>(mut self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.map.next_key_seed(seed)? {
Some(key) => Ok((key, private::map_as_enum(self.map))),
None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")),
}
} }
} }
@@ -1305,7 +1329,7 @@ where
mod private { mod private {
use lib::*; use lib::*;
use de::{self, Unexpected}; use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct UnitOnly<E> { pub struct UnitOnly<E> {
@@ -1366,6 +1390,92 @@ mod private {
} }
} }
#[derive(Clone, Debug)]
pub struct MapAsEnum<A> {
map: A,
}
pub fn map_as_enum<A>(map: A) -> MapAsEnum<A> {
MapAsEnum { map: map }
}
impl<'de, A> VariantAccess<'de> for MapAsEnum<A>
where
A: MapAccess<'de>,
{
type Error = A::Error;
fn unit_variant(mut self) -> Result<(), Self::Error> {
self.map.next_value()
}
fn newtype_variant_seed<T>(mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
self.map.next_value_seed(seed)
}
fn tuple_variant<V>(mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.map.next_value_seed(SeedTupleVariant {
len: len,
visitor: visitor,
})
}
fn struct_variant<V>(
mut self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
self.map
.next_value_seed(SeedStructVariant { visitor: visitor })
}
}
struct SeedTupleVariant<V> {
len: usize,
visitor: V,
}
impl<'de, V> DeserializeSeed<'de> for SeedTupleVariant<V>
where
V: Visitor<'de>,
{
type Value = V::Value;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple(self.len, self.visitor)
}
}
struct SeedStructVariant<V> {
visitor: V,
}
impl<'de, V> DeserializeSeed<'de> for SeedStructVariant<V>
where
V: Visitor<'de>,
{
type Value = V::Value;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(self.visitor)
}
}
/// Avoid having to restate the generic types on `MapDeserializer`. The /// Avoid having to restate the generic types on `MapDeserializer`. The
/// `Iterator::Item` contains enough information to figure out K and V. /// `Iterator::Item` contains enough information to figure out K and V.
pub trait Pair { pub trait Pair {
+4 -1
View File
@@ -9,7 +9,10 @@ pub use lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy; pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::Vec; pub use lib::{ToString, Vec};
#[cfg(core_try_from)]
pub use lib::convert::TryFrom;
mod string { mod string {
use lib::*; use lib::*;
+12 -16
View File
@@ -1,22 +1,20 @@
/// Conditional compilation depending on whether Serde is built with support for /// Conditional compilation depending on whether Serde is built with support for
/// 128-bit integers. /// 128-bit integers.
/// ///
/// Data formats that wish to support Rust compiler versions older than 1.26 may /// Data formats that wish to support Rust compiler versions older than 1.26
/// place the i128 / u128 methods of their Serializer and Deserializer behind /// (or targets that lack 128-bit integers) may place the i128 / u128 methods
/// this macro. /// of their Serializer and Deserializer behind this macro.
/// ///
/// Data formats that require a minimum Rust compiler version of at least 1.26 /// Data formats that require a minimum Rust compiler version of at least 1.26,
/// do not need to bother with this macro and may assume support for 128-bit /// or do not target platforms that lack 128-bit integers, do not need to
/// integers. /// bother with this macro and may assume support for 128-bit integers.
/// ///
/// ```rust /// ```edition2018
/// #[macro_use]
/// extern crate serde;
///
/// use serde::Serializer;
/// # use serde::private::ser::Error; /// # use serde::private::ser::Error;
/// # /// #
/// # struct MySerializer; /// # struct MySerializer;
/// #
/// use serde::{serde_if_integer128, Serializer};
/// ///
/// impl Serializer for MySerializer { /// impl Serializer for MySerializer {
/// type Ok = (); /// type Ok = ();
@@ -41,20 +39,18 @@
/// } /// }
/// } /// }
/// # /// #
/// # __serialize_unimplemented! { /// # serde::__serialize_unimplemented! {
/// # bool i8 i16 i32 u8 u16 u32 u64 f32 f64 char str bytes none some /// # bool i8 i16 i32 u8 u16 u32 u64 f32 f64 char str bytes none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant seq /// # unit unit_struct unit_variant newtype_struct newtype_variant seq
/// # tuple tuple_struct tuple_variant map struct struct_variant /// # tuple tuple_struct tuple_variant map struct struct_variant
/// # } /// # }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
/// ///
/// When Serde is built with support for 128-bit integers, this macro expands /// When Serde is built with support for 128-bit integers, this macro expands
/// transparently into just the input tokens. /// transparently into just the input tokens.
/// ///
/// ```rust /// ```edition2018
/// macro_rules! serde_if_integer128 { /// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => { /// ($($tt:tt)*) => {
/// $($tt)* /// $($tt)*
@@ -65,7 +61,7 @@
/// When built without support for 128-bit integers, this macro expands to /// When built without support for 128-bit integers, this macro expands to
/// nothing. /// nothing.
/// ///
/// ```rust /// ```edition2018
/// macro_rules! serde_if_integer128 { /// macro_rules! serde_if_integer128 {
/// ($($tt:tt)*) => {}; /// ($($tt:tt)*) => {};
/// } /// }
+49 -80
View File
@@ -46,13 +46,13 @@
//! - [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 //! - [Avro], a binary format used within Apache Hadoop, with support for schema
//! definition. //! definition.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [JSON5], A superset of JSON including some productions from ES5. //! - [JSON5], A superset of JSON including some productions from ES5.
//! - [URL], the x-www-form-urlencoded format. //! - [URL], the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs. //! - [Envy], a way to deserialize environment variables into Rust structs.
//! *(deserialization only)* //! *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into //! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//! Rust structs. *(deserialization only)* //! Rust structs. *(deserialization only)*
//! - [Postcard], a `no_std` and embedded-systems friendly compact binary format.
//! //!
//! [JSON]: https://github.com/serde-rs/json //! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode //! [Bincode]: https://github.com/TyOverby/bincode
@@ -64,18 +64,18 @@
//! [RON]: https://github.com/ron-rs/ron //! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs //! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs //! [Avro]: https://github.com/flavray/avro-rs
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [JSON5]: https://github.com/callum-oakley/json5-rs //! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://github.com/nox/serde_urlencoded //! [URL]: https://github.com/nox/serde_urlencoded
//! [Envy]: https://github.com/softprops/envy //! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store //! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html //! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html //! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html
//! [Postcard]: https://github.com/jamesmunns/postcard
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// 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.83")] #![doc(html_root_url = "https://docs.rs/serde/1.0.100")]
// 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
@@ -83,55 +83,38 @@
// //
// https://github.com/serde-rs/serde/issues/812 // https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))] #![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))] #![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints // Ignored clippy and clippy_pedantic lints
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
cast_lossless, // not available in our oldest supported compiler
const_static_lifetime, checked_conversions,
doc_markdown, empty_enum,
linkedlist,
needless_pass_by_value,
redundant_field_names, redundant_field_names,
redundant_static_lifetimes,
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_sign_loss,
// things are often more readable this way
cast_lossless,
module_name_repetitions,
single_match_else,
type_complexity, type_complexity,
unreadable_literal, use_self,
zero_prefixed_literal zero_prefixed_literal,
// not practical
needless_pass_by_value,
similar_names,
// preference
doc_markdown,
) )
)] )]
// Whitelisted clippy_pedantic lints // Rustc lints.
#![cfg_attr(feature = "cargo-clippy", allow( #![deny(missing_docs, unused_imports)]
// integer and float ser/de requires these sorts of casts
cast_possible_truncation,
cast_possible_wrap,
cast_precision_loss,
cast_sign_loss,
// simplifies some macros
invalid_upcast_comparisons,
// things are often more readable this way
decimal_literal_representation,
option_unwrap_used,
result_unwrap_used,
shadow_reuse,
single_match_else,
stutter,
use_self,
// not practical
indexing_slicing,
many_single_char_names,
missing_docs_in_private_items,
similar_names,
// alternative is not stable
empty_enum,
use_debug,
))]
// Blacklisted Rust lints.
//
// Compiler bug involving unused_imports:
// https://github.com/rust-lang/rust/issues/51661
#![deny(missing_docs, /*unused_imports*/)]
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -172,7 +155,7 @@ mod lib {
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::string::{String, ToString}; pub use alloc::string::{String, ToString};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::string::String; pub use std::string::{String, ToString};
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::vec::Vec; pub use alloc::vec::Vec;
@@ -219,11 +202,28 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::time::{SystemTime, UNIX_EPOCH}; pub use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(any(core_duration, feature = "std"))] #[cfg(all(feature = "std", collections_bound))]
pub use self::core::time::Duration; pub use std::collections::Bound;
#[cfg(core_reverse)]
pub use self::core::cmp::Reverse;
#[cfg(ops_bound)]
pub use self::core::ops::Bound;
#[cfg(range_inclusive)] #[cfg(range_inclusive)]
pub use self::core::ops::RangeInclusive; pub use self::core::ops::RangeInclusive;
#[cfg(all(feature = "std", std_atomic))]
pub use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize, Ordering,
};
#[cfg(all(feature = "std", std_atomic64))]
pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(any(core_duration, feature = "std"))]
pub use self::core::time::Duration;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -250,42 +250,11 @@ pub mod export;
#[doc(hidden)] #[doc(hidden)]
pub mod private; pub mod private;
#[cfg(not(feature = "std"))]
mod std_error;
// Re-export #[derive(Serialize, Deserialize)]. // Re-export #[derive(Serialize, Deserialize)].
// //
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
// [features]
// serde-impls = ["serde", "serde_derive"]
//
// [dependencies]
// serde = { version = "1.0", optional = true }
// serde_derive = { version = "1.0", optional = true }
//
// # Used like this:
// # #[cfg(feature = "serde-impls")]
// # #[macro_use]
// # extern crate serde_derive;
// #
// # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
// # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
// [dependencies]
// serde = { version = "1.0", optional = true, features = ["derive"] }
//
// # Used like this:
// # #[cfg(feature = "serde")]
// # #[macro_use]
// # extern crate serde;
// #
// # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
// # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would // The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They // be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std. // would need to disable default features and then explicitly re-enable std.
+6 -18
View File
@@ -11,10 +11,8 @@
/// input. This requires repetitive implementations of all the [`Deserializer`] /// input. This requires repetitive implementations of all the [`Deserializer`]
/// trait methods. /// trait methods.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::forward_to_deserialize_any;
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor}; /// # use serde::de::{value, Deserializer, Visitor};
/// # /// #
/// # struct MyDeserializer; /// # struct MyDeserializer;
@@ -43,18 +41,14 @@
/// # tuple_struct map struct enum identifier ignored_any /// # tuple_struct map struct enum identifier ignored_any
/// # } /// # }
/// # } /// # }
/// #
/// # fn main() {}
/// ``` /// ```
/// ///
/// The `forward_to_deserialize_any!` macro implements these simple forwarding /// The `forward_to_deserialize_any!` macro implements these simple forwarding
/// methods so that they forward directly to [`Deserializer::deserialize_any`]. /// methods so that they forward directly to [`Deserializer::deserialize_any`].
/// You can choose which methods to forward. /// You can choose which methods to forward.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::forward_to_deserialize_any;
/// # extern crate serde;
/// #
/// # use serde::de::{value, Deserializer, Visitor}; /// # use serde::de::{value, Deserializer, Visitor};
/// # /// #
/// # struct MyDeserializer; /// # struct MyDeserializer;
@@ -77,8 +71,6 @@
/// tuple_struct map struct enum identifier ignored_any /// tuple_struct map struct enum identifier ignored_any
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
/// ///
/// The macro assumes the convention that your `Deserializer` lifetime parameter /// The macro assumes the convention that your `Deserializer` lifetime parameter
@@ -86,12 +78,10 @@
/// called `V`. A different type parameter and a different lifetime can be /// called `V`. A different type parameter and a different lifetime can be
/// specified explicitly if necessary. /// specified explicitly if necessary.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// # /// #
/// # use serde::forward_to_deserialize_any;
/// # use serde::de::{value, Deserializer, Visitor}; /// # use serde::de::{value, Deserializer, Visitor};
/// # /// #
/// # struct MyDeserializer<V>(PhantomData<V>); /// # struct MyDeserializer<V>(PhantomData<V>);
@@ -113,8 +103,6 @@
/// tuple_struct map struct enum identifier ignored_any /// tuple_struct map struct enum identifier ignored_any
/// } /// }
/// # } /// # }
/// #
/// # fn main() {}
/// ``` /// ```
/// ///
/// [`Deserializer`]: trait.Deserializer.html /// [`Deserializer`]: trait.Deserializer.html
+3 -1
View File
@@ -1420,6 +1420,7 @@ mod content {
Content::ByteBuf(v) => visitor.visit_byte_buf(v), Content::ByteBuf(v) => visitor.visit_byte_buf(v),
Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
Content::U8(v) => visitor.visit_u8(v), Content::U8(v) => visitor.visit_u8(v),
Content::U64(v) => visitor.visit_u64(v),
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
@@ -2123,6 +2124,7 @@ mod content {
Content::ByteBuf(ref v) => visitor.visit_bytes(v), Content::ByteBuf(ref v) => visitor.visit_bytes(v),
Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
Content::U8(v) => visitor.visit_u8(v), Content::U8(v) => visitor.visit_u8(v),
Content::U64(v) => visitor.visit_u64(v),
_ => Err(self.invalid_type(&visitor)), _ => Err(self.invalid_type(&visitor)),
} }
} }
@@ -2709,7 +2711,7 @@ where
} }
Err(Error::custom(format_args!( Err(Error::custom(format_args!(
"no variant of enum {} not found in flattened data", "no variant of enum {} found in flattened data",
name name
))) )))
} }
+88 -5
View File
@@ -160,10 +160,12 @@ macro_rules! array_impls {
} }
} }
array_impls!(01 02 03 04 05 06 07 08 09 10 array_impls! {
11 12 13 14 15 16 17 18 19 20 01 02 03 04 05 06 07 08 09 10
21 22 23 24 25 26 27 28 29 30 11 12 13 14 15 16 17 18 19 20
31 32); 21 22 23 24 25 26 27 28 29 30
31 32
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -256,6 +258,29 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(ops_bound, collections_bound))]
impl<T> Serialize for Bound<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Bound::Unbounded => serializer.serialize_unit_variant("Bound", 0, "Unbounded"),
Bound::Included(ref value) => {
serializer.serialize_newtype_variant("Bound", 1, "Included", value)
}
Bound::Excluded(ref value) => {
serializer.serialize_newtype_variant("Bound", 2, "Excluded", value)
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
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>
@@ -456,7 +481,6 @@ macro_rules! nonzero_integers {
} }
nonzero_integers! { nonzero_integers! {
// Not including signed NonZeroI* since they might be removed
NonZeroU8, NonZeroU8,
NonZeroU16, NonZeroU16,
NonZeroU32, NonZeroU32,
@@ -464,12 +488,26 @@ nonzero_integers! {
NonZeroUsize, NonZeroUsize,
} }
#[cfg(num_nonzero_signed)]
nonzero_integers! {
NonZeroI8,
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroIsize,
}
// Currently 128-bit integers do not work on Emscripten targets so we need an // Currently 128-bit integers do not work on Emscripten targets so we need an
// additional `#[cfg]` // additional `#[cfg]`
serde_if_integer128! { serde_if_integer128! {
nonzero_integers! { nonzero_integers! {
NonZeroU128, NonZeroU128,
} }
#[cfg(num_nonzero_signed)]
nonzero_integers! {
NonZeroI128,
}
} }
impl<T> Serialize for Cell<T> impl<T> Serialize for Cell<T>
@@ -595,6 +633,7 @@ impl Serialize for SystemTime {
#[cfg(feature = "std")] #[cfg(feature = "std")]
macro_rules! serialize_display_bounded_length { macro_rules! serialize_display_bounded_length {
($value:expr, $max:expr, $serializer:expr) => {{ ($value:expr, $max:expr, $serializer:expr) => {{
#[allow(deprecated)]
let mut buffer: [u8; $max] = unsafe { mem::uninitialized() }; let mut buffer: [u8; $max] = unsafe { mem::uninitialized() };
let remaining_len = { let remaining_len = {
let mut remaining = &mut buffer[..]; let mut remaining = &mut buffer[..];
@@ -799,3 +838,47 @@ where
self.0.serialize(serializer) self.0.serialize(serializer)
} }
} }
#[cfg(core_reverse)]
impl<T> Serialize for Reverse<T>
where
T: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
////////////////////////////////////////////////////////////////////////////////
#[cfg(all(feature = "std", std_atomic))]
macro_rules! atomic_impl {
($($ty:ident)*) => {
$(
impl Serialize for $ty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.load(Ordering::SeqCst).serialize(serializer)
}
}
)*
}
}
#[cfg(all(feature = "std", std_atomic))]
atomic_impl! {
AtomicBool
AtomicI8 AtomicI16 AtomicI32 AtomicIsize
AtomicU8 AtomicU16 AtomicU32 AtomicUsize
}
#[cfg(all(feature = "std", std_atomic64))]
atomic_impl! {
AtomicI64 AtomicU64
}
+2 -7
View File
@@ -15,10 +15,7 @@ use ser::{
/// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`], /// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`],
/// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`]. /// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`].
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::ser::{Serializer, Impossible}; /// # use serde::ser::{Serializer, Impossible};
/// # use serde::private::ser::Error; /// # use serde::private::ser::Error;
/// # /// #
@@ -44,14 +41,12 @@ use ser::{
/// } /// }
/// ///
/// /* other Serializer methods */ /// /* other Serializer methods */
/// # __serialize_unimplemented! { /// # serde::__serialize_unimplemented! {
/// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some /// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant /// # unit unit_struct unit_variant newtype_struct newtype_variant
/// # tuple tuple_struct tuple_variant map struct struct_variant /// # tuple tuple_struct tuple_variant map struct struct_variant
/// # } /// # }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
/// ///
/// [`Serializer`]: trait.Serializer.html /// [`Serializer`]: trait.Serializer.html
+76 -157
View File
@@ -56,13 +56,13 @@
//! - PhantomData\<T\> //! - PhantomData\<T\>
//! - **Wrapper types**: //! - **Wrapper types**:
//! - Box\<T\> //! - Box\<T\>
//! - Rc\<T\>
//! - Arc\<T\>
//! - Cow\<'a, T\> //! - Cow\<'a, T\>
//! - Cell\<T\> //! - Cell\<T\>
//! - RefCell\<T\> //! - RefCell\<T\>
//! - Mutex\<T\> //! - Mutex\<T\>
//! - RwLock\<T\> //! - RwLock\<T\>
//! - Rc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - Arc\<T\>&emsp;*(if* features = ["rc"] *is enabled)*
//! - **Collection types**: //! - **Collection types**:
//! - BTreeMap\<K, V\> //! - BTreeMap\<K, V\>
//! - BTreeSet\<T\> //! - BTreeSet\<T\>
@@ -84,6 +84,7 @@
//! - PathBuf //! - PathBuf
//! - Range\<T\> //! - Range\<T\>
//! - RangeInclusive\<T\> //! - RangeInclusive\<T\>
//! - Bound\<T\>
//! - num::NonZero* //! - num::NonZero*
//! - `!` *(unstable)* //! - `!` *(unstable)*
//! - **Net types**: //! - **Net types**:
@@ -113,6 +114,13 @@ mod impossible;
pub use self::impossible::Impossible; pub use self::impossible::Impossible;
#[cfg(feature = "std")]
#[doc(no_inline)]
pub use std::error::Error as StdError;
#[cfg(not(feature = "std"))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
macro_rules! declare_error_trait { macro_rules! declare_error_trait {
@@ -137,7 +145,7 @@ macro_rules! declare_error_trait {
/// For example, a filesystem [`Path`] may refuse to serialize /// For example, a filesystem [`Path`] may refuse to serialize
/// itself if it contains invalid UTF-8 data. /// itself if it contains invalid UTF-8 data.
/// ///
/// ```rust /// ```edition2018
/// # struct Path; /// # struct Path;
/// # /// #
/// # impl Path { /// # impl Path {
@@ -171,7 +179,7 @@ macro_rules! declare_error_trait {
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
declare_error_trait!(Error: Sized + error::Error); declare_error_trait!(Error: Sized + StdError);
#[cfg(not(feature = "std"))] #[cfg(not(feature = "std"))]
declare_error_trait!(Error: Sized + Debug + Display); declare_error_trait!(Error: Sized + Debug + Display);
@@ -210,7 +218,7 @@ pub trait Serialize {
/// See the [Implementing `Serialize`] section of the manual for more /// See the [Implementing `Serialize`] section of the manual for more
/// information about how to implement this method. /// information about how to implement this method.
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// use serde::ser::{Serialize, SerializeStruct, Serializer};
/// ///
/// struct Person { /// struct Person {
@@ -377,13 +385,10 @@ pub trait Serializer: Sized {
/// Serialize a `bool` value. /// Serialize a `bool` value.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for bool { /// impl Serialize for bool {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -393,8 +398,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_bool(*self) /// serializer.serialize_bool(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error>; fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error>;
@@ -404,13 +407,10 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `i64` and /// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`. /// forward to `serialize_i64`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for i8 { /// impl Serialize for i8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -420,8 +420,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_i8(*self) /// serializer.serialize_i8(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error>; fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error>;
@@ -431,13 +429,10 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `i64` and /// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`. /// forward to `serialize_i64`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for i16 { /// impl Serialize for i16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -447,8 +442,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_i16(*self) /// serializer.serialize_i16(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error>; fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error>;
@@ -458,13 +451,10 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `i64` and /// reasonable implementation would be to cast the value to `i64` and
/// forward to `serialize_i64`. /// forward to `serialize_i64`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for i32 { /// impl Serialize for i32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -474,20 +464,15 @@ pub trait Serializer: Sized {
/// serializer.serialize_i32(*self) /// serializer.serialize_i32(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error>; fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error>;
/// Serialize an `i64` value. /// Serialize an `i64` value.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for i64 { /// impl Serialize for i64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -497,21 +482,16 @@ pub trait Serializer: Sized {
/// serializer.serialize_i64(*self) /// serializer.serialize_i64(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>; fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! { serde_if_integer128! {
/// Serialize an `i128` value. /// Serialize an `i128` value.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for i128 { /// impl Serialize for i128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -521,8 +501,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_i128(*self) /// serializer.serialize_i128(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
/// ///
/// This method is available only on Rust compiler versions >=1.26. The /// This method is available only on Rust compiler versions >=1.26. The
@@ -539,13 +517,10 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `u64` and /// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`. /// forward to `serialize_u64`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for u8 { /// impl Serialize for u8 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -555,8 +530,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_u8(*self) /// serializer.serialize_u8(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error>; fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error>;
@@ -566,13 +539,10 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `u64` and /// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`. /// forward to `serialize_u64`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for u16 { /// impl Serialize for u16 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -582,8 +552,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_u16(*self) /// serializer.serialize_u16(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error>; fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error>;
@@ -593,13 +561,10 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `u64` and /// reasonable implementation would be to cast the value to `u64` and
/// forward to `serialize_u64`. /// forward to `serialize_u64`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for u32 { /// impl Serialize for u32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -609,20 +574,15 @@ pub trait Serializer: Sized {
/// serializer.serialize_u32(*self) /// serializer.serialize_u32(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error>; fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error>;
/// Serialize a `u64` value. /// Serialize a `u64` value.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for u64 { /// impl Serialize for u64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -632,21 +592,16 @@ pub trait Serializer: Sized {
/// serializer.serialize_u64(*self) /// serializer.serialize_u64(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>; fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error>;
serde_if_integer128! { serde_if_integer128! {
/// Serialize a `u128` value. /// Serialize a `u128` value.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for u128 { /// impl Serialize for u128 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -656,8 +611,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_u128(*self) /// serializer.serialize_u128(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
/// ///
/// This method is available only on Rust compiler versions >=1.26. The /// This method is available only on Rust compiler versions >=1.26. The
@@ -674,13 +627,10 @@ pub trait Serializer: Sized {
/// reasonable implementation would be to cast the value to `f64` and /// reasonable implementation would be to cast the value to `f64` and
/// forward to `serialize_f64`. /// forward to `serialize_f64`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for f32 { /// impl Serialize for f32 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -690,20 +640,15 @@ pub trait Serializer: Sized {
/// serializer.serialize_f32(*self) /// serializer.serialize_f32(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error>; fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error>;
/// Serialize an `f64` value. /// Serialize an `f64` value.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for f64 { /// impl Serialize for f64 {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -713,8 +658,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_f64(*self) /// serializer.serialize_f64(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error>; fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error>;
@@ -723,13 +666,10 @@ pub trait Serializer: Sized {
/// If the format does not support characters, it is reasonable to serialize /// If the format does not support characters, it is reasonable to serialize
/// it as a single element `str` or a `u32`. /// it as a single element `str` or a `u32`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for char { /// impl Serialize for char {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -739,20 +679,15 @@ pub trait Serializer: Sized {
/// serializer.serialize_char(*self) /// serializer.serialize_char(*self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error>; fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error>;
/// Serialize a `&str`. /// Serialize a `&str`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for str { /// impl Serialize for str {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -762,8 +697,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_str(self) /// serializer.serialize_str(self)
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error>; fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error>;
@@ -775,10 +708,7 @@ pub trait Serializer: Sized {
/// `serialize_seq`. If forwarded, the implementation looks usually just /// `serialize_seq`. If forwarded, the implementation looks usually just
/// like this: /// like this:
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::ser::{Serializer, SerializeSeq}; /// # use serde::ser::{Serializer, SerializeSeq};
/// # use serde::private::ser::Error; /// # use serde::private::ser::Error;
/// # /// #
@@ -796,22 +726,18 @@ pub trait Serializer: Sized {
/// seq.end() /// seq.end()
/// } /// }
/// # /// #
/// # __serialize_unimplemented! { /// # serde::__serialize_unimplemented! {
/// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str none some /// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str none some
/// # unit unit_struct unit_variant newtype_struct newtype_variant /// # unit unit_struct unit_variant newtype_struct newtype_variant
/// # seq tuple tuple_struct tuple_variant map struct struct_variant /// # seq tuple tuple_struct tuple_variant map struct struct_variant
/// # } /// # }
/// # } /// # }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error>; fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error>;
/// Serialize a [`None`] value. /// Serialize a [`None`] value.
/// ///
/// ```rust /// ```edition2018
/// # extern crate serde;
/// #
/// # use serde::{Serialize, Serializer}; /// # use serde::{Serialize, Serializer};
/// # /// #
/// # enum Option<T> { /// # enum Option<T> {
@@ -819,7 +745,7 @@ pub trait Serializer: Sized {
/// # None, /// # None,
/// # } /// # }
/// # /// #
/// # use Option::{Some, None}; /// # use self::Option::{Some, None};
/// # /// #
/// impl<T> Serialize for Option<T> /// impl<T> Serialize for Option<T>
/// where /// where
@@ -844,9 +770,7 @@ pub trait Serializer: Sized {
/// Serialize a [`Some(T)`] value. /// Serialize a [`Some(T)`] value.
/// ///
/// ```rust /// ```edition2018
/// # extern crate serde;
/// #
/// # use serde::{Serialize, Serializer}; /// # use serde::{Serialize, Serializer};
/// # /// #
/// # enum Option<T> { /// # enum Option<T> {
@@ -854,7 +778,7 @@ pub trait Serializer: Sized {
/// # None, /// # None,
/// # } /// # }
/// # /// #
/// # use Option::{Some, None}; /// # use self::Option::{Some, None};
/// # /// #
/// impl<T> Serialize for Option<T> /// impl<T> Serialize for Option<T>
/// where /// where
@@ -881,13 +805,10 @@ pub trait Serializer: Sized {
/// Serialize a `()` value. /// Serialize a `()` value.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde;
/// #
/// # use serde::Serializer; /// # use serde::Serializer;
/// # /// #
/// # __private_serialize!(); /// # serde::__private_serialize!();
/// # /// #
/// impl Serialize for () { /// impl Serialize for () {
/// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> /// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
@@ -897,8 +818,6 @@ pub trait Serializer: Sized {
/// serializer.serialize_unit() /// serializer.serialize_unit()
/// } /// }
/// } /// }
/// #
/// # fn main() {}
/// ``` /// ```
fn serialize_unit(self) -> Result<Self::Ok, Self::Error>; fn serialize_unit(self) -> Result<Self::Ok, Self::Error>;
@@ -906,7 +825,7 @@ pub trait Serializer: Sized {
/// ///
/// A reasonable implementation would be to forward to `serialize_unit`. /// A reasonable implementation would be to forward to `serialize_unit`.
/// ///
/// ```rust /// ```edition2018
/// use serde::{Serialize, Serializer}; /// use serde::{Serialize, Serializer};
/// ///
/// struct Nothing; /// struct Nothing;
@@ -928,7 +847,7 @@ pub trait Serializer: Sized {
/// this variant within the enum, and the `variant` is the name of the /// this variant within the enum, and the `variant` is the name of the
/// variant. /// variant.
/// ///
/// ```rust /// ```edition2018
/// use serde::{Serialize, Serializer}; /// use serde::{Serialize, Serializer};
/// ///
/// enum E { /// enum E {
@@ -961,7 +880,7 @@ pub trait Serializer: Sized {
/// wrappers around the data they contain. A reasonable implementation would /// wrappers around the data they contain. A reasonable implementation would
/// be to forward to `value.serialize(self)`. /// be to forward to `value.serialize(self)`.
/// ///
/// ```rust /// ```edition2018
/// use serde::{Serialize, Serializer}; /// use serde::{Serialize, Serializer};
/// ///
/// struct Millimeters(u8); /// struct Millimeters(u8);
@@ -989,7 +908,7 @@ pub trait Serializer: Sized {
/// this variant within the enum, and the `variant` is the name of the /// this variant within the enum, and the `variant` is the name of the
/// variant. The `value` is the data contained within this newtype variant. /// variant. The `value` is the data contained within this newtype variant.
/// ///
/// ```rust /// ```edition2018
/// use serde::{Serialize, Serializer}; /// use serde::{Serialize, Serializer};
/// ///
/// enum E { /// enum E {
@@ -1027,7 +946,7 @@ pub trait Serializer: Sized {
/// not be computable before the sequence is iterated. Some serializers only /// not be computable before the sequence is iterated. Some serializers only
/// support sequences whose length is known up front. /// support sequences whose length is known up front.
/// ///
/// ```rust /// ```edition2018
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// # /// #
/// # struct Vec<T>(PhantomData<T>); /// # struct Vec<T>(PhantomData<T>);
@@ -1072,7 +991,7 @@ pub trait Serializer: Sized {
/// This call must be followed by zero or more calls to `serialize_element`, /// This call must be followed by zero or more calls to `serialize_element`,
/// then a call to `end`. /// then a call to `end`.
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, Serializer, SerializeTuple}; /// use serde::ser::{Serialize, Serializer, SerializeTuple};
/// ///
/// # mod fool { /// # mod fool {
@@ -1102,7 +1021,7 @@ pub trait Serializer: Sized {
/// } /// }
/// ``` /// ```
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// use serde::ser::{Serialize, SerializeTuple, Serializer};
/// ///
/// const VRAM_SIZE: usize = 386; /// const VRAM_SIZE: usize = 386;
@@ -1130,7 +1049,7 @@ pub trait Serializer: Sized {
/// The `name` is the name of the tuple struct and the `len` is the number /// The `name` is the name of the tuple struct and the `len` is the number
/// of data fields that will be serialized. /// of data fields that will be serialized.
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
/// ///
/// struct Rgb(u8, u8, u8); /// struct Rgb(u8, u8, u8);
@@ -1162,7 +1081,7 @@ pub trait Serializer: Sized {
/// this variant within the enum, the `variant` is the name of the variant, /// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized. /// and the `len` is the number of data fields that will be serialized.
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeTupleVariant, Serializer}; /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
/// ///
/// enum E { /// enum E {
@@ -1208,7 +1127,7 @@ pub trait Serializer: Sized {
/// be computable before the map is iterated. Some serializers only support /// be computable before the map is iterated. Some serializers only support
/// maps whose length is known up front. /// maps whose length is known up front.
/// ///
/// ```rust /// ```edition2018
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// # /// #
/// # struct HashMap<K, V>(PhantomData<K>, PhantomData<V>); /// # struct HashMap<K, V>(PhantomData<K>, PhantomData<V>);
@@ -1256,7 +1175,7 @@ pub trait Serializer: Sized {
/// The `name` is the name of the struct and the `len` is the number of /// The `name` is the name of the struct and the `len` is the number of
/// data fields that will be serialized. /// data fields that will be serialized.
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// use serde::ser::{Serialize, SerializeStruct, Serializer};
/// ///
/// struct Rgb { /// struct Rgb {
@@ -1292,7 +1211,7 @@ pub trait Serializer: Sized {
/// this variant within the enum, the `variant` is the name of the variant, /// this variant within the enum, the `variant` is the name of the variant,
/// and the `len` is the number of data fields that will be serialized. /// and the `len` is the number of data fields that will be serialized.
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; /// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
/// ///
/// enum E { /// enum E {
@@ -1334,7 +1253,7 @@ pub trait Serializer: Sized {
/// using [`serialize_seq`]. Implementors should not need to override this /// using [`serialize_seq`]. Implementors should not need to override this
/// method. /// method.
/// ///
/// ```rust /// ```edition2018
/// use serde::{Serialize, Serializer}; /// use serde::{Serialize, Serializer};
/// ///
/// struct SecretlyOneHigher { /// struct SecretlyOneHigher {
@@ -1371,7 +1290,7 @@ pub trait Serializer: Sized {
/// using [`serialize_map`]. Implementors should not need to override this /// using [`serialize_map`]. Implementors should not need to override this
/// method. /// method.
/// ///
/// ```rust /// ```edition2018
/// use serde::{Serialize, Serializer}; /// use serde::{Serialize, Serializer};
/// use std::collections::BTreeSet; /// use std::collections::BTreeSet;
/// ///
@@ -1411,7 +1330,7 @@ pub trait Serializer: Sized {
/// delegates to [`serialize_str`]. Serializers are encouraged to provide a /// delegates to [`serialize_str`]. Serializers are encouraged to provide a
/// more efficient implementation if possible. /// more efficient implementation if possible.
/// ///
/// ```rust /// ```edition2018
/// # struct DateTime; /// # struct DateTime;
/// # /// #
/// # impl DateTime { /// # impl DateTime {
@@ -1452,7 +1371,7 @@ pub trait Serializer: Sized {
/// of this method. If no more sensible behavior is possible, the /// of this method. If no more sensible behavior is possible, the
/// implementation is expected to return an error. /// implementation is expected to return an error.
/// ///
/// ```rust /// ```edition2018
/// # struct DateTime; /// # struct DateTime;
/// # /// #
/// # impl DateTime { /// # impl DateTime {
@@ -1487,7 +1406,7 @@ pub trait Serializer: Sized {
/// human-readable one and binary formats like Bincode will prefer the /// human-readable one and binary formats like Bincode will prefer the
/// compact one. /// compact one.
/// ///
/// ``` /// ```edition2018
/// # use std::fmt::{self, Display}; /// # use std::fmt::{self, Display};
/// # /// #
/// # struct Timestamp; /// # struct Timestamp;
@@ -1536,7 +1455,7 @@ pub trait Serializer: Sized {
/// ///
/// # Example use /// # Example use
/// ///
/// ```rust /// ```edition2018
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// # /// #
/// # struct Vec<T>(PhantomData<T>); /// # struct Vec<T>(PhantomData<T>);
@@ -1600,7 +1519,7 @@ pub trait SerializeSeq {
/// ///
/// # Example use /// # Example use
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, Serializer, SerializeTuple}; /// use serde::ser::{Serialize, Serializer, SerializeTuple};
/// ///
/// # mod fool { /// # mod fool {
@@ -1630,7 +1549,7 @@ pub trait SerializeSeq {
/// } /// }
/// ``` /// ```
/// ///
/// ```rust /// ```edition2018
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// # /// #
/// # struct Array<T>(PhantomData<T>); /// # struct Array<T>(PhantomData<T>);
@@ -1700,7 +1619,7 @@ pub trait SerializeTuple {
/// ///
/// # Example use /// # Example use
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer};
/// ///
/// struct Rgb(u8, u8, u8); /// struct Rgb(u8, u8, u8);
@@ -1745,7 +1664,7 @@ pub trait SerializeTupleStruct {
/// ///
/// # Example use /// # Example use
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeTupleVariant, Serializer}; /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer};
/// ///
/// enum E { /// enum E {
@@ -1803,7 +1722,7 @@ pub trait SerializeTupleVariant {
/// ///
/// # Example use /// # Example use
/// ///
/// ```rust /// ```edition2018
/// # use std::marker::PhantomData; /// # use std::marker::PhantomData;
/// # /// #
/// # struct HashMap<K, V>(PhantomData<K>, PhantomData<V>); /// # struct HashMap<K, V>(PhantomData<K>, PhantomData<V>);
@@ -1914,7 +1833,7 @@ pub trait SerializeMap {
/// ///
/// # Example use /// # Example use
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// use serde::ser::{Serialize, SerializeStruct, Serializer};
/// ///
/// struct Rgb { /// struct Rgb {
@@ -1974,7 +1893,7 @@ pub trait SerializeStruct {
/// ///
/// # Example use /// # Example use
/// ///
/// ```rust /// ```edition2018
/// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; /// use serde::ser::{Serialize, SerializeStructVariant, Serializer};
/// ///
/// enum E { /// enum E {
+48
View File
@@ -0,0 +1,48 @@
use lib::{Debug, Display};
/// Either a re-export of std::error::Error or a new identical trait, depending
/// on whether Serde's "std" feature is enabled.
///
/// Serde's error traits [`serde::ser::Error`] and [`serde::de::Error`] require
/// [`std::error::Error`] as a supertrait, but only when Serde is built with
/// "std" enabled. Data formats that don't care about no\_std support should
/// generally provide their error types with a `std::error::Error` impl
/// directly:
///
/// ```edition2018
/// #[derive(Debug)]
/// struct MySerError {...}
///
/// impl serde::ser::Error for MySerError {...}
///
/// impl std::fmt::Display for MySerError {...}
///
/// // We don't support no_std!
/// impl std::error::Error for MySerError {}
/// ```
///
/// Data formats that *do* support no\_std may either have a "std" feature of
/// their own:
///
/// ```toml
/// [features]
/// std = ["serde/std"]
/// ```
///
/// ```edition2018
/// #[cfg(feature = "std")]
/// impl std::error::Error for MySerError {}
/// ```
///
/// ... or else provide the std Error impl unconditionally via Serde's
/// re-export:
///
/// ```edition2018
/// impl serde::ser::StdError for MySerError {}
/// ```
pub trait Error: Debug + Display {
/// The underlying cause of this error, if any.
fn source(&self) -> Option<&(Error + 'static)> {
None
}
}
+5 -5
View File
@@ -1,8 +1,8 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.83" # remember to update html_root_url version = "1.0.100" # 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 OR Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
homepage = "https://serde.rs" homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
@@ -24,9 +24,9 @@ name = "serde_derive"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
proc-macro2 = "0.4" proc-macro2 = "1.0"
quote = "0.6.3" quote = "1.0"
syn = { version = "0.15.22", features = ["visit"] } syn = { version = "1.0", features = ["visit"] }
[dev-dependencies] [dev-dependencies]
serde = { version = "1.0", path = "../serde" } serde = { version = "1.0", path = "../serde" }
+2 -2
View File
@@ -115,7 +115,7 @@ pub fn with_bound(
impl<'ast> Visit<'ast> for FindTyParams<'ast> { impl<'ast> Visit<'ast> for FindTyParams<'ast> {
fn visit_field(&mut self, field: &'ast syn::Field) { fn visit_field(&mut self, field: &'ast syn::Field) {
if let syn::Type::Path(ref ty) = field.ty { if let syn::Type::Path(ref ty) = field.ty {
if let Some(Pair::Punctuated(ref t, _)) = ty.path.segments.first() { if let Some(Pair::Punctuated(ref t, _)) = ty.path.segments.pairs().next() {
if self.all_type_params.contains(&t.ident) { if self.all_type_params.contains(&t.ident) {
self.associated_type_usage.push(ty); self.associated_type_usage.push(ty);
} }
@@ -126,7 +126,7 @@ pub fn with_bound(
fn visit_path(&mut self, path: &'ast syn::Path) { fn visit_path(&mut self, path: &'ast syn::Path) {
if let Some(seg) = path.segments.last() { if let Some(seg) = path.segments.last() {
if seg.into_value().ident == "PhantomData" { if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements // Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it. // Serialize and Deserialize whether or not T implements it.
return; return;
+115 -90
View File
@@ -20,22 +20,23 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<TokenStream
None => return Err(ctxt.check().unwrap_err()), None => return Err(ctxt.check().unwrap_err()),
}; };
precondition(&ctxt, &cont); precondition(&ctxt, &cont);
try!(ctxt.check()); ctxt.check()?;
let ident = &cont.ident; let ident = &cont.ident;
let params = Parameters::new(&cont); let params = Parameters::new(&cont);
let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params); let (de_impl_generics, _, ty_generics, where_clause) = split_with_de_lifetime(&params);
let body = Stmts(deserialize_body(&cont, &params)); let body = Stmts(deserialize_body(&cont, &params));
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
let serde = cont.attrs.serde_path();
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis; let vis = &input.vis;
let used = pretend::pretend_used(&cont); let used = pretend::pretend_used(&cont);
quote! { quote! {
impl #de_impl_generics #ident #ty_generics #where_clause { impl #de_impl_generics #ident #ty_generics #where_clause {
#vis fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error> #vis fn deserialize<__D>(__deserializer: __D) -> #serde::export::Result<#remote #ty_generics, __D::Error>
where where
__D: _serde::Deserializer<#delife>, __D: #serde::Deserializer<#delife>,
{ {
#used #used
#body #body
@@ -47,10 +48,10 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<TokenStream
quote! { quote! {
#[automatically_derived] #[automatically_derived]
impl #de_impl_generics _serde::Deserialize<#delife> for #ident #ty_generics #where_clause { impl #de_impl_generics #serde::Deserialize<#delife> for #ident #ty_generics #where_clause {
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error> fn deserialize<__D>(__deserializer: __D) -> #serde::export::Result<Self, __D::Error>
where where
__D: _serde::Deserializer<#delife>, __D: #serde::Deserializer<#delife>,
{ {
#body #body
} }
@@ -60,7 +61,12 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<TokenStream
} }
}; };
Ok(dummy::wrap_in_const("DESERIALIZE", ident, impl_block)) Ok(dummy::wrap_in_const(
cont.attrs.custom_serde_path(),
"DESERIALIZE",
ident,
impl_block,
))
} }
fn precondition(cx: &Ctxt, cont: &Container) { fn precondition(cx: &Ctxt, cont: &Container) {
@@ -139,7 +145,7 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to /// Type name to use in error messages and `&'static str` arguments to
/// various Deserializer methods. /// various Deserializer methods.
fn type_name(&self) -> String { fn type_name(&self) -> String {
self.this.segments.last().unwrap().value().ident.to_string() self.this.segments.last().unwrap().ident.to_string()
} }
} }
@@ -263,6 +269,8 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
deserialize_transparent(cont, params) deserialize_transparent(cont, params)
} else if let Some(type_from) = cont.attrs.type_from() { } else if let Some(type_from) = cont.attrs.type_from() {
deserialize_from(type_from) deserialize_from(type_from)
} else if let Some(type_try_from) = cont.attrs.type_try_from() {
deserialize_try_from(type_try_from)
} else if let attr::Identifier::No = cont.attrs.identifier() { } else if let attr::Identifier::No = cont.attrs.identifier() {
match cont.data { match cont.data {
Data::Enum(ref variants) => deserialize_enum(params, variants, &cont.attrs), Data::Enum(ref variants) => deserialize_enum(params, variants, &cont.attrs),
@@ -292,6 +300,7 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<St
if cont.attrs.transparent() if cont.attrs.transparent()
|| cont.attrs.type_from().is_some() || cont.attrs.type_from().is_some()
|| cont.attrs.type_try_from().is_some()
|| cont.attrs.identifier().is_some() || cont.attrs.identifier().is_some()
|| cont || cont
.data .data
@@ -384,6 +393,14 @@ fn deserialize_from(type_from: &syn::Type) -> Fragment {
} }
} }
fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment {
quote_block! {
_serde::export::Result::and_then(
<#type_try_from as _serde::Deserialize>::deserialize(__deserializer),
|v| _serde::export::TryFrom::try_from(v).map_err(_serde::de::Error::custom))
}
}
fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment { fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fragment {
let this = &params.this; let this = &params.this;
let type_name = cattrs.name().deserialize_name(); let type_name = cattrs.name().deserialize_name();
@@ -1140,25 +1157,21 @@ fn deserialize_enum(
} }
} }
fn deserialize_externally_tagged_enum( fn prepare_enum_variant_enum(
params: &Parameters,
variants: &[Variant], variants: &[Variant],
cattrs: &attr::Container, cattrs: &attr::Container,
) -> Fragment { ) -> (TokenStream, Stmts) {
let this = &params.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
let type_name = cattrs.name().deserialize_name();
let expecting = format!("enum {}", params.type_name());
let variant_names_idents: Vec<_> = variants let variant_names_idents: Vec<_> = variants
.iter() .iter()
.enumerate() .enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing()) .filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i))) .map(|(i, variant)| {
(
variant.attrs.name().deserialize_name(),
field_i(i),
variant.attrs.aliases(),
)
})
.collect(); .collect();
let other_idx = variants let other_idx = variants
@@ -1166,7 +1179,7 @@ fn deserialize_externally_tagged_enum(
.position(|ref variant| variant.attrs.other()); .position(|ref variant| variant.attrs.other());
let variants_stmt = { let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name); let variant_names = variant_names_idents.iter().map(|&(ref name, _, _)| name);
quote! { quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
} }
@@ -1179,6 +1192,24 @@ fn deserialize_externally_tagged_enum(
other_idx, other_idx,
)); ));
(variants_stmt, variant_visitor)
}
fn deserialize_externally_tagged_enum(
params: &Parameters,
variants: &[Variant],
cattrs: &attr::Container,
) -> Fragment {
let this = &params.this;
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) =
split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime();
let type_name = cattrs.name().deserialize_name();
let expecting = format!("enum {}", params.type_name());
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
// Match arms to extract a variant from a string // Match arms to extract a variant from a string
let variant_arms = variants let variant_arms = variants
.iter() .iter()
@@ -1261,30 +1292,7 @@ fn deserialize_internally_tagged_enum(
cattrs: &attr::Container, cattrs: &attr::Container,
tag: &str, tag: &str,
) -> Fragment { ) -> Fragment {
let variant_names_idents: Vec<_> = variants let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
.collect();
let other_idx = variants
.iter()
.position(|ref variant| variant.attrs.other());
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
let variant_visitor = Stmts(deserialize_generated_identifier(
&variant_names_idents,
cattrs,
true,
other_idx,
));
// Match arms to extract a variant from a string // Match arms to extract a variant from a string
let variant_arms = variants let variant_arms = variants
@@ -1335,30 +1343,7 @@ fn deserialize_adjacently_tagged_enum(
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
let variant_names_idents: Vec<_> = variants let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.map(|(i, variant)| (variant.attrs.name().deserialize_name(), field_i(i)))
.collect();
let other_idx = variants
.iter()
.position(|ref variant| variant.attrs.other());
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
};
let variant_visitor = Stmts(deserialize_generated_identifier(
&variant_names_idents,
cattrs,
true,
other_idx,
));
let variant_arms: &Vec<_> = &variants let variant_arms: &Vec<_> = &variants
.iter() .iter()
@@ -1870,13 +1855,13 @@ fn deserialize_untagged_newtype_variant(
} }
fn deserialize_generated_identifier( fn deserialize_generated_identifier(
fields: &[(String, Ident)], fields: &[(String, Ident, Vec<String>)],
cattrs: &attr::Container, cattrs: &attr::Container,
is_variant: bool, is_variant: bool,
other_idx: Option<usize>, other_idx: Option<usize>,
) -> Fragment { ) -> Fragment {
let this = quote!(__Field); let this = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident)| ident).collect(); let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident, _)| ident).collect();
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() { let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),); let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),);
@@ -1977,11 +1962,12 @@ fn deserialize_custom_identifier(
( (
variant.attrs.name().deserialize_name(), variant.attrs.name().deserialize_name(),
variant.ident.clone(), variant.ident.clone(),
variant.attrs.aliases(),
) )
}) })
.collect(); .collect();
let names = names_idents.iter().map(|&(ref name, _)| name); let names = names_idents.iter().map(|&(ref name, _, _)| name);
let names_const = if fallthrough.is_some() { let names_const = if fallthrough.is_some() {
None None
@@ -2032,24 +2018,33 @@ fn deserialize_custom_identifier(
fn deserialize_identifier( fn deserialize_identifier(
this: &TokenStream, this: &TokenStream,
fields: &[(String, Ident)], fields: &[(String, Ident, Vec<String>)],
is_variant: bool, is_variant: bool,
fallthrough: Option<TokenStream>, fallthrough: Option<TokenStream>,
collect_other_fields: bool, collect_other_fields: bool,
) -> Fragment { ) -> Fragment {
let field_strs = fields.iter().map(|&(ref name, _)| name); let mut flat_fields = Vec::new();
let field_borrowed_strs = fields.iter().map(|&(ref name, _)| name); for &(_, ref ident, ref aliases) in fields {
let field_bytes = fields flat_fields.extend(aliases.iter().map(|alias| (alias, ident)))
}
let field_strs = flat_fields.iter().map(|&(ref name, _)| name);
let field_borrowed_strs = flat_fields.iter().map(|&(ref name, _)| name);
let field_bytes = flat_fields
.iter() .iter()
.map(|&(ref name, _)| Literal::byte_string(name.as_bytes())); .map(|&(ref name, _)| Literal::byte_string(name.as_bytes()));
let field_borrowed_bytes = fields let field_borrowed_bytes = flat_fields
.iter() .iter()
.map(|&(ref name, _)| Literal::byte_string(name.as_bytes())); .map(|&(ref name, _)| Literal::byte_string(name.as_bytes()));
let constructors: &Vec<_> = &fields let constructors: &Vec<_> = &flat_fields
.iter() .iter()
.map(|&(_, ref ident)| quote!(#this::#ident)) .map(|&(_, ref ident)| quote!(#this::#ident))
.collect(); .collect();
let main_constructors: &Vec<_> = &fields
.iter()
.map(|&(_, ref ident, _)| quote!(#this::#ident))
.collect();
let expecting = if is_variant { let expecting = if is_variant {
"variant identifier" "variant identifier"
@@ -2075,7 +2070,7 @@ fn deserialize_identifier(
) = if collect_other_fields { ) = if collect_other_fields {
( (
Some(quote! { Some(quote! {
let __value = _serde::private::de::Content::String(__value.to_string()); let __value = _serde::private::de::Content::String(_serde::export::ToString::to_string(__value));
}), }),
Some(quote! { Some(quote! {
let __value = _serde::private::de::Content::Str(__value); let __value = _serde::private::de::Content::Str(__value);
@@ -2237,7 +2232,7 @@ fn deserialize_identifier(
{ {
match __value { match __value {
#( #(
#variant_indices => _serde::export::Ok(#constructors), #variant_indices => _serde::export::Ok(#main_constructors),
)* )*
_ => _serde::export::Err(_serde::de::Error::invalid_value( _ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value), _serde::de::Unexpected::Unsigned(__value),
@@ -2300,11 +2295,17 @@ fn deserialize_struct_as_struct_visitor(
.iter() .iter()
.enumerate() .enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing()) .filter(|&(_, field)| !field.attrs.skip_deserializing())
.map(|(i, field)| (field.attrs.name().deserialize_name(), field_i(i))) .map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect(); .collect();
let fields_stmt = { let fields_stmt = {
let field_names = field_names_idents.iter().map(|&(ref name, _)| name); let field_names = field_names_idents.iter().map(|&(ref name, _, _)| name);
quote_block! { quote_block! {
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
} }
@@ -2327,7 +2328,13 @@ fn deserialize_struct_as_map_visitor(
.iter() .iter()
.enumerate() .enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|(i, field)| (field.attrs.name().deserialize_name(), field_i(i))) .map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect(); .collect();
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None); let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None);
@@ -2394,7 +2401,12 @@ fn deserialize_map(
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({ quote!({
#wrapper #wrapper
try!(_serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map)).value match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) {
_serde::export::Ok(__wrapper) => __wrapper.value,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
}) })
} }
}; };
@@ -2461,7 +2473,7 @@ fn deserialize_map(
let extract_collected = fields_names let extract_collected = fields_names
.iter() .iter()
.filter(|&&(field, _)| field.attrs.flatten()) .filter(|&&(field, _)| field.attrs.flatten() && !field.attrs.skip_deserializing())
.map(|&(field, ref name)| { .map(|&(field, ref name)| {
let field_ty = field.ty; let field_ty = field.ty;
let func = match field.attrs.deserialize_with() { let func = match field.attrs.deserialize_with() {
@@ -2481,7 +2493,9 @@ fn deserialize_map(
let collected_deny_unknown_fields = if cattrs.has_flatten() && cattrs.deny_unknown_fields() { let collected_deny_unknown_fields = if cattrs.has_flatten() && cattrs.deny_unknown_fields() {
Some(quote! { Some(quote! {
if let _serde::export::Some(_serde::export::Some((__key, _))) = __collect.into_iter().filter(|x| x.is_some()).next() { if let _serde::export::Some(_serde::export::Some((__key, _))) =
__collect.into_iter().filter(_serde::export::Option::is_some).next()
{
if let _serde::export::Some(__key) = __key.as_str() { if let _serde::export::Some(__key) = __key.as_str() {
return _serde::export::Err( return _serde::export::Err(
_serde::de::Error::custom(format_args!("unknown field `{}`", &__key))); _serde::de::Error::custom(format_args!("unknown field `{}`", &__key)));
@@ -2558,11 +2572,17 @@ fn deserialize_struct_as_struct_in_place_visitor(
.iter() .iter()
.enumerate() .enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing()) .filter(|&(_, field)| !field.attrs.skip_deserializing())
.map(|(i, field)| (field.attrs.name().deserialize_name(), field_i(i))) .map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect(); .collect();
let fields_stmt = { let fields_stmt = {
let field_names = field_names_idents.iter().map(|&(ref name, _)| name); let field_names = field_names_idents.iter().map(|&(ref name, _, _)| name);
quote_block! { quote_block! {
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
} }
@@ -2619,7 +2639,12 @@ fn deserialize_map_in_place(
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
quote!({ quote!({
#wrapper #wrapper
self.place.#member = try!(_serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map)).value self.place.#member = match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) {
_serde::export::Ok(__wrapper) => __wrapper.value,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}) })
} }
}; };
+19 -4
View File
@@ -1,8 +1,14 @@
use proc_macro2::{Ident, Span, TokenStream}; use proc_macro2::{Ident, Span, TokenStream};
use syn;
use try; use try;
pub fn wrap_in_const(trait_: &str, ty: &Ident, code: TokenStream) -> TokenStream { pub fn wrap_in_const(
serde_path: Option<&syn::Path>,
trait_: &str,
ty: &Ident,
code: TokenStream,
) -> TokenStream {
let try_replacement = try::replacement(); let try_replacement = try::replacement();
let dummy_const = Ident::new( let dummy_const = Ident::new(
@@ -10,13 +16,22 @@ pub fn wrap_in_const(trait_: &str, ty: &Ident, code: TokenStream) -> TokenStream
Span::call_site(), Span::call_site(),
); );
quote! { let use_serde = match serde_path {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] Some(path) => quote! {
const #dummy_const: () = { use #path as _serde;
},
None => quote! {
#[allow(unknown_lints)] #[allow(unknown_lints)]
#[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))] #[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
#[allow(rust_2018_idioms)] #[allow(rust_2018_idioms)]
extern crate serde as _serde; extern crate serde as _serde;
},
};
quote! {
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
#use_serde
#try_replacement #try_replacement
#code #code
}; };
File diff suppressed because it is too large Load Diff
+26 -22
View File
@@ -13,6 +13,7 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_internal_tag_field_name_conflict(cx, cont); check_internal_tag_field_name_conflict(cx, cont);
check_adjacent_tag_conflict(cx, cont); check_adjacent_tag_conflict(cx, cont);
check_transparent(cx, cont, derive); check_transparent(cx, cont, derive);
check_from_and_try_from(cx, cont);
} }
/// Getters are only allowed inside structs (not enums) with the `remote` /// Getters are only allowed inside structs (not enums) with the `remote`
@@ -76,25 +77,6 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
} }
_ => {} _ => {}
} }
if field.attrs.skip_serializing() {
cx.error_spanned_by(
field.original,
"#[serde(flatten)] can not be combined with \
#[serde(skip_serializing)]",
);
} else if field.attrs.skip_serializing_if().is_some() {
cx.error_spanned_by(
field.original,
"#[serde(flatten)] can not be combined with \
#[serde(skip_serializing_if = \"...\")]",
);
} else if field.attrs.skip_deserializing() {
cx.error_spanned_by(
field.original,
"#[serde(flatten)] can not be combined with \
#[serde(skip_deserializing)]",
);
}
} }
/// The `other` attribute must be used at most once and it must be the last /// The `other` attribute must be used at most once and it must be the last
@@ -295,12 +277,18 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
let check_de = !field.attrs.skip_deserializing(); let check_de = !field.attrs.skip_deserializing();
let name = field.attrs.name(); let name = field.attrs.name();
let ser_name = name.serialize_name(); let ser_name = name.serialize_name();
let de_name = name.deserialize_name();
if check_ser && ser_name == tag || check_de && de_name == tag { if check_ser && ser_name == tag {
diagnose_conflict(); diagnose_conflict();
return; return;
} }
for de_name in field.attrs.aliases() {
if check_de && de_name == tag {
diagnose_conflict();
return;
}
}
} }
} }
Style::Unit | Style::Newtype | Style::Tuple => {} Style::Unit | Style::Newtype | Style::Tuple => {}
@@ -343,6 +331,13 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
); );
} }
if cont.attrs.type_try_from().is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(transparent)] is not allowed with #[serde(try_from = \"...\")]",
);
}
if cont.attrs.type_into().is_some() { if cont.attrs.type_into().is_some() {
cx.error_spanned_by( cx.error_spanned_by(
cont.original, cont.original,
@@ -412,7 +407,7 @@ fn member_message(member: &Member) -> String {
fn allow_transparent(field: &Field, derive: Derive) -> bool { fn allow_transparent(field: &Field, derive: Derive) -> bool {
if let Type::Path(ref ty) = *field.ty { if let Type::Path(ref ty) = *field.ty {
if let Some(seg) = ty.path.segments.last() { if let Some(seg) = ty.path.segments.last() {
if seg.into_value().ident == "PhantomData" { if seg.ident == "PhantomData" {
return false; return false;
} }
} }
@@ -423,3 +418,12 @@ fn allow_transparent(field: &Field, derive: Derive) -> bool {
Derive::Deserialize => !field.attrs.skip_deserializing() && field.attrs.default().is_none(), Derive::Deserialize => !field.attrs.skip_deserializing() && field.attrs.default().is_none(),
} }
} }
fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) {
if cont.attrs.type_from().is_some() && cont.attrs.type_try_from().is_some() {
cx.error_spanned_by(
cont.original,
"#[serde(from = \"...\")] and #[serde(try_from = \"...\")] conflict with each other",
);
}
}
+1
View File
@@ -6,6 +6,7 @@ pub use self::ctxt::Ctxt;
mod case; mod case;
mod check; mod check;
mod symbol;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum Derive { pub enum Derive {
+67
View File
@@ -0,0 +1,67 @@
use std::fmt::{self, Display};
use syn::{Ident, Path};
#[derive(Copy, Clone)]
pub struct Symbol(&'static str);
pub const ALIAS: Symbol = Symbol("alias");
pub const BORROW: Symbol = Symbol("borrow");
pub const BOUND: Symbol = Symbol("bound");
pub const CONTENT: Symbol = Symbol("content");
pub const CRATE: Symbol = Symbol("crate");
pub const DEFAULT: Symbol = Symbol("default");
pub const DENY_UNKNOWN_FIELDS: Symbol = Symbol("deny_unknown_fields");
pub const DESERIALIZE: Symbol = Symbol("deserialize");
pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with");
pub const FIELD_IDENTIFIER: Symbol = Symbol("field_identifier");
pub const FLATTEN: Symbol = Symbol("flatten");
pub const FROM: Symbol = Symbol("from");
pub const GETTER: Symbol = Symbol("getter");
pub const INTO: Symbol = Symbol("into");
pub const OTHER: Symbol = Symbol("other");
pub const REMOTE: Symbol = Symbol("remote");
pub const RENAME: Symbol = Symbol("rename");
pub const RENAME_ALL: Symbol = Symbol("rename_all");
pub const SERDE: Symbol = Symbol("serde");
pub const SERIALIZE: Symbol = Symbol("serialize");
pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with");
pub const SKIP: Symbol = Symbol("skip");
pub const SKIP_DESERIALIZING: Symbol = Symbol("skip_deserializing");
pub const SKIP_SERIALIZING: Symbol = Symbol("skip_serializing");
pub const SKIP_SERIALIZING_IF: Symbol = Symbol("skip_serializing_if");
pub const TAG: Symbol = Symbol("tag");
pub const TRANSPARENT: Symbol = Symbol("transparent");
pub const TRY_FROM: Symbol = Symbol("try_from");
pub const UNTAGGED: Symbol = Symbol("untagged");
pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier");
pub const WITH: Symbol = Symbol("with");
impl PartialEq<Symbol> for Ident {
fn eq(&self, word: &Symbol) -> bool {
self == word.0
}
}
impl<'a> PartialEq<Symbol> for &'a Ident {
fn eq(&self, word: &Symbol) -> bool {
*self == word.0
}
}
impl PartialEq<Symbol> for Path {
fn eq(&self, word: &Symbol) -> bool {
self.is_ident(word.0)
}
}
impl<'a> PartialEq<Symbol> for &'a Path {
fn eq(&self, word: &Symbol) -> bool {
self.is_ident(word.0)
}
}
impl Display for Symbol {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str(self.0)
}
}
+10 -8
View File
@@ -1,8 +1,7 @@
//! This crate provides Serde's two derive macros. //! This crate provides Serde's two derive macros.
//! //!
//! ```rust //! ```edition2018
//! # #[macro_use] //! # use serde_derive::{Serialize, Deserialize};
//! # extern crate serde_derive;
//! # //! #
//! #[derive(Serialize, Deserialize)] //! #[derive(Serialize, Deserialize)]
//! # struct S; //! # struct S;
@@ -14,35 +13,38 @@
//! //!
//! [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.83")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.100")]
#![allow(unknown_lints, bare_trait_objects)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints // Ignored clippy lints
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
cyclomatic_complexity, cognitive_complexity,
enum_variant_names, enum_variant_names,
needless_pass_by_value, needless_pass_by_value,
redundant_field_names, redundant_field_names,
too_many_arguments, too_many_arguments,
trivially_copy_pass_by_ref,
used_underscore_binding, used_underscore_binding,
) )
)] )]
// Whitelisted clippy_pedantic lints // Ignored clippy_pedantic lints
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
cast_possible_truncation, cast_possible_truncation,
checked_conversions,
doc_markdown, doc_markdown,
enum_glob_use, enum_glob_use,
filter_map, filter_map,
indexing_slicing, indexing_slicing,
items_after_statements, items_after_statements,
match_same_arms, match_same_arms,
module_name_repetitions,
similar_names, similar_names,
single_match_else, single_match_else,
stutter,
unseparated_literal_suffix, unseparated_literal_suffix,
use_self, use_self,
) )
+48 -45
View File
@@ -16,21 +16,22 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream,
None => return Err(ctxt.check().unwrap_err()), None => return Err(ctxt.check().unwrap_err()),
}; };
precondition(&ctxt, &cont); precondition(&ctxt, &cont);
try!(ctxt.check()); ctxt.check()?;
let ident = &cont.ident; let ident = &cont.ident;
let params = Parameters::new(&cont); let params = Parameters::new(&cont);
let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl(); let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl();
let body = Stmts(serialize_body(&cont, &params)); let body = Stmts(serialize_body(&cont, &params));
let serde = cont.attrs.serde_path();
let impl_block = if let Some(remote) = cont.attrs.remote() { let impl_block = if let Some(remote) = cont.attrs.remote() {
let vis = &input.vis; let vis = &input.vis;
let used = pretend::pretend_used(&cont); let used = pretend::pretend_used(&cont);
quote! { quote! {
impl #impl_generics #ident #ty_generics #where_clause { impl #impl_generics #ident #ty_generics #where_clause {
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::export::Result<__S::Ok, __S::Error>
where where
__S: _serde::Serializer, __S: #serde::Serializer,
{ {
#used #used
#body #body
@@ -40,10 +41,10 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream,
} else { } else {
quote! { quote! {
#[automatically_derived] #[automatically_derived]
impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause { impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> fn serialize<__S>(&self, __serializer: __S) -> #serde::export::Result<__S::Ok, __S::Error>
where where
__S: _serde::Serializer, __S: #serde::Serializer,
{ {
#body #body
} }
@@ -51,7 +52,12 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream,
} }
}; };
Ok(dummy::wrap_in_const("SERIALIZE", ident, impl_block)) Ok(dummy::wrap_in_const(
cont.attrs.custom_serde_path(),
"SERIALIZE",
ident,
impl_block,
))
} }
fn precondition(cx: &Ctxt, cont: &Container) { fn precondition(cx: &Ctxt, cont: &Container) {
@@ -110,7 +116,7 @@ impl Parameters {
/// Type name to use in error messages and `&'static str` arguments to /// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods. /// various Serializer methods.
fn type_name(&self) -> String { fn type_name(&self) -> String {
self.this.segments.last().unwrap().value().ident.to_string() self.this.segments.last().unwrap().ident.to_string()
} }
} }
@@ -289,37 +295,38 @@ fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Contai
} }
} }
fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream {
match *cattrs.tag() {
attr::TagType::Internal { ref tag } => {
let type_name = cattrs.name().serialize_name();
let func = struct_trait.serialize_field(Span::call_site());
quote! {
try!(#func(&mut __serde_state, #tag, #type_name));
}
}
_ => quote! {},
}
}
fn serialize_struct_as_struct( fn serialize_struct_as_struct(
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
cattrs: &attr::Container, cattrs: &attr::Container,
) -> Fragment { ) -> Fragment {
let mut serialize_fields = let serialize_fields =
serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct); serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct);
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
let additional_field_count: usize = match cattrs.tag() { let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct);
&attr::TagType::Internal { ref tag } => { let tag_field_exists = !tag_field.is_empty();
let func = StructTrait::SerializeStruct.serialize_field(Span::call_site());
serialize_fields.insert(
0,
quote! {
try!(#func(&mut __serde_state, #tag, #type_name));
},
);
1
}
_ => 0,
};
let mut serialized_fields = fields let mut serialized_fields = fields
.iter() .iter()
.filter(|&field| !field.attrs.skip_serializing()) .filter(|&field| !field.attrs.skip_serializing())
.peekable(); .peekable();
let let_mut = mut_if(serialized_fields.peek().is_some()); let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
let len = serialized_fields let len = serialized_fields
.map(|field| match field.attrs.skip_serializing_if() { .map(|field| match field.attrs.skip_serializing_if() {
@@ -330,12 +337,13 @@ fn serialize_struct_as_struct(
} }
}) })
.fold( .fold(
quote!(#additional_field_count), quote!(#tag_field_exists as usize),
|sum, expr| quote!(#sum + #expr), |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));
#tag_field
#(#serialize_fields)* #(#serialize_fields)*
_serde::ser::SerializeStruct::end(__serde_state) _serde::ser::SerializeStruct::end(__serde_state)
} }
@@ -349,12 +357,15 @@ fn serialize_struct_as_map(
let serialize_fields = let serialize_fields =
serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap); serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap);
let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap);
let tag_field_exists = !tag_field.is_empty();
let mut serialized_fields = fields let mut serialized_fields = fields
.iter() .iter()
.filter(|&field| !field.attrs.skip_serializing()) .filter(|&field| !field.attrs.skip_serializing())
.peekable(); .peekable();
let let_mut = mut_if(serialized_fields.peek().is_some()); let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists);
let len = if cattrs.has_flatten() { let len = if cattrs.has_flatten() {
quote!(_serde::export::None) quote!(_serde::export::None)
@@ -367,12 +378,16 @@ fn serialize_struct_as_map(
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!(#tag_field_exists as usize),
|sum, expr| quote!(#sum + #expr),
);
quote!(_serde::export::Some(#len)) quote!(_serde::export::Some(#len))
}; };
quote_block! { quote_block! {
let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len)); let #let_mut __serde_state = try!(_serde::Serializer::serialize_map(__serializer, #len));
#tag_field
#(#serialize_fields)* #(#serialize_fields)*
_serde::ser::SerializeMap::end(__serde_state) _serde::ser::SerializeMap::end(__serde_state)
} }
@@ -1252,15 +1267,9 @@ enum StructTrait {
impl StructTrait { impl StructTrait {
fn serialize_field(&self, span: Span) -> TokenStream { fn serialize_field(&self, span: Span) -> TokenStream {
match *self { match *self {
StructTrait::SerializeMap => { StructTrait::SerializeMap => quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry),
quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry) StructTrait::SerializeStruct => quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field),
} StructTrait::SerializeStructVariant => quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field),
StructTrait::SerializeStruct => {
quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field)
}
StructTrait::SerializeStructVariant => {
quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field)
}
} }
} }
@@ -1286,15 +1295,9 @@ enum TupleTrait {
impl TupleTrait { impl TupleTrait {
fn serialize_element(&self, span: Span) -> TokenStream { fn serialize_element(&self, span: Span) -> TokenStream {
match *self { match *self {
TupleTrait::SerializeTuple => { TupleTrait::SerializeTuple => quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element),
quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element) TupleTrait::SerializeTupleStruct => quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field),
} TupleTrait::SerializeTupleVariant => quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field),
TupleTrait::SerializeTupleStruct => {
quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field)
}
TupleTrait::SerializeTupleVariant => {
quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field)
}
} }
} }
} }
+4 -4
View File
@@ -2,7 +2,7 @@
name = "serde_derive_internals" name = "serde_derive_internals"
version = "0.24.1" # remember to update html_root_url version = "0.24.1" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT OR Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable." description = "AST representation used by Serde derive macros. Unstable."
homepage = "https://serde.rs" homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
@@ -14,9 +14,9 @@ include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "LICENSE-APACHE", "LICENSE-MIT
path = "lib.rs" path = "lib.rs"
[dependencies] [dependencies]
proc-macro2 = "0.4" proc-macro2 = "1.0"
quote = "0.6.3" quote = "1.0"
syn = { version = "0.15", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] } syn = { version = "1.0", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
[badges] [badges]
travis-ci = { repository = "serde-rs/serde" } travis-ci = { repository = "serde-rs/serde" }
+4 -4
View File
@@ -1,12 +1,12 @@
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.24.1")] #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.24.1")]
#![allow(unknown_lints, bare_trait_objects)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
cyclomatic_complexity, cognitive_complexity,
doc_markdown, redundant_field_names,
match_same_arms, trivially_copy_pass_by_ref
redundant_field_names
) )
)] )]
+3 -3
View File
@@ -1,8 +1,8 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.83" # remember to update html_root_url version = "1.0.100" # 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 OR Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
homepage = "https://serde.rs" homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
@@ -15,7 +15,7 @@ include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-AP
serde = { version = "1.0.60", path = "../serde" } serde = { version = "1.0.60", path = "../serde" }
[dev-dependencies] [dev-dependencies]
serde = { version = "1.0", path = "../serde", features = ["rc"] } serde = { version = "1.0", path = "../serde" }
serde_derive = { version = "1.0", path = "../serde_derive" } serde_derive = { version = "1.0", path = "../serde_derive" }
[badges] [badges]
+28 -52
View File
@@ -8,13 +8,8 @@ use std::fmt::Debug;
/// Runs both `assert_ser_tokens` and `assert_de_tokens`. /// Runs both `assert_ser_tokens` and `assert_de_tokens`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -45,13 +40,8 @@ where
/// Asserts that `value` serializes to the given `tokens`. /// Asserts that `value` serializes to the given `tokens`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_ser_tokens, Token}; /// # use serde_test::{assert_ser_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -90,16 +80,11 @@ where
/// Asserts that `value` serializes to the given `tokens`, and then yields /// Asserts that `value` serializes to the given `tokens`, and then yields
/// `error`. /// `error`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use]
/// # extern crate serde_derive;
/// #
/// # extern crate serde_test;
/// #
/// # fn main() {
/// use std::sync::{Arc, Mutex}; /// use std::sync::{Arc, Mutex};
/// use std::thread; /// use std::thread;
/// ///
/// use serde::Serialize;
/// use serde_test::{assert_ser_tokens_error, Token}; /// use serde_test::{assert_ser_tokens_error, Token};
/// ///
/// #[derive(Serialize)] /// #[derive(Serialize)]
@@ -107,26 +92,27 @@ where
/// lock: Arc<Mutex<u32>>, /// lock: Arc<Mutex<u32>>,
/// } /// }
/// ///
/// let example = Example { lock: Arc::new(Mutex::new(0)) }; /// fn main() {
/// let lock = example.lock.clone(); /// let example = Example { lock: Arc::new(Mutex::new(0)) };
/// let lock = example.lock.clone();
/// ///
/// let _ = thread::spawn(move || { /// let _ = thread::spawn(move || {
/// // This thread will acquire the mutex first, unwrapping the result /// // This thread will acquire the mutex first, unwrapping the result
/// // of `lock` because the lock has not been poisoned. /// // of `lock` because the lock has not been poisoned.
/// let _guard = lock.lock().unwrap(); /// let _guard = lock.lock().unwrap();
/// ///
/// // This panic while holding the lock (`_guard` is in scope) will /// // This panic while holding the lock (`_guard` is in scope) will
/// // poison the mutex. /// // poison the mutex.
/// panic!() /// panic!()
/// }).join(); /// }).join();
/// ///
/// let expected = &[ /// let expected = &[
/// Token::Struct { name: "Example", len: 1 }, /// Token::Struct { name: "Example", len: 1 },
/// Token::Str("lock"), /// Token::Str("lock"),
/// ]; /// ];
/// let error = "lock poison error while serializing"; /// let error = "lock poison error while serializing";
/// assert_ser_tokens_error(&example, expected, error); /// assert_ser_tokens_error(&example, expected, error);
/// # } /// }
/// ``` /// ```
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: &str) pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: &str)
where where
@@ -145,13 +131,8 @@ where
/// Asserts that the given `tokens` deserialize into `value`. /// Asserts that the given `tokens` deserialize into `value`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_de_tokens, Token}; /// # use serde_test::{assert_de_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -205,13 +186,8 @@ where
/// Asserts that the given `tokens` yield `error` when deserializing. /// Asserts that the given `tokens` yield `error` when deserializing.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_de_tokens_error, Token}; /// # use serde_test::{assert_de_tokens_error, Token};
/// # /// #
/// # fn main() { /// # fn main() {
+1 -4
View File
@@ -14,10 +14,7 @@ pub struct Compact<T: ?Sized>(T);
/// Trait to determine whether a value is represented in human-readable or /// Trait to determine whether a value is represented in human-readable or
/// compact form. /// compact form.
/// ///
/// ``` /// ```edition2018
/// extern crate serde;
/// extern crate serde_test;
///
/// use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// use serde_test::{assert_tokens, Configure, Token}; /// use serde_test::{assert_tokens, Configure, Token};
/// ///
+8 -8
View File
@@ -89,11 +89,11 @@ impl<'de> Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let value = try!(visitor.visit_seq(DeserializerSeqVisitor { let value = visitor.visit_seq(DeserializerSeqVisitor {
de: self, de: self,
len: len, len: len,
end: end, end: end,
},)); })?;
assert_next_token!(self, end); assert_next_token!(self, end);
Ok(value) Ok(value)
} }
@@ -107,11 +107,11 @@ impl<'de> Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let value = try!(visitor.visit_map(DeserializerMapVisitor { let value = visitor.visit_map(DeserializerMapVisitor {
de: self, de: self,
len: len, len: len,
end: end, end: end,
},)); })?;
assert_next_token!(self, end); assert_next_token!(self, end);
Ok(value) Ok(value)
} }
@@ -456,11 +456,11 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
| Token::TupleVariant { variant: v, .. } | Token::TupleVariant { variant: v, .. }
| Token::StructVariant { variant: v, .. } => { | Token::StructVariant { variant: v, .. } => {
let de = v.into_deserializer(); let de = v.into_deserializer();
let value = try!(seed.deserialize(de)); let value = seed.deserialize(de)?;
Ok((value, self)) Ok((value, self))
} }
_ => { _ => {
let value = try!(seed.deserialize(&mut *self.de)); let value = seed.deserialize(&mut *self.de)?;
Ok((value, self)) Ok((value, self))
} }
} }
@@ -613,7 +613,7 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
len: None, len: None,
end: Token::TupleVariantEnd, end: Token::TupleVariantEnd,
}; };
try!(seed.deserialize(SeqAccessDeserializer::new(visitor))) seed.deserialize(SeqAccessDeserializer::new(visitor))?
}; };
assert_next_token!(self.de, Token::TupleVariantEnd); assert_next_token!(self.de, Token::TupleVariantEnd);
Ok(value) Ok(value)
@@ -625,7 +625,7 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
len: None, len: None,
end: Token::StructVariantEnd, end: Token::StructVariantEnd,
}; };
try!(seed.deserialize(MapAccessDeserializer::new(visitor))) seed.deserialize(MapAccessDeserializer::new(visitor))?
}; };
assert_next_token!(self.de, Token::StructVariantEnd); assert_next_token!(self.de, Token::StructVariantEnd);
Ok(value) Ok(value)
+7 -16
View File
@@ -24,19 +24,10 @@
//! //!
//! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map //! [`linked-hash-map`]: https://github.com/contain-rs/linked-hash-map
//! //!
//! ```rust //! ```edition2018
//! # extern crate serde; //! # const IGNORE: &str = stringify! {
//! #
//! # macro_rules! ignore {
//! # ($($tt:tt)+) => {}
//! # }
//! #
//! # ignore! {
//! extern crate linked_hash_map;
//! use linked_hash_map::LinkedHashMap; //! use linked_hash_map::LinkedHashMap;
//! # } //! # };
//!
//! extern crate serde_test;
//! use serde_test::{Token, assert_tokens}; //! use serde_test::{Token, assert_tokens};
//! //!
//! # use std::fmt; //! # use std::fmt;
@@ -153,19 +144,19 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.83")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.100")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints // Ignored clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))] #![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
// Whitelisted clippy_pedantic lints // Ignored clippy_pedantic lints
#![cfg_attr( #![cfg_attr(
feature = "cargo-clippy", feature = "cargo-clippy",
allow( allow(
empty_line_after_outer_attr, empty_line_after_outer_attr,
missing_docs_in_private_items, missing_docs_in_private_items,
module_name_repetitions,
redundant_field_names, redundant_field_names,
stutter,
use_debug, use_debug,
use_self use_self
) )
+2 -2
View File
@@ -427,7 +427,7 @@ impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
where where
T: Serialize, T: Serialize,
{ {
try!(key.serialize(&mut **self)); key.serialize(&mut **self)?;
value.serialize(&mut **self) value.serialize(&mut **self)
} }
@@ -449,7 +449,7 @@ impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
where where
T: Serialize, T: Serialize,
{ {
try!(key.serialize(&mut *self.ser)); key.serialize(&mut *self.ser)?;
value.serialize(&mut *self.ser) value.serialize(&mut *self.ser)
} }
+39 -84
View File
@@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Display};
pub enum Token { pub enum Token {
/// A serialized `bool`. /// A serialized `bool`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&true, &[Token::Bool(true)]); /// assert_tokens(&true, &[Token::Bool(true)]);
@@ -13,7 +13,7 @@ pub enum Token {
/// A serialized `i8`. /// A serialized `i8`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0i8, &[Token::I8(0)]); /// assert_tokens(&0i8, &[Token::I8(0)]);
@@ -22,7 +22,7 @@ pub enum Token {
/// A serialized `i16`. /// A serialized `i16`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0i16, &[Token::I16(0)]); /// assert_tokens(&0i16, &[Token::I16(0)]);
@@ -31,7 +31,7 @@ pub enum Token {
/// A serialized `i32`. /// A serialized `i32`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0i32, &[Token::I32(0)]); /// assert_tokens(&0i32, &[Token::I32(0)]);
@@ -40,7 +40,7 @@ pub enum Token {
/// A serialized `i64`. /// A serialized `i64`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0i64, &[Token::I64(0)]); /// assert_tokens(&0i64, &[Token::I64(0)]);
@@ -49,7 +49,7 @@ pub enum Token {
/// A serialized `u8`. /// A serialized `u8`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0u8, &[Token::U8(0)]); /// assert_tokens(&0u8, &[Token::U8(0)]);
@@ -58,7 +58,7 @@ pub enum Token {
/// A serialized `u16`. /// A serialized `u16`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0u16, &[Token::U16(0)]); /// assert_tokens(&0u16, &[Token::U16(0)]);
@@ -67,7 +67,7 @@ pub enum Token {
/// A serialized `u32`. /// A serialized `u32`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0u32, &[Token::U32(0)]); /// assert_tokens(&0u32, &[Token::U32(0)]);
@@ -76,7 +76,7 @@ pub enum Token {
/// A serialized `u64`. /// A serialized `u64`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0u64, &[Token::U64(0)]); /// assert_tokens(&0u64, &[Token::U64(0)]);
@@ -85,7 +85,7 @@ pub enum Token {
/// A serialized `f32`. /// A serialized `f32`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0f32, &[Token::F32(0.0)]); /// assert_tokens(&0f32, &[Token::F32(0.0)]);
@@ -94,7 +94,7 @@ pub enum Token {
/// A serialized `f64`. /// A serialized `f64`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&0f64, &[Token::F64(0.0)]); /// assert_tokens(&0f64, &[Token::F64(0.0)]);
@@ -103,7 +103,7 @@ pub enum Token {
/// A serialized `char`. /// A serialized `char`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&'\n', &[Token::Char('\n')]); /// assert_tokens(&'\n', &[Token::Char('\n')]);
@@ -112,7 +112,7 @@ pub enum Token {
/// A serialized `str`. /// A serialized `str`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// let s = String::from("transient"); /// let s = String::from("transient");
@@ -122,7 +122,7 @@ pub enum Token {
/// A borrowed `str`. /// A borrowed `str`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// let s: &str = "borrowed"; /// let s: &str = "borrowed";
@@ -132,7 +132,7 @@ pub enum Token {
/// A serialized `String`. /// A serialized `String`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// let s = String::from("owned"); /// let s = String::from("owned");
@@ -151,7 +151,7 @@ pub enum Token {
/// A serialized `Option<T>` containing none. /// A serialized `Option<T>` containing none.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// let opt = None::<char>; /// let opt = None::<char>;
@@ -163,7 +163,7 @@ pub enum Token {
/// ///
/// The tokens of the value follow after this header. /// The tokens of the value follow after this header.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// let opt = Some('c'); /// let opt = Some('c');
@@ -176,7 +176,7 @@ pub enum Token {
/// A serialized `()`. /// A serialized `()`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// assert_tokens(&(), &[Token::Unit]); /// assert_tokens(&(), &[Token::Unit]);
@@ -185,13 +185,8 @@ pub enum Token {
/// A serialized unit struct of the given name. /// A serialized unit struct of the given name.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -205,13 +200,8 @@ pub enum Token {
/// A unit variant of an enum. /// A unit variant of an enum.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -233,13 +223,8 @@ pub enum Token {
/// ///
/// After this header is the value contained in the newtype struct. /// After this header is the value contained in the newtype struct.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -259,13 +244,8 @@ pub enum Token {
/// ///
/// After this header is the value contained in the newtype variant. /// After this header is the value contained in the newtype variant.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -291,7 +271,7 @@ pub enum Token {
/// After this header are the elements of the sequence, followed by /// After this header are the elements of the sequence, followed by
/// `SeqEnd`. /// `SeqEnd`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// let vec = vec!['a', 'b', 'c']; /// let vec = vec!['a', 'b', 'c'];
@@ -312,7 +292,7 @@ pub enum Token {
/// ///
/// After this header are the elements of the tuple, followed by `TupleEnd`. /// After this header are the elements of the tuple, followed by `TupleEnd`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// let tuple = ('a', 100); /// let tuple = ('a', 100);
@@ -333,13 +313,8 @@ pub enum Token {
/// After this header are the fields of the tuple struct, followed by /// After this header are the fields of the tuple struct, followed by
/// `TupleStructEnd`. /// `TupleStructEnd`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -365,13 +340,8 @@ pub enum Token {
/// After this header are the fields of the tuple variant, followed by /// After this header are the fields of the tuple variant, followed by
/// `TupleVariantEnd`. /// `TupleVariantEnd`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -402,7 +372,7 @@ pub enum Token {
/// ///
/// After this header are the entries of the map, followed by `MapEnd`. /// After this header are the entries of the map, followed by `MapEnd`.
/// ///
/// ```rust /// ```edition2018
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// use std::collections::BTreeMap; /// use std::collections::BTreeMap;
@@ -429,13 +399,8 @@ pub enum Token {
/// ///
/// After this header are the fields of the struct, followed by `StructEnd`. /// After this header are the fields of the struct, followed by `StructEnd`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -466,13 +431,8 @@ pub enum Token {
/// After this header are the fields of the struct variant, followed by /// After this header are the fields of the struct variant, followed by
/// `StructVariantEnd`. /// `StructVariantEnd`.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
@@ -501,13 +461,8 @@ pub enum Token {
/// The header to an enum of the given name. /// The header to an enum of the given name.
/// ///
/// ```rust /// ```edition2018
/// # #[macro_use] /// # use serde::{Serialize, Deserialize};
/// # extern crate serde_derive;
/// #
/// # extern crate serde;
/// # extern crate serde_test;
/// #
/// # use serde_test::{assert_tokens, Token}; /// # use serde_test::{assert_tokens, Token};
/// # /// #
/// # fn main() { /// # fn main() {
+8 -5
View File
@@ -2,17 +2,20 @@
name = "serde_test_suite" name = "serde_test_suite"
version = "0.0.0" version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
edition = "2018"
publish = false publish = false
[features] [features]
unstable = ["serde/unstable", "compiletest_rs"] unstable = ["serde/unstable"]
[dependencies]
serde = { path = "../serde" }
[dev-dependencies] [dev-dependencies]
fnv = "1.0" fnv = "1.0"
rustc-serialize = "0.3.16" rustc-serialize = "0.3.16"
serde = { path = "../serde", features = ["rc"] } rustversion = "0.1"
serde = { path = "../serde", features = ["rc", "derive"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" } serde_test = { path = "../serde_test" }
trybuild = "1.0"
[dependencies]
compiletest_rs = { version = "0.3", optional = true, features = ["stable"] }
-11
View File
@@ -1,11 +0,0 @@
[package]
name = "serde_test_suite_deps"
version = "0.0.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false
[workspace]
[dependencies]
serde = { path = "../../serde" }
serde_derive = { path = "../../serde_derive" }
-3
View File
@@ -1,3 +0,0 @@
#![feature(/*=============================================]
#![=== Serde test suite requires a nightly compiler. ===]
#![====================================================*/)]
+2 -2
View File
@@ -1,11 +1,11 @@
[package] [package]
name = "serde_derive_tests_no_std" name = "serde_derive_tests_no_std"
version = "0.0.0" version = "0.0.0"
edition = "2018"
publish = false publish = false
[dependencies] [dependencies]
libc = { version = "0.2", default-features = false } libc = { version = "0.2", default-features = false }
serde = { path = "../../serde", default-features = false } serde = { path = "../../serde", default-features = false, features = ["derive"] }
serde_derive = { path = "../../serde_derive" }
[workspace] [workspace]
+1 -4
View File
@@ -1,8 +1,6 @@
#![feature(lang_items, start)] #![feature(lang_items, start)]
#![no_std] #![no_std]
extern crate libc;
#[start] #[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize { fn start(_argc: isize, _argv: *const *const u8) -> isize {
0 0
@@ -21,8 +19,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#[macro_use] use serde::{Serialize, Deserialize};
extern crate serde_derive;
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Unit; struct Unit;
+1 -1
View File
@@ -22,7 +22,7 @@ impl<'de> Visitor<'de> for ByteBufVisitor {
V: SeqAccess<'de>, V: SeqAccess<'de>,
{ {
let mut values = Vec::new(); let mut values = Vec::new();
while let Some(value) = try!(visitor.next_element()) { while let Some(value) = visitor.next_element()? {
values.push(value); values.push(value);
} }
Ok(values) Ok(values)
+4 -12
View File
@@ -1,15 +1,7 @@
#![cfg(feature = "unstable")] #[cfg(not(target_os = "emscripten"))]
#[rustversion::attr(not(nightly), ignore)]
extern crate compiletest_rs as compiletest;
#[test] #[test]
fn ui() { fn ui() {
let config = compiletest::Config { let t = trybuild::TestCases::new();
mode: compiletest::common::Mode::Ui, t.compile_fail("tests/ui/**/*.rs");
src_base: std::path::PathBuf::from("tests/ui"),
target_rustcflags: Some("-L deps/target/debug/deps".to_owned()),
..Default::default()
};
compiletest::run_tests(&config);
} }
+182 -17
View File
@@ -1,19 +1,14 @@
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![allow(clippy::cast_lossless, clippy::trivially_copy_pass_by_ref)]
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
#[macro_use] use serde::de::{self, MapAccess, Unexpected, Visitor};
extern crate serde_derive; use serde::{Deserialize, Deserializer, Serialize, Serializer};
extern crate serde;
use self::serde::de::{self, MapAccess, Unexpected, Visitor};
use self::serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
extern crate serde_test; use serde_test::{
use self::serde_test::{
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error, assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
assert_tokens, Token, assert_tokens, Token,
}; };
@@ -68,7 +63,7 @@ impl DeserializeWith for i32 {
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
if try!(Deserialize::deserialize(de)) { if Deserialize::deserialize(de)? {
Ok(123) Ok(123)
} else { } else {
Ok(2) Ok(2)
@@ -522,6 +517,16 @@ struct RenameStructSerializeDeserialize {
a2: i32, a2: i32,
} }
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
struct AliasStruct {
a1: i32,
#[serde(alias = "a3")]
a2: i32,
#[serde(alias = "a5", rename = "a6")]
a4: i32,
}
#[test] #[test]
fn test_rename_struct() { fn test_rename_struct() {
assert_tokens( assert_tokens(
@@ -568,6 +573,67 @@ fn test_rename_struct() {
Token::StructEnd, Token::StructEnd,
], ],
); );
assert_de_tokens(
&AliasStruct {
a1: 1,
a2: 2,
a4: 3,
},
&[
Token::Struct {
name: "AliasStruct",
len: 3,
},
Token::Str("a1"),
Token::I32(1),
Token::Str("a2"),
Token::I32(2),
Token::Str("a5"),
Token::I32(3),
Token::StructEnd,
],
);
assert_de_tokens(
&AliasStruct {
a1: 1,
a2: 2,
a4: 3,
},
&[
Token::Struct {
name: "AliasStruct",
len: 3,
},
Token::Str("a1"),
Token::I32(1),
Token::Str("a3"),
Token::I32(2),
Token::Str("a6"),
Token::I32(3),
Token::StructEnd,
],
);
}
#[test]
fn test_unknown_field_rename_struct() {
assert_de_tokens_error::<AliasStruct>(
&[
Token::Struct {
name: "AliasStruct",
len: 3,
},
Token::Str("a1"),
Token::I32(1),
Token::Str("a3"),
Token::I32(2),
Token::Str("a4"),
Token::I32(3),
],
"unknown field `a4`, expected one of `a1`, `a2`, `a6`",
);
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -598,6 +664,19 @@ enum RenameEnumSerializeDeserialize<A> {
}, },
} }
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
enum AliasEnum {
#[serde(rename = "sailor_moon", alias = "usagi_tsukino")]
SailorMoon {
a: i8,
#[serde(alias = "c")]
b: i8,
#[serde(alias = "e", rename = "f")]
d: i8,
},
}
#[test] #[test]
fn test_rename_enum() { fn test_rename_enum() {
assert_tokens( assert_tokens(
@@ -684,6 +763,71 @@ fn test_rename_enum() {
Token::StructVariantEnd, Token::StructVariantEnd,
], ],
); );
assert_de_tokens(
&AliasEnum::SailorMoon { a: 0, b: 1, d: 2 },
&[
Token::StructVariant {
name: "AliasEnum",
variant: "sailor_moon",
len: 3,
},
Token::Str("a"),
Token::I8(0),
Token::Str("b"),
Token::I8(1),
Token::Str("e"),
Token::I8(2),
Token::StructVariantEnd,
],
);
assert_de_tokens(
&AliasEnum::SailorMoon { a: 0, b: 1, d: 2 },
&[
Token::StructVariant {
name: "AliasEnum",
variant: "usagi_tsukino",
len: 3,
},
Token::Str("a"),
Token::I8(0),
Token::Str("c"),
Token::I8(1),
Token::Str("f"),
Token::I8(2),
Token::StructVariantEnd,
],
);
}
#[test]
fn test_unknown_field_rename_enum() {
assert_de_tokens_error::<AliasEnum>(
&[Token::StructVariant {
name: "AliasEnum",
variant: "SailorMoon",
len: 3,
}],
"unknown variant `SailorMoon`, expected `sailor_moon`",
);
assert_de_tokens_error::<AliasEnum>(
&[
Token::StructVariant {
name: "AliasEnum",
variant: "usagi_tsukino",
len: 3,
},
Token::Str("a"),
Token::I8(0),
Token::Str("c"),
Token::I8(1),
Token::Str("d"),
Token::I8(2),
],
"unknown field `d`, expected one of `a`, `b`, `f`",
);
} }
#[derive(Debug, PartialEq, Serialize)] #[derive(Debug, PartialEq, Serialize)]
@@ -1445,14 +1589,35 @@ impl From<Option<u32>> for EnumToU32 {
} }
} }
#[derive(Clone, Deserialize, PartialEq, Debug)]
#[serde(try_from = "u32")]
enum TryFromU32 {
One,
Two,
}
impl TryFrom<u32> for TryFromU32 {
type Error = String;
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
1 => Ok(TryFromU32::One),
2 => Ok(TryFromU32::Two),
_ => Err("out of range".to_owned()),
}
}
}
#[test] #[test]
fn test_from_into_traits() { fn test_from_into_traits() {
assert_ser_tokens::<EnumToU32>(&EnumToU32::One, &[Token::Some, Token::U32(1)]); assert_ser_tokens(&EnumToU32::One, &[Token::Some, Token::U32(1)]);
assert_ser_tokens::<EnumToU32>(&EnumToU32::Nothing, &[Token::None]); assert_ser_tokens(&EnumToU32::Nothing, &[Token::None]);
assert_de_tokens::<EnumToU32>(&EnumToU32::Two, &[Token::Some, Token::U32(2)]); assert_de_tokens(&EnumToU32::Two, &[Token::Some, Token::U32(2)]);
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(Some(5)), &[Token::None]); assert_ser_tokens(&StructFromEnum(Some(5)), &[Token::None]);
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(None), &[Token::None]); assert_ser_tokens(&StructFromEnum(None), &[Token::None]);
assert_de_tokens::<StructFromEnum>(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]); assert_de_tokens(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]);
assert_de_tokens(&TryFromU32::Two, &[Token::U32(2)]);
assert_de_tokens_error::<TryFromU32>(&[Token::U32(5)], "out of range");
} }
#[test] #[test]
-6
View File
@@ -1,10 +1,4 @@
#[macro_use]
extern crate serde_derive;
extern crate serde;
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
extern crate serde_test;
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token}; use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
use std::borrow::Cow; use std::borrow::Cow;
+97 -12
View File
@@ -1,28 +1,29 @@
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![allow(clippy::decimal_literal_representation, clippy::unreadable_literal)]
#![cfg_attr(feature = "cargo-clippy", allow(decimal_literal_representation))]
#![cfg_attr(feature = "unstable", feature(never_type))] #![cfg_attr(feature = "unstable", feature(never_type))]
#[macro_use]
extern crate serde_derive;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::default::Default; use std::default::Default;
use std::ffi::{CStr, CString, OsString}; use std::ffi::{CStr, CString, OsString};
use std::fmt::Debug;
use std::net; use std::net;
use std::num::Wrapping; use std::num::Wrapping;
use std::ops::Bound;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak as RcWeak}; use std::rc::{Rc, Weak as RcWeak};
use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize, Ordering,
};
use std::sync::{Arc, Weak as ArcWeak}; use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH}; use std::time::{Duration, UNIX_EPOCH};
extern crate serde; #[cfg(target_arch = "x86_64")]
use std::sync::atomic::{AtomicI64, AtomicU64};
use fnv::FnvHasher;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
use serde_test::{assert_de_tokens, assert_de_tokens_error, Configure, Token};
extern crate fnv;
use self::fnv::FnvHasher;
extern crate serde_test;
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, Configure, Token};
#[macro_use] #[macro_use]
mod macros; mod macros;
@@ -132,6 +133,19 @@ enum EnumOther {
Other, Other,
} }
#[derive(PartialEq, Debug)]
struct IgnoredAny;
impl<'de> Deserialize<'de> for IgnoredAny {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
serde::de::IgnoredAny::deserialize(deserializer)?;
Ok(IgnoredAny)
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
macro_rules! declare_tests { macro_rules! declare_tests {
@@ -845,6 +859,23 @@ declare_tests! {
Token::SeqEnd, Token::SeqEnd,
], ],
} }
test_bound {
Bound::Unbounded::<()> => &[
Token::Enum { name: "Bound" },
Token::Str("Unbounded"),
Token::Unit,
],
Bound::Included(0) => &[
Token::Enum { name: "Bound" },
Token::Str("Included"),
Token::U8(0),
],
Bound::Excluded(0) => &[
Token::Enum { name: "Bound" },
Token::Str("Excluded"),
Token::U8(0),
],
}
test_path { test_path {
Path::new("/usr/local/lib") => &[ Path::new("/usr/local/lib") => &[
Token::BorrowedStr("/usr/local/lib"), Token::BorrowedStr("/usr/local/lib"),
@@ -920,6 +951,21 @@ declare_tests! {
Token::SeqEnd, Token::SeqEnd,
], ],
} }
test_ignored_any {
IgnoredAny => &[
Token::Str("s"),
],
IgnoredAny => &[
Token::Seq { len: Some(1) },
Token::Bool(true),
Token::SeqEnd,
],
IgnoredAny => &[
Token::Enum { name: "E" },
Token::Str("Rust"),
Token::Unit,
],
}
} }
declare_tests! { declare_tests! {
@@ -1103,6 +1149,45 @@ fn test_never_type() {
); );
} }
#[test]
fn test_atomics() {
fn test<L, A, T>(load: L, val: T, token: Token)
where
L: Fn(&A, Ordering) -> T,
A: DeserializeOwned,
T: PartialEq + Debug,
{
let tokens = &[token];
let mut de = serde_test::Deserializer::new(tokens);
match A::deserialize(&mut de) {
Ok(v) => {
let loaded = load(&v, Ordering::SeqCst);
assert_eq!(val, loaded);
}
Err(e) => panic!("tokens failed to deserialize: {}", e),
};
if de.remaining() > 0 {
panic!("{} remaining tokens", de.remaining());
}
}
test(AtomicBool::load, true, Token::Bool(true));
test(AtomicI8::load, -127, Token::I8(-127i8));
test(AtomicI16::load, -510, Token::I16(-510i16));
test(AtomicI32::load, -131072, Token::I32(-131072i32));
test(AtomicIsize::load, -131072isize, Token::I32(-131072));
test(AtomicU8::load, 127, Token::U8(127u8));
test(AtomicU16::load, 510u16, Token::U16(510u16));
test(AtomicU32::load, 131072u32, Token::U32(131072u32));
test(AtomicUsize::load, 131072usize, Token::U32(131072));
#[cfg(target_arch = "x86_64")]
{
test(AtomicI64::load, -8589934592, Token::I64(-8589934592));
test(AtomicU64::load, 8589934592u64, Token::U64(8589934592));
}
}
declare_error_tests! { declare_error_tests! {
test_unknown_field<StructDenyUnknown> { test_unknown_field<StructDenyUnknown> {
&[ &[
+34 -7
View File
@@ -4,13 +4,10 @@
#![deny(warnings)] #![deny(warnings)]
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))] #![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
#![allow(clippy::trivially_copy_pass_by_ref)]
#[macro_use] use serde::de::DeserializeOwned;
extern crate serde_derive; use serde::{Deserialize, Deserializer, Serialize, Serializer};
extern crate serde;
use self::serde::de::{DeserializeOwned, Deserializer};
use self::serde::ser::{Serialize, Serializer};
use std::borrow::Cow; use std::borrow::Cow;
use std::marker::PhantomData; use std::marker::PhantomData;
@@ -268,7 +265,7 @@ fn test_gen() {
#[cfg(feature = "unstable")] #[cfg(feature = "unstable")]
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct NonAsciiIdents { struct NonAsciiIdents {
σ: f64, σ: f64,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -384,6 +381,8 @@ fn test_gen() {
} }
mod vis { mod vis {
use serde::{Deserialize, Serialize};
pub struct S; pub struct S;
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -523,6 +522,13 @@ fn test_gen() {
} }
assert::<FlattenWith>(); assert::<FlattenWith>();
#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct FlattenDenyUnknown<T> {
#[serde(flatten)]
t: T,
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct StaticStrStruct<'a> { struct StaticStrStruct<'a> {
a: &'a str, a: &'a str,
@@ -607,6 +613,8 @@ fn test_gen() {
mod restricted { mod restricted {
mod inner { mod inner {
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct Restricted { struct Restricted {
pub(super) a: usize, pub(super) a: usize,
@@ -664,6 +672,25 @@ fn test_gen() {
ty: &'a str, ty: &'a str,
id: String, id: String,
} }
#[derive(Serialize, Deserialize)]
struct FlattenSkipSerializing<T> {
#[serde(flatten, skip_serializing)]
#[allow(dead_code)]
flat: T,
}
#[derive(Serialize, Deserialize)]
struct FlattenSkipSerializingIf<T> {
#[serde(flatten, skip_serializing_if = "StdOption::is_none")]
flat: StdOption<T>,
}
#[derive(Serialize, Deserialize)]
struct FlattenSkipDeserializing<T> {
#[serde(flatten, skip_deserializing)]
flat: T,
}
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
+1 -4
View File
@@ -1,7 +1,4 @@
#[macro_use] use serde::Deserialize;
extern crate serde_derive;
extern crate serde_test;
use serde_test::{assert_de_tokens, Token}; use serde_test::{assert_de_tokens, Token};
#[test] #[test]
+104
View File
@@ -0,0 +1,104 @@
use serde::de::value::{Error, MapDeserializer, SeqDeserializer};
use serde::de::{
DeserializeSeed, EnumAccess, IgnoredAny, IntoDeserializer, VariantAccess, Visitor,
};
use serde::{forward_to_deserialize_any, Deserialize, Deserializer};
#[derive(PartialEq, Debug, Deserialize)]
enum Target {
Unit,
Newtype(i32),
Tuple(i32, i32),
Struct { a: i32 },
}
struct Enum(&'static str);
impl<'de> Deserializer<'de> for Enum {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_enum(self)
}
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
}
}
impl<'de> EnumAccess<'de> for Enum {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: DeserializeSeed<'de>,
{
let v = seed.deserialize(self.0.into_deserializer())?;
Ok((v, self))
}
}
impl<'de> VariantAccess<'de> for Enum {
type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> {
Ok(())
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
seed.deserialize(10i32.into_deserializer())
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let seq = SeqDeserializer::new(vec![1i32, 2].into_iter());
visitor.visit_seq(seq)
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
let map = MapDeserializer::new(vec![("a", 10i32)].into_iter());
visitor.visit_map(map)
}
}
#[test]
fn test_deserialize_enum() {
// First just make sure the Deserializer impl works
assert_eq!(Target::Unit, Target::deserialize(Enum("Unit")).unwrap());
assert_eq!(
Target::Newtype(10),
Target::deserialize(Enum("Newtype")).unwrap()
);
assert_eq!(
Target::Tuple(1, 2),
Target::deserialize(Enum("Tuple")).unwrap()
);
assert_eq!(
Target::Struct { a: 10 },
Target::deserialize(Enum("Struct")).unwrap()
);
// Now try IgnoredAny
IgnoredAny::deserialize(Enum("Unit")).unwrap();
IgnoredAny::deserialize(Enum("Newtype")).unwrap();
IgnoredAny::deserialize(Enum("Tuple")).unwrap();
IgnoredAny::deserialize(Enum("Struct")).unwrap();
}
+90 -9
View File
@@ -1,16 +1,10 @@
#![deny(trivial_numeric_casts)] #![deny(trivial_numeric_casts)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![allow(clippy::redundant_field_names)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_test;
mod bytes; mod bytes;
use self::serde_test::{ use serde::{Deserialize, Serialize};
use serde_test::{
assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token, assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_tokens, Token,
}; };
@@ -1413,6 +1407,93 @@ fn test_internally_tagged_struct() {
); );
} }
#[test]
fn test_internally_tagged_braced_struct_with_zero_fields() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type")]
struct S {}
assert_tokens(
&S {},
&[
Token::Struct { name: "S", len: 1 },
Token::Str("type"),
Token::Str("S"),
Token::StructEnd,
],
);
}
#[test]
fn test_internally_tagged_struct_with_flattened_field() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "tag_struct")]
pub struct Struct {
#[serde(flatten)]
pub flat: Enum,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "tag_enum", content = "content")]
pub enum Enum {
A(u64),
}
assert_tokens(
&Struct { flat: Enum::A(0) },
&[
Token::Map { len: None },
Token::Str("tag_struct"),
Token::Str("Struct"),
Token::Str("tag_enum"),
Token::Str("A"),
Token::Str("content"),
Token::U64(0),
Token::MapEnd,
],
);
assert_de_tokens(
&Struct { flat: Enum::A(0) },
&[
Token::Map { len: None },
Token::Str("tag_enum"),
Token::Str("A"),
Token::Str("content"),
Token::U64(0),
Token::MapEnd,
],
);
}
#[test]
fn test_untagged_enum_with_flattened_integer_key() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Untagged {
Variant {
#[serde(flatten)]
map: BTreeMap<u64, String>,
},
}
assert_tokens(
&Untagged::Variant {
map: {
let mut map = BTreeMap::new();
map.insert(100, "BTreeMap".to_owned());
map
},
},
&[
Token::Map { len: None },
Token::U64(100),
Token::Str("BTreeMap"),
Token::MapEnd,
],
);
}
#[test] #[test]
fn test_enum_in_untagged_enum() { fn test_enum_in_untagged_enum() {
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
+2 -4
View File
@@ -1,8 +1,6 @@
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))] #![allow(clippy::redundant_field_names)]
#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]
#[macro_use] use serde::{Deserialize, Serialize};
extern crate serde_derive;
mod remote { mod remote {
pub struct Unit; pub struct Unit;
+1 -2
View File
@@ -1,5 +1,4 @@
extern crate serde_test; use serde_test::{assert_tokens, Configure, Token};
use self::serde_test::{assert_tokens, Configure, Token};
use std::net; use std::net;
+48 -8
View File
@@ -1,27 +1,30 @@
#![allow(clippy::unreadable_literal)]
#![cfg_attr(feature = "unstable", feature(never_type))] #![cfg_attr(feature = "unstable", feature(never_type))]
#[macro_use]
extern crate serde_derive;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::ffi::CString; use std::ffi::CString;
use std::mem; use std::mem;
use std::net; use std::net;
use std::num::Wrapping; use std::num::Wrapping;
use std::ops::Bound;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak as RcWeak}; use std::rc::{Rc, Weak as RcWeak};
use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
AtomicUsize,
};
use std::sync::{Arc, Weak as ArcWeak}; use std::sync::{Arc, Weak as ArcWeak};
use std::time::{Duration, UNIX_EPOCH}; use std::time::{Duration, UNIX_EPOCH};
#[cfg(unix)] #[cfg(unix)]
use std::str; use std::str;
#[cfg(target_arch = "x86_64")]
use std::sync::atomic::{AtomicI64, AtomicU64};
extern crate serde_test; use fnv::FnvHasher;
use self::serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token}; use serde::Serialize;
use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token};
extern crate fnv;
use self::fnv::FnvHasher;
#[macro_use] #[macro_use]
mod macros; mod macros;
@@ -380,6 +383,23 @@ declare_tests! {
Token::StructEnd, Token::StructEnd,
], ],
} }
test_bound {
Bound::Unbounded::<()> => &[
Token::Enum { name: "Bound" },
Token::Str("Unbounded"),
Token::Unit,
],
Bound::Included(0u8) => &[
Token::Enum { name: "Bound" },
Token::Str("Included"),
Token::U8(0),
],
Bound::Excluded(0u8) => &[
Token::Enum { name: "Bound" },
Token::Str("Excluded"),
Token::U8(0),
],
}
test_path { test_path {
Path::new("/usr/local/lib") => &[ Path::new("/usr/local/lib") => &[
Token::Str("/usr/local/lib"), Token::Str("/usr/local/lib"),
@@ -470,6 +490,26 @@ declare_tests! {
Token::Str("1a"), Token::Str("1a"),
], ],
} }
test_atomic {
AtomicBool::new(false) => &[Token::Bool(false)],
AtomicBool::new(true) => &[Token::Bool(true)],
AtomicI8::new(63i8) => &[Token::I8(63i8)],
AtomicI16::new(-318i16) => &[Token::I16(-318i16)],
AtomicI32::new(65792i32) => &[Token::I32(65792i32)],
AtomicIsize::new(-65792isize) => &[Token::I64(-65792i64)],
AtomicU8::new(192u8) => &[Token::U8(192u8)],
AtomicU16::new(510u16) => &[Token::U16(510u16)],
AtomicU32::new(131072u32) => &[Token::U32(131072u32)],
AtomicUsize::new(655360usize) => &[Token::U64(655360u64)],
}
}
#[cfg(target_arch = "x86_64")]
declare_tests! {
test_atomic64 {
AtomicI64::new(-4295032832i64) => &[Token::I64(-4295032832i64)],
AtomicU64::new(12884901888u64) => &[Token::U64(12884901888u64)],
}
} }
declare_tests! { declare_tests! {
+40
View File
@@ -0,0 +1,40 @@
#[test]
fn test_gen_custom_serde() {
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(crate = "fake_serde")]
struct Foo;
// Would be overlapping if serde::Serialize were implemented
impl AssertNotSerdeSerialize for Foo {}
// Would be overlapping if serde::Deserialize were implemented
impl<'a> AssertNotSerdeDeserialize<'a> for Foo {}
fake_serde::assert::<Foo>();
}
mod fake_serde {
pub use serde::*;
pub fn assert<T>()
where
T: Serialize,
T: for<'a> Deserialize<'a>,
{
}
pub trait Serialize {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
}
pub trait Deserialize<'a>: Sized {
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error>;
}
}
trait AssertNotSerdeSerialize {}
impl<T: serde::Serialize> AssertNotSerdeSerialize for T {}
trait AssertNotSerdeDeserialize<'a> {}
impl<'a, T: serde::Deserialize<'a>> AssertNotSerdeDeserialize<'a> for T {}
-9
View File
@@ -1,14 +1,5 @@
#![deny(warnings)] #![deny(warnings)]
#[cfg(feature = "unstable")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "unstable")]
extern crate serde;
#[cfg(feature = "unstable")]
extern crate serde_test;
// This test target is convoluted with the actual #[test] in a separate file to // This test target is convoluted with the actual #[test] in a separate file to
// get it so that the stable compiler does not need to parse the code of the // get it so that the stable compiler does not need to parse the code of the
// test. If the test were written with #[cfg(feature = "unstable")] #[test] // test. If the test were written with #[cfg(feature = "unstable")] #[test]
+62 -6
View File
@@ -1,9 +1,8 @@
#[macro_use] use serde::de::value::{self, MapAccessDeserializer};
extern crate serde_derive; use serde::de::{IntoDeserializer, MapAccess, Visitor};
use serde::{Deserialize, Deserializer};
extern crate serde; use serde_test::{assert_de_tokens, Token};
use serde::de::{value, IntoDeserializer}; use std::fmt;
use serde::Deserialize;
#[test] #[test]
fn test_u32_to_enum() { fn test_u32_to_enum() {
@@ -36,3 +35,60 @@ fn test_integer128() {
// i128 to i128 // i128 to i128
assert_eq!(1i128, i128::deserialize(de_i128).unwrap()); assert_eq!(1i128, i128::deserialize(de_i128).unwrap());
} }
#[test]
fn test_map_access_to_enum() {
#[derive(PartialEq, Debug)]
struct Potential(PotentialKind);
#[derive(PartialEq, Debug, Deserialize)]
enum PotentialKind {
Airebo(Airebo),
}
#[derive(PartialEq, Debug, Deserialize)]
struct Airebo {
lj_sigma: f64,
}
impl<'de> Deserialize<'de> for Potential {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct PotentialVisitor;
impl<'de> Visitor<'de> for PotentialVisitor {
type Value = Potential;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a map")
}
fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
Deserialize::deserialize(MapAccessDeserializer::new(map)).map(Potential)
}
}
deserializer.deserialize_any(PotentialVisitor)
}
}
let expected = Potential(PotentialKind::Airebo(Airebo { lj_sigma: 14.0 }));
assert_de_tokens(
&expected,
&[
Token::Map { len: Some(1) },
Token::Str("Airebo"),
Token::Map { len: Some(1) },
Token::Str("lj_sigma"),
Token::F64(14.0),
Token::MapEnd,
Token::MapEnd,
],
);
}
+1 -2
View File
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Test<'a> { struct Test<'a> {
@@ -1,8 +1,5 @@
error: failed to parse borrowed lifetimes: "zzz" error: failed to parse borrowed lifetimes: "zzz"
--> $DIR/bad_lifetimes.rs:6:22 --> $DIR/bad_lifetimes.rs:5:22
| |
6 | #[serde(borrow = "zzz")] 5 | #[serde(borrow = "zzz")]
| ^^^^^ | ^^^^^
error: aborting due to previous error
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Test<'a> { struct Test<'a> {
@@ -1,8 +1,5 @@
error: duplicate borrowed lifetime `'a` error: duplicate borrowed lifetime `'a`
--> $DIR/duplicate_lifetime.rs:6:22 --> $DIR/duplicate_lifetime.rs:5:22
| |
6 | #[serde(borrow = "'a + 'a")] 5 | #[serde(borrow = "'a + 'a")]
| ^^^^^^^^^ | ^^^^^^^^^
error: aborting due to previous error
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Str<'a>(&'a str); struct Str<'a>(&'a str);
@@ -1,8 +1,5 @@
error: duplicate serde attribute `borrow` error: duplicate serde attribute `borrow`
--> $DIR/duplicate_variant.rs:9:13 --> $DIR/duplicate_variant.rs:8:13
| |
9 | #[serde(borrow)] 8 | #[serde(borrow)]
| ^^^^^^ | ^^^^^^
error: aborting due to previous error
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Test<'a> { struct Test<'a> {
@@ -1,8 +1,5 @@
error: at least one lifetime must be borrowed error: at least one lifetime must be borrowed
--> $DIR/empty_lifetimes.rs:6:22 --> $DIR/empty_lifetimes.rs:5:22
| |
6 | #[serde(borrow = "")] 5 | #[serde(borrow = "")]
| ^^ | ^^
error: aborting due to previous error
+1 -2
View File
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Test { struct Test {
@@ -1,9 +1,6 @@
error: field `s` has no lifetimes to borrow error: field `s` has no lifetimes to borrow
--> $DIR/no_lifetimes.rs:6:5 --> $DIR/no_lifetimes.rs:5:5
| |
6 | / #[serde(borrow)] 5 | / #[serde(borrow)]
7 | | s: String, 6 | | s: String,
| |_____________^ | |_____________^
error: aborting due to previous error
+1 -2
View File
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Str<'a>(&'a str); struct Str<'a>(&'a str);
@@ -1,9 +1,6 @@
error: #[serde(borrow)] may only be used on newtype variants error: #[serde(borrow)] may only be used on newtype variants
--> $DIR/struct_variant.rs:9:5 --> $DIR/struct_variant.rs:8:5
| |
9 | / #[serde(borrow)] 8 | / #[serde(borrow)]
10 | | S { s: Str<'a> }, 9 | | S { s: Str<'a> },
| |____________________^ | |____________________^
error: aborting due to previous error
+1 -2
View File
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
struct Test<'a> { struct Test<'a> {
@@ -1,9 +1,6 @@
error: field `s` does not have lifetime 'b error: field `s` does not have lifetime 'b
--> $DIR/wrong_lifetime.rs:6:5 --> $DIR/wrong_lifetime.rs:5:5
| |
6 | / #[serde(borrow = "'b")] 5 | / #[serde(borrow = "'b")]
7 | | s: &'a str, 6 | | s: &'a str,
| |______________^ | |______________^
error: aborting due to previous error
+1 -2
View File
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Serialize;
extern crate serde_derive;
#[derive(Serialize)] #[derive(Serialize)]
#[serde(tag = "conflict", content = "conflict")] #[serde(tag = "conflict", content = "conflict")]
@@ -1,12 +1,9 @@
error: enum tags `conflict` for type and content conflict with each other error: enum tags `conflict` for type and content conflict with each other
--> $DIR/adjacent-tag.rs:5:1 --> $DIR/adjacent-tag.rs:4:1
| |
5 | / #[serde(tag = "conflict", content = "conflict")] 4 | / #[serde(tag = "conflict", content = "conflict")]
6 | | enum E { 5 | | enum E {
7 | | A, 6 | | A,
8 | | B, 7 | | B,
9 | | } 8 | | }
| |_^ | |_^
error: aborting due to previous error
@@ -1,5 +1,6 @@
#[macro_use] use serde_derive::Serialize;
extern crate serde_derive;
use std::collections::HashMap;
#[derive(Serialize)] #[derive(Serialize)]
struct Foo(#[serde(flatten)] HashMap<String, String>); struct Foo(#[serde(flatten)] HashMap<String, String>);
@@ -1,8 +1,5 @@
error: #[serde(flatten)] cannot be used on newtype structs error: #[serde(flatten)] cannot be used on newtype structs
--> $DIR/flatten-newtype-struct.rs:5:12 --> $DIR/flatten-newtype-struct.rs:6:12
| |
5 | struct Foo(#[serde(flatten)] HashMap<String, String>); 6 | struct Foo(#[serde(flatten)] HashMap<String, String>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
@@ -1,15 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Deserialize)]
struct Foo {
#[serde(flatten, skip_deserializing)]
other: Other,
}
#[derive(Deserialize)]
struct Other {
x: u32,
}
fn main() {}
@@ -1,9 +0,0 @@
error: #[serde(flatten)] can not be combined with #[serde(skip_deserializing)]
--> $DIR/flatten-skip-deserializing.rs:6:5
|
6 | / #[serde(flatten, skip_deserializing)]
7 | | other: Other,
| |________________^
error: aborting due to previous error
@@ -1,15 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)]
struct Foo {
#[serde(flatten, skip_serializing_if = "Option::is_none")]
other: Option<Other>,
}
#[derive(Serialize)]
struct Other {
x: u32,
}
fn main() {}
@@ -1,9 +0,0 @@
error: #[serde(flatten)] can not be combined with #[serde(skip_serializing_if = "...")]
--> $DIR/flatten-skip-serializing-if.rs:6:5
|
6 | / #[serde(flatten, skip_serializing_if = "Option::is_none")]
7 | | other: Option<Other>,
| |________________________^
error: aborting due to previous error
@@ -1,15 +0,0 @@
#[macro_use]
extern crate serde_derive;
#[derive(Serialize)]
struct Foo {
#[serde(flatten, skip_serializing)]
other: Other,
}
#[derive(Serialize)]
struct Other {
x: u32,
}
fn main() {}
@@ -1,9 +0,0 @@
error: #[serde(flatten)] can not be combined with #[serde(skip_serializing)]
--> $DIR/flatten-skip-serializing.rs:6:5
|
6 | / #[serde(flatten, skip_serializing)]
7 | | other: Other,
| |________________^
error: aborting due to previous error
@@ -1,5 +1,6 @@
#[macro_use] use serde_derive::Serialize;
extern crate serde_derive;
use std::collections::HashMap;
#[derive(Serialize)] #[derive(Serialize)]
struct Foo(u32, #[serde(flatten)] HashMap<String, String>); struct Foo(u32, #[serde(flatten)] HashMap<String, String>);
@@ -1,8 +1,5 @@
error: #[serde(flatten)] cannot be used on tuple structs error: #[serde(flatten)] cannot be used on tuple structs
--> $DIR/flatten-tuple-struct.rs:5:17 --> $DIR/flatten-tuple-struct.rs:6:17
| |
5 | struct Foo(u32, #[serde(flatten)] HashMap<String, String>); 6 | struct Foo(u32, #[serde(flatten)] HashMap<String, String>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
@@ -0,0 +1,9 @@
use serde_derive::Serialize;
#[derive(Serialize)]
#[serde(from = "u64", try_from = "u64")]
struct S {
a: u8,
}
fn main() {}
@@ -0,0 +1,8 @@
error: #[serde(from = "...")] and #[serde(try_from = "...")] conflict with each other
--> $DIR/from-try-from.rs:4:1
|
4 | / #[serde(from = "u64", try_from = "u64")]
5 | | struct S {
6 | | a: u8,
7 | | }
| |_^
@@ -0,0 +1,12 @@
use serde_derive::Serialize;
#[derive(Serialize)]
#[serde(tag = "conflict")]
enum E {
A {
#[serde(alias = "conflict")]
x: (),
},
}
fn main() {}
@@ -0,0 +1,11 @@
error: variant field name `conflict` conflicts with internal tag
--> $DIR/internal-tag-alias.rs:4:1
|
4 | / #[serde(tag = "conflict")]
5 | | enum E {
6 | | A {
7 | | #[serde(alias = "conflict")]
8 | | x: (),
9 | | },
10 | | }
| |_^
+1 -2
View File
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Serialize;
extern crate serde_derive;
#[derive(Serialize)] #[derive(Serialize)]
#[serde(tag = "conflict")] #[serde(tag = "conflict")]
@@ -1,14 +1,11 @@
error: variant field name `conflict` conflicts with internal tag error: variant field name `conflict` conflicts with internal tag
--> $DIR/internal-tag.rs:5:1 --> $DIR/internal-tag.rs:4:1
| |
5 | / #[serde(tag = "conflict")] 4 | / #[serde(tag = "conflict")]
6 | | enum E { 5 | | enum E {
7 | | A { 6 | | A {
8 | | #[serde(rename = "conflict")] 7 | | #[serde(rename = "conflict")]
9 | | x: (), 8 | | x: (),
10 | | }, 9 | | },
11 | | } 10 | | }
| |_^ | |_^
error: aborting due to previous error
@@ -1,8 +1,9 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(default)] #[serde(default)]
enum E { enum E {
S { f: u8 }, S { f: u8 },
} }
fn main() {}
@@ -1,8 +1,5 @@
error: #[serde(default)] can only be used on structs with named fields error: #[serde(default)] can only be used on structs with named fields
--> $DIR/enum.rs:6:1 --> $DIR/enum.rs:5:1
| |
6 | enum E { 5 | enum E {
| ^^^^ | ^^^^
error: aborting due to previous error
@@ -1,8 +1,9 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(default = "default_e")] #[serde(default = "default_e")]
enum E { enum E {
S { f: u8 }, S { f: u8 },
} }
fn main() {}
@@ -1,8 +1,5 @@
error: #[serde(default = "...")] can only be used on structs with named fields error: #[serde(default = "...")] can only be used on structs with named fields
--> $DIR/enum_path.rs:6:1 --> $DIR/enum_path.rs:5:1
| |
6 | enum E { 5 | enum E {
| ^^^^ | ^^^^
error: aborting due to previous error
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(default)] #[serde(default)]
@@ -1,8 +1,5 @@
error: #[serde(default)] can only be used on structs with named fields error: #[serde(default)] can only be used on structs with named fields
--> $DIR/nameless_struct_fields.rs:6:9 --> $DIR/nameless_struct_fields.rs:5:9
| |
6 | struct T(u8, u8); 5 | struct T(u8, u8);
| ^^^^^^^^ | ^^^^^^^^
error: aborting due to previous error
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Deserialize;
extern crate serde_derive;
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(default = "default_t")] #[serde(default = "default_t")]
@@ -1,8 +1,5 @@
error: #[serde(default = "...")] can only be used on structs with named fields error: #[serde(default = "...")] can only be used on structs with named fields
--> $DIR/nameless_struct_fields_path.rs:6:9 --> $DIR/nameless_struct_fields_path.rs:5:9
| |
6 | struct T(u8, u8); 5 | struct T(u8, u8);
| ^^^^^^^^ | ^^^^^^^^
error: aborting due to previous error
@@ -1,5 +1,4 @@
#[macro_use] use serde_derive::Serialize;
extern crate serde_derive;
#[derive(Serialize)] #[derive(Serialize)]
struct S { struct S {
@@ -1,8 +1,5 @@
error: unknown serde field attribute `serialize` error: unknown serde field attribute `serialize`
--> $DIR/rename-and-ser.rs:6:27 --> $DIR/rename-and-ser.rs:5:27
| |
6 | #[serde(rename = "x", serialize = "y")] 5 | #[serde(rename = "x", serialize = "y")]
| ^^^^^^^^^ | ^^^^^^^^^
error: aborting due to previous error

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