Compare commits

...

216 Commits

Author SHA1 Message Date
David Tolnay b539cb45d7 Release 1.0.116 2020-09-11 11:56:19 -07:00
David Tolnay a5490e20e1 Merge pull request #1888 from joshtriplett/fix-enum-deserialization-u64
Fix hand-written enum variant deserializations to allow u64 discriminant
2020-09-11 11:55:35 -07:00
Josh Triplett 45c45e87bf Fix hand-written enum variant deserializations to allow u64 discriminant
Automatically generated enum variant deserializers allowed any integer
type as the discriminant, but the hand-written ones for specific enum
types such as Result or IpAddr only allowed types up to u32. This broke
some non-human-readable deserializers for these enums, with
deserializers that emit any integer type as a u64. Switch the visit_u32
methods to visit_u64 methods to allow discriminants to have any size up
to a u64.
2020-09-10 23:24:33 -07:00
David Tolnay 2e76f7013f Update code of conduct link 2020-09-05 13:09:37 -07:00
David Tolnay d35de19120 Merge pull request #1885 from dtolnay/qs
Replace serde_urlencoded link with serde_qs
2020-09-05 10:35:12 -07:00
David Tolnay e5b3507145 Replace serde_urlencoded link with serde_qs 2020-09-05 10:26:36 -07:00
David Tolnay 7ea7c2ceb9 Merge pull request #1882 from dtolnay/bincode
Rename TyOverby/bincode to servo/bincode
2020-08-28 15:43:00 -07:00
David Tolnay 2b5b15967e Rename TyOverby/bincode to servo/bincode 2020-08-28 15:36:51 -07:00
David Tolnay 2ef60b62ac Release 1.0.115 2020-08-10 15:51:19 -07:00
David Tolnay e6f086d85e Merge pull request #1874 from dtolnay/flatunit
Support flattening a Unit
2020-08-10 15:50:30 -07:00
David Tolnay bf76f50294 Support deserializing flattened unit 2020-08-10 15:06:52 -07:00
David Tolnay ba07075590 Support serializing flattened unit 2020-08-10 15:06:47 -07:00
David Tolnay 26186bddd1 Add test for flattened unit 2020-08-10 15:06:34 -07:00
David Tolnay 53b9871b17 Quote no longer requires high recursion 2020-07-16 10:49:16 -07:00
David Tolnay f8787c3ca8 Suppress match_like_matches_macro clippy lint 2020-07-14 18:57:26 -07:00
David Tolnay 3022064f84 Suppress option_if_let_else clippy pedantic lint 2020-07-14 18:57:24 -07:00
David Tolnay 9e140a2071 Tweak yaml format blurb 2020-07-05 20:00:33 -07:00
David Tolnay 24e6acbfae Drop 'help or discussion' issue template
Per https://github.com/serde-rs/serde#getting-help we're steering these
to Discord / Stack Overflow / Reddit / etc.

Can reconsider when GitHub Discussions is out of beta
(https://github.com/vercel/next.js/discussions).
2020-07-04 20:44:22 -07:00
David Tolnay 29c5a50935 Suppress unused_attributes warning in test suite
This test has multiple #[ignore] attributes in some configurations.

    $ cargo +beta check --test expandtest
    warning: unused attribute
     --> test_suite/tests/expandtest.rs:2:29
      |
    2 | #[cfg_attr(not(expandtest), ignore)]
      |                             ^^^^^^
      |
      = note: `#[warn(unused_attributes)]` on by default
2020-06-26 21:37:30 -07:00
David Tolnay c619b2a7c4 Suppress unknown_lints warning in test suite
When building with beta and older rustc:

    error: unknown lint: `mixed_script_confusables`
     --> test_suite/tests/test_gen.rs:7:10
      |
    7 | #![allow(mixed_script_confusables, clippy::trivially_copy_pass_by_ref)]
      |          ^^^^^^^^^^^^^^^^^^^^^^^^
      |
    note: the lint level is defined here
     --> test_suite/tests/test_gen.rs:5:9
      |
    5 | #![deny(warnings)]
      |         ^^^^^^^^
      = note: `#[deny(unknown_lints)]` implied by `#[deny(warnings)]`
2020-06-26 21:37:26 -07:00
David Tolnay 764ebd9b17 Suppress mixed_script_confusables in test suite
error: The usage of Script Group `Greek` in this crate consists solely of mixed script confusables
       --> test_suite/tests/test_gen.rs:269:9
        |
    269 |         σ: f64,
        |         ^
        |
    note: the lint level is defined here
       --> test_suite/tests/test_gen.rs:5:9
        |
    5   | #![deny(warnings)]
        |         ^^^^^^^^
        = note: `#[deny(mixed_script_confusables)]` implied by `#[deny(warnings)]`
        = note: The usage includes 'σ' (U+03C3).
        = note: Please recheck to make sure their usages are indeed what you want.
2020-06-26 19:06:13 -07:00
David Tolnay 9c6f0c3a0e Release 1.0.114 2020-06-21 17:31:02 -07:00
David Tolnay a9f8ea0a1e Simplify search for packed repr attr 2020-06-21 17:22:07 -07:00
David Tolnay 04faac962a Remove error_on_line_overflow rustfmt setting
No longer seeing warnings on this from rustfmt.
2020-06-21 16:48:22 -07:00
Tanner Rogalsky 7e5701ad2b add alignment specific packed repr tests 2020-06-21 16:46:27 -07:00
Tanner Rogalsky 1cd10a7d09 Improved packed repr matching. 2020-06-21 16:46:27 -07:00
Tanner Rogalsky d5e6436b28 Add tests validating Serialize derivation for packed structs. 2020-06-21 16:46:27 -07:00
David Tolnay 8ff11dc234 Merge pull request #1841 from dtolnay/lenhint
Remove len hint specialization
2020-06-20 19:08:34 -07:00
David Tolnay 6b3777b617 Remove len hint specialization 2020-06-20 19:02:26 -07:00
David Tolnay 7350b58f5c Release 1.0.113 2020-06-19 13:31:38 -07:00
David Tolnay 7351e0e55a Link to feature announcements where available 2020-06-19 13:30:14 -07:00
David Tolnay b3ff7e43ef Merge pull request #1827 from taiki-e/underscore_consts
Use underscore consts on Rust 1.37+
2020-06-19 13:27:33 -07:00
Taiki Endo a50e1c20e9 Use underscore consts on Rust 1.37+ 2020-06-19 15:55:43 +09:00
David Tolnay 6980727d74 Merge pull request #1840 from rw/patch-1
Add FlexBuffers to serde ecosystem list
2020-06-18 22:57:59 -07:00
Robert Winslow bb1dedf04d Add FlexBuffers to serde ecosystem list
Add FlexBuffers to serde ecosystem list
2020-06-16 13:36:14 -07:00
David Tolnay f3520e526b Release 1.0.112 2020-06-14 11:16:04 -07:00
David Tolnay e8fd2c85c3 Merge pull request #1839 from dtolnay/entry
Forward serialize_entry on flattened maps
2020-06-14 11:15:26 -07:00
David Tolnay 97962d51e2 Forward serialize_entry on flattened maps 2020-06-14 11:10:18 -07:00
David Tolnay 95b1a5d3d9 Ignore unnested_or_patterns suggesting unstable code
Clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
2020-06-10 19:41:16 -07:00
David Tolnay 0856a2c101 No need to specify Cargo.toml in package.include
Cargo.toml is always included in the published crate.
2020-06-10 01:21:19 -07:00
David Tolnay 9f331cc257 Release 1.0.111 2020-05-29 18:53:07 -07:00
David Tolnay ef16c815f6 Merge pull request #1821 from dtolnay/ungroup
Look inside of None-delimited groups when examining types
2020-05-29 18:11:14 -07:00
David Tolnay c45a809d5c Look inside of None-delimited groups when examining types 2020-05-29 17:58:34 -07:00
David Tolnay f7d06cae4c Add failing test involving macro_rules metavariable 2020-05-29 17:58:10 -07:00
David Tolnay 31fe82a215 Resolve match_wildcard_for_single_variants pedantic lint 2020-05-29 17:46:40 -07:00
David Tolnay ef6ed1d1be Copy some new links from serde.rs to the crate-level doc 2020-05-22 12:49:15 -07:00
David Tolnay 9d1251548b Mirror 'Getting help' from github readme to crates.io readme 2020-05-15 23:09:48 -07:00
David Tolnay c20730ee39 Remove reference to mozilla irc 2020-05-15 23:07:35 -07:00
David Tolnay afd51ef0f4 Merge pull request #1808 from dtolnay/help
Update 'Getting help' section
2020-05-09 23:38:40 -07:00
David Tolnay 3167f98689 Update 'Getting help' section 2020-05-09 23:34:38 -07:00
David Tolnay 078b171c1b Release 1.0.110 2020-05-09 23:06:56 -07:00
David Tolnay da8d6f678e Simplify finding of repr(packed) attributes 2020-05-09 23:02:49 -07:00
David Tolnay 548eb8f667 Format PR 1791 with rustfmt 2020-05-09 22:54:42 -07:00
David Tolnay 1fe39043ee Simplify access of packed struct fields in derived Serialize impls 2020-05-09 22:53:38 -07:00
David Tolnay c2114491ca Add test of Serialize impl for packed struct 2020-05-09 22:52:49 -07:00
alvardes 9f47c47cad Add support for packed structs. 2020-05-09 22:45:44 -07:00
David Tolnay d6b39fd2c1 Merge pull request #1807 from dtolnay/31
Add a CI builder on 1.31.0
2020-05-09 22:44:41 -07:00
David Tolnay 4d6d0ae539 Add a CI builder on 1.31.0 2020-05-09 22:38:26 -07:00
David Tolnay dda070f45c Fix borrow error on pre-NLL compilers
error[E0506]: cannot assign to `missing_content` because it is borrowed
        --> serde_derive/src/de.rs:1414:9
         |
    1388 |           .filter_map(|(i, variant)| {
         |                       -------------- borrow of `missing_content` occurs here
    ...
    1414 | /         missing_content = quote! {
    1415 | |             match __field {
    1416 | |                 #(#missing_content_arms)*
    1417 | |                 #missing_content_fallthrough
    1418 | |             }
    1419 | |         };
         | |_________^ assignment to borrowed `missing_content` occurs here

    error[E0502]: cannot borrow `missing_content_fallthrough` as immutable because it is also borrowed as mutable
        --> serde_derive/src/de.rs:1414:27
         |
    1388 |           .filter_map(|(i, variant)| {
         |                       -------------- mutable borrow occurs here
    ...
    1404 |                       missing_content_fallthrough = quote!(_ => #missing_content);
         |                       --------------------------- previous borrow occurs due to use of `missing_content_fallthrough` in closure
    ...
    1414 |           missing_content = quote! {
         |  ___________________________^
    1415 | |             match __field {
    1416 | |                 #(#missing_content_arms)*
    1417 | |                 #missing_content_fallthrough
    1418 | |             }
    1419 | |         };
         | |_________^ immutable borrow occurs here
    ...
    1622 |   }
         |   - mutable borrow ends here
         |
         = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
2020-05-09 22:37:31 -07:00
David Tolnay b97a183e82 Release 1.0.109 2020-05-09 21:00:51 -07:00
David Tolnay 9433004307 Omit missing content match if not needed 2020-05-09 20:59:01 -07:00
David Tolnay 9476838264 Omit missing content fallthrough arm if not needed 2020-05-09 20:59:00 -07:00
asdsad 172edc4cf4 Allow optional content field for adjacently tagged newtype variants
* Deserialize adjacently tagged newtype variants with optional content as None instead of erroring when content field is missing

* refactor to remove duplicate code and remove panic
2020-05-09 20:58:28 -07:00
David Tolnay 3c97e1b9a9 Format PR 1702 with rustfmt 2020-05-09 18:24:05 -07:00
ppc a81968af3c Turn panic to error in SystemTime serialization 2020-05-09 18:22:29 -07:00
David Tolnay ea2789df0f Release 1.0.108 2020-05-09 17:53:23 -07:00
David Tolnay b7cfe33101 Add example usage to Formatter Serializer impl 2020-05-09 17:48:27 -07:00
David Tolnay 1b8ebf6b64 Add 128-bit integer support for Formatter 2020-05-09 17:48:27 -07:00
David Tolnay 35ad468780 Allow serializing newtype struct to Formatter
Serialize_newtype_struct is typically expected to just pass through the
wrapped value.
2020-05-09 17:48:27 -07:00
David Tolnay 850a29beb1 Directly display to the Formatter
This allows formatter flags to take effect.
2020-05-09 17:48:26 -07:00
David Tolnay 16bf9871cd Remove serialize_unit from Formatter's impl 2020-05-09 17:48:26 -07:00
David Tolnay 6182eceed1 Move the Formatter Serializer to a module
Let's keep impls.rs for Serialize impls, which there are enough of
already.
2020-05-09 17:48:26 -07:00
David Tolnay 99bc52f685 Support no-default-features mode in Formatter's impl 2020-05-09 17:48:26 -07:00
Jethro Beekman 726ff5ed31 impl Serializer for &mut fmt::Formatter 2020-05-09 17:48:13 -07:00
David Tolnay f63acb52dc Release 1.0.107 2020-05-08 15:45:36 -07:00
David Tolnay 36a66873cc Merge pull request #1805 from dtolnay/skip
Fix indexing bug when `skip` and `other` are combined
2020-05-08 15:43:51 -07:00
David Tolnay 63809e69c7 Fix indexing bug when skip and other are combined 2020-05-08 15:39:07 -07:00
David Tolnay f44402e224 Add regression test for issue 1804 2020-05-08 15:38:44 -07:00
David Tolnay 099fa25b86 Fix unused matrix component in name of clippy job 2020-05-06 01:53:58 -07:00
David Tolnay c120c4518b Move clippy to ci.yml gated with github.event_name != 'pull_request' 2020-05-05 22:09:35 -07:00
David Tolnay 115c1b4830 Exclude expansion tests from test suite by default
This test isn't high enough signal to have all contributors run it.
2020-05-05 21:52:37 -07:00
David Tolnay 23db3a41e7 Run expansion tests only if rustfmt is present 2020-05-05 21:50:14 -07:00
David Tolnay e2ff603587 Add Actions job to run macrotest 2020-05-05 17:41:35 -07:00
David Tolnay 19a11237b8 Regenerate macrotest *.expanded.rs files
This picks up changes from a135199ab1 and 1b35c9e27e.
2020-05-05 17:23:30 -07:00
David Tolnay 732544aed6 Update to macrotest 1.0 2020-05-05 17:23:30 -07:00
David Tolnay 65dfa607c8 Update to rustversion 1.0 2020-05-05 17:23:30 -07:00
David Tolnay 59104bbc24 Remove AppVeyor configuration 2020-05-05 17:08:09 -07:00
David Tolnay 38ad09aeb7 Add Windows CI in GitHub Actions 2020-05-05 17:08:09 -07:00
David Tolnay 02631cef42 Remove clippy from main CI workflow
We don't run clippy on PRs. It is covered by a separate clippy.yml
workflow.
2020-05-05 17:04:51 -07:00
David Tolnay f369707dc5 Update build status badge to GitHub Actions 2020-05-05 16:43:36 -07:00
David Tolnay e16e924c21 Split test suite to its own Actions job
Since this step takes the longest.
2020-05-05 16:39:36 -07:00
David Tolnay 8b52ddd5b9 Add GitHub Actions workflow to run Clippy 2020-05-05 16:34:27 -07:00
David Tolnay 112f2040ea Remove Travis configuration 2020-05-05 11:33:56 -07:00
David Tolnay cd836eb3ca Try caching Cargo index to speed up 1.13 build
This one build always took several (10+) minutes on:

    Updating registry `https://github.com/rust-lang/crates.io-index`
2020-05-03 17:59:26 -07:00
David Tolnay 2b4355724e Merge pull request #1795 from serde-rs/actions
Enable GitHub Actions
2020-05-03 02:38:48 -07:00
David Tolnay 5534bf4df1 Enable GitHub Actions 2020-05-03 02:23:04 -07:00
David Tolnay 60522937af Remove CI badge from Cargo.toml
Support for badges has been deprecated by crates.io.
2020-05-01 21:11:02 -07:00
David Tolnay 29be721f79 Work around clippy redundant_field_names bug 2020-04-23 11:21:28 -07:00
David Tolnay 0c4ffad9ec Run clippy on latest nightly that has clippy 2020-04-23 10:44:12 -07:00
David Tolnay 03addbae55 Format with rustfmt 2020-03-11 2020-04-19 17:32:11 -07:00
David Tolnay 0bab6be124 Resolve redundant_pattern_matching lint 2020-04-19 17:31:15 -07:00
David Tolnay b6def5300a Resolve redundant_field_names lint in serde_derive 2020-04-05 21:07:52 -07:00
David Tolnay 1b35c9e27e Update serde_derive to tool attrs 2020-04-05 21:00:58 -07:00
David Tolnay d1564525ad Release 1.0.106 2020-04-03 14:26:42 -07:00
David Tolnay 645f672a55 Merge pull request #1768 from robo9k/dummy-const-hidden-doc
Hide generated dummy const in rustdoc
2020-04-03 14:25:50 -07:00
robo9k a135199ab1 Hide generated dummy const in rustdoc 2020-04-03 22:21:38 +02:00
David Tolnay 2a9971a69d Merge pull request #1764 from serde-rs/collect
Simplify default Serializer::collect_str implementation
2020-03-27 23:10:06 -07:00
David Tolnay e2ada0efef Simplify default Serializer::collect_str implementation 2020-03-27 22:55:25 -07:00
David Tolnay 69653a762d Release 1.0.105 2020-03-18 11:42:51 -07:00
David Tolnay c33fb95127 Merge pull request #1754 from maciejhirsz/non-std-cow-borrow
Allow #[serde(borrow)] for non-std Cow
2020-03-18 11:40:35 -07:00
Maciej Hirsz ec6ca6bf73 Allow non-std Cow borrows 2020-03-18 13:34:38 +01:00
David Tolnay 078e88b223 Select a single docs.rs build target 2020-03-17 13:31:35 -07:00
David Tolnay 1894cb703f Resolve clippy question_mark lint 2020-03-05 19:48:07 -08:00
David Tolnay 27c283ab53 Suppress wildcard import pedantic lints 2020-02-26 21:00:12 -08:00
David Tolnay 142955b109 Ignore struct_excessive_bools pedantic lint 2020-02-12 19:34:14 -08:00
David Tolnay a61cd0f236 Update ui tests to nightly-2020-02-08 2020-02-08 00:10:00 -08:00
David Tolnay cb1632e957 Fix unused_parens lint
These are left over from a series of unfortunate rustfmt interactions.
https://github.com/serde-rs/serde/commit/ee75e6c0e9e5cc359163202554feb00a28b62d0d#diff-c052b162f01a664f8184ef1855d1f1cfL767-R735
https://github.com/serde-rs/serde/commit/cc2558b0dc6fd0a40f45c5c5fc3088332b4d6cdf#diff-c052b162f01a664f8184ef1855d1f1cfL733-R738
https://github.com/serde-rs/serde/commit/9f38ca032e0735109adbde10a9f16822a4b975aa#diff-c052b162f01a664f8184ef1855d1f1cfL779-R782
2020-01-25 00:05:15 -08:00
David Tolnay dbf1f9ab8f Remove unneeded type ascription 2020-01-17 19:50:48 -08:00
David Tolnay 137ab48aff Suppress unseparated_literal_suffix lint 2020-01-17 19:50:09 -08:00
David Tolnay fc43def8a3 Merge pull request #1721 from WildCryptoFox/remove-unsafe-code
remove the tiny bit of unsafe code
2020-01-17 14:13:35 -08:00
James McGlashan 2a351016ed remove the tiny bit of unsafe code 2020-01-17 00:00:00 +00:00
David Tolnay dfa321a1dd Ignore wildcard_in_or_patterns lint 2020-01-14 20:31:03 -08:00
David Tolnay 895eb2ba6c Update ui tests to nightly-2019-12-19 2019-12-18 23:46:29 -08:00
David Tolnay cd365de70c Update ui tests to nightly-2019-12-18 2019-12-17 23:47:40 -08:00
David Tolnay 7f799f3948 Ignore missing_errors_doc pedantic lint 2019-12-15 20:16:22 -08:00
David Tolnay 234fbfd7e3 Release 1.0.104 2019-12-15 20:01:04 -08:00
David Tolnay b9909cef3d Revert "Remove never_type feature gate"
This reverts commit 533fb9cc44.
2019-12-15 19:52:59 -08:00
David Tolnay d540e72fc7 Format with rustfmt 2019-10-07 2019-11-26 00:02:11 -08:00
David Tolnay 13d0899776 Add missing import in de_enum expand test 2019-11-26 00:00:05 -08:00
David Tolnay 4fefa7a01d Format imports in expandtest inputs 2019-11-25 23:57:34 -08:00
David Tolnay 90486607a1 Update test suite to nightly-2019-11-26 2019-11-25 23:51:43 -08:00
David Tolnay 0b303c766c Mark tests ignored on emscripten rather than omitting
This way they still appear in `cargo test`'s output.
2019-11-24 17:27:30 -08:00
David Tolnay c371563bfc Reduce nesting of macrotest test cases 2019-11-24 17:25:44 -08:00
David Tolnay d17d8eb3ee Rely on std::process::Command's path search 2019-11-24 17:23:02 -08:00
David Tolnay bcaebdb2b7 Merge pull request #1662 from eupn/use-macrotest
Implement expansion tests
2019-11-24 17:14:35 -08:00
David Tolnay 43a9f59c18 Release 1.0.103 2019-11-24 16:15:13 -08:00
David Tolnay ff70409215 Merge pull request #1669 from H2CO3/master
Allow untagged unit variants to deserialize from `Visitor::visit_none()`
2019-11-24 16:13:37 -08:00
David Tolnay 97a98a7031 Test only deser for untagged unit visit_none 2019-11-24 15:59:08 -08:00
David Tolnay 533fb9cc44 Remove never_type feature gate
The stabilization for this feature has landed in nightly.
2019-11-23 19:30:39 -08:00
Árpád Goretity 59b99d2d60 Move test for untagged-variant-from-unit where it belongs 2019-11-07 21:18:12 +01:00
Árpád Goretity c796daed7c Fix test for untagged unit variant 2019-11-07 12:58:09 +01:00
Árpád Goretity 6e2c385fa5 Allow untagged unit variants to deserialize from Visitor::visit_none() 2019-11-06 17:31:27 +01:00
Evgenii P 9a0e4e0176 Ignore expansion test if cargo-expand subcommand isn't present 2019-11-03 20:31:08 +08:00
Evgenii P 640f8e0e82 Remove stdlib derives and fix expanded files to have newlines at the end 2019-11-03 20:08:39 +08:00
David Tolnay 4eb580790d Require serde_derive version to be the same as serde version
Without this, Cargo could combine new serde_derive with old serde
resulting in generated code that refers to types that don't exist yet in
the serde version.
2019-11-02 15:17:09 -07:00
David Tolnay a2c83d754b Merge pull request #1664 from mathstuf/minimal-versions-compat
serde_derive: require the same version as serde
2019-11-02 12:04:20 -07:00
Ben Boeckel 6f946b20ec serde_derive: require the same version as serde
This ensures that all features supported by serde are always available
through the derive macro provided through the feature flag.

Fixes: #1647
2019-11-01 19:47:31 -04:00
Evgenii P 4dda90502a Add *.expanded.rs files 2019-11-01 02:32:34 +08:00
Evgenii P dc6dbba47c Implement derive macros expansion tests using macrotest 2019-11-01 02:32:06 +08:00
David Tolnay 2ceabad360 Release 1.0.102 2019-10-27 13:39:27 -07:00
David Tolnay a00aee1495 Use a dedicated cfg for PathBuf::into_boxed_path 2019-10-27 13:38:25 -07:00
David Tolnay 4e31c9984d Merge pull request #1656 from heftig/path-improvements
Improve Path deserialization
2019-10-27 13:37:12 -07:00
Jan Alexander Steffens (heftig) b8772a1e40 Deserialize Box<Path> through PathBuf::into_boxed_path
Including Rc<Path> et al.

Fixes https://github.com/serde-rs/serde/issues/1633
2019-10-22 22:31:51 +02:00
Jan Alexander Steffens (heftig) 42990d8264 Deserialize PathBuf from bytes
&Path already allows this. Also complete the tests for Path/PathBuf.
2019-10-22 22:30:53 +02:00
David Tolnay cf31418555 Resolve unused_self lint 2019-10-17 11:05:30 -04:00
David Tolnay 5db72b8ad9 Ignore must_use_candidate pedantic lint 2019-10-17 11:05:28 -04:00
David Tolnay fe8f8bcf7b Address needless_doctest_main lint in serde_test 2019-10-08 21:23:17 -07:00
David Tolnay d4d737de8d Resolve redundant_clone lint 2019-10-08 21:16:45 -07:00
David Tolnay 52f6e96ee8 Ignore needless_doctest_main lint 2019-10-08 21:15:08 -07:00
David Tolnay 44fa7b0f6b Remove unused rustc-serialize dependency from test suite 2019-10-04 21:29:06 -04:00
David Tolnay bda561df4e Update test suite to nightly-2019-10-04 2019-10-03 21:45:09 -04:00
David Tolnay 8955420baf Update test suite to nightly-2019-10-02 2019-10-02 09:45:00 -04:00
David Tolnay 21ee256911 Update test suite to nightly-2019-09-30 2019-09-30 15:56:04 -04:00
David Tolnay 4aba6fae78 Release 1.0.101 2019-09-16 00:32:28 -07:00
David Tolnay fe06bc2f88 More concise explanation of allow(unused_variables) 2019-09-16 00:31:23 -07:00
David Tolnay 8dfb4cd02f Merge pull request #1617 from arilotter/master
Fix unused variable warning when field of adjacently tagged enum is skipped
2019-09-15 23:51:39 -07:00
David Tolnay d1ade37827 Ignore new too_many_lines lint 2019-09-10 23:15:59 -07:00
Ari Lotter 9de49241fb Bug fix for #1610
Allow unused variables in tuple in AdjacentlyTagged serializer
2019-09-09 10:43:05 -04:00
David Tolnay b24d50160a Remove use of ref keyword from serde_derive 2019-09-07 23:16:02 -07:00
David Tolnay e46463e69f Add tests for attribute parse errors 2019-09-07 22:57:27 -07:00
David Tolnay a3157c9572 Produce errors on attr that fails to parse as Meta 2019-09-07 22:46:50 -07:00
David Tolnay 0d4722680a Use flatten() to iterate serde meta items 2019-09-07 22:44:25 -07:00
David Tolnay 7ab12597bb Un-wrap error message strings for better grepping 2019-09-07 22:40:24 -07:00
David Tolnay b86a46c83c Factor skipping in newtype variants into effective_style 2019-09-07 22:16:56 -07:00
David Tolnay 187a0a3ec0 Format with rustfmt 2019-08-19 2019-09-07 22:16:49 -07:00
David Tolnay 111c18dec3 Merge pull request #1622 from Xaeroxe/fix-new-types
Fix (de)serialization of new types where the internal type is skipped
2019-09-07 22:16:40 -07:00
David Tolnay 7a2b137912 Reuse span in default deserialize_with path for Cows 2019-09-07 20:24:59 -07:00
David Tolnay 791b9fbe81 Release serde_derive_internals 2019-09-07 20:14:30 -07:00
David Tolnay 0fdc0257aa Sort Postcard in the same order as on the website 2019-09-07 19:10:48 -07:00
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
Jake Kiesel fcbb3d3783 Add support for other enum representations 2019-09-07 11:43:53 -06:00
Jake Kiesel acc8640c1e Fix (de)serialization of new types where the internal type is skipped 2019-09-07 03:20:43 -06: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
Zeyi Fan 4c29eea790 add attribute try_from 2019-05-11 23:31:24 -07:00
90 changed files with 7401 additions and 1441 deletions
-7
View File
@@ -1,7 +0,0 @@
---
name: Help or discussion
about: This is the right place
---
+163
View File
@@ -0,0 +1,163 @@
name: CI
on:
push:
pull_request:
schedule: [cron: "40 1 * * *"]
jobs:
test:
name: Test suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@nightly
- run: cd test_suite && cargo test --features unstable
windows:
name: Test suite (windows)
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@nightly
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
stable:
name: Rust stable
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@stable
- run: cd serde && cargo build --features rc
- run: cd serde && cargo build --no-default-features
- run: cd serde_test && cargo build
- run: cd serde_test && cargo test --features serde/derive,serde/rc
beta:
name: Rust beta
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@beta
- run: cd serde && cargo build --features rc
- run: cd test_suite && cargo test
nightly:
name: Rust nightly ${{matrix.os == 'windows' && '(windows)' || ''}}
runs-on: ${{matrix.os}}-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu, windows]
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@nightly
- run: cd serde && cargo build
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build --no-default-features --features alloc
- run: cd serde && cargo build --no-default-features --features rc,alloc
- run: cd serde && cargo test --features derive,rc,unstable
- run: cd test_suite/no_std && cargo build
if: matrix.os != 'windows'
msrv:
name: Rust 1.13.0
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@1.13.0
- name: Get timestamp for cache
id: date
run: echo ::set-output name=yearmo::$(date +%Y%m)
- uses: actions/cache@v1
with:
path: ~/.cargo/registry/index
key: cargo-registry-index-${{steps.date.outputs.yearmo}}
- run: cd serde && cargo build --features rc
- run: cd serde && cargo build --no-default-features
- run: cd serde_test && cargo build
build:
name: Rust ${{matrix.rust}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0]
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build
more:
name: Rust ${{matrix.rust}}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust: [1.27.0, 1.28.0]
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{matrix.rust}}
# Work around failing to parse manifest because editions are unstable.
- run: sed -i /test_suite/d Cargo.toml
- run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build
derive:
name: Rust 1.31.0
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@1.31.0
- run: cd serde_derive && cargo check
alloc:
name: Rust 1.36.0
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@1.36.0
- run: cd serde && cargo build --no-default-features --features alloc
emscripten:
name: Emscripten
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@nightly
- uses: actions/setup-node@v1
with:
node-version: 9
- name: Install cargo-web
run: |
CARGO_WEB_RELEASE=$(curl -L -s -H Accept:application/json https://github.com/koute/cargo-web/releases/latest)
CARGO_WEB_VERSION=$(echo "${CARGO_WEB_RELEASE}" | jq -r .tag_name)
CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/${CARGO_WEB_VERSION}/cargo-web-x86_64-unknown-linux-gnu.gz"
mkdir -p ~/.cargo/bin
curl -L "${CARGO_WEB_URL}" | gzip -d > ~/.cargo/bin/cargo-web
chmod +x ~/.cargo/bin/cargo-web
- run: cd test_suite && cargo web test --target=asmjs-unknown-emscripten --nodejs
continue-on-error: true
- run: cd test_suite && cargo web test --target=wasm32-unknown-emscripten --nodejs
continue-on-error: true
clippy:
name: Clippy
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
steps:
- uses: actions/checkout@v2
- uses: dtolnay/rust-toolchain@clippy
# The need for -Aredundant_field_names here is a Clippy bug.
# https://github.com/rust-lang/rust-clippy/issues/5356
- run: cd serde && cargo clippy --features rc,unstable -- -D clippy::all -A clippy::redundant_field_names
- run: cd serde_derive && cargo clippy -- -D clippy::all
- run: cd serde_test && cargo clippy -- -D clippy::all -A clippy::redundant_field_names
- run: cd test_suite && cargo clippy --tests --features unstable -- -D clippy::all -A clippy::redundant_field_names
- run: cd test_suite/no_std && cargo clippy -- -D clippy::all -A clippy::redundant_field_names
-99
View File
@@ -1,99 +0,0 @@
language: rust
matrix:
include:
- rust: stable
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cargo build --no-default-features
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo build
- cargo test --features serde/derive,serde/rc
- rust: beta
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo test
- rust: nightly
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build
- cargo build --no-default-features
- cargo build --no-default-features --features alloc
- cargo build --no-default-features --features rc,alloc
- cargo test --features derive,rc,unstable
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo test --features unstable
- cd "${TRAVIS_BUILD_DIR}/test_suite/no_std"
- cargo build
- rust: 1.13.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --features rc
- cargo build --no-default-features
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo build
- rust: 1.15.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo build
- rust: 1.20.0
- rust: 1.21.0
- rust: 1.25.0
- rust: 1.26.0
- rust: 1.34.0
- rust: 1.36.0
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --no-default-features --features alloc
- rust: nightly
name: Clippy
script:
- rustup component add clippy || travis_terminate 0
- cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo clippy --features rc,unstable -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde_derive"
- cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/serde_test"
- cargo clippy -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo clippy --tests --features unstable -- -D clippy::all
- cd "${TRAVIS_BUILD_DIR}/test_suite/no_std"
- cargo clippy -- -D clippy::all
- rust: nightly
name: Emscripten
script:
- CARGO_WEB_RELEASE=$(curl -L -s -H Accept:application/json https://github.com/koute/cargo-web/releases/latest)
- CARGO_WEB_VERSION=$(echo "${CARGO_WEB_RELEASE}" | jq -r .tag_name)
- CARGO_WEB_URL="https://github.com/koute/cargo-web/releases/download/${CARGO_WEB_VERSION}/cargo-web-x86_64-unknown-linux-gnu.gz"
- nvm install 9
- mkdir -p ~/.cargo/bin
- curl -L "${CARGO_WEB_URL}" | gzip -d > ~/.cargo/bin/cargo-web
- chmod +x ~/.cargo/bin/cargo-web
- cd "${TRAVIS_BUILD_DIR}/test_suite"
- cargo web test --target=asmjs-unknown-emscripten --nodejs
- cargo web test --target=wasm32-unknown-emscripten --nodejs
allow_failures:
- rust: nightly
name: Clippy
- rust: nightly
name: Emscripten
script:
- cd "${TRAVIS_BUILD_DIR}/serde"
- cargo build --no-default-features
- cargo build
+1 -6
View File
@@ -4,11 +4,6 @@ Serde welcomes contribution from everyone in the form of suggestions, bug
reports, pull requests, and feedback. This document gives some guidance if you
are thinking of helping us.
Please reach out here in a GitHub issue or in the #serde IRC channel on
[`irc.mozilla.org`] if we can do anything to help you contribute.
[`irc.mozilla.org`]: https://wiki.mozilla.org/IRC
## Submitting bug reports and feature requests
Serde development is spread across lots of repositories, but this serde-rs/serde
@@ -63,4 +58,4 @@ In all Serde-related forums, we follow the [Rust Code of Conduct]. For
escalation or moderation issues please contact Erick (erick.tryzelaar@gmail.com)
instead of the Rust moderation team.
[Rust Code of Conduct]: https://www.rust-lang.org/conduct.html
[Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct
+23 -11
View File
@@ -1,11 +1,13 @@
# Serde &emsp; [![Build Status]][travis] [![Latest Version]][crates.io] [![Rustc Version 1.13+]][rustc]
# Serde &emsp; [![Build Status]][actions] [![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
[travis]: https://travis-ci.org/serde-rs/serde
[Build Status]: https://img.shields.io/github/workflow/status/serde-rs/serde/CI/master
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde
[Rustc Version 1.13+]: https://img.shields.io/badge/rustc-1.13+-lightgray.svg
[rustc]: https://blog.rust-lang.org/2016/11/10/Rust-1.13.html
[serde: rustc 1.13+]: https://img.shields.io/badge/serde-rustc_1.13+-lightgray.svg
[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.**
@@ -73,13 +75,23 @@ fn main() {
## Getting help
Serde developers live in the #serde channel on [`irc.mozilla.org`][irc]. The
\#rust channel is also a good resource with generally faster response time but
less specific knowledge about Serde. If IRC is not your thing or you don't get a
good response, we are happy to respond to [GitHub issues][issues] as well.
Serde is one of the most widely used Rust libraries so any place that Rustaceans
congregate will be able to help you out. For chat, consider trying the
[#general] or [#beginners] channels of the unofficial community Discord, the
[#rust-usage] channel of the official Rust Project Discord, or the
[#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag
on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned
weekly easy questions post, or the Rust [Discourse forum][discourse]. It's
acceptable to file a support issue in this repo but they tend not to get as many
eyes as any of the above and may get closed without a response after some time.
[irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose
[#general]: https://discord.com/channels/273534239310479360/274215136414400513
[#beginners]: https://discord.com/channels/273534239310479360/273541522815713281
[#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848
[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general
[stackoverflow]: https://stackoverflow.com/questions/tagged/rust
[/r/rust]: https://www.reddit.com/r/rust
[discourse]: https://users.rust-lang.org
<br>
-39
View File
@@ -1,39 +0,0 @@
environment:
matrix:
- APPVEYOR_RUST_CHANNEL: stable
- APPVEYOR_RUST_CHANNEL: nightly
install:
# Install rust, x86_64-pc-windows-msvc host
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
- rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain %APPVEYOR_RUST_CHANNEL%
- set PATH=C:\msys64\usr\bin;%PATH%;C:\Users\appveyor\.cargo\bin
- rustc -vV
- cargo -vV
build: false
for:
- matrix:
only:
- APPVEYOR_RUST_CHANNEL: stable
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\serde
- cargo build --features rc
- cargo build --no-default-features
- cd %APPVEYOR_BUILD_FOLDER%\serde_test
- cargo build
- cargo test --features serde/derive,serde/rc
- matrix:
only:
- APPVEYOR_RUST_CHANNEL: nightly
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\serde
- cargo build
- cargo build --no-default-features
- cargo build --no-default-features --features alloc
- cargo build --no-default-features --features rc,alloc
- cargo test --features derive,rc,unstable
- cd %APPVEYOR_BUILD_FOLDER%\test_suite
- cargo test --features unstable
+16 -6
View File
@@ -43,10 +43,20 @@ fn main() {
## Getting help
Serde developers live in the #serde channel on [`irc.mozilla.org`][irc]. The
\#rust channel is also a good resource with generally faster response time but
less specific knowledge about Serde. If IRC is not your thing or you don't get a
good response, we are happy to respond to [GitHub issues][issues] as well.
Serde is one of the most widely used Rust libraries so any place that Rustaceans
congregate will be able to help you out. For chat, consider trying the
[#general] or [#beginners] channels of the unofficial community Discord, the
[#rust-usage] channel of the official Rust Project Discord, or the
[#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag
on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned
weekly easy questions post, or the Rust [Discourse forum][discourse]. It's
acceptable to file a support issue in this repo but they tend not to get as many
eyes as any of the above and may get closed without a response after some time.
[irc]: https://wiki.mozilla.org/IRC
[issues]: https://github.com/serde-rs/serde/issues/new/choose
[#general]: https://discord.com/channels/273534239310479360/274215136414400513
[#beginners]: https://discord.com/channels/273534239310479360/273541522815713281
[#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848
[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general
[stackoverflow]: https://stackoverflow.com/questions/tagged/rust
[/r/rust]: https://www.reddit.com/r/rust
[discourse]: https://users.rust-lang.org
-1
View File
@@ -1 +0,0 @@
error_on_line_overflow = false
+6 -7
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "1.0.96" # remember to update html_root_url
version = "1.0.116" # remember to update html_root_url and serde_derive dependency
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0"
description = "A generic serialization/deserialization framework"
@@ -10,15 +10,11 @@ documentation = "https://docs.serde.rs/serde/"
keywords = ["serde", "serialization", "no_std"]
categories = ["encoding"]
readme = "crates-io.md"
include = ["Cargo.toml", "build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
build = "build.rs"
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[dependencies]
serde_derive = { version = "1.0", optional = true, path = "../serde_derive" }
serde_derive = { version = "=1.0.116", optional = true, path = "../serde_derive" }
[dev-dependencies]
serde_derive = { version = "1.0", path = "../serde_derive" }
@@ -26,6 +22,9 @@ serde_derive = { version = "1.0", path = "../serde_derive" }
[package.metadata.playground]
features = ["derive", "rc"]
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
### FEATURES #################################################################
+10 -2
View File
@@ -29,10 +29,12 @@ fn main() {
println!("cargo:rustc-cfg=core_reverse");
}
// CString::into_boxed_c_str stabilized in Rust 1.20:
// CString::into_boxed_c_str and PathBuf::into_boxed_path 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/path/struct.PathBuf.html#method.into_boxed_path
if minor >= 20 {
println!("cargo:rustc-cfg=de_boxed_c_str");
println!("cargo:rustc-cfg=de_boxed_path");
}
// From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
@@ -64,12 +66,18 @@ fn main() {
}
// Non-zero integers stabilized in Rust 1.28:
// https://github.com/rust-lang/rust/pull/50808
// https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations
if minor >= 28 {
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.
+47 -10
View File
@@ -90,10 +90,13 @@ macro_rules! visit_integer_method {
{
match FromPrimitive::$from_method(v) {
Some(v) => Ok(v),
None => Err(Error::invalid_value(Unexpected::$group(v as $group_ty), &self)),
None => Err(Error::invalid_value(
Unexpected::$group(v as $group_ty),
&self,
)),
}
}
}
};
}
macro_rules! visit_float_method {
@@ -105,7 +108,7 @@ macro_rules! visit_float_method {
{
Ok(v as Self::Value)
}
}
};
}
macro_rules! impl_deserialize_num {
@@ -1310,7 +1313,7 @@ macro_rules! variant_identifier {
formatter.write_str($expecting_message)
}
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: Error,
{
@@ -1318,7 +1321,7 @@ macro_rules! variant_identifier {
$(
$index => Ok($name_kind :: $variant),
)*
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),),
_ => Err(Error::invalid_value(Unexpected::Unsigned(value), &self),),
}
}
@@ -1580,6 +1583,24 @@ impl<'de> Visitor<'de> for PathBufVisitor {
{
Ok(From::from(v))
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
str::from_utf8(v)
.map(From::from)
.map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self))
}
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
where
E: Error,
{
String::from_utf8(v)
.map(From::from)
.map_err(|e| Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self))
}
}
#[cfg(feature = "std")]
@@ -1592,6 +1613,9 @@ impl<'de> Deserialize<'de> for PathBuf {
}
}
#[cfg(all(feature = "std", de_boxed_path))]
forwarded_impl!((), Box<Path>, PathBuf::into_boxed_path);
////////////////////////////////////////////////////////////////////////////////
// If this were outside of the serde crate, it would just use:
@@ -2302,7 +2326,7 @@ where
formatter.write_str("`Unbounded`, `Included` or `Excluded`")
}
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: Error,
{
@@ -2311,7 +2335,7 @@ where
1 => Ok(Field::Included),
2 => Ok(Field::Excluded),
_ => Err(Error::invalid_value(
Unexpected::Unsigned(value as u64),
Unexpected::Unsigned(value),
&self,
)),
}
@@ -2404,7 +2428,6 @@ macro_rules! nonzero_integers {
}
nonzero_integers! {
// Not including signed NonZeroI* since they might be removed
NonZeroU8,
NonZeroU16,
NonZeroU32,
@@ -2412,12 +2435,26 @@ nonzero_integers! {
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
// additional `#[cfg]`
serde_if_integer128! {
nonzero_integers! {
NonZeroU128,
}
#[cfg(num_nonzero_signed)]
nonzero_integers! {
NonZeroI128,
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -2455,7 +2492,7 @@ where
formatter.write_str("`Ok` or `Err`")
}
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: Error,
{
@@ -2463,7 +2500,7 @@ where
0 => Ok(Field::Ok),
1 => Ok(Field::Err),
_ => Err(Error::invalid_value(
Unexpected::Unsigned(value as u64),
Unexpected::Unsigned(value),
&self,
)),
}
+10 -3
View File
@@ -104,7 +104,7 @@
//! [`Deserialize`]: ../trait.Deserialize.html
//! [`Deserializer`]: ../trait.Deserializer.html
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
//! [`bincode`]: https://github.com/TyOverby/bincode
//! [`bincode`]: https://github.com/servo/bincode
//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
//! [`serde_derive`]: https://crates.io/crates/serde_derive
//! [`serde_json`]: https://github.com/serde-rs/json
@@ -125,6 +125,13 @@ mod utf8;
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 {
@@ -288,7 +295,7 @@ macro_rules! declare_error_trait {
}
#[cfg(feature = "std")]
declare_error_trait!(Error: Sized + error::Error);
declare_error_trait!(Error: Sized + StdError);
#[cfg(not(feature = "std"))]
declare_error_trait!(Error: Sized + Debug + Display);
@@ -787,7 +794,7 @@ where
///
/// The role of this trait is to define the deserialization half of the [Serde
/// data model], which is a way to categorize every Rust data type into one of
/// 29 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.
///
/// Implementations of `Deserialize` map themselves into this data model by
+3
View File
@@ -11,6 +11,9 @@ pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::{ToString, Vec};
#[cfg(core_try_from)]
pub use lib::convert::TryFrom;
mod string {
use lib::*;
+34 -8
View File
@@ -37,8 +37,8 @@
//! used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//! size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//! language.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//! markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
@@ -47,14 +47,19 @@
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//! definition.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [URL], the x-www-form-urlencoded format.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//! *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//! Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//! Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [Bincode]: https://github.com/servo/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
@@ -64,30 +69,36 @@
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.96")]
#![doc(html_root_url = "https://docs.rs/serde/1.0.116")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
// https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![allow(unknown_lints, bare_trait_objects)]
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
unnested_or_patterns,
// not available in our oldest supported compiler
checked_conversions,
empty_enum,
@@ -100,18 +111,30 @@
// things are often more readable this way
cast_lossless,
module_name_repetitions,
option_if_let_else,
single_match_else,
type_complexity,
use_self,
zero_prefixed_literal,
// correctly used
enum_glob_use,
wildcard_imports,
// not practical
needless_pass_by_value,
similar_names,
too_many_lines,
// preference
doc_markdown,
unseparated_literal_suffix,
// false positive
needless_doctest_main,
// noisy
missing_errors_doc,
must_use_candidate,
)
)]
// Rustc lints.
#![forbid(unsafe_code)]
#![deny(missing_docs, unused_imports)]
////////////////////////////////////////////////////////////////////////////////
@@ -248,6 +271,9 @@ pub mod export;
#[doc(hidden)]
pub mod private;
#[cfg(not(feature = "std"))]
mod std_error;
// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
+25 -8
View File
@@ -53,9 +53,10 @@ where
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn borrow_cow_str<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, str>, D::Error>
pub fn borrow_cow_str<'de: 'a, 'a, D, R>(deserializer: D) -> Result<R, D::Error>
where
D: Deserializer<'de>,
R: From<Cow<'a, str>>,
{
struct CowStrVisitor;
@@ -121,13 +122,14 @@ where
}
}
deserializer.deserialize_str(CowStrVisitor)
deserializer.deserialize_str(CowStrVisitor).map(From::from)
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn borrow_cow_bytes<'de: 'a, 'a, D>(deserializer: D) -> Result<Cow<'a, [u8]>, D::Error>
pub fn borrow_cow_bytes<'de: 'a, 'a, D, R>(deserializer: D) -> Result<R, D::Error>
where
D: Deserializer<'de>,
R: From<Cow<'a, [u8]>>,
{
struct CowBytesVisitor;
@@ -181,7 +183,9 @@ where
}
}
deserializer.deserialize_bytes(CowBytesVisitor)
deserializer
.deserialize_bytes(CowBytesVisitor)
.map(From::from)
}
pub mod size_hint {
@@ -1558,7 +1562,7 @@ mod content {
other.unexpected(),
&"struct variant",
)),
_ => Err(de::Error::invalid_type(
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"struct variant",
)),
@@ -2248,7 +2252,7 @@ mod content {
other.unexpected(),
&"struct variant",
)),
_ => Err(de::Error::invalid_type(
None => Err(de::Error::invalid_type(
de::Unexpected::UnitVariant,
&"struct variant",
)),
@@ -2470,7 +2474,7 @@ mod content {
where
M: MapAccess<'de>,
{
while let Some(_) = try!(access.next_entry::<IgnoredAny, IgnoredAny>()) {}
while try!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
Ok(())
}
}
@@ -2510,6 +2514,13 @@ mod content {
{
Ok(())
}
fn visit_none<E>(self) -> Result<(), E>
where
E: de::Error,
{
Ok(())
}
}
}
@@ -2752,6 +2763,13 @@ where
}
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}
forward_to_deserialize_other! {
deserialize_bool()
deserialize_i8()
@@ -2769,7 +2787,6 @@ where
deserialize_string()
deserialize_bytes()
deserialize_byte_buf()
deserialize_unit()
deserialize_unit_struct(&'static str)
deserialize_seq()
deserialize_tuple(usize)
+34 -22
View File
@@ -1032,7 +1032,7 @@ impl<'a, M> FlatMapSerializer<'a, M>
where
M: SerializeMap + 'a,
{
fn bad_type(self, what: Unsupported) -> M::Error {
fn bad_type(what: Unsupported) -> M::Error {
ser::Error::custom(format_args!(
"can only flatten structs and maps (got {})",
what
@@ -1057,59 +1057,59 @@ where
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Boolean))
Err(Self::bad_type(Unsupported::Boolean))
}
fn serialize_i8(self, _: i8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_i16(self, _: i16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_i32(self, _: i32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_i64(self, _: i64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_u8(self, _: u8) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_u16(self, _: u16) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_u32(self, _: u32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_u64(self, _: u64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Integer))
Err(Self::bad_type(Unsupported::Integer))
}
fn serialize_f32(self, _: f32) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
Err(Self::bad_type(Unsupported::Float))
}
fn serialize_f64(self, _: f64) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Float))
Err(Self::bad_type(Unsupported::Float))
}
fn serialize_char(self, _: char) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Char))
Err(Self::bad_type(Unsupported::Char))
}
fn serialize_str(self, _: &str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::String))
Err(Self::bad_type(Unsupported::String))
}
fn serialize_bytes(self, _: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::ByteArray))
Err(Self::bad_type(Unsupported::ByteArray))
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
@@ -1124,11 +1124,11 @@ where
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Unit))
Ok(())
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::UnitStruct))
Err(Self::bad_type(Unsupported::UnitStruct))
}
fn serialize_unit_variant(
@@ -1137,7 +1137,7 @@ where
_: u32,
_: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
Err(Self::bad_type(Unsupported::Enum))
}
fn serialize_newtype_struct<T: ?Sized>(
@@ -1166,11 +1166,11 @@ where
}
fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(self.bad_type(Unsupported::Sequence))
Err(Self::bad_type(Unsupported::Sequence))
}
fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(self.bad_type(Unsupported::Tuple))
Err(Self::bad_type(Unsupported::Tuple))
}
fn serialize_tuple_struct(
@@ -1178,7 +1178,7 @@ where
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(self.bad_type(Unsupported::TupleStruct))
Err(Self::bad_type(Unsupported::TupleStruct))
}
fn serialize_tuple_variant(
@@ -1188,7 +1188,7 @@ where
_: &'static str,
_: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(self.bad_type(Unsupported::Enum))
Err(Self::bad_type(Unsupported::Enum))
}
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -1243,6 +1243,18 @@ where
self.0.serialize_value(value)
}
fn serialize_entry<K: ?Sized, V: ?Sized>(
&mut self,
key: &K,
value: &V,
) -> Result<(), Self::Error>
where
K: Serialize,
V: Serialize,
{
self.0.serialize_entry(key, value)
}
fn end(self) -> Result<(), Self::Error> {
Ok(())
}
+174
View File
@@ -0,0 +1,174 @@
use lib::*;
use ser::{Error, Impossible, Serialize, Serializer};
impl Error for fmt::Error {
fn custom<T: Display>(_msg: T) -> Self {
fmt::Error
}
}
macro_rules! fmt_primitives {
($($f:ident: $t:ty,)*) => {
$(
fn $f(self, v: $t) -> fmt::Result {
Display::fmt(&v, self)
}
)*
};
}
/// ```edition2018
/// use serde::Serialize;
/// use std::fmt::{self, Display};
///
/// #[derive(Serialize)]
/// #[serde(rename_all = "kebab-case")]
/// pub enum MessageType {
/// StartRequest,
/// EndRequest,
/// }
///
/// impl Display for MessageType {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// self.serialize(f)
/// }
/// }
/// ```
impl<'a, 'b> Serializer for &'a mut fmt::Formatter<'b> {
type Ok = ();
type Error = fmt::Error;
type SerializeSeq = Impossible<(), fmt::Error>;
type SerializeTuple = Impossible<(), fmt::Error>;
type SerializeTupleStruct = Impossible<(), fmt::Error>;
type SerializeTupleVariant = Impossible<(), fmt::Error>;
type SerializeMap = Impossible<(), fmt::Error>;
type SerializeStruct = Impossible<(), fmt::Error>;
type SerializeStructVariant = Impossible<(), fmt::Error>;
fmt_primitives! {
serialize_bool: bool,
serialize_i8: i8,
serialize_i16: i16,
serialize_i32: i32,
serialize_i64: i64,
serialize_u8: u8,
serialize_u16: u16,
serialize_u32: u32,
serialize_u64: u64,
serialize_f32: f32,
serialize_f64: f64,
serialize_char: char,
serialize_str: &str,
serialize_unit_struct: &'static str,
}
serde_if_integer128! {
fmt_primitives! {
serialize_i128: i128,
serialize_u128: u128,
}
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> fmt::Result {
Display::fmt(variant, self)
}
fn serialize_newtype_struct<T: ?Sized>(self, _name: &'static str, value: &T) -> fmt::Result
where
T: Serialize,
{
Serialize::serialize(value, self)
}
fn serialize_bytes(self, _v: &[u8]) -> fmt::Result {
Err(fmt::Error)
}
fn serialize_none(self) -> fmt::Result {
Err(fmt::Error)
}
fn serialize_some<T: ?Sized>(self, _value: &T) -> fmt::Result
where
T: Serialize,
{
Err(fmt::Error)
}
fn serialize_unit(self) -> fmt::Result {
Err(fmt::Error)
}
fn serialize_newtype_variant<T: ?Sized>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> fmt::Result
where
T: Serialize,
{
Err(fmt::Error)
}
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, fmt::Error> {
Err(fmt::Error)
}
fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, fmt::Error> {
Err(fmt::Error)
}
fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, fmt::Error> {
Err(fmt::Error)
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, fmt::Error> {
Err(fmt::Error)
}
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, fmt::Error> {
Err(fmt::Error)
}
fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, fmt::Error> {
Err(fmt::Error)
}
fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, fmt::Error> {
Err(fmt::Error)
}
fn collect_str<T: ?Sized>(self, value: &T) -> fmt::Result
where
T: Display,
{
Display::fmt(value, self)
}
}
+17 -5
View File
@@ -481,7 +481,6 @@ macro_rules! nonzero_integers {
}
nonzero_integers! {
// Not including signed NonZeroI* since they might be removed
NonZeroU8,
NonZeroU16,
NonZeroU32,
@@ -489,12 +488,26 @@ nonzero_integers! {
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
// additional `#[cfg]`
serde_if_integer128! {
nonzero_integers! {
NonZeroU128,
}
#[cfg(num_nonzero_signed)]
nonzero_integers! {
NonZeroI128,
}
}
impl<T> Serialize for Cell<T>
@@ -603,7 +616,7 @@ impl Serialize for SystemTime {
use super::SerializeStruct;
let duration_since_epoch = self
.duration_since(UNIX_EPOCH)
.expect("SystemTime must be later than UNIX_EPOCH");
.map_err(|_| S::Error::custom("SystemTime must be later than UNIX_EPOCH"))?;
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
@@ -620,8 +633,7 @@ impl Serialize for SystemTime {
#[cfg(feature = "std")]
macro_rules! serialize_display_bounded_length {
($value:expr, $max:expr, $serializer:expr) => {{
#[allow(deprecated)]
let mut buffer: [u8; $max] = unsafe { mem::uninitialized() };
let mut buffer = [0u8; $max];
let remaining_len = {
let mut remaining = &mut buffer[..];
write!(remaining, "{}", $value).unwrap();
@@ -633,7 +645,7 @@ macro_rules! serialize_display_bounded_length {
// write! only provides fmt::Formatter to Display implementations, which
// has methods write_str and write_char but no method to write arbitrary
// bytes. Therefore `written` must be valid UTF-8.
let written_str = unsafe { str::from_utf8_unchecked(written) };
let written_str = str::from_utf8(written).expect("must be valid UTF-8");
$serializer.serialize_str(written_str)
}};
}
+13 -37
View File
@@ -99,7 +99,7 @@
//! [`LinkedHashMap<K, V>`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html
//! [`Serialize`]: ../trait.Serialize.html
//! [`Serializer`]: ../trait.Serializer.html
//! [`bincode`]: https://github.com/TyOverby/bincode
//! [`bincode`]: https://github.com/servo/bincode
//! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map
//! [`serde_derive`]: https://crates.io/crates/serde_derive
//! [`serde_json`]: https://github.com/serde-rs/json
@@ -109,11 +109,19 @@
use lib::*;
mod fmt;
mod impls;
mod 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 {
@@ -172,7 +180,7 @@ macro_rules! declare_error_trait {
}
#[cfg(feature = "std")]
declare_error_trait!(Error: Sized + error::Error);
declare_error_trait!(Error: Sized + StdError);
#[cfg(not(feature = "std"))]
declare_error_trait!(Error: Sized + Debug + Display);
@@ -1270,7 +1278,7 @@ pub trait Serializer: Sized {
<I as IntoIterator>::Item: Serialize,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iter.len_hint()));
let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter)));
for item in iter {
try!(serializer.serialize_element(&item));
}
@@ -1310,7 +1318,7 @@ pub trait Serializer: Sized {
I: IntoIterator<Item = (K, V)>,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iter.len_hint()));
let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter)));
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
}
@@ -1352,10 +1360,7 @@ pub trait Serializer: Sized {
where
T: Display,
{
use lib::fmt::Write;
let mut string = String::new();
write!(string, "{}", value).unwrap();
self.serialize_str(&string)
self.serialize_str(&value.to_string())
}
/// Serialize a string produced by an implementation of `Display`.
@@ -1948,35 +1953,6 @@ pub trait SerializeStructVariant {
fn end(self) -> Result<Self::Ok, Self::Error>;
}
trait LenHint: Iterator {
fn len_hint(&self) -> Option<usize>;
}
impl<I> LenHint for I
where
I: Iterator,
{
#[cfg(not(feature = "unstable"))]
fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
#[cfg(feature = "unstable")]
default fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
}
#[cfg(feature = "unstable")]
impl<I> LenHint for I
where
I: ExactSizeIterator,
{
fn len_hint(&self) -> Option<usize> {
Some(self.len())
}
}
fn iterator_len_hint<I>(iter: &I) -> Option<usize>
where
I: Iterator,
+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
}
}
+8 -9
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive"
version = "1.0.96" # remember to update html_root_url
version = "1.0.116" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -9,11 +9,7 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://serde.rs/derive.html"
keywords = ["serde", "serialization", "no_std"]
readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[features]
default = []
@@ -24,9 +20,12 @@ name = "serde_derive"
proc-macro = true
[dependencies]
proc-macro2 = "0.4"
quote = "0.6.3"
syn = { version = "0.15.22", features = ["visit"] }
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0.33", features = ["visit"] }
[dev-dependencies]
serde = { version = "1.0", path = "../serde" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+30
View File
@@ -0,0 +1,30 @@
use std::env;
use std::process::Command;
use std::str;
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
let minor = match rustc_minor_version() {
Some(minor) => minor,
None => return,
};
// Underscore const names stabilized in Rust 1.37:
// https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html#using-unnamed-const-items-for-macros
if minor >= 37 {
println!("cargo:rustc-cfg=underscore_consts");
}
}
fn rustc_minor_version() -> Option<u32> {
let rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
let version = str::from_utf8(&output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
pieces.next()?.parse().ok()
}
+19 -19
View File
@@ -5,7 +5,7 @@ use syn::punctuated::{Pair, Punctuated};
use syn::visit::{self, Visit};
use internals::ast::{Container, Data};
use internals::attr;
use internals::{attr, ungroup};
use proc_macro2::Span;
@@ -17,8 +17,8 @@ pub fn without_defaults(generics: &syn::Generics) -> syn::Generics {
params: generics
.params
.iter()
.map(|param| match *param {
syn::GenericParam::Type(ref param) => syn::GenericParam::Type(syn::TypeParam {
.map(|param| match param {
syn::GenericParam::Type(param) => syn::GenericParam::Type(syn::TypeParam {
eq_token: None,
default: None,
..param.clone()
@@ -63,8 +63,8 @@ pub fn with_where_predicates_from_variants(
generics: &syn::Generics,
from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>,
) -> syn::Generics {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return generics.clone();
}
@@ -114,8 +114,8 @@ pub fn with_bound(
}
impl<'ast> Visit<'ast> for FindTyParams<'ast> {
fn visit_field(&mut self, field: &'ast syn::Field) {
if let syn::Type::Path(ref ty) = field.ty {
if let Some(Pair::Punctuated(ref t, _)) = ty.path.segments.first() {
if let syn::Type::Path(ty) = ungroup(&field.ty) {
if let Some(Pair::Punctuated(t, _)) = ty.path.segments.pairs().next() {
if self.all_type_params.contains(&t.ident) {
self.associated_type_usage.push(ty);
}
@@ -126,7 +126,7 @@ pub fn with_bound(
fn visit_path(&mut self, path: &'ast syn::Path) {
if let Some(seg) = path.segments.last() {
if seg.into_value().ident == "PhantomData" {
if seg.ident == "PhantomData" {
// Hardcoded exception, because PhantomData<T> implements
// Serialize and Deserialize whether or not T implements it.
return;
@@ -156,12 +156,12 @@ pub fn with_bound(
.collect();
let mut visitor = FindTyParams {
all_type_params: all_type_params,
all_type_params,
relevant_type_params: HashSet::new(),
associated_type_usage: Vec::new(),
};
match cont.data {
Data::Enum(ref variants) => {
match &cont.data {
Data::Enum(variants) => {
for variant in variants.iter() {
let relevant_fields = variant
.fields
@@ -172,7 +172,7 @@ pub fn with_bound(
}
}
}
Data::Struct(_, ref fields) => {
Data::Struct(_, fields) => {
for field in fields.iter().filter(|field| filter(&field.attrs, None)) {
visitor.visit_field(field.original);
}
@@ -255,11 +255,11 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
let params = Some(syn::GenericParam::Lifetime(def))
.into_iter()
.chain(generics.params.iter().cloned().map(|mut param| {
match param {
syn::GenericParam::Lifetime(ref mut param) => {
match &mut param {
syn::GenericParam::Lifetime(param) => {
param.bounds.push(bound.clone());
}
syn::GenericParam::Type(ref mut param) => {
syn::GenericParam::Type(param) => {
param
.bounds
.push(syn::TypeParamBound::Lifetime(bound.clone()));
@@ -271,7 +271,7 @@ pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Gen
.collect();
syn::Generics {
params: params,
params,
..generics.clone()
}
}
@@ -291,14 +291,14 @@ fn type_of_item(cont: &Container) -> syn::Type {
.generics
.params
.iter()
.map(|param| match *param {
syn::GenericParam::Type(ref param) => {
.map(|param| match param {
syn::GenericParam::Type(param) => {
syn::GenericArgument::Type(syn::Type::Path(syn::TypePath {
qself: None,
path: param.ident.clone().into(),
}))
}
syn::GenericParam::Lifetime(ref param) => {
syn::GenericParam::Lifetime(param) => {
syn::GenericArgument::Lifetime(param.lifetime.clone())
}
syn::GenericParam::Const(_) => {
+155 -117
View File
@@ -8,7 +8,7 @@ use bound;
use dummy;
use fragment::{Expr, Fragment, Match, Stmts};
use internals::ast::{Container, Data, Field, Style, Variant};
use internals::{attr, Ctxt, Derive};
use internals::{attr, ungroup, Ctxt, Derive};
use pretend;
use std::collections::BTreeSet;
@@ -20,7 +20,7 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<TokenStream
None => return Err(ctxt.check().unwrap_err()),
};
precondition(&ctxt, &cont);
try!(ctxt.check());
ctxt.check()?;
let ident = &cont.ident;
let params = Parameters::new(&cont);
@@ -75,9 +75,9 @@ fn precondition(cx: &Ctxt, cont: &Container) {
}
fn precondition_sized(cx: &Ctxt, cont: &Container) {
if let Data::Struct(_, ref fields) = cont.data {
if let Data::Struct(_, fields) = &cont.data {
if let Some(last) = fields.last() {
if let syn::Type::Slice(_) = *last.ty {
if let syn::Type::Slice(_) = ungroup(last.ty) {
cx.error_spanned_by(
cont.original,
"cannot deserialize a dynamically sized struct",
@@ -134,18 +134,18 @@ impl Parameters {
let has_getter = cont.data.has_getter();
Parameters {
local: local,
this: this,
generics: generics,
borrowed: borrowed,
has_getter: has_getter,
local,
this,
generics,
borrowed,
has_getter,
}
}
/// Type name to use in error messages and `&'static str` arguments to
/// various Deserializer methods.
fn type_name(&self) -> String {
self.this.segments.last().unwrap().value().ident.to_string()
self.this.segments.last().unwrap().ident.to_string()
}
}
@@ -229,8 +229,8 @@ impl BorrowedLifetimes {
}
fn de_lifetime_def(&self) -> Option<syn::LifetimeDef> {
match *self {
BorrowedLifetimes::Borrowed(ref bounds) => Some(syn::LifetimeDef {
match self {
BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeDef {
attrs: Vec::new(),
lifetime: syn::Lifetime::new("'de", Span::call_site()),
colon_token: None,
@@ -269,22 +269,22 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
deserialize_transparent(cont, params)
} else if let Some(type_from) = cont.attrs.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() {
match cont.data {
Data::Enum(ref variants) => deserialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, ref fields) => {
match &cont.data {
Data::Enum(variants) => deserialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, fields) => {
deserialize_struct(None, params, fields, &cont.attrs, None, &Untagged::No)
}
Data::Struct(Style::Tuple, ref fields) | Data::Struct(Style::Newtype, ref fields) => {
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
deserialize_tuple(None, params, fields, &cont.attrs, None)
}
Data::Struct(Style::Unit, _) => deserialize_unit_struct(params, &cont.attrs),
}
} else {
match cont.data {
Data::Enum(ref variants) => {
deserialize_custom_identifier(params, variants, &cont.attrs)
}
match &cont.data {
Data::Enum(variants) => deserialize_custom_identifier(params, variants, &cont.attrs),
Data::Struct(_, _) => unreachable!("checked in serde_derive_internals"),
}
}
@@ -298,6 +298,7 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<St
if cont.attrs.transparent()
|| cont.attrs.type_from().is_some()
|| cont.attrs.type_try_from().is_some()
|| cont.attrs.identifier().is_some()
|| cont
.data
@@ -307,16 +308,11 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<St
return None;
}
let code = match cont.data {
Data::Struct(Style::Struct, ref fields) => {
if let Some(code) = deserialize_struct_in_place(None, params, fields, &cont.attrs, None)
{
code
} else {
return None;
}
let code = match &cont.data {
Data::Struct(Style::Struct, fields) => {
deserialize_struct_in_place(None, params, fields, &cont.attrs, None)?
}
Data::Struct(Style::Tuple, ref fields) | Data::Struct(Style::Newtype, ref fields) => {
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
deserialize_tuple_in_place(None, params, fields, &cont.attrs, None)
}
Data::Enum(_) | Data::Struct(Style::Unit, _) => {
@@ -345,8 +341,8 @@ fn deserialize_in_place_body(_cont: &Container, _params: &Parameters) -> Option<
}
fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
let fields = match cont.data {
Data::Struct(_, ref fields) => fields,
let fields = match &cont.data {
Data::Struct(_, fields) => fields,
Data::Enum(_) => unreachable!(),
};
@@ -366,9 +362,9 @@ fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
if field as *const Field == transparent_field as *const Field {
quote!(#member: __transparent)
} else {
let value = match *field.attrs.default() {
let value = match field.attrs.default() {
attr::Default::Default => quote!(_serde::export::Default::default()),
attr::Default::Path(ref path) => quote!(#path()),
attr::Default::Path(path) => quote!(#path()),
attr::Default::None => quote!(_serde::export::PhantomData),
};
quote!(#member: #value)
@@ -390,6 +386,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 {
let this = &params.this;
let type_name = cattrs.name().deserialize_name();
@@ -445,7 +449,7 @@ fn deserialize_tuple(
let is_enum = variant_ident.is_some();
let type_path = match variant_ident {
Some(ref variant_ident) => quote!(#construct::#variant_ident),
Some(variant_ident) => quote!(#construct::#variant_ident),
None => construct,
};
let expecting = match variant_ident {
@@ -653,9 +657,9 @@ fn deserialize_seq(
})
}
};
let value_if_none = match *field.attrs.default() {
let value_if_none = match field.attrs.default() {
attr::Default::Default => quote!(_serde::export::Default::default()),
attr::Default::Path(ref path) => quote!(#path()),
attr::Default::Path(path) => quote!(#path()),
attr::Default::None => quote!(
return _serde::export::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
),
@@ -691,11 +695,11 @@ fn deserialize_seq(
};
}
let let_default = match *cattrs.default() {
let let_default = match cattrs.default() {
attr::Default::Default => Some(quote!(
let __default: Self::Value = _serde::export::Default::default();
)),
attr::Default::Path(ref path) => Some(quote!(
attr::Default::Path(path) => Some(quote!(
let __default: Self::Value = #path();
)),
attr::Default::None => {
@@ -739,11 +743,11 @@ fn deserialize_seq_in_place(
self.place.#member = #default;
}
} else {
let value_if_none = match *field.attrs.default() {
let value_if_none = match field.attrs.default() {
attr::Default::Default => quote!(
self.place.#member = _serde::export::Default::default();
),
attr::Default::Path(ref path) => quote!(
attr::Default::Path(path) => quote!(
self.place.#member = #path();
),
attr::Default::None => quote!(
@@ -782,11 +786,11 @@ fn deserialize_seq_in_place(
let this = &params.this;
let (_, ty_generics, _) = params.generics.split_for_impl();
let let_default = match *cattrs.default() {
let let_default = match cattrs.default() {
attr::Default::Default => Some(quote!(
let __default: #this #ty_generics = _serde::export::Default::default();
)),
attr::Default::Path(ref path) => Some(quote!(
attr::Default::Path(path) => Some(quote!(
let __default: #this #ty_generics = #path();
)),
attr::Default::None => {
@@ -896,7 +900,7 @@ fn deserialize_struct(
};
let type_path = match variant_ident {
Some(ref variant_ident) => quote!(#construct::#variant_ident),
Some(variant_ident) => quote!(#construct::#variant_ident),
None => construct,
};
let expecting = match variant_ident {
@@ -1133,15 +1137,14 @@ fn deserialize_enum(
variants: &[Variant],
cattrs: &attr::Container,
) -> Fragment {
match *cattrs.tag() {
match cattrs.tag() {
attr::TagType::External => deserialize_externally_tagged_enum(params, variants, cattrs),
attr::TagType::Internal { ref tag } => {
attr::TagType::Internal { tag } => {
deserialize_internally_tagged_enum(params, variants, cattrs, tag)
}
attr::TagType::Adjacent {
ref tag,
ref content,
} => deserialize_adjacently_tagged_enum(params, variants, cattrs, tag, content),
attr::TagType::Adjacent { tag, content } => {
deserialize_adjacently_tagged_enum(params, variants, cattrs, tag, content)
}
attr::TagType::None => deserialize_untagged_enum(params, variants, cattrs),
}
}
@@ -1150,10 +1153,13 @@ fn prepare_enum_variant_enum(
variants: &[Variant],
cattrs: &attr::Container,
) -> (TokenStream, Stmts) {
let variant_names_idents: Vec<_> = variants
let mut deserialized_variants = variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.filter(|&(_, variant)| !variant.attrs.skip_deserializing());
let variant_names_idents: Vec<_> = deserialized_variants
.clone()
.map(|(i, variant)| {
(
variant.attrs.name().deserialize_name(),
@@ -1163,12 +1169,10 @@ fn prepare_enum_variant_enum(
})
.collect();
let other_idx = variants
.iter()
.position(|ref variant| variant.attrs.other());
let other_idx = deserialized_variants.position(|(_, variant)| variant.attrs.other());
let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|&(ref name, _, _)| name);
let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
quote! {
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
}
@@ -1373,39 +1377,44 @@ fn deserialize_adjacently_tagged_enum(
}
};
fn is_unit(variant: &Variant) -> bool {
match variant.style {
Style::Unit => true,
Style::Struct | Style::Tuple | Style::Newtype => false,
}
}
let mut missing_content = quote! {
_serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#content))
};
if variants.iter().any(is_unit) {
let fallthrough = if variants.iter().all(is_unit) {
None
} else {
Some(quote! {
_ => #missing_content
})
};
let arms = variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing() && is_unit(variant))
.map(|(i, variant)| {
let variant_index = field_i(i);
let variant_ident = &variant.ident;
quote! {
__Field::#variant_index => _serde::export::Ok(#this::#variant_ident),
let mut missing_content_fallthrough = quote!();
let missing_content_arms = variants
.iter()
.enumerate()
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
.filter_map(|(i, variant)| {
let variant_index = field_i(i);
let variant_ident = &variant.ident;
let arm = match variant.style {
Style::Unit => quote! {
_serde::export::Ok(#this::#variant_ident)
},
Style::Newtype if variant.attrs.deserialize_with().is_none() => {
let span = variant.original.span();
let func = quote_spanned!(span=> _serde::private::de::missing_field);
quote! {
#func(#content).map(#this::#variant_ident)
}
}
});
_ => {
missing_content_fallthrough = quote!(_ => #missing_content);
return None;
}
};
Some(quote! {
__Field::#variant_index => #arm,
})
})
.collect::<Vec<_>>();
if !missing_content_arms.is_empty() {
missing_content = quote! {
match __field {
#(#arms)*
#fallthrough
#(#missing_content_arms)*
#missing_content_fallthrough
}
};
}
@@ -1677,9 +1686,12 @@ fn deserialize_externally_tagged_variant(
_serde::export::Ok(#this::#variant_ident)
}
}
Style::Newtype => {
deserialize_externally_tagged_newtype_variant(variant_ident, params, &variant.fields[0])
}
Style::Newtype => deserialize_externally_tagged_newtype_variant(
variant_ident,
params,
&variant.fields[0],
cattrs,
),
Style::Tuple => {
deserialize_tuple(Some(variant_ident), params, &variant.fields, cattrs, None)
}
@@ -1706,14 +1718,18 @@ fn deserialize_internally_tagged_variant(
let variant_ident = &variant.ident;
match variant.style {
match effective_style(variant) {
Style::Unit => {
let this = &params.this;
let type_name = params.type_name();
let variant_name = variant.ident.to_string();
let default = variant.fields.get(0).map(|field| {
let default = Expr(expr_is_missing(field, cattrs));
quote!((#default))
});
quote_block! {
try!(_serde::Deserializer::deserialize_any(#deserializer, _serde::private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name)));
_serde::export::Ok(#this::#variant_ident)
_serde::export::Ok(#this::#variant_ident #default)
}
}
Style::Newtype => deserialize_untagged_newtype_variant(
@@ -1751,17 +1767,21 @@ fn deserialize_untagged_variant(
let variant_ident = &variant.ident;
match variant.style {
match effective_style(variant) {
Style::Unit => {
let this = &params.this;
let type_name = params.type_name();
let variant_name = variant.ident.to_string();
let default = variant.fields.get(0).map(|field| {
let default = Expr(expr_is_missing(field, cattrs));
quote!((#default))
});
quote_expr! {
match _serde::Deserializer::deserialize_any(
#deserializer,
_serde::private::de::UntaggedUnitVisitor::new(#type_name, #variant_name)
) {
_serde::export::Ok(()) => _serde::export::Ok(#this::#variant_ident),
_serde::export::Ok(()) => _serde::export::Ok(#this::#variant_ident #default),
_serde::export::Err(__err) => _serde::export::Err(__err),
}
}
@@ -1794,8 +1814,19 @@ fn deserialize_externally_tagged_newtype_variant(
variant_ident: &syn::Ident,
params: &Parameters,
field: &Field,
cattrs: &attr::Container,
) -> Fragment {
let this = &params.this;
if field.attrs.skip_deserializing() {
let this = &params.this;
let default = Expr(expr_is_missing(field, cattrs));
return quote_block! {
try!(_serde::de::VariantAccess::unit_variant(__variant));
_serde::export::Ok(#this::#variant_ident(#default))
};
}
match field.attrs.deserialize_with() {
None => {
let field_ty = field.ty;
@@ -1850,7 +1881,7 @@ fn deserialize_generated_identifier(
other_idx: Option<usize>,
) -> Fragment {
let this = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|&(_, ref ident, _)| ident).collect();
let field_idents: &Vec<_> = &fields.iter().map(|(_, ident, _)| ident).collect();
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),);
@@ -1956,7 +1987,7 @@ fn deserialize_custom_identifier(
})
.collect();
let names = names_idents.iter().map(|&(ref name, _, _)| name);
let names = names_idents.iter().map(|(name, _, _)| name);
let names_const = if fallthrough.is_some() {
None
@@ -2013,26 +2044,26 @@ fn deserialize_identifier(
collect_other_fields: bool,
) -> Fragment {
let mut flat_fields = Vec::new();
for &(_, ref ident, ref aliases) in fields {
for (_, ident, aliases) in 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_strs = flat_fields.iter().map(|(name, _)| name);
let field_borrowed_strs = flat_fields.iter().map(|(name, _)| name);
let field_bytes = flat_fields
.iter()
.map(|&(ref name, _)| Literal::byte_string(name.as_bytes()));
.map(|(name, _)| Literal::byte_string(name.as_bytes()));
let field_borrowed_bytes = flat_fields
.iter()
.map(|&(ref name, _)| Literal::byte_string(name.as_bytes()));
.map(|(name, _)| Literal::byte_string(name.as_bytes()));
let constructors: &Vec<_> = &flat_fields
.iter()
.map(|&(_, ref ident)| quote!(#this::#ident))
.map(|(_, ident)| quote!(#this::#ident))
.collect();
let main_constructors: &Vec<_> = &fields
.iter()
.map(|&(_, ref ident, _)| quote!(#this::#ident))
.map(|(_, ident, _)| quote!(#this::#ident))
.collect();
let expecting = if is_variant {
@@ -2294,7 +2325,7 @@ fn deserialize_struct_as_struct_visitor(
.collect();
let fields_stmt = {
let field_names = field_names_idents.iter().map(|&(ref name, _, _)| name);
let field_names = field_names_idents.iter().map(|(name, _, _)| name);
quote_block! {
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
}
@@ -2350,7 +2381,7 @@ fn deserialize_map(
let let_values = fields_names
.iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|&(field, ref name)| {
.map(|(field, name)| {
let field_ty = field.ty;
quote! {
let mut #name: _serde::export::Option<#field_ty> = _serde::export::None;
@@ -2373,7 +2404,7 @@ fn deserialize_map(
let value_arms = fields_names
.iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|&(field, ref name)| {
.map(|(field, name)| {
let deser_name = field.attrs.name().deserialize_name();
let visit = match field.attrs.deserialize_with() {
@@ -2449,7 +2480,7 @@ fn deserialize_map(
let extract_values = fields_names
.iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten())
.map(|&(field, ref name)| {
.map(|(field, name)| {
let missing_expr = Match(expr_is_missing(field, cattrs));
quote! {
@@ -2463,7 +2494,7 @@ fn deserialize_map(
let extract_collected = fields_names
.iter()
.filter(|&&(field, _)| field.attrs.flatten() && !field.attrs.skip_deserializing())
.map(|&(field, ref name)| {
.map(|(field, name)| {
let field_ty = field.ty;
let func = match field.attrs.deserialize_with() {
None => {
@@ -2498,7 +2529,7 @@ fn deserialize_map(
None
};
let result = fields_names.iter().map(|&(field, ref name)| {
let result = fields_names.iter().map(|(field, name)| {
let member = &field.member;
if field.attrs.skip_deserializing() {
let value = Expr(expr_is_missing(field, cattrs));
@@ -2508,11 +2539,11 @@ fn deserialize_map(
}
});
let let_default = match *cattrs.default() {
let let_default = match cattrs.default() {
attr::Default::Default => Some(quote!(
let __default: Self::Value = _serde::export::Default::default();
)),
attr::Default::Path(ref path) => Some(quote!(
attr::Default::Path(path) => Some(quote!(
let __default: Self::Value = #path();
)),
attr::Default::None => {
@@ -2571,7 +2602,7 @@ fn deserialize_struct_as_struct_in_place_visitor(
.collect();
let fields_stmt = {
let field_names = field_names_idents.iter().map(|&(ref name, _, _)| name);
let field_names = field_names_idents.iter().map(|(name, _, _)| name);
quote_block! {
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
}
@@ -2604,7 +2635,7 @@ fn deserialize_map_in_place(
let let_flags = fields_names
.iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
.map(|&(_, ref name)| {
.map(|(_, name)| {
quote! {
let mut #name: bool = false;
}
@@ -2614,7 +2645,7 @@ fn deserialize_map_in_place(
let value_arms_from = fields_names
.iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
.map(|&(field, ref name)| {
.map(|(field, name)| {
let deser_name = field.attrs.name().deserialize_name();
let member = &field.member;
@@ -2681,7 +2712,7 @@ fn deserialize_map_in_place(
let check_flags = fields_names
.iter()
.filter(|&&(field, _)| !field.attrs.skip_deserializing())
.map(|&(field, ref name)| {
.map(|(field, name)| {
let missing_expr = expr_is_missing(field, cattrs);
// If missing_expr unconditionally returns an error, don't try
// to assign its value to self.place.
@@ -2709,11 +2740,11 @@ fn deserialize_map_in_place(
let this = &params.this;
let (_, _, ty_generics, _) = split_with_de_lifetime(params);
let let_default = match *cattrs.default() {
let let_default = match cattrs.default() {
attr::Default::Default => Some(quote!(
let __default: #this #ty_generics = _serde::export::Default::default();
)),
attr::Default::Path(ref path) => Some(quote!(
attr::Default::Path(path) => Some(quote!(
let __default: #this #ty_generics = #path();
)),
attr::Default::None => {
@@ -2832,13 +2863,13 @@ fn wrap_deserialize_variant_with(
}
fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
match *field.attrs.default() {
match field.attrs.default() {
attr::Default::Default => {
let span = field.original.span();
let func = quote_spanned!(span=> _serde::export::Default::default);
return quote_expr!(#func());
}
attr::Default::Path(ref path) => {
attr::Default::Path(path) => {
return quote_expr!(#path());
}
attr::Default::None => { /* below */ }
@@ -2869,6 +2900,13 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
}
}
fn effective_style(variant: &Variant) -> Style {
match variant.style {
Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit,
other => other,
}
}
struct DeImplGenerics<'a>(&'a Parameters);
#[cfg(feature = "deserialize_in_place")]
struct InPlaceImplGenerics<'a>(&'a Parameters);
@@ -2895,11 +2933,11 @@ impl<'a> ToTokens for InPlaceImplGenerics<'a> {
// Add lifetime for `&'place mut Self, and `'a: 'place`
for param in &mut generics.params {
match *param {
syn::GenericParam::Lifetime(ref mut param) => {
match param {
syn::GenericParam::Lifetime(param) => {
param.bounds.push(place_lifetime.lifetime.clone());
}
syn::GenericParam::Type(ref mut param) => {
syn::GenericParam::Type(param) => {
param.bounds.push(syn::TypeParamBound::Lifetime(
place_lifetime.lifetime.clone(),
));
+9 -8
View File
@@ -1,4 +1,5 @@
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro2::{Ident, TokenStream};
use quote::format_ident;
use syn;
use try;
@@ -11,24 +12,24 @@ pub fn wrap_in_const(
) -> TokenStream {
let try_replacement = try::replacement();
let dummy_const = Ident::new(
&format!("_IMPL_{}_FOR_{}", trait_, unraw(ty)),
Span::call_site(),
);
let dummy_const = if cfg!(underscore_consts) {
format_ident!("_")
} else {
format_ident!("_IMPL_{}_FOR_{}", trait_, unraw(ty))
};
let use_serde = match serde_path {
Some(path) => quote! {
use #path as _serde;
},
None => quote! {
#[allow(unknown_lints)]
#[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
#[allow(rust_2018_idioms)]
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
},
};
quote! {
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const #dummy_const: () = {
#use_serde
+12 -12
View File
@@ -27,9 +27,9 @@ macro_rules! quote_block {
pub struct Expr(pub Fragment);
impl ToTokens for Expr {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => {
match &self.0 {
Fragment::Expr(expr) => expr.to_tokens(out),
Fragment::Block(block) => {
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
@@ -40,9 +40,9 @@ impl ToTokens for Expr {
pub struct Stmts(pub Fragment);
impl ToTokens for Stmts {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => expr.to_tokens(out),
Fragment::Block(ref block) => block.to_tokens(out),
match &self.0 {
Fragment::Expr(expr) => expr.to_tokens(out),
Fragment::Block(block) => block.to_tokens(out),
}
}
}
@@ -52,12 +52,12 @@ impl ToTokens for Stmts {
pub struct Match(pub Fragment);
impl ToTokens for Match {
fn to_tokens(&self, out: &mut TokenStream) {
match self.0 {
Fragment::Expr(ref expr) => {
match &self.0 {
Fragment::Expr(expr) => {
expr.to_tokens(out);
<Token![,]>::default().to_tokens(out);
}
Fragment::Block(ref block) => {
Fragment::Block(block) => {
token::Brace::default().surround(out, |out| block.to_tokens(out));
}
}
@@ -66,9 +66,9 @@ impl ToTokens for Match {
impl AsRef<TokenStream> for Fragment {
fn as_ref(&self) -> &TokenStream {
match *self {
Fragment::Expr(ref expr) => expr,
Fragment::Block(ref block) => block,
match self {
Fragment::Expr(expr) => expr,
Fragment::Block(block) => block,
}
}
}
+20 -22
View File
@@ -67,11 +67,9 @@ impl<'a> Container<'a> {
) -> Option<Container<'a>> {
let mut attrs = attr::Container::from_ast(cx, item);
let mut data = match item.data {
syn::Data::Enum(ref data) => {
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
}
syn::Data::Struct(ref data) => {
let mut data = match &item.data {
syn::Data::Enum(data) => Data::Enum(enum_from_ast(cx, &data.variants, attrs.default())),
syn::Data::Struct(data) => {
let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
Data::Struct(style, fields)
}
@@ -82,8 +80,8 @@ impl<'a> Container<'a> {
};
let mut has_flatten = false;
match data {
Data::Enum(ref mut variants) => {
match &mut data {
Data::Enum(variants) => {
for variant in variants {
variant.attrs.rename_by_rules(attrs.rename_all_rules());
for field in &mut variant.fields {
@@ -96,7 +94,7 @@ impl<'a> Container<'a> {
}
}
}
Data::Struct(_, ref mut fields) => {
Data::Struct(_, fields) => {
for field in fields {
if field.attrs.flatten() {
has_flatten = true;
@@ -112,8 +110,8 @@ impl<'a> Container<'a> {
let mut item = Container {
ident: item.ident.clone(),
attrs: attrs,
data: data,
attrs,
data,
generics: &item.generics,
original: item,
};
@@ -124,11 +122,11 @@ impl<'a> Container<'a> {
impl<'a> Data<'a> {
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
match *self {
Data::Enum(ref variants) => {
match self {
Data::Enum(variants) => {
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
}
Data::Struct(_, ref fields) => Box::new(fields.iter()),
Data::Struct(_, fields) => Box::new(fields.iter()),
}
}
@@ -150,9 +148,9 @@ fn enum_from_ast<'a>(
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
Variant {
ident: variant.ident.clone(),
attrs: attrs,
style: style,
fields: fields,
attrs,
style,
fields,
original: variant,
}
})
@@ -165,16 +163,16 @@ fn struct_from_ast<'a>(
attrs: Option<&attr::Variant>,
container_default: &attr::Default,
) -> (Style, Vec<Field<'a>>) {
match *fields {
syn::Fields::Named(ref fields) => (
match fields {
syn::Fields::Named(fields) => (
Style::Struct,
fields_from_ast(cx, &fields.named, attrs, container_default),
),
syn::Fields::Unnamed(ref fields) if fields.unnamed.len() == 1 => (
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => (
Style::Newtype,
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
syn::Fields::Unnamed(ref fields) => (
syn::Fields::Unnamed(fields) => (
Style::Tuple,
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
),
@@ -192,8 +190,8 @@ fn fields_from_ast<'a>(
.iter()
.enumerate()
.map(|(i, field)| Field {
member: match field.ident {
Some(ref ident) => syn::Member::Named(ident.clone()),
member: match &field.ident {
Some(ident) => syn::Member::Named(ident.clone()),
None => syn::Member::Unnamed(i.into()),
},
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
File diff suppressed because it is too large Load Diff
+45 -37
View File
@@ -1,6 +1,6 @@
use internals::ast::{Container, Data, Field, Style};
use internals::attr::{Identifier, TagType};
use internals::{Ctxt, Derive};
use internals::{ungroup, Ctxt, Derive};
use syn::{Member, Type};
/// Cross-cutting checks that require looking at more than a single attrs
@@ -13,6 +13,7 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_internal_tag_field_name_conflict(cx, cont);
check_adjacent_tag_conflict(cx, cont);
check_transparent(cx, cont, derive);
check_from_and_try_from(cx, cont);
}
/// Getters are only allowed inside structs (not enums) with the `remote`
@@ -31,8 +32,7 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
if cont.data.has_getter() && cont.attrs.remote().is_none() {
cx.error_spanned_by(
cont.original,
"#[serde(getter = \"...\")] can only be used in structs \
that have #[serde(remote = \"...\")]",
"#[serde(getter = \"...\")] can only be used in structs that have #[serde(remote = \"...\")]",
);
}
}
@@ -41,17 +41,17 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
/// Flattening has some restrictions we can test.
fn check_flatten(cx: &Ctxt, cont: &Container) {
match cont.data {
Data::Enum(ref variants) => {
match &cont.data {
Data::Enum(variants) => {
for variant in variants {
for field in &variant.fields {
check_flatten_field(cx, variant.style, field);
}
}
}
Data::Struct(style, ref fields) => {
Data::Struct(style, fields) => {
for field in fields {
check_flatten_field(cx, style, field);
check_flatten_field(cx, *style, field);
}
}
}
@@ -85,8 +85,8 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return;
}
@@ -169,8 +169,8 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return;
}
@@ -182,8 +182,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
#[serde(skip_serializing)]",
"variant `{}` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)]",
variant.ident
),
);
@@ -196,8 +195,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing)]",
"variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing)]",
variant.ident, member
),
);
@@ -207,8 +205,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(serialize_with)] and \
a field {} marked with #[serde(skip_serializing_if)]",
"variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing_if)]",
variant.ident, member
),
);
@@ -221,8 +218,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(deserialize_with)] and \
#[serde(skip_deserializing)]",
"variant `{}` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)]",
variant.ident
),
);
@@ -235,8 +231,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
cx.error_spanned_by(
variant.original,
format!(
"variant `{}` cannot have both #[serde(deserialize_with)] \
and a field {} marked with #[serde(skip_deserializing)]",
"variant `{}` cannot have both #[serde(deserialize_with)] and a field {} marked with #[serde(skip_deserializing)]",
variant.ident, member
),
);
@@ -251,13 +246,13 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
/// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => return,
};
let tag = match *cont.attrs.tag() {
TagType::Internal { ref tag } => tag.as_str(),
let tag = match cont.attrs.tag() {
TagType::Internal { tag } => tag.as_str(),
TagType::External | TagType::Adjacent { .. } | TagType::None => return,
};
@@ -298,11 +293,8 @@ fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
/// In the case of adjacently-tagged enums, the type and the
/// contents tag must differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
let (type_tag, content_tag) = match *cont.attrs.tag() {
TagType::Adjacent {
ref tag,
ref content,
} => (tag, content),
let (type_tag, content_tag) = match cont.attrs.tag() {
TagType::Adjacent { tag, content } => (tag, content),
TagType::Internal { .. } | TagType::External | TagType::None => return,
};
@@ -330,6 +322,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() {
cx.error_spanned_by(
cont.original,
@@ -337,7 +336,7 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
);
}
let fields = match cont.data {
let fields = match &mut cont.data {
Data::Enum(_) => {
cx.error_spanned_by(
cont.original,
@@ -352,7 +351,7 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
);
return;
}
Data::Struct(_, ref mut fields) => fields,
Data::Struct(_, fields) => fields,
};
let mut transparent_field = None;
@@ -390,16 +389,16 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
}
fn member_message(member: &Member) -> String {
match *member {
Member::Named(ref ident) => format!("`{}`", ident),
Member::Unnamed(ref i) => format!("#{}", i.index),
match member {
Member::Named(ident) => format!("`{}`", ident),
Member::Unnamed(i) => format!("#{}", i.index),
}
}
fn allow_transparent(field: &Field, derive: Derive) -> bool {
if let Type::Path(ref ty) = *field.ty {
if let Type::Path(ty) = ungroup(&field.ty) {
if let Some(seg) = ty.path.segments.last() {
if seg.into_value().ident == "PhantomData" {
if seg.ident == "PhantomData" {
return false;
}
}
@@ -410,3 +409,12 @@ fn allow_transparent(field: &Field, derive: Derive) -> bool {
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",
);
}
}
+5
View File
@@ -38,6 +38,11 @@ impl Ctxt {
.push(syn::Error::new_spanned(obj.into_token_stream(), msg));
}
/// Add one of Syn's parse errors.
pub fn syn_error(&self, err: syn::Error) {
self.errors.borrow_mut().as_mut().unwrap().push(err);
}
/// Consume this object, producing a formatted error string if there are errors.
pub fn check(self) -> Result<(), Vec<syn::Error>> {
let errors = self.errors.borrow_mut().take().unwrap();
+10
View File
@@ -6,9 +6,19 @@ pub use self::ctxt::Ctxt;
mod case;
mod check;
mod symbol;
use syn::Type;
#[derive(Copy, Clone)]
pub enum Derive {
Serialize,
Deserialize,
}
pub fn ungroup(mut ty: &Type) -> &Type {
while let Type::Group(group) = ty {
ty = &group.elem;
}
ty
}
+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)
}
}
+32 -33
View File
@@ -13,44 +13,43 @@
//!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.96")]
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.116")]
#![allow(unknown_lints, bare_trait_objects)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
#![deny(clippy::all, clippy::pedantic)]
// Ignored clippy lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
cognitive_complexity,
enum_variant_names,
needless_pass_by_value,
redundant_field_names,
too_many_arguments,
trivially_copy_pass_by_ref,
used_underscore_binding,
)
#![allow(
clippy::cognitive_complexity,
clippy::enum_variant_names,
clippy::match_like_matches_macro,
clippy::needless_pass_by_value,
clippy::too_many_arguments,
clippy::trivially_copy_pass_by_ref,
clippy::used_underscore_binding,
clippy::wildcard_in_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
clippy::unnested_or_patterns,
)]
// Ignored clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
allow(
cast_possible_truncation,
checked_conversions,
doc_markdown,
enum_glob_use,
filter_map,
indexing_slicing,
items_after_statements,
match_same_arms,
module_name_repetitions,
similar_names,
single_match_else,
unseparated_literal_suffix,
use_self,
)
#![allow(
clippy::cast_possible_truncation,
clippy::checked_conversions,
clippy::doc_markdown,
clippy::enum_glob_use,
clippy::filter_map,
clippy::indexing_slicing,
clippy::items_after_statements,
clippy::match_same_arms,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::option_if_let_else,
clippy::similar_names,
clippy::single_match_else,
clippy::struct_excessive_bools,
clippy::too_many_lines,
clippy::unseparated_literal_suffix,
clippy::use_self,
clippy::wildcard_imports
)]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "512"]
#[macro_use]
extern crate quote;
+5 -5
View File
@@ -52,8 +52,8 @@ fn pretend_fields_used(cont: &Container) -> TokenStream {
let type_ident = &cont.ident;
let (_, ty_generics, _) = cont.generics.split_for_impl();
let patterns = match cont.data {
Data::Enum(ref variants) => variants
let patterns = match &cont.data {
Data::Enum(variants) => variants
.iter()
.filter_map(|variant| match variant.style {
Style::Struct => {
@@ -64,7 +64,7 @@ fn pretend_fields_used(cont: &Container) -> TokenStream {
_ => None,
})
.collect::<Vec<_>>(),
Data::Struct(Style::Struct, ref fields) => {
Data::Struct(Style::Struct, fields) => {
let pat = struct_pattern(fields);
vec![quote!(#type_ident #pat)]
}
@@ -93,8 +93,8 @@ fn pretend_fields_used(cont: &Container) -> TokenStream {
// }
//
fn pretend_variants_used(cont: &Container) -> TokenStream {
let variants = match cont.data {
Data::Enum(ref variants) => variants,
let variants = match &cont.data {
Data::Enum(variants) => variants,
Data::Struct(_, _) => {
return quote!();
}
+65 -46
View File
@@ -16,7 +16,7 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result<TokenStream,
None => return Err(ctxt.check().unwrap_err()),
};
precondition(&ctxt, &cont);
try!(ctxt.check());
ctxt.check()?;
let ident = &cont.ident;
let params = Parameters::new(&cont);
@@ -87,6 +87,9 @@ struct Parameters {
/// Type has a `serde(remote = "...")` attribute.
is_remote: bool,
/// Type has a repr(packed) attribute.
is_packed: bool,
}
impl Parameters {
@@ -103,20 +106,23 @@ impl Parameters {
None => cont.ident.clone().into(),
};
let is_packed = cont.attrs.is_packed();
let generics = build_generics(cont);
Parameters {
self_var: self_var,
this: this,
generics: generics,
is_remote: is_remote,
self_var,
this,
generics,
is_remote,
is_packed,
}
}
/// Type name to use in error messages and `&'static str` arguments to
/// various Serializer methods.
fn type_name(&self) -> String {
self.this.segments.last().unwrap().value().ident.to_string()
self.this.segments.last().unwrap().ident.to_string()
}
}
@@ -164,15 +170,13 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
} else if let Some(type_into) = cont.attrs.type_into() {
serialize_into(params, type_into)
} else {
match cont.data {
Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, ref fields) => {
serialize_struct(params, fields, &cont.attrs)
}
Data::Struct(Style::Tuple, ref fields) => {
match &cont.data {
Data::Enum(variants) => serialize_enum(params, variants, &cont.attrs),
Data::Struct(Style::Struct, fields) => serialize_struct(params, fields, &cont.attrs),
Data::Struct(Style::Tuple, fields) => {
serialize_tuple_struct(params, fields, &cont.attrs)
}
Data::Struct(Style::Newtype, ref fields) => {
Data::Struct(Style::Newtype, fields) => {
serialize_newtype_struct(params, &fields[0], &cont.attrs)
}
Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs),
@@ -181,8 +185,8 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
}
fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
let fields = match cont.data {
Data::Struct(_, ref fields) => fields,
let fields = match &cont.data {
Data::Struct(_, fields) => fields,
Data::Enum(_) => unreachable!(),
};
@@ -259,7 +263,7 @@ fn serialize_tuple_struct(
let mut serialized_fields = fields
.iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.filter(|(_, field)| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
@@ -296,8 +300,8 @@ 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 } => {
match cattrs.tag() {
attr::TagType::Internal { tag } => {
let type_name = cattrs.name().serialize_name();
let func = struct_trait.serialize_field(Span::call_site());
quote! {
@@ -467,17 +471,16 @@ fn serialize_variant(
}
};
let body = Match(match *cattrs.tag() {
let body = Match(match cattrs.tag() {
attr::TagType::External => {
serialize_externally_tagged_variant(params, variant, variant_index, cattrs)
}
attr::TagType::Internal { ref tag } => {
attr::TagType::Internal { tag } => {
serialize_internally_tagged_variant(params, variant, cattrs, tag)
}
attr::TagType::Adjacent {
ref tag,
ref content,
} => serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content),
attr::TagType::Adjacent { tag, content } => {
serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content)
}
attr::TagType::None => serialize_untagged_variant(params, variant, cattrs),
});
@@ -509,7 +512,7 @@ fn serialize_externally_tagged_variant(
};
}
match variant.style {
match effective_style(variant) {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit_variant(
@@ -541,17 +544,17 @@ fn serialize_externally_tagged_variant(
}
Style::Tuple => serialize_tuple_variant(
TupleVariant::ExternallyTagged {
type_name: type_name,
variant_index: variant_index,
variant_name: variant_name,
type_name,
variant_index,
variant_name,
},
params,
&variant.fields,
),
Style::Struct => serialize_struct_variant(
StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
variant_index,
variant_name,
},
params,
&variant.fields,
@@ -586,7 +589,7 @@ fn serialize_internally_tagged_variant(
};
}
match variant.style {
match effective_style(variant) {
Style::Unit => {
quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
@@ -617,10 +620,7 @@ fn serialize_internally_tagged_variant(
}
}
Style::Struct => serialize_struct_variant(
StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
},
StructVariant::InternallyTagged { tag, variant_name },
params,
&variant.fields,
&type_name,
@@ -646,7 +646,7 @@ fn serialize_adjacently_tagged_variant(
_serde::Serialize::serialize(#ser, __serializer)
}
} else {
match variant.style {
match effective_style(variant) {
Style::Unit => {
return quote_block! {
let mut __struct = try!(_serde::Serializer::serialize_struct(
@@ -723,6 +723,8 @@ fn serialize_adjacently_tagged_variant(
where
__S: _serde::Serializer,
{
// Elements that have skip_serializing will be unused.
#[allow(unused_variables)]
let (#(#fields_ident,)*) = self.data;
#inner
}
@@ -753,7 +755,7 @@ fn serialize_untagged_variant(
};
}
match variant.style {
match effective_style(variant) {
Style::Unit => {
quote_expr! {
_serde::Serializer::serialize_unit(__serializer)
@@ -804,7 +806,7 @@ fn serialize_tuple_variant(
let mut serialized_fields = fields
.iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.filter(|(_, field)| !field.attrs.skip_serializing())
.peekable();
let let_mut = mut_if(serialized_fields.peek().is_some());
@@ -871,9 +873,9 @@ fn serialize_struct_variant<'a>(
}
let struct_trait = match context {
StructVariant::ExternallyTagged { .. } => (StructTrait::SerializeStructVariant),
StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant,
StructVariant::InternallyTagged { .. } | StructVariant::Untagged => {
(StructTrait::SerializeStruct)
StructTrait::SerializeStruct
}
};
@@ -1039,7 +1041,7 @@ fn serialize_tuple_struct_visitor(
fields
.iter()
.enumerate()
.filter(|&(_, ref field)| !field.attrs.skip_serializing())
.filter(|(_, field)| !field.attrs.skip_serializing())
.map(|(i, field)| {
let mut field_expr = if is_enum {
let id = Ident::new(&format!("__field{}", i), Span::call_site());
@@ -1163,9 +1165,9 @@ fn wrap_serialize_variant_with(
.fields
.iter()
.map(|field| {
let id = match field.member {
Member::Named(ref ident) => ident.clone(),
Member::Unnamed(ref member) => {
let id = match &field.member {
Member::Named(ident) => ident.clone(),
Member::Unnamed(member) => {
Ident::new(&format!("__field{}", member.index), Span::call_site())
}
};
@@ -1242,9 +1244,19 @@ fn mut_if(is_mut: bool) -> Option<TokenStream> {
fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
let self_var = &params.self_var;
match (params.is_remote, field.attrs.getter()) {
(false, None) => quote!(&#self_var.#member),
(false, None) => {
if params.is_packed {
quote!(&{#self_var.#member})
} else {
quote!(&#self_var.#member)
}
}
(true, None) => {
let inner = quote!(&#self_var.#member);
let inner = if params.is_packed {
quote!(&{#self_var.#member})
} else {
quote!(&#self_var.#member)
};
let ty = field.ty;
quote!(_serde::private::ser::constrain::<#ty>(#inner))
}
@@ -1258,6 +1270,13 @@ fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStrea
}
}
fn effective_style(variant: &Variant) -> Style {
match variant.style {
Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit,
other => other,
}
}
enum StructTrait {
SerializeMap,
SerializeStruct,
+7 -8
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_derive_internals"
version = "0.24.1" # remember to update html_root_url
version = "0.25.0" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0"
description = "AST representation used by Serde derive macros. Unstable."
@@ -8,16 +8,15 @@ homepage = "https://serde.rs"
repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.rs/serde_derive_internals"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "lib.rs", "src/**/*.rs", "LICENSE-APACHE", "LICENSE-MIT"]
include = ["lib.rs", "src/**/*.rs", "LICENSE-APACHE", "LICENSE-MIT"]
[lib]
path = "lib.rs"
[dependencies]
proc-macro2 = "0.4"
quote = "0.6.3"
syn = { version = "0.15", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0.33", default-features = false, features = ["derive", "parsing", "printing", "clone-impls"] }
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+5 -2
View File
@@ -1,4 +1,4 @@
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.24.1")]
#![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.25.0")]
#![allow(unknown_lints, bare_trait_objects)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(
@@ -6,7 +6,10 @@
allow(
cognitive_complexity,
redundant_field_names,
trivially_copy_pass_by_ref
trivially_copy_pass_by_ref,
wildcard_in_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
unnested_or_patterns,
)
)]
+4 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_test"
version = "1.0.96" # remember to update html_root_url
version = "1.0.116" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT OR Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
@@ -9,7 +9,7 @@ repository = "https://github.com/serde-rs/serde"
documentation = "https://docs.serde.rs/serde_test/"
keywords = ["serde", "serialization"]
readme = "crates-io.md"
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
include = ["src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
[dependencies]
serde = { version = "1.0.60", path = "../serde" }
@@ -18,6 +18,5 @@ serde = { version = "1.0.60", path = "../serde" }
serde = { version = "1.0", path = "../serde" }
serde_derive = { version = "1.0", path = "../serde_derive" }
[badges]
travis-ci = { repository = "serde-rs/serde" }
appveyor = { repository = "serde-rs/serde" }
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
-8
View File
@@ -12,7 +12,6 @@ use std::fmt::Debug;
/// # use serde::{Serialize, Deserialize};
/// # use serde_test::{assert_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
@@ -28,7 +27,6 @@ use std::fmt::Debug;
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
@@ -44,7 +42,6 @@ where
/// # use serde::{Serialize, Deserialize};
/// # use serde_test::{assert_ser_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
@@ -60,7 +57,6 @@ where
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where
@@ -135,7 +131,6 @@ where
/// # use serde::{Serialize, Deserialize};
/// # use serde_test::{assert_de_tokens, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// struct S {
/// a: u8,
@@ -151,7 +146,6 @@ where
/// Token::U8(0),
/// Token::StructEnd,
/// ]);
/// # }
/// ```
pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token])
where
@@ -190,7 +184,6 @@ where
/// # use serde::{Serialize, Deserialize};
/// # use serde_test::{assert_de_tokens_error, Token};
/// #
/// # fn main() {
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
/// #[serde(deny_unknown_fields)]
/// struct S {
@@ -205,7 +198,6 @@ where
/// ],
/// "unknown field `x`, expected `a` or `b`",
/// );
/// # }
/// ```
pub fn assert_de_tokens_error<'de, T>(tokens: &'de [Token], error: &str)
where
+8 -8
View File
@@ -89,11 +89,11 @@ impl<'de> Deserializer<'de> {
where
V: Visitor<'de>,
{
let value = try!(visitor.visit_seq(DeserializerSeqVisitor {
let value = visitor.visit_seq(DeserializerSeqVisitor {
de: self,
len: len,
end: end,
},));
})?;
assert_next_token!(self, end);
Ok(value)
}
@@ -107,11 +107,11 @@ impl<'de> Deserializer<'de> {
where
V: Visitor<'de>,
{
let value = try!(visitor.visit_map(DeserializerMapVisitor {
let value = visitor.visit_map(DeserializerMapVisitor {
de: self,
len: len,
end: end,
},));
})?;
assert_next_token!(self, end);
Ok(value)
}
@@ -456,11 +456,11 @@ impl<'de, 'a> EnumAccess<'de> for DeserializerEnumVisitor<'a, 'de> {
| Token::TupleVariant { variant: v, .. }
| Token::StructVariant { variant: v, .. } => {
let de = v.into_deserializer();
let value = try!(seed.deserialize(de));
let value = seed.deserialize(de)?;
Ok((value, self))
}
_ => {
let value = try!(seed.deserialize(&mut *self.de));
let value = seed.deserialize(&mut *self.de)?;
Ok((value, self))
}
}
@@ -613,7 +613,7 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
len: None,
end: Token::TupleVariantEnd,
};
try!(seed.deserialize(SeqAccessDeserializer::new(visitor)))
seed.deserialize(SeqAccessDeserializer::new(visitor))?
};
assert_next_token!(self.de, Token::TupleVariantEnd);
Ok(value)
@@ -625,7 +625,7 @@ impl<'de, 'a> MapAccess<'de> for EnumMapVisitor<'a, 'de> {
len: None,
end: Token::StructVariantEnd,
};
try!(seed.deserialize(MapAccessDeserializer::new(visitor)))
seed.deserialize(MapAccessDeserializer::new(visitor))?
};
assert_next_token!(self.de, Token::StructVariantEnd);
Ok(value)
+3 -2
View File
@@ -144,11 +144,11 @@
//! # }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.96")]
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.116")]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy lints
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, needless_doctest_main))]
// Ignored clippy_pedantic lints
#![cfg_attr(
feature = "cargo-clippy",
@@ -156,6 +156,7 @@
empty_line_after_outer_attr,
missing_docs_in_private_items,
module_name_repetitions,
must_use_candidate,
redundant_field_names,
use_debug,
use_self
+2 -2
View File
@@ -427,7 +427,7 @@ impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
where
T: Serialize,
{
try!(key.serialize(&mut **self));
key.serialize(&mut **self)?;
value.serialize(&mut **self)
}
@@ -449,7 +449,7 @@ impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
where
T: Serialize,
{
try!(key.serialize(&mut *self.ser));
key.serialize(&mut *self.ser)?;
value.serialize(&mut *self.ser)
}
+7 -2
View File
@@ -4,17 +4,22 @@ version = "0.0.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
edition = "2018"
publish = false
build = "build.rs"
[features]
expandtest = []
unstable = ["serde/unstable"]
[dependencies]
serde = { path = "../serde" }
[build-dependencies]
toolchain_find = "0.1"
[dev-dependencies]
fnv = "1.0"
rustc-serialize = "0.3.16"
rustversion = "0.1"
macrotest = "=1.0.0"
rustversion = "1.0"
serde = { path = "../serde", features = ["rc", "derive"] }
serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] }
serde_test = { path = "../serde_test" }
+29
View File
@@ -0,0 +1,29 @@
use std::process::{Command, ExitStatus, Stdio};
fn has_cargo_expand() -> bool {
let cargo_expand = if cfg!(windows) {
"cargo-expand.exe"
} else {
"cargo-expand"
};
Command::new(cargo_expand)
.arg("--version")
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.as_ref()
.map(ExitStatus::success)
.unwrap_or(false)
}
fn has_rustfmt() -> bool {
toolchain_find::find_installed_component("rustfmt").is_some()
}
fn main() {
if cfg!(feature = "expandtest") && has_cargo_expand() && has_rustfmt() {
println!("cargo:rustc-cfg=expandtest");
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
#[cfg(not(target_os = "emscripten"))]
#[cfg_attr(target_os = "emscripten", ignore)]
#[rustversion::attr(not(nightly), ignore)]
#[test]
fn ui() {
File diff suppressed because it is too large Load Diff
+13
View File
@@ -0,0 +1,13 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
enum DeEnum<B, C, D> {
Unit,
Seq(i8, B, C, D),
Map { a: i8, b: B, c: C, d: D },
// Make sure we can support more than one variant.
_Unit2,
_Seq2(i8, B, C, D),
_Map2 { a: i8, b: B, c: C, d: D },
}
@@ -0,0 +1,401 @@
use serde::{Deserialize, Serialize};
trait AssociatedType {
type X;
}
impl AssociatedType for i32 {
type X = i32;
}
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
phantom: PhantomData<T>,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<T: AssociatedType<X = i32>> _serde::Serialize for DefaultTyParam<T> {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let mut __serde_state = match _serde::Serializer::serialize_struct(
__serializer,
"DefaultTyParam",
false as usize + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(
&mut __serde_state,
"phantom",
&self.phantom,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T: AssociatedType<X = i32>> _serde::Deserialize<'de> for DefaultTyParam<T> {
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "field identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"phantom" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"phantom" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de, T: AssociatedType<X = i32>> {
marker: _serde::export::PhantomData<DefaultTyParam<T>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, T: AssociatedType<X = i32>> _serde::de::Visitor<'de> for __Visitor<'de, T> {
type Value = DefaultTyParam<T>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "struct DefaultTyParam")
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<PhantomData<T>>(
&mut __seq,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"struct DefaultTyParam with 1 element",
));
}
};
_serde::export::Ok(DefaultTyParam { phantom: __field0 })
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::export::Option<PhantomData<T>> = _serde::export::None;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if _serde::export::Option::is_some(&__field0) {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"phantom",
),
);
}
__field0 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<PhantomData<T>>(
&mut __map,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::export::Some(__field0) => __field0,
_serde::export::None => match _serde::private::de::missing_field("phantom")
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
};
_serde::export::Ok(DefaultTyParam { phantom: __field0 })
}
}
const FIELDS: &'static [&'static str] = &["phantom"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"DefaultTyParam",
FIELDS,
__Visitor {
marker: _serde::export::PhantomData::<DefaultTyParam<T>>,
lifetime: _serde::export::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::export::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "field identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"phantom" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"phantom" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de, 'place, T: AssociatedType<X = i32> + 'place> {
place: &'place mut DefaultTyParam<T>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'place, T: AssociatedType<X = i32> + 'place> _serde::de::Visitor<'de>
for __Visitor<'de, 'place, T>
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "struct DefaultTyParam")
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.phantom),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"struct DefaultTyParam with 1 element",
));
}
_serde::export::Ok(())
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: bool = false;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if __field0 {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field(
"phantom",
),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::private::de::InPlaceSeed(&mut self.place.phantom),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
__field0 = true;
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
if !__field0 {
self.place.phantom = match _serde::private::de::missing_field("phantom") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
};
_serde::export::Ok(())
}
}
const FIELDS: &'static [&'static str] = &["phantom"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"DefaultTyParam",
FIELDS,
__Visitor {
place: __place,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
@@ -0,0 +1,14 @@
use serde::{Deserialize, Serialize};
trait AssociatedType {
type X;
}
impl AssociatedType for i32 {
type X = i32;
}
#[derive(Serialize, Deserialize)]
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
phantom: PhantomData<T>,
}
@@ -0,0 +1,582 @@
use serde::{Deserialize, Serialize};
pub enum GenericEnum<T, U> {
Unit,
NewType(T),
Seq(T, U),
Map { x: T, y: U },
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<T, U> _serde::Serialize for GenericEnum<T, U>
where
T: _serde::Serialize,
U: _serde::Serialize,
{
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
match *self {
GenericEnum::Unit => _serde::Serializer::serialize_unit_variant(
__serializer,
"GenericEnum",
0u32,
"Unit",
),
GenericEnum::NewType(ref __field0) => {
_serde::Serializer::serialize_newtype_variant(
__serializer,
"GenericEnum",
1u32,
"NewType",
__field0,
)
}
GenericEnum::Seq(ref __field0, ref __field1) => {
let mut __serde_state = match _serde::Serializer::serialize_tuple_variant(
__serializer,
"GenericEnum",
2u32,
"Seq",
0 + 1 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field0,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
GenericEnum::Map { ref x, ref y } => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"GenericEnum",
3u32,
"Map",
0 + 1 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"x",
x,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"y",
y,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T, U> _serde::Deserialize<'de> for GenericEnum<T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__field3,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "variant identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
2u64 => _serde::export::Ok(__Field::__field2),
3u64 => _serde::export::Ok(__Field::__field3),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"variant index 0 <= i < 4",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"Unit" => _serde::export::Ok(__Field::__field0),
"NewType" => _serde::export::Ok(__Field::__field1),
"Seq" => _serde::export::Ok(__Field::__field2),
"Map" => _serde::export::Ok(__Field::__field3),
_ => _serde::export::Err(_serde::de::Error::unknown_variant(
__value, VARIANTS,
)),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"Unit" => _serde::export::Ok(__Field::__field0),
b"NewType" => _serde::export::Ok(__Field::__field1),
b"Seq" => _serde::export::Ok(__Field::__field2),
b"Map" => _serde::export::Ok(__Field::__field3),
_ => {
let __value = &_serde::export::from_utf8_lossy(__value);
_serde::export::Err(_serde::de::Error::unknown_variant(
__value, VARIANTS,
))
}
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
marker: _serde::export::PhantomData<GenericEnum<T, U>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = GenericEnum<T, U>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "enum GenericEnum")
}
fn visit_enum<__A>(
self,
__data: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::EnumAccess<'de>,
{
match match _serde::de::EnumAccess::variant(__data) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
(__Field::__field0, __variant) => {
match _serde::de::VariantAccess::unit_variant(__variant) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::export::Ok(GenericEnum::Unit)
}
(__Field::__field1, __variant) => _serde::export::Result::map(
_serde::de::VariantAccess::newtype_variant::<T>(__variant),
GenericEnum::NewType,
),
(__Field::__field2, __variant) => {
struct __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
marker: _serde::export::PhantomData<GenericEnum<T, U>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = GenericEnum<T, U>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"tuple variant GenericEnum::Seq",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
T,
>(
&mut __seq
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde :: export :: Err ( _serde :: de :: Error :: invalid_length ( 0usize , & "tuple variant GenericEnum::Seq with 2 elements" ) ) ;
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<
U,
>(
&mut __seq
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde :: export :: Err ( _serde :: de :: Error :: invalid_length ( 1usize , & "tuple variant GenericEnum::Seq with 2 elements" ) ) ;
}
};
_serde::export::Ok(GenericEnum::Seq(__field0, __field1))
}
}
_serde::de::VariantAccess::tuple_variant(
__variant,
2usize,
__Visitor {
marker: _serde::export::PhantomData::<GenericEnum<T, U>>,
lifetime: _serde::export::PhantomData,
},
)
}
(__Field::__field3, __variant) => {
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 2",
)),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"x" => _serde::export::Ok(__Field::__field0),
"y" => _serde::export::Ok(__Field::__field1),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"x" => _serde::export::Ok(__Field::__field0),
b"y" => _serde::export::Ok(__Field::__field1),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
marker: _serde::export::PhantomData<GenericEnum<T, U>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = GenericEnum<T, U>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"struct variant GenericEnum::Map",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
T,
>(
&mut __seq
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde :: export :: Err ( _serde :: de :: Error :: invalid_length ( 0usize , & "struct variant GenericEnum::Map with 2 elements" ) ) ;
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<
U,
>(
&mut __seq
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde :: export :: Err ( _serde :: de :: Error :: invalid_length ( 1usize , & "struct variant GenericEnum::Map with 2 elements" ) ) ;
}
};
_serde::export::Ok(GenericEnum::Map {
x: __field0,
y: __field1,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::export::Option<T> =
_serde::export::None;
let mut __field1: _serde::export::Option<U> =
_serde::export::None;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if _serde::export::Option::is_some(&__field0) {
return _serde :: export :: Err ( < __A :: Error as _serde :: de :: Error > :: duplicate_field ( "x" ) ) ;
}
__field0 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<T>(
&mut __map,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
__Field::__field1 => {
if _serde::export::Option::is_some(&__field1) {
return _serde :: export :: Err ( < __A :: Error as _serde :: de :: Error > :: duplicate_field ( "y" ) ) ;
}
__field1 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<U>(
&mut __map,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(
&mut __map
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::export::Some(__field0) => __field0,
_serde::export::None => {
match _serde::private::de::missing_field("x") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
}
};
let __field1 = match __field1 {
_serde::export::Some(__field1) => __field1,
_serde::export::None => {
match _serde::private::de::missing_field("y") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
}
};
_serde::export::Ok(GenericEnum::Map {
x: __field0,
y: __field1,
})
}
}
const FIELDS: &'static [&'static str] = &["x", "y"];
_serde::de::VariantAccess::struct_variant(
__variant,
FIELDS,
__Visitor {
marker: _serde::export::PhantomData::<GenericEnum<T, U>>,
lifetime: _serde::export::PhantomData,
},
)
}
}
}
}
const VARIANTS: &'static [&'static str] = &["Unit", "NewType", "Seq", "Map"];
_serde::Deserializer::deserialize_enum(
__deserializer,
"GenericEnum",
VARIANTS,
__Visitor {
marker: _serde::export::PhantomData::<GenericEnum<T, U>>,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
+9
View File
@@ -0,0 +1,9 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub enum GenericEnum<T, U> {
Unit,
NewType(T),
Seq(T, U),
Map { x: T, y: U },
}
@@ -0,0 +1,582 @@
use serde::{Deserialize, Serialize};
pub struct GenericStruct<T> {
x: T,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<T> _serde::Serialize for GenericStruct<T>
where
T: _serde::Serialize,
{
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let mut __serde_state = match _serde::Serializer::serialize_struct(
__serializer,
"GenericStruct",
false as usize + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state, "x", &self.x) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T> _serde::Deserialize<'de> for GenericStruct<T>
where
T: _serde::Deserialize<'de>,
{
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "field identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"x" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"x" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de, T>
where
T: _serde::Deserialize<'de>,
{
marker: _serde::export::PhantomData<GenericStruct<T>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
where
T: _serde::Deserialize<'de>,
{
type Value = GenericStruct<T>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "struct GenericStruct")
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<T>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"struct GenericStruct with 1 element",
));
}
};
_serde::export::Ok(GenericStruct { x: __field0 })
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::export::Option<T> = _serde::export::None;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if _serde::export::Option::is_some(&__field0) {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field("x"),
);
}
__field0 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<T>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::export::Some(__field0) => __field0,
_serde::export::None => match _serde::private::de::missing_field("x") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
};
_serde::export::Ok(GenericStruct { x: __field0 })
}
}
const FIELDS: &'static [&'static str] = &["x"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"GenericStruct",
FIELDS,
__Visitor {
marker: _serde::export::PhantomData::<GenericStruct<T>>,
lifetime: _serde::export::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::export::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "field identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"x" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"x" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de, 'place, T: 'place>
where
T: _serde::Deserialize<'de>,
{
place: &'place mut GenericStruct<T>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'place, T: 'place> _serde::de::Visitor<'de> for __Visitor<'de, 'place, T>
where
T: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "struct GenericStruct")
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.x),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"struct GenericStruct with 1 element",
));
}
_serde::export::Ok(())
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: bool = false;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if __field0 {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field("x"),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::private::de::InPlaceSeed(&mut self.place.x),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
__field0 = true;
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
if !__field0 {
self.place.x = match _serde::private::de::missing_field("x") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
};
_serde::export::Ok(())
}
}
const FIELDS: &'static [&'static str] = &["x"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"GenericStruct",
FIELDS,
__Visitor {
place: __place,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
pub struct GenericNewTypeStruct<T>(T);
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<T> _serde::Serialize for GenericNewTypeStruct<T>
where
T: _serde::Serialize,
{
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
_serde::Serializer::serialize_newtype_struct(
__serializer,
"GenericNewTypeStruct",
&self.0,
)
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T> _serde::Deserialize<'de> for GenericNewTypeStruct<T>
where
T: _serde::Deserialize<'de>,
{
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, T>
where
T: _serde::Deserialize<'de>,
{
marker: _serde::export::PhantomData<GenericNewTypeStruct<T>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, T> _serde::de::Visitor<'de> for __Visitor<'de, T>
where
T: _serde::Deserialize<'de>,
{
type Value = GenericNewTypeStruct<T>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"tuple struct GenericNewTypeStruct",
)
}
#[inline]
fn visit_newtype_struct<__E>(
self,
__e: __E,
) -> _serde::export::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<'de>,
{
let __field0: T = match <T as _serde::Deserialize>::deserialize(__e) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::export::Ok(GenericNewTypeStruct(__field0))
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<T>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"tuple struct GenericNewTypeStruct with 1 element",
));
}
};
_serde::export::Ok(GenericNewTypeStruct(__field0))
}
}
_serde::Deserializer::deserialize_newtype_struct(
__deserializer,
"GenericNewTypeStruct",
__Visitor {
marker: _serde::export::PhantomData::<GenericNewTypeStruct<T>>,
lifetime: _serde::export::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::export::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, 'place, T: 'place>
where
T: _serde::Deserialize<'de>,
{
place: &'place mut GenericNewTypeStruct<T>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'place, T: 'place> _serde::de::Visitor<'de> for __Visitor<'de, 'place, T>
where
T: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"tuple struct GenericNewTypeStruct",
)
}
#[inline]
fn visit_newtype_struct<__E>(
self,
__e: __E,
) -> _serde::export::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<'de>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.0),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"tuple struct GenericNewTypeStruct with 1 element",
));
}
_serde::export::Ok(())
}
}
_serde::Deserializer::deserialize_newtype_struct(
__deserializer,
"GenericNewTypeStruct",
__Visitor {
place: __place,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
@@ -0,0 +1,9 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct GenericStruct<T> {
x: T,
}
#[derive(Serialize, Deserialize)]
pub struct GenericNewTypeStruct<T>(T);
@@ -0,0 +1,172 @@
use serde::{Deserialize, Serialize};
pub struct GenericTupleStruct<T, U>(T, U);
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, T, U> _serde::Deserialize<'de> for GenericTupleStruct<T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
marker: _serde::export::PhantomData<GenericTupleStruct<T, U>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, T, U> _serde::de::Visitor<'de> for __Visitor<'de, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = GenericTupleStruct<T, U>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"tuple struct GenericTupleStruct",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<T>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"tuple struct GenericTupleStruct with 2 elements",
));
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<U>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
1usize,
&"tuple struct GenericTupleStruct with 2 elements",
));
}
};
_serde::export::Ok(GenericTupleStruct(__field0, __field1))
}
}
_serde::Deserializer::deserialize_tuple_struct(
__deserializer,
"GenericTupleStruct",
2usize,
__Visitor {
marker: _serde::export::PhantomData::<GenericTupleStruct<T, U>>,
lifetime: _serde::export::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::export::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, 'place, T: 'place, U: 'place>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
place: &'place mut GenericTupleStruct<T, U>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'place, T: 'place, U: 'place> _serde::de::Visitor<'de> for __Visitor<'de, 'place, T, U>
where
T: _serde::Deserialize<'de>,
U: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"tuple struct GenericTupleStruct",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.0),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"tuple struct GenericTupleStruct with 2 elements",
));
}
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.1),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
1usize,
&"tuple struct GenericTupleStruct with 2 elements",
));
}
_serde::export::Ok(())
}
}
_serde::Deserializer::deserialize_tuple_struct(
__deserializer,
"GenericTupleStruct",
2usize,
__Visitor {
place: __place,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
@@ -0,0 +1,4 @@
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
pub struct GenericTupleStruct<T, U>(T, U);
@@ -0,0 +1,601 @@
use serde::{Deserialize, Serialize};
enum Lifetimes<'a> {
LifetimeSeq(&'a i32),
NoLifetimeSeq(i32),
LifetimeMap { a: &'a i32 },
NoLifetimeMap { a: i32 },
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'a> _serde::Serialize for Lifetimes<'a> {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
match *self {
Lifetimes::LifetimeSeq(ref __field0) => {
_serde::Serializer::serialize_newtype_variant(
__serializer,
"Lifetimes",
0u32,
"LifetimeSeq",
__field0,
)
}
Lifetimes::NoLifetimeSeq(ref __field0) => {
_serde::Serializer::serialize_newtype_variant(
__serializer,
"Lifetimes",
1u32,
"NoLifetimeSeq",
__field0,
)
}
Lifetimes::LifetimeMap { ref a } => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"Lifetimes",
2u32,
"LifetimeMap",
0 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"a",
a,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
Lifetimes::NoLifetimeMap { ref a } => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"Lifetimes",
3u32,
"NoLifetimeMap",
0 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"a",
a,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, 'a> _serde::Deserialize<'de> for Lifetimes<'a> {
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__field3,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "variant identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
2u64 => _serde::export::Ok(__Field::__field2),
3u64 => _serde::export::Ok(__Field::__field3),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"variant index 0 <= i < 4",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"LifetimeSeq" => _serde::export::Ok(__Field::__field0),
"NoLifetimeSeq" => _serde::export::Ok(__Field::__field1),
"LifetimeMap" => _serde::export::Ok(__Field::__field2),
"NoLifetimeMap" => _serde::export::Ok(__Field::__field3),
_ => _serde::export::Err(_serde::de::Error::unknown_variant(
__value, VARIANTS,
)),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"LifetimeSeq" => _serde::export::Ok(__Field::__field0),
b"NoLifetimeSeq" => _serde::export::Ok(__Field::__field1),
b"LifetimeMap" => _serde::export::Ok(__Field::__field2),
b"NoLifetimeMap" => _serde::export::Ok(__Field::__field3),
_ => {
let __value = &_serde::export::from_utf8_lossy(__value);
_serde::export::Err(_serde::de::Error::unknown_variant(
__value, VARIANTS,
))
}
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de, 'a> {
marker: _serde::export::PhantomData<Lifetimes<'a>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'a> _serde::de::Visitor<'de> for __Visitor<'de, 'a> {
type Value = Lifetimes<'a>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "enum Lifetimes")
}
fn visit_enum<__A>(
self,
__data: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::EnumAccess<'de>,
{
match match _serde::de::EnumAccess::variant(__data) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
(__Field::__field0, __variant) => _serde::export::Result::map(
_serde::de::VariantAccess::newtype_variant::<&'a i32>(__variant),
Lifetimes::LifetimeSeq,
),
(__Field::__field1, __variant) => _serde::export::Result::map(
_serde::de::VariantAccess::newtype_variant::<i32>(__variant),
Lifetimes::NoLifetimeSeq,
),
(__Field::__field2, __variant) => {
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"a" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"a" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, 'a> {
marker: _serde::export::PhantomData<Lifetimes<'a>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'a> _serde::de::Visitor<'de> for __Visitor<'de, 'a> {
type Value = Lifetimes<'a>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"struct variant Lifetimes::LifetimeMap",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
&'a i32,
>(
&mut __seq
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde :: export :: Err ( _serde :: de :: Error :: invalid_length ( 0usize , & "struct variant Lifetimes::LifetimeMap with 1 element" ) ) ;
}
};
_serde::export::Ok(Lifetimes::LifetimeMap { a: __field0 })
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::export::Option<&'a i32> =
_serde::export::None;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if _serde::export::Option::is_some(&__field0) {
return _serde :: export :: Err ( < __A :: Error as _serde :: de :: Error > :: duplicate_field ( "a" ) ) ;
}
__field0 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<&'a i32>(
&mut __map,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(
&mut __map
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::export::Some(__field0) => __field0,
_serde::export::None => {
match _serde::private::de::missing_field("a") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
}
};
_serde::export::Ok(Lifetimes::LifetimeMap { a: __field0 })
}
}
const FIELDS: &'static [&'static str] = &["a"];
_serde::de::VariantAccess::struct_variant(
__variant,
FIELDS,
__Visitor {
marker: _serde::export::PhantomData::<Lifetimes<'a>>,
lifetime: _serde::export::PhantomData,
},
)
}
(__Field::__field3, __variant) => {
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"field identifier",
)
}
fn visit_u64<__E>(
self,
__value: u64,
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 1",
)),
}
}
fn visit_str<__E>(
self,
__value: &str,
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"a" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"a" => _serde::export::Ok(__Field::__field0),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(
__deserializer: __D,
) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(
__deserializer,
__FieldVisitor,
)
}
}
struct __Visitor<'de, 'a> {
marker: _serde::export::PhantomData<Lifetimes<'a>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'a> _serde::de::Visitor<'de> for __Visitor<'de, 'a> {
type Value = Lifetimes<'a>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(
__formatter,
"struct variant Lifetimes::NoLifetimeMap",
)
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<
i32,
>(
&mut __seq
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde :: export :: Err ( _serde :: de :: Error :: invalid_length ( 0usize , & "struct variant Lifetimes::NoLifetimeMap with 1 element" ) ) ;
}
};
_serde::export::Ok(Lifetimes::NoLifetimeMap { a: __field0 })
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::export::Option<i32> =
_serde::export::None;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if _serde::export::Option::is_some(&__field0) {
return _serde :: export :: Err ( < __A :: Error as _serde :: de :: Error > :: duplicate_field ( "a" ) ) ;
}
__field0 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<i32>(
&mut __map,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(
&mut __map
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::export::Some(__field0) => __field0,
_serde::export::None => {
match _serde::private::de::missing_field("a") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
}
};
_serde::export::Ok(Lifetimes::NoLifetimeMap { a: __field0 })
}
}
const FIELDS: &'static [&'static str] = &["a"];
_serde::de::VariantAccess::struct_variant(
__variant,
FIELDS,
__Visitor {
marker: _serde::export::PhantomData::<Lifetimes<'a>>,
lifetime: _serde::export::PhantomData,
},
)
}
}
}
}
const VARIANTS: &'static [&'static str] = &[
"LifetimeSeq",
"NoLifetimeSeq",
"LifetimeMap",
"NoLifetimeMap",
];
_serde::Deserializer::deserialize_enum(
__deserializer,
"Lifetimes",
VARIANTS,
__Visitor {
marker: _serde::export::PhantomData::<Lifetimes<'a>>,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
+9
View File
@@ -0,0 +1,9 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
enum Lifetimes<'a> {
LifetimeSeq(&'a i32),
NoLifetimeSeq(i32),
LifetimeMap { a: &'a i32 },
NoLifetimeMap { a: i32 },
}
@@ -0,0 +1,615 @@
use serde::{Deserialize, Serialize};
struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
a: &'a A,
b: &'b mut B,
c: C,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedMap<'a, 'b, A, B, C>
where
A: _serde::Serialize,
B: _serde::Serialize,
C: _serde::Serialize,
{
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let mut __serde_state = match _serde::Serializer::serialize_struct(
__serializer,
"SerNamedMap",
false as usize + 1 + 1 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state, "a", &self.a) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state, "b", &self.b) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStruct::serialize_field(&mut __serde_state, "c", &self.c) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStruct::end(__serde_state)
}
}
};
struct DeNamedMap<A, B, C> {
a: A,
b: B,
c: C,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedMap<A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "field identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
2u64 => _serde::export::Ok(__Field::__field2),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"a" => _serde::export::Ok(__Field::__field0),
"b" => _serde::export::Ok(__Field::__field1),
"c" => _serde::export::Ok(__Field::__field2),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"a" => _serde::export::Ok(__Field::__field0),
b"b" => _serde::export::Ok(__Field::__field1),
b"c" => _serde::export::Ok(__Field::__field2),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
marker: _serde::export::PhantomData<DeNamedMap<A, B, C>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, A, B, C> _serde::de::Visitor<'de> for __Visitor<'de, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
type Value = DeNamedMap<A, B, C>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "struct DeNamedMap")
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<A>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"struct DeNamedMap with 3 elements",
));
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<B>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
1usize,
&"struct DeNamedMap with 3 elements",
));
}
};
let __field2 = match match _serde::de::SeqAccess::next_element::<C>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
2usize,
&"struct DeNamedMap with 3 elements",
));
}
};
_serde::export::Ok(DeNamedMap {
a: __field0,
b: __field1,
c: __field2,
})
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: _serde::export::Option<A> = _serde::export::None;
let mut __field1: _serde::export::Option<B> = _serde::export::None;
let mut __field2: _serde::export::Option<C> = _serde::export::None;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if _serde::export::Option::is_some(&__field0) {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field("a"),
);
}
__field0 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<A>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
__Field::__field1 => {
if _serde::export::Option::is_some(&__field1) {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field("b"),
);
}
__field1 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<B>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
__Field::__field2 => {
if _serde::export::Option::is_some(&__field2) {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field("c"),
);
}
__field2 = _serde::export::Some(
match _serde::de::MapAccess::next_value::<C>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
);
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
let __field0 = match __field0 {
_serde::export::Some(__field0) => __field0,
_serde::export::None => match _serde::private::de::missing_field("a") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
};
let __field1 = match __field1 {
_serde::export::Some(__field1) => __field1,
_serde::export::None => match _serde::private::de::missing_field("b") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
};
let __field2 = match __field2 {
_serde::export::Some(__field2) => __field2,
_serde::export::None => match _serde::private::de::missing_field("c") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
},
};
_serde::export::Ok(DeNamedMap {
a: __field0,
b: __field1,
c: __field2,
})
}
}
const FIELDS: &'static [&'static str] = &["a", "b", "c"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"DeNamedMap",
FIELDS,
__Visitor {
marker: _serde::export::PhantomData::<DeNamedMap<A, B, C>>,
lifetime: _serde::export::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::export::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {
__field0,
__field1,
__field2,
__ignore,
}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "field identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
0u64 => _serde::export::Ok(__Field::__field0),
1u64 => _serde::export::Ok(__Field::__field1),
2u64 => _serde::export::Ok(__Field::__field2),
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
"a" => _serde::export::Ok(__Field::__field0),
"b" => _serde::export::Ok(__Field::__field1),
"c" => _serde::export::Ok(__Field::__field2),
_ => _serde::export::Ok(__Field::__ignore),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
b"a" => _serde::export::Ok(__Field::__field0),
b"b" => _serde::export::Ok(__Field::__field1),
b"c" => _serde::export::Ok(__Field::__field2),
_ => _serde::export::Ok(__Field::__ignore),
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de, 'place, A: 'place, B: 'place, C: 'place>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
place: &'place mut DeNamedMap<A, B, C>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'place, A: 'place, B: 'place, C: 'place> _serde::de::Visitor<'de>
for __Visitor<'de, 'place, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "struct DeNamedMap")
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.a),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"struct DeNamedMap with 3 elements",
));
}
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.b),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
1usize,
&"struct DeNamedMap with 3 elements",
));
}
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.c),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
2usize,
&"struct DeNamedMap with 3 elements",
));
}
_serde::export::Ok(())
}
#[inline]
fn visit_map<__A>(
self,
mut __map: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::MapAccess<'de>,
{
let mut __field0: bool = false;
let mut __field1: bool = false;
let mut __field2: bool = false;
while let _serde::export::Some(__key) =
match _serde::de::MapAccess::next_key::<__Field>(&mut __map) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
}
{
match __key {
__Field::__field0 => {
if __field0 {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field("a"),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::private::de::InPlaceSeed(&mut self.place.a),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
__field0 = true;
}
__Field::__field1 => {
if __field1 {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field("b"),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::private::de::InPlaceSeed(&mut self.place.b),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
__field1 = true;
}
__Field::__field2 => {
if __field2 {
return _serde::export::Err(
<__A::Error as _serde::de::Error>::duplicate_field("c"),
);
}
match _serde::de::MapAccess::next_value_seed(
&mut __map,
_serde::private::de::InPlaceSeed(&mut self.place.c),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
__field2 = true;
}
_ => {
let _ = match _serde::de::MapAccess::next_value::<
_serde::de::IgnoredAny,
>(&mut __map)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
}
}
}
if !__field0 {
self.place.a = match _serde::private::de::missing_field("a") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
};
if !__field1 {
self.place.b = match _serde::private::de::missing_field("b") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
};
if !__field2 {
self.place.c = match _serde::private::de::missing_field("c") {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
};
_serde::export::Ok(())
}
}
const FIELDS: &'static [&'static str] = &["a", "b", "c"];
_serde::Deserializer::deserialize_struct(
__deserializer,
"DeNamedMap",
FIELDS,
__Visitor {
place: __place,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
+15
View File
@@ -0,0 +1,15 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
a: &'a A,
b: &'b mut B,
c: C,
}
#[derive(Deserialize)]
struct DeNamedMap<A, B, C> {
a: A,
b: B,
c: C,
}
@@ -0,0 +1,250 @@
use serde::{Deserialize, Serialize};
struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'a, 'b, A: 'a, B: 'b, C> _serde::Serialize for SerNamedTuple<'a, 'b, A, B, C>
where
A: _serde::Serialize,
B: _serde::Serialize,
C: _serde::Serialize,
{
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
let mut __serde_state = match _serde::Serializer::serialize_tuple_struct(
__serializer,
"SerNamedTuple",
0 + 1 + 1 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleStruct::serialize_field(&mut __serde_state, &self.0) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleStruct::serialize_field(&mut __serde_state, &self.1) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleStruct::serialize_field(&mut __serde_state, &self.2) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeTupleStruct::end(__serde_state)
}
}
};
struct DeNamedTuple<A, B, C>(A, B, C);
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de, A, B, C> _serde::Deserialize<'de> for DeNamedTuple<A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
marker: _serde::export::PhantomData<DeNamedTuple<A, B, C>>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, A, B, C> _serde::de::Visitor<'de> for __Visitor<'de, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
type Value = DeNamedTuple<A, B, C>;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "tuple struct DeNamedTuple")
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
let __field0 = match match _serde::de::SeqAccess::next_element::<A>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"tuple struct DeNamedTuple with 3 elements",
));
}
};
let __field1 = match match _serde::de::SeqAccess::next_element::<B>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
1usize,
&"tuple struct DeNamedTuple with 3 elements",
));
}
};
let __field2 = match match _serde::de::SeqAccess::next_element::<C>(&mut __seq)
{
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
_serde::export::Some(__value) => __value,
_serde::export::None => {
return _serde::export::Err(_serde::de::Error::invalid_length(
2usize,
&"tuple struct DeNamedTuple with 3 elements",
));
}
};
_serde::export::Ok(DeNamedTuple(__field0, __field1, __field2))
}
}
_serde::Deserializer::deserialize_tuple_struct(
__deserializer,
"DeNamedTuple",
3usize,
__Visitor {
marker: _serde::export::PhantomData::<DeNamedTuple<A, B, C>>,
lifetime: _serde::export::PhantomData,
},
)
}
fn deserialize_in_place<__D>(
__deserializer: __D,
__place: &mut Self,
) -> _serde::export::Result<(), __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor<'de, 'place, A: 'place, B: 'place, C: 'place>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
place: &'place mut DeNamedTuple<A, B, C>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de, 'place, A: 'place, B: 'place, C: 'place> _serde::de::Visitor<'de>
for __Visitor<'de, 'place, A, B, C>
where
A: _serde::Deserialize<'de>,
B: _serde::Deserialize<'de>,
C: _serde::Deserialize<'de>,
{
type Value = ();
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "tuple struct DeNamedTuple")
}
#[inline]
fn visit_seq<__A>(
self,
mut __seq: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<'de>,
{
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.0),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
0usize,
&"tuple struct DeNamedTuple with 3 elements",
));
}
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.1),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
1usize,
&"tuple struct DeNamedTuple with 3 elements",
));
}
if let _serde::export::None = match _serde::de::SeqAccess::next_element_seed(
&mut __seq,
_serde::private::de::InPlaceSeed(&mut self.place.2),
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
} {
return _serde::export::Err(_serde::de::Error::invalid_length(
2usize,
&"tuple struct DeNamedTuple with 3 elements",
));
}
_serde::export::Ok(())
}
}
_serde::Deserializer::deserialize_tuple_struct(
__deserializer,
"DeNamedTuple",
3usize,
__Visitor {
place: __place,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
+7
View File
@@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize)]
struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
#[derive(Deserialize)]
struct DeNamedTuple<A, B, C>(A, B, C);
@@ -0,0 +1,49 @@
use serde::{Deserialize, Serialize};
struct NamedUnit;
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl _serde::Serialize for NamedUnit {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
_serde::Serializer::serialize_unit_struct(__serializer, "NamedUnit")
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for NamedUnit {
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
struct __Visitor;
impl<'de> _serde::de::Visitor<'de> for __Visitor {
type Value = NamedUnit;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "unit struct NamedUnit")
}
#[inline]
fn visit_unit<__E>(self) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
_serde::export::Ok(NamedUnit)
}
}
_serde::Deserializer::deserialize_unit_struct(__deserializer, "NamedUnit", __Visitor)
}
}
};
+4
View File
@@ -0,0 +1,4 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct NamedUnit;
@@ -0,0 +1,268 @@
use serde::Serialize;
enum SerEnum<'a, B: 'a, C: 'a, D>
where
D: 'a,
{
Unit,
Seq(i8, B, &'a C, &'a mut D),
Map { a: i8, b: B, c: &'a C, d: &'a mut D },
_Unit2,
_Seq2(i8, B, &'a C, &'a mut D),
_Map2 { a: i8, b: B, c: &'a C, d: &'a mut D },
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'a, B: 'a, C: 'a, D> _serde::Serialize for SerEnum<'a, B, C, D>
where
D: 'a,
B: _serde::Serialize,
C: _serde::Serialize,
D: _serde::Serialize,
{
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
match *self {
SerEnum::Unit => _serde::Serializer::serialize_unit_variant(
__serializer,
"SerEnum",
0u32,
"Unit",
),
SerEnum::Seq(ref __field0, ref __field1, ref __field2, ref __field3) => {
let mut __serde_state = match _serde::Serializer::serialize_tuple_variant(
__serializer,
"SerEnum",
1u32,
"Seq",
0 + 1 + 1 + 1 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field0,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field2,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field3,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
SerEnum::Map {
ref a,
ref b,
ref c,
ref d,
} => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"SerEnum",
2u32,
"Map",
0 + 1 + 1 + 1 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"a",
a,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"b",
b,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"c",
c,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"d",
d,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
SerEnum::_Unit2 => _serde::Serializer::serialize_unit_variant(
__serializer,
"SerEnum",
3u32,
"_Unit2",
),
SerEnum::_Seq2(ref __field0, ref __field1, ref __field2, ref __field3) => {
let mut __serde_state = match _serde::Serializer::serialize_tuple_variant(
__serializer,
"SerEnum",
4u32,
"_Seq2",
0 + 1 + 1 + 1 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field0,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field2,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeTupleVariant::serialize_field(
&mut __serde_state,
__field3,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeTupleVariant::end(__serde_state)
}
SerEnum::_Map2 {
ref a,
ref b,
ref c,
ref d,
} => {
let mut __serde_state = match _serde::Serializer::serialize_struct_variant(
__serializer,
"SerEnum",
5u32,
"_Map2",
0 + 1 + 1 + 1 + 1,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"a",
a,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"b",
b,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"c",
c,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
match _serde::ser::SerializeStructVariant::serialize_field(
&mut __serde_state,
"d",
d,
) {
_serde::export::Ok(__val) => __val,
_serde::export::Err(__err) => {
return _serde::export::Err(__err);
}
};
_serde::ser::SerializeStructVariant::end(__serde_state)
}
}
}
}
};
+16
View File
@@ -0,0 +1,16 @@
use serde::Serialize;
#[derive(Serialize)]
enum SerEnum<'a, B: 'a, C: 'a, D>
where
D: 'a,
{
Unit,
Seq(i8, B, &'a C, &'a mut D),
Map { a: i8, b: B, c: &'a C, d: &'a mut D },
// Make sure we can support more than one variant.
_Unit2,
_Seq2(i8, B, &'a C, &'a mut D),
_Map2 { a: i8, b: B, c: &'a C, d: &'a mut D },
}
+124
View File
@@ -0,0 +1,124 @@
use serde::{Deserialize, Serialize};
enum Void {}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl _serde::Serialize for Void {
fn serialize<__S>(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error>
where
__S: _serde::Serializer,
{
match *self {}
}
}
};
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () = {
#[allow(rust_2018_idioms, clippy::useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for Void {
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
#[allow(non_camel_case_types)]
enum __Field {}
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "variant identifier")
}
fn visit_u64<__E>(self, __value: u64) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
_ => _serde::export::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&"variant index 0 <= i < 0",
)),
}
}
fn visit_str<__E>(self, __value: &str) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
_ => _serde::export::Err(_serde::de::Error::unknown_variant(
__value, VARIANTS,
)),
}
}
fn visit_bytes<__E>(
self,
__value: &[u8],
) -> _serde::export::Result<Self::Value, __E>
where
__E: _serde::de::Error,
{
match __value {
_ => {
let __value = &_serde::export::from_utf8_lossy(__value);
_serde::export::Err(_serde::de::Error::unknown_variant(
__value, VARIANTS,
))
}
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result<Self, __D::Error>
where
__D: _serde::Deserializer<'de>,
{
_serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor)
}
}
struct __Visitor<'de> {
marker: _serde::export::PhantomData<Void>,
lifetime: _serde::export::PhantomData<&'de ()>,
}
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = Void;
fn expecting(
&self,
__formatter: &mut _serde::export::Formatter,
) -> _serde::export::fmt::Result {
_serde::export::Formatter::write_str(__formatter, "enum Void")
}
fn visit_enum<__A>(
self,
__data: __A,
) -> _serde::export::Result<Self::Value, __A::Error>
where
__A: _serde::de::EnumAccess<'de>,
{
_serde::export::Result::map(
_serde::de::EnumAccess::variant::<__Field>(__data),
|(__impossible, _)| match __impossible {},
)
}
}
const VARIANTS: &'static [&'static str] = &[];
_serde::Deserializer::deserialize_enum(
__deserializer,
"Void",
VARIANTS,
__Visitor {
marker: _serde::export::PhantomData::<Void>,
lifetime: _serde::export::PhantomData,
},
)
}
}
};
+4
View File
@@ -0,0 +1,4 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
enum Void {}
+8
View File
@@ -0,0 +1,8 @@
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg_attr(not(expandtest), ignore)]
#[rustversion::attr(not(nightly), ignore)]
#[allow(unused_attributes)]
#[test]
fn expandtest() {
macrotest::expand("tests/expand/*.rs");
}
+51 -6
View File
@@ -4,6 +4,7 @@ use serde::de::{self, MapAccess, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::{BTreeMap, HashMap};
use std::convert::TryFrom;
use std::fmt;
use std::marker::PhantomData;
@@ -1588,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]
fn test_from_into_traits() {
assert_ser_tokens::<EnumToU32>(&EnumToU32::One, &[Token::Some, Token::U32(1)]);
assert_ser_tokens::<EnumToU32>(&EnumToU32::Nothing, &[Token::None]);
assert_de_tokens::<EnumToU32>(&EnumToU32::Two, &[Token::Some, Token::U32(2)]);
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(Some(5)), &[Token::None]);
assert_ser_tokens::<StructFromEnum>(&StructFromEnum(None), &[Token::None]);
assert_de_tokens::<StructFromEnum>(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]);
assert_ser_tokens(&EnumToU32::One, &[Token::Some, Token::U32(1)]);
assert_ser_tokens(&EnumToU32::Nothing, &[Token::None]);
assert_de_tokens(&EnumToU32::Two, &[Token::Some, Token::U32(2)]);
assert_ser_tokens(&StructFromEnum(Some(5)), &[Token::None]);
assert_ser_tokens(&StructFromEnum(None), &[Token::None]);
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]
@@ -1945,6 +1967,29 @@ fn test_flatten_map_twice() {
);
}
#[test]
fn test_flatten_unit() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Response<T> {
#[serde(flatten)]
data: T,
status: usize,
}
assert_tokens(
&Response {
data: (),
status: 0,
},
&[
Token::Map { len: None },
Token::Str("status"),
Token::U64(0),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_unsupported_type() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
+39 -4
View File
@@ -104,6 +104,9 @@ struct StructSkipAllDenyUnknown {
a: i32,
}
#[derive(Default, PartialEq, Debug)]
struct NotDeserializable;
#[derive(PartialEq, Debug, Deserialize)]
enum Enum {
#[allow(dead_code)]
@@ -117,6 +120,7 @@ enum Enum {
b: i32,
c: i32,
},
SimpleWithSkipped(#[serde(skip_deserializing)] NotDeserializable),
}
#[derive(PartialEq, Debug, Deserialize)]
@@ -728,6 +732,11 @@ declare_tests! {
Token::I32(1),
],
}
test_enum_simple_with_skipped {
Enum::SimpleWithSkipped(NotDeserializable) => &[
Token::UnitVariant { name: "Enum", variant: "SimpleWithSkipped" },
],
}
test_enum_seq {
Enum::Seq(1, 2, 3) => &[
Token::TupleVariant { name: "Enum", variant: "Seq", len: 3 },
@@ -880,11 +889,37 @@ declare_tests! {
Path::new("/usr/local/lib") => &[
Token::BorrowedStr("/usr/local/lib"),
],
Path::new("/usr/local/lib") => &[
Token::BorrowedBytes(b"/usr/local/lib"),
],
}
test_path_buf {
PathBuf::from("/usr/local/lib") => &[
Token::Str("/usr/local/lib"),
],
PathBuf::from("/usr/local/lib") => &[
Token::String("/usr/local/lib"),
],
PathBuf::from("/usr/local/lib") => &[
Token::Bytes(b"/usr/local/lib"),
],
PathBuf::from("/usr/local/lib") => &[
Token::ByteBuf(b"/usr/local/lib"),
],
}
test_boxed_path {
PathBuf::from("/usr/local/lib").into_boxed_path() => &[
Token::Str("/usr/local/lib"),
],
PathBuf::from("/usr/local/lib").into_boxed_path() => &[
Token::String("/usr/local/lib"),
],
PathBuf::from("/usr/local/lib").into_boxed_path() => &[
Token::Bytes(b"/usr/local/lib"),
],
PathBuf::from("/usr/local/lib").into_boxed_path() => &[
Token::ByteBuf(b"/usr/local/lib"),
],
}
test_cstring {
CString::new("abc").unwrap() => &[
@@ -1217,13 +1252,13 @@ declare_error_tests! {
&[
Token::UnitVariant { name: "Enum", variant: "Foo" },
],
"unknown variant `Foo`, expected one of `Unit`, `Simple`, `Seq`, `Map`",
"unknown variant `Foo`, expected one of `Unit`, `Simple`, `Seq`, `Map`, `SimpleWithSkipped`",
}
test_enum_skipped_variant<Enum> {
&[
Token::UnitVariant { name: "Enum", variant: "Skipped" },
],
"unknown variant `Skipped`, expected one of `Unit`, `Simple`, `Seq`, `Map`",
"unknown variant `Skipped`, expected one of `Unit`, `Simple`, `Seq`, `Map`, `SimpleWithSkipped`",
}
test_enum_skip_all<EnumSkipAll> {
&[
@@ -1254,10 +1289,10 @@ declare_error_tests! {
test_enum_out_of_range<Enum> {
&[
Token::Enum { name: "Enum" },
Token::U32(4),
Token::U32(5),
Token::Unit,
],
"invalid value: integer `4`, expected variant index 0 <= i < 4",
"invalid value: integer `5`, expected variant index 0 <= i < 5",
}
test_short_tuple<(u8, u8, u8)> {
&[
+34 -2
View File
@@ -4,7 +4,11 @@
#![deny(warnings)]
#![cfg_attr(feature = "unstable", feature(non_ascii_idents))]
#![allow(clippy::trivially_copy_pass_by_ref)]
#![allow(
unknown_lints,
mixed_script_confusables,
clippy::trivially_copy_pass_by_ref
)]
use serde::de::DeserializeOwned;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
@@ -265,7 +269,7 @@ fn test_gen() {
#[cfg(feature = "unstable")]
#[derive(Serialize, Deserialize)]
struct NonAsciiIdents {
σ: f64,
σ: f64,
}
#[derive(Serialize, Deserialize)]
@@ -691,6 +695,34 @@ fn test_gen() {
#[serde(flatten, skip_deserializing)]
flat: T,
}
// https://github.com/serde-rs/serde/issues/1804
#[derive(Serialize, Deserialize)]
enum Message {
#[serde(skip)]
#[allow(dead_code)]
String(String),
#[serde(other)]
Unknown,
}
#[derive(Serialize)]
#[repr(packed)]
struct Packed {
x: u8,
y: u16,
}
macro_rules! deriving {
($field:ty) => {
#[derive(Deserialize)]
struct MacroRules<'a> {
field: $field,
}
};
}
deriving!(&'a str);
}
//////////////////////////////////////////////////////////////////////////
+45 -5
View File
@@ -637,7 +637,10 @@ fn test_untagged_enum() {
],
);
// Serializes to unit, deserializes from either depending on format's
// preference.
assert_tokens(&Untagged::C, &[Token::Unit]);
assert_de_tokens(&Untagged::C, &[Token::None]);
assert_tokens(&Untagged::D(4), &[Token::U8(4)]);
assert_tokens(&Untagged::E("e".to_owned()), &[Token::Str("e")]);
@@ -652,11 +655,6 @@ fn test_untagged_enum() {
],
);
assert_de_tokens_error::<Untagged>(
&[Token::None],
"data did not match any variant of untagged enum Untagged",
);
assert_de_tokens_error::<Untagged>(
&[Token::Tuple { len: 1 }, Token::U8(1), Token::TupleEnd],
"data did not match any variant of untagged enum Untagged",
@@ -1147,6 +1145,20 @@ fn test_adjacently_tagged_enum() {
],
);
// optional newtype with no content field
assert_de_tokens(
&AdjacentlyTagged::Newtype::<Option<u8>>(None),
&[
Token::Struct {
name: "AdjacentlyTagged",
len: 1,
},
Token::Str("t"),
Token::Str("Newtype"),
Token::StructEnd,
],
);
// tuple with tag first
assert_tokens(
&AdjacentlyTagged::Tuple::<u8>(1, 1),
@@ -1866,3 +1878,31 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() {
],
);
}
#[deny(safe_packed_borrows)]
#[test]
fn test_packed_struct_can_derive_serialize() {
#[derive(Copy, Clone, Serialize)]
#[repr(packed, C)]
struct PackedC {
t: f32,
}
#[derive(Copy, Clone, Serialize)]
#[repr(C, packed)]
struct CPacked {
t: f32,
}
#[derive(Copy, Clone, Serialize)]
#[repr(C, packed(2))]
struct CPacked2 {
t: f32,
}
#[derive(Copy, Clone, Serialize)]
#[repr(packed(2), C)]
struct Packed2C {
t: f32,
}
}
+14 -2
View File
@@ -44,6 +44,9 @@ struct Struct {
c: i32,
}
#[derive(PartialEq, Debug)]
struct NotSerializable;
#[derive(Serialize, PartialEq, Debug)]
enum Enum {
Unit,
@@ -64,6 +67,7 @@ enum Enum {
_a: i32,
_b: i32,
},
OneWithSkipped(#[serde(skip_serializing)] NotSerializable),
}
//////////////////////////////////////////////////////////////////////////
@@ -309,8 +313,13 @@ declare_tests! {
],
}
test_enum {
Enum::Unit => &[Token::UnitVariant { name: "Enum", variant: "Unit" }],
Enum::One(42) => &[Token::NewtypeVariant { name: "Enum", variant: "One" }, Token::I32(42)],
Enum::Unit => &[
Token::UnitVariant { name: "Enum", variant: "Unit" },
],
Enum::One(42) => &[
Token::NewtypeVariant { name: "Enum", variant: "One" },
Token::I32(42),
],
Enum::Seq(1, 2) => &[
Token::TupleVariant { name: "Enum", variant: "Seq", len: 2 },
Token::I32(1),
@@ -326,6 +335,9 @@ declare_tests! {
Token::I32(2),
Token::StructVariantEnd,
],
Enum::OneWithSkipped(NotSerializable) => &[
Token::UnitVariant { name: "Enum", variant: "OneWithSkipped" },
],
}
test_box {
Box::new(0i32) => &[Token::I32(0)],
@@ -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 | | }
| |_^
+7
View File
@@ -0,0 +1,7 @@
use serde_derive::Serialize;
#[derive(Serialize)]
#[serde(rename =)]
struct S;
fn main() {}
@@ -0,0 +1,5 @@
error: unexpected end of input, expected literal
--> $DIR/cut_off.rs:4:17
|
4 | #[serde(rename =)]
| ^
@@ -0,0 +1,8 @@
use serde_derive::Serialize;
#[derive(Serialize)]
#[serde]
#[serde = "?"]
struct S;
fn main() {}
@@ -0,0 +1,11 @@
error: expected #[serde(...)]
--> $DIR/not_list.rs:4:3
|
4 | #[serde]
| ^^^^^
error: expected #[serde(...)]
--> $DIR/not_list.rs:5:3
|
5 | #[serde = "?"]
| ^^^^^^^^^^^
@@ -3,5 +3,3 @@ error[E0063]: missing field `b` in initializer of `remote::S`
|
11 | #[serde(remote = "remote::S")]
| ^^^^^^^^^^^ missing `b`
For more information about this error, try `rustc --explain E0063`.
@@ -2,13 +2,10 @@ error[E0609]: no field `b` on type `&remote::S`
--> $DIR/unknown_field.rs:12:5
|
12 | b: u8,
| ^
| ^ help: a field with a similar name exists: `a`
error[E0560]: struct `remote::S` has no field named `b`
--> $DIR/unknown_field.rs:12:5
|
12 | b: u8,
| ^ help: a field with a similar name exists: `a`
Some errors have detailed explanations: E0560, E0609.
For more information about an error, try `rustc --explain E0560`.
+6 -3
View File
@@ -2,6 +2,9 @@ error[E0308]: mismatched types
--> $DIR/wrong_de.rs:7:10
|
7 | #[derive(Deserialize)]
| ^^^^^^^^^^^ expected u16, found u8
For more information about this error, try `rustc --explain E0308`.
| ^^^^^^^^^^^
| |
| expected `u16`, found `u8`
| help: you can convert an `u8` to `u16`: `Deserialize.into()`
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -2,9 +2,8 @@ error[E0308]: mismatched types
--> $DIR/wrong_getter.rs:15:10
|
15 | #[derive(Serialize)]
| ^^^^^^^^^ expected u8, found u16
| ^^^^^^^^^ expected `u8`, found `u16`
|
= note: expected type `&u8`
found type `&u16`
For more information about this error, try `rustc --explain E0308`.
= note: expected reference `&u8`
found reference `&u16`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
+4 -5
View File
@@ -2,9 +2,8 @@ error[E0308]: mismatched types
--> $DIR/wrong_ser.rs:9:10
|
9 | #[derive(Serialize)]
| ^^^^^^^^^ expected u8, found u16
| ^^^^^^^^^ expected `u8`, found `u16`
|
= note: expected type `&u8`
found type `&u16`
For more information about this error, try `rustc --explain E0308`.
= note: expected reference `&u8`
found reference `&u16`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -3,3 +3,5 @@ error: #[serde(tag = "...")] can only be used on enums and structs with named fi
|
3 | #[derive(Serialize)]
| ^^^^^^^^^
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -0,0 +1,9 @@
use serde_derive::Serialize;
#[derive(Serialize)]
#[serde(transparent, try_from = "u64")]
struct S {
a: u8,
}
fn main() {}
@@ -0,0 +1,8 @@
error: #[serde(transparent)] is not allowed with #[serde(try_from = "...")]
--> $DIR/with_try_from.rs:4:1
|
4 | / #[serde(transparent, try_from = "u64")]
5 | | struct S {
6 | | a: u8,
7 | | }
| |_^
@@ -0,0 +1,12 @@
use serde_derive::Deserialize;
#[derive(Deserialize)]
#[serde(try_from = "Option<T")]
enum TestOne {
Testing,
One,
Two,
Three,
}
fn main() {}
@@ -0,0 +1,5 @@
error: failed to parse type: try_from = "Option<T"
--> $DIR/try_from.rs:4:20
|
4 | #[serde(try_from = "Option<T")]
| ^^^^^^^^^^