Compare commits

...

87 Commits

Author SHA1 Message Date
David Tolnay 05a5b7e3c6 Release 1.0.183 2023-08-06 21:00:14 -07:00
David Tolnay 3bff326fb3 Merge pull request #2555 from Mingun/field
Refactor code that generates `__Field` enums
2023-08-06 18:23:52 -07:00
David Tolnay aaadd93878 Merge pull request #2556 from DBLouis/master
Add forward impl for OsStr
2023-08-06 18:02:21 -07:00
Louis Dupré Bertoni 9c864f0b02 Add forward impl for OsStr 2023-08-06 19:41:19 +03:00
Mingun 070cce0d9c Get rid of temporary variable 2023-08-06 19:55:48 +05:00
Mingun b58e8bac12 Replace if let Some(...) = ... to Option::map 2023-08-06 19:53:39 +05:00
Mingun ada50b077e ignore_variant variable is always None, let's take this into account 2023-08-06 19:36:48 +05:00
Mingun 5e313a7330 Move generiс code out-of-function, create more specialized and simple code 2023-08-06 19:35:27 +05:00
Mingun 2a36d11238 Introduce a dedicated function for generating Field enum
(the enum that represents all fields of a struct)
2023-08-06 19:32:53 +05:00
David Tolnay b6685cf9dd Release 1.0.182 2023-08-05 22:16:46 -07:00
David Tolnay fc273c6763 Resolve needless_return clippy lint in PR 2553
warning: unneeded `return` statement
        --> serde_derive/src/de.rs:2986:13
         |
    2986 |             return quote!(#assign_to __default.#member);
         |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_return
         = note: `-W clippy::needless-return` implied by `-W clippy::all`
    help: remove `return`
         |
    2986 -             return quote!(#assign_to __default.#member);
    2986 +             quote!(#assign_to __default.#member)
         |
2023-08-05 22:16:19 -07:00
David Tolnay bd7b0e257e Touch up PR 2553 2023-08-05 22:13:09 -07:00
David Tolnay 73931692b2 Merge pull request #2553 from Mingun/default-on-tuples
Allow `#[serde(default)]` on tuple structs
2023-08-05 22:12:10 -07:00
David Tolnay 4d93e9f44c Keep deserialize aliases as a sorted set 2023-08-05 17:06:11 -07:00
David Tolnay da55ed7e8d Remove some clones of names of things 2023-08-05 17:01:34 -07:00
David Tolnay e3617e1f28 Update explanation of correct_aliases 2023-08-05 16:39:38 -07:00
David Tolnay 431636af0d Merge pull request #2458 from Mingun/identifier
Keep aliases always sorted and include aliases in expecting message for field/variant_identifier
2023-08-05 16:39:14 -07:00
David Tolnay 891ced598a Update test suite to nightly-2023-08-05
error: the feature `lang_items` is internal to the compiler or standard library
     --> src/main.rs:1:12
      |
    1 | #![feature(lang_items, start)]
      |            ^^^^^^^^^^
      |
      = note: using it is strongly discouraged
      = note: `#[deny(internal_features)]` on by default
2023-08-04 19:09:00 -07:00
David Tolnay 57dc0ee769 Release 1.0.181 2023-08-03 16:58:45 -07:00
David Tolnay 5e102c4da1 Relocate private size_hint module
Let's keep crate::__private for only things that *need* to be accessible
to the macro-generated code. Size_hint can be pub(crate).
2023-08-03 16:53:44 -07:00
Mingun 5c33931422 Allow #[serde(default)] on tuple structs 2023-08-03 22:32:34 +05:00
David Tolnay 4aa54222f4 Delete double reference when setting up adjacently tagged variant seed 2023-08-01 22:54:47 -07:00
David Tolnay ef4f860384 Improve "expecting" message of adjacently tagged enum variant 2023-08-01 22:49:44 -07:00
David Tolnay 9bd52ec5c1 Inline AdjacentlyTaggedEnumVariant::new 2023-08-01 22:38:47 -07:00
David Tolnay 5cdd82d41e Remove Serializer from name of private type that is not a Serializer 2023-08-01 22:26:04 -07:00
David Tolnay 110bf10481 Condense AdjacentlyTaggedEnummVariantVisitor implementation 2023-08-01 22:26:03 -07:00
David Tolnay 43035f6f37 Merge pull request #2505 from Baptistemontan/rework_adjacently_tagged_enum
Revisit of the representation of adjacently tagged enums tag
2023-08-01 22:25:31 -07:00
David Tolnay 83b1a3d5dc Merge pull request #2443 from Mingun/deserialize-in-place
Simplify code in deserialize_in_place_struct and implement #2387 for in-place case
2023-08-01 21:51:22 -07:00
Mingun 878110a4bc Simplify code after dead code elimination 2023-08-01 19:03:21 +05:00
Mingun 59ec8b7db2 Remove dead code - variant_ident and deserializer are always None 2023-08-01 19:03:20 +05:00
Mingun cae1b43829 Inline deserialize_newtype_struct_in_place 2023-08-01 19:03:19 +05:00
Mingun 99fde4ee3e Implement #2387 also for deserialize_in_place method 2023-08-01 19:03:19 +05:00
Mingun afe3872810 Simplify check for missing fields 2023-08-01 19:03:18 +05:00
Mingun 3a3e6bf103 Reorder variables to match order in final quote! 2023-08-01 19:03:18 +05:00
Mingun 935f0bd70f Merge some quote! blocks 2023-08-01 19:03:17 +05:00
Mingun 5c18bfeda6 Inline deserialize_struct_as_struct_in_place_visitor 2023-08-01 19:03:17 +05:00
Baptiste de Montangon 957ef206d1 Revisit of the representation of adjacently tagged enums tag 2023-07-31 20:53:02 +02:00
David Tolnay 0c367838cc Merge pull request #2548 from dtolnay/toolattr
Adopt tool attrs for clippy lint level attributes
2023-07-31 11:48:33 -07:00
David Tolnay 2023cf345f Adopt tool attrs for clippy lint level attributes
Requires rustc 1.31+.
2023-07-31 11:39:31 -07:00
David Tolnay 033d05f70b Release 1.0.180 2023-07-31 11:16:12 -07:00
David Tolnay fe4e3fd3b0 Merge pull request #2547 from dtolnay/tombstone
Delete tombstones of the `__private` module
2023-07-30 22:48:34 -07:00
David Tolnay 8a8a8a70ee Delete tombstones of the __private module
These are previous names of the `__private` module -- first
`serde::export` then `serde::private` then `serde::__private` -- in all
cases marked `doc(hidden)` and documented as not public API. Leaving a
tombstone made rustc give a better diagnostic "module is private" rather
than "unresolved import". But the rename to `__private` was 2.5 years
ago in dd1f4b483e so it's unlikely anyone
is still benefiting from the tombstone at this point.
2023-07-30 22:44:59 -07:00
David Tolnay 339dca828d Merge pull request #2546 from dtolnay/edition
Update to 2018 edition
2023-07-30 22:11:44 -07:00
David Tolnay 0d7349fa4e Resolve ambiguous core import on rustc 1.64 through 1.71
In 1.72+, this is fixed by https://github.com/rust-lang/rust/pull/112086.

    error[E0659]: `core` is ambiguous
       --> serde/src/lib.rs:227:13
        |
    227 |     pub use core::ffi::CStr;
        |             ^^^^ ambiguous name
        |
        = note: ambiguous because of multiple potential import sources
        = note: `core` could refer to a built-in crate
        = help: use `::core` to refer to this crate unambiguously
    note: `core` could also refer to the module defined here
       --> serde/src/lib.rs:166:5
        |
    166 | /     mod core {
    167 | |         #[cfg(not(feature = "std"))]
    168 | |         pub use core::*;
    169 | |         #[cfg(feature = "std")]
    170 | |         pub use std::*;
    171 | |     }
        | |_____^
        = help: use `self::core` to refer to this module unambiguously
2023-07-30 22:06:18 -07:00
David Tolnay 830528d5b1 Update to 2018 edition 2023-07-30 21:45:35 -07:00
David Tolnay ab90fbc7c9 Apply 'cargo fix --edition' 2023-07-30 21:42:57 -07:00
David Tolnay 3eec111e8f Delete support for compilers without crate::-based module system 2023-07-30 21:42:57 -07:00
David Tolnay 9388433642 Rename 'try!' macro to 'tri!' in preparation for 2018 edition
Because 'try' is a keyword in 2018+.
2023-07-30 21:29:53 -07:00
David Tolnay ba12070665 Merge pull request #2545 from dtolnay/up
Delete support for rustc versions 1.19 through 1.27
2023-07-30 21:25:58 -07:00
David Tolnay a57a324d72 Delete support for compilers without NonZero integer types 2023-07-30 21:14:32 -07:00
David Tolnay 92e91b3557 Delete support for compilers without Iterator::try_for_each 2023-07-30 21:14:31 -07:00
David Tolnay 4dcf791706 Delete support for compilers without inclusive range accessors 2023-07-30 21:11:43 -07:00
David Tolnay e77900fb94 Update integer128 case in build script 2023-07-30 21:11:09 -07:00
David Tolnay 1b14cadf20 Delete support for compilers without core::ops::Bound 2023-07-30 21:11:02 -07:00
David Tolnay 4f59cd217a Delete support for compilers without core::time 2023-07-30 21:10:49 -07:00
David Tolnay 27c8b2d66a Delete support for compilers without dynamically sized Rc construction 2023-07-30 20:48:27 -07:00
David Tolnay 89976c2712 Delete support for compilers without PathBuf::into_boxed_path 2023-07-30 20:48:27 -07:00
David Tolnay c91737fef1 Delete support for compilers without CString::into_boxed_c_str 2023-07-30 20:48:27 -07:00
David Tolnay a100719bc6 Delete support for compilers without core::cmp::Reverse 2023-07-30 20:48:27 -07:00
David Tolnay 9a0e149225 Sort version checks in build.rs 2023-07-30 20:48:27 -07:00
David Tolnay 9350927903 Delete support for compilers without std::collections::Bound 2023-07-30 20:48:27 -07:00
David Tolnay 677c13a4ec Merge pull request #2544 from dtolnay/testprecompiled
Add CI job to run test suite against precompiled serde_derive
2023-07-30 18:58:13 -07:00
David Tolnay ee8e1ee7ff Add CI job to run test suite against precompiled serde_derive 2023-07-30 18:50:16 -07:00
David Tolnay f969080b9f Pull in syn fix that makes serde test suite independent of "full" feature
See https://github.com/dtolnay/syn/pull/1491.
2023-07-30 17:39:44 -07:00
David Tolnay c2b16bfbb0 Release 1.0.179 2023-07-30 17:20:10 -07:00
David Tolnay e7df53701c Resolve doc_markdown clippy lint from PR 2448
warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2870:25
         |
    2870 |             /// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
         |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
         = note: `-W clippy::doc-markdown` implied by `-W clippy::pedantic`
    help: try
         |
    2870 |             /// Reaches `crate::private::de::content::VariantDeserializer::tuple_variant`
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2871:17
         |
    2871 |             /// Content::Seq case
         |                 ^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2871 |             /// `Content::Seq` case
         |                 ~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2872:21
         |
    2872 |             /// via FlatMapDeserializer::deserialize_enum
         |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2872 |             /// via `FlatMapDeserializer::deserialize_enum`
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2894:25
         |
    2894 |             /// Reaches crate::private::de::content::VariantDeserializer::struct_variant
         |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2894 |             /// Reaches `crate::private::de::content::VariantDeserializer::struct_variant`
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2895:17
         |
    2895 |             /// Content::Seq case
         |                 ^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2895 |             /// `Content::Seq` case
         |                 ~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2896:21
         |
    2896 |             /// via FlatMapDeserializer::deserialize_enum
         |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2896 |             /// via `FlatMapDeserializer::deserialize_enum`
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2921:25
         |
    2921 |             /// Reaches crate::private::de::content::VariantDeserializer::struct_variant
         |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2921 |             /// Reaches `crate::private::de::content::VariantDeserializer::struct_variant`
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2922:17
         |
    2922 |             /// Content::Map case
         |                 ^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2922 |             /// `Content::Map` case
         |                 ~~~~~~~~~~~~~~

    warning: item in documentation is missing backticks
        --> test_suite/tests/test_annotations.rs:2923:21
         |
    2923 |             /// via FlatMapDeserializer::deserialize_enum
         |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
    help: try
         |
    2923 |             /// via `FlatMapDeserializer::deserialize_enum`
         |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2023-07-30 16:15:29 -07:00
David Tolnay 02c34e490b Resolve redundant_field_names clippy lint from PR 2448
warning: redundant field names in struct initialization
        --> serde/src/private/ser.rs:1278:13
         |
    1278 |             map: map,
         |             ^^^^^^^^ help: replace it with: `map`
         |
         = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
         = note: `-W clippy::redundant-field-names` implied by `-W clippy::all`
2023-07-30 16:07:27 -07:00
David Tolnay 427c839b3d Merge pull request #2448 from Mingun/ser-flatten-enums
Implement serialization of tuple variants of flatten enums
2023-07-30 16:02:37 -07:00
Mingun f709fc05b0 Do not run the code when results are not used 2023-07-23 15:23:39 +05:00
Mingun 089aae1292 Eliminate even more allocations 2023-07-23 15:23:39 +05:00
Mingun 855acaf112 Eliminate additional allocations for flattening aliases 2023-07-23 15:23:38 +05:00
Mingun 7ca7720262 Slightly reduced number of allocations 2023-07-23 15:23:37 +05:00
Mingun 78fea3aa4a Show possible aliases in the expected message
Fixes tests
2023-07-23 15:23:37 +05:00
Mingun 1efb8b6a53 Add tests for aliases
failures (2):
    field_identifier::unknown
    variant_identifier::unknown
2023-07-23 15:23:36 +05:00
Mingun bc1960b106 Add tests for unknown field / variant 2023-07-23 15:23:33 +05:00
Mingun 967023b755 Group field_identifier and variant_identifier tests in sub-modules
(review this commit with "ignore whitespace changes" option on)
2023-07-23 15:21:22 +05:00
Mingun bb51e68f16 Keep aliases sorted 2023-07-23 15:21:21 +05:00
Mingun 4e5e55bf1c Remove custom implementations of SeqDeserializer and MapDeserializer for enums
Those deserializers are used to deserialize tuple or struct variants from Content
which is used by internally tagged enums and by flatten

FlatMapDeserializer is reached in the following tests:
    flatten::enum_::externally_tagged::newtype
    flatten::enum_::externally_tagged::struct_from_map
    flatten::enum_::externally_tagged::struct_from_seq
    flatten::enum_::externally_tagged::tuple

ContentDeserializer is reached in the following tests:
    test_enum_in_internally_tagged_enum
    test_internally_tagged_struct_variant_containing_unit_variant
2023-07-11 22:01:48 +05:00
Mingun 4513a9e6a7 Move test_flatten_enum_newtype into new group of flatten tests - flatten::enum_::externally_tagged::newtype 2023-07-11 22:00:38 +05:00
Mingun 4f922e4e5b Implement serialization of flattened tuple variants of externally tagged enums
The Container struct

  struct Container {
    #[serde(flatten)]
    enum_field: Enum,
  }
  enum Enum {
    Tuple(u32, u32),
  }

now can be serialized to JSON as

  { "enum_field": [1, 2] }

Deserialization already works

Fixes (1):
    flatten::enum_::externally_tagged::tuple
2023-07-11 22:00:10 +05:00
Mingun 993966600e Implement tests for crate::private::de::content::VariantDeserializer
failures (1):
    flatten::enum_::externally_tagged::tuple
2023-07-11 21:59:22 +05:00
Mingun 5b96cf1bde Use traditional order for enum variants (Unit, Newtype, Tuple, Struct) and names for tag and content fields 2023-07-11 21:58:43 +05:00
Mingun f3d50e5209 Use FromIterator to fill HashMap 2023-07-11 21:58:14 +05:00
Mingun ab21d4d017 Merge assert_de_tokens and assert_ser_tokens into assert_tokens 2023-07-11 21:57:49 +05:00
Mingun f7c5d93e6a Pull up types from function into module, unify style 2023-07-11 21:57:22 +05:00
Mingun 52a7d40e6e Rename test types so their names reflects, what's tested 2023-07-11 21:56:53 +05:00
Mingun 348bc6b257 Move flatten enum tests to a dedicated module
(review with "ignore whitespace" option on and editor that shows line moves,
for example, TortoiseGitMerge)
2023-07-11 21:56:22 +05:00
46 changed files with 1533 additions and 1377 deletions
+24 -19
View File
@@ -77,7 +77,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
rust: [1.19.0, 1.20.0, 1.21.0, 1.25.0, 1.26.0, 1.34.0] rust: [1.31.0, 1.34.0]
timeout-minutes: 45 timeout-minutes: 45
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@@ -88,24 +88,6 @@ jobs:
- run: cd serde && cargo build --no-default-features - run: cd serde && cargo build --no-default-features
- run: cd serde && cargo build - 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]
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- 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: derive:
name: Rust 1.56.0 name: Rust 1.56.0
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -127,6 +109,29 @@ jobs:
- uses: dtolnay/rust-toolchain@1.36.0 - uses: dtolnay/rust-toolchain@1.36.0
- run: cd serde && cargo build --no-default-features --features alloc - run: cd serde && cargo build --no-default-features --features alloc
precompiled:
name: Precompiled
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@nightly
with:
components: rust-src
targets: x86_64-unknown-linux-musl
- run: precompiled/build.sh
- name: replace serde_derive dependency with precompiled
run: |
# FIXME: consider using `cargo rm serde_derive` but it's currently broken
# https://github.com/rust-lang/cargo/issues/12419
sed -i '/serde_derive =/d' serde/Cargo.toml
sed -i '/derive = \["serde_derive"\]/d' serde/Cargo.toml
sed -i '/"serde_derive"/d' Cargo.toml
sed -i '/\[workspace\]/d' precompiled/serde_derive/Cargo.toml
cargo add --dev serde_derive --path precompiled/serde_derive --manifest-path test_suite/Cargo.toml
git diff
- run: cd test_suite && cargo test --features unstable -- --skip ui --exact
macos: macos:
name: macOS name: macOS
runs-on: macos-latest runs-on: macos-latest
+3 -3
View File
@@ -1,12 +1,12 @@
# Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.19+]][Rust 1.19] [![serde_derive: rustc 1.56+]][Rust 1.56] # Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde: rustc 1.31+]][Rust 1.31] [![serde_derive: rustc 1.56+]][Rust 1.56]
[Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master [Build Status]: https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master
[actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster [actions]: https://github.com/serde-rs/serde/actions?query=branch%3Amaster
[Latest Version]: https://img.shields.io/crates/v/serde.svg [Latest Version]: https://img.shields.io/crates/v/serde.svg
[crates.io]: https://crates.io/crates/serde [crates.io]: https://crates.io/crates/serde
[serde: rustc 1.19+]: https://img.shields.io/badge/serde-rustc_1.19+-lightgray.svg [serde: rustc 1.31+]: https://img.shields.io/badge/serde-rustc_1.31+-lightgray.svg
[serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg [serde_derive: rustc 1.56+]: https://img.shields.io/badge/serde_derive-rustc_1.56+-lightgray.svg
[Rust 1.19]: https://blog.rust-lang.org/2017/07/20/Rust-1.19.html [Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
[Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html [Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0.html
**Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.**
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.178" version = "1.0.183"
authors = ["David Tolnay <dtolnay@gmail.com>"] authors = ["David Tolnay <dtolnay@gmail.com>"]
publish = false publish = false
@@ -14,4 +14,4 @@ path = "main.rs"
[dependencies] [dependencies]
proc-macro2 = "1" proc-macro2 = "1"
quote = { version = "1", default-features = false } quote = { version = "1", default-features = false }
syn = { version = "2.0.25", default-features = false, features = ["clone-impls", "derive", "full", "parsing", "printing"] } syn = { version = "2.0.28", default-features = false, features = ["clone-impls", "derive", "full", "parsing", "printing"] }
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.178" version = "1.0.183"
authors = ["David Tolnay <dtolnay@gmail.com>"] authors = ["David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std", "no-std::no-alloc"] categories = ["no-std", "no-std::no-alloc"]
description = "Implementation of #[derive(Serialize, Deserialize)]" description = "Implementation of #[derive(Serialize, Deserialize)]"
@@ -24,7 +24,7 @@ proc-macro = true
[target.'cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))'.dependencies] [target.'cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))'.dependencies]
proc-macro2 = "1" proc-macro2 = "1"
quote = "1" quote = "1"
syn = "2.0.25" syn = "2.0.28"
[dev-dependencies] [dev-dependencies]
serde = { version = "1", path = "../../serde" } serde = { version = "1", path = "../../serde" }
+1 -1
View File
@@ -13,7 +13,7 @@
//! //!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html //! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.178")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.183")]
#[cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))] #[cfg(not(all(target_arch = "x86_64", target_os = "linux", target_env = "gnu")))]
include!("lib_from_source.rs"); include!("lib_from_source.rs");
+4 -3
View File
@@ -1,20 +1,21 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.178" # remember to update html_root_url and serde_derive dependency version = "1.0.183" # remember to update html_root_url and serde_derive dependency
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
build = "build.rs" build = "build.rs"
categories = ["encoding", "no-std", "no-std::no-alloc"] categories = ["encoding", "no-std", "no-std::no-alloc"]
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
documentation = "https://docs.rs/serde" documentation = "https://docs.rs/serde"
edition = "2018"
homepage = "https://serde.rs" homepage = "https://serde.rs"
keywords = ["serde", "serialization", "no_std"] keywords = ["serde", "serialization", "no_std"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
readme = "crates-io.md" readme = "crates-io.md"
repository = "https://github.com/serde-rs/serde" repository = "https://github.com/serde-rs/serde"
rust-version = "1.19" rust-version = "1.31"
[dependencies] [dependencies]
serde_derive = { version = "=1.0.178", optional = true, path = "../serde_derive" } serde_derive = { version = "=1.0.183", optional = true, path = "../serde_derive" }
[dev-dependencies] [dev-dependencies]
serde_derive = { version = "1", path = "../serde_derive" } serde_derive = { version = "1", path = "../serde_derive" }
+7 -62
View File
@@ -16,68 +16,6 @@ fn main() {
let target = env::var("TARGET").unwrap(); let target = env::var("TARGET").unwrap();
let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten"; let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";
// std::collections::Bound was stabilized in Rust 1.17
// but it was moved to core::ops later in Rust 1.26:
// https://doc.rust-lang.org/core/ops/enum.Bound.html
if minor < 26 {
println!("cargo:rustc-cfg=no_ops_bound");
if minor < 17 {
println!("cargo:rustc-cfg=no_collections_bound");
}
}
// core::cmp::Reverse stabilized in Rust 1.19:
// https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
if minor < 19 {
println!("cargo:rustc-cfg=no_core_reverse");
}
// 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=no_de_boxed_c_str");
println!("cargo:rustc-cfg=no_de_boxed_path");
}
// From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
// https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
// https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
if minor < 21 {
println!("cargo:rustc-cfg=no_de_rc_dst");
}
// Duration available in core since Rust 1.25:
// https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
if minor < 25 {
println!("cargo:rustc-cfg=no_core_duration");
}
// 128-bit integers stabilized in Rust 1.26:
// https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
//
// Disabled on Emscripten targets before Rust 1.40 since
// Emscripten did not support 128-bit integers until Rust 1.40
// (https://github.com/rust-lang/rust/pull/65251)
if minor < 26 || emscripten && minor < 40 {
println!("cargo:rustc-cfg=no_integer128");
}
// Inclusive ranges methods stabilized in Rust 1.27:
// https://github.com/rust-lang/rust/pull/50758
// Also Iterator::try_for_each:
// https://blog.rust-lang.org/2018/06/21/Rust-1.27.html#library-stabilizations
if minor < 27 {
println!("cargo:rustc-cfg=no_range_inclusive");
println!("cargo:rustc-cfg=no_iterator_try_fold");
}
// Non-zero integers stabilized in Rust 1.28:
// https://blog.rust-lang.org/2018/08/02/Rust-1.28.html#library-stabilizations
if minor < 28 {
println!("cargo:rustc-cfg=no_num_nonzero");
}
// TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add // TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add
// stabilized in Rust 1.34: // 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#tryfrom-and-tryinto
@@ -89,6 +27,13 @@ fn main() {
println!("cargo:rustc-cfg=no_relaxed_trait_bounds"); println!("cargo:rustc-cfg=no_relaxed_trait_bounds");
} }
// Disabled on Emscripten targets before Rust 1.40 since
// Emscripten did not support 128-bit integers until Rust 1.40
// (https://github.com/rust-lang/rust/pull/65251)
if emscripten && minor < 40 {
println!("cargo:rustc-cfg=no_integer128");
}
// Current minimum supported version of serde_derive crate is Rust 1.56. // Current minimum supported version of serde_derive crate is Rust 1.56.
if minor < 56 { if minor < 56 {
println!("cargo:rustc-cfg=no_serde_derive"); println!("cargo:rustc-cfg=no_serde_derive");
+2 -2
View File
@@ -1,5 +1,5 @@
use lib::fmt::{self, Write}; use crate::lib::fmt::{self, Write};
use lib::str; use crate::lib::str;
pub(super) struct Buf<'a> { pub(super) struct Buf<'a> {
bytes: &'a mut [u8], bytes: &'a mut [u8],
+5 -5
View File
@@ -1,6 +1,6 @@
use lib::*; use crate::lib::*;
use de::{ use crate::de::{
Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor, Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor,
}; };
@@ -197,7 +197,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
while let Some(IgnoredAny) = try!(seq.next_element()) { while let Some(IgnoredAny) = tri!(seq.next_element()) {
// Gobble // Gobble
} }
Ok(IgnoredAny) Ok(IgnoredAny)
@@ -208,7 +208,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where where
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
while let Some((IgnoredAny, IgnoredAny)) = try!(map.next_entry()) { while let Some((IgnoredAny, IgnoredAny)) = tri!(map.next_entry()) {
// Gobble // Gobble
} }
Ok(IgnoredAny) Ok(IgnoredAny)
@@ -227,7 +227,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
try!(data.variant::<IgnoredAny>()).1.newtype_variant() tri!(data.variant::<IgnoredAny>()).1.newtype_variant()
} }
} }
+74 -116
View File
@@ -1,16 +1,14 @@
use lib::*; use crate::lib::*;
use de::{ use crate::de::{
Deserialize, Deserializer, EnumAccess, Error, SeqAccess, Unexpected, VariantAccess, Visitor, Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, Unexpected, VariantAccess,
Visitor,
}; };
#[cfg(any(feature = "std", feature = "alloc", not(no_core_duration)))] use crate::seed::InPlaceSeed;
use de::MapAccess;
use seed::InPlaceSeed;
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use __private::size_hint; use crate::de::size_hint;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -84,7 +82,7 @@ macro_rules! impl_deserialize_num {
($primitive:ident, $nonzero:ident $(cfg($($cfg:tt)*))*, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => { ($primitive:ident, $nonzero:ident $(cfg($($cfg:tt)*))*, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => {
impl_deserialize_num!($primitive, $deserialize $($method!($($val : $visit)*);)*); impl_deserialize_num!($primitive, $deserialize $($method!($($val : $visit)*);)*);
#[cfg(all(not(no_num_nonzero), $($($cfg)*)*))] $(#[cfg($($cfg)*)])*
impl<'de> Deserialize<'de> for num::$nonzero { impl<'de> Deserialize<'de> for num::$nonzero {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -684,7 +682,7 @@ impl<'de> Visitor<'de> for CStringVisitor {
let capacity = size_hint::cautious::<u8>(seq.size_hint()); let capacity = size_hint::cautious::<u8>(seq.size_hint());
let mut values = Vec::<u8>::with_capacity(capacity); let mut values = Vec::<u8>::with_capacity(capacity);
while let Some(value) = try!(seq.next_element()) { while let Some(value) = tri!(seq.next_element()) {
values.push(value); values.push(value);
} }
@@ -747,13 +745,9 @@ macro_rules! forwarded_impl {
} }
} }
#[cfg(all( #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))]
any(feature = "std", all(not(no_core_cstr), feature = "alloc")),
not(no_de_boxed_c_str)
))]
forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str); forwarded_impl!((), Box<CStr>, CString::into_boxed_c_str);
#[cfg(not(no_core_reverse))]
forwarded_impl!((T), Reverse<T>, Reverse); forwarded_impl!((T), Reverse<T>, Reverse);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -901,7 +895,7 @@ macro_rules! seq_impl {
{ {
let mut values = $with_capacity; let mut values = $with_capacity;
while let Some(value) = try!($access.next_element()) { while let Some(value) = tri!($access.next_element()) {
$insert(&mut values, value); $insert(&mut values, value);
} }
@@ -939,7 +933,7 @@ macro_rules! seq_impl {
$reserve(&mut self.0, size_hint::cautious::<T>($access.size_hint())); $reserve(&mut self.0, size_hint::cautious::<T>($access.size_hint()));
// FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList) // FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList)
while let Some(value) = try!($access.next_element()) { while let Some(value) = tri!($access.next_element()) {
$insert(&mut self.0, value); $insert(&mut self.0, value);
} }
@@ -1039,7 +1033,7 @@ where
let capacity = size_hint::cautious::<T>(seq.size_hint()); let capacity = size_hint::cautious::<T>(seq.size_hint());
let mut values = Vec::<T>::with_capacity(capacity); let mut values = Vec::<T>::with_capacity(capacity);
while let Some(value) = try!(seq.next_element()) { while let Some(value) = tri!(seq.next_element()) {
values.push(value); values.push(value);
} }
@@ -1081,7 +1075,7 @@ where
for i in 0..self.0.len() { for i in 0..self.0.len() {
let next = { let next = {
let next_place = InPlaceSeed(&mut self.0[i]); let next_place = InPlaceSeed(&mut self.0[i]);
try!(seq.next_element_seed(next_place)) tri!(seq.next_element_seed(next_place))
}; };
if next.is_none() { if next.is_none() {
self.0.truncate(i); self.0.truncate(i);
@@ -1089,7 +1083,7 @@ where
} }
} }
while let Some(value) = try!(seq.next_element()) { while let Some(value) = tri!(seq.next_element()) {
self.0.push(value); self.0.push(value);
} }
@@ -1161,7 +1155,7 @@ macro_rules! array_impls {
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
Ok([$( Ok([$(
match try!(seq.next_element()) { match tri!(seq.next_element()) {
Some(val) => val, Some(val) => val,
None => return Err(Error::invalid_length($n, &self)), None => return Err(Error::invalid_length($n, &self)),
} }
@@ -1186,7 +1180,7 @@ macro_rules! array_impls {
{ {
let mut fail_idx = None; let mut fail_idx = None;
for (idx, dest) in self.0[..].iter_mut().enumerate() { for (idx, dest) in self.0[..].iter_mut().enumerate() {
if try!(seq.next_element_seed(InPlaceSeed(dest))).is_none() { if tri!(seq.next_element_seed(InPlaceSeed(dest))).is_none() {
fail_idx = Some(idx); fail_idx = Some(idx);
break; break;
} }
@@ -1284,7 +1278,7 @@ macro_rules! tuple_impls {
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
$( $(
let $name = match try!(seq.next_element()) { let $name = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => return Err(Error::invalid_length($n, &self)), None => return Err(Error::invalid_length($n, &self)),
}; };
@@ -1318,7 +1312,7 @@ macro_rules! tuple_impls {
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
$( $(
if try!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() { if tri!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() {
return Err(Error::invalid_length($n, &self)); return Err(Error::invalid_length($n, &self));
} }
)+ )+
@@ -1395,7 +1389,7 @@ macro_rules! map_impl {
{ {
let mut values = $with_capacity; let mut values = $with_capacity;
while let Some((key, value)) = try!($access.next_entry()) { while let Some((key, value)) = tri!($access.next_entry()) {
values.insert(key, value); values.insert(key, value);
} }
@@ -1541,7 +1535,7 @@ macro_rules! deserialize_enum {
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
match try!(data.variant()) { match tri!(data.variant()) {
$( $(
($name_kind :: $variant, v) => v.newtype_variant().map($name :: $variant), ($name_kind :: $variant, v) => v.newtype_variant().map($name :: $variant),
)* )*
@@ -1561,7 +1555,7 @@ impl<'de> Deserialize<'de> for net::IpAddr {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
deserializer.deserialize_str(FromStrVisitor::new("IP address")) deserializer.deserialize_str(FromStrVisitor::new("IP address"))
} else { } else {
use lib::net::IpAddr; use crate::lib::net::IpAddr;
deserialize_enum! { deserialize_enum! {
IpAddr IpAddrKind (V4; b"V4"; 0, V6; b"V6"; 1) IpAddr IpAddrKind (V4; b"V4"; 0, V6; b"V6"; 1)
"`V4` or `V6`", "`V4` or `V6`",
@@ -1604,7 +1598,7 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
if deserializer.is_human_readable() { if deserializer.is_human_readable() {
deserializer.deserialize_str(FromStrVisitor::new("socket address")) deserializer.deserialize_str(FromStrVisitor::new("socket address"))
} else { } else {
use lib::net::SocketAddr; use crate::lib::net::SocketAddr;
deserialize_enum! { deserialize_enum! {
SocketAddr SocketAddrKind (V4; b"V4"; 0, V6; b"V6"; 1) SocketAddr SocketAddrKind (V4; b"V4"; 0, V6; b"V6"; 1)
"`V4` or `V6`", "`V4` or `V6`",
@@ -1714,7 +1708,7 @@ impl<'de> Deserialize<'de> for PathBuf {
} }
} }
#[cfg(all(feature = "std", not(no_de_boxed_path)))] #[cfg(feature = "std")]
forwarded_impl!((), Box<Path>, PathBuf::into_boxed_path); forwarded_impl!((), Box<Path>, PathBuf::into_boxed_path);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1748,7 +1742,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
{ {
use std::os::unix::ffi::OsStringExt; use std::os::unix::ffi::OsStringExt;
match try!(data.variant()) { match tri!(data.variant()) {
(OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec), (OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec),
(OsStringKind::Windows, _) => Err(Error::custom( (OsStringKind::Windows, _) => Err(Error::custom(
"cannot deserialize Windows OS string on Unix", "cannot deserialize Windows OS string on Unix",
@@ -1763,7 +1757,7 @@ impl<'de> Visitor<'de> for OsStringVisitor {
{ {
use std::os::windows::ffi::OsStringExt; use std::os::windows::ffi::OsStringExt;
match try!(data.variant()) { match tri!(data.variant()) {
(OsStringKind::Windows, v) => v (OsStringKind::Windows, v) => v
.newtype_variant::<Vec<u16>>() .newtype_variant::<Vec<u16>>()
.map(|vec| OsString::from_wide(&vec)), .map(|vec| OsString::from_wide(&vec)),
@@ -1795,29 +1789,8 @@ forwarded_impl!((T), Box<[T]>, Vec::into_boxed_slice);
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
forwarded_impl!((), Box<str>, String::into_boxed_str); forwarded_impl!((), Box<str>, String::into_boxed_str);
#[cfg(all(no_de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg(all(feature = "std", any(unix, windows)))]
forwarded_impl! { forwarded_impl!((), Box<OsStr>, OsString::into_boxed_os_str);
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Deserializing a data structure containing `Arc` will not attempt to
/// deduplicate `Arc` references to the same data. Every deserialized `Arc`
/// will end up with a strong count of 1.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
(T), Arc<T>, Arc::new
}
#[cfg(all(no_de_rc_dst, feature = "rc", any(feature = "std", feature = "alloc")))]
forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde.
///
/// Deserializing a data structure containing `Rc` will not attempt to
/// deduplicate `Rc` references to the same data. Every deserialized `Rc`
/// will end up with a strong count of 1.
///
/// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc
(T), Rc<T>, Rc::new
}
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>
@@ -1849,7 +1822,7 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
try!(Option::<T>::deserialize(deserializer)); tri!(Option::<T>::deserialize(deserializer));
Ok(RcWeak::new()) Ok(RcWeak::new())
} }
} }
@@ -1867,18 +1840,14 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
try!(Option::<T>::deserialize(deserializer)); tri!(Option::<T>::deserialize(deserializer));
Ok(ArcWeak::new()) Ok(ArcWeak::new())
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(all( #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
macro_rules! box_forwarded_impl { macro_rules! box_forwarded_impl {
( (
$(#[doc = $doc:tt])* $(#[doc = $doc:tt])*
@@ -1899,11 +1868,7 @@ macro_rules! box_forwarded_impl {
}; };
} }
#[cfg(all( #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
box_forwarded_impl! { box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1915,11 +1880,7 @@ box_forwarded_impl! {
Rc Rc
} }
#[cfg(all( #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))]
not(no_de_rc_dst),
feature = "rc",
any(feature = "std", feature = "alloc")
))]
box_forwarded_impl! { box_forwarded_impl! {
/// This impl requires the [`"rc"`] Cargo feature of Serde. /// This impl requires the [`"rc"`] Cargo feature of Serde.
/// ///
@@ -1963,7 +1924,6 @@ forwarded_impl!((T), RwLock<T>, RwLock::new);
// secs: u64, // secs: u64,
// nanos: u32, // nanos: u32,
// } // }
#[cfg(any(feature = "std", not(no_core_duration)))]
impl<'de> Deserialize<'de> for Duration { impl<'de> Deserialize<'de> for Duration {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -2011,7 +1971,7 @@ impl<'de> Deserialize<'de> for Duration {
b"secs" => Ok(Field::Secs), b"secs" => Ok(Field::Secs),
b"nanos" => Ok(Field::Nanos), b"nanos" => Ok(Field::Nanos),
_ => { _ => {
let value = ::__private::from_utf8_lossy(value); let value = crate::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS)) Err(Error::unknown_field(&*value, FIELDS))
} }
} }
@@ -2046,19 +2006,19 @@ impl<'de> Deserialize<'de> for Duration {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
let secs: u64 = match try!(seq.next_element()) { let secs: u64 = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => { None => {
return Err(Error::invalid_length(0, &self)); return Err(Error::invalid_length(0, &self));
} }
}; };
let nanos: u32 = match try!(seq.next_element()) { let nanos: u32 = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => { None => {
return Err(Error::invalid_length(1, &self)); return Err(Error::invalid_length(1, &self));
} }
}; };
try!(check_overflow(secs, nanos)); tri!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
@@ -2068,19 +2028,19 @@ impl<'de> Deserialize<'de> for Duration {
{ {
let mut secs: Option<u64> = None; let mut secs: Option<u64> = None;
let mut nanos: Option<u32> = None; let mut nanos: Option<u32> = None;
while let Some(key) = try!(map.next_key()) { while let Some(key) = tri!(map.next_key()) {
match key { match key {
Field::Secs => { Field::Secs => {
if secs.is_some() { if secs.is_some() {
return Err(<A::Error as Error>::duplicate_field("secs")); return Err(<A::Error as Error>::duplicate_field("secs"));
} }
secs = Some(try!(map.next_value())); secs = Some(tri!(map.next_value()));
} }
Field::Nanos => { Field::Nanos => {
if nanos.is_some() { if nanos.is_some() {
return Err(<A::Error as Error>::duplicate_field("nanos")); return Err(<A::Error as Error>::duplicate_field("nanos"));
} }
nanos = Some(try!(map.next_value())); nanos = Some(tri!(map.next_value()));
} }
} }
} }
@@ -2092,7 +2052,7 @@ impl<'de> Deserialize<'de> for Duration {
Some(nanos) => nanos, Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos")), None => return Err(<A::Error as Error>::missing_field("nanos")),
}; };
try!(check_overflow(secs, nanos)); tri!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
} }
@@ -2184,19 +2144,19 @@ impl<'de> Deserialize<'de> for SystemTime {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
let secs: u64 = match try!(seq.next_element()) { let secs: u64 = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => { None => {
return Err(Error::invalid_length(0, &self)); return Err(Error::invalid_length(0, &self));
} }
}; };
let nanos: u32 = match try!(seq.next_element()) { let nanos: u32 = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => { None => {
return Err(Error::invalid_length(1, &self)); return Err(Error::invalid_length(1, &self));
} }
}; };
try!(check_overflow(secs, nanos)); tri!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
@@ -2206,7 +2166,7 @@ impl<'de> Deserialize<'de> for SystemTime {
{ {
let mut secs: Option<u64> = None; let mut secs: Option<u64> = None;
let mut nanos: Option<u32> = None; let mut nanos: Option<u32> = None;
while let Some(key) = try!(map.next_key()) { while let Some(key) = tri!(map.next_key()) {
match key { match key {
Field::Secs => { Field::Secs => {
if secs.is_some() { if secs.is_some() {
@@ -2214,7 +2174,7 @@ impl<'de> Deserialize<'de> for SystemTime {
"secs_since_epoch", "secs_since_epoch",
)); ));
} }
secs = Some(try!(map.next_value())); secs = Some(tri!(map.next_value()));
} }
Field::Nanos => { Field::Nanos => {
if nanos.is_some() { if nanos.is_some() {
@@ -2222,7 +2182,7 @@ impl<'de> Deserialize<'de> for SystemTime {
"nanos_since_epoch", "nanos_since_epoch",
)); ));
} }
nanos = Some(try!(map.next_value())); nanos = Some(tri!(map.next_value()));
} }
} }
} }
@@ -2234,13 +2194,13 @@ impl<'de> Deserialize<'de> for SystemTime {
Some(nanos) => nanos, Some(nanos) => nanos,
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")), None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
}; };
try!(check_overflow(secs, nanos)); tri!(check_overflow(secs, nanos));
Ok(Duration::new(secs, nanos)) Ok(Duration::new(secs, nanos))
} }
} }
const FIELDS: &[&str] = &["secs_since_epoch", "nanos_since_epoch"]; const FIELDS: &[&str] = &["secs_since_epoch", "nanos_since_epoch"];
let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor)); let duration = tri!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
#[cfg(not(no_systemtime_checked_add))] #[cfg(not(no_systemtime_checked_add))]
let ret = UNIX_EPOCH let ret = UNIX_EPOCH
.checked_add(duration) .checked_add(duration)
@@ -2269,7 +2229,7 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let (start, end) = try!(deserializer.deserialize_struct( let (start, end) = tri!(deserializer.deserialize_struct(
"Range", "Range",
range::FIELDS, range::FIELDS,
range::RangeVisitor { range::RangeVisitor {
@@ -2281,7 +2241,6 @@ where
} }
} }
#[cfg(not(no_range_inclusive))]
impl<'de, Idx> Deserialize<'de> for RangeInclusive<Idx> impl<'de, Idx> Deserialize<'de> for RangeInclusive<Idx>
where where
Idx: Deserialize<'de>, Idx: Deserialize<'de>,
@@ -2290,7 +2249,7 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let (start, end) = try!(deserializer.deserialize_struct( let (start, end) = tri!(deserializer.deserialize_struct(
"RangeInclusive", "RangeInclusive",
range::FIELDS, range::FIELDS,
range::RangeVisitor { range::RangeVisitor {
@@ -2303,9 +2262,9 @@ where
} }
mod range { mod range {
use lib::*; use crate::lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &[&str] = &["start", "end"]; pub const FIELDS: &[&str] = &["start", "end"];
@@ -2351,7 +2310,7 @@ mod range {
b"start" => Ok(Field::Start), b"start" => Ok(Field::Start),
b"end" => Ok(Field::End), b"end" => Ok(Field::End),
_ => { _ => {
let value = ::__private::from_utf8_lossy(value); let value = crate::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS)) Err(Error::unknown_field(&*value, FIELDS))
} }
} }
@@ -2381,13 +2340,13 @@ mod range {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
let start: Idx = match try!(seq.next_element()) { let start: Idx = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => { None => {
return Err(Error::invalid_length(0, &self)); return Err(Error::invalid_length(0, &self));
} }
}; };
let end: Idx = match try!(seq.next_element()) { let end: Idx = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => { None => {
return Err(Error::invalid_length(1, &self)); return Err(Error::invalid_length(1, &self));
@@ -2402,19 +2361,19 @@ mod range {
{ {
let mut start: Option<Idx> = None; let mut start: Option<Idx> = None;
let mut end: Option<Idx> = None; let mut end: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) { while let Some(key) = tri!(map.next_key()) {
match key { match key {
Field::Start => { Field::Start => {
if start.is_some() { if start.is_some() {
return Err(<A::Error as Error>::duplicate_field("start")); return Err(<A::Error as Error>::duplicate_field("start"));
} }
start = Some(try!(map.next_value())); start = Some(tri!(map.next_value()));
} }
Field::End => { Field::End => {
if end.is_some() { if end.is_some() {
return Err(<A::Error as Error>::duplicate_field("end")); return Err(<A::Error as Error>::duplicate_field("end"));
} }
end = Some(try!(map.next_value())); end = Some(tri!(map.next_value()));
} }
} }
} }
@@ -2448,7 +2407,7 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let start = try!(deserializer.deserialize_struct( let start = tri!(deserializer.deserialize_struct(
"RangeFrom", "RangeFrom",
range_from::FIELDS, range_from::FIELDS,
range_from::RangeFromVisitor { range_from::RangeFromVisitor {
@@ -2461,9 +2420,9 @@ where
} }
mod range_from { mod range_from {
use lib::*; use crate::lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &[&str] = &["end"]; pub const FIELDS: &[&str] = &["end"];
@@ -2506,7 +2465,7 @@ mod range_from {
match value { match value {
b"end" => Ok(Field::End), b"end" => Ok(Field::End),
_ => { _ => {
let value = ::__private::from_utf8_lossy(value); let value = crate::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS)) Err(Error::unknown_field(&*value, FIELDS))
} }
} }
@@ -2536,7 +2495,7 @@ mod range_from {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
let end: Idx = match try!(seq.next_element()) { let end: Idx = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => { None => {
return Err(Error::invalid_length(0, &self)); return Err(Error::invalid_length(0, &self));
@@ -2550,13 +2509,13 @@ mod range_from {
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
let mut end: Option<Idx> = None; let mut end: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) { while let Some(key) = tri!(map.next_key()) {
match key { match key {
Field::End => { Field::End => {
if end.is_some() { if end.is_some() {
return Err(<A::Error as Error>::duplicate_field("end")); return Err(<A::Error as Error>::duplicate_field("end"));
} }
end = Some(try!(map.next_value())); end = Some(tri!(map.next_value()));
} }
} }
} }
@@ -2586,7 +2545,7 @@ where
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
let end = try!(deserializer.deserialize_struct( let end = tri!(deserializer.deserialize_struct(
"RangeTo", "RangeTo",
range_to::FIELDS, range_to::FIELDS,
range_to::RangeToVisitor { range_to::RangeToVisitor {
@@ -2599,9 +2558,9 @@ where
} }
mod range_to { mod range_to {
use lib::*; use crate::lib::*;
use de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
pub const FIELDS: &[&str] = &["start"]; pub const FIELDS: &[&str] = &["start"];
@@ -2644,7 +2603,7 @@ mod range_to {
match value { match value {
b"start" => Ok(Field::Start), b"start" => Ok(Field::Start),
_ => { _ => {
let value = ::__private::from_utf8_lossy(value); let value = crate::__private::from_utf8_lossy(value);
Err(Error::unknown_field(&*value, FIELDS)) Err(Error::unknown_field(&*value, FIELDS))
} }
} }
@@ -2674,7 +2633,7 @@ mod range_to {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
let start: Idx = match try!(seq.next_element()) { let start: Idx = match tri!(seq.next_element()) {
Some(value) => value, Some(value) => value,
None => { None => {
return Err(Error::invalid_length(0, &self)); return Err(Error::invalid_length(0, &self));
@@ -2688,13 +2647,13 @@ mod range_to {
A: MapAccess<'de>, A: MapAccess<'de>,
{ {
let mut start: Option<Idx> = None; let mut start: Option<Idx> = None;
while let Some(key) = try!(map.next_key()) { while let Some(key) = tri!(map.next_key()) {
match key { match key {
Field::Start => { Field::Start => {
if start.is_some() { if start.is_some() {
return Err(<A::Error as Error>::duplicate_field("start")); return Err(<A::Error as Error>::duplicate_field("start"));
} }
start = Some(try!(map.next_value())); start = Some(tri!(map.next_value()));
} }
} }
} }
@@ -2709,7 +2668,6 @@ mod range_to {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<'de, T> Deserialize<'de> for Bound<T> impl<'de, T> Deserialize<'de> for Bound<T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
@@ -2801,7 +2759,7 @@ where
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
match try!(data.variant()) { match tri!(data.variant()) {
(Field::Unbounded, v) => v.unit_variant().map(|()| Bound::Unbounded), (Field::Unbounded, v) => v.unit_variant().map(|()| Bound::Unbounded),
(Field::Included, v) => v.newtype_variant().map(Bound::Included), (Field::Included, v) => v.newtype_variant().map(Bound::Included),
(Field::Excluded, v) => v.newtype_variant().map(Bound::Excluded), (Field::Excluded, v) => v.newtype_variant().map(Bound::Excluded),
@@ -2910,7 +2868,7 @@ where
where where
A: EnumAccess<'de>, A: EnumAccess<'de>,
{ {
match try!(data.variant()) { match tri!(data.variant()) {
(Field::Ok, v) => v.newtype_variant().map(Ok), (Field::Ok, v) => v.newtype_variant().map(Ok),
(Field::Err, v) => v.newtype_variant().map(Err), (Field::Err, v) => v.newtype_variant().map(Err),
} }
+14 -13
View File
@@ -112,7 +112,7 @@
//! [derive section of the manual]: https://serde.rs/derive.html //! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats //! [data formats]: https://serde.rs/#data-formats
use lib::*; use crate::lib::*;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -122,19 +122,20 @@ pub mod value;
mod format; mod format;
mod ignored_any; mod ignored_any;
mod impls; mod impls;
pub(crate) mod size_hint;
mod utf8; mod utf8;
pub use self::ignored_any::IgnoredAny; pub use self::ignored_any::IgnoredAny;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use crate::std_error::Error as StdError;
#[cfg(all(feature = "unstable", not(feature = "std")))] #[cfg(all(feature = "unstable", not(feature = "std")))]
#[doc(no_inline)] #[doc(no_inline)]
pub use core::error::Error as StdError; pub use core::error::Error as StdError;
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[doc(no_inline)] #[doc(no_inline)]
pub use std::error::Error as StdError; pub use std::error::Error as StdError;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -569,7 +570,7 @@ pub trait Deserialize<'de>: Sized {
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
// Default implementation just delegates to `deserialize` impl. // Default implementation just delegates to `deserialize` impl.
*place = try!(Deserialize::deserialize(deserializer)); *place = tri!(Deserialize::deserialize(deserializer));
Ok(()) Ok(())
} }
} }
@@ -1229,11 +1230,11 @@ pub trait Deserializer<'de>: Sized {
#[doc(hidden)] #[doc(hidden)]
fn __deserialize_content<V>( fn __deserialize_content<V>(
self, self,
_: ::actually_private::T, _: crate::actually_private::T,
visitor: V, visitor: V,
) -> Result<::private::de::Content<'de>, Self::Error> ) -> Result<crate::__private::de::Content<'de>, Self::Error>
where where
V: Visitor<'de, Value = ::private::de::Content<'de>>, V: Visitor<'de, Value = crate::__private::de::Content<'de>>,
{ {
self.deserialize_any(visitor) self.deserialize_any(visitor)
} }
@@ -1834,9 +1835,9 @@ pub trait MapAccess<'de> {
K: DeserializeSeed<'de>, K: DeserializeSeed<'de>,
V: DeserializeSeed<'de>, V: DeserializeSeed<'de>,
{ {
match try!(self.next_key_seed(kseed)) { match tri!(self.next_key_seed(kseed)) {
Some(key) => { Some(key) => {
let value = try!(self.next_value_seed(vseed)); let value = tri!(self.next_value_seed(vseed));
Ok(Some((key, value))) Ok(Some((key, value)))
} }
None => Ok(None), None => Ok(None),
@@ -2284,12 +2285,12 @@ impl Display for OneOf {
1 => write!(formatter, "`{}`", self.names[0]), 1 => write!(formatter, "`{}`", self.names[0]),
2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]), 2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]),
_ => { _ => {
try!(write!(formatter, "one of ")); tri!(write!(formatter, "one of "));
for (i, alt) in self.names.iter().enumerate() { for (i, alt) in self.names.iter().enumerate() {
if i > 0 { if i > 0 {
try!(write!(formatter, ", ")); tri!(write!(formatter, ", "));
} }
try!(write!(formatter, "`{}`", alt)); tri!(write!(formatter, "`{}`", alt));
} }
Ok(()) Ok(())
} }
+1 -1
View File
@@ -1,4 +1,4 @@
use de::{Deserialize, DeserializeSeed, Deserializer}; use crate::de::{Deserialize, DeserializeSeed, Deserializer};
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors. /// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
/// ///
@@ -1,4 +1,4 @@
use lib::*; use crate::lib::*;
pub fn from_bounds<I>(iter: &I) -> Option<usize> pub fn from_bounds<I>(iter: &I) -> Option<usize>
where where
+1 -1
View File
@@ -1,4 +1,4 @@
use lib::*; use crate::lib::*;
const TAG_CONT: u8 = 0b1000_0000; const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000; const TAG_TWO_B: u8 = 0b1100_0000;
+17 -16
View File
@@ -21,12 +21,11 @@
//! } //! }
//! ``` //! ```
use lib::*; use crate::lib::*;
use self::private::{First, Second}; use self::private::{First, Second};
use __private::size_hint; use crate::de::{self, size_hint, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor};
use de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor}; use crate::ser;
use ser;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -937,8 +936,8 @@ where
where where
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
let v = try!(visitor.visit_seq(&mut self)); let v = tri!(visitor.visit_seq(&mut self));
try!(self.end()); tri!(self.end());
Ok(v) Ok(v)
} }
@@ -1162,8 +1161,8 @@ where
where where
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
let value = try!(visitor.visit_map(&mut self)); let value = tri!(visitor.visit_map(&mut self));
try!(self.end()); tri!(self.end());
Ok(value) Ok(value)
} }
@@ -1171,8 +1170,8 @@ where
where where
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
let value = try!(visitor.visit_seq(&mut self)); let value = tri!(visitor.visit_seq(&mut self));
try!(self.end()); tri!(self.end());
Ok(value) Ok(value)
} }
@@ -1236,8 +1235,8 @@ where
{ {
match self.next_pair() { match self.next_pair() {
Some((key, value)) => { Some((key, value)) => {
let key = try!(kseed.deserialize(key.into_deserializer())); let key = tri!(kseed.deserialize(key.into_deserializer()));
let value = try!(vseed.deserialize(value.into_deserializer())); let value = tri!(vseed.deserialize(value.into_deserializer()));
Ok(Some((key, value))) Ok(Some((key, value)))
} }
None => Ok(None), None => Ok(None),
@@ -1341,7 +1340,7 @@ where
V: de::Visitor<'de>, V: de::Visitor<'de>,
{ {
let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData); let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData);
let pair = try!(visitor.visit_seq(&mut pair_visitor)); let pair = tri!(visitor.visit_seq(&mut pair_visitor));
if pair_visitor.1.is_none() { if pair_visitor.1.is_none() {
Ok(pair) Ok(pair)
} else { } else {
@@ -1501,7 +1500,7 @@ where
where where
T: de::DeserializeSeed<'de>, T: de::DeserializeSeed<'de>,
{ {
match try!(self.map.next_key_seed(seed)) { match tri!(self.map.next_key_seed(seed)) {
Some(key) => Ok((key, private::map_as_enum(self.map))), Some(key) => Ok((key, private::map_as_enum(self.map))),
None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")), None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")),
} }
@@ -1546,9 +1545,11 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
mod private { mod private {
use lib::*; use crate::lib::*;
use de::{self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor}; use crate::de::{
self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor,
};
pub struct UnitOnly<E> { pub struct UnitOnly<E> {
marker: PhantomData<E>, marker: PhantomData<E>,
+50 -72
View File
@@ -93,7 +93,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here. // Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.178")] #![doc(html_root_url = "https://docs.rs/serde/1.0.183")]
// Support using Serde without the standard library! // Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and // Unstable functionality only if the user asks for it. For tracking and
@@ -102,55 +102,51 @@
// https://github.com/serde-rs/serde/issues/812 // https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(error_in_core, never_type))] #![cfg_attr(feature = "unstable", feature(error_in_core, never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)] #![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
// Ignored clippy and clippy_pedantic lints // Ignored clippy and clippy_pedantic lints
#![cfg_attr( #![allow(
feature = "cargo-clippy", // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
allow( clippy::unnested_or_patterns,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768
unnested_or_patterns, clippy::semicolon_if_nothing_returned,
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768 // not available in our oldest supported compiler
semicolon_if_nothing_returned, clippy::empty_enum,
// not available in our oldest supported compiler clippy::type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772
empty_enum, // integer and float ser/de requires these sorts of casts
type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772 clippy::cast_possible_truncation,
// integer and float ser/de requires these sorts of casts clippy::cast_possible_wrap,
cast_possible_truncation, clippy::cast_sign_loss,
cast_possible_wrap, // things are often more readable this way
cast_sign_loss, clippy::cast_lossless,
// things are often more readable this way clippy::module_name_repetitions,
cast_lossless, clippy::option_if_let_else,
module_name_repetitions, clippy::single_match_else,
option_if_let_else, clippy::type_complexity,
single_match_else, clippy::use_self,
type_complexity, clippy::zero_prefixed_literal,
use_self, // correctly used
zero_prefixed_literal, clippy::derive_partial_eq_without_eq,
// correctly used clippy::enum_glob_use,
derive_partial_eq_without_eq, clippy::explicit_auto_deref,
enum_glob_use, clippy::let_underscore_untyped,
explicit_auto_deref, clippy::map_err_ignore,
let_underscore_untyped, clippy::new_without_default,
map_err_ignore, clippy::result_unit_err,
new_without_default, clippy::wildcard_imports,
result_unit_err, // not practical
wildcard_imports, clippy::needless_pass_by_value,
// not practical clippy::similar_names,
needless_pass_by_value, clippy::too_many_lines,
similar_names, // preference
too_many_lines, clippy::doc_markdown,
// preference clippy::unseparated_literal_suffix,
doc_markdown, // false positive
unseparated_literal_suffix, clippy::needless_doctest_main,
// false positive // noisy
needless_doctest_main, clippy::missing_errors_doc,
// noisy clippy::must_use_candidate,
missing_errors_doc,
must_use_candidate,
)
)] )]
// Restrictions // Restrictions
#![cfg_attr(feature = "cargo-clippy", deny(question_mark_used))] #![deny(clippy::question_mark_used)]
// Rustc lints. // Rustc lints.
#![deny(missing_docs, unused_imports)] #![deny(missing_docs, unused_imports)]
@@ -177,14 +173,16 @@ mod lib {
pub use self::core::cell::{Cell, RefCell}; pub use self::core::cell::{Cell, RefCell};
pub use self::core::clone::{self, Clone}; pub use self::core::clone::{self, Clone};
pub use self::core::cmp::Reverse;
pub use self::core::convert::{self, From, Into}; pub use self::core::convert::{self, From, Into};
pub use self::core::default::{self, Default}; pub use self::core::default::{self, Default};
pub use self::core::fmt::{self, Debug, Display}; pub use self::core::fmt::{self, Debug, Display};
pub use self::core::marker::{self, PhantomData}; pub use self::core::marker::{self, PhantomData};
pub use self::core::num::Wrapping; pub use self::core::num::Wrapping;
pub use self::core::ops::{Range, RangeFrom, RangeTo}; pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo};
pub use self::core::option::{self, Option}; pub use self::core::option::{self, Option};
pub use self::core::result::{self, Result}; pub use self::core::result::{self, Result};
pub use self::core::time::Duration;
#[cfg(all(feature = "alloc", not(feature = "std")))] #[cfg(all(feature = "alloc", not(feature = "std")))]
pub use alloc::borrow::{Cow, ToOwned}; pub use alloc::borrow::{Cow, ToOwned};
@@ -222,7 +220,7 @@ mod lib {
pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
#[cfg(all(not(no_core_cstr), not(feature = "std")))] #[cfg(all(not(no_core_cstr), not(feature = "std")))]
pub use core::ffi::CStr; pub use self::core::ffi::CStr;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::ffi::CStr; pub use std::ffi::CStr;
@@ -249,18 +247,6 @@ mod lib {
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use std::time::{SystemTime, UNIX_EPOCH}; pub use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(all(feature = "std", not(no_collections_bound), no_ops_bound))]
pub use std::collections::Bound;
#[cfg(not(no_core_reverse))]
pub use self::core::cmp::Reverse;
#[cfg(not(no_ops_bound))]
pub use self::core::ops::Bound;
#[cfg(not(no_range_inclusive))]
pub use self::core::ops::RangeInclusive;
#[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))] #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))]
pub use std::sync::atomic::{ pub use std::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
@@ -281,16 +267,13 @@ mod lib {
pub use std::sync::atomic::{AtomicI64, AtomicU64}; pub use std::sync::atomic::{AtomicI64, AtomicU64};
#[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))] #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))]
pub use std::sync::atomic::{AtomicIsize, AtomicUsize}; pub use std::sync::atomic::{AtomicIsize, AtomicUsize};
#[cfg(any(feature = "std", not(no_core_duration)))]
pub use self::core::time::Duration;
} }
// None of this crate's error handling needs the `From::from` error conversion // None of this crate's error handling needs the `From::from` error conversion
// performed implicitly by the `?` operator or the standard library's `try!` // performed implicitly by the `?` operator or the standard library's `try!`
// macro. This simplified macro gives a 5.5% improvement in compile time // macro. This simplified macro gives a 5.5% improvement in compile time
// compared to standard `try!`, and 9% improvement compared to `?`. // compared to standard `try!`, and 9% improvement compared to `?`.
macro_rules! try { macro_rules! tri {
($expr:expr) => { ($expr:expr) => {
match $expr { match $expr {
Ok(val) => val, Ok(val) => val,
@@ -311,20 +294,15 @@ pub mod de;
pub mod ser; pub mod ser;
#[doc(inline)] #[doc(inline)]
pub use de::{Deserialize, Deserializer}; pub use crate::de::{Deserialize, Deserializer};
#[doc(inline)] #[doc(inline)]
pub use ser::{Serialize, Serializer}; pub use crate::ser::{Serialize, Serializer};
// Used by generated code and doc tests. Not public API. // Used by generated code and doc tests. Not public API.
#[doc(hidden)] #[doc(hidden)]
#[path = "private/mod.rs"] #[path = "private/mod.rs"]
pub mod __private; pub mod __private;
#[allow(unused_imports)]
use self::__private as export;
#[allow(unused_imports)]
use self::__private as private;
#[path = "de/seed.rs"] #[path = "de/seed.rs"]
mod seed; mod seed;
+101 -185
View File
@@ -1,10 +1,13 @@
use lib::*; use crate::lib::*;
use de::value::{BorrowedBytesDeserializer, BytesDeserializer}; use crate::de::value::{BorrowedBytesDeserializer, BytesDeserializer};
use de::{Deserialize, Deserializer, Error, IntoDeserializer, Visitor}; use crate::de::{
Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, IntoDeserializer, VariantAccess,
Visitor,
};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use de::{DeserializeSeed, MapAccess, Unexpected}; use crate::de::{MapAccess, Unexpected};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub use self::content::{ pub use self::content::{
@@ -13,7 +16,7 @@ pub use self::content::{
TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor, TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor,
}; };
pub use seed::InPlaceSeed; pub use crate::seed::InPlaceSeed;
/// If the missing field is of type `Option<T>` then treat is as `None`, /// If the missing field is of type `Option<T>` then treat is as `None`,
/// otherwise it is an error. /// otherwise it is an error.
@@ -203,13 +206,13 @@ mod content {
// This issue is tracking making some of this stuff public: // This issue is tracking making some of this stuff public:
// https://github.com/serde-rs/serde/issues/741 // https://github.com/serde-rs/serde/issues/741
use lib::*; use crate::lib::*;
use __private::size_hint; use crate::actually_private;
use actually_private; use crate::de::value::{MapDeserializer, SeqDeserializer};
use de::{ use crate::de::{
self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, self, size_hint, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected,
MapAccess, SeqAccess, Unexpected, Visitor, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor,
}; };
/// Used from generated code to buffer the contents of the Deserializer when /// Used from generated code to buffer the contents of the Deserializer when
@@ -299,6 +302,17 @@ mod content {
} }
} }
impl<'de, E> de::IntoDeserializer<'de, E> for Content<'de>
where
E: de::Error,
{
type Deserializer = ContentDeserializer<'de, E>;
fn into_deserializer(self) -> Self::Deserializer {
ContentDeserializer::new(self)
}
}
struct ContentVisitor<'de> { struct ContentVisitor<'de> {
value: PhantomData<Content<'de>>, value: PhantomData<Content<'de>>,
} }
@@ -476,7 +490,7 @@ mod content {
{ {
let mut vec = let mut vec =
Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint())); Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint()));
while let Some(e) = try!(visitor.next_element()) { while let Some(e) = tri!(visitor.next_element()) {
vec.push(e); vec.push(e);
} }
Ok(Content::Seq(vec)) Ok(Content::Seq(vec))
@@ -490,7 +504,7 @@ mod content {
Vec::<(Content, Content)>::with_capacity( Vec::<(Content, Content)>::with_capacity(
size_hint::cautious::<(Content, Content)>(visitor.size_hint()), size_hint::cautious::<(Content, Content)>(visitor.size_hint()),
); );
while let Some(kv) = try!(visitor.next_entry()) { while let Some(kv) = tri!(visitor.next_entry()) {
vec.push(kv); vec.push(kv);
} }
Ok(Content::Map(vec)) Ok(Content::Map(vec))
@@ -833,14 +847,14 @@ mod content {
where where
S: SeqAccess<'de>, S: SeqAccess<'de>,
{ {
let tag = match try!(seq.next_element()) { let tag = match tri!(seq.next_element()) {
Some(tag) => tag, Some(tag) => tag,
None => { None => {
return Err(de::Error::missing_field(self.tag_name)); return Err(de::Error::missing_field(self.tag_name));
} }
}; };
let rest = de::value::SeqAccessDeserializer::new(seq); let rest = de::value::SeqAccessDeserializer::new(seq);
Ok((tag, try!(Content::deserialize(rest)))) Ok((tag, tri!(Content::deserialize(rest))))
} }
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error> fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
@@ -852,16 +866,16 @@ mod content {
Content, Content,
Content, Content,
)>(map.size_hint())); )>(map.size_hint()));
while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
match k { match k {
TagOrContent::Tag => { TagOrContent::Tag => {
if tag.is_some() { if tag.is_some() {
return Err(de::Error::duplicate_field(self.tag_name)); return Err(de::Error::duplicate_field(self.tag_name));
} }
tag = Some(try!(map.next_value())); tag = Some(tri!(map.next_value()));
} }
TagOrContent::Content(k) => { TagOrContent::Content(k) => {
let v = try!(map.next_value()); let v = tri!(map.next_value());
vec.push((k, v)); vec.push((k, v));
} }
} }
@@ -1074,9 +1088,9 @@ mod content {
E: de::Error, E: de::Error,
{ {
let seq = content.into_iter().map(ContentDeserializer::new); let seq = content.into_iter().map(ContentDeserializer::new);
let mut seq_visitor = de::value::SeqDeserializer::new(seq); let mut seq_visitor = SeqDeserializer::new(seq);
let value = try!(visitor.visit_seq(&mut seq_visitor)); let value = tri!(visitor.visit_seq(&mut seq_visitor));
try!(seq_visitor.end()); tri!(seq_visitor.end());
Ok(value) Ok(value)
} }
@@ -1091,9 +1105,9 @@ mod content {
let map = content let map = content
.into_iter() .into_iter()
.map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v))); .map(|(k, v)| (ContentDeserializer::new(k), ContentDeserializer::new(v)));
let mut map_visitor = de::value::MapDeserializer::new(map); let mut map_visitor = MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor)); let value = tri!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end()); tri!(map_visitor.end());
Ok(value) Ok(value)
} }
@@ -1569,7 +1583,7 @@ mod content {
{ {
match self.value { match self.value {
Some(Content::Seq(v)) => { Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
} }
Some(other) => Err(de::Error::invalid_type( Some(other) => Err(de::Error::invalid_type(
other.unexpected(), other.unexpected(),
@@ -1592,10 +1606,10 @@ mod content {
{ {
match self.value { match self.value {
Some(Content::Map(v)) => { Some(Content::Map(v)) => {
de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor) de::Deserializer::deserialize_any(MapDeserializer::new(v.into_iter()), visitor)
} }
Some(Content::Seq(v)) => { Some(Content::Seq(v)) => {
de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) de::Deserializer::deserialize_any(SeqDeserializer::new(v.into_iter()), visitor)
} }
Some(other) => Err(de::Error::invalid_type( Some(other) => Err(de::Error::invalid_type(
other.unexpected(), other.unexpected(),
@@ -1609,156 +1623,6 @@ mod content {
} }
} }
struct SeqDeserializer<'de, E>
where
E: de::Error,
{
iter: <Vec<Content<'de>> as IntoIterator>::IntoIter,
err: PhantomData<E>,
}
impl<'de, E> SeqDeserializer<'de, E>
where
E: de::Error,
{
fn new(vec: Vec<Content<'de>>) -> Self {
SeqDeserializer {
iter: vec.into_iter(),
err: PhantomData,
}
}
}
impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
#[inline]
fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
let len = self.iter.len();
if len == 0 {
visitor.visit_unit()
} else {
let ret = try!(visitor.visit_seq(&mut self));
let remaining = self.iter.len();
if remaining == 0 {
Ok(ret)
} else {
Err(de::Error::invalid_length(len, &"fewer elements in array"))
}
}
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some(value) => seed.deserialize(ContentDeserializer::new(value)).map(Some),
None => Ok(None),
}
}
fn size_hint(&self) -> Option<usize> {
size_hint::from_bounds(&self.iter)
}
}
struct MapDeserializer<'de, E>
where
E: de::Error,
{
iter: <Vec<(Content<'de>, Content<'de>)> as IntoIterator>::IntoIter,
value: Option<Content<'de>>,
err: PhantomData<E>,
}
impl<'de, E> MapDeserializer<'de, E>
where
E: de::Error,
{
fn new(map: Vec<(Content<'de>, Content<'de>)>) -> Self {
MapDeserializer {
iter: map.into_iter(),
value: None,
err: PhantomData,
}
}
}
impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.iter.next() {
Some((key, value)) => {
self.value = Some(value);
seed.deserialize(ContentDeserializer::new(key)).map(Some)
}
None => Ok(None),
}
}
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
where
T: de::DeserializeSeed<'de>,
{
match self.value.take() {
Some(value) => seed.deserialize(ContentDeserializer::new(value)),
None => Err(de::Error::custom("value is missing")),
}
}
fn size_hint(&self) -> Option<usize> {
size_hint::from_bounds(&self.iter)
}
}
impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E>
where
E: de::Error,
{
type Error = E;
#[inline]
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
visitor.visit_map(self)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map struct enum identifier ignored_any
}
}
/// Not public API. /// Not public API.
pub struct ContentRefDeserializer<'a, 'de: 'a, E> { pub struct ContentRefDeserializer<'a, 'de: 'a, E> {
content: &'a Content<'de>, content: &'a Content<'de>,
@@ -1820,9 +1684,9 @@ mod content {
E: de::Error, E: de::Error,
{ {
let seq = content.iter().map(ContentRefDeserializer::new); let seq = content.iter().map(ContentRefDeserializer::new);
let mut seq_visitor = de::value::SeqDeserializer::new(seq); let mut seq_visitor = SeqDeserializer::new(seq);
let value = try!(visitor.visit_seq(&mut seq_visitor)); let value = tri!(visitor.visit_seq(&mut seq_visitor));
try!(seq_visitor.end()); tri!(seq_visitor.end());
Ok(value) Ok(value)
} }
@@ -1840,9 +1704,9 @@ mod content {
ContentRefDeserializer::new(v), ContentRefDeserializer::new(v),
) )
}); });
let mut map_visitor = de::value::MapDeserializer::new(map); let mut map_visitor = MapDeserializer::new(map);
let value = try!(visitor.visit_map(&mut map_visitor)); let value = tri!(visitor.visit_map(&mut map_visitor));
try!(map_visitor.end()); tri!(map_visitor.end());
Ok(value) Ok(value)
} }
@@ -2362,7 +2226,7 @@ mod content {
if len == 0 { if len == 0 {
visitor.visit_unit() visitor.visit_unit()
} else { } else {
let ret = try!(visitor.visit_seq(&mut self)); let ret = tri!(visitor.visit_seq(&mut self));
let remaining = self.iter.len(); let remaining = self.iter.len();
if remaining == 0 { if remaining == 0 {
Ok(ret) Ok(ret)
@@ -2541,7 +2405,7 @@ mod content {
where where
M: MapAccess<'de>, M: MapAccess<'de>,
{ {
while try!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {} while tri!(access.next_entry::<IgnoredAny, IgnoredAny>()).is_some() {}
Ok(()) Ok(())
} }
} }
@@ -2974,3 +2838,55 @@ fn flat_map_take_entry<'de>(
None None
} }
} }
pub struct AdjacentlyTaggedEnumVariantSeed<F> {
pub enum_name: &'static str,
pub variants: &'static [&'static str],
pub fields_enum: PhantomData<F>,
}
pub struct AdjacentlyTaggedEnumVariantVisitor<F> {
enum_name: &'static str,
fields_enum: PhantomData<F>,
}
impl<'de, F> Visitor<'de> for AdjacentlyTaggedEnumVariantVisitor<F>
where
F: Deserialize<'de>,
{
type Value = F;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "variant of enum {}", self.enum_name)
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
let (variant, variant_access) = tri!(data.variant());
tri!(variant_access.unit_variant());
Ok(variant)
}
}
impl<'de, F> DeserializeSeed<'de> for AdjacentlyTaggedEnumVariantSeed<F>
where
F: Deserialize<'de>,
{
type Value = F;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_enum(
self.enum_name,
self.variants,
AdjacentlyTaggedEnumVariantVisitor {
enum_name: self.enum_name,
fields_enum: PhantomData,
},
)
}
}
+2 -2
View File
@@ -1,8 +1,8 @@
// Used only by Serde doc tests. Not public API. // Used only by Serde doc tests. Not public API.
use lib::*; use crate::lib::*;
use ser; use crate::ser;
#[doc(hidden)] #[doc(hidden)]
#[derive(Debug)] #[derive(Debug)]
+11 -13
View File
@@ -3,30 +3,28 @@ pub mod de;
#[cfg(not(no_serde_derive))] #[cfg(not(no_serde_derive))]
pub mod ser; pub mod ser;
pub mod size_hint;
// FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed. // FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed.
pub mod doc; pub mod doc;
pub use lib::clone::Clone; pub use crate::lib::clone::Clone;
pub use lib::convert::{From, Into}; pub use crate::lib::convert::{From, Into};
pub use lib::default::Default; pub use crate::lib::default::Default;
pub use lib::fmt::{self, Formatter}; pub use crate::lib::fmt::{self, Formatter};
pub use lib::marker::PhantomData; pub use crate::lib::marker::PhantomData;
pub use lib::option::Option::{self, None, Some}; pub use crate::lib::option::Option::{self, None, Some};
pub use lib::ptr; pub use crate::lib::ptr;
pub use lib::result::Result::{self, Err, Ok}; pub use crate::lib::result::Result::{self, Err, Ok};
pub use self::string::from_utf8_lossy; pub use self::string::from_utf8_lossy;
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
pub use lib::{ToString, Vec}; pub use crate::lib::{ToString, Vec};
#[cfg(not(no_core_try_from))] #[cfg(not(no_core_try_from))]
pub use lib::convert::TryFrom; pub use crate::lib::convert::TryFrom;
mod string { mod string {
use lib::*; use crate::lib::*;
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> { pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<str> {
+128 -66
View File
@@ -1,6 +1,6 @@
use lib::*; use crate::lib::*;
use ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer}; use crate::ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer};
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
use self::content::{ use self::content::{
@@ -182,14 +182,14 @@ where
} }
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(1))); let mut map = tri!(self.delegate.serialize_map(Some(1)));
try!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(self.tag, self.variant_name));
map.end() map.end()
} }
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> { fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(1))); let mut map = tri!(self.delegate.serialize_map(Some(1)));
try!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(self.tag, self.variant_name));
map.end() map.end()
} }
@@ -199,9 +199,9 @@ where
_: u32, _: u32,
inner_variant: &'static str, inner_variant: &'static str,
) -> Result<Self::Ok, Self::Error> { ) -> Result<Self::Ok, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2))); let mut map = tri!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, &())); tri!(map.serialize_entry(inner_variant, &()));
map.end() map.end()
} }
@@ -226,9 +226,9 @@ where
where where
T: Serialize, T: Serialize,
{ {
let mut map = try!(self.delegate.serialize_map(Some(2))); let mut map = tri!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_entry(inner_variant, inner_value)); tri!(map.serialize_entry(inner_variant, inner_value));
map.end() map.end()
} }
@@ -269,9 +269,9 @@ where
inner_variant: &'static str, inner_variant: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> { ) -> Result<Self::SerializeTupleVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2))); let mut map = tri!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant)); tri!(map.serialize_key(inner_variant));
Ok(SerializeTupleVariantAsMapValue::new( Ok(SerializeTupleVariantAsMapValue::new(
map, map,
inner_variant, inner_variant,
@@ -280,8 +280,8 @@ where
} }
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
let mut map = try!(self.delegate.serialize_map(len.map(|len| len + 1))); let mut map = tri!(self.delegate.serialize_map(len.map(|len| len + 1)));
try!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(self.tag, self.variant_name));
Ok(map) Ok(map)
} }
@@ -290,8 +290,8 @@ where
name: &'static str, name: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeStruct, Self::Error> { ) -> Result<Self::SerializeStruct, Self::Error> {
let mut state = try!(self.delegate.serialize_struct(name, len + 1)); let mut state = tri!(self.delegate.serialize_struct(name, len + 1));
try!(state.serialize_field(self.tag, self.variant_name)); tri!(state.serialize_field(self.tag, self.variant_name));
Ok(state) Ok(state)
} }
@@ -316,9 +316,9 @@ where
inner_variant: &'static str, inner_variant: &'static str,
len: usize, len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> { ) -> Result<Self::SerializeStructVariant, Self::Error> {
let mut map = try!(self.delegate.serialize_map(Some(2))); let mut map = tri!(self.delegate.serialize_map(Some(2)));
try!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(self.tag, self.variant_name));
try!(map.serialize_key(inner_variant)); tri!(map.serialize_key(inner_variant));
Ok(SerializeStructVariantAsMapValue::new( Ok(SerializeStructVariantAsMapValue::new(
map, map,
inner_variant, inner_variant,
@@ -337,9 +337,9 @@ where
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
mod content { mod content {
use lib::*; use crate::lib::*;
use ser::{self, Serialize, Serializer}; use crate::ser::{self, Serialize, Serializer};
pub struct SerializeTupleVariantAsMapValue<M> { pub struct SerializeTupleVariantAsMapValue<M> {
map: M, map: M,
@@ -368,13 +368,13 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new())); let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value); self.fields.push(value);
Ok(()) Ok(())
} }
fn end(mut self) -> Result<M::Ok, M::Error> { fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self tri!(self
.map .map
.serialize_value(&Content::TupleStruct(self.name, self.fields))); .serialize_value(&Content::TupleStruct(self.name, self.fields)));
self.map.end() self.map.end()
@@ -412,13 +412,13 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new())); let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value)); self.fields.push((key, value));
Ok(()) Ok(())
} }
fn end(mut self) -> Result<M::Ok, M::Error> { fn end(mut self) -> Result<M::Ok, M::Error> {
try!(self tri!(self
.map .map
.serialize_value(&Content::Struct(self.name, self.fields))); .serialize_value(&Content::Struct(self.name, self.fields)));
self.map.end() self.map.end()
@@ -499,50 +499,50 @@ mod content {
} }
Content::Seq(ref elements) => elements.serialize(serializer), Content::Seq(ref elements) => elements.serialize(serializer),
Content::Tuple(ref elements) => { Content::Tuple(ref elements) => {
use ser::SerializeTuple; use crate::ser::SerializeTuple;
let mut tuple = try!(serializer.serialize_tuple(elements.len())); let mut tuple = tri!(serializer.serialize_tuple(elements.len()));
for e in elements { for e in elements {
try!(tuple.serialize_element(e)); tri!(tuple.serialize_element(e));
} }
tuple.end() tuple.end()
} }
Content::TupleStruct(n, ref fields) => { Content::TupleStruct(n, ref fields) => {
use ser::SerializeTupleStruct; use crate::ser::SerializeTupleStruct;
let mut ts = try!(serializer.serialize_tuple_struct(n, fields.len())); let mut ts = tri!(serializer.serialize_tuple_struct(n, fields.len()));
for f in fields { for f in fields {
try!(ts.serialize_field(f)); tri!(ts.serialize_field(f));
} }
ts.end() ts.end()
} }
Content::TupleVariant(n, i, v, ref fields) => { Content::TupleVariant(n, i, v, ref fields) => {
use ser::SerializeTupleVariant; use crate::ser::SerializeTupleVariant;
let mut tv = try!(serializer.serialize_tuple_variant(n, i, v, fields.len())); let mut tv = tri!(serializer.serialize_tuple_variant(n, i, v, fields.len()));
for f in fields { for f in fields {
try!(tv.serialize_field(f)); tri!(tv.serialize_field(f));
} }
tv.end() tv.end()
} }
Content::Map(ref entries) => { Content::Map(ref entries) => {
use ser::SerializeMap; use crate::ser::SerializeMap;
let mut map = try!(serializer.serialize_map(Some(entries.len()))); let mut map = tri!(serializer.serialize_map(Some(entries.len())));
for (k, v) in entries { for (k, v) in entries {
try!(map.serialize_entry(k, v)); tri!(map.serialize_entry(k, v));
} }
map.end() map.end()
} }
Content::Struct(n, ref fields) => { Content::Struct(n, ref fields) => {
use ser::SerializeStruct; use crate::ser::SerializeStruct;
let mut s = try!(serializer.serialize_struct(n, fields.len())); let mut s = tri!(serializer.serialize_struct(n, fields.len()));
for &(k, ref v) in fields { for &(k, ref v) in fields {
try!(s.serialize_field(k, v)); tri!(s.serialize_field(k, v));
} }
s.end() s.end()
} }
Content::StructVariant(n, i, v, ref fields) => { Content::StructVariant(n, i, v, ref fields) => {
use ser::SerializeStructVariant; use crate::ser::SerializeStructVariant;
let mut sv = try!(serializer.serialize_struct_variant(n, i, v, fields.len())); let mut sv = tri!(serializer.serialize_struct_variant(n, i, v, fields.len()));
for &(k, ref v) in fields { for &(k, ref v) in fields {
try!(sv.serialize_field(k, v)); tri!(sv.serialize_field(k, v));
} }
sv.end() sv.end()
} }
@@ -639,7 +639,7 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
Ok(Content::Some(Box::new(try!(value.serialize(self))))) Ok(Content::Some(Box::new(tri!(value.serialize(self)))))
} }
fn serialize_unit(self) -> Result<Content, E> { fn serialize_unit(self) -> Result<Content, E> {
@@ -669,7 +669,7 @@ mod content {
{ {
Ok(Content::NewtypeStruct( Ok(Content::NewtypeStruct(
name, name,
Box::new(try!(value.serialize(self))), Box::new(tri!(value.serialize(self))),
)) ))
} }
@@ -687,7 +687,7 @@ mod content {
name, name,
variant_index, variant_index,
variant, variant,
Box::new(try!(value.serialize(self))), Box::new(tri!(value.serialize(self))),
)) ))
} }
@@ -786,7 +786,7 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value); self.elements.push(value);
Ok(()) Ok(())
} }
@@ -812,7 +812,7 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.elements.push(value); self.elements.push(value);
Ok(()) Ok(())
} }
@@ -839,7 +839,7 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value); self.fields.push(value);
Ok(()) Ok(())
} }
@@ -868,7 +868,7 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push(value); self.fields.push(value);
Ok(()) Ok(())
} }
@@ -900,7 +900,7 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let key = try!(key.serialize(ContentSerializer::<E>::new())); let key = tri!(key.serialize(ContentSerializer::<E>::new()));
self.key = Some(key); self.key = Some(key);
Ok(()) Ok(())
} }
@@ -913,7 +913,7 @@ mod content {
.key .key
.take() .take()
.expect("serialize_value called before serialize_key"); .expect("serialize_value called before serialize_key");
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value)); self.entries.push((key, value));
Ok(()) Ok(())
} }
@@ -927,8 +927,8 @@ mod content {
K: Serialize, K: Serialize,
V: Serialize, V: Serialize,
{ {
let key = try!(key.serialize(ContentSerializer::<E>::new())); let key = tri!(key.serialize(ContentSerializer::<E>::new()));
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.entries.push((key, value)); self.entries.push((key, value));
Ok(()) Ok(())
} }
@@ -951,7 +951,7 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value)); self.fields.push((key, value));
Ok(()) Ok(())
} }
@@ -980,7 +980,7 @@ mod content {
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<E>::new())); let value = tri!(value.serialize(ContentSerializer::<E>::new()));
self.fields.push((key, value)); self.fields.push((key, value));
Ok(()) Ok(())
} }
@@ -1025,7 +1025,7 @@ where
type SerializeTupleStruct = Impossible<Self::Ok, M::Error>; type SerializeTupleStruct = Impossible<Self::Ok, M::Error>;
type SerializeMap = FlatMapSerializeMap<'a, M>; type SerializeMap = FlatMapSerializeMap<'a, M>;
type SerializeStruct = FlatMapSerializeStruct<'a, M>; type SerializeStruct = FlatMapSerializeStruct<'a, M>;
type SerializeTupleVariant = Impossible<Self::Ok, M::Error>; type SerializeTupleVariant = FlatMapSerializeTupleVariantAsMapValue<'a, M>;
type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>; type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>;
fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> { fn serialize_bool(self, _: bool) -> Result<Self::Ok, Self::Error> {
@@ -1133,7 +1133,7 @@ where
where where
T: Serialize, T: Serialize,
{ {
try!(self.0.serialize_key(variant)); tri!(self.0.serialize_key(variant));
self.0.serialize_value(value) self.0.serialize_value(value)
} }
@@ -1157,10 +1157,11 @@ where
self, self,
_: &'static str, _: &'static str,
_: u32, _: u32,
_: &'static str, variant: &'static str,
_: usize, _: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> { ) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(Self::bad_type(Unsupported::Enum)) tri!(self.0.serialize_key(variant));
Ok(FlatMapSerializeTupleVariantAsMapValue::new(self.0))
} }
fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -1182,7 +1183,7 @@ where
inner_variant: &'static str, inner_variant: &'static str,
_: usize, _: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> { ) -> Result<Self::SerializeStructVariant, Self::Error> {
try!(self.0.serialize_key(inner_variant)); tri!(self.0.serialize_key(inner_variant));
Ok(FlatMapSerializeStructVariantAsMapValue::new( Ok(FlatMapSerializeStructVariantAsMapValue::new(
self.0, self.0,
inner_variant, inner_variant,
@@ -1259,6 +1260,52 @@ where
} }
} }
////////////////////////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeTupleVariantAsMapValue<'a, M: 'a> {
map: &'a mut M,
fields: Vec<Content>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> FlatMapSerializeTupleVariantAsMapValue<'a, M>
where
M: SerializeMap + 'a,
{
fn new(map: &'a mut M) -> Self {
FlatMapSerializeTupleVariantAsMapValue {
map,
fields: Vec::new(),
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, M> ser::SerializeTupleVariant for FlatMapSerializeTupleVariantAsMapValue<'a, M>
where
M: SerializeMap + 'a,
{
type Ok = ();
type Error = M::Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
where
T: Serialize,
{
let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push(value);
Ok(())
}
fn end(self) -> Result<(), Self::Error> {
tri!(self.map.serialize_value(&Content::Seq(self.fields)));
Ok(())
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> { pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> {
map: &'a mut M, map: &'a mut M,
@@ -1296,15 +1343,30 @@ where
where where
T: Serialize, T: Serialize,
{ {
let value = try!(value.serialize(ContentSerializer::<M::Error>::new())); let value = tri!(value.serialize(ContentSerializer::<M::Error>::new()));
self.fields.push((key, value)); self.fields.push((key, value));
Ok(()) Ok(())
} }
fn end(self) -> Result<(), Self::Error> { fn end(self) -> Result<(), Self::Error> {
try!(self tri!(self
.map .map
.serialize_value(&Content::Struct(self.name, self.fields))); .serialize_value(&Content::Struct(self.name, self.fields)));
Ok(()) Ok(())
} }
} }
pub struct AdjacentlyTaggedEnumVariant {
pub enum_name: &'static str,
pub variant_index: u32,
pub variant_name: &'static str,
}
impl Serialize for AdjacentlyTaggedEnumVariant {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_unit_variant(self.enum_name, self.variant_index, self.variant_name)
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
use lib::*; use crate::lib::*;
use ser::{Error, Impossible, Serialize, Serializer}; use crate::ser::{Error, Impossible, Serialize, Serializer};
impl Error for fmt::Error { impl Error for fmt::Error {
fn custom<T: Display>(_msg: T) -> Self { fn custom<T: Display>(_msg: T) -> Self {
+23 -28
View File
@@ -1,6 +1,6 @@
use lib::*; use crate::lib::*;
use ser::{Error, Serialize, SerializeTuple, Serializer}; use crate::ser::{Error, Serialize, SerializeTuple, Serializer};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -133,7 +133,7 @@ impl<T> Serialize for [T; 0] {
where where
S: Serializer, S: Serializer,
{ {
try!(serializer.serialize_tuple(0)).end() tri!(serializer.serialize_tuple(0)).end()
} }
} }
@@ -149,9 +149,9 @@ macro_rules! array_impls {
where where
S: Serializer, S: Serializer,
{ {
let mut seq = try!(serializer.serialize_tuple($len)); let mut seq = tri!(serializer.serialize_tuple($len));
for e in self { for e in self {
try!(seq.serialize_element(e)); tri!(seq.serialize_element(e));
} }
seq.end() seq.end()
} }
@@ -248,9 +248,9 @@ where
S: Serializer, S: Serializer,
{ {
use super::SerializeStruct; use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Range", 2)); let mut state = tri!(serializer.serialize_struct("Range", 2));
try!(state.serialize_field("start", &self.start)); tri!(state.serialize_field("start", &self.start));
try!(state.serialize_field("end", &self.end)); tri!(state.serialize_field("end", &self.end));
state.end() state.end()
} }
} }
@@ -266,15 +266,14 @@ where
S: Serializer, S: Serializer,
{ {
use super::SerializeStruct; use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeFrom", 1)); let mut state = tri!(serializer.serialize_struct("RangeFrom", 1));
try!(state.serialize_field("start", &self.start)); tri!(state.serialize_field("start", &self.start));
state.end() state.end()
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(not(no_range_inclusive))]
impl<Idx> Serialize for RangeInclusive<Idx> impl<Idx> Serialize for RangeInclusive<Idx>
where where
Idx: Serialize, Idx: Serialize,
@@ -284,9 +283,9 @@ where
S: Serializer, S: Serializer,
{ {
use super::SerializeStruct; use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeInclusive", 2)); let mut state = tri!(serializer.serialize_struct("RangeInclusive", 2));
try!(state.serialize_field("start", &self.start())); tri!(state.serialize_field("start", &self.start()));
try!(state.serialize_field("end", &self.end())); tri!(state.serialize_field("end", &self.end()));
state.end() state.end()
} }
} }
@@ -302,15 +301,14 @@ where
S: Serializer, S: Serializer,
{ {
use super::SerializeStruct; use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("RangeTo", 1)); let mut state = tri!(serializer.serialize_struct("RangeTo", 1));
try!(state.serialize_field("end", &self.end)); tri!(state.serialize_field("end", &self.end));
state.end() state.end()
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(not(no_ops_bound), all(feature = "std", not(no_collections_bound))))]
impl<T> Serialize for Bound<T> impl<T> Serialize for Bound<T>
where where
T: Serialize, T: Serialize,
@@ -367,9 +365,9 @@ macro_rules! tuple_impls {
where where
S: Serializer, S: Serializer,
{ {
let mut tuple = try!(serializer.serialize_tuple($len)); let mut tuple = tri!(serializer.serialize_tuple($len));
$( $(
try!(tuple.serialize_element(&self.$n)); tri!(tuple.serialize_element(&self.$n));
)+ )+
tuple.end() tuple.end()
} }
@@ -538,7 +536,6 @@ where
macro_rules! nonzero_integers { macro_rules! nonzero_integers {
($($T:ident,)+) => { ($($T:ident,)+) => {
$( $(
#[cfg(not(no_num_nonzero))]
impl Serialize for num::$T { impl Serialize for num::$T {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
@@ -662,16 +659,15 @@ where
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[cfg(any(feature = "std", not(no_core_duration)))]
impl Serialize for Duration { impl Serialize for Duration {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
{ {
use super::SerializeStruct; use super::SerializeStruct;
let mut state = try!(serializer.serialize_struct("Duration", 2)); let mut state = tri!(serializer.serialize_struct("Duration", 2));
try!(state.serialize_field("secs", &self.as_secs())); tri!(state.serialize_field("secs", &self.as_secs()));
try!(state.serialize_field("nanos", &self.subsec_nanos())); tri!(state.serialize_field("nanos", &self.subsec_nanos()));
state.end() state.end()
} }
} }
@@ -689,9 +685,9 @@ impl Serialize for SystemTime {
Ok(duration_since_epoch) => duration_since_epoch, Ok(duration_since_epoch) => duration_since_epoch,
Err(_) => return Err(S::Error::custom("SystemTime must be later than UNIX_EPOCH")), Err(_) => return Err(S::Error::custom("SystemTime must be later than UNIX_EPOCH")),
}; };
let mut state = try!(serializer.serialize_struct("SystemTime", 2)); let mut state = tri!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs())); tri!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos())); tri!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
state.end() state.end()
} }
} }
@@ -963,7 +959,6 @@ where
} }
} }
#[cfg(not(no_core_reverse))]
impl<T> Serialize for Reverse<T> impl<T> Serialize for Reverse<T>
where where
T: Serialize, T: Serialize,
+2 -2
View File
@@ -1,8 +1,8 @@
//! This module contains `Impossible` serializer and its implementations. //! This module contains `Impossible` serializer and its implementations.
use lib::*; use crate::lib::*;
use ser::{ use crate::ser::{
self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant,
SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, SerializeTuple, SerializeTupleStruct, SerializeTupleVariant,
}; };
+11 -37
View File
@@ -107,7 +107,7 @@
//! [derive section of the manual]: https://serde.rs/derive.html //! [derive section of the manual]: https://serde.rs/derive.html
//! [data formats]: https://serde.rs/#data-formats //! [data formats]: https://serde.rs/#data-formats
use lib::*; use crate::lib::*;
mod fmt; mod fmt;
mod impls; mod impls;
@@ -115,15 +115,15 @@ mod impossible;
pub use self::impossible::Impossible; pub use self::impossible::Impossible;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use crate::std_error::Error as StdError;
#[cfg(all(feature = "unstable", not(feature = "std")))] #[cfg(all(feature = "unstable", not(feature = "std")))]
#[doc(no_inline)] #[doc(no_inline)]
pub use core::error::Error as StdError; pub use core::error::Error as StdError;
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[doc(no_inline)] #[doc(no_inline)]
pub use std::error::Error as StdError; pub use std::error::Error as StdError;
#[cfg(not(any(feature = "std", feature = "unstable")))]
#[doc(no_inline)]
pub use std_error::Error as StdError;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -1279,22 +1279,9 @@ pub trait Serializer: Sized {
I: IntoIterator, I: IntoIterator,
<I as IntoIterator>::Item: Serialize, <I as IntoIterator>::Item: Serialize,
{ {
let iter = iter.into_iter(); let mut iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter))); let mut serializer = tri!(self.serialize_seq(iterator_len_hint(&iter)));
tri!(iter.try_for_each(|item| serializer.serialize_element(&item)));
#[cfg(not(no_iterator_try_fold))]
{
let mut iter = iter;
try!(iter.try_for_each(|item| serializer.serialize_element(&item)));
}
#[cfg(no_iterator_try_fold)]
{
for item in iter {
try!(serializer.serialize_element(&item));
}
}
serializer.end() serializer.end()
} }
@@ -1330,22 +1317,9 @@ pub trait Serializer: Sized {
V: Serialize, V: Serialize,
I: IntoIterator<Item = (K, V)>, I: IntoIterator<Item = (K, V)>,
{ {
let iter = iter.into_iter(); let mut iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter))); let mut serializer = tri!(self.serialize_map(iterator_len_hint(&iter)));
tri!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
#[cfg(not(no_iterator_try_fold))]
{
let mut iter = iter;
try!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value)));
}
#[cfg(no_iterator_try_fold)]
{
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
}
}
serializer.end() serializer.end()
} }
@@ -1839,7 +1813,7 @@ pub trait SerializeMap {
K: Serialize, K: Serialize,
V: Serialize, V: Serialize,
{ {
try!(self.serialize_key(key)); tri!(self.serialize_key(key));
self.serialize_value(value) self.serialize_value(value)
} }
+1 -1
View File
@@ -1,4 +1,4 @@
use lib::{Debug, Display}; use crate::lib::{Debug, Display};
/// Either a re-export of std::error::Error or a new identical trait, depending /// Either a re-export of std::error::Error or a new identical trait, depending
/// on whether Serde's "std" feature is enabled. /// on whether Serde's "std" feature is enabled.
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.178" # remember to update html_root_url version = "1.0.183" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
categories = ["no-std", "no-std::no-alloc"] categories = ["no-std", "no-std::no-alloc"]
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
@@ -23,7 +23,7 @@ proc-macro = true
[dependencies] [dependencies]
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = "2.0.25" syn = "2.0.28"
[dev-dependencies] [dev-dependencies]
serde = { version = "1", path = "../serde" } serde = { version = "1", path = "../serde" }
+184 -231
View File
@@ -324,10 +324,10 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<St
let code = match &cont.data { let code = match &cont.data {
Data::Struct(Style::Struct, fields) => { Data::Struct(Style::Struct, fields) => {
deserialize_struct_in_place(None, params, fields, &cont.attrs, None)? deserialize_struct_in_place(params, fields, &cont.attrs)?
} }
Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => {
deserialize_tuple_in_place(None, params, fields, &cont.attrs, None) deserialize_tuple_in_place(params, fields, &cont.attrs)
} }
Data::Enum(_) | Data::Struct(Style::Unit, _) => { Data::Enum(_) | Data::Struct(Style::Unit, _) => {
return None; return None;
@@ -582,11 +582,9 @@ fn deserialize_tuple(
#[cfg(feature = "deserialize_in_place")] #[cfg(feature = "deserialize_in_place")]
fn deserialize_tuple_in_place( fn deserialize_tuple_in_place(
variant_ident: Option<syn::Ident>,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
cattrs: &attr::Container, cattrs: &attr::Container,
deserializer: Option<TokenStream>,
) -> Fragment { ) -> Fragment {
assert!(!cattrs.has_flatten()); assert!(!cattrs.has_flatten());
@@ -600,17 +598,25 @@ fn deserialize_tuple_in_place(
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
let is_enum = variant_ident.is_some(); let expecting = format!("tuple struct {}", params.type_name());
let expecting = match variant_ident {
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
None => format!("tuple struct {}", params.type_name()),
};
let expecting = cattrs.expecting().unwrap_or(&expecting); let expecting = cattrs.expecting().unwrap_or(&expecting);
let nfields = fields.len(); let nfields = fields.len();
let visit_newtype_struct = if !is_enum && nfields == 1 { let visit_newtype_struct = if nfields == 1 {
Some(deserialize_newtype_struct_in_place(params, &fields[0])) // We do not generate deserialize_in_place if every field has a
// deserialize_with.
assert!(fields[0].attrs.deserialize_with().is_none());
Some(quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
})
} else { } else {
None None
}; };
@@ -624,15 +630,10 @@ fn deserialize_tuple_in_place(
} }
}; };
let dispatch = if let Some(deserializer) = deserializer { let type_name = cattrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #field_count, #visitor_expr)) let dispatch = if nfields == 1 {
} else if is_enum {
quote!(_serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr))
} else if nfields == 1 {
let type_name = cattrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr))
} else { } else {
let type_name = cattrs.name().deserialize_name();
quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)) quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr))
}; };
@@ -722,19 +723,11 @@ fn deserialize_seq(
}) })
} }
}; };
let value_if_none = match field.attrs.default() { let value_if_none = expr_is_missing_seq(None, index_in_seq, field, cattrs, expecting);
attr::Default::Default => quote!(_serde::__private::Default::default()),
attr::Default::Path(path) => quote!(#path()),
attr::Default::None => quote!(
return _serde::__private::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
),
};
let assign = quote! { let assign = quote! {
let #var = match #visit { let #var = match #visit {
_serde::__private::Some(__value) => __value, _serde::__private::Some(__value) => __value,
_serde::__private::None => { _serde::__private::None => #value_if_none,
#value_if_none
}
}; };
}; };
index_in_seq += 1; index_in_seq += 1;
@@ -810,24 +803,14 @@ fn deserialize_seq_in_place(
self.place.#member = #default; self.place.#member = #default;
} }
} else { } else {
let value_if_none = match field.attrs.default() { let value_if_none = expr_is_missing_seq(Some(quote!(self.place.#member = )), index_in_seq, field, cattrs, expecting);
attr::Default::Default => quote!(
self.place.#member = _serde::__private::Default::default();
),
attr::Default::Path(path) => quote!(
self.place.#member = #path();
),
attr::Default::None => quote!(
return _serde::__private::Err(_serde::de::Error::invalid_length(#index_in_seq, &#expecting));
),
};
let write = match field.attrs.deserialize_with() { let write = match field.attrs.deserialize_with() {
None => { None => {
quote! { quote! {
if let _serde::__private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq, if let _serde::__private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq,
_serde::__private::de::InPlaceSeed(&mut self.place.#member))? _serde::__private::de::InPlaceSeed(&mut self.place.#member))?
{ {
#value_if_none #value_if_none;
} }
} }
} }
@@ -840,7 +823,7 @@ fn deserialize_seq_in_place(
self.place.#member = __wrap.value; self.place.#member = __wrap.value;
} }
_serde::__private::None => { _serde::__private::None => {
#value_if_none #value_if_none;
} }
} }
}) })
@@ -918,25 +901,6 @@ fn deserialize_newtype_struct(
} }
} }
#[cfg(feature = "deserialize_in_place")]
fn deserialize_newtype_struct_in_place(params: &Parameters, field: &Field) -> TokenStream {
// We do not generate deserialize_in_place if every field has a
// deserialize_with.
assert!(field.attrs.deserialize_with().is_none());
let delife = params.borrowed.de_lifetime();
quote! {
#[inline]
fn visit_newtype_struct<__E>(self, __e: __E) -> _serde::__private::Result<Self::Value, __E::Error>
where
__E: _serde::Deserializer<#delife>,
{
_serde::Deserialize::deserialize_in_place(__e, &mut self.place.0)
}
}
}
enum StructForm<'a> { enum StructForm<'a> {
Struct, Struct,
/// Contains a variant name /// Contains a variant name
@@ -1001,12 +965,7 @@ fn deserialize_struct(
) )
}) })
.collect(); .collect();
let field_visitor = Stmts(deserialize_generated_identifier( let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
&field_names_idents,
cattrs,
false,
None,
));
// untagged struct variants do not get a visit_seq method. The same applies to // untagged struct variants do not get a visit_seq method. The same applies to
// structs that only have a map representation. // structs that only have a map representation.
@@ -1058,7 +1017,7 @@ fn deserialize_struct(
} else { } else {
let field_names = field_names_idents let field_names = field_names_idents
.iter() .iter()
.flat_map(|(_, _, aliases)| aliases); .flat_map(|&(_, _, aliases)| aliases);
Some(quote! { Some(quote! {
#[doc(hidden)] #[doc(hidden)]
@@ -1133,14 +1092,10 @@ fn deserialize_struct(
#[cfg(feature = "deserialize_in_place")] #[cfg(feature = "deserialize_in_place")]
fn deserialize_struct_in_place( fn deserialize_struct_in_place(
variant_ident: Option<syn::Ident>,
params: &Parameters, params: &Parameters,
fields: &[Field], fields: &[Field],
cattrs: &attr::Container, cattrs: &attr::Container,
deserializer: Option<TokenStream>,
) -> Option<Fragment> { ) -> Option<Fragment> {
let is_enum = variant_ident.is_some();
// for now we do not support in_place deserialization for structs that // for now we do not support in_place deserialization for structs that
// are represented as map. // are represented as map.
if cattrs.has_flatten() { if cattrs.has_flatten() {
@@ -1152,58 +1107,35 @@ fn deserialize_struct_in_place(
split_with_de_lifetime(params); split_with_de_lifetime(params);
let delife = params.borrowed.de_lifetime(); let delife = params.borrowed.de_lifetime();
let expecting = match variant_ident { let expecting = format!("struct {}", params.type_name());
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
None => format!("struct {}", params.type_name()),
};
let expecting = cattrs.expecting().unwrap_or(&expecting); let expecting = cattrs.expecting().unwrap_or(&expecting);
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let field_names_idents: Vec<_> = fields
.iter()
.enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing())
.map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect();
let (field_visitor, fields_stmt, visit_map) = let field_visitor = deserialize_field_identifier(&field_names_idents, cattrs);
deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs);
let field_visitor = Stmts(field_visitor); let mut_seq = if field_names_idents.is_empty() {
let fields_stmt = Stmts(fields_stmt);
let visit_map = Stmts(visit_map);
let visitor_expr = quote! {
__Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
}
};
let dispatch = if let Some(deserializer) = deserializer {
quote! {
_serde::Deserializer::deserialize_any(#deserializer, #visitor_expr)
}
} else if is_enum {
quote! {
_serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr)
}
} else {
let type_name = cattrs.name().deserialize_name();
quote! {
_serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr)
}
};
let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing());
let visitor_var = if all_skipped {
quote!(_) quote!(_)
} else { } else {
quote!(mut __seq) quote!(mut __seq)
}; };
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting));
let visit_seq = quote! { let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs));
#[inline] let field_names = field_names_idents
fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::__private::Result<Self::Value, __A::Error> .iter()
where .flat_map(|&(_, _, aliases)| aliases);
__A: _serde::de::SeqAccess<#delife>, let type_name = cattrs.name().deserialize_name();
{
#visit_seq
}
};
let in_place_impl_generics = de_impl_generics.in_place(); let in_place_impl_generics = de_impl_generics.in_place();
let in_place_ty_generics = de_ty_generics.in_place(); let in_place_ty_generics = de_ty_generics.in_place();
@@ -1225,7 +1157,13 @@ fn deserialize_struct_in_place(
_serde::__private::Formatter::write_str(__formatter, #expecting) _serde::__private::Formatter::write_str(__formatter, #expecting)
} }
#visit_seq #[inline]
fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::__private::Result<Self::Value, __A::Error>
where
__A: _serde::de::SeqAccess<#delife>,
{
#visit_seq
}
#[inline] #[inline]
fn visit_map<__A>(self, mut __map: __A) -> _serde::__private::Result<Self::Value, __A::Error> fn visit_map<__A>(self, mut __map: __A) -> _serde::__private::Result<Self::Value, __A::Error>
@@ -1236,9 +1174,13 @@ fn deserialize_struct_in_place(
} }
} }
#fields_stmt #[doc(hidden)]
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
#dispatch _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor {
place: __place,
lifetime: _serde::__private::PhantomData,
})
}) })
} }
@@ -1295,7 +1237,12 @@ fn prepare_enum_variant_enum(
}) })
.collect(); .collect();
let other_idx = deserialized_variants.position(|(_, variant)| variant.attrs.other()); let fallthrough = deserialized_variants
.position(|(_, variant)| variant.attrs.other())
.map(|other_idx| {
let ignore_variant = variant_names_idents[other_idx].1.clone();
quote!(_serde::__private::Ok(__Field::#ignore_variant))
});
let variants_stmt = { let variants_stmt = {
let variant_names = variant_names_idents.iter().map(|(name, _, _)| name); let variant_names = variant_names_idents.iter().map(|(name, _, _)| name);
@@ -1309,7 +1256,8 @@ fn prepare_enum_variant_enum(
&variant_names_idents, &variant_names_idents,
cattrs, cattrs,
true, true,
other_idx, None,
fallthrough,
)); ));
(variants_stmt, variant_visitor) (variants_stmt, variant_visitor)
@@ -1490,7 +1438,8 @@ fn deserialize_adjacently_tagged_enum(
}) })
.collect(); .collect();
let expecting = format!("adjacently tagged enum {}", params.type_name()); let rust_name = params.type_name();
let expecting = format!("adjacently tagged enum {}", rust_name);
let expecting = cattrs.expecting().unwrap_or(&expecting); let expecting = cattrs.expecting().unwrap_or(&expecting);
let type_name = cattrs.name().deserialize_name(); let type_name = cattrs.name().deserialize_name();
let deny_unknown_fields = cattrs.deny_unknown_fields(); let deny_unknown_fields = cattrs.deny_unknown_fields();
@@ -1510,6 +1459,14 @@ fn deserialize_adjacently_tagged_enum(
} }
}; };
let variant_seed = quote! {
_serde::__private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> {
enum_name: #rust_name,
variants: VARIANTS,
fields_enum: _serde::__private::PhantomData
}
};
let mut missing_content = quote! { let mut missing_content = quote! {
_serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#content)) _serde::__private::Err(<__A::Error as _serde::de::Error>::missing_field(#content))
}; };
@@ -1557,6 +1514,10 @@ fn deserialize_adjacently_tagged_enum(
_serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)? _serde::de::MapAccess::next_key_seed(&mut __map, #tag_or_content)?
}; };
let variant_from_map = quote! {
_serde::de::MapAccess::next_value_seed(&mut __map, #variant_seed)?
};
// When allowing unknown fields, we want to transparently step through keys // When allowing unknown fields, we want to transparently step through keys
// we don't care about until we find `tag`, `content`, or run out of keys. // we don't care about until we find `tag`, `content`, or run out of keys.
let next_relevant_key = if deny_unknown_fields { let next_relevant_key = if deny_unknown_fields {
@@ -1602,11 +1563,11 @@ fn deserialize_adjacently_tagged_enum(
let finish_content_then_tag = if variant_arms.is_empty() { let finish_content_then_tag = if variant_arms.is_empty() {
quote! { quote! {
match _serde::de::MapAccess::next_value::<__Field>(&mut __map)? {} match #variant_from_map {}
} }
} else { } else {
quote! { quote! {
let __ret = match _serde::de::MapAccess::next_value(&mut __map)? { let __ret = match #variant_from_map {
// Deserialize the buffered content now that we know the variant. // Deserialize the buffered content now that we know the variant.
#(#variant_arms)* #(#variant_arms)*
}?; }?;
@@ -1662,7 +1623,7 @@ fn deserialize_adjacently_tagged_enum(
// First key is the tag. // First key is the tag.
_serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => { _serde::__private::Some(_serde::__private::de::TagOrContentField::Tag) => {
// Parse the tag. // Parse the tag.
let __field = _serde::de::MapAccess::next_value(&mut __map)?; let __field = #variant_from_map;
// Visit the second key. // Visit the second key.
match #next_relevant_key { match #next_relevant_key {
// Second key is a duplicate of the tag. // Second key is a duplicate of the tag.
@@ -2018,30 +1979,15 @@ fn deserialize_untagged_newtype_variant(
} }
fn deserialize_generated_identifier( fn deserialize_generated_identifier(
fields: &[(String, Ident, Vec<String>)], fields: &[(&str, Ident, &BTreeSet<String>)],
cattrs: &attr::Container, cattrs: &attr::Container,
is_variant: bool, is_variant: bool,
other_idx: Option<usize>, ignore_variant: Option<TokenStream>,
fallthrough: Option<TokenStream>,
) -> Fragment { ) -> Fragment {
let this_value = quote!(__Field); let this_value = quote!(__Field);
let field_idents: &Vec<_> = &fields.iter().map(|(_, 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>),);
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
(Some(ignore_variant), Some(fallthrough))
} else if let Some(other_idx) = other_idx {
let ignore_variant = fields[other_idx].1.clone();
let fallthrough = quote!(_serde::__private::Ok(__Field::#ignore_variant));
(None, Some(fallthrough))
} else if is_variant || cattrs.deny_unknown_fields() {
(None, None)
} else {
let ignore_variant = quote!(__ignore,);
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
(Some(ignore_variant), Some(fallthrough))
};
let visitor_impl = Stmts(deserialize_identifier( let visitor_impl = Stmts(deserialize_identifier(
&this_value, &this_value,
fields, fields,
@@ -2087,6 +2033,33 @@ fn deserialize_generated_identifier(
} }
} }
/// Generates enum and its `Deserialize` implementation that represents each
/// non-skipped field of the struct
fn deserialize_field_identifier(
fields: &[(&str, Ident, &BTreeSet<String>)],
cattrs: &attr::Container,
) -> Stmts {
let (ignore_variant, fallthrough) = if cattrs.has_flatten() {
let ignore_variant = quote!(__other(_serde::__private::de::Content<'de>),);
let fallthrough = quote!(_serde::__private::Ok(__Field::__other(__value)));
(Some(ignore_variant), Some(fallthrough))
} else if cattrs.deny_unknown_fields() {
(None, None)
} else {
let ignore_variant = quote!(__ignore,);
let fallthrough = quote!(_serde::__private::Ok(__Field::__ignore));
(Some(ignore_variant), Some(fallthrough))
};
Stmts(deserialize_generated_identifier(
fields,
cattrs,
false,
ignore_variant,
fallthrough,
))
}
// Generates `Deserialize::deserialize` body for an enum with // Generates `Deserialize::deserialize` body for an enum with
// `serde(field_identifier)` or `serde(variant_identifier)` attribute. // `serde(field_identifier)` or `serde(variant_identifier)` attribute.
fn deserialize_custom_identifier( fn deserialize_custom_identifier(
@@ -2148,7 +2121,7 @@ fn deserialize_custom_identifier(
}) })
.collect(); .collect();
let names = names_idents.iter().map(|(name, _, _)| name); let names = names_idents.iter().flat_map(|&(_, _, aliases)| aliases);
let names_const = if fallthrough.is_some() { let names_const = if fallthrough.is_some() {
None None
@@ -2204,32 +2177,24 @@ fn deserialize_custom_identifier(
fn deserialize_identifier( fn deserialize_identifier(
this_value: &TokenStream, this_value: &TokenStream,
fields: &[(String, Ident, Vec<String>)], fields: &[(&str, Ident, &BTreeSet<String>)],
is_variant: bool, is_variant: bool,
fallthrough: Option<TokenStream>, fallthrough: Option<TokenStream>,
fallthrough_borrowed: Option<TokenStream>, fallthrough_borrowed: Option<TokenStream>,
collect_other_fields: bool, collect_other_fields: bool,
expecting: Option<&str>, expecting: Option<&str>,
) -> Fragment { ) -> Fragment {
let mut flat_fields = Vec::new(); let str_mapping = fields.iter().map(|(_, ident, aliases)| {
for (_, ident, aliases) in fields { // `aliases` also contains a main name
flat_fields.extend(aliases.iter().map(|alias| (alias, ident))); quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
} });
let bytes_mapping = fields.iter().map(|(_, ident, aliases)| {
let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect(); // `aliases` also contains a main name
let field_bytes: &Vec<_> = &flat_fields let aliases = aliases
.iter() .iter()
.map(|(name, _)| Literal::byte_string(name.as_bytes())) .map(|alias| Literal::byte_string(alias.as_bytes()));
.collect(); quote!(#(#aliases)|* => _serde::__private::Ok(#this_value::#ident))
});
let constructors: &Vec<_> = &flat_fields
.iter()
.map(|(_, ident)| quote!(#this_value::#ident))
.collect();
let main_constructors: &Vec<_> = &fields
.iter()
.map(|(_, ident, _)| quote!(#this_value::#ident))
.collect();
let expecting = expecting.unwrap_or(if is_variant { let expecting = expecting.unwrap_or(if is_variant {
"variant identifier" "variant identifier"
@@ -2237,8 +2202,6 @@ fn deserialize_identifier(
"field identifier" "field identifier"
}); });
let index_expecting = if is_variant { "variant" } else { "field" };
let bytes_to_str = if fallthrough.is_some() || collect_other_fields { let bytes_to_str = if fallthrough.is_some() || collect_other_fields {
None None
} else { } else {
@@ -2286,21 +2249,6 @@ fn deserialize_identifier(
&fallthrough_arm_tokens &fallthrough_arm_tokens
}; };
let u64_fallthrough_arm_tokens;
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
fallthrough
} else {
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
u64_fallthrough_arm_tokens = quote! {
_serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
};
&u64_fallthrough_arm_tokens
};
let variant_indices = 0_u64..;
let visit_other = if collect_other_fields { let visit_other = if collect_other_fields {
quote! { quote! {
fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result<Self::Value, __E> fn visit_bool<__E>(self, __value: bool) -> _serde::__private::Result<Self::Value, __E>
@@ -2395,15 +2343,33 @@ fn deserialize_identifier(
} }
} }
} else { } else {
let u64_mapping = fields.iter().enumerate().map(|(i, (_, ident, _))| {
let i = i as u64;
quote!(#i => _serde::__private::Ok(#this_value::#ident))
});
let u64_fallthrough_arm_tokens;
let u64_fallthrough_arm = if let Some(fallthrough) = &fallthrough {
fallthrough
} else {
let index_expecting = if is_variant { "variant" } else { "field" };
let fallthrough_msg = format!("{} index 0 <= i < {}", index_expecting, fields.len());
u64_fallthrough_arm_tokens = quote! {
_serde::__private::Err(_serde::de::Error::invalid_value(
_serde::de::Unexpected::Unsigned(__value),
&#fallthrough_msg,
))
};
&u64_fallthrough_arm_tokens
};
quote! { quote! {
fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result<Self::Value, __E> fn visit_u64<__E>(self, __value: u64) -> _serde::__private::Result<Self::Value, __E>
where where
__E: _serde::de::Error, __E: _serde::de::Error,
{ {
match __value { match __value {
#( #(#u64_mapping,)*
#variant_indices => _serde::__private::Ok(#main_constructors),
)*
_ => #u64_fallthrough_arm, _ => #u64_fallthrough_arm,
} }
} }
@@ -2411,6 +2377,8 @@ fn deserialize_identifier(
}; };
let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields { let visit_borrowed = if fallthrough_borrowed.is_some() || collect_other_fields {
let str_mapping = str_mapping.clone();
let bytes_mapping = bytes_mapping.clone();
let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm); let fallthrough_borrowed_arm = fallthrough_borrowed.as_ref().unwrap_or(fallthrough_arm);
Some(quote! { Some(quote! {
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E> fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::__private::Result<Self::Value, __E>
@@ -2418,9 +2386,7 @@ fn deserialize_identifier(
__E: _serde::de::Error, __E: _serde::de::Error,
{ {
match __value { match __value {
#( #(#str_mapping,)*
#field_strs => _serde::__private::Ok(#constructors),
)*
_ => { _ => {
#value_as_borrowed_str_content #value_as_borrowed_str_content
#fallthrough_borrowed_arm #fallthrough_borrowed_arm
@@ -2433,9 +2399,7 @@ fn deserialize_identifier(
__E: _serde::de::Error, __E: _serde::de::Error,
{ {
match __value { match __value {
#( #(#bytes_mapping,)*
#field_bytes => _serde::__private::Ok(#constructors),
)*
_ => { _ => {
#bytes_to_str #bytes_to_str
#value_as_borrowed_bytes_content #value_as_borrowed_bytes_content
@@ -2460,9 +2424,7 @@ fn deserialize_identifier(
__E: _serde::de::Error, __E: _serde::de::Error,
{ {
match __value { match __value {
#( #(#str_mapping,)*
#field_strs => _serde::__private::Ok(#constructors),
)*
_ => { _ => {
#value_as_str_content #value_as_str_content
#fallthrough_arm #fallthrough_arm
@@ -2475,9 +2437,7 @@ fn deserialize_identifier(
__E: _serde::de::Error, __E: _serde::de::Error,
{ {
match __value { match __value {
#( #(#bytes_mapping,)*
#field_bytes => _serde::__private::Ok(#constructors),
)*
_ => { _ => {
#bytes_to_str #bytes_to_str
#value_as_bytes_content #value_as_bytes_content
@@ -2707,42 +2667,6 @@ fn deserialize_map(
} }
} }
#[cfg(feature = "deserialize_in_place")]
fn deserialize_struct_as_struct_in_place_visitor(
params: &Parameters,
fields: &[Field],
cattrs: &attr::Container,
) -> (Fragment, Fragment, Fragment) {
assert!(!cattrs.has_flatten());
let field_names_idents: Vec<_> = fields
.iter()
.enumerate()
.filter(|&(_, field)| !field.attrs.skip_deserializing())
.map(|(i, field)| {
(
field.attrs.name().deserialize_name(),
field_i(i),
field.attrs.aliases(),
)
})
.collect();
let fields_stmt = {
let field_names = field_names_idents.iter().map(|(name, _, _)| name);
quote_block! {
#[doc(hidden)]
const FIELDS: &'static [&'static str] = &[ #(#field_names),* ];
}
};
let field_visitor = deserialize_generated_identifier(&field_names_idents, cattrs, false, None);
let visit_map = deserialize_map_in_place(params, fields, cattrs);
(field_visitor, fields_stmt, visit_map)
}
#[cfg(feature = "deserialize_in_place")] #[cfg(feature = "deserialize_in_place")]
fn deserialize_map_in_place( fn deserialize_map_in_place(
params: &Parameters, params: &Parameters,
@@ -3046,6 +2970,35 @@ fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment {
} }
} }
fn expr_is_missing_seq(
assign_to: Option<TokenStream>,
index: usize,
field: &Field,
cattrs: &attr::Container,
expecting: &str,
) -> TokenStream {
match field.attrs.default() {
attr::Default::Default => {
let span = field.original.span();
return quote_spanned!(span=> #assign_to _serde::__private::Default::default());
}
attr::Default::Path(path) => {
return quote_spanned!(path.span()=> #assign_to #path());
}
attr::Default::None => { /* below */ }
}
match *cattrs.default() {
attr::Default::Default | attr::Default::Path(_) => {
let member = &field.member;
quote!(#assign_to __default.#member)
}
attr::Default::None => quote!(
return _serde::__private::Err(_serde::de::Error::invalid_length(#index, &#expecting))
),
}
}
fn effective_style(variant: &Variant) -> Style { fn effective_style(variant: &Variant) -> Style {
match variant.style { match variant.style {
Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit, Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit,
+31 -34
View File
@@ -134,7 +134,7 @@ pub struct Name {
serialize_renamed: bool, serialize_renamed: bool,
deserialize: String, deserialize: String,
deserialize_renamed: bool, deserialize_renamed: bool,
deserialize_aliases: Vec<String>, deserialize_aliases: BTreeSet<String>,
} }
fn unraw(ident: &Ident) -> String { fn unraw(ident: &Ident) -> String {
@@ -148,16 +148,12 @@ impl Name {
de_name: Attr<String>, de_name: Attr<String>,
de_aliases: Option<VecAttr<String>>, de_aliases: Option<VecAttr<String>>,
) -> Name { ) -> Name {
let deserialize_aliases = match de_aliases { let mut alias_set = BTreeSet::new();
Some(de_aliases) => { if let Some(de_aliases) = de_aliases {
let mut alias_list = BTreeSet::new(); for alias_name in de_aliases.get() {
for alias_name in de_aliases.get() { alias_set.insert(alias_name);
alias_list.insert(alias_name);
}
alias_list.into_iter().collect()
} }
None => Vec::new(), }
};
let ser_name = ser_name.get(); let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some(); let ser_renamed = ser_name.is_some();
@@ -168,27 +164,22 @@ impl Name {
serialize_renamed: ser_renamed, serialize_renamed: ser_renamed,
deserialize: de_name.unwrap_or(source_name), deserialize: de_name.unwrap_or(source_name),
deserialize_renamed: de_renamed, deserialize_renamed: de_renamed,
deserialize_aliases, deserialize_aliases: alias_set,
} }
} }
/// Return the container name for the container when serializing. /// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> String { pub fn serialize_name(&self) -> &str {
self.serialize.clone() &self.serialize
} }
/// Return the container name for the container when deserializing. /// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> String { pub fn deserialize_name(&self) -> &str {
self.deserialize.clone() &self.deserialize
} }
fn deserialize_aliases(&self) -> Vec<String> { fn deserialize_aliases(&self) -> &BTreeSet<String> {
let mut aliases = self.deserialize_aliases.clone(); &self.deserialize_aliases
let main_name = self.deserialize_name();
if !aliases.contains(&main_name) {
aliases.push(main_name);
}
aliases
} }
} }
@@ -405,20 +396,20 @@ impl Container {
if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? {
match &item.data { match &item.data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
syn::Fields::Named(_) => { syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
default.set(&meta.path, Default::Path(path)); default.set(&meta.path, Default::Path(path));
} }
syn::Fields::Unnamed(_) | syn::Fields::Unit => { syn::Fields::Unit => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields"; let msg = "#[serde(default = \"...\")] can only be used on structs that have fields";
cx.syn_error(meta.error(msg)); cx.syn_error(meta.error(msg));
} }
}, },
syn::Data::Enum(_) => { syn::Data::Enum(_) => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields"; let msg = "#[serde(default = \"...\")] can only be used on structs";
cx.syn_error(meta.error(msg)); cx.syn_error(meta.error(msg));
} }
syn::Data::Union(_) => { syn::Data::Union(_) => {
let msg = "#[serde(default = \"...\")] can only be used on structs with named fields"; let msg = "#[serde(default = \"...\")] can only be used on structs";
cx.syn_error(meta.error(msg)); cx.syn_error(meta.error(msg));
} }
} }
@@ -427,20 +418,20 @@ impl Container {
// #[serde(default)] // #[serde(default)]
match &item.data { match &item.data {
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
syn::Fields::Named(_) => { syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
default.set(meta.path, Default::Default); default.set(meta.path, Default::Default);
} }
syn::Fields::Unnamed(_) | syn::Fields::Unit => { syn::Fields::Unit => {
let msg = "#[serde(default)] can only be used on structs with named fields"; let msg = "#[serde(default)] can only be used on structs that have fields";
cx.error_spanned_by(fields, msg); cx.error_spanned_by(fields, msg);
} }
}, },
syn::Data::Enum(_) => { syn::Data::Enum(_) => {
let msg = "#[serde(default)] can only be used on structs with named fields"; let msg = "#[serde(default)] can only be used on structs";
cx.syn_error(meta.error(msg)); cx.syn_error(meta.error(msg));
} }
syn::Data::Union(_) => { syn::Data::Union(_) => {
let msg = "#[serde(default)] can only be used on structs with named fields"; let msg = "#[serde(default)] can only be used on structs";
cx.syn_error(meta.error(msg)); cx.syn_error(meta.error(msg));
} }
} }
@@ -977,7 +968,7 @@ impl Variant {
&self.name &self.name
} }
pub fn aliases(&self) -> Vec<String> { pub fn aliases(&self) -> &BTreeSet<String> {
self.name.deserialize_aliases() self.name.deserialize_aliases()
} }
@@ -988,6 +979,9 @@ impl Variant {
if !self.name.deserialize_renamed { if !self.name.deserialize_renamed {
self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize); self.name.deserialize = rules.deserialize.apply_to_variant(&self.name.deserialize);
} }
self.name
.deserialize_aliases
.insert(self.name.deserialize.clone());
} }
pub fn rename_all_rules(&self) -> RenameAllRules { pub fn rename_all_rules(&self) -> RenameAllRules {
@@ -1316,7 +1310,7 @@ impl Field {
&self.name &self.name
} }
pub fn aliases(&self) -> Vec<String> { pub fn aliases(&self) -> &BTreeSet<String> {
self.name.deserialize_aliases() self.name.deserialize_aliases()
} }
@@ -1327,6 +1321,9 @@ impl Field {
if !self.name.deserialize_renamed { if !self.name.deserialize_renamed {
self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize); self.name.deserialize = rules.deserialize.apply_to_field(&self.name.deserialize);
} }
self.name
.deserialize_aliases
.insert(self.name.deserialize.clone());
} }
pub fn skip_serializing(&self) -> bool { pub fn skip_serializing(&self) -> bool {
+35 -1
View File
@@ -1,11 +1,12 @@
use crate::internals::ast::{Container, Data, Field, Style}; use crate::internals::ast::{Container, Data, Field, Style};
use crate::internals::attr::{Identifier, TagType}; use crate::internals::attr::{Default, Identifier, TagType};
use crate::internals::{ungroup, Ctxt, Derive}; use crate::internals::{ungroup, Ctxt, Derive};
use syn::{Member, Type}; use syn::{Member, Type};
// Cross-cutting checks that require looking at more than a single attrs object. // Cross-cutting checks that require looking at more than a single attrs object.
// Simpler checks should happen when parsing and building the attrs. // Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) { pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_default_on_tuple(cx, cont);
check_remote_generic(cx, cont); check_remote_generic(cx, cont);
check_getter(cx, cont); check_getter(cx, cont);
check_flatten(cx, cont); check_flatten(cx, cont);
@@ -17,6 +18,39 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
check_from_and_try_from(cx, cont); check_from_and_try_from(cx, cont);
} }
// If some field of a tuple struct is marked #[serde(default)] then all fields
// after it must also be marked with that attribute, or the struct must have a
// container-level serde(default) attribute. A field's default value is only
// used for tuple fields if the sequence is exhausted at that point; that means
// all subsequent fields will fail to deserialize if they don't have their own
// default.
fn check_default_on_tuple(cx: &Ctxt, cont: &Container) {
if let Default::None = cont.attrs.default() {
if let Data::Struct(Style::Tuple, fields) = &cont.data {
let mut first_default_index = None;
for (i, field) in fields.iter().enumerate() {
// Skipped fields automatically get the #[serde(default)]
// attribute. We are interested only on non-skipped fields here.
if field.attrs.skip_deserializing() {
continue;
}
if let Default::None = field.attrs.default() {
if let Some(first) = first_default_index {
cx.error_spanned_by(
field.ty,
format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first),
);
}
continue;
}
if first_default_index.is_none() {
first_default_index = Some(i);
}
}
}
}
}
// Remote derive definition type must have either all of the generics of the // Remote derive definition type must have either all of the generics of the
// remote type: // remote type:
// //
+1 -1
View File
@@ -13,7 +13,7 @@
//! //!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html //! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.178")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.183")]
// Ignored clippy lints // Ignored clippy lints
#![allow( #![allow(
// clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054
+28 -13
View File
@@ -478,7 +478,14 @@ fn serialize_variant(
serialize_internally_tagged_variant(params, variant, cattrs, tag) serialize_internally_tagged_variant(params, variant, cattrs, tag)
} }
(attr::TagType::Adjacent { tag, content }, false) => { (attr::TagType::Adjacent { tag, content }, false) => {
serialize_adjacently_tagged_variant(params, variant, cattrs, tag, content) serialize_adjacently_tagged_variant(
params,
variant,
cattrs,
variant_index,
tag,
content,
)
} }
(attr::TagType::None, _) | (_, true) => { (attr::TagType::None, _) | (_, true) => {
serialize_untagged_variant(params, variant, cattrs) serialize_untagged_variant(params, variant, cattrs)
@@ -559,7 +566,7 @@ fn serialize_externally_tagged_variant(
}, },
params, params,
&variant.fields, &variant.fields,
&type_name, type_name,
), ),
} }
} }
@@ -624,7 +631,7 @@ fn serialize_internally_tagged_variant(
StructVariant::InternallyTagged { tag, variant_name }, StructVariant::InternallyTagged { tag, variant_name },
params, params,
&variant.fields, &variant.fields,
&type_name, type_name,
), ),
Style::Tuple => unreachable!("checked in serde_derive_internals"), Style::Tuple => unreachable!("checked in serde_derive_internals"),
} }
@@ -634,12 +641,20 @@ fn serialize_adjacently_tagged_variant(
params: &Parameters, params: &Parameters,
variant: &Variant, variant: &Variant,
cattrs: &attr::Container, cattrs: &attr::Container,
variant_index: u32,
tag: &str, tag: &str,
content: &str, content: &str,
) -> Fragment { ) -> Fragment {
let this_type = &params.this_type; let this_type = &params.this_type;
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
let variant_name = variant.attrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name();
let serialize_variant = quote! {
&_serde::__private::ser::AdjacentlyTaggedEnumVariant {
enum_name: #type_name,
variant_index: #variant_index,
variant_name: #variant_name,
}
};
let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() { let inner = Stmts(if let Some(path) = variant.attrs.serialize_with() {
let ser = wrap_serialize_variant_with(params, path, variant); let ser = wrap_serialize_variant_with(params, path, variant);
@@ -653,7 +668,7 @@ fn serialize_adjacently_tagged_variant(
let mut __struct = _serde::Serializer::serialize_struct( let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 1)?; __serializer, #type_name, 1)?;
_serde::ser::SerializeStruct::serialize_field( _serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name)?; &mut __struct, #tag, #serialize_variant)?;
_serde::ser::SerializeStruct::end(__struct) _serde::ser::SerializeStruct::end(__struct)
}; };
} }
@@ -670,7 +685,7 @@ fn serialize_adjacently_tagged_variant(
let mut __struct = _serde::Serializer::serialize_struct( let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 2)?; __serializer, #type_name, 2)?;
_serde::ser::SerializeStruct::serialize_field( _serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name)?; &mut __struct, #tag, #serialize_variant)?;
#func( #func(
&mut __struct, #content, #field_expr)?; &mut __struct, #content, #field_expr)?;
_serde::ser::SerializeStruct::end(__struct) _serde::ser::SerializeStruct::end(__struct)
@@ -683,7 +698,7 @@ fn serialize_adjacently_tagged_variant(
StructVariant::Untagged, StructVariant::Untagged,
params, params,
&variant.fields, &variant.fields,
&variant_name, variant_name,
), ),
} }
}); });
@@ -735,7 +750,7 @@ fn serialize_adjacently_tagged_variant(
let mut __struct = _serde::Serializer::serialize_struct( let mut __struct = _serde::Serializer::serialize_struct(
__serializer, #type_name, 2)?; __serializer, #type_name, 2)?;
_serde::ser::SerializeStruct::serialize_field( _serde::ser::SerializeStruct::serialize_field(
&mut __struct, #tag, #variant_name)?; &mut __struct, #tag, #serialize_variant)?;
_serde::ser::SerializeStruct::serialize_field( _serde::ser::SerializeStruct::serialize_field(
&mut __struct, #content, &__AdjacentlyTagged { &mut __struct, #content, &__AdjacentlyTagged {
data: (#(#fields_ident,)*), data: (#(#fields_ident,)*),
@@ -779,16 +794,16 @@ fn serialize_untagged_variant(
Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields), Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields),
Style::Struct => { Style::Struct => {
let type_name = cattrs.name().serialize_name(); let type_name = cattrs.name().serialize_name();
serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, &type_name) serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name)
} }
} }
} }
enum TupleVariant { enum TupleVariant<'a> {
ExternallyTagged { ExternallyTagged {
type_name: String, type_name: &'a str,
variant_index: u32, variant_index: u32,
variant_name: String, variant_name: &'a str,
}, },
Untagged, Untagged,
} }
@@ -855,11 +870,11 @@ fn serialize_tuple_variant(
enum StructVariant<'a> { enum StructVariant<'a> {
ExternallyTagged { ExternallyTagged {
variant_index: u32, variant_index: u32,
variant_name: String, variant_name: &'a str,
}, },
InternallyTagged { InternallyTagged {
tag: &'a str, tag: &'a str,
variant_name: String, variant_name: &'a str,
}, },
Untagged, Untagged,
} }
+1 -1
View File
@@ -17,7 +17,7 @@ path = "lib.rs"
[dependencies] [dependencies]
proc-macro2 = "1.0" proc-macro2 = "1.0"
quote = "1.0" quote = "1.0"
syn = { version = "2.0.25", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] } syn = { version = "2.0.28", default-features = false, features = ["clone-impls", "derive", "parsing", "printing"] }
[package.metadata.docs.rs] [package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"] targets = ["x86_64-unknown-linux-gnu"]
+1
View File
@@ -1,3 +1,4 @@
#![allow(internal_features)]
#![feature(lang_items, start)] #![feature(lang_items, start)]
#![no_std] #![no_std]
+357 -336
View File
@@ -114,42 +114,6 @@ struct CollectOther {
extra: HashMap<String, u32>, extra: HashMap<String, u32>,
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructEnumWrapper {
#[serde(flatten)]
data: FlattenStructEnum,
#[serde(flatten)]
extra: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum FlattenStructEnum {
InsertInteger { index: u32, value: u32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumWrapper {
outer: u32,
#[serde(flatten)]
data: FlattenStructTagContentEnumNewtype,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumNewtype(pub FlattenStructTagContentEnum);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
enum FlattenStructTagContentEnum {
InsertInteger { index: u32, value: u32 },
NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant),
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumNewtypeVariant {
value: u32,
}
#[test] #[test]
fn test_default_struct() { fn test_default_struct() {
assert_de_tokens( assert_de_tokens(
@@ -641,7 +605,7 @@ fn test_unknown_field_rename_struct() {
Token::Str("a4"), Token::Str("a4"),
Token::I32(3), Token::I32(3),
], ],
"unknown field `a4`, expected one of `a1`, `a3`, `a2`, `a5`, `a6`", "unknown field `a4`, expected one of `a1`, `a2`, `a3`, `a5`, `a6`",
); );
} }
@@ -835,7 +799,7 @@ fn test_unknown_field_rename_enum() {
Token::Str("d"), Token::Str("d"),
Token::I8(2), Token::I8(2),
], ],
"unknown field `d`, expected one of `a`, `c`, `b`, `e`, `f`", "unknown field `d`, expected one of `a`, `b`, `c`, `e`, `f`",
); );
} }
@@ -1643,149 +1607,6 @@ fn test_collect_other() {
); );
} }
#[test]
fn test_flatten_struct_enum() {
let mut extra = HashMap::new();
extra.insert("extra_key".into(), "extra value".into());
let change_request = FlattenStructEnumWrapper {
data: FlattenStructEnum::InsertInteger {
index: 0,
value: 42,
},
extra,
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("insert_integer"),
Token::Map { len: None },
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::MapEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("insert_integer"),
Token::Struct {
len: 2,
name: "insert_integer",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_struct_tag_content_enum() {
let change_request = FlattenStructTagContentEnumWrapper {
outer: 42,
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::InsertInteger {
index: 0,
value: 42,
}),
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("insert_integer"),
Token::Str("value"),
Token::Map { len: None },
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::MapEnd,
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("insert_integer"),
Token::Str("value"),
Token::Struct {
len: 2,
name: "insert_integer",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_struct_tag_content_enum_newtype() {
let change_request = FlattenStructTagContentEnumWrapper {
outer: 42,
data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::NewtypeVariant(
FlattenStructTagContentEnumNewtypeVariant { value: 23 },
)),
};
assert_de_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("newtype_variant"),
Token::Str("value"),
Token::Map { len: None },
Token::Str("value"),
Token::U32(23),
Token::MapEnd,
Token::MapEnd,
],
);
assert_ser_tokens(
&change_request,
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("type"),
Token::Str("newtype_variant"),
Token::Str("value"),
Token::Struct {
len: 1,
name: "FlattenStructTagContentEnumNewtypeVariant",
},
Token::Str("value"),
Token::U32(23),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test] #[test]
fn test_unknown_field_in_flatten() { fn test_unknown_field_in_flatten() {
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]
@@ -2142,86 +1963,6 @@ fn test_lifetime_propagation_for_flatten() {
); );
} }
#[test]
fn test_flatten_enum_newtype() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
flat: E,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum E {
Q(HashMap<String, String>),
}
let e = E::Q({
let mut map = HashMap::new();
map.insert("k".to_owned(), "v".to_owned());
map
});
let s = S { flat: e };
assert_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("Q"),
Token::Map { len: Some(1) },
Token::Str("k"),
Token::Str("v"),
Token::MapEnd,
Token::MapEnd,
],
);
}
#[test]
fn test_flatten_internally_tagged() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeX")]
enum X {
A { a: i32 },
B { b: i32 },
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(tag = "typeY")]
enum Y {
C { c: i32 },
D { d: i32 },
}
let s = S {
x: X::B { b: 1 },
y: Y::D { d: 2 },
};
assert_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("B"),
Token::Str("b"),
Token::I32(1),
Token::Str("typeY"),
Token::Str("D"),
Token::Str("d"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test] #[test]
fn test_externally_tagged_enum_containing_flatten() { fn test_externally_tagged_enum_containing_flatten() {
#[derive(Serialize, Deserialize, PartialEq, Debug)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -2367,7 +2108,10 @@ fn test_adjacently_tagged_enum_bytes() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("A"), Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Str("c"), Token::Str("c"),
Token::Struct { name: "A", len: 1 }, Token::Struct { name: "A", len: 1 },
Token::Str("a"), Token::Str("a"),
@@ -2385,7 +2129,10 @@ fn test_adjacently_tagged_enum_bytes() {
len: 2, len: 2,
}, },
Token::Bytes(b"t"), Token::Bytes(b"t"),
Token::Str("A"), Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Bytes(b"c"), Token::Bytes(b"c"),
Token::Struct { name: "A", len: 1 }, Token::Struct { name: "A", len: 1 },
Token::Str("a"), Token::Str("a"),
@@ -2426,7 +2173,10 @@ fn test_adjacently_tagged_enum_containing_flatten() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("A"), Token::UnitVariant {
name: "Data",
variant: "A",
},
Token::Str("c"), Token::Str("c"),
Token::Map { len: None }, Token::Map { len: None },
Token::Str("a"), Token::Str("a"),
@@ -2630,35 +2380,6 @@ fn test_partially_untagged_enum_desugared() {
); );
} }
#[test]
fn test_flatten_untagged_enum() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Outer {
#[serde(flatten)]
inner: Inner,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(untagged)]
enum Inner {
Variant { a: i32 },
}
let data = Outer {
inner: Inner::Variant { a: 0 },
};
assert_tokens(
&data,
&[
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test] #[test]
fn test_flatten_option() { fn test_flatten_option() {
#[derive(Serialize, Deserialize, PartialEq, Debug)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -2815,48 +2536,6 @@ fn test_internally_tagged_unit_enum_with_unknown_fields() {
); );
} }
#[test]
fn test_flattened_internally_tagged_unit_enum_with_unknown_fields() {
#[derive(Deserialize, PartialEq, Debug)]
struct S {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Deserialize, PartialEq, Debug)]
#[serde(tag = "typeX")]
enum X {
A,
}
#[derive(Deserialize, PartialEq, Debug)]
#[serde(tag = "typeY")]
enum Y {
B { c: u32 },
}
let s = S {
x: X::A,
y: Y::B { c: 0 },
};
assert_de_tokens(
&s,
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("A"),
Token::Str("typeY"),
Token::Str("B"),
Token::Str("c"),
Token::I32(0),
Token::MapEnd,
],
);
}
#[test] #[test]
fn test_flatten_any_after_flatten_struct() { fn test_flatten_any_after_flatten_struct() {
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
@@ -3087,7 +2766,7 @@ fn test_expecting_message_adjacently_tagged_enum() {
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
assert_de_tokens_error::<Enum>( assert_de_tokens_error::<Enum>(
&[Token::Map { len: None }, Token::Str("tag"), Token::Unit], &[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
r#"invalid type: unit value, expected variant identifier"#, r#"invalid type: unit value, expected variant of enum Enum"#,
); );
} }
@@ -3149,3 +2828,345 @@ fn test_expecting_message_identifier_enum() {
r#"invalid type: map, expected something strange..."#, r#"invalid type: map, expected something strange..."#,
); );
} }
mod flatten {
use super::*;
mod enum_ {
use super::*;
mod externally_tagged {
use super::*;
use std::iter::FromIterator;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
data: Enum,
#[serde(flatten)]
extra: HashMap<String, String>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum Enum {
Newtype(HashMap<String, String>),
Tuple(u32, u32),
Struct { index: u32, value: u32 },
}
#[test]
fn newtype() {
assert_tokens(
&Flatten {
data: Enum::Newtype(HashMap::from_iter([("key".into(), "value".into())])),
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Newtype"), // variant
Token::Map { len: Some(1) },
Token::Str("key"),
Token::Str("value"),
Token::MapEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
// Content::Seq case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn tuple() {
assert_tokens(
&Flatten {
data: Enum::Tuple(0, 42),
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Tuple"), // variant
Token::Seq { len: Some(2) },
Token::U32(0),
Token::U32(42),
Token::SeqEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Seq case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn struct_from_seq() {
assert_de_tokens(
&Flatten {
data: Enum::Struct {
index: 0,
value: 42,
},
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Struct"), // variant
Token::Seq { len: Some(2) },
Token::U32(0), // index
Token::U32(42), // value
Token::SeqEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Map case
// via FlatMapDeserializer::deserialize_enum
#[test]
fn struct_from_map() {
assert_tokens(
&Flatten {
data: Enum::Struct {
index: 0,
value: 42,
},
extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]),
},
&[
Token::Map { len: None },
Token::Str("Struct"), // variant
Token::Struct {
len: 2,
name: "Struct",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::Str("extra_key"),
Token::Str("extra value"),
Token::MapEnd,
],
);
}
}
mod adjacently_tagged {
use super::*;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
outer: u32,
#[serde(flatten)]
data: NewtypeWrapper,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct NewtypeWrapper(pub Enum);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "tag", content = "content")]
enum Enum {
Newtype(NewtypeVariant),
Struct { index: u32, value: u32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct NewtypeVariant {
value: u32,
}
#[test]
fn struct_() {
assert_tokens(
&Flatten {
outer: 42,
data: NewtypeWrapper(Enum::Struct {
index: 0,
value: 42,
}),
},
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("tag"),
Token::UnitVariant {
name: "Enum",
variant: "Struct",
},
Token::Str("content"),
Token::Struct {
len: 2,
name: "Struct",
},
Token::Str("index"),
Token::U32(0),
Token::Str("value"),
Token::U32(42),
Token::StructEnd,
Token::MapEnd,
],
);
}
#[test]
fn newtype() {
assert_tokens(
&Flatten {
outer: 42,
data: NewtypeWrapper(Enum::Newtype(NewtypeVariant { value: 23 })),
},
&[
Token::Map { len: None },
Token::Str("outer"),
Token::U32(42),
Token::Str("tag"),
Token::UnitVariant {
name: "Enum",
variant: "Newtype",
},
Token::Str("content"),
Token::Struct {
len: 1,
name: "NewtypeVariant",
},
Token::Str("value"),
Token::U32(23),
Token::StructEnd,
Token::MapEnd,
],
);
}
}
mod internally_tagged {
use super::*;
#[test]
fn structs() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "typeX")]
enum X {
A { a: i32 },
B { b: i32 },
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "typeY")]
enum Y {
C { c: i32 },
D { d: i32 },
}
assert_tokens(
&Flatten {
x: X::B { b: 1 },
y: Y::D { d: 2 },
},
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("B"),
Token::Str("b"),
Token::I32(1),
Token::Str("typeY"),
Token::Str("D"),
Token::Str("d"),
Token::I32(2),
Token::MapEnd,
],
);
}
#[test]
fn unit_enum_with_unknown_fields() {
#[derive(Debug, PartialEq, Deserialize)]
struct Flatten {
#[serde(flatten)]
x: X,
#[serde(flatten)]
y: Y,
}
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "typeX")]
enum X {
A,
}
#[derive(Debug, PartialEq, Deserialize)]
#[serde(tag = "typeY")]
enum Y {
B { c: u32 },
}
assert_de_tokens(
&Flatten {
x: X::A,
y: Y::B { c: 0 },
},
&[
Token::Map { len: None },
Token::Str("typeX"),
Token::Str("A"),
Token::Str("typeY"),
Token::Str("B"),
Token::Str("c"),
Token::I32(0),
Token::MapEnd,
],
);
}
}
mod untagged {
use super::*;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Flatten {
#[serde(flatten)]
data: Enum,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
enum Enum {
Struct { a: i32 },
}
#[test]
fn struct_() {
assert_tokens(
&Flatten {
data: Enum::Struct { a: 0 },
},
&[
Token::Map { len: None },
Token::Str("a"),
Token::I32(0),
Token::MapEnd,
],
);
}
}
}
}
+158 -58
View File
@@ -3,86 +3,186 @@
#![allow(clippy::derive_partial_eq_without_eq)] #![allow(clippy::derive_partial_eq_without_eq)]
use serde_derive::Deserialize; use serde_derive::Deserialize;
use serde_test::{assert_de_tokens, Token}; use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
mod variant_identifier {
use super::*;
#[test]
fn test_variant_identifier() {
#[derive(Deserialize, Debug, PartialEq)] #[derive(Deserialize, Debug, PartialEq)]
#[serde(variant_identifier)] #[serde(variant_identifier)]
enum V { enum V {
Aaa, Aaa,
#[serde(alias = "Ccc", alias = "Ddd")]
Bbb, Bbb,
} }
assert_de_tokens(&V::Aaa, &[Token::U8(0)]); #[test]
assert_de_tokens(&V::Aaa, &[Token::U16(0)]); fn variant1() {
assert_de_tokens(&V::Aaa, &[Token::U32(0)]); assert_de_tokens(&V::Aaa, &[Token::U8(0)]);
assert_de_tokens(&V::Aaa, &[Token::U64(0)]); assert_de_tokens(&V::Aaa, &[Token::U16(0)]);
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]); assert_de_tokens(&V::Aaa, &[Token::U32(0)]);
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]); assert_de_tokens(&V::Aaa, &[Token::U64(0)]);
assert_de_tokens(&V::Aaa, &[Token::Str("Aaa")]);
assert_de_tokens(&V::Aaa, &[Token::Bytes(b"Aaa")]);
}
#[test]
fn aliases() {
assert_de_tokens(&V::Bbb, &[Token::U8(1)]);
assert_de_tokens(&V::Bbb, &[Token::U16(1)]);
assert_de_tokens(&V::Bbb, &[Token::U32(1)]);
assert_de_tokens(&V::Bbb, &[Token::U64(1)]);
assert_de_tokens(&V::Bbb, &[Token::Str("Bbb")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Bbb")]);
assert_de_tokens(&V::Bbb, &[Token::Str("Ccc")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ccc")]);
assert_de_tokens(&V::Bbb, &[Token::Str("Ddd")]);
assert_de_tokens(&V::Bbb, &[Token::Bytes(b"Ddd")]);
}
#[test]
fn unknown() {
assert_de_tokens_error::<V>(
&[Token::U8(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U16(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U32(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::U64(42)],
"invalid value: integer `42`, expected variant index 0 <= i < 2",
);
assert_de_tokens_error::<V>(
&[Token::Str("Unknown")],
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
);
assert_de_tokens_error::<V>(
&[Token::Bytes(b"Unknown")],
"unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`",
);
}
} }
#[test] mod field_identifier {
fn test_field_identifier() { use super::*;
#[derive(Deserialize, Debug, PartialEq)] #[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")] #[serde(field_identifier, rename_all = "snake_case")]
enum F { enum F {
Aaa, Aaa,
#[serde(alias = "ccc", alias = "ddd")]
Bbb, Bbb,
} }
assert_de_tokens(&F::Aaa, &[Token::U8(0)]); #[test]
assert_de_tokens(&F::Aaa, &[Token::U16(0)]); fn field1() {
assert_de_tokens(&F::Aaa, &[Token::U32(0)]); assert_de_tokens(&F::Aaa, &[Token::U8(0)]);
assert_de_tokens(&F::Aaa, &[Token::U64(0)]); assert_de_tokens(&F::Aaa, &[Token::U16(0)]);
assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]); assert_de_tokens(&F::Aaa, &[Token::U32(0)]);
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]); assert_de_tokens(&F::Aaa, &[Token::U64(0)]);
} assert_de_tokens(&F::Aaa, &[Token::Str("aaa")]);
assert_de_tokens(&F::Aaa, &[Token::Bytes(b"aaa")]);
#[test]
fn test_unit_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
#[serde(other)]
Other,
} }
assert_de_tokens(&F::Other, &[Token::U8(42)]); #[test]
assert_de_tokens(&F::Other, &[Token::U16(42)]); fn aliases() {
assert_de_tokens(&F::Other, &[Token::U32(42)]); assert_de_tokens(&F::Bbb, &[Token::U8(1)]);
assert_de_tokens(&F::Other, &[Token::U64(42)]); assert_de_tokens(&F::Bbb, &[Token::U16(1)]);
assert_de_tokens(&F::Other, &[Token::Str("x")]); assert_de_tokens(&F::Bbb, &[Token::U32(1)]);
} assert_de_tokens(&F::Bbb, &[Token::U64(1)]);
#[test] assert_de_tokens(&F::Bbb, &[Token::Str("bbb")]);
fn test_newtype_fallthrough() { assert_de_tokens(&F::Bbb, &[Token::Bytes(b"bbb")]);
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")] assert_de_tokens(&F::Bbb, &[Token::Str("ccc")]);
enum F { assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ccc")]);
Aaa,
Bbb, assert_de_tokens(&F::Bbb, &[Token::Str("ddd")]);
Other(String), assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ddd")]);
} }
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]); #[test]
} fn unknown() {
assert_de_tokens_error::<F>(
#[test] &[Token::U8(42)],
fn test_newtype_fallthrough_generic() { "invalid value: integer `42`, expected field index 0 <= i < 2",
#[derive(Deserialize, Debug, PartialEq)] );
#[serde(field_identifier, rename_all = "snake_case")] assert_de_tokens_error::<F>(
enum F<T> { &[Token::U16(42)],
Aaa, "invalid value: integer `42`, expected field index 0 <= i < 2",
Bbb, );
Other(T), assert_de_tokens_error::<F>(
&[Token::U32(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::U64(42)],
"invalid value: integer `42`, expected field index 0 <= i < 2",
);
assert_de_tokens_error::<F>(
&[Token::Str("unknown")],
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
);
assert_de_tokens_error::<F>(
&[Token::Bytes(b"unknown")],
"unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`",
);
} }
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]); #[test]
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]); fn unit_fallthrough() {
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]); #[derive(Deserialize, Debug, PartialEq)]
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]); #[serde(field_identifier, rename_all = "snake_case")]
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]); enum F {
Aaa,
Bbb,
#[serde(other)]
Other,
}
assert_de_tokens(&F::Other, &[Token::U8(42)]);
assert_de_tokens(&F::Other, &[Token::U16(42)]);
assert_de_tokens(&F::Other, &[Token::U32(42)]);
assert_de_tokens(&F::Other, &[Token::U64(42)]);
assert_de_tokens(&F::Other, &[Token::Str("x")]);
}
#[test]
fn newtype_fallthrough() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F {
Aaa,
Bbb,
Other(String),
}
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
}
#[test]
fn newtype_fallthrough_generic() {
#[derive(Deserialize, Debug, PartialEq)]
#[serde(field_identifier, rename_all = "snake_case")]
enum F<T> {
Aaa,
Bbb,
Other(T),
}
assert_de_tokens(&F::Other(42u8), &[Token::U8(42)]);
assert_de_tokens(&F::Other(42u16), &[Token::U16(42)]);
assert_de_tokens(&F::Other(42u32), &[Token::U32(42)]);
assert_de_tokens(&F::Other(42u64), &[Token::U64(42)]);
assert_de_tokens(&F::Other("x".to_owned()), &[Token::Str("x")]);
}
} }
+99 -19
View File
@@ -472,7 +472,10 @@ fn test_adjacently_tagged_newtype_struct() {
}, },
Token::U32(5), Token::U32(5),
Token::Str("t"), Token::Str("t"),
Token::Str("Newtype"), Token::UnitVariant {
name: "E",
variant: "Newtype",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1066,7 +1069,10 @@ fn test_adjacently_tagged_enum() {
len: 1, len: 1,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Unit"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1080,7 +1086,10 @@ fn test_adjacently_tagged_enum() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Unit"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1094,7 +1103,10 @@ fn test_adjacently_tagged_enum() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Unit"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"), Token::Str("c"),
Token::Unit, Token::Unit,
Token::StructEnd, Token::StructEnd,
@@ -1112,7 +1124,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("c"), Token::Str("c"),
Token::Unit, Token::Unit,
Token::Str("t"), Token::Str("t"),
Token::Str("Unit"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1128,7 +1143,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("f"), Token::Str("f"),
Token::Unit, Token::Unit,
Token::Str("t"), Token::Str("t"),
Token::Str("Unit"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("g"), Token::Str("g"),
Token::Unit, Token::Unit,
Token::Str("c"), Token::Str("c"),
@@ -1148,7 +1166,10 @@ fn test_adjacently_tagged_enum() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Newtype"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::Str("c"), Token::Str("c"),
Token::U8(1), Token::U8(1),
Token::StructEnd, Token::StructEnd,
@@ -1166,7 +1187,10 @@ fn test_adjacently_tagged_enum() {
Token::Str("c"), Token::Str("c"),
Token::U8(1), Token::U8(1),
Token::Str("t"), Token::Str("t"),
Token::Str("Newtype"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1180,7 +1204,10 @@ fn test_adjacently_tagged_enum() {
len: 1, len: 1,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Newtype"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1194,7 +1221,10 @@ fn test_adjacently_tagged_enum() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Tuple"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Tuple",
},
Token::Str("c"), Token::Str("c"),
Token::Tuple { len: 2 }, Token::Tuple { len: 2 },
Token::U8(1), Token::U8(1),
@@ -1218,7 +1248,10 @@ fn test_adjacently_tagged_enum() {
Token::U8(1), Token::U8(1),
Token::TupleEnd, Token::TupleEnd,
Token::Str("t"), Token::Str("t"),
Token::Str("Tuple"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Tuple",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1232,7 +1265,10 @@ fn test_adjacently_tagged_enum() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Struct"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Struct",
},
Token::Str("c"), Token::Str("c"),
Token::Struct { Token::Struct {
name: "Struct", name: "Struct",
@@ -1262,7 +1298,10 @@ fn test_adjacently_tagged_enum() {
Token::U8(1), Token::U8(1),
Token::StructEnd, Token::StructEnd,
Token::Str("t"), Token::Str("t"),
Token::Str("Struct"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Struct",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1278,7 +1317,10 @@ fn test_adjacently_tagged_enum() {
Token::U64(1), // content field Token::U64(1), // content field
Token::U8(1), Token::U8(1),
Token::U64(0), // tag field Token::U64(0), // tag field
Token::Str("Newtype"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1294,7 +1336,10 @@ fn test_adjacently_tagged_enum() {
Token::Bytes(b"c"), Token::Bytes(b"c"),
Token::U8(1), Token::U8(1),
Token::Bytes(b"t"), Token::Bytes(b"t"),
Token::Str("Newtype"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Newtype",
},
Token::StructEnd, Token::StructEnd,
], ],
); );
@@ -1316,7 +1361,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Unit"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"), Token::Str("c"),
Token::Unit, Token::Unit,
Token::StructEnd, Token::StructEnd,
@@ -1330,7 +1378,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2, len: 2,
}, },
Token::Str("t"), Token::Str("t"),
Token::Str("Unit"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::Str("c"), Token::Str("c"),
Token::Unit, Token::Unit,
Token::Str("h"), Token::Str("h"),
@@ -1369,7 +1420,10 @@ fn test_adjacently_tagged_enum_deny_unknown_fields() {
len: 2, len: 2,
}, },
Token::U64(0), // tag field Token::U64(0), // tag field
Token::Str("Unit"), Token::UnitVariant {
name: "AdjacentlyTagged",
variant: "Unit",
},
Token::U64(3), Token::U64(3),
], ],
r#"invalid value: integer `3`, expected "t" or "c""#, r#"invalid value: integer `3`, expected "t" or "c""#,
@@ -1429,6 +1483,9 @@ fn test_enum_in_internally_tagged_enum() {
], ],
); );
// Reaches crate::private::de::content::VariantDeserializer::tuple_variant
// Content::Seq case
// via ContentDeserializer::deserialize_enum
assert_tokens( assert_tokens(
&Outer::Inner(Inner::Tuple(1, 1)), &Outer::Inner(Inner::Tuple(1, 1)),
&[ &[
@@ -1447,6 +1504,9 @@ fn test_enum_in_internally_tagged_enum() {
], ],
); );
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Map case
// via ContentDeserializer::deserialize_enum
assert_tokens( assert_tokens(
&Outer::Inner(Inner::Struct { f: 1 }), &Outer::Inner(Inner::Struct { f: 1 }),
&[ &[
@@ -1464,6 +1524,23 @@ fn test_enum_in_internally_tagged_enum() {
Token::MapEnd, Token::MapEnd,
], ],
); );
// Reaches crate::private::de::content::VariantDeserializer::struct_variant
// Content::Seq case
// via ContentDeserializer::deserialize_enum
assert_de_tokens(
&Outer::Inner(Inner::Struct { f: 1 }),
&[
Token::Map { len: Some(2) },
Token::Str("type"),
Token::Str("Inner"),
Token::Str("Struct"),
Token::Seq { len: Some(1) },
Token::U8(1), // f
Token::SeqEnd,
Token::MapEnd,
],
);
} }
#[test] #[test]
@@ -1542,7 +1619,10 @@ fn test_internally_tagged_struct_with_flattened_field() {
Token::Str("tag_struct"), Token::Str("tag_struct"),
Token::Str("Struct"), Token::Str("Struct"),
Token::Str("tag_enum"), Token::Str("tag_enum"),
Token::Str("A"), Token::UnitVariant {
name: "Enum",
variant: "A",
},
Token::Str("content"), Token::Str("content"),
Token::U64(0), Token::U64(0),
Token::MapEnd, Token::MapEnd,
@@ -1,4 +1,4 @@
error: #[serde(default)] can only be used on structs with named fields error: #[serde(default)] can only be used on structs
--> tests/ui/default-attribute/enum.rs:4:9 --> tests/ui/default-attribute/enum.rs:4:9
| |
4 | #[serde(default)] 4 | #[serde(default)]
@@ -1,4 +1,4 @@
error: #[serde(default = "...")] can only be used on structs with named fields error: #[serde(default = "...")] can only be used on structs
--> tests/ui/default-attribute/enum_path.rs:4:9 --> tests/ui/default-attribute/enum_path.rs:4:9
| |
4 | #[serde(default = "default_e")] 4 | #[serde(default = "default_e")]
@@ -1,7 +0,0 @@
use serde_derive::Deserialize;
#[derive(Deserialize)]
#[serde(default)]
struct T(u8, u8);
fn main() {}
@@ -1,5 +0,0 @@
error: #[serde(default)] can only be used on structs with named fields
--> tests/ui/default-attribute/nameless_struct_fields.rs:5:9
|
5 | struct T(u8, u8);
| ^^^^^^^^
@@ -1,7 +0,0 @@
use serde_derive::Deserialize;
#[derive(Deserialize)]
#[serde(default = "default_t")]
struct T(u8, u8);
fn main() {}
@@ -1,5 +0,0 @@
error: #[serde(default = "...")] can only be used on structs with named fields
--> tests/ui/default-attribute/nameless_struct_fields_path.rs:4:9
|
4 | #[serde(default = "default_t")]
| ^^^^^^^^^^^^^^^^^^^^^
@@ -0,0 +1,47 @@
use serde_derive::Deserialize;
// No errors expected.
#[derive(Deserialize)]
struct T0(u8, u8);
// No errors expected:
// - If both fields are provided, both get value from data.
// - If only one field is provided, the second gets default value.
#[derive(Deserialize)]
struct T1(u8, #[serde(default)] u8);
// ERROR: The first field can get default value only if sequence is empty, but
// that mean that all other fields cannot be deserialized without errors.
#[derive(Deserialize)]
struct T2(#[serde(default)] u8, u8, u8);
// No errors expected:
// - If both fields are provided, both get value from data.
// - If only one field is provided, the second gets default value.
// - If no fields are provided, both get default value.
#[derive(Deserialize)]
struct T3(#[serde(default)] u8, #[serde(default)] u8);
////////////////////////////////////////////////////////////////////////////////
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T4(u8, u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T5(#[serde(default)] u8, u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T6(u8, #[serde(default)] u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T7(#[serde(default)] u8, #[serde(default)] u8);
fn main() {}
@@ -0,0 +1,11 @@
error: field must have #[serde(default)] because previous field 0 has #[serde(default)]
--> tests/ui/default-attribute/tuple_struct.rs:16:33
|
16 | struct T2(#[serde(default)] u8, u8, u8);
| ^^
error: field must have #[serde(default)] because previous field 0 has #[serde(default)]
--> tests/ui/default-attribute/tuple_struct.rs:16:37
|
16 | struct T2(#[serde(default)] u8, u8, u8);
| ^^
@@ -0,0 +1,76 @@
use serde_derive::Deserialize;
fn d<T>() -> T {
unimplemented!()
}
// No errors expected:
// - If both fields are provided, both get value from data.
// - If only one field is provided, the second gets default value.
#[derive(Deserialize)]
struct T1(u8, #[serde(default = "d")] u8);
// ERROR: The first field can get default value only if sequence is empty, but
// that mean that all other fields cannot be deserialized without errors.
#[derive(Deserialize)]
struct T2(#[serde(default = "d")] u8, u8, u8);
// No errors expected:
// - If both fields are provided, both get value from data.
// - If only one field is provided, the second gets default value.
// - If no fields are provided, both get default value.
#[derive(Deserialize)]
struct T3(#[serde(default = "d")] u8, #[serde(default = "d")] u8);
////////////////////////////////////////////////////////////////////////////////
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T1D(#[serde(default = "d")] u8, u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T2D(u8, #[serde(default = "d")] u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T3D(#[serde(default = "d")] u8, #[serde(default = "d")] u8);
////////////////////////////////////////////////////////////////////////////////
// No errors expected -- missing fields get default values.
#[derive(Deserialize)]
#[serde(default = "d")]
struct T1Path(#[serde(default)] u8, u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize)]
#[serde(default = "d")]
struct T2Path(u8, #[serde(default)] u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize)]
#[serde(default = "d")]
struct T3Path(#[serde(default)] u8, #[serde(default)] u8);
////////////////////////////////////////////////////////////////////////////////
// No errors expected -- missing fields get default values.
#[derive(Deserialize)]
#[serde(default = "d")]
struct T1PathD(#[serde(default = "d")] u8, u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize)]
#[serde(default = "d")]
struct T2PathD(u8, #[serde(default = "d")] u8);
// No errors expected -- missing fields get default values.
#[derive(Deserialize)]
#[serde(default = "d")]
struct T3PathD(#[serde(default = "d")] u8, #[serde(default = "d")] u8);
fn main() {}
@@ -0,0 +1,11 @@
error: field must have #[serde(default)] because previous field 0 has #[serde(default)]
--> tests/ui/default-attribute/tuple_struct_path.rs:16:39
|
16 | struct T2(#[serde(default = "d")] u8, u8, u8);
| ^^
error: field must have #[serde(default)] because previous field 0 has #[serde(default)]
--> tests/ui/default-attribute/tuple_struct_path.rs:16:43
|
16 | struct T2(#[serde(default = "d")] u8, u8, u8);
| ^^