Repository: serde-rs/serde Branch: master Commit: fa7da4a93567 Files: 347 Total size: 1.3 MB Directory structure: gitextract_h3ikti25/ ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── 1-problem.md │ │ ├── 2-suggestion.md │ │ ├── 3-documentation.md │ │ └── 4-other.md │ └── workflows/ │ └── ci.yml ├── .gitignore ├── CONTRIBUTING.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── crates-io.md ├── serde/ │ ├── Cargo.toml │ ├── build.rs │ └── src/ │ ├── integer128.rs │ ├── lib.rs │ └── private/ │ ├── de.rs │ ├── mod.rs │ └── ser.rs ├── serde_core/ │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ └── src/ │ ├── crate_root.rs │ ├── de/ │ │ ├── ignored_any.rs │ │ ├── impls.rs │ │ ├── mod.rs │ │ └── value.rs │ ├── format.rs │ ├── lib.rs │ ├── macros.rs │ ├── private/ │ │ ├── content.rs │ │ ├── doc.rs │ │ ├── mod.rs │ │ ├── seed.rs │ │ ├── size_hint.rs │ │ └── string.rs │ ├── ser/ │ │ ├── fmt.rs │ │ ├── impls.rs │ │ ├── impossible.rs │ │ └── mod.rs │ └── std_error.rs ├── serde_derive/ │ ├── Cargo.toml │ ├── build.rs │ └── src/ │ ├── bound.rs │ ├── de/ │ │ ├── enum_.rs │ │ ├── enum_adjacently.rs │ │ ├── enum_externally.rs │ │ ├── enum_internally.rs │ │ ├── enum_untagged.rs │ │ ├── identifier.rs │ │ ├── struct_.rs │ │ ├── tuple.rs │ │ └── unit.rs │ ├── de.rs │ ├── deprecated.rs │ ├── dummy.rs │ ├── fragment.rs │ ├── internals/ │ │ ├── ast.rs │ │ ├── attr.rs │ │ ├── case.rs │ │ ├── check.rs │ │ ├── ctxt.rs │ │ ├── mod.rs │ │ ├── name.rs │ │ ├── receiver.rs │ │ ├── respan.rs │ │ └── symbol.rs │ ├── lib.rs │ ├── pretend.rs │ ├── ser.rs │ └── this.rs ├── serde_derive_internals/ │ ├── Cargo.toml │ ├── build.rs │ └── lib.rs └── test_suite/ ├── Cargo.toml ├── no_std/ │ ├── .gitignore │ ├── Cargo.toml │ └── src/ │ └── main.rs └── tests/ ├── bytes/ │ └── mod.rs ├── compiletest.rs ├── macros/ │ └── mod.rs ├── regression/ │ ├── issue1904.rs │ ├── issue2371.rs │ ├── issue2409.rs │ ├── issue2415.rs │ ├── issue2565.rs │ ├── issue2792.rs │ ├── issue2844.rs │ └── issue2846.rs ├── regression.rs ├── test_annotations.rs ├── test_borrow.rs ├── test_de.rs ├── test_de_error.rs ├── test_deprecated.rs ├── test_enum_adjacently_tagged.rs ├── test_enum_internally_tagged.rs ├── test_enum_untagged.rs ├── test_gen.rs ├── test_identifier.rs ├── test_ignored_any.rs ├── test_macros.rs ├── test_remote.rs ├── test_roundtrip.rs ├── test_self.rs ├── test_ser.rs ├── test_serde_path.rs ├── test_unstable.rs ├── test_value.rs ├── ui/ │ ├── borrow/ │ │ ├── bad_lifetimes.rs │ │ ├── bad_lifetimes.stderr │ │ ├── duplicate_lifetime.rs │ │ ├── duplicate_lifetime.stderr │ │ ├── duplicate_variant.rs │ │ ├── duplicate_variant.stderr │ │ ├── empty_lifetimes.rs │ │ ├── empty_lifetimes.stderr │ │ ├── no_lifetimes.rs │ │ ├── no_lifetimes.stderr │ │ ├── struct_variant.rs │ │ ├── struct_variant.stderr │ │ ├── wrong_lifetime.rs │ │ └── wrong_lifetime.stderr │ ├── conflict/ │ │ ├── adjacent-tag.rs │ │ ├── adjacent-tag.stderr │ │ ├── alias-enum.rs │ │ ├── alias-enum.stderr │ │ ├── alias.rs │ │ ├── alias.stderr │ │ ├── flatten-newtype-struct.rs │ │ ├── flatten-newtype-struct.stderr │ │ ├── flatten-tuple-struct.rs │ │ ├── flatten-tuple-struct.stderr │ │ ├── from-try-from.rs │ │ ├── from-try-from.stderr │ │ ├── internal-tag-alias.rs │ │ ├── internal-tag-alias.stderr │ │ ├── internal-tag.rs │ │ └── internal-tag.stderr │ ├── default-attribute/ │ │ ├── enum.rs │ │ ├── enum.stderr │ │ ├── enum_path.rs │ │ ├── enum_path.stderr │ │ ├── incorrect_type_enum_adjacently_tagged.rs │ │ ├── incorrect_type_enum_adjacently_tagged.stderr │ │ ├── incorrect_type_enum_externally_tagged.rs │ │ ├── incorrect_type_enum_externally_tagged.stderr │ │ ├── incorrect_type_enum_internally_tagged.rs │ │ ├── incorrect_type_enum_internally_tagged.stderr │ │ ├── incorrect_type_enum_untagged.rs │ │ ├── incorrect_type_enum_untagged.stderr │ │ ├── incorrect_type_newtype.rs │ │ ├── incorrect_type_newtype.stderr │ │ ├── incorrect_type_struct.rs │ │ ├── incorrect_type_struct.stderr │ │ ├── incorrect_type_tuple.rs │ │ ├── incorrect_type_tuple.stderr │ │ ├── tuple_struct.rs │ │ ├── tuple_struct.stderr │ │ ├── tuple_struct_path.rs │ │ ├── tuple_struct_path.stderr │ │ ├── union.rs │ │ ├── union.stderr │ │ ├── union_path.rs │ │ ├── union_path.stderr │ │ ├── unit.rs │ │ ├── unit.stderr │ │ ├── unit_path.rs │ │ └── unit_path.stderr │ ├── deprecated/ │ │ ├── deprecated_de_with.rs │ │ ├── deprecated_de_with.stderr │ │ ├── deprecated_ser_with.rs │ │ └── deprecated_ser_with.stderr │ ├── duplicate-attribute/ │ │ ├── rename-and-ser.rs │ │ ├── rename-and-ser.stderr │ │ ├── rename-ser-rename-ser.rs │ │ ├── rename-ser-rename-ser.stderr │ │ ├── rename-ser-rename.rs │ │ ├── rename-ser-rename.stderr │ │ ├── rename-ser-ser.rs │ │ ├── rename-ser-ser.stderr │ │ ├── two-rename-ser.rs │ │ ├── two-rename-ser.stderr │ │ ├── with-and-serialize-with.rs │ │ └── with-and-serialize-with.stderr │ ├── enum-representation/ │ │ ├── content-no-tag.rs │ │ ├── content-no-tag.stderr │ │ ├── internal-tuple-variant.rs │ │ ├── internal-tuple-variant.stderr │ │ ├── partially_tagged_wrong_order.rs │ │ ├── partially_tagged_wrong_order.stderr │ │ ├── untagged-and-adjacent.rs │ │ ├── untagged-and-adjacent.stderr │ │ ├── untagged-and-content.rs │ │ ├── untagged-and-content.stderr │ │ ├── untagged-and-internal.rs │ │ ├── untagged-and-internal.stderr │ │ ├── untagged-struct.rs │ │ └── untagged-struct.stderr │ ├── expected-string/ │ │ ├── boolean.rs │ │ ├── boolean.stderr │ │ ├── byte_character.rs │ │ ├── byte_character.stderr │ │ ├── byte_string.rs │ │ ├── byte_string.stderr │ │ ├── character.rs │ │ ├── character.stderr │ │ ├── float.rs │ │ ├── float.stderr │ │ ├── integer.rs │ │ └── integer.stderr │ ├── identifier/ │ │ ├── both.rs │ │ ├── both.stderr │ │ ├── field_struct.rs │ │ ├── field_struct.stderr │ │ ├── field_tuple.rs │ │ ├── field_tuple.stderr │ │ ├── newtype_not_last.rs │ │ ├── newtype_not_last.stderr │ │ ├── not_unit.rs │ │ ├── not_unit.stderr │ │ ├── other_not_last.rs │ │ ├── other_not_last.stderr │ │ ├── other_untagged.rs │ │ ├── other_untagged.stderr │ │ ├── other_variant.rs │ │ ├── other_variant.stderr │ │ ├── variant_struct.rs │ │ ├── variant_struct.stderr │ │ ├── variant_tuple.rs │ │ └── variant_tuple.stderr │ ├── malformed/ │ │ ├── bound.rs │ │ ├── bound.stderr │ │ ├── cut_off.rs │ │ ├── cut_off.stderr │ │ ├── not_list.rs │ │ ├── not_list.stderr │ │ ├── rename.rs │ │ ├── rename.stderr │ │ ├── str_suffix.rs │ │ ├── str_suffix.stderr │ │ ├── trailing_expr.rs │ │ └── trailing_expr.stderr │ ├── precondition/ │ │ ├── deserialize_de_lifetime.rs │ │ ├── deserialize_de_lifetime.stderr │ │ ├── deserialize_dst.rs │ │ ├── deserialize_dst.stderr │ │ ├── serialize_field_identifier.rs │ │ ├── serialize_field_identifier.stderr │ │ ├── serialize_variant_identifier.rs │ │ └── serialize_variant_identifier.stderr │ ├── remote/ │ │ ├── bad_getter.rs │ │ ├── bad_getter.stderr │ │ ├── bad_remote.rs │ │ ├── bad_remote.stderr │ │ ├── double_generic.rs │ │ ├── double_generic.stderr │ │ ├── enum_getter.rs │ │ ├── enum_getter.stderr │ │ ├── missing_field.rs │ │ ├── missing_field.stderr │ │ ├── nonremote_getter.rs │ │ ├── nonremote_getter.stderr │ │ ├── unknown_field.rs │ │ ├── unknown_field.stderr │ │ ├── wrong_de.rs │ │ ├── wrong_de.stderr │ │ ├── wrong_getter.rs │ │ ├── wrong_getter.stderr │ │ ├── wrong_ser.rs │ │ └── wrong_ser.stderr │ ├── rename/ │ │ ├── container_unknown_rename_rule.rs │ │ ├── container_unknown_rename_rule.stderr │ │ ├── variant_unknown_rename_rule.rs │ │ └── variant_unknown_rename_rule.stderr │ ├── struct-representation/ │ │ ├── internally-tagged-tuple.rs │ │ ├── internally-tagged-tuple.stderr │ │ ├── internally-tagged-unit.rs │ │ └── internally-tagged-unit.stderr │ ├── transparent/ │ │ ├── at_most_one.rs │ │ ├── at_most_one.stderr │ │ ├── de_at_least_one.rs │ │ ├── de_at_least_one.stderr │ │ ├── enum.rs │ │ ├── enum.stderr │ │ ├── ser_at_least_one.rs │ │ ├── ser_at_least_one.stderr │ │ ├── unit_struct.rs │ │ ├── unit_struct.stderr │ │ ├── with_from.rs │ │ ├── with_from.stderr │ │ ├── with_into.rs │ │ ├── with_into.stderr │ │ ├── with_try_from.rs │ │ └── with_try_from.stderr │ ├── type-attribute/ │ │ ├── from.rs │ │ ├── from.stderr │ │ ├── into.rs │ │ ├── into.stderr │ │ ├── try_from.rs │ │ └── try_from.stderr │ ├── unexpected-literal/ │ │ ├── container.rs │ │ ├── container.stderr │ │ ├── field.rs │ │ ├── field.stderr │ │ ├── variant.rs │ │ └── variant.stderr │ ├── unimplemented/ │ │ ├── required_by_dependency.rs │ │ ├── required_by_dependency.stderr │ │ ├── required_locally.rs │ │ └── required_locally.stderr │ ├── unknown-attribute/ │ │ ├── container.rs │ │ ├── container.stderr │ │ ├── field.rs │ │ ├── field.stderr │ │ ├── variant.rs │ │ └── variant.stderr │ ├── unsupported/ │ │ ├── union_de.rs │ │ ├── union_de.stderr │ │ ├── union_ser.rs │ │ └── union_ser.stderr │ ├── with/ │ │ ├── incorrect_type.rs │ │ └── incorrect_type.stderr │ └── with-variant/ │ ├── skip_de_newtype_field.rs │ ├── skip_de_newtype_field.stderr │ ├── skip_de_struct_field.rs │ ├── skip_de_struct_field.stderr │ ├── skip_de_tuple_field.rs │ ├── skip_de_tuple_field.stderr │ ├── skip_de_whole_variant.rs │ ├── skip_de_whole_variant.stderr │ ├── skip_ser_newtype_field.rs │ ├── skip_ser_newtype_field.stderr │ ├── skip_ser_newtype_field_if.rs │ ├── skip_ser_newtype_field_if.stderr │ ├── skip_ser_struct_field.rs │ ├── skip_ser_struct_field.stderr │ ├── skip_ser_struct_field_if.rs │ ├── skip_ser_struct_field_if.stderr │ ├── skip_ser_tuple_field.rs │ ├── skip_ser_tuple_field.stderr │ ├── skip_ser_tuple_field_if.rs │ ├── skip_ser_tuple_field_if.stderr │ ├── skip_ser_whole_variant.rs │ └── skip_ser_whole_variant.stderr └── unstable/ └── mod.rs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/FUNDING.yml ================================================ github: dtolnay ================================================ FILE: .github/ISSUE_TEMPLATE/1-problem.md ================================================ --- name: Problem about: Something does not seem right --- ================================================ FILE: .github/ISSUE_TEMPLATE/2-suggestion.md ================================================ --- name: Suggestion about: Share how Serde could support your use case better --- ================================================ FILE: .github/ISSUE_TEMPLATE/3-documentation.md ================================================ --- name: Documentation about: Certainly there is room for improvement --- ================================================ FILE: .github/ISSUE_TEMPLATE/4-other.md ================================================ --- name: Anything else! about: Whatever is on your mind --- ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: pull_request: workflow_dispatch: schedule: [cron: "40 1 * * *"] permissions: contents: read env: RUSTFLAGS: -Dwarnings jobs: test: name: Test suite runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@nightly - run: cd test_suite && cargo test --features unstable - uses: actions/upload-artifact@v6 if: always() with: name: Cargo.lock path: Cargo.lock continue-on-error: true windows: name: Test suite (windows) runs-on: windows-latest timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@nightly - run: cd test_suite && cargo test --features unstable -- --skip ui --exact stable: name: Rust ${{matrix.rust}} runs-on: ubuntu-latest strategy: fail-fast: false matrix: rust: [stable, beta] timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} - run: cd serde && cargo build --features rc - run: cd serde && cargo build --no-default-features - run: cd test_suite/no_std && cargo build nightly: name: Rust nightly${{matrix.os == 'windows' && ' (windows)' || ''}} runs-on: ${{matrix.os}}-latest strategy: fail-fast: false matrix: os: [ubuntu, windows] timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@nightly - run: cd serde && cargo build - run: cd serde && cargo build --no-default-features - run: cd serde && cargo build --no-default-features --features alloc - run: cd serde && cargo build --no-default-features --features rc,alloc - run: cd serde && cargo build --no-default-features --features unstable - run: cd serde_core && cargo test --features rc,unstable - run: cd test_suite/no_std && cargo build if: matrix.os != 'windows' - run: cd serde_derive && cargo check --tests env: RUSTFLAGS: --cfg exhaustive ${{env.RUSTFLAGS}} if: matrix.os != 'windows' build: name: Rust ${{matrix.rust}} runs-on: ubuntu-latest strategy: fail-fast: false matrix: rust: [1.56.0, 1.60.0] timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} - run: sed -i '/"test_suite"/d' Cargo.toml - run: cd serde && cargo build --features rc - run: cd serde && cargo build --no-default-features - run: cd serde && cargo build --no-default-features --features alloc - run: cd serde && cargo build derive: name: Rust 1.71.0 runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@1.71.0 - run: | sed -i 's/proc-macro2 = { workspace = true/proc-macro2 = { version = "1"/' serde_derive*/Cargo.toml sed -i 's/quote = { workspace = true/quote = { version = "1"/' serde_derive*/Cargo.toml sed -i 's/syn = { workspace = true/syn = { version = "2"/' serde_derive*/Cargo.toml - run: cd serde && cargo check --no-default-features - run: cd serde && cargo check - run: cd serde_derive && cargo check minimal: name: Minimal versions runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@nightly - run: cargo generate-lockfile -Z minimal-versions - run: cargo check --locked --workspace doc: name: Documentation runs-on: ubuntu-latest timeout-minutes: 45 env: RUSTDOCFLAGS: -Dwarnings steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@nightly - uses: dtolnay/install@cargo-docs-rs - run: cargo docs-rs -p serde - run: cargo docs-rs -p serde_core - run: cargo docs-rs -p serde_derive - run: cargo docs-rs -p serde_derive_internals clippy: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@clippy - run: cd serde && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic - run: cd serde_core && cargo clippy --features rc,unstable -- -Dclippy::all -Dclippy::pedantic - run: cd serde_derive && cargo clippy -- -Dclippy::all -Dclippy::pedantic - run: cd serde_derive_internals && cargo clippy -- -Dclippy::all -Dclippy::pedantic - run: cd test_suite && cargo clippy --tests --features unstable -- -Dclippy::all -Dclippy::pedantic - run: cd test_suite/no_std && cargo clippy -- -Dclippy::all -Dclippy::pedantic miri: name: Miri runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@miri - run: cargo miri setup - run: cd serde_core && cargo miri test --features rc,unstable env: MIRIFLAGS: -Zmiri-strict-provenance - run: cd test_suite && cargo miri test --features unstable env: MIRIFLAGS: -Zmiri-strict-provenance outdated: name: Outdated runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 ================================================ FILE: .gitignore ================================================ /target/ /Cargo.lock ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to Serde Serde welcomes contribution from everyone in the form of suggestions, bug reports, pull requests, and feedback. This document gives some guidance if you are thinking of helping us. ## Submitting bug reports and feature requests Serde development is spread across lots of repositories, but this serde-rs/serde repository is always a safe choice for opening any issues related to Serde. When reporting a bug or asking for help, please include enough details so that the people helping you can reproduce the behavior you are seeing. For some tips on how to approach this, read about how to produce a [Minimal, Complete, and Verifiable example]. [Minimal, Complete, and Verifiable example]: https://stackoverflow.com/help/mcve When making a feature request, please make it clear what problem you intend to solve with the feature, any ideas for how Serde could support solving that problem, any possible alternatives, and any disadvantages. ## Running the test suite We encourage you to check that the test suite passes locally before submitting a pull request with your changes. If anything does not pass, typically it will be easier to iterate and fix it locally than waiting for the CI servers to run tests for you. ##### In the [`serde_core`] directory ```sh # Test all the example code in Serde documentation cargo test ``` ##### In the [`test_suite`] directory ```sh # Run the full test suite, including tests of unstable functionality cargo +nightly test --features unstable ``` Note that this test suite currently only supports running on a nightly compiler. [`serde_core`]: https://github.com/serde-rs/serde/tree/master/serde_core [`test_suite`]: https://github.com/serde-rs/serde/tree/master/test_suite ## Conduct In all Serde-related forums, we follow the [Rust Code of Conduct]. For escalation or moderation issues please contact Erick (erick.tryzelaar@gmail.com) instead of the Rust moderation team. [Rust Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct ================================================ FILE: Cargo.toml ================================================ [workspace] members = [ "serde", "serde_core", "serde_derive", "serde_derive_internals", "test_suite", ] resolver = "2" [patch.crates-io] serde = { path = "serde" } serde_core = { path = "serde_core" } serde_derive = { path = "serde_derive" } [workspace.dependencies] proc-macro2 = { version = "1.0.74", default-features = false } quote = { version = "1.0.35", default-features = false } syn = { version = "2.0.81", default-features = false } ================================================ FILE: LICENSE-APACHE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: LICENSE-MIT ================================================ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Serde   [![Build Status]][actions] [![Latest Version]][crates.io] [![serde msrv]][Rust 1.56] [![serde_derive msrv]][Rust 1.71] [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 [Latest Version]: https://img.shields.io/crates/v/serde.svg [crates.io]: https://crates.io/crates/serde [serde msrv]: https://img.shields.io/crates/msrv/serde.svg?label=serde%20msrv&color=lightgray [serde_derive msrv]: https://img.shields.io/crates/msrv/serde_derive.svg?label=serde_derive%20msrv&color=lightgray [Rust 1.56]: https://blog.rust-lang.org/2021/10/21/Rust-1.56.0/ [Rust 1.71]: https://blog.rust-lang.org/2023/07/13/Rust-1.71.0/ **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** --- You may be looking for: - [An overview of Serde](https://serde.rs) - [Data formats supported by Serde](https://serde.rs/#data-formats) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html) - [Examples](https://serde.rs/examples.html) - [API documentation](https://docs.rs/serde) - [Release notes](https://github.com/serde-rs/serde/releases) ## Serde in action
Click to show Cargo.toml. Run this code in the playground. ```toml [dependencies] # The core APIs, including the Serialize and Deserialize traits. Always # required when using Serde. The "derive" feature is only required when # using #[derive(Serialize, Deserialize)] to make Serde work with structs # and enums defined in your crate. serde = { version = "1.0", features = ["derive"] } # Each data format lives in its own crate; the sample code below uses JSON # but you may be using a different one. serde_json = "1.0" ```

```rust use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { x: i32, y: i32, } fn main() { let point = Point { x: 1, y: 2 }; // Convert the Point to a JSON string. let serialized = serde_json::to_string(&point).unwrap(); // Prints serialized = {"x":1,"y":2} println!("serialized = {}", serialized); // Convert the JSON string back to a Point. let deserialized: Point = serde_json::from_str(&serialized).unwrap(); // Prints deserialized = Point { x: 1, y: 2 } println!("deserialized = {:?}", deserialized); } ``` ## Getting help Serde is one of the most widely used Rust libraries so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the [#rust-questions] or [#rust-beginners] channels of the unofficial community Discord (invite: ), the [#rust-usage] or [#beginners] channels of the official Rust Project Discord (invite: ), or the [#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust [Discourse forum][discourse]. It's acceptable to file a support issue in this repo but they tend not to get as many eyes as any of the above and may get closed without a response after some time. [#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513 [#rust-beginners]: https://discord.com/channels/273534239310479360/273541522815713281 [#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848 [#beginners]: https://discord.com/channels/442252698964721669/448238009733742612 [zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general [stackoverflow]: https://stackoverflow.com/questions/tagged/rust [/r/rust]: https://www.reddit.com/r/rust [discourse]: https://users.rust-lang.org
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Serde by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. ================================================ FILE: crates-io.md ================================================ **Serde is a framework for *ser*ializing and *de*serializing Rust data structures efficiently and generically.** --- You may be looking for: - [An overview of Serde](https://serde.rs) - [Data formats supported by Serde](https://serde.rs/#data-formats) - [Setting up `#[derive(Serialize, Deserialize)]`](https://serde.rs/derive.html) - [Examples](https://serde.rs/examples.html) - [API documentation](https://docs.rs/serde) - [Release notes](https://github.com/serde-rs/serde/releases) ## Serde in action ```rust use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] struct Point { x: i32, y: i32, } fn main() { let point = Point { x: 1, y: 2 }; // Convert the Point to a JSON string. let serialized = serde_json::to_string(&point).unwrap(); // Prints serialized = {"x":1,"y":2} println!("serialized = {}", serialized); // Convert the JSON string back to a Point. let deserialized: Point = serde_json::from_str(&serialized).unwrap(); // Prints deserialized = Point { x: 1, y: 2 } println!("deserialized = {:?}", deserialized); } ``` ## Getting help Serde is one of the most widely used Rust libraries so any place that Rustaceans congregate will be able to help you out. For chat, consider trying the [#rust-questions] or [#rust-beginners] channels of the unofficial community Discord (invite: ), the [#rust-usage] or [#beginners] channels of the official Rust Project Discord (invite: ), or the [#general][zulip] stream in Zulip. For asynchronous, consider the [\[rust\] tag on StackOverflow][stackoverflow], the [/r/rust] subreddit which has a pinned weekly easy questions post, or the Rust [Discourse forum][discourse]. It's acceptable to file a support issue in this repo but they tend not to get as many eyes as any of the above and may get closed without a response after some time. [#rust-questions]: https://discord.com/channels/273534239310479360/274215136414400513 [#rust-beginners]: https://discord.com/channels/273534239310479360/273541522815713281 [#rust-usage]: https://discord.com/channels/442252698964721669/443150878111694848 [#beginners]: https://discord.com/channels/442252698964721669/448238009733742612 [zulip]: https://rust-lang.zulipchat.com/#narrow/stream/122651-general [stackoverflow]: https://stackoverflow.com/questions/tagged/rust [/r/rust]: https://www.reddit.com/r/rust [discourse]: https://users.rust-lang.org ================================================ FILE: serde/Cargo.toml ================================================ [package] name = "serde" version = "1.0.228" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] description = "A generic serialization/deserialization framework" documentation = "https://docs.rs/serde" edition = "2021" homepage = "https://serde.rs" keywords = ["serde", "serialization", "no_std"] license = "MIT OR Apache-2.0" readme = "crates-io.md" repository = "https://github.com/serde-rs/serde" rust-version = "1.56" [dependencies] serde_core = { version = "=1.0.228", path = "../serde_core", default-features = false, features = ["result"] } serde_derive = { version = "1", optional = true, path = "../serde_derive" } [package.metadata.playground] features = ["derive", "rc"] [package.metadata.docs.rs] features = ["derive", "rc", "unstable"] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = [ "--generate-link-to-definition", "--generate-macro-expansion", "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", ] ### FEATURES ################################################################# [features] default = ["std"] # Provide derive(Serialize, Deserialize) macros. derive = ["serde_derive"] # Provide impls for common standard library types like Vec and HashMap. # Requires a dependency on the Rust standard library. std = ["serde_core/std"] # Provide impls for types that require unstable functionality. For tracking and # discussion of unstable functionality please refer to this issue: # # https://github.com/serde-rs/serde/issues/812 unstable = ["serde_core/unstable"] # Provide impls for types in the Rust core allocation and collections library # including String, Box, Vec, and Cow. This is a subset of std but may # be enabled without depending on all of std. alloc = ["serde_core/alloc"] # Opt into impls for Rc and Arc. Serializing and deserializing these types # does not preserve identity and may result in multiple copies of the same data. # Be sure that this is what you want before enabling this feature. rc = ["serde_core/rc"] ================================================ FILE: serde/build.rs ================================================ use std::env; use std::fs; use std::path::PathBuf; use std::process::Command; use std::str; const PRIVATE: &str = "\ #[doc(hidden)] pub mod __private$$ { #[doc(hidden)] pub use crate::private::*; } use serde_core::__private$$ as serde_core_private; "; // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable // these cfgs other than by executing our build script. fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rustc-cfg=if_docsrs_then_no_serde_core"); let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let patch_version = env::var("CARGO_PKG_VERSION_PATCH").unwrap(); let module = PRIVATE.replace("$$", &patch_version); fs::write(out_dir.join("private.rs"), module).unwrap(); let minor = match rustc_minor_version() { Some(minor) => minor, None => return, }; if minor >= 77 { println!("cargo:rustc-check-cfg=cfg(feature, values(\"result\"))"); println!("cargo:rustc-check-cfg=cfg(if_docsrs_then_no_serde_core)"); println!("cargo:rustc-check-cfg=cfg(no_core_cstr)"); println!("cargo:rustc-check-cfg=cfg(no_core_error)"); println!("cargo:rustc-check-cfg=cfg(no_core_net)"); println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); println!("cargo:rustc-check-cfg=cfg(no_serde_derive)"); println!("cargo:rustc-check-cfg=cfg(no_std_atomic)"); println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)"); println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)"); } // Current minimum supported version of serde_derive crate is Rust 1.71. if minor < 71 { println!("cargo:rustc-cfg=no_serde_derive"); } // Support for the `#[diagnostic]` tool attribute namespace // https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes if minor < 78 { println!("cargo:rustc-cfg=no_diagnostic_namespace"); } } fn rustc_minor_version() -> Option { let rustc = env::var_os("RUSTC")?; let output = Command::new(rustc).arg("--version").output().ok()?; let version = str::from_utf8(&output.stdout).ok()?; let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } pieces.next()?.parse().ok() } ================================================ FILE: serde/src/integer128.rs ================================================ #[macro_export] #[deprecated = " This macro has no effect on any version of Serde released in the past 2 years. It was used long ago in crates that needed to support Rustc older than 1.26.0, or Emscripten targets older than 1.40.0, which did not yet have 128-bit integer support. These days Serde requires a Rust compiler newer than that so 128-bit integers are always supported. "] #[doc(hidden)] macro_rules! serde_if_integer128 { ($($tt:tt)*) => { $($tt)* }; } ================================================ FILE: serde/src/lib.rs ================================================ //! # Serde //! //! Serde is a framework for ***ser***ializing and ***de***serializing Rust data //! structures efficiently and generically. //! //! The Serde ecosystem consists of data structures that know how to serialize //! and deserialize themselves along with data formats that know how to //! serialize and deserialize other things. Serde provides the layer by which //! these two groups interact with each other, allowing any supported data //! structure to be serialized and deserialized using any supported data format. //! //! See the Serde website for additional documentation and //! usage examples. //! //! ## Design //! //! Where many other languages rely on runtime reflection for serializing data, //! Serde is instead built on Rust's powerful trait system. A data structure //! that knows how to serialize and deserialize itself is one that implements //! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive //! attribute to automatically generate implementations at compile time). This //! avoids any overhead of reflection or runtime type information. In fact in //! many situations the interaction between data structure and data format can //! be completely optimized away by the Rust compiler, leaving Serde //! serialization to perform the same speed as a handwritten serializer for the //! specific selection of data structure and data format. //! //! ## Data formats //! //! The following is a partial list of data formats that have been implemented //! for Serde by the community. //! //! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs. //! - [Postcard], a no\_std and embedded-systems friendly compact binary format. //! - [CBOR], a Concise Binary Object Representation designed for small message //! size without the need for version negotiation. //! - [YAML], a self-proclaimed human-friendly configuration language that ain't //! markup language. //! - [MessagePack], an efficient binary format that resembles a compact JSON. //! - [TOML], a minimal configuration format used by [Cargo]. //! - [Pickle], a format common in the Python world. //! - [RON], a Rusty Object Notation. //! - [BSON], the data storage and network transfer format used by MongoDB. //! - [Avro], a binary format used within Apache Hadoop, with support for schema //! definition. //! - [JSON5], a superset of JSON including some productions from ES5. //! - [URL] query strings, in the x-www-form-urlencoded format. //! - [Starlark], the format used for describing build targets by the Bazel and //! Buck build systems. *(serialization only)* //! - [Envy], a way to deserialize environment variables into Rust structs. //! *(deserialization only)* //! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into //! Rust structs. *(deserialization only)* //! - [S-expressions], the textual representation of code and data used by the //! Lisp language family. //! - [D-Bus]'s binary wire format. //! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy //! serialization format. //! - [Bencode], a simple binary format used in the BitTorrent protocol. //! - [Token streams], for processing Rust procedural macro input. //! *(deserialization only)* //! - [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to //! and from DynamoDB. //! - [Hjson], a syntax extension to JSON designed around human reading and //! editing. *(deserialization only)* //! - [CSV], Comma-separated values is a tabular text file format. //! //! [JSON]: https://github.com/serde-rs/json //! [Postcard]: https://github.com/jamesmunns/postcard //! [CBOR]: https://github.com/enarx/ciborium //! [YAML]: https://github.com/dtolnay/serde-yaml //! [MessagePack]: https://github.com/3Hren/msgpack-rust //! [TOML]: https://docs.rs/toml //! [Pickle]: https://github.com/birkenfeld/serde-pickle //! [RON]: https://github.com/ron-rs/ron //! [BSON]: https://github.com/mongodb/bson-rust //! [Avro]: https://docs.rs/apache-avro //! [JSON5]: https://github.com/callum-oakley/json5-rs //! [URL]: https://docs.rs/serde_qs //! [Starlark]: https://github.com/dtolnay/serde-starlark //! [Envy]: https://github.com/softprops/envy //! [Envy Store]: https://github.com/softprops/envy-store //! [Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html //! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html //! [S-expressions]: https://github.com/rotty/lexpr-rs //! [D-Bus]: https://docs.rs/zvariant //! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers //! [Bencode]: https://github.com/P3KI/bendy //! [Token streams]: https://github.com/oxidecomputer/serde_tokenstream //! [DynamoDB Items]: https://docs.rs/serde_dynamo //! [rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb //! [Hjson]: https://github.com/Canop/deser-hjson //! [CSV]: https://docs.rs/csv //////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. #![doc(html_root_url = "https://docs.rs/serde/1.0.228")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. #![cfg_attr(docsrs, feature(doc_cfg, rustdoc_internals))] #![cfg_attr(docsrs, allow(internal_features))] // Unstable functionality only if the user asks for it. For tracking and // discussion of these features please refer to this issue: // // https://github.com/serde-rs/serde/issues/812 #![cfg_attr(all(feature = "unstable", docsrs), feature(never_type))] #![allow( unknown_lints, bare_trait_objects, deprecated, mismatched_lifetime_syntaxes )] // Ignored clippy and clippy_pedantic lints #![allow( // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 clippy::unnested_or_patterns, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768 clippy::semicolon_if_nothing_returned, // not available in our oldest supported compiler clippy::empty_enums, clippy::type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772 // integer and float ser/de requires these sorts of casts clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_sign_loss, // things are often more readable this way clippy::cast_lossless, clippy::module_name_repetitions, clippy::single_match_else, clippy::type_complexity, clippy::use_self, clippy::zero_prefixed_literal, // correctly used clippy::derive_partial_eq_without_eq, clippy::enum_glob_use, clippy::explicit_auto_deref, clippy::incompatible_msrv, clippy::let_underscore_untyped, clippy::map_err_ignore, clippy::new_without_default, clippy::result_unit_err, clippy::wildcard_imports, // not practical clippy::needless_pass_by_value, clippy::similar_names, clippy::too_many_lines, // preference clippy::doc_markdown, clippy::elidable_lifetime_names, clippy::needless_lifetimes, clippy::unseparated_literal_suffix, // false positive clippy::needless_doctest_main, // noisy clippy::missing_errors_doc, clippy::must_use_candidate, )] // Restrictions #![deny(clippy::question_mark_used)] // Rustc lints. #![deny(missing_docs, unused_imports)] //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "alloc")] extern crate alloc; // Rustdoc has a lot of shortcomings related to cross-crate re-exports that make // the rendered documentation of serde_core traits in serde more challenging to // understand than the equivalent documentation of the same items in serde_core. // https://github.com/rust-lang/rust/labels/A-cross-crate-reexports // So, just for the purpose of docs.rs documentation, we inline the contents of // serde_core into serde. This sidesteps all the cross-crate rustdoc bugs. #[cfg(docsrs)] #[macro_use] #[path = "core/crate_root.rs"] mod crate_root; #[cfg(docsrs)] #[macro_use] #[path = "core/macros.rs"] mod macros; #[cfg(not(docsrs))] macro_rules! crate_root { () => { /// A facade around all the types we need from the `std`, `core`, and `alloc` /// crates. This avoids elaborate import wrangling having to happen in every /// module. mod lib { mod core { #[cfg(not(feature = "std"))] pub use core::*; #[cfg(feature = "std")] pub use std::*; } pub use self::core::{f32, f64}; pub use self::core::{ptr, str}; #[cfg(any(feature = "std", feature = "alloc"))] pub use self::core::slice; pub use self::core::clone; pub use self::core::convert; pub use self::core::default; pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite}; pub use self::core::marker::{self, PhantomData}; pub use self::core::option; pub use self::core::result; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::borrow::{Cow, ToOwned}; #[cfg(feature = "std")] pub use std::borrow::{Cow, ToOwned}; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::string::{String, ToString}; #[cfg(feature = "std")] pub use std::string::{String, ToString}; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::vec::Vec; #[cfg(feature = "std")] pub use std::vec::Vec; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::boxed::Box; #[cfg(feature = "std")] pub use std::boxed::Box; } // None of this crate's error handling needs the `From::from` error conversion // performed implicitly by the `?` operator or the standard library's `try!` // macro. This simplified macro gives a 5.5% improvement in compile time // compared to standard `try!`, and 9% improvement compared to `?`. #[cfg(not(no_serde_derive))] macro_rules! tri { ($expr:expr) => { match $expr { Ok(val) => val, Err(err) => return Err(err), } }; } //////////////////////////////////////////////////////////////////////////////// pub use serde_core::{ de, forward_to_deserialize_any, ser, Deserialize, Deserializer, Serialize, Serializer, }; // Used by generated code and doc tests. Not public API. #[doc(hidden)] mod private; include!(concat!(env!("OUT_DIR"), "/private.rs")); }; } crate_root!(); mod integer128; // Re-export #[derive(Serialize, Deserialize)]. // // The reason re-exporting is not enabled by default is that disabling it would // be annoying for crates that provide handwritten impls or data formats. They // would need to disable default features and then explicitly re-enable std. #[cfg(feature = "serde_derive")] extern crate serde_derive; /// Derive macro available if serde is built with `features = ["derive"]`. #[cfg(feature = "serde_derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use serde_derive::{Deserialize, Serialize}; #[macro_export] #[doc(hidden)] macro_rules! __require_serde_not_serde_core { () => {}; } ================================================ FILE: serde/src/private/de.rs ================================================ use crate::lib::*; use crate::de::value::{BorrowedBytesDeserializer, BytesDeserializer}; use crate::de::{ Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, IntoDeserializer, VariantAccess, Visitor, }; #[cfg(any(feature = "std", feature = "alloc"))] use crate::de::{MapAccess, Unexpected}; #[cfg(any(feature = "std", feature = "alloc"))] pub use self::content::{ content_as_str, Content, ContentDeserializer, ContentRefDeserializer, ContentVisitor, EnumDeserializer, InternallyTaggedUnitVisitor, TagContentOtherField, TagContentOtherFieldVisitor, TagOrContentField, TagOrContentFieldVisitor, TaggedContentVisitor, UntaggedUnitVisitor, }; pub use crate::serde_core_private::InPlaceSeed; /// If the missing field is of type `Option` then treat is as `None`, /// otherwise it is an error. pub fn missing_field<'de, V, E>(field: &'static str) -> Result where V: Deserialize<'de>, E: Error, { struct MissingFieldDeserializer(&'static str, PhantomData); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> Deserializer<'de> for MissingFieldDeserializer where E: Error, { type Error = E; fn deserialize_any(self, _visitor: V) -> Result where V: Visitor<'de>, { Err(Error::missing_field(self.0)) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_none() } serde_core::forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } let deserializer = MissingFieldDeserializer(field, PhantomData); Deserialize::deserialize(deserializer) } #[cfg(any(feature = "std", feature = "alloc"))] pub fn borrow_cow_str<'de: 'a, 'a, D, R>(deserializer: D) -> Result where D: Deserializer<'de>, R: From>, { struct CowStrVisitor; #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a> Visitor<'a> for CowStrVisitor { type Value = Cow<'a, str>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string") } fn visit_str(self, v: &str) -> Result where E: Error, { Ok(Cow::Owned(v.to_owned())) } fn visit_borrowed_str(self, v: &'a str) -> Result where E: Error, { Ok(Cow::Borrowed(v)) } fn visit_string(self, v: String) -> Result where E: Error, { Ok(Cow::Owned(v)) } fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { match str::from_utf8(v) { Ok(s) => Ok(Cow::Owned(s.to_owned())), Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), } } fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result where E: Error, { match str::from_utf8(v) { Ok(s) => Ok(Cow::Borrowed(s)), Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), } } fn visit_byte_buf(self, v: Vec) -> Result where E: Error, { match String::from_utf8(v) { Ok(s) => Ok(Cow::Owned(s)), Err(e) => Err(Error::invalid_value( Unexpected::Bytes(&e.into_bytes()), &self, )), } } } deserializer.deserialize_str(CowStrVisitor).map(From::from) } #[cfg(any(feature = "std", feature = "alloc"))] pub fn borrow_cow_bytes<'de: 'a, 'a, D, R>(deserializer: D) -> Result where D: Deserializer<'de>, R: From>, { struct CowBytesVisitor; #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a> Visitor<'a> for CowBytesVisitor { type Value = Cow<'a, [u8]>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a byte array") } fn visit_str(self, v: &str) -> Result where E: Error, { Ok(Cow::Owned(v.as_bytes().to_vec())) } fn visit_borrowed_str(self, v: &'a str) -> Result where E: Error, { Ok(Cow::Borrowed(v.as_bytes())) } fn visit_string(self, v: String) -> Result where E: Error, { Ok(Cow::Owned(v.into_bytes())) } fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { Ok(Cow::Owned(v.to_vec())) } fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result where E: Error, { Ok(Cow::Borrowed(v)) } fn visit_byte_buf(self, v: Vec) -> Result where E: Error, { Ok(Cow::Owned(v)) } } deserializer .deserialize_bytes(CowBytesVisitor) .map(From::from) } #[cfg(any(feature = "std", feature = "alloc"))] mod content { // This module is private and nothing here should be used outside of // generated code. // // We will iterate on the implementation for a few releases and only have to // worry about backward compatibility for the `untagged` and `tag` attributes // rather than for this entire mechanism. // // This issue is tracking making some of this stuff public: // https://github.com/serde-rs/serde/issues/741 use crate::lib::*; use crate::de::{ self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Expected, IgnoredAny, MapAccess, SeqAccess, Unexpected, Visitor, }; use crate::serde_core_private::size_hint; pub use crate::serde_core_private::Content; pub fn content_as_str<'a, 'de>(content: &'a Content<'de>) -> Option<&'a str> { match *content { Content::Str(x) => Some(x), Content::String(ref x) => Some(x), Content::Bytes(x) => str::from_utf8(x).ok(), Content::ByteBuf(ref x) => str::from_utf8(x).ok(), _ => None, } } fn content_clone<'de>(content: &Content<'de>) -> Content<'de> { match content { Content::Bool(b) => Content::Bool(*b), Content::U8(n) => Content::U8(*n), Content::U16(n) => Content::U16(*n), Content::U32(n) => Content::U32(*n), Content::U64(n) => Content::U64(*n), Content::I8(n) => Content::I8(*n), Content::I16(n) => Content::I16(*n), Content::I32(n) => Content::I32(*n), Content::I64(n) => Content::I64(*n), Content::F32(f) => Content::F32(*f), Content::F64(f) => Content::F64(*f), Content::Char(c) => Content::Char(*c), Content::String(s) => Content::String(s.clone()), Content::Str(s) => Content::Str(*s), Content::ByteBuf(b) => Content::ByteBuf(b.clone()), Content::Bytes(b) => Content::Bytes(b), Content::None => Content::None, Content::Some(content) => Content::Some(Box::new(content_clone(content))), Content::Unit => Content::Unit, Content::Newtype(content) => Content::Newtype(Box::new(content_clone(content))), Content::Seq(seq) => Content::Seq(seq.iter().map(content_clone).collect()), Content::Map(map) => Content::Map( map.iter() .map(|(k, v)| (content_clone(k), content_clone(v))) .collect(), ), } } #[cold] fn content_unexpected<'a, 'de>(content: &'a Content<'de>) -> Unexpected<'a> { match *content { Content::Bool(b) => Unexpected::Bool(b), Content::U8(n) => Unexpected::Unsigned(n as u64), Content::U16(n) => Unexpected::Unsigned(n as u64), Content::U32(n) => Unexpected::Unsigned(n as u64), Content::U64(n) => Unexpected::Unsigned(n), Content::I8(n) => Unexpected::Signed(n as i64), Content::I16(n) => Unexpected::Signed(n as i64), Content::I32(n) => Unexpected::Signed(n as i64), Content::I64(n) => Unexpected::Signed(n), Content::F32(f) => Unexpected::Float(f as f64), Content::F64(f) => Unexpected::Float(f), Content::Char(c) => Unexpected::Char(c), Content::String(ref s) => Unexpected::Str(s), Content::Str(s) => Unexpected::Str(s), Content::ByteBuf(ref b) => Unexpected::Bytes(b), Content::Bytes(b) => Unexpected::Bytes(b), Content::None | Content::Some(_) => Unexpected::Option, Content::Unit => Unexpected::Unit, Content::Newtype(_) => Unexpected::NewtypeStruct, Content::Seq(_) => Unexpected::Seq, Content::Map(_) => Unexpected::Map, } } pub struct ContentVisitor<'de> { value: PhantomData>, } impl<'de> ContentVisitor<'de> { pub fn new() -> Self { ContentVisitor { value: PhantomData } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de> DeserializeSeed<'de> for ContentVisitor<'de> { type Value = Content<'de>; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.__deserialize_content_v1(self) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de> Visitor<'de> for ContentVisitor<'de> { type Value = Content<'de>; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str("any value") } fn visit_bool(self, value: bool) -> Result where F: de::Error, { Ok(Content::Bool(value)) } fn visit_i8(self, value: i8) -> Result where F: de::Error, { Ok(Content::I8(value)) } fn visit_i16(self, value: i16) -> Result where F: de::Error, { Ok(Content::I16(value)) } fn visit_i32(self, value: i32) -> Result where F: de::Error, { Ok(Content::I32(value)) } fn visit_i64(self, value: i64) -> Result where F: de::Error, { Ok(Content::I64(value)) } fn visit_u8(self, value: u8) -> Result where F: de::Error, { Ok(Content::U8(value)) } fn visit_u16(self, value: u16) -> Result where F: de::Error, { Ok(Content::U16(value)) } fn visit_u32(self, value: u32) -> Result where F: de::Error, { Ok(Content::U32(value)) } fn visit_u64(self, value: u64) -> Result where F: de::Error, { Ok(Content::U64(value)) } fn visit_f32(self, value: f32) -> Result where F: de::Error, { Ok(Content::F32(value)) } fn visit_f64(self, value: f64) -> Result where F: de::Error, { Ok(Content::F64(value)) } fn visit_char(self, value: char) -> Result where F: de::Error, { Ok(Content::Char(value)) } fn visit_str(self, value: &str) -> Result where F: de::Error, { Ok(Content::String(value.into())) } fn visit_borrowed_str(self, value: &'de str) -> Result where F: de::Error, { Ok(Content::Str(value)) } fn visit_string(self, value: String) -> Result where F: de::Error, { Ok(Content::String(value)) } fn visit_bytes(self, value: &[u8]) -> Result where F: de::Error, { Ok(Content::ByteBuf(value.into())) } fn visit_borrowed_bytes(self, value: &'de [u8]) -> Result where F: de::Error, { Ok(Content::Bytes(value)) } fn visit_byte_buf(self, value: Vec) -> Result where F: de::Error, { Ok(Content::ByteBuf(value)) } fn visit_unit(self) -> Result where F: de::Error, { Ok(Content::Unit) } fn visit_none(self) -> Result where F: de::Error, { Ok(Content::None) } fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { let v = tri!(ContentVisitor::new().deserialize(deserializer)); Ok(Content::Some(Box::new(v))) } fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer<'de>, { let v = tri!(ContentVisitor::new().deserialize(deserializer)); Ok(Content::Newtype(Box::new(v))) } fn visit_seq(self, mut visitor: V) -> Result where V: SeqAccess<'de>, { let mut vec = Vec::::with_capacity(size_hint::cautious::(visitor.size_hint())); while let Some(e) = tri!(visitor.next_element_seed(ContentVisitor::new())) { vec.push(e); } Ok(Content::Seq(vec)) } fn visit_map(self, mut visitor: V) -> Result where V: MapAccess<'de>, { let mut vec = Vec::<(Content, Content)>::with_capacity( size_hint::cautious::<(Content, Content)>(visitor.size_hint()), ); while let Some(kv) = tri!(visitor.next_entry_seed(ContentVisitor::new(), ContentVisitor::new())) { vec.push(kv); } Ok(Content::Map(vec)) } fn visit_enum(self, _visitor: V) -> Result where V: EnumAccess<'de>, { Err(de::Error::custom( "untagged and internally tagged enums do not support enum input", )) } } /// This is the type of the map keys in an internally tagged enum. /// /// Not public API. pub enum TagOrContent<'de> { Tag, Content(Content<'de>), } /// Serves as a seed for deserializing a key of internally tagged enum. /// Cannot capture externally tagged enums, `i128` and `u128`. struct TagOrContentVisitor<'de> { name: &'static str, value: PhantomData>, } impl<'de> TagOrContentVisitor<'de> { fn new(name: &'static str) -> Self { TagOrContentVisitor { name, value: PhantomData, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de> DeserializeSeed<'de> for TagOrContentVisitor<'de> { type Value = TagOrContent<'de>; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { // Internally tagged enums are only supported in self-describing // formats. deserializer.deserialize_any(self) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de> Visitor<'de> for TagOrContentVisitor<'de> { type Value = TagOrContent<'de>; fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "a type tag `{}` or any other value", self.name) } fn visit_bool(self, value: bool) -> Result where F: de::Error, { ContentVisitor::new() .visit_bool(value) .map(TagOrContent::Content) } fn visit_i8(self, value: i8) -> Result where F: de::Error, { ContentVisitor::new() .visit_i8(value) .map(TagOrContent::Content) } fn visit_i16(self, value: i16) -> Result where F: de::Error, { ContentVisitor::new() .visit_i16(value) .map(TagOrContent::Content) } fn visit_i32(self, value: i32) -> Result where F: de::Error, { ContentVisitor::new() .visit_i32(value) .map(TagOrContent::Content) } fn visit_i64(self, value: i64) -> Result where F: de::Error, { ContentVisitor::new() .visit_i64(value) .map(TagOrContent::Content) } fn visit_u8(self, value: u8) -> Result where F: de::Error, { ContentVisitor::new() .visit_u8(value) .map(TagOrContent::Content) } fn visit_u16(self, value: u16) -> Result where F: de::Error, { ContentVisitor::new() .visit_u16(value) .map(TagOrContent::Content) } fn visit_u32(self, value: u32) -> Result where F: de::Error, { ContentVisitor::new() .visit_u32(value) .map(TagOrContent::Content) } fn visit_u64(self, value: u64) -> Result where F: de::Error, { ContentVisitor::new() .visit_u64(value) .map(TagOrContent::Content) } fn visit_f32(self, value: f32) -> Result where F: de::Error, { ContentVisitor::new() .visit_f32(value) .map(TagOrContent::Content) } fn visit_f64(self, value: f64) -> Result where F: de::Error, { ContentVisitor::new() .visit_f64(value) .map(TagOrContent::Content) } fn visit_char(self, value: char) -> Result where F: de::Error, { ContentVisitor::new() .visit_char(value) .map(TagOrContent::Content) } fn visit_str(self, value: &str) -> Result where F: de::Error, { if value == self.name { Ok(TagOrContent::Tag) } else { ContentVisitor::new() .visit_str(value) .map(TagOrContent::Content) } } fn visit_borrowed_str(self, value: &'de str) -> Result where F: de::Error, { if value == self.name { Ok(TagOrContent::Tag) } else { ContentVisitor::new() .visit_borrowed_str(value) .map(TagOrContent::Content) } } fn visit_string(self, value: String) -> Result where F: de::Error, { if value == self.name { Ok(TagOrContent::Tag) } else { ContentVisitor::new() .visit_string(value) .map(TagOrContent::Content) } } fn visit_bytes(self, value: &[u8]) -> Result where F: de::Error, { if value == self.name.as_bytes() { Ok(TagOrContent::Tag) } else { ContentVisitor::new() .visit_bytes(value) .map(TagOrContent::Content) } } fn visit_borrowed_bytes(self, value: &'de [u8]) -> Result where F: de::Error, { if value == self.name.as_bytes() { Ok(TagOrContent::Tag) } else { ContentVisitor::new() .visit_borrowed_bytes(value) .map(TagOrContent::Content) } } fn visit_byte_buf(self, value: Vec) -> Result where F: de::Error, { if value == self.name.as_bytes() { Ok(TagOrContent::Tag) } else { ContentVisitor::new() .visit_byte_buf(value) .map(TagOrContent::Content) } } fn visit_unit(self) -> Result where F: de::Error, { ContentVisitor::new() .visit_unit() .map(TagOrContent::Content) } fn visit_none(self) -> Result where F: de::Error, { ContentVisitor::new() .visit_none() .map(TagOrContent::Content) } fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { ContentVisitor::new() .visit_some(deserializer) .map(TagOrContent::Content) } fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer<'de>, { ContentVisitor::new() .visit_newtype_struct(deserializer) .map(TagOrContent::Content) } fn visit_seq(self, visitor: V) -> Result where V: SeqAccess<'de>, { ContentVisitor::new() .visit_seq(visitor) .map(TagOrContent::Content) } fn visit_map(self, visitor: V) -> Result where V: MapAccess<'de>, { ContentVisitor::new() .visit_map(visitor) .map(TagOrContent::Content) } fn visit_enum(self, visitor: V) -> Result where V: EnumAccess<'de>, { ContentVisitor::new() .visit_enum(visitor) .map(TagOrContent::Content) } } /// Used by generated code to deserialize an internally tagged enum. /// /// Captures map or sequence from the original deserializer and searches /// a tag in it (in case of sequence, tag is the first element of sequence). /// /// Not public API. pub struct TaggedContentVisitor { tag_name: &'static str, expecting: &'static str, value: PhantomData, } impl TaggedContentVisitor { /// Visitor for the content of an internally tagged enum with the given /// tag name. pub fn new(name: &'static str, expecting: &'static str) -> Self { TaggedContentVisitor { tag_name: name, expecting, value: PhantomData, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, T> Visitor<'de> for TaggedContentVisitor where T: Deserialize<'de>, { type Value = (T, Content<'de>); fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.write_str(self.expecting) } fn visit_seq(self, mut seq: S) -> Result where S: SeqAccess<'de>, { let tag = match tri!(seq.next_element()) { Some(tag) => tag, None => { return Err(de::Error::missing_field(self.tag_name)); } }; let rest = de::value::SeqAccessDeserializer::new(seq); Ok((tag, tri!(ContentVisitor::new().deserialize(rest)))) } fn visit_map(self, mut map: M) -> Result where M: MapAccess<'de>, { let mut tag = None; let mut vec = Vec::<(Content, Content)>::with_capacity(size_hint::cautious::<( Content, Content, )>(map.size_hint())); while let Some(k) = tri!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { match k { TagOrContent::Tag => { if tag.is_some() { return Err(de::Error::duplicate_field(self.tag_name)); } tag = Some(tri!(map.next_value())); } TagOrContent::Content(k) => { let v = tri!(map.next_value_seed(ContentVisitor::new())); vec.push((k, v)); } } } match tag { None => Err(de::Error::missing_field(self.tag_name)), Some(tag) => Ok((tag, Content::Map(vec))), } } } /// Used by generated code to deserialize an adjacently tagged enum. /// /// Not public API. pub enum TagOrContentField { Tag, Content, } /// Not public API. pub struct TagOrContentFieldVisitor { /// Name of the tag field of the adjacently tagged enum pub tag: &'static str, /// Name of the content field of the adjacently tagged enum pub content: &'static str, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de> DeserializeSeed<'de> for TagOrContentFieldVisitor { type Value = TagOrContentField; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_identifier(self) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de> Visitor<'de> for TagOrContentFieldVisitor { type Value = TagOrContentField; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:?} or {:?}", self.tag, self.content) } fn visit_u64(self, field_index: u64) -> Result where E: de::Error, { match field_index { 0 => Ok(TagOrContentField::Tag), 1 => Ok(TagOrContentField::Content), _ => Err(de::Error::invalid_value( Unexpected::Unsigned(field_index), &self, )), } } fn visit_str(self, field: &str) -> Result where E: de::Error, { if field == self.tag { Ok(TagOrContentField::Tag) } else if field == self.content { Ok(TagOrContentField::Content) } else { Err(de::Error::invalid_value(Unexpected::Str(field), &self)) } } fn visit_bytes(self, field: &[u8]) -> Result where E: de::Error, { if field == self.tag.as_bytes() { Ok(TagOrContentField::Tag) } else if field == self.content.as_bytes() { Ok(TagOrContentField::Content) } else { Err(de::Error::invalid_value(Unexpected::Bytes(field), &self)) } } } /// Used by generated code to deserialize an adjacently tagged enum when /// ignoring unrelated fields is allowed. /// /// Not public API. pub enum TagContentOtherField { Tag, Content, Other, } /// Not public API. pub struct TagContentOtherFieldVisitor { /// Name of the tag field of the adjacently tagged enum pub tag: &'static str, /// Name of the content field of the adjacently tagged enum pub content: &'static str, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de> DeserializeSeed<'de> for TagContentOtherFieldVisitor { type Value = TagContentOtherField; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_identifier(self) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de> Visitor<'de> for TagContentOtherFieldVisitor { type Value = TagContentOtherField; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!( formatter, "{:?}, {:?}, or other ignored fields", self.tag, self.content ) } fn visit_u64(self, field_index: u64) -> Result where E: de::Error, { match field_index { 0 => Ok(TagContentOtherField::Tag), 1 => Ok(TagContentOtherField::Content), _ => Ok(TagContentOtherField::Other), } } fn visit_str(self, field: &str) -> Result where E: de::Error, { self.visit_bytes(field.as_bytes()) } fn visit_bytes(self, field: &[u8]) -> Result where E: de::Error, { if field == self.tag.as_bytes() { Ok(TagContentOtherField::Tag) } else if field == self.content.as_bytes() { Ok(TagContentOtherField::Content) } else { Ok(TagContentOtherField::Other) } } } /// Not public API pub struct ContentDeserializer<'de, E> { content: Content<'de>, err: PhantomData, } impl<'de, E> ContentDeserializer<'de, E> where E: de::Error, { #[cold] fn invalid_type(self, exp: &dyn Expected) -> E { de::Error::invalid_type(content_unexpected(&self.content), exp) } fn deserialize_integer(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::U8(v) => visitor.visit_u8(v), Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_float(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::F32(v) => visitor.visit_f32(v), Content::F64(v) => visitor.visit_f64(v), Content::U8(v) => visitor.visit_u8(v), Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), _ => Err(self.invalid_type(&visitor)), } } } fn visit_content_seq<'de, V, E>(content: Vec>, visitor: V) -> Result where V: Visitor<'de>, E: de::Error, { let mut seq_visitor = SeqDeserializer::new(content); let value = tri!(visitor.visit_seq(&mut seq_visitor)); tri!(seq_visitor.end()); Ok(value) } fn visit_content_map<'de, V, E>( content: Vec<(Content<'de>, Content<'de>)>, visitor: V, ) -> Result where V: Visitor<'de>, E: de::Error, { let mut map_visitor = MapDeserializer::new(content); let value = tri!(visitor.visit_map(&mut map_visitor)); tri!(map_visitor.end()); Ok(value) } /// Used when deserializing an internally tagged enum because the content /// will be used exactly once. #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E> where E: de::Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::Bool(v) => visitor.visit_bool(v), Content::U8(v) => visitor.visit_u8(v), Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), Content::F32(v) => visitor.visit_f32(v), Content::F64(v) => visitor.visit_f64(v), Content::Char(v) => visitor.visit_char(v), Content::String(v) => visitor.visit_string(v), Content::Str(v) => visitor.visit_borrowed_str(v), Content::ByteBuf(v) => visitor.visit_byte_buf(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::Unit => visitor.visit_unit(), Content::None => visitor.visit_none(), Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)), Content::Seq(v) => visit_content_seq(v, visitor), Content::Map(v) => visit_content_map(v, visitor), } } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::Bool(v) => visitor.visit_bool(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_float(visitor) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_float(visitor) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::Char(v) => visitor.visit_char(v), Content::String(v) => visitor.visit_string(v), Content::Str(v) => visitor.visit_borrowed_str(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_string(visitor) } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::String(v) => visitor.visit_string(v), Content::Str(v) => visitor.visit_borrowed_str(v), Content::ByteBuf(v) => visitor.visit_byte_buf(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_byte_buf(visitor) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::String(v) => visitor.visit_string(v), Content::Str(v) => visitor.visit_borrowed_str(v), Content::ByteBuf(v) => visitor.visit_byte_buf(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::Seq(v) => visit_content_seq(v, visitor), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::None => visitor.visit_none(), Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), Content::Unit => visitor.visit_unit(), _ => visitor.visit_some(self), } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::Unit => visitor.visit_unit(), // Allow deserializing newtype variant containing unit. // // #[derive(Deserialize)] // #[serde(tag = "result")] // enum Response { // Success(T), // } // // We want {"result":"Success"} to deserialize into Response<()>. Content::Map(ref v) if v.is_empty() => visitor.visit_unit(), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_unit_struct( self, _name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { match self.content { // As a special case, allow deserializing untagged newtype // variant containing unit struct. // // #[derive(Deserialize)] // struct Info; // // #[derive(Deserialize)] // #[serde(tag = "topic")] // enum Message { // Info(Info), // } // // We want {"topic":"Info"} to deserialize even though // ordinarily unit structs do not deserialize from empty map/seq. Content::Map(ref v) if v.is_empty() => visitor.visit_unit(), Content::Seq(ref v) if v.is_empty() => visitor.visit_unit(), _ => self.deserialize_any(visitor), } } fn deserialize_newtype_struct( self, _name: &str, visitor: V, ) -> Result where V: Visitor<'de>, { match self.content { Content::Newtype(v) => visitor.visit_newtype_struct(ContentDeserializer::new(*v)), _ => visitor.visit_newtype_struct(self), } } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::Seq(v) => visit_content_seq(v, visitor), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_tuple(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_tuple_struct( self, _name: &'static str, _len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::Map(v) => visit_content_map(v, visitor), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_struct( self, _name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { match self.content { Content::Seq(v) => visit_content_seq(v, visitor), Content::Map(v) => visit_content_map(v, visitor), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_enum( self, _name: &str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let (variant, value) = match self.content { Content::Map(value) => { let mut iter = value.into_iter(); let (variant, value) = match iter.next() { Some(v) => v, None => { return Err(de::Error::invalid_value( de::Unexpected::Map, &"map with a single key", )); } }; // enums are encoded in json as maps with a single key:value pair if iter.next().is_some() { return Err(de::Error::invalid_value( de::Unexpected::Map, &"map with a single key", )); } (variant, Some(value)) } s @ Content::String(_) | s @ Content::Str(_) => (s, None), other => { return Err(de::Error::invalid_type( content_unexpected(&other), &"string or map", )); } }; visitor.visit_enum(EnumDeserializer::new(variant, value)) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { match self.content { Content::String(v) => visitor.visit_string(v), Content::Str(v) => visitor.visit_borrowed_str(v), Content::ByteBuf(v) => visitor.visit_byte_buf(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::U8(v) => visitor.visit_u8(v), Content::U64(v) => visitor.visit_u64(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { drop(self); visitor.visit_unit() } fn __deserialize_content_v1(self, visitor: V) -> Result where V: Visitor<'de, Value = Content<'de>>, { let _ = visitor; Ok(self.content) } } impl<'de, E> ContentDeserializer<'de, E> { /// private API, don't use pub fn new(content: Content<'de>) -> Self { ContentDeserializer { content, err: PhantomData, } } } struct SeqDeserializer<'de, E> { iter: > as IntoIterator>::IntoIter, count: usize, marker: PhantomData, } impl<'de, E> SeqDeserializer<'de, E> { fn new(content: Vec>) -> Self { SeqDeserializer { iter: content.into_iter(), count: 0, marker: PhantomData, } } } impl<'de, E> SeqDeserializer<'de, E> where E: de::Error, { fn end(self) -> Result<(), E> { let remaining = self.iter.count(); if remaining == 0 { Ok(()) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length( self.count + remaining, &ExpectedInSeq(self.count), )) } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> Deserializer<'de> for SeqDeserializer<'de, E> where E: de::Error, { type Error = E; fn deserialize_any(mut self, visitor: V) -> Result where V: Visitor<'de>, { let v = tri!(visitor.visit_seq(&mut self)); tri!(self.end()); Ok(v) } serde_core::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 } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> SeqAccess<'de> for SeqDeserializer<'de, E> where E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: V) -> Result, Self::Error> where V: DeserializeSeed<'de>, { match self.iter.next() { Some(value) => { self.count += 1; seed.deserialize(ContentDeserializer::new(value)).map(Some) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } struct ExpectedInSeq(usize); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Expected for ExpectedInSeq { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { formatter.write_str("1 element in sequence") } else { write!(formatter, "{} elements in sequence", self.0) } } } struct MapDeserializer<'de, E> { iter: , Content<'de>)> as IntoIterator>::IntoIter, value: Option>, count: usize, error: PhantomData, } impl<'de, E> MapDeserializer<'de, E> { fn new(content: Vec<(Content<'de>, Content<'de>)>) -> Self { MapDeserializer { iter: content.into_iter(), value: None, count: 0, error: PhantomData, } } } impl<'de, E> MapDeserializer<'de, E> where E: de::Error, { fn end(self) -> Result<(), E> { let remaining = self.iter.count(); if remaining == 0 { Ok(()) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length( self.count + remaining, &ExpectedInMap(self.count), )) } } } impl<'de, E> MapDeserializer<'de, E> { fn next_pair(&mut self) -> Option<(Content<'de>, Content<'de>)> { match self.iter.next() { Some((k, v)) => { self.count += 1; Some((k, v)) } None => None, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> Deserializer<'de> for MapDeserializer<'de, E> where E: de::Error, { type Error = E; fn deserialize_any(mut self, visitor: V) -> Result where V: Visitor<'de>, { let value = tri!(visitor.visit_map(&mut self)); tri!(self.end()); Ok(value) } fn deserialize_seq(mut self, visitor: V) -> Result where V: Visitor<'de>, { let value = tri!(visitor.visit_seq(&mut self)); tri!(self.end()); Ok(value) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { let _ = len; self.deserialize_seq(visitor) } serde_core::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 tuple_struct map struct enum identifier ignored_any } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> MapAccess<'de> for MapDeserializer<'de, E> where E: de::Error, { type Error = E; fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { match self.next_pair() { Some((key, value)) => { self.value = Some(value); seed.deserialize(ContentDeserializer::new(key)).map(Some) } None => Ok(None), } } fn next_value_seed(&mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { let value = self.value.take(); // Panic because this indicates a bug in the program rather than an // expected failure. let value = value.expect("MapAccess::next_value called before next_key"); seed.deserialize(ContentDeserializer::new(value)) } fn next_entry_seed( &mut self, kseed: TK, vseed: TV, ) -> Result, Self::Error> where TK: DeserializeSeed<'de>, TV: DeserializeSeed<'de>, { match self.next_pair() { Some((key, value)) => { let key = tri!(kseed.deserialize(ContentDeserializer::new(key))); let value = tri!(vseed.deserialize(ContentDeserializer::new(value))); Ok(Some((key, value))) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> SeqAccess<'de> for MapDeserializer<'de, E> where E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: de::DeserializeSeed<'de>, { match self.next_pair() { Some((k, v)) => { let de = PairDeserializer(k, v, PhantomData); seed.deserialize(de).map(Some) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } struct PairDeserializer<'de, E>(Content<'de>, Content<'de>, PhantomData); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> Deserializer<'de> for PairDeserializer<'de, E> where E: de::Error, { type Error = E; serde_core::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 tuple_struct map struct enum identifier ignored_any } fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData); let pair = tri!(visitor.visit_seq(&mut pair_visitor)); if pair_visitor.1.is_none() { Ok(pair) } else { let remaining = pair_visitor.size_hint().unwrap(); // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length(2, &ExpectedInSeq(2 - remaining))) } } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { if len == 2 { self.deserialize_seq(visitor) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length(2, &ExpectedInSeq(len))) } } } struct PairVisitor<'de, E>(Option>, Option>, PhantomData); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> SeqAccess<'de> for PairVisitor<'de, E> where E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { if let Some(k) = self.0.take() { seed.deserialize(ContentDeserializer::new(k)).map(Some) } else if let Some(v) = self.1.take() { seed.deserialize(ContentDeserializer::new(v)).map(Some) } else { Ok(None) } } fn size_hint(&self) -> Option { if self.0.is_some() { Some(2) } else if self.1.is_some() { Some(1) } else { Some(0) } } } struct ExpectedInMap(usize); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Expected for ExpectedInMap { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { formatter.write_str("1 element in map") } else { write!(formatter, "{} elements in map", self.0) } } } pub struct EnumDeserializer<'de, E> where E: de::Error, { variant: Content<'de>, value: Option>, err: PhantomData, } impl<'de, E> EnumDeserializer<'de, E> where E: de::Error, { pub fn new(variant: Content<'de>, value: Option>) -> EnumDeserializer<'de, E> { EnumDeserializer { variant, value, err: PhantomData, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<'de, E> where E: de::Error, { type Error = E; type Variant = VariantDeserializer<'de, Self::Error>; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), E> where V: de::DeserializeSeed<'de>, { let visitor = VariantDeserializer { value: self.value, err: PhantomData, }; seed.deserialize(ContentDeserializer::new(self.variant)) .map(|v| (v, visitor)) } } pub struct VariantDeserializer<'de, E> where E: de::Error, { value: Option>, err: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<'de, E> where E: de::Error, { type Error = E; fn unit_variant(self) -> Result<(), E> { match self.value { Some(value) => de::Deserialize::deserialize(ContentDeserializer::new(value)), None => Ok(()), } } fn newtype_variant_seed(self, seed: T) -> Result where T: de::DeserializeSeed<'de>, { match self.value { Some(value) => seed.deserialize(ContentDeserializer::new(value)), None => Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"newtype variant", )), } } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { match self.value { Some(Content::Seq(v)) => { de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) } Some(other) => Err(de::Error::invalid_type( content_unexpected(&other), &"tuple variant", )), None => Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"tuple variant", )), } } fn struct_variant( self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { match self.value { Some(Content::Map(v)) => { de::Deserializer::deserialize_any(MapDeserializer::new(v), visitor) } Some(Content::Seq(v)) => { de::Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) } Some(other) => Err(de::Error::invalid_type( content_unexpected(&other), &"struct variant", )), None => Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"struct variant", )), } } } /// Not public API. pub struct ContentRefDeserializer<'a, 'de: 'a, E> { content: &'a Content<'de>, err: PhantomData, } impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> where E: de::Error, { #[cold] fn invalid_type(self, exp: &dyn Expected) -> E { de::Error::invalid_type(content_unexpected(self.content), exp) } fn deserialize_integer(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::U8(v) => visitor.visit_u8(v), Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_float(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::F32(v) => visitor.visit_f32(v), Content::F64(v) => visitor.visit_f64(v), Content::U8(v) => visitor.visit_u8(v), Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), _ => Err(self.invalid_type(&visitor)), } } } fn visit_content_seq_ref<'a, 'de, V, E>( content: &'a [Content<'de>], visitor: V, ) -> Result where V: Visitor<'de>, E: de::Error, { let mut seq_visitor = SeqRefDeserializer::new(content); let value = tri!(visitor.visit_seq(&mut seq_visitor)); tri!(seq_visitor.end()); Ok(value) } fn visit_content_map_ref<'a, 'de, V, E>( content: &'a [(Content<'de>, Content<'de>)], visitor: V, ) -> Result where V: Visitor<'de>, E: de::Error, { let mut map_visitor = MapRefDeserializer::new(content); let value = tri!(visitor.visit_map(&mut map_visitor)); tri!(map_visitor.end()); Ok(value) } /// Used when deserializing an untagged enum because the content may need /// to be used more than once. #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::Bool(v) => visitor.visit_bool(v), Content::U8(v) => visitor.visit_u8(v), Content::U16(v) => visitor.visit_u16(v), Content::U32(v) => visitor.visit_u32(v), Content::U64(v) => visitor.visit_u64(v), Content::I8(v) => visitor.visit_i8(v), Content::I16(v) => visitor.visit_i16(v), Content::I32(v) => visitor.visit_i32(v), Content::I64(v) => visitor.visit_i64(v), Content::F32(v) => visitor.visit_f32(v), Content::F64(v) => visitor.visit_f64(v), Content::Char(v) => visitor.visit_char(v), Content::String(ref v) => visitor.visit_str(v), Content::Str(v) => visitor.visit_borrowed_str(v), Content::ByteBuf(ref v) => visitor.visit_bytes(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::Unit => visitor.visit_unit(), Content::None => visitor.visit_none(), Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), Content::Newtype(ref v) => { visitor.visit_newtype_struct(ContentRefDeserializer::new(v)) } Content::Seq(ref v) => visit_content_seq_ref(v, visitor), Content::Map(ref v) => visit_content_map_ref(v, visitor), } } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::Bool(v) => visitor.visit_bool(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_integer(visitor) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_float(visitor) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_float(visitor) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::Char(v) => visitor.visit_char(v), Content::String(ref v) => visitor.visit_str(v), Content::Str(v) => visitor.visit_borrowed_str(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::String(ref v) => visitor.visit_str(v), Content::Str(v) => visitor.visit_borrowed_str(v), Content::ByteBuf(ref v) => visitor.visit_bytes(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::String(ref v) => visitor.visit_str(v), Content::Str(v) => visitor.visit_borrowed_str(v), Content::ByteBuf(ref v) => visitor.visit_bytes(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::Seq(ref v) => visit_content_seq_ref(v, visitor), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_bytes(visitor) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { // Covered by tests/test_enum_untagged.rs // with_optional_field::* match *self.content { Content::None => visitor.visit_none(), Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), Content::Unit => visitor.visit_unit(), // This case is to support data formats which do not encode an // indication whether a value is optional. An example of such a // format is JSON, and a counterexample is RON. When requesting // `deserialize_any` in JSON, the data format never performs // `Visitor::visit_some` but we still must be able to // deserialize the resulting Content into data structures with // optional fields. _ => visitor.visit_some(self), } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::Unit => visitor.visit_unit(), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_unit_struct( self, _name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_unit(visitor) } fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result where V: Visitor<'de>, { // Covered by tests/test_enum_untagged.rs // newtype_struct match *self.content { Content::Newtype(ref v) => { visitor.visit_newtype_struct(ContentRefDeserializer::new(v)) } // This case is to support data formats that encode newtype // structs and their underlying data the same, with no // indication whether a newtype wrapper was present. For example // JSON does this, while RON does not. In RON a newtype's name // is included in the serialized representation and it knows to // call `Visitor::visit_newtype_struct` from `deserialize_any`. // JSON's `deserialize_any` never calls `visit_newtype_struct` // but in this code we still must be able to deserialize the // resulting Content into newtypes. _ => visitor.visit_newtype_struct(self), } } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::Seq(ref v) => visit_content_seq_ref(v, visitor), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_tuple(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_tuple_struct( self, _name: &'static str, _len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::Map(ref v) => visit_content_map_ref(v, visitor), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_struct( self, _name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { match *self.content { Content::Seq(ref v) => visit_content_seq_ref(v, visitor), Content::Map(ref v) => visit_content_map_ref(v, visitor), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_enum( self, _name: &str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let (variant, value) = match *self.content { Content::Map(ref value) => { let mut iter = value.iter(); let (variant, value) = match iter.next() { Some(v) => v, None => { return Err(de::Error::invalid_value( de::Unexpected::Map, &"map with a single key", )); } }; // enums are encoded in json as maps with a single key:value pair if iter.next().is_some() { return Err(de::Error::invalid_value( de::Unexpected::Map, &"map with a single key", )); } (variant, Some(value)) } ref s @ Content::String(_) | ref s @ Content::Str(_) => (s, None), ref other => { return Err(de::Error::invalid_type( content_unexpected(other), &"string or map", )); } }; visitor.visit_enum(EnumRefDeserializer { variant, value, err: PhantomData, }) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { match *self.content { Content::String(ref v) => visitor.visit_str(v), Content::Str(v) => visitor.visit_borrowed_str(v), Content::ByteBuf(ref v) => visitor.visit_bytes(v), Content::Bytes(v) => visitor.visit_borrowed_bytes(v), Content::U8(v) => visitor.visit_u8(v), Content::U64(v) => visitor.visit_u64(v), _ => Err(self.invalid_type(&visitor)), } } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } fn __deserialize_content_v1(self, visitor: V) -> Result where V: Visitor<'de, Value = Content<'de>>, { let _ = visitor; Ok(content_clone(self.content)) } } impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> { /// private API, don't use pub fn new(content: &'a Content<'de>) -> Self { ContentRefDeserializer { content, err: PhantomData, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de: 'a, E> Copy for ContentRefDeserializer<'a, 'de, E> {} #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de: 'a, E> Clone for ContentRefDeserializer<'a, 'de, E> { fn clone(&self) -> Self { *self } } struct SeqRefDeserializer<'a, 'de, E> { iter: <&'a [Content<'de>] as IntoIterator>::IntoIter, count: usize, marker: PhantomData, } impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E> { fn new(content: &'a [Content<'de>]) -> Self { SeqRefDeserializer { iter: content.iter(), count: 0, marker: PhantomData, } } } impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E> where E: de::Error, { fn end(self) -> Result<(), E> { let remaining = self.iter.count(); if remaining == 0 { Ok(()) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length( self.count + remaining, &ExpectedInSeq(self.count), )) } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> Deserializer<'de> for SeqRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; fn deserialize_any(mut self, visitor: V) -> Result where V: Visitor<'de>, { let v = tri!(visitor.visit_seq(&mut self)); tri!(self.end()); Ok(v) } serde_core::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 } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: V) -> Result, Self::Error> where V: DeserializeSeed<'de>, { match self.iter.next() { Some(value) => { self.count += 1; seed.deserialize(ContentRefDeserializer::new(value)) .map(Some) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } struct MapRefDeserializer<'a, 'de, E> { iter: <&'a [(Content<'de>, Content<'de>)] as IntoIterator>::IntoIter, value: Option<&'a Content<'de>>, count: usize, error: PhantomData, } impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E> { fn new(content: &'a [(Content<'de>, Content<'de>)]) -> Self { MapRefDeserializer { iter: content.iter(), value: None, count: 0, error: PhantomData, } } } impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E> where E: de::Error, { fn end(self) -> Result<(), E> { let remaining = self.iter.count(); if remaining == 0 { Ok(()) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length( self.count + remaining, &ExpectedInMap(self.count), )) } } } impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E> { fn next_pair(&mut self) -> Option<(&'a Content<'de>, &'a Content<'de>)> { match self.iter.next() { Some((k, v)) => { self.count += 1; Some((k, v)) } None => None, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> Deserializer<'de> for MapRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; fn deserialize_any(mut self, visitor: V) -> Result where V: Visitor<'de>, { let value = tri!(visitor.visit_map(&mut self)); tri!(self.end()); Ok(value) } fn deserialize_seq(mut self, visitor: V) -> Result where V: Visitor<'de>, { let value = tri!(visitor.visit_seq(&mut self)); tri!(self.end()); Ok(value) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { let _ = len; self.deserialize_seq(visitor) } serde_core::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 tuple_struct map struct enum identifier ignored_any } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> MapAccess<'de> for MapRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { match self.next_pair() { Some((key, value)) => { self.value = Some(value); seed.deserialize(ContentRefDeserializer::new(key)).map(Some) } None => Ok(None), } } fn next_value_seed(&mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { let value = self.value.take(); // Panic because this indicates a bug in the program rather than an // expected failure. let value = value.expect("MapAccess::next_value called before next_key"); seed.deserialize(ContentRefDeserializer::new(value)) } fn next_entry_seed( &mut self, kseed: TK, vseed: TV, ) -> Result, Self::Error> where TK: DeserializeSeed<'de>, TV: DeserializeSeed<'de>, { match self.next_pair() { Some((key, value)) => { let key = tri!(kseed.deserialize(ContentRefDeserializer::new(key))); let value = tri!(vseed.deserialize(ContentRefDeserializer::new(value))); Ok(Some((key, value))) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> SeqAccess<'de> for MapRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: de::DeserializeSeed<'de>, { match self.next_pair() { Some((k, v)) => { let de = PairRefDeserializer(k, v, PhantomData); seed.deserialize(de).map(Some) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } struct PairRefDeserializer<'a, 'de, E>(&'a Content<'de>, &'a Content<'de>, PhantomData); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> Deserializer<'de> for PairRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; serde_core::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 tuple_struct map struct enum identifier ignored_any } fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { let mut pair_visitor = PairRefVisitor(Some(self.0), Some(self.1), PhantomData); let pair = tri!(visitor.visit_seq(&mut pair_visitor)); if pair_visitor.1.is_none() { Ok(pair) } else { let remaining = pair_visitor.size_hint().unwrap(); // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length(2, &ExpectedInSeq(2 - remaining))) } } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { if len == 2 { self.deserialize_seq(visitor) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length(2, &ExpectedInSeq(len))) } } } struct PairRefVisitor<'a, 'de, E>( Option<&'a Content<'de>>, Option<&'a Content<'de>>, PhantomData, ); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> SeqAccess<'de> for PairRefVisitor<'a, 'de, E> where E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { if let Some(k) = self.0.take() { seed.deserialize(ContentRefDeserializer::new(k)).map(Some) } else if let Some(v) = self.1.take() { seed.deserialize(ContentRefDeserializer::new(v)).map(Some) } else { Ok(None) } } fn size_hint(&self) -> Option { if self.0.is_some() { Some(2) } else if self.1.is_some() { Some(1) } else { Some(0) } } } struct EnumRefDeserializer<'a, 'de: 'a, E> where E: de::Error, { variant: &'a Content<'de>, value: Option<&'a Content<'de>>, err: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; type Variant = VariantRefDeserializer<'a, 'de, Self::Error>; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: de::DeserializeSeed<'de>, { let visitor = VariantRefDeserializer { value: self.value, err: PhantomData, }; seed.deserialize(ContentRefDeserializer::new(self.variant)) .map(|v| (v, visitor)) } } struct VariantRefDeserializer<'a, 'de: 'a, E> where E: de::Error, { value: Option<&'a Content<'de>>, err: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, 'de, E> where E: de::Error, { type Error = E; fn unit_variant(self) -> Result<(), E> { match self.value { Some(value) => de::Deserialize::deserialize(ContentRefDeserializer::new(value)), // Covered by tests/test_annotations.rs // test_partially_untagged_adjacently_tagged_enum // Covered by tests/test_enum_untagged.rs // newtype_enum::unit None => Ok(()), } } fn newtype_variant_seed(self, seed: T) -> Result where T: de::DeserializeSeed<'de>, { match self.value { // Covered by tests/test_annotations.rs // test_partially_untagged_enum_desugared // test_partially_untagged_enum_generic // Covered by tests/test_enum_untagged.rs // newtype_enum::newtype Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), None => Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"newtype variant", )), } } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { match self.value { // Covered by tests/test_annotations.rs // test_partially_untagged_enum // test_partially_untagged_enum_desugared // Covered by tests/test_enum_untagged.rs // newtype_enum::tuple0 // newtype_enum::tuple2 Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor), Some(other) => Err(de::Error::invalid_type( content_unexpected(other), &"tuple variant", )), None => Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"tuple variant", )), } } fn struct_variant( self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { match self.value { // Covered by tests/test_enum_untagged.rs // newtype_enum::struct_from_map Some(Content::Map(v)) => visit_content_map_ref(v, visitor), // Covered by tests/test_enum_untagged.rs // newtype_enum::struct_from_seq // newtype_enum::empty_struct_from_seq Some(Content::Seq(v)) => visit_content_seq_ref(v, visitor), Some(other) => Err(de::Error::invalid_type( content_unexpected(other), &"struct variant", )), None => Err(de::Error::invalid_type( de::Unexpected::UnitVariant, &"struct variant", )), } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<'de, E> where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, 'de, E> where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } /// Visitor for deserializing an internally tagged unit variant. /// /// Not public API. pub struct InternallyTaggedUnitVisitor<'a> { type_name: &'a str, variant_name: &'a str, } impl<'a> InternallyTaggedUnitVisitor<'a> { /// Not public API. pub fn new(type_name: &'a str, variant_name: &'a str) -> Self { InternallyTaggedUnitVisitor { type_name, variant_name, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, 'a> Visitor<'de> for InternallyTaggedUnitVisitor<'a> { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!( formatter, "unit variant {}::{}", self.type_name, self.variant_name ) } fn visit_seq(self, _: S) -> Result<(), S::Error> where S: SeqAccess<'de>, { Ok(()) } fn visit_map(self, mut access: M) -> Result<(), M::Error> where M: MapAccess<'de>, { while tri!(access.next_entry::()).is_some() {} Ok(()) } } /// Visitor for deserializing an untagged unit variant. /// /// Not public API. pub struct UntaggedUnitVisitor<'a> { type_name: &'a str, variant_name: &'a str, } impl<'a> UntaggedUnitVisitor<'a> { /// Not public API. pub fn new(type_name: &'a str, variant_name: &'a str) -> Self { UntaggedUnitVisitor { type_name, variant_name, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, 'a> Visitor<'de> for UntaggedUnitVisitor<'a> { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!( formatter, "unit variant {}::{}", self.type_name, self.variant_name ) } fn visit_unit(self) -> Result<(), E> where E: de::Error, { Ok(()) } fn visit_none(self) -> Result<(), E> where E: de::Error, { Ok(()) } } } //////////////////////////////////////////////////////////////////////////////// // Like `IntoDeserializer` but also implemented for `&[u8]`. This is used for // the newtype fallthrough case of `field_identifier`. // // #[derive(Deserialize)] // #[serde(field_identifier)] // enum F { // A, // B, // Other(String), // deserialized using IdentifierDeserializer // } pub trait IdentifierDeserializer<'de, E: Error> { type Deserializer: Deserializer<'de, Error = E>; fn from(self) -> Self::Deserializer; } pub struct Borrowed<'de, T: 'de + ?Sized>(pub &'de T); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> IdentifierDeserializer<'de, E> for u64 where E: Error, { type Deserializer = >::Deserializer; fn from(self) -> Self::Deserializer { self.into_deserializer() } } pub struct StrDeserializer<'a, E> { value: &'a str, marker: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, 'a, E> Deserializer<'de> for StrDeserializer<'a, E> where E: Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_str(self.value) } serde_core::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 } } pub struct BorrowedStrDeserializer<'de, E> { value: &'de str, marker: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> Deserializer<'de> for BorrowedStrDeserializer<'de, E> where E: Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_borrowed_str(self.value) } serde_core::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 } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, E> IdentifierDeserializer<'a, E> for &'a str where E: Error, { type Deserializer = StrDeserializer<'a, E>; fn from(self) -> Self::Deserializer { StrDeserializer { value: self, marker: PhantomData, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> IdentifierDeserializer<'de, E> for Borrowed<'de, str> where E: Error, { type Deserializer = BorrowedStrDeserializer<'de, E>; fn from(self) -> Self::Deserializer { BorrowedStrDeserializer { value: self.0, marker: PhantomData, } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, E> IdentifierDeserializer<'a, E> for &'a [u8] where E: Error, { type Deserializer = BytesDeserializer<'a, E>; fn from(self) -> Self::Deserializer { BytesDeserializer::new(self) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, E> IdentifierDeserializer<'de, E> for Borrowed<'de, [u8]> where E: Error, { type Deserializer = BorrowedBytesDeserializer<'de, E>; fn from(self) -> Self::Deserializer { BorrowedBytesDeserializer::new(self.0) } } #[cfg(any(feature = "std", feature = "alloc"))] pub struct FlatMapDeserializer<'a, 'de: 'a, E>( pub &'a mut Vec, Content<'de>)>>, pub PhantomData, ); #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, 'de, E> FlatMapDeserializer<'a, 'de, E> where E: Error, { fn deserialize_other() -> Result { Err(Error::custom("can only flatten structs and maps")) } } #[cfg(any(feature = "std", feature = "alloc"))] macro_rules! forward_to_deserialize_other { ($($func:ident ($($arg:ty),*))*) => { $( fn $func(self, $(_: $arg,)* _visitor: V) -> Result where V: Visitor<'de>, { Self::deserialize_other() } )* } } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> Deserializer<'de> for FlatMapDeserializer<'a, 'de, E> where E: Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_map(visitor) } fn deserialize_enum( self, name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { for entry in self.0 { if let Some((key, value)) = flat_map_take_entry(entry, variants) { return visitor.visit_enum(EnumDeserializer::new(key, Some(value))); } } Err(Error::custom(format_args!( "no variant of enum {} found in flattened data", name ))) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_map(FlatMapAccess { iter: self.0.iter(), pending_content: None, _marker: PhantomData, }) } fn deserialize_struct( self, _: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_map(FlatStructAccess { iter: self.0.iter_mut(), pending_content: None, fields, _marker: PhantomData, }) } fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { match visitor.__private_visit_untagged_option(self) { Ok(value) => Ok(value), Err(()) => Self::deserialize_other(), } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } fn deserialize_unit_struct( self, _name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_unit() } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } forward_to_deserialize_other! { deserialize_bool() deserialize_i8() deserialize_i16() deserialize_i32() deserialize_i64() deserialize_u8() deserialize_u16() deserialize_u32() deserialize_u64() deserialize_f32() deserialize_f64() deserialize_char() deserialize_str() deserialize_string() deserialize_bytes() deserialize_byte_buf() deserialize_seq() deserialize_tuple(usize) deserialize_tuple_struct(&'static str, usize) deserialize_identifier() } } #[cfg(any(feature = "std", feature = "alloc"))] struct FlatMapAccess<'a, 'de: 'a, E> { iter: slice::Iter<'a, Option<(Content<'de>, Content<'de>)>>, pending_content: Option<&'a Content<'de>>, _marker: PhantomData, } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> MapAccess<'de> for FlatMapAccess<'a, 'de, E> where E: Error, { type Error = E; fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { for item in &mut self.iter { // Items in the vector are nulled out when used by a struct. if let Some((ref key, ref content)) = *item { // Do not take(), instead borrow this entry. The internally tagged // enum does its own buffering so we can't tell whether this entry // is going to be consumed. Borrowing here leaves the entry // available for later flattened fields. self.pending_content = Some(content); return seed.deserialize(ContentRefDeserializer::new(key)).map(Some); } } Ok(None) } fn next_value_seed(&mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.pending_content.take() { Some(value) => seed.deserialize(ContentRefDeserializer::new(value)), None => Err(Error::custom("value is missing")), } } } #[cfg(any(feature = "std", feature = "alloc"))] struct FlatStructAccess<'a, 'de: 'a, E> { iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>, pending_content: Option>, fields: &'static [&'static str], _marker: PhantomData, } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, E> MapAccess<'de> for FlatStructAccess<'a, 'de, E> where E: Error, { type Error = E; fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { for entry in self.iter.by_ref() { if let Some((key, content)) = flat_map_take_entry(entry, self.fields) { self.pending_content = Some(content); return seed.deserialize(ContentDeserializer::new(key)).map(Some); } } Ok(None) } fn next_value_seed(&mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.pending_content.take() { Some(value) => seed.deserialize(ContentDeserializer::new(value)), None => Err(Error::custom("value is missing")), } } } /// Claims one key-value pair from a FlatMapDeserializer's field buffer if the /// field name matches any of the recognized ones. #[cfg(any(feature = "std", feature = "alloc"))] fn flat_map_take_entry<'de>( entry: &mut Option<(Content<'de>, Content<'de>)>, recognized: &[&str], ) -> Option<(Content<'de>, Content<'de>)> { // Entries in the FlatMapDeserializer buffer are nulled out as they get // claimed for deserialization. We only use an entry if it is still present // and if the field is one recognized by the current data structure. let is_recognized = match entry { None => false, Some((k, _v)) => content_as_str(k).map_or(false, |name| recognized.contains(&name)), }; if is_recognized { entry.take() } else { None } } pub struct AdjacentlyTaggedEnumVariantSeed { pub enum_name: &'static str, pub variants: &'static [&'static str], pub fields_enum: PhantomData, } pub struct AdjacentlyTaggedEnumVariantVisitor { enum_name: &'static str, fields_enum: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, F> Visitor<'de> for AdjacentlyTaggedEnumVariantVisitor 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(self, data: A) -> Result where A: EnumAccess<'de>, { let (variant, variant_access) = tri!(data.variant()); tri!(variant_access.unit_variant()); Ok(variant) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'de, F> DeserializeSeed<'de> for AdjacentlyTaggedEnumVariantSeed where F: Deserialize<'de>, { type Value = F; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_enum( self.enum_name, self.variants, AdjacentlyTaggedEnumVariantVisitor { enum_name: self.enum_name, fields_enum: PhantomData, }, ) } } ================================================ FILE: serde/src/private/mod.rs ================================================ #[cfg(not(no_serde_derive))] pub mod de; #[cfg(not(no_serde_derive))] pub mod ser; pub use crate::lib::clone::Clone; pub use crate::lib::convert::{From, Into, TryFrom}; pub use crate::lib::default::Default; pub use crate::lib::fmt::{self, Formatter}; pub use crate::lib::marker::PhantomData; pub use crate::lib::option::Option::{self, None, Some}; pub use crate::lib::ptr; pub use crate::lib::result::Result::{self, Err, Ok}; pub use crate::serde_core_private::string::from_utf8_lossy; #[cfg(any(feature = "alloc", feature = "std"))] pub use crate::lib::{ToString, Vec}; ================================================ FILE: serde/src/private/ser.rs ================================================ use crate::lib::*; use crate::ser::{self, Impossible, Serialize, SerializeMap, SerializeStruct, Serializer}; #[cfg(any(feature = "std", feature = "alloc"))] use self::content::{ Content, ContentSerializer, SerializeStructVariantAsMapValue, SerializeTupleVariantAsMapValue, }; /// Used to check that serde(getter) attributes return the expected type. /// Not public API. pub fn constrain(t: &T) -> &T { t } /// Not public API. pub fn serialize_tagged_newtype( serializer: S, type_ident: &'static str, variant_ident: &'static str, tag: &'static str, variant_name: &'static str, value: &T, ) -> Result where S: Serializer, T: Serialize, { value.serialize(TaggedSerializer { type_ident, variant_ident, tag, variant_name, delegate: serializer, }) } struct TaggedSerializer { type_ident: &'static str, variant_ident: &'static str, tag: &'static str, variant_name: &'static str, delegate: S, } enum Unsupported { Boolean, Integer, Float, Char, String, ByteArray, Optional, Sequence, Tuple, TupleStruct, #[cfg(not(any(feature = "std", feature = "alloc")))] Enum, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Display for Unsupported { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match *self { Unsupported::Boolean => formatter.write_str("a boolean"), Unsupported::Integer => formatter.write_str("an integer"), Unsupported::Float => formatter.write_str("a float"), Unsupported::Char => formatter.write_str("a char"), Unsupported::String => formatter.write_str("a string"), Unsupported::ByteArray => formatter.write_str("a byte array"), Unsupported::Optional => formatter.write_str("an optional"), Unsupported::Sequence => formatter.write_str("a sequence"), Unsupported::Tuple => formatter.write_str("a tuple"), Unsupported::TupleStruct => formatter.write_str("a tuple struct"), #[cfg(not(any(feature = "std", feature = "alloc")))] Unsupported::Enum => formatter.write_str("an enum"), } } } impl TaggedSerializer where S: Serializer, { fn bad_type(self, what: Unsupported) -> S::Error { ser::Error::custom(format_args!( "cannot serialize tagged newtype variant {}::{} containing {}", self.type_ident, self.variant_ident, what )) } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Serializer for TaggedSerializer where S: Serializer, { type Ok = S::Ok; type Error = S::Error; type SerializeSeq = Impossible; type SerializeTuple = Impossible; type SerializeTupleStruct = Impossible; type SerializeMap = S::SerializeMap; type SerializeStruct = S::SerializeStruct; #[cfg(not(any(feature = "std", feature = "alloc")))] type SerializeTupleVariant = Impossible; #[cfg(any(feature = "std", feature = "alloc"))] type SerializeTupleVariant = SerializeTupleVariantAsMapValue; #[cfg(not(any(feature = "std", feature = "alloc")))] type SerializeStructVariant = Impossible; #[cfg(any(feature = "std", feature = "alloc"))] type SerializeStructVariant = SerializeStructVariantAsMapValue; fn serialize_bool(self, _: bool) -> Result { Err(self.bad_type(Unsupported::Boolean)) } fn serialize_i8(self, _: i8) -> Result { Err(self.bad_type(Unsupported::Integer)) } fn serialize_i16(self, _: i16) -> Result { Err(self.bad_type(Unsupported::Integer)) } fn serialize_i32(self, _: i32) -> Result { Err(self.bad_type(Unsupported::Integer)) } fn serialize_i64(self, _: i64) -> Result { Err(self.bad_type(Unsupported::Integer)) } fn serialize_u8(self, _: u8) -> Result { Err(self.bad_type(Unsupported::Integer)) } fn serialize_u16(self, _: u16) -> Result { Err(self.bad_type(Unsupported::Integer)) } fn serialize_u32(self, _: u32) -> Result { Err(self.bad_type(Unsupported::Integer)) } fn serialize_u64(self, _: u64) -> Result { Err(self.bad_type(Unsupported::Integer)) } fn serialize_f32(self, _: f32) -> Result { Err(self.bad_type(Unsupported::Float)) } fn serialize_f64(self, _: f64) -> Result { Err(self.bad_type(Unsupported::Float)) } fn serialize_char(self, _: char) -> Result { Err(self.bad_type(Unsupported::Char)) } fn serialize_str(self, _: &str) -> Result { Err(self.bad_type(Unsupported::String)) } fn serialize_bytes(self, _: &[u8]) -> Result { Err(self.bad_type(Unsupported::ByteArray)) } fn serialize_none(self) -> Result { Err(self.bad_type(Unsupported::Optional)) } fn serialize_some(self, _: &T) -> Result where T: ?Sized + Serialize, { Err(self.bad_type(Unsupported::Optional)) } fn serialize_unit(self) -> Result { let mut map = tri!(self.delegate.serialize_map(Some(1))); tri!(map.serialize_entry(self.tag, self.variant_name)); map.end() } fn serialize_unit_struct(self, _: &'static str) -> Result { let mut map = tri!(self.delegate.serialize_map(Some(1))); tri!(map.serialize_entry(self.tag, self.variant_name)); map.end() } fn serialize_unit_variant( self, _: &'static str, _: u32, inner_variant: &'static str, ) -> Result { let mut map = tri!(self.delegate.serialize_map(Some(2))); tri!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(inner_variant, &())); map.end() } fn serialize_newtype_struct( self, _: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize, { value.serialize(self) } fn serialize_newtype_variant( self, _: &'static str, _: u32, inner_variant: &'static str, inner_value: &T, ) -> Result where T: ?Sized + Serialize, { let mut map = tri!(self.delegate.serialize_map(Some(2))); tri!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_entry(inner_variant, inner_value)); map.end() } fn serialize_seq(self, _: Option) -> Result { Err(self.bad_type(Unsupported::Sequence)) } fn serialize_tuple(self, _: usize) -> Result { Err(self.bad_type(Unsupported::Tuple)) } fn serialize_tuple_struct( self, _: &'static str, _: usize, ) -> Result { Err(self.bad_type(Unsupported::TupleStruct)) } #[cfg(not(any(feature = "std", feature = "alloc")))] fn serialize_tuple_variant( self, _: &'static str, _: u32, _: &'static str, _: usize, ) -> Result { // Lack of push-based serialization means we need to buffer the content // of the tuple variant, so it requires std. Err(self.bad_type(Unsupported::Enum)) } #[cfg(any(feature = "std", feature = "alloc"))] fn serialize_tuple_variant( self, _: &'static str, _: u32, inner_variant: &'static str, len: usize, ) -> Result { let mut map = tri!(self.delegate.serialize_map(Some(2))); tri!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_key(inner_variant)); Ok(SerializeTupleVariantAsMapValue::new( map, inner_variant, len, )) } fn serialize_map(self, len: Option) -> Result { let mut map = tri!(self.delegate.serialize_map(len.map(|len| len + 1))); tri!(map.serialize_entry(self.tag, self.variant_name)); Ok(map) } fn serialize_struct( self, name: &'static str, len: usize, ) -> Result { let mut state = tri!(self.delegate.serialize_struct(name, len + 1)); tri!(state.serialize_field(self.tag, self.variant_name)); Ok(state) } #[cfg(not(any(feature = "std", feature = "alloc")))] fn serialize_struct_variant( self, _: &'static str, _: u32, _: &'static str, _: usize, ) -> Result { // Lack of push-based serialization means we need to buffer the content // of the struct variant, so it requires std. Err(self.bad_type(Unsupported::Enum)) } #[cfg(any(feature = "std", feature = "alloc"))] fn serialize_struct_variant( self, _: &'static str, _: u32, inner_variant: &'static str, len: usize, ) -> Result { let mut map = tri!(self.delegate.serialize_map(Some(2))); tri!(map.serialize_entry(self.tag, self.variant_name)); tri!(map.serialize_key(inner_variant)); Ok(SerializeStructVariantAsMapValue::new( map, inner_variant, len, )) } #[cfg(not(any(feature = "std", feature = "alloc")))] fn collect_str(self, _: &T) -> Result where T: ?Sized + Display, { Err(self.bad_type(Unsupported::String)) } } #[cfg(any(feature = "std", feature = "alloc"))] mod content { use crate::lib::*; use crate::ser::{self, Serialize, Serializer}; pub struct SerializeTupleVariantAsMapValue { map: M, name: &'static str, fields: Vec, } impl SerializeTupleVariantAsMapValue { pub fn new(map: M, name: &'static str, len: usize) -> Self { SerializeTupleVariantAsMapValue { map, name, fields: Vec::with_capacity(len), } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeTupleVariant for SerializeTupleVariantAsMapValue where M: ser::SerializeMap, { type Ok = M::Ok; type Error = M::Error; fn serialize_field(&mut self, value: &T) -> Result<(), M::Error> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); Ok(()) } fn end(mut self) -> Result { tri!(self .map .serialize_value(&Content::TupleStruct(self.name, self.fields))); self.map.end() } } pub struct SerializeStructVariantAsMapValue { map: M, name: &'static str, fields: Vec<(&'static str, Content)>, } impl SerializeStructVariantAsMapValue { pub fn new(map: M, name: &'static str, len: usize) -> Self { SerializeStructVariantAsMapValue { map, name, fields: Vec::with_capacity(len), } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeStructVariant for SerializeStructVariantAsMapValue where M: ser::SerializeMap, { type Ok = M::Ok; type Error = M::Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), M::Error> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); Ok(()) } fn end(mut self) -> Result { tri!(self .map .serialize_value(&Content::Struct(self.name, self.fields))); self.map.end() } } pub enum Content { Bool(bool), U8(u8), U16(u16), U32(u32), U64(u64), I8(i8), I16(i16), I32(i32), I64(i64), F32(f32), F64(f64), Char(char), String(String), Bytes(Vec), None, Some(Box), Unit, UnitStruct(&'static str), UnitVariant(&'static str, u32, &'static str), NewtypeStruct(&'static str, Box), NewtypeVariant(&'static str, u32, &'static str, Box), Seq(Vec), Tuple(Vec), TupleStruct(&'static str, Vec), TupleVariant(&'static str, u32, &'static str, Vec), Map(Vec<(Content, Content)>), Struct(&'static str, Vec<(&'static str, Content)>), StructVariant( &'static str, u32, &'static str, Vec<(&'static str, Content)>, ), } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Serialize for Content { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match *self { Content::Bool(b) => serializer.serialize_bool(b), Content::U8(u) => serializer.serialize_u8(u), Content::U16(u) => serializer.serialize_u16(u), Content::U32(u) => serializer.serialize_u32(u), Content::U64(u) => serializer.serialize_u64(u), Content::I8(i) => serializer.serialize_i8(i), Content::I16(i) => serializer.serialize_i16(i), Content::I32(i) => serializer.serialize_i32(i), Content::I64(i) => serializer.serialize_i64(i), Content::F32(f) => serializer.serialize_f32(f), Content::F64(f) => serializer.serialize_f64(f), Content::Char(c) => serializer.serialize_char(c), Content::String(ref s) => serializer.serialize_str(s), Content::Bytes(ref b) => serializer.serialize_bytes(b), Content::None => serializer.serialize_none(), Content::Some(ref c) => serializer.serialize_some(&**c), Content::Unit => serializer.serialize_unit(), Content::UnitStruct(n) => serializer.serialize_unit_struct(n), Content::UnitVariant(n, i, v) => serializer.serialize_unit_variant(n, i, v), Content::NewtypeStruct(n, ref c) => serializer.serialize_newtype_struct(n, &**c), Content::NewtypeVariant(n, i, v, ref c) => { serializer.serialize_newtype_variant(n, i, v, &**c) } Content::Seq(ref elements) => elements.serialize(serializer), Content::Tuple(ref elements) => { use crate::ser::SerializeTuple; let mut tuple = tri!(serializer.serialize_tuple(elements.len())); for e in elements { tri!(tuple.serialize_element(e)); } tuple.end() } Content::TupleStruct(n, ref fields) => { use crate::ser::SerializeTupleStruct; let mut ts = tri!(serializer.serialize_tuple_struct(n, fields.len())); for f in fields { tri!(ts.serialize_field(f)); } ts.end() } Content::TupleVariant(n, i, v, ref fields) => { use crate::ser::SerializeTupleVariant; let mut tv = tri!(serializer.serialize_tuple_variant(n, i, v, fields.len())); for f in fields { tri!(tv.serialize_field(f)); } tv.end() } Content::Map(ref entries) => { use crate::ser::SerializeMap; let mut map = tri!(serializer.serialize_map(Some(entries.len()))); for (k, v) in entries { tri!(map.serialize_entry(k, v)); } map.end() } Content::Struct(n, ref fields) => { use crate::ser::SerializeStruct; let mut s = tri!(serializer.serialize_struct(n, fields.len())); for &(k, ref v) in fields { tri!(s.serialize_field(k, v)); } s.end() } Content::StructVariant(n, i, v, ref fields) => { use crate::ser::SerializeStructVariant; let mut sv = tri!(serializer.serialize_struct_variant(n, i, v, fields.len())); for &(k, ref v) in fields { tri!(sv.serialize_field(k, v)); } sv.end() } } } } pub struct ContentSerializer { error: PhantomData, } impl ContentSerializer { pub fn new() -> Self { ContentSerializer { error: PhantomData } } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Serializer for ContentSerializer where E: ser::Error, { type Ok = Content; type Error = E; type SerializeSeq = SerializeSeq; type SerializeTuple = SerializeTuple; type SerializeTupleStruct = SerializeTupleStruct; type SerializeTupleVariant = SerializeTupleVariant; type SerializeMap = SerializeMap; type SerializeStruct = SerializeStruct; type SerializeStructVariant = SerializeStructVariant; fn serialize_bool(self, v: bool) -> Result { Ok(Content::Bool(v)) } fn serialize_i8(self, v: i8) -> Result { Ok(Content::I8(v)) } fn serialize_i16(self, v: i16) -> Result { Ok(Content::I16(v)) } fn serialize_i32(self, v: i32) -> Result { Ok(Content::I32(v)) } fn serialize_i64(self, v: i64) -> Result { Ok(Content::I64(v)) } fn serialize_u8(self, v: u8) -> Result { Ok(Content::U8(v)) } fn serialize_u16(self, v: u16) -> Result { Ok(Content::U16(v)) } fn serialize_u32(self, v: u32) -> Result { Ok(Content::U32(v)) } fn serialize_u64(self, v: u64) -> Result { Ok(Content::U64(v)) } fn serialize_f32(self, v: f32) -> Result { Ok(Content::F32(v)) } fn serialize_f64(self, v: f64) -> Result { Ok(Content::F64(v)) } fn serialize_char(self, v: char) -> Result { Ok(Content::Char(v)) } fn serialize_str(self, value: &str) -> Result { Ok(Content::String(value.to_owned())) } fn serialize_bytes(self, value: &[u8]) -> Result { Ok(Content::Bytes(value.to_owned())) } fn serialize_none(self) -> Result { Ok(Content::None) } fn serialize_some(self, value: &T) -> Result where T: ?Sized + Serialize, { Ok(Content::Some(Box::new(tri!(value.serialize(self))))) } fn serialize_unit(self) -> Result { Ok(Content::Unit) } fn serialize_unit_struct(self, name: &'static str) -> Result { Ok(Content::UnitStruct(name)) } fn serialize_unit_variant( self, name: &'static str, variant_index: u32, variant: &'static str, ) -> Result { Ok(Content::UnitVariant(name, variant_index, variant)) } fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result where T: ?Sized + Serialize, { Ok(Content::NewtypeStruct( name, Box::new(tri!(value.serialize(self))), )) } fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize, { Ok(Content::NewtypeVariant( name, variant_index, variant, Box::new(tri!(value.serialize(self))), )) } fn serialize_seq(self, len: Option) -> Result { Ok(SerializeSeq { elements: Vec::with_capacity(len.unwrap_or(0)), error: PhantomData, }) } fn serialize_tuple(self, len: usize) -> Result { Ok(SerializeTuple { elements: Vec::with_capacity(len), error: PhantomData, }) } fn serialize_tuple_struct( self, name: &'static str, len: usize, ) -> Result { Ok(SerializeTupleStruct { name, fields: Vec::with_capacity(len), error: PhantomData, }) } fn serialize_tuple_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(SerializeTupleVariant { name, variant_index, variant, fields: Vec::with_capacity(len), error: PhantomData, }) } fn serialize_map(self, len: Option) -> Result { Ok(SerializeMap { entries: Vec::with_capacity(len.unwrap_or(0)), key: None, error: PhantomData, }) } fn serialize_struct( self, name: &'static str, len: usize, ) -> Result { Ok(SerializeStruct { name, fields: Vec::with_capacity(len), error: PhantomData, }) } fn serialize_struct_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(SerializeStructVariant { name, variant_index, variant, fields: Vec::with_capacity(len), error: PhantomData, }) } } pub struct SerializeSeq { elements: Vec, error: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeSeq for SerializeSeq where E: ser::Error, { type Ok = Content; type Error = E; fn serialize_element(&mut self, value: &T) -> Result<(), E> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.elements.push(value); Ok(()) } fn end(self) -> Result { Ok(Content::Seq(self.elements)) } } pub struct SerializeTuple { elements: Vec, error: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeTuple for SerializeTuple where E: ser::Error, { type Ok = Content; type Error = E; fn serialize_element(&mut self, value: &T) -> Result<(), E> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.elements.push(value); Ok(()) } fn end(self) -> Result { Ok(Content::Tuple(self.elements)) } } pub struct SerializeTupleStruct { name: &'static str, fields: Vec, error: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeTupleStruct for SerializeTupleStruct where E: ser::Error, { type Ok = Content; type Error = E; fn serialize_field(&mut self, value: &T) -> Result<(), E> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); Ok(()) } fn end(self) -> Result { Ok(Content::TupleStruct(self.name, self.fields)) } } pub struct SerializeTupleVariant { name: &'static str, variant_index: u32, variant: &'static str, fields: Vec, error: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeTupleVariant for SerializeTupleVariant where E: ser::Error, { type Ok = Content; type Error = E; fn serialize_field(&mut self, value: &T) -> Result<(), E> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push(value); Ok(()) } fn end(self) -> Result { Ok(Content::TupleVariant( self.name, self.variant_index, self.variant, self.fields, )) } } pub struct SerializeMap { entries: Vec<(Content, Content)>, key: Option, error: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeMap for SerializeMap where E: ser::Error, { type Ok = Content; type Error = E; fn serialize_key(&mut self, key: &T) -> Result<(), E> where T: ?Sized + Serialize, { let key = tri!(key.serialize(ContentSerializer::::new())); self.key = Some(key); Ok(()) } fn serialize_value(&mut self, value: &T) -> Result<(), E> where T: ?Sized + Serialize, { let key = self .key .take() .expect("serialize_value called before serialize_key"); let value = tri!(value.serialize(ContentSerializer::::new())); self.entries.push((key, value)); Ok(()) } fn end(self) -> Result { Ok(Content::Map(self.entries)) } fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), E> where K: ?Sized + Serialize, V: ?Sized + Serialize, { let key = tri!(key.serialize(ContentSerializer::::new())); let value = tri!(value.serialize(ContentSerializer::::new())); self.entries.push((key, value)); Ok(()) } } pub struct SerializeStruct { name: &'static str, fields: Vec<(&'static str, Content)>, error: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeStruct for SerializeStruct where E: ser::Error, { type Ok = Content; type Error = E; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); Ok(()) } fn end(self) -> Result { Ok(Content::Struct(self.name, self.fields)) } } pub struct SerializeStructVariant { name: &'static str, variant_index: u32, variant: &'static str, fields: Vec<(&'static str, Content)>, error: PhantomData, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::SerializeStructVariant for SerializeStructVariant where E: ser::Error, { type Ok = Content; type Error = E; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), E> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); Ok(()) } fn end(self) -> Result { Ok(Content::StructVariant( self.name, self.variant_index, self.variant, self.fields, )) } } } #[cfg(any(feature = "std", feature = "alloc"))] pub struct FlatMapSerializer<'a, M: 'a>(pub &'a mut M); #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, M> FlatMapSerializer<'a, M> where M: SerializeMap + 'a, { fn bad_type(what: Unsupported) -> M::Error { ser::Error::custom(format_args!( "can only flatten structs and maps (got {})", what )) } } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, M> Serializer for FlatMapSerializer<'a, M> where M: SerializeMap + 'a, { type Ok = (); type Error = M::Error; type SerializeSeq = Impossible; type SerializeTuple = Impossible; type SerializeTupleStruct = Impossible; type SerializeMap = FlatMapSerializeMap<'a, M>; type SerializeStruct = FlatMapSerializeStruct<'a, M>; type SerializeTupleVariant = FlatMapSerializeTupleVariantAsMapValue<'a, M>; type SerializeStructVariant = FlatMapSerializeStructVariantAsMapValue<'a, M>; fn serialize_bool(self, _: bool) -> Result { Err(Self::bad_type(Unsupported::Boolean)) } fn serialize_i8(self, _: i8) -> Result { Err(Self::bad_type(Unsupported::Integer)) } fn serialize_i16(self, _: i16) -> Result { Err(Self::bad_type(Unsupported::Integer)) } fn serialize_i32(self, _: i32) -> Result { Err(Self::bad_type(Unsupported::Integer)) } fn serialize_i64(self, _: i64) -> Result { Err(Self::bad_type(Unsupported::Integer)) } fn serialize_u8(self, _: u8) -> Result { Err(Self::bad_type(Unsupported::Integer)) } fn serialize_u16(self, _: u16) -> Result { Err(Self::bad_type(Unsupported::Integer)) } fn serialize_u32(self, _: u32) -> Result { Err(Self::bad_type(Unsupported::Integer)) } fn serialize_u64(self, _: u64) -> Result { Err(Self::bad_type(Unsupported::Integer)) } fn serialize_f32(self, _: f32) -> Result { Err(Self::bad_type(Unsupported::Float)) } fn serialize_f64(self, _: f64) -> Result { Err(Self::bad_type(Unsupported::Float)) } fn serialize_char(self, _: char) -> Result { Err(Self::bad_type(Unsupported::Char)) } fn serialize_str(self, _: &str) -> Result { Err(Self::bad_type(Unsupported::String)) } fn serialize_bytes(self, _: &[u8]) -> Result { Err(Self::bad_type(Unsupported::ByteArray)) } fn serialize_none(self) -> Result { Ok(()) } fn serialize_some(self, value: &T) -> Result where T: ?Sized + Serialize, { value.serialize(self) } fn serialize_unit(self) -> Result { Ok(()) } fn serialize_unit_struct(self, _: &'static str) -> Result { Ok(()) } fn serialize_unit_variant( self, _: &'static str, _: u32, variant: &'static str, ) -> Result { self.0.serialize_entry(variant, &()) } fn serialize_newtype_struct( self, _: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize, { value.serialize(self) } fn serialize_newtype_variant( self, _: &'static str, _: u32, variant: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize, { self.0.serialize_entry(variant, value) } fn serialize_seq(self, _: Option) -> Result { Err(Self::bad_type(Unsupported::Sequence)) } fn serialize_tuple(self, _: usize) -> Result { Err(Self::bad_type(Unsupported::Tuple)) } fn serialize_tuple_struct( self, _: &'static str, _: usize, ) -> Result { Err(Self::bad_type(Unsupported::TupleStruct)) } fn serialize_tuple_variant( self, _: &'static str, _: u32, variant: &'static str, _: usize, ) -> Result { tri!(self.0.serialize_key(variant)); Ok(FlatMapSerializeTupleVariantAsMapValue::new(self.0)) } fn serialize_map(self, _: Option) -> Result { Ok(FlatMapSerializeMap(self.0)) } fn serialize_struct( self, _: &'static str, _: usize, ) -> Result { Ok(FlatMapSerializeStruct(self.0)) } fn serialize_struct_variant( self, _: &'static str, _: u32, inner_variant: &'static str, _: usize, ) -> Result { tri!(self.0.serialize_key(inner_variant)); Ok(FlatMapSerializeStructVariantAsMapValue::new( self.0, inner_variant, )) } } #[cfg(any(feature = "std", feature = "alloc"))] pub struct FlatMapSerializeMap<'a, M: 'a>(&'a mut M); #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, M> ser::SerializeMap for FlatMapSerializeMap<'a, M> where M: SerializeMap + 'a, { type Ok = (); type Error = M::Error; fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { self.0.serialize_key(key) } fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { self.0.serialize_value(value) } fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where K: ?Sized + Serialize, V: ?Sized + Serialize, { self.0.serialize_entry(key, value) } fn end(self) -> Result<(), Self::Error> { Ok(()) } } #[cfg(any(feature = "std", feature = "alloc"))] pub struct FlatMapSerializeStruct<'a, M: 'a>(&'a mut M); #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, M> ser::SerializeStruct for FlatMapSerializeStruct<'a, M> where M: SerializeMap + 'a, { type Ok = (); type Error = M::Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { self.0.serialize_entry(key, value) } fn end(self) -> Result<(), Self::Error> { Ok(()) } } //////////////////////////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] pub struct FlatMapSerializeTupleVariantAsMapValue<'a, M: 'a> { map: &'a mut M, fields: Vec, } #[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"))] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, M> ser::SerializeTupleVariant for FlatMapSerializeTupleVariantAsMapValue<'a, M> where M: SerializeMap + 'a, { type Ok = (); type Error = M::Error; fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::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"))] pub struct FlatMapSerializeStructVariantAsMapValue<'a, M: 'a> { map: &'a mut M, name: &'static str, fields: Vec<(&'static str, Content)>, } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, M> FlatMapSerializeStructVariantAsMapValue<'a, M> where M: SerializeMap + 'a, { fn new(map: &'a mut M, name: &'static str) -> FlatMapSerializeStructVariantAsMapValue<'a, M> { FlatMapSerializeStructVariantAsMapValue { map, name, fields: Vec::new(), } } } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, M> ser::SerializeStructVariant for FlatMapSerializeStructVariantAsMapValue<'a, M> where M: SerializeMap + 'a, { type Ok = (); type Error = M::Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { let value = tri!(value.serialize(ContentSerializer::::new())); self.fields.push((key, value)); Ok(()) } fn end(self) -> Result<(), Self::Error> { tri!(self .map .serialize_value(&Content::Struct(self.name, self.fields))); Ok(()) } } pub struct AdjacentlyTaggedEnumVariant { pub enum_name: &'static str, pub variant_index: u32, pub variant_name: &'static str, } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Serialize for AdjacentlyTaggedEnumVariant { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_unit_variant(self.enum_name, self.variant_index, self.variant_name) } } // Error when Serialize for a non_exhaustive remote enum encounters a variant // that is not recognized. pub struct CannotSerializeVariant(pub T); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Display for CannotSerializeVariant where T: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "enum variant cannot be serialized: {:?}", self.0) } } ================================================ FILE: serde_core/Cargo.toml ================================================ [package] name = "serde_core" version = "1.0.228" authors = ["Erick Tryzelaar ", "David Tolnay "] build = "build.rs" categories = ["encoding", "no-std", "no-std::no-alloc"] description = "Serde traits only, with no support for derive -- use the `serde` crate instead" documentation = "https://docs.rs/serde_core" edition = "2021" homepage = "https://serde.rs" keywords = ["serde", "serialization", "no_std"] license = "MIT OR Apache-2.0" repository = "https://github.com/serde-rs/serde" rust-version = "1.56" [dev-dependencies] serde = { version = "1", path = "../serde" } serde_derive = { version = "1", path = "../serde_derive" } [package.metadata.playground] features = ["rc", "result"] [package.metadata.docs.rs] features = ["rc", "result", "unstable"] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = [ "--generate-link-to-definition", "--generate-macro-expansion", "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", ] # This cfg cannot be enabled, but it still forces Cargo to keep serde_derive's # version in lockstep with serde's, even if someone depends on the two crates # separately with serde's "derive" feature disabled. Every serde_derive release # is compatible with exactly one serde release because the generated code # involves nonpublic APIs which are not bound by semver. [target.'cfg(any())'.dependencies] serde_derive = { version = "=1.0.228", path = "../serde_derive" } ### FEATURES ################################################################# [features] default = ["std", "result"] # Provide impls for common standard library types like Vec and HashMap. # Requires a dependency on the Rust standard library. std = [] # Provide impls for types that require unstable functionality. For tracking and # discussion of unstable functionality please refer to this issue: # # https://github.com/serde-rs/serde/issues/812 unstable = [] # Provide impls for types in the Rust core allocation and collections library # including String, Box, Vec, and Cow. This is a subset of std but may # be enabled without depending on all of std. alloc = [] # Opt into impls for Rc and Arc. Serializing and deserializing these types # does not preserve identity and may result in multiple copies of the same data. # Be sure that this is what you want before enabling this feature. rc = [] # Provide impls for Result. Convenient in some contexts but can lead to # confusion if ? or unwrap are used incautiously. result = [] ================================================ FILE: serde_core/README.md ================================================ The `serde_core` crate contains Serde's trait definitions with **no support for #\[derive()\]**. In crates that derive an implementation of `Serialize` or `Deserialize`, you must depend on the [`serde`] crate, not `serde_core`. [`serde`]: https://crates.io/crates/serde In crates that handwrite implementations of Serde traits, or only use them as trait bounds, depending on `serde_core` is permitted. But `serde` re-exports all of these traits and can be used for this use case too. If in doubt, disregard `serde_core` and always use `serde`. Crates that depend on `serde_core` instead of `serde` are able to compile in parallel with `serde_derive` even when `serde`'s "derive" feature is turned on, as shown in the following build timings.
| When `serde_json` depends on `serde` | |---| | |
| When `serde_json` depends on `serde_core` | |---| | | ================================================ FILE: serde_core/build.rs ================================================ use std::env; use std::fs; use std::path::PathBuf; use std::process::Command; use std::str; const PRIVATE: &str = "\ #[doc(hidden)] pub mod __private$$ { #[doc(hidden)] pub use crate::private::*; } "; // The rustc-cfg strings below are *not* public API. Please let us know by // opening a GitHub issue if your build environment requires some way to enable // these cfgs other than by executing our build script. fn main() { println!("cargo:rerun-if-changed=build.rs"); let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let patch_version = env::var("CARGO_PKG_VERSION_PATCH").unwrap(); let module = PRIVATE.replace("$$", &patch_version); fs::write(out_dir.join("private.rs"), module).unwrap(); let minor = match rustc_minor_version() { Some(minor) => minor, None => return, }; if minor >= 77 { println!("cargo:rustc-check-cfg=cfg(if_docsrs_then_no_serde_core)"); println!("cargo:rustc-check-cfg=cfg(no_core_cstr)"); println!("cargo:rustc-check-cfg=cfg(no_core_error)"); println!("cargo:rustc-check-cfg=cfg(no_core_net)"); println!("cargo:rustc-check-cfg=cfg(no_core_num_saturating)"); println!("cargo:rustc-check-cfg=cfg(no_diagnostic_namespace)"); println!("cargo:rustc-check-cfg=cfg(no_serde_derive)"); println!("cargo:rustc-check-cfg=cfg(no_std_atomic)"); println!("cargo:rustc-check-cfg=cfg(no_std_atomic64)"); println!("cargo:rustc-check-cfg=cfg(no_target_has_atomic)"); } let target = env::var("TARGET").unwrap(); let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten"; // Support for #[cfg(target_has_atomic = "...")] stabilized in Rust 1.60. if minor < 60 { println!("cargo:rustc-cfg=no_target_has_atomic"); // Allowlist of archs that support std::sync::atomic module. This is // based on rustc's compiler/rustc_target/src/spec/*.rs. let has_atomic64 = target.starts_with("x86_64") || target.starts_with("i686") || target.starts_with("aarch64") || target.starts_with("powerpc64") || target.starts_with("sparc64") || target.starts_with("mips64el") || target.starts_with("riscv64"); let has_atomic32 = has_atomic64 || emscripten; if minor < 34 || !has_atomic64 { println!("cargo:rustc-cfg=no_std_atomic64"); } if minor < 34 || !has_atomic32 { println!("cargo:rustc-cfg=no_std_atomic"); } } // Support for core::ffi::CStr and alloc::ffi::CString stabilized in Rust 1.64. // https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#c-compatible-ffi-types-in-core-and-alloc if minor < 64 { println!("cargo:rustc-cfg=no_core_cstr"); } // Current minimum supported version of serde_derive crate is Rust 1.71. if minor < 71 { println!("cargo:rustc-cfg=no_serde_derive"); } // Support for core::num::Saturating and std::num::Saturating stabilized in Rust 1.74 // https://blog.rust-lang.org/2023/11/16/Rust-1.74.0.html#stabilized-apis if minor < 74 { println!("cargo:rustc-cfg=no_core_num_saturating"); } // Support for core::net stabilized in Rust 1.77. // https://blog.rust-lang.org/2024/03/21/Rust-1.77.0.html if minor < 77 { println!("cargo:rustc-cfg=no_core_net"); } // Support for the `#[diagnostic]` tool attribute namespace // https://blog.rust-lang.org/2024/05/02/Rust-1.78.0.html#diagnostic-attributes if minor < 78 { println!("cargo:rustc-cfg=no_diagnostic_namespace"); } // The Error trait became available in core in 1.81. // https://blog.rust-lang.org/2024/09/05/Rust-1.81.0.html#coreerrorerror if minor < 81 { println!("cargo:rustc-cfg=no_core_error"); } } fn rustc_minor_version() -> Option { let rustc = env::var_os("RUSTC")?; let output = Command::new(rustc).arg("--version").output().ok()?; let version = str::from_utf8(&output.stdout).ok()?; let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } pieces.next()?.parse().ok() } ================================================ FILE: serde_core/src/crate_root.rs ================================================ macro_rules! crate_root { () => { /// A facade around all the types we need from the `std`, `core`, and `alloc` /// crates. This avoids elaborate import wrangling having to happen in every /// module. mod lib { mod core { #[cfg(not(feature = "std"))] pub use core::*; #[cfg(feature = "std")] pub use std::*; } pub use self::core::{f32, f64}; pub use self::core::{iter, num, str}; #[cfg(any(feature = "std", feature = "alloc"))] pub use self::core::{cmp, mem}; pub use self::core::cell::{Cell, RefCell}; pub use self::core::cmp::Reverse; pub use self::core::fmt::{self, Debug, Display, Write as FmtWrite}; pub use self::core::marker::PhantomData; pub use self::core::num::Wrapping; pub use self::core::ops::{Bound, Range, RangeFrom, RangeInclusive, RangeTo}; pub use self::core::result; pub use self::core::time::Duration; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::borrow::{Cow, ToOwned}; #[cfg(feature = "std")] pub use std::borrow::{Cow, ToOwned}; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::string::{String, ToString}; #[cfg(feature = "std")] pub use std::string::{String, ToString}; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::vec::Vec; #[cfg(feature = "std")] pub use std::vec::Vec; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::boxed::Box; #[cfg(feature = "std")] pub use std::boxed::Box; #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))] pub use alloc::rc::{Rc, Weak as RcWeak}; #[cfg(all(feature = "rc", feature = "std"))] pub use std::rc::{Rc, Weak as RcWeak}; #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))] pub use alloc::sync::{Arc, Weak as ArcWeak}; #[cfg(all(feature = "rc", feature = "std"))] pub use std::sync::{Arc, Weak as ArcWeak}; #[cfg(all(feature = "alloc", not(feature = "std")))] pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; #[cfg(feature = "std")] pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; #[cfg(all(not(no_core_cstr), not(feature = "std")))] pub use self::core::ffi::CStr; #[cfg(feature = "std")] pub use std::ffi::CStr; #[cfg(all(not(no_core_cstr), feature = "alloc", not(feature = "std")))] pub use alloc::ffi::CString; #[cfg(feature = "std")] pub use std::ffi::CString; #[cfg(all(not(no_core_net), not(feature = "std")))] pub use self::core::net; #[cfg(feature = "std")] pub use std::net; #[cfg(feature = "std")] pub use std::error; #[cfg(feature = "std")] pub use std::collections::{HashMap, HashSet}; #[cfg(feature = "std")] pub use std::ffi::{OsStr, OsString}; #[cfg(feature = "std")] pub use std::hash::{BuildHasher, Hash}; #[cfg(feature = "std")] pub use std::io::Write; #[cfg(feature = "std")] pub use std::path::{Path, PathBuf}; #[cfg(feature = "std")] pub use std::sync::{Mutex, RwLock}; #[cfg(feature = "std")] pub use std::time::{SystemTime, UNIX_EPOCH}; #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic)))] pub use std::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, Ordering, }; #[cfg(all(feature = "std", no_target_has_atomic, not(no_std_atomic64)))] pub use std::sync::atomic::{AtomicI64, AtomicU64}; #[cfg(all(feature = "std", not(no_target_has_atomic)))] pub use std::sync::atomic::Ordering; #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "8"))] pub use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU8}; #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "16"))] pub use std::sync::atomic::{AtomicI16, AtomicU16}; #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "32"))] pub use std::sync::atomic::{AtomicI32, AtomicU32}; #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "64"))] pub use std::sync::atomic::{AtomicI64, AtomicU64}; #[cfg(all(feature = "std", not(no_target_has_atomic), target_has_atomic = "ptr"))] pub use std::sync::atomic::{AtomicIsize, AtomicUsize}; #[cfg(not(no_core_num_saturating))] pub use self::core::num::Saturating; } // None of this crate's error handling needs the `From::from` error conversion // performed implicitly by the `?` operator or the standard library's `try!` // macro. This simplified macro gives a 5.5% improvement in compile time // compared to standard `try!`, and 9% improvement compared to `?`. macro_rules! tri { ($expr:expr) => { match $expr { Ok(val) => val, Err(err) => return Err(err), } }; } #[cfg_attr(all(docsrs, if_docsrs_then_no_serde_core), path = "core/de/mod.rs")] pub mod de; #[cfg_attr(all(docsrs, if_docsrs_then_no_serde_core), path = "core/ser/mod.rs")] pub mod ser; #[cfg_attr(all(docsrs, if_docsrs_then_no_serde_core), path = "core/format.rs")] mod format; #[doc(inline)] pub use crate::de::{Deserialize, Deserializer}; #[doc(inline)] pub use crate::ser::{Serialize, Serializer}; // Used by generated code. Not public API. #[doc(hidden)] #[cfg_attr( all(docsrs, if_docsrs_then_no_serde_core), path = "core/private/mod.rs" )] mod private; // Used by declarative macro generated code. Not public API. #[doc(hidden)] pub mod __private { #[doc(hidden)] pub use crate::private::doc; #[doc(hidden)] pub use core::result::Result; } include!(concat!(env!("OUT_DIR"), "/private.rs")); #[cfg(all(not(feature = "std"), no_core_error))] #[cfg_attr(all(docsrs, if_docsrs_then_no_serde_core), path = "core/std_error.rs")] mod std_error; }; } ================================================ FILE: serde_core/src/de/ignored_any.rs ================================================ use crate::lib::*; use crate::de::{ Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor, }; /// An efficient way of discarding data from a deserializer. /// /// Think of this like `serde_json::Value` in that it can be deserialized from /// any type, except that it does not store any information about the data that /// gets deserialized. /// /// ```edition2021 /// use serde::de::{ /// self, Deserialize, DeserializeSeed, Deserializer, IgnoredAny, SeqAccess, Visitor, /// }; /// use std::fmt; /// use std::marker::PhantomData; /// /// /// A seed that can be used to deserialize only the `n`th element of a sequence /// /// while efficiently discarding elements of any type before or after index `n`. /// /// /// /// For example to deserialize only the element at index 3: /// /// /// /// ``` /// /// NthElement::new(3).deserialize(deserializer) /// /// ``` /// pub struct NthElement { /// n: usize, /// marker: PhantomData, /// } /// /// impl NthElement { /// pub fn new(n: usize) -> Self { /// NthElement { /// n: n, /// marker: PhantomData, /// } /// } /// } /// /// impl<'de, T> Visitor<'de> for NthElement /// where /// T: Deserialize<'de>, /// { /// type Value = T; /// /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// write!( /// formatter, /// "a sequence in which we care about element {}", /// self.n /// ) /// } /// /// fn visit_seq
(self, mut seq: A) -> Result /// where /// A: SeqAccess<'de>, /// { /// // Skip over the first `n` elements. /// for i in 0..self.n { /// // It is an error if the sequence ends before we get to element `n`. /// if seq.next_element::()?.is_none() { /// return Err(de::Error::invalid_length(i, &self)); /// } /// } /// /// // Deserialize the one we care about. /// let nth = match seq.next_element()? { /// Some(nth) => nth, /// None => { /// return Err(de::Error::invalid_length(self.n, &self)); /// } /// }; /// /// // Skip over any remaining elements in the sequence after `n`. /// while let Some(IgnoredAny) = seq.next_element()? { /// // ignore /// } /// /// Ok(nth) /// } /// } /// /// impl<'de, T> DeserializeSeed<'de> for NthElement /// where /// T: Deserialize<'de>, /// { /// type Value = T; /// /// fn deserialize(self, deserializer: D) -> Result /// where /// D: Deserializer<'de>, /// { /// deserializer.deserialize_seq(self) /// } /// } /// /// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error> /// # where /// # D: Deserializer<'de>, /// # { /// // Deserialize only the sequence element at index 3 from this deserializer. /// // The element at index 3 is required to be a string. Elements before and /// // after index 3 are allowed to be of any type. /// let s: String = NthElement::new(3).deserialize(deserializer)?; /// # Ok(()) /// # } /// ``` #[derive(Copy, Clone, Debug, Default, PartialEq)] pub struct IgnoredAny; impl<'de> Visitor<'de> for IgnoredAny { type Value = IgnoredAny; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("anything at all") } #[inline] fn visit_bool(self, x: bool) -> Result { let _ = x; Ok(IgnoredAny) } #[inline] fn visit_i64(self, x: i64) -> Result { let _ = x; Ok(IgnoredAny) } #[inline] fn visit_i128(self, x: i128) -> Result { let _ = x; Ok(IgnoredAny) } #[inline] fn visit_u64(self, x: u64) -> Result { let _ = x; Ok(IgnoredAny) } #[inline] fn visit_u128(self, x: u128) -> Result { let _ = x; Ok(IgnoredAny) } #[inline] fn visit_f64(self, x: f64) -> Result { let _ = x; Ok(IgnoredAny) } #[inline] fn visit_str(self, s: &str) -> Result where E: Error, { let _ = s; Ok(IgnoredAny) } #[inline] fn visit_none(self) -> Result { Ok(IgnoredAny) } #[inline] fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { IgnoredAny::deserialize(deserializer) } #[inline] fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer<'de>, { IgnoredAny::deserialize(deserializer) } #[inline] fn visit_unit(self) -> Result { Ok(IgnoredAny) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { while let Some(IgnoredAny) = tri!(seq.next_element()) { // Gobble } Ok(IgnoredAny) } #[inline] fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { while let Some((IgnoredAny, IgnoredAny)) = tri!(map.next_entry()) { // Gobble } Ok(IgnoredAny) } #[inline] fn visit_bytes(self, bytes: &[u8]) -> Result where E: Error, { let _ = bytes; Ok(IgnoredAny) } fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { tri!(data.variant::()).1.newtype_variant() } } impl<'de> Deserialize<'de> for IgnoredAny { #[inline] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_ignored_any(IgnoredAny) } } ================================================ FILE: serde_core/src/de/impls.rs ================================================ use crate::lib::*; use crate::de::{ Deserialize, Deserializer, EnumAccess, Error, MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, }; use crate::private::{self, InPlaceSeed}; #[cfg(any(feature = "std", feature = "alloc"))] use crate::private::size_hint; //////////////////////////////////////////////////////////////////////////////// struct UnitVisitor; impl<'de> Visitor<'de> for UnitVisitor { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("unit") } fn visit_unit(self) -> Result where E: Error, { Ok(()) } } impl<'de> Deserialize<'de> for () { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_unit(UnitVisitor) } } #[cfg(feature = "unstable")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] impl<'de> Deserialize<'de> for ! { fn deserialize(_deserializer: D) -> Result where D: Deserializer<'de>, { Err(Error::custom("cannot deserialize `!`")) } } //////////////////////////////////////////////////////////////////////////////// struct BoolVisitor; impl<'de> Visitor<'de> for BoolVisitor { type Value = bool; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a boolean") } fn visit_bool(self, v: bool) -> Result where E: Error, { Ok(v) } } impl<'de> Deserialize<'de> for bool { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_bool(BoolVisitor) } } //////////////////////////////////////////////////////////////////////////////// macro_rules! impl_deserialize_num { ($primitive:ident, $nonzero:ident, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => { impl_deserialize_num!($primitive, $deserialize $($method!($($val : $visit)*);)*); impl<'de> Deserialize<'de> for num::$nonzero { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct NonZeroVisitor; impl<'de> Visitor<'de> for NonZeroVisitor { type Value = num::$nonzero; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(concat!("a nonzero ", stringify!($primitive))) } $($($method!(nonzero $primitive $val : $visit);)*)* } deserializer.$deserialize(NonZeroVisitor) } } #[cfg(not(no_core_num_saturating))] impl<'de> Deserialize<'de> for Saturating<$primitive> { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct SaturatingVisitor; impl<'de> Visitor<'de> for SaturatingVisitor { type Value = Saturating<$primitive>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("integer with support for saturating semantics") } $($($method!(saturating $primitive $val : $visit);)*)* } deserializer.$deserialize(SaturatingVisitor) } } }; ($primitive:ident, $deserialize:ident $($method:ident!($($val:ident : $visit:ident)*);)*) => { impl<'de> Deserialize<'de> for $primitive { #[inline] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct PrimitiveVisitor; impl<'de> Visitor<'de> for PrimitiveVisitor { type Value = $primitive; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(stringify!($primitive)) } $($($method!($val : $visit);)*)* } deserializer.$deserialize(PrimitiveVisitor) } } }; } macro_rules! num_self { ($ty:ident : $visit:ident) => { #[inline] fn $visit(self, v: $ty) -> Result where E: Error, { Ok(v) } }; (nonzero $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if let Some(nonzero) = Self::Value::new(v) { Ok(nonzero) } else { Err(Error::invalid_value(Unexpected::Unsigned(0), &self)) } } }; (saturating $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { Ok(Saturating(v)) } }; } macro_rules! num_as_self { ($ty:ident : $visit:ident) => { #[inline] fn $visit(self, v: $ty) -> Result where E: Error, { Ok(v as Self::Value) } }; (nonzero $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if let Some(nonzero) = Self::Value::new(v as $primitive) { Ok(nonzero) } else { Err(Error::invalid_value(Unexpected::Unsigned(0), &self)) } } }; (saturating $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { Ok(Saturating(v as $primitive)) } }; } macro_rules! num_as_copysign_self { ($ty:ident : $visit:ident) => { #[inline] fn $visit(self, v: $ty) -> Result where E: Error, { #[cfg(not(feature = "std"))] { Ok(v as Self::Value) } #[cfg(feature = "std")] { // Preserve sign of NaN. The `as` produces a nondeterministic sign. let sign = if v.is_sign_positive() { 1.0 } else { -1.0 }; Ok((v as Self::Value).copysign(sign)) } } }; } macro_rules! int_to_int { ($ty:ident : $visit:ident) => { #[inline] fn $visit(self, v: $ty) -> Result where E: Error, { Self::Value::try_from(v as i64) .map_err(|_| Error::invalid_value(Unexpected::Signed(v as i64), &self)) } }; (nonzero $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if let Ok(v) = $primitive::try_from(v as i64) { if let Some(nonzero) = Self::Value::new(v) { return Ok(nonzero); } } Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) } }; (saturating $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if (v as i64) < $primitive::MIN as i64 { Ok(Saturating($primitive::MIN)) } else if ($primitive::MAX as i64) < v as i64 { Ok(Saturating($primitive::MAX)) } else { Ok(Saturating(v as $primitive)) } } }; } macro_rules! int_to_uint { ($ty:ident : $visit:ident) => { #[inline] fn $visit(self, v: $ty) -> Result where E: Error, { if 0 <= v { #[allow(irrefutable_let_patterns)] if let Ok(v) = Self::Value::try_from(v as u64) { return Ok(v as Self::Value); } } Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) } }; (nonzero $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if 0 < v { #[allow(irrefutable_let_patterns)] if let Ok(v) = $primitive::try_from(v as u64) { if let Some(nonzero) = Self::Value::new(v) { return Ok(nonzero); } } } Err(Error::invalid_value(Unexpected::Signed(v as i64), &self)) } }; (saturating $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if v < 0 { Ok(Saturating(0)) } else if ($primitive::MAX as u64) < v as u64 { Ok(Saturating($primitive::MAX)) } else { Ok(Saturating(v as $primitive)) } } }; } macro_rules! uint_to_self { ($ty:ident : $visit:ident) => { #[inline] fn $visit(self, v: $ty) -> Result where E: Error, { Self::Value::try_from(v as u64) .map_err(|_| Error::invalid_value(Unexpected::Unsigned(v as u64), &self)) } }; (nonzero $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if let Ok(v) = $primitive::try_from(v as u64) { if let Some(nonzero) = Self::Value::new(v) { return Ok(nonzero); } } Err(Error::invalid_value(Unexpected::Unsigned(v as u64), &self)) } }; (saturating $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if let Ok(v) = $primitive::try_from(v as u64) { Ok(Saturating(v as $primitive)) } else { Ok(Saturating($primitive::MAX)) } } }; } impl_deserialize_num! { i8, NonZeroI8, deserialize_i8 num_self!(i8:visit_i8); int_to_int!(i16:visit_i16 i32:visit_i32 i64:visit_i64); uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { i16, NonZeroI16, deserialize_i16 num_self!(i16:visit_i16); num_as_self!(i8:visit_i8); int_to_int!(i32:visit_i32 i64:visit_i64); uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { i32, NonZeroI32, deserialize_i32 num_self!(i32:visit_i32); num_as_self!(i8:visit_i8 i16:visit_i16); int_to_int!(i64:visit_i64); uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { i64, NonZeroI64, deserialize_i64 num_self!(i64:visit_i64); num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32); uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { isize, NonZeroIsize, deserialize_i64 num_as_self!(i8:visit_i8 i16:visit_i16); int_to_int!(i32:visit_i32 i64:visit_i64); uint_to_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { u8, NonZeroU8, deserialize_u8 num_self!(u8:visit_u8); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); uint_to_self!(u16:visit_u16 u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { u16, NonZeroU16, deserialize_u16 num_self!(u16:visit_u16); num_as_self!(u8:visit_u8); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); uint_to_self!(u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { u32, NonZeroU32, deserialize_u32 num_self!(u32:visit_u32); num_as_self!(u8:visit_u8 u16:visit_u16); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); uint_to_self!(u64:visit_u64); } impl_deserialize_num! { u64, NonZeroU64, deserialize_u64 num_self!(u64:visit_u64); num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); } impl_deserialize_num! { usize, NonZeroUsize, deserialize_u64 num_as_self!(u8:visit_u8 u16:visit_u16); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); uint_to_self!(u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { f32, deserialize_f32 num_self!(f32:visit_f32); num_as_copysign_self!(f64:visit_f64); num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } impl_deserialize_num! { f64, deserialize_f64 num_self!(f64:visit_f64); num_as_copysign_self!(f32:visit_f32); num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); } macro_rules! num_128 { ($ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if v as i128 >= Self::Value::MIN as i128 && v as u128 <= Self::Value::MAX as u128 { Ok(v as Self::Value) } else { Err(Error::invalid_value( Unexpected::Other(stringify!($ty)), &self, )) } } }; (nonzero $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if v as i128 >= $primitive::MIN as i128 && v as u128 <= $primitive::MAX as u128 { if let Some(nonzero) = Self::Value::new(v as $primitive) { Ok(nonzero) } else { Err(Error::invalid_value(Unexpected::Unsigned(0), &self)) } } else { Err(Error::invalid_value( Unexpected::Other(stringify!($ty)), &self, )) } } }; (saturating $primitive:ident $ty:ident : $visit:ident) => { fn $visit(self, v: $ty) -> Result where E: Error, { if (v as i128) < $primitive::MIN as i128 { Ok(Saturating($primitive::MIN)) } else if ($primitive::MAX as u128) < v as u128 { Ok(Saturating($primitive::MAX)) } else { Ok(Saturating(v as $primitive)) } } }; } impl_deserialize_num! { i128, NonZeroI128, deserialize_i128 num_self!(i128:visit_i128); num_as_self!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); num_128!(u128:visit_u128); } impl_deserialize_num! { u128, NonZeroU128, deserialize_u128 num_self!(u128:visit_u128); num_as_self!(u8:visit_u8 u16:visit_u16 u32:visit_u32 u64:visit_u64); int_to_uint!(i8:visit_i8 i16:visit_i16 i32:visit_i32 i64:visit_i64); num_128!(i128:visit_i128); } //////////////////////////////////////////////////////////////////////////////// struct CharVisitor; impl<'de> Visitor<'de> for CharVisitor { type Value = char; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a character") } #[inline] fn visit_char(self, v: char) -> Result where E: Error, { Ok(v) } #[inline] fn visit_str(self, v: &str) -> Result where E: Error, { let mut iter = v.chars(); match (iter.next(), iter.next()) { (Some(c), None) => Ok(c), _ => Err(Error::invalid_value(Unexpected::Str(v), &self)), } } } impl<'de> Deserialize<'de> for char { #[inline] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_char(CharVisitor) } } //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] struct StringVisitor; #[cfg(any(feature = "std", feature = "alloc"))] struct StringInPlaceVisitor<'a>(&'a mut String); #[cfg(any(feature = "std", feature = "alloc"))] impl<'de> Visitor<'de> for StringVisitor { type Value = String; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string") } fn visit_str(self, v: &str) -> Result where E: Error, { Ok(v.to_owned()) } fn visit_string(self, v: String) -> Result where E: Error, { Ok(v) } fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { match str::from_utf8(v) { Ok(s) => Ok(s.to_owned()), Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), } } fn visit_byte_buf(self, v: Vec) -> Result where E: Error, { match String::from_utf8(v) { Ok(s) => Ok(s), Err(e) => Err(Error::invalid_value( Unexpected::Bytes(&e.into_bytes()), &self, )), } } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, 'de> Visitor<'de> for StringInPlaceVisitor<'a> { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string") } fn visit_str(self, v: &str) -> Result where E: Error, { self.0.clear(); self.0.push_str(v); Ok(()) } fn visit_string(self, v: String) -> Result where E: Error, { *self.0 = v; Ok(()) } fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { match str::from_utf8(v) { Ok(s) => { self.0.clear(); self.0.push_str(s); Ok(()) } Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)), } } fn visit_byte_buf(self, v: Vec) -> Result where E: Error, { match String::from_utf8(v) { Ok(s) => { *self.0 = s; Ok(()) } Err(e) => Err(Error::invalid_value( Unexpected::Bytes(&e.into_bytes()), &self, )), } } } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de> Deserialize<'de> for String { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_string(StringVisitor) } fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> where D: Deserializer<'de>, { deserializer.deserialize_string(StringInPlaceVisitor(place)) } } //////////////////////////////////////////////////////////////////////////////// struct StrVisitor; impl<'a> Visitor<'a> for StrVisitor { type Value = &'a str; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a borrowed string") } fn visit_borrowed_str(self, v: &'a str) -> Result where E: Error, { Ok(v) // so easy } fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result where E: Error, { str::from_utf8(v).map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self)) } } impl<'de: 'a, 'a> Deserialize<'de> for &'a str { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_str(StrVisitor) } } //////////////////////////////////////////////////////////////////////////////// struct BytesVisitor; impl<'a> Visitor<'a> for BytesVisitor { type Value = &'a [u8]; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a borrowed byte array") } fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result where E: Error, { Ok(v) } fn visit_borrowed_str(self, v: &'a str) -> Result where E: Error, { Ok(v.as_bytes()) } } impl<'de: 'a, 'a> Deserialize<'de> for &'a [u8] { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_bytes(BytesVisitor) } } //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] struct CStringVisitor; #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] impl<'de> Visitor<'de> for CStringVisitor { type Value = CString; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("byte array") } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let capacity = size_hint::cautious::(seq.size_hint()); let mut values = Vec::::with_capacity(capacity); while let Some(value) = tri!(seq.next_element()) { values.push(value); } CString::new(values).map_err(Error::custom) } fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { CString::new(v).map_err(Error::custom) } fn visit_byte_buf(self, v: Vec) -> Result where E: Error, { CString::new(v).map_err(Error::custom) } fn visit_str(self, v: &str) -> Result where E: Error, { CString::new(v).map_err(Error::custom) } fn visit_string(self, v: String) -> Result where E: Error, { CString::new(v).map_err(Error::custom) } } #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de> Deserialize<'de> for CString { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_byte_buf(CStringVisitor) } } macro_rules! forwarded_impl { ( $(#[$attr:meta])* ($($id:ident),*), $ty:ty, $func:expr ) => { $(#[$attr])* impl<'de $(, $id : Deserialize<'de>,)*> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Deserialize::deserialize(deserializer).map($func) } } } } forwarded_impl! { #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] (), Box, CString::into_boxed_c_str } forwarded_impl! { (T), Reverse, Reverse } //////////////////////////////////////////////////////////////////////////////// struct OptionVisitor { marker: PhantomData, } impl<'de, T> Visitor<'de> for OptionVisitor where T: Deserialize<'de>, { type Value = Option; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("option") } #[inline] fn visit_unit(self) -> Result where E: Error, { Ok(None) } #[inline] fn visit_none(self) -> Result where E: Error, { Ok(None) } #[inline] fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { T::deserialize(deserializer).map(Some) } fn __private_visit_untagged_option(self, deserializer: D) -> Result where D: Deserializer<'de>, { Ok(T::deserialize(deserializer).ok()) } } impl<'de, T> Deserialize<'de> for Option where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_option(OptionVisitor { marker: PhantomData, }) } // The Some variant's repr is opaque, so we can't play cute tricks with its // tag to have deserialize_in_place build the content in place unconditionally. // // FIXME: investigate whether branching on the old value being Some to // deserialize_in_place the value is profitable (probably data-dependent?) } //////////////////////////////////////////////////////////////////////////////// struct PhantomDataVisitor { marker: PhantomData, } impl<'de, T> Visitor<'de> for PhantomDataVisitor where T: ?Sized, { type Value = PhantomData; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("unit") } #[inline] fn visit_unit(self) -> Result where E: Error, { Ok(PhantomData) } } impl<'de, T> Deserialize<'de> for PhantomData where T: ?Sized, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let visitor = PhantomDataVisitor { marker: PhantomData, }; deserializer.deserialize_unit_struct("PhantomData", visitor) } } //////////////////////////////////////////////////////////////////////////////// macro_rules! seq_impl { ( $(#[$attr:meta])* $ty:ident , $access:ident, $clear:expr, $with_capacity:expr, $reserve:expr, $insert:expr ) => { $(#[$attr])* impl<'de, T $(, $typaram)*> Deserialize<'de> for $ty where T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, $($typaram: $bound1 $(+ $bound2)*,)* { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct SeqVisitor { marker: PhantomData<$ty>, } impl<'de, T $(, $typaram)*> Visitor<'de> for SeqVisitor where T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, $($typaram: $bound1 $(+ $bound2)*,)* { type Value = $ty; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence") } #[inline] fn visit_seq(self, mut $access: A) -> Result where A: SeqAccess<'de>, { let mut values = $with_capacity; while let Some(value) = tri!($access.next_element()) { $insert(&mut values, value); } Ok(values) } } let visitor = SeqVisitor { marker: PhantomData }; deserializer.deserialize_seq(visitor) } fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> where D: Deserializer<'de>, { struct SeqInPlaceVisitor<'a, T: 'a $(, $typaram: 'a)*>(&'a mut $ty); impl<'a, 'de, T $(, $typaram)*> Visitor<'de> for SeqInPlaceVisitor<'a, T $(, $typaram)*> where T: Deserialize<'de> $(+ $tbound1 $(+ $tbound2)*)*, $($typaram: $bound1 $(+ $bound2)*,)* { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence") } #[inline] fn visit_seq(mut self, mut $access: A) -> Result where A: SeqAccess<'de>, { $clear(&mut self.0); $reserve(&mut self.0, size_hint::cautious::($access.size_hint())); // FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList) while let Some(value) = tri!($access.next_element()) { $insert(&mut self.0, value); } Ok(()) } } deserializer.deserialize_seq(SeqInPlaceVisitor(place)) } } } } // Dummy impl of reserve #[cfg(any(feature = "std", feature = "alloc"))] fn nop_reserve(_seq: T, _n: usize) {} seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BinaryHeap, seq, BinaryHeap::clear, BinaryHeap::with_capacity(size_hint::cautious::(seq.size_hint())), BinaryHeap::reserve, BinaryHeap::push ); seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeSet, seq, BTreeSet::clear, BTreeSet::new(), nop_reserve, BTreeSet::insert ); seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] LinkedList, seq, LinkedList::clear, LinkedList::new(), nop_reserve, LinkedList::push_back ); seq_impl!( #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] HashSet, seq, HashSet::clear, HashSet::with_capacity_and_hasher(size_hint::cautious::(seq.size_hint()), S::default()), HashSet::reserve, HashSet::insert ); seq_impl!( #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] VecDeque, seq, VecDeque::clear, VecDeque::with_capacity(size_hint::cautious::(seq.size_hint())), VecDeque::reserve, VecDeque::push_back ); //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T> Deserialize<'de> for Vec where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct VecVisitor { marker: PhantomData, } impl<'de, T> Visitor<'de> for VecVisitor where T: Deserialize<'de>, { type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence") } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let capacity = size_hint::cautious::(seq.size_hint()); let mut values = Vec::::with_capacity(capacity); while let Some(value) = tri!(seq.next_element()) { values.push(value); } Ok(values) } } let visitor = VecVisitor { marker: PhantomData, }; deserializer.deserialize_seq(visitor) } fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> where D: Deserializer<'de>, { struct VecInPlaceVisitor<'a, T: 'a>(&'a mut Vec); impl<'a, 'de, T> Visitor<'de> for VecInPlaceVisitor<'a, T> where T: Deserialize<'de>, { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence") } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let hint = size_hint::cautious::(seq.size_hint()); if let Some(additional) = hint.checked_sub(self.0.len()) { self.0.reserve(additional); } for i in 0..self.0.len() { let next = { let next_place = InPlaceSeed(&mut self.0[i]); tri!(seq.next_element_seed(next_place)) }; if next.is_none() { self.0.truncate(i); return Ok(()); } } while let Some(value) = tri!(seq.next_element()) { self.0.push(value); } Ok(()) } } deserializer.deserialize_seq(VecInPlaceVisitor(place)) } } //////////////////////////////////////////////////////////////////////////////// struct ArrayVisitor { marker: PhantomData, } struct ArrayInPlaceVisitor<'a, A: 'a>(&'a mut A); impl ArrayVisitor { fn new() -> Self { ArrayVisitor { marker: PhantomData, } } } impl<'de, T> Visitor<'de> for ArrayVisitor<[T; 0]> { type Value = [T; 0]; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("an empty array") } #[inline] fn visit_seq(self, _: A) -> Result where A: SeqAccess<'de>, { Ok([]) } } // Does not require T: Deserialize<'de>. impl<'de, T> Deserialize<'de> for [T; 0] { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_tuple(0, ArrayVisitor::<[T; 0]>::new()) } } macro_rules! array_impls { ($($len:expr => ($($n:tt)+))+) => { $( impl<'de, T> Visitor<'de> for ArrayVisitor<[T; $len]> where T: Deserialize<'de>, { type Value = [T; $len]; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(concat!("an array of length ", $len)) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { Ok([$( match tri!(seq.next_element()) { Some(val) => val, None => return Err(Error::invalid_length($n, &self)), } ),+]) } } impl<'a, 'de, T> Visitor<'de> for ArrayInPlaceVisitor<'a, [T; $len]> where T: Deserialize<'de>, { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(concat!("an array of length ", $len)) } #[inline] fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let mut fail_idx = None; for (idx, dest) in self.0[..].iter_mut().enumerate() { if tri!(seq.next_element_seed(InPlaceSeed(dest))).is_none() { fail_idx = Some(idx); break; } } if let Some(idx) = fail_idx { return Err(Error::invalid_length(idx, &self)); } Ok(()) } } impl<'de, T> Deserialize<'de> for [T; $len] where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_tuple($len, ArrayVisitor::<[T; $len]>::new()) } fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> where D: Deserializer<'de>, { deserializer.deserialize_tuple($len, ArrayInPlaceVisitor(place)) } } )+ } } array_impls! { 1 => (0) 2 => (0 1) 3 => (0 1 2) 4 => (0 1 2 3) 5 => (0 1 2 3 4) 6 => (0 1 2 3 4 5) 7 => (0 1 2 3 4 5 6) 8 => (0 1 2 3 4 5 6 7) 9 => (0 1 2 3 4 5 6 7 8) 10 => (0 1 2 3 4 5 6 7 8 9) 11 => (0 1 2 3 4 5 6 7 8 9 10) 12 => (0 1 2 3 4 5 6 7 8 9 10 11) 13 => (0 1 2 3 4 5 6 7 8 9 10 11 12) 14 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13) 15 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14) 16 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) 17 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) 18 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17) 19 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18) 20 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19) 21 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20) 22 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21) 23 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22) 24 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23) 25 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24) 26 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25) 27 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26) 28 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27) 29 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28) 30 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29) 31 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30) 32 => (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) } //////////////////////////////////////////////////////////////////////////////// macro_rules! tuple_impls { ($($len:tt => ($($n:tt $name:ident)+))+) => { $( #[cfg_attr(docsrs, doc(hidden))] impl<'de, $($name),+> Deserialize<'de> for ($($name,)+) where $($name: Deserialize<'de>,)+ { tuple_impl_body!($len => ($($n $name)+)); } )+ }; } macro_rules! tuple_impl_body { ($len:tt => ($($n:tt $name:ident)+)) => { #[inline] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct TupleVisitor<$($name,)+> { marker: PhantomData<($($name,)+)>, } impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> { type Value = ($($name,)+); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(concat!("a tuple of size ", $len)) } #[inline] #[allow(non_snake_case)] fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { $( let $name = match tri!(seq.next_element()) { Some(value) => value, None => return Err(Error::invalid_length($n, &self)), }; )+ Ok(($($name,)+)) } } deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData }) } #[inline] fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> where D: Deserializer<'de>, { struct TupleInPlaceVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+)); impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleInPlaceVisitor<'a, $($name,)+> { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(concat!("a tuple of size ", $len)) } #[inline] #[allow(non_snake_case)] fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { $( if tri!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() { return Err(Error::invalid_length($n, &self)); } )+ Ok(()) } } deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place)) } }; } #[cfg_attr(docsrs, doc(fake_variadic))] #[cfg_attr( docsrs, doc = "This trait is implemented for tuples up to 16 items long." )] impl<'de, T> Deserialize<'de> for (T,) where T: Deserialize<'de>, { tuple_impl_body!(1 => (0 T)); } tuple_impls! { 2 => (0 T0 1 T1) 3 => (0 T0 1 T1 2 T2) 4 => (0 T0 1 T1 2 T2 3 T3) 5 => (0 T0 1 T1 2 T2 3 T3 4 T4) 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5) 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6) 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7) 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8) 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9) 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10) 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11) 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12) 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13) 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14) 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15) } //////////////////////////////////////////////////////////////////////////////// macro_rules! map_impl { ( $(#[$attr:meta])* $ty:ident , $access:ident, $with_capacity:expr, ) => { $(#[$attr])* impl<'de, K, V $(, $typaram)*> Deserialize<'de> for $ty where K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, V: Deserialize<'de>, $($typaram: $bound1 $(+ $bound2)*),* { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct MapVisitor { marker: PhantomData<$ty>, } impl<'de, K, V $(, $typaram)*> Visitor<'de> for MapVisitor where K: Deserialize<'de> $(+ $kbound1 $(+ $kbound2)*)*, V: Deserialize<'de>, $($typaram: $bound1 $(+ $bound2)*),* { type Value = $ty; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a map") } #[inline] fn visit_map(self, mut $access: A) -> Result where A: MapAccess<'de>, { let mut values = $with_capacity; while let Some((key, value)) = tri!($access.next_entry()) { values.insert(key, value); } Ok(values) } } let visitor = MapVisitor { marker: PhantomData }; deserializer.deserialize_map(visitor) } } } } map_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeMap, map, BTreeMap::new(), } map_impl! { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] HashMap, map, HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default()), } //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! parse_ip_impl { ($ty:ty, $expecting:expr, $size:tt) => { impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { if deserializer.is_human_readable() { deserializer.deserialize_str(FromStrVisitor::new($expecting)) } else { <[u8; $size]>::deserialize(deserializer).map(<$ty>::from) } } } }; } #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! variant_identifier { ( $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*) $expecting_message:expr, $variants_name:ident ) => { enum $name_kind { $($variant),* } static $variants_name: &[&str] = &[$(stringify!($variant)),*]; impl<'de> Deserialize<'de> for $name_kind { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct KindVisitor; impl<'de> Visitor<'de> for KindVisitor { type Value = $name_kind; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str($expecting_message) } fn visit_u64(self, value: u64) -> Result where E: Error, { match value { $( $index => Ok($name_kind :: $variant), )* _ => Err(Error::invalid_value(Unexpected::Unsigned(value), &self),), } } fn visit_str(self, value: &str) -> Result where E: Error, { match value { $( stringify!($variant) => Ok($name_kind :: $variant), )* _ => Err(Error::unknown_variant(value, $variants_name)), } } fn visit_bytes(self, value: &[u8]) -> Result where E: Error, { match value { $( $bytes => Ok($name_kind :: $variant), )* _ => { match str::from_utf8(value) { Ok(value) => Err(Error::unknown_variant(value, $variants_name)), Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)), } } } } } deserializer.deserialize_identifier(KindVisitor) } } } } #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! deserialize_enum { ( $name:ident $name_kind:ident ($($variant:ident; $bytes:expr; $index:expr),*) $expecting_message:expr, $deserializer:expr ) => { variant_identifier! { $name_kind ($($variant; $bytes; $index),*) $expecting_message, VARIANTS } struct EnumVisitor; impl<'de> Visitor<'de> for EnumVisitor { type Value = $name; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(concat!("a ", stringify!($name))) } fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { match tri!(data.variant()) { $( ($name_kind :: $variant, v) => v.newtype_variant().map($name :: $variant), )* } } } $deserializer.deserialize_enum(stringify!($name), VARIANTS, EnumVisitor) } } #[cfg(any(feature = "std", not(no_core_net)))] impl<'de> Deserialize<'de> for net::IpAddr { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { if deserializer.is_human_readable() { deserializer.deserialize_str(FromStrVisitor::new("IP address")) } else { use crate::lib::net::IpAddr; deserialize_enum! { IpAddr IpAddrKind (V4; b"V4"; 0, V6; b"V6"; 1) "`V4` or `V6`", deserializer } } } } #[cfg(any(feature = "std", not(no_core_net)))] parse_ip_impl!(net::Ipv4Addr, "IPv4 address", 4); #[cfg(any(feature = "std", not(no_core_net)))] parse_ip_impl!(net::Ipv6Addr, "IPv6 address", 16); #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! parse_socket_impl { ( $ty:ty, $expecting:tt, $new:expr, ) => { impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { if deserializer.is_human_readable() { deserializer.deserialize_str(FromStrVisitor::new($expecting)) } else { <(_, u16)>::deserialize(deserializer).map($new) } } } }; } #[cfg(any(feature = "std", not(no_core_net)))] impl<'de> Deserialize<'de> for net::SocketAddr { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { if deserializer.is_human_readable() { deserializer.deserialize_str(FromStrVisitor::new("socket address")) } else { use crate::lib::net::SocketAddr; deserialize_enum! { SocketAddr SocketAddrKind (V4; b"V4"; 0, V6; b"V6"; 1) "`V4` or `V6`", deserializer } } } } #[cfg(any(feature = "std", not(no_core_net)))] parse_socket_impl! { net::SocketAddrV4, "IPv4 socket address", |(ip, port)| net::SocketAddrV4::new(ip, port), } #[cfg(any(feature = "std", not(no_core_net)))] parse_socket_impl! { net::SocketAddrV6, "IPv6 socket address", |(ip, port)| net::SocketAddrV6::new(ip, port, 0, 0), } //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] struct PathVisitor; #[cfg(feature = "std")] impl<'a> Visitor<'a> for PathVisitor { type Value = &'a Path; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a borrowed path") } fn visit_borrowed_str(self, v: &'a str) -> Result where E: Error, { Ok(v.as_ref()) } fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result where E: Error, { str::from_utf8(v) .map(AsRef::as_ref) .map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self)) } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_str(PathVisitor) } } #[cfg(feature = "std")] struct PathBufVisitor; #[cfg(feature = "std")] impl<'de> Visitor<'de> for PathBufVisitor { type Value = PathBuf; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("path string") } fn visit_str(self, v: &str) -> Result where E: Error, { Ok(From::from(v)) } fn visit_string(self, v: String) -> Result where E: Error, { Ok(From::from(v)) } fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { str::from_utf8(v) .map(From::from) .map_err(|_| Error::invalid_value(Unexpected::Bytes(v), &self)) } fn visit_byte_buf(self, v: Vec) -> Result where E: Error, { String::from_utf8(v) .map(From::from) .map_err(|e| Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)) } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for PathBuf { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_string(PathBufVisitor) } } forwarded_impl! { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] (), Box, PathBuf::into_boxed_path } //////////////////////////////////////////////////////////////////////////////// // If this were outside of the serde crate, it would just use: // // #[derive(Deserialize)] // #[serde(variant_identifier)] #[cfg(all(feature = "std", any(unix, windows)))] variant_identifier! { OsStringKind (Unix; b"Unix"; 0, Windows; b"Windows"; 1) "`Unix` or `Windows`", OSSTR_VARIANTS } #[cfg(all(feature = "std", any(unix, windows)))] struct OsStringVisitor; #[cfg(all(feature = "std", any(unix, windows)))] impl<'de> Visitor<'de> for OsStringVisitor { type Value = OsString; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("os string") } #[cfg(unix)] fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { use std::os::unix::ffi::OsStringExt; match tri!(data.variant()) { (OsStringKind::Unix, v) => v.newtype_variant().map(OsString::from_vec), (OsStringKind::Windows, _) => Err(Error::custom( "cannot deserialize Windows OS string on Unix", )), } } #[cfg(windows)] fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { use std::os::windows::ffi::OsStringExt; match tri!(data.variant()) { (OsStringKind::Windows, v) => v .newtype_variant::>() .map(|vec| OsString::from_wide(&vec)), (OsStringKind::Unix, _) => Err(Error::custom( "cannot deserialize Unix OS string on Windows", )), } } } #[cfg(all(feature = "std", any(unix, windows)))] #[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))] impl<'de> Deserialize<'de> for OsString { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_enum("OsString", OSSTR_VARIANTS, OsStringVisitor) } } //////////////////////////////////////////////////////////////////////////////// forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] (T), Box, Box::new } forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] (T), Box<[T]>, Vec::into_boxed_slice } forwarded_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] (), Box, String::into_boxed_str } forwarded_impl! { #[cfg(all(feature = "std", any(unix, windows)))] #[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))] (), Box, OsString::into_boxed_os_str } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, 'a, T> Deserialize<'de> for Cow<'a, T> where T: ?Sized + ToOwned, T::Owned: Deserialize<'de>, { #[inline] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { T::Owned::deserialize(deserializer).map(Cow::Owned) } } //////////////////////////////////////////////////////////////////////////////// /// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting /// `Weak` has a reference count of 0 and cannot be upgraded. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr( docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] impl<'de, T> Deserialize<'de> for RcWeak where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { tri!(Option::::deserialize(deserializer)); Ok(RcWeak::new()) } } /// This impl requires the [`"rc"`] Cargo feature of Serde. The resulting /// `Weak` has a reference count of 0 and cannot be upgraded. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr( docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] impl<'de, T> Deserialize<'de> for ArcWeak where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { tri!(Option::::deserialize(deserializer)); Ok(ArcWeak::new()) } } //////////////////////////////////////////////////////////////////////////////// macro_rules! box_forwarded_impl { ( $(#[$attr:meta])* $t:ident ) => { $(#[$attr])* impl<'de, T> Deserialize<'de> for $t where T: ?Sized, Box: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Box::deserialize(deserializer).map(Into::into) } } }; } box_forwarded_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// /// Deserializing a data structure containing `Rc` will not attempt to /// deduplicate `Rc` references to the same data. Every deserialized `Rc` /// will end up with a strong count of 1. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Rc } box_forwarded_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// /// Deserializing a data structure containing `Arc` will not attempt to /// deduplicate `Arc` references to the same data. Every deserialized `Arc` /// will end up with a strong count of 1. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Arc } //////////////////////////////////////////////////////////////////////////////// impl<'de, T> Deserialize<'de> for Cell where T: Deserialize<'de> + Copy, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { T::deserialize(deserializer).map(Cell::new) } } forwarded_impl! { (T), RefCell, RefCell::new } forwarded_impl! { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] (T), Mutex, Mutex::new } forwarded_impl! { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] (T), RwLock, RwLock::new } //////////////////////////////////////////////////////////////////////////////// // This is a cleaned-up version of the impl generated by: // // #[derive(Deserialize)] // #[serde(deny_unknown_fields)] // struct Duration { // secs: u64, // nanos: u32, // } impl<'de> Deserialize<'de> for Duration { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { // If this were outside of the serde crate, it would just use: // // #[derive(Deserialize)] // #[serde(field_identifier, rename_all = "lowercase")] enum Field { Secs, Nanos, } impl<'de> Deserialize<'de> for Field { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct FieldVisitor; impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("`secs` or `nanos`") } fn visit_str(self, value: &str) -> Result where E: Error, { match value { "secs" => Ok(Field::Secs), "nanos" => Ok(Field::Nanos), _ => Err(Error::unknown_field(value, FIELDS)), } } fn visit_bytes(self, value: &[u8]) -> Result where E: Error, { match value { b"secs" => Ok(Field::Secs), b"nanos" => Ok(Field::Nanos), _ => { let value = private::string::from_utf8_lossy(value); Err(Error::unknown_field(&*value, FIELDS)) } } } } deserializer.deserialize_identifier(FieldVisitor) } } fn check_overflow(secs: u64, nanos: u32) -> Result<(), E> where E: Error, { static NANOS_PER_SEC: u32 = 1_000_000_000; match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(_) => Ok(()), None => Err(E::custom("overflow deserializing Duration")), } } struct DurationVisitor; impl<'de> Visitor<'de> for DurationVisitor { type Value = Duration; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("struct Duration") } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let secs: u64 = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; let nanos: u32 = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(1, &self)); } }; tri!(check_overflow(secs, nanos)); Ok(Duration::new(secs, nanos)) } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut secs: Option = None; let mut nanos: Option = None; while let Some(key) = tri!(map.next_key()) { match key { Field::Secs => { if secs.is_some() { return Err(::duplicate_field("secs")); } secs = Some(tri!(map.next_value())); } Field::Nanos => { if nanos.is_some() { return Err(::duplicate_field("nanos")); } nanos = Some(tri!(map.next_value())); } } } let secs = match secs { Some(secs) => secs, None => return Err(::missing_field("secs")), }; let nanos = match nanos { Some(nanos) => nanos, None => return Err(::missing_field("nanos")), }; tri!(check_overflow(secs, nanos)); Ok(Duration::new(secs, nanos)) } } const FIELDS: &[&str] = &["secs", "nanos"]; deserializer.deserialize_struct("Duration", FIELDS, DurationVisitor) } } //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de> Deserialize<'de> for SystemTime { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { // Reuse duration enum Field { Secs, Nanos, } impl<'de> Deserialize<'de> for Field { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct FieldVisitor; impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("`secs_since_epoch` or `nanos_since_epoch`") } fn visit_str(self, value: &str) -> Result where E: Error, { match value { "secs_since_epoch" => Ok(Field::Secs), "nanos_since_epoch" => Ok(Field::Nanos), _ => Err(Error::unknown_field(value, FIELDS)), } } fn visit_bytes(self, value: &[u8]) -> Result where E: Error, { match value { b"secs_since_epoch" => Ok(Field::Secs), b"nanos_since_epoch" => Ok(Field::Nanos), _ => { let value = String::from_utf8_lossy(value); Err(Error::unknown_field(&value, FIELDS)) } } } } deserializer.deserialize_identifier(FieldVisitor) } } fn check_overflow(secs: u64, nanos: u32) -> Result<(), E> where E: Error, { static NANOS_PER_SEC: u32 = 1_000_000_000; match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(_) => Ok(()), None => Err(E::custom("overflow deserializing SystemTime epoch offset")), } } struct DurationVisitor; impl<'de> Visitor<'de> for DurationVisitor { type Value = Duration; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("struct SystemTime") } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let secs: u64 = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; let nanos: u32 = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(1, &self)); } }; tri!(check_overflow(secs, nanos)); Ok(Duration::new(secs, nanos)) } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut secs: Option = None; let mut nanos: Option = None; while let Some(key) = tri!(map.next_key()) { match key { Field::Secs => { if secs.is_some() { return Err(::duplicate_field( "secs_since_epoch", )); } secs = Some(tri!(map.next_value())); } Field::Nanos => { if nanos.is_some() { return Err(::duplicate_field( "nanos_since_epoch", )); } nanos = Some(tri!(map.next_value())); } } } let secs = match secs { Some(secs) => secs, None => return Err(::missing_field("secs_since_epoch")), }; let nanos = match nanos { Some(nanos) => nanos, None => return Err(::missing_field("nanos_since_epoch")), }; tri!(check_overflow(secs, nanos)); Ok(Duration::new(secs, nanos)) } } const FIELDS: &[&str] = &["secs_since_epoch", "nanos_since_epoch"]; let duration = tri!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor)); UNIX_EPOCH .checked_add(duration) .ok_or_else(|| D::Error::custom("overflow deserializing SystemTime")) } } //////////////////////////////////////////////////////////////////////////////// // Similar to: // // #[derive(Deserialize)] // #[serde(deny_unknown_fields)] // struct Range { // start: Idx, // end: Idx, // } impl<'de, Idx> Deserialize<'de> for Range where Idx: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let (start, end) = tri!(deserializer.deserialize_struct( "Range", range::FIELDS, range::RangeVisitor { expecting: "struct Range", phantom: PhantomData, }, )); Ok(start..end) } } impl<'de, Idx> Deserialize<'de> for RangeInclusive where Idx: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let (start, end) = tri!(deserializer.deserialize_struct( "RangeInclusive", range::FIELDS, range::RangeVisitor { expecting: "struct RangeInclusive", phantom: PhantomData, }, )); Ok(RangeInclusive::new(start, end)) } } mod range { use crate::lib::*; use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; use crate::private; pub const FIELDS: &[&str] = &["start", "end"]; // If this were outside of the serde crate, it would just use: // // #[derive(Deserialize)] // #[serde(field_identifier, rename_all = "lowercase")] enum Field { Start, End, } impl<'de> Deserialize<'de> for Field { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct FieldVisitor; impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("`start` or `end`") } fn visit_str(self, value: &str) -> Result where E: Error, { match value { "start" => Ok(Field::Start), "end" => Ok(Field::End), _ => Err(Error::unknown_field(value, FIELDS)), } } fn visit_bytes(self, value: &[u8]) -> Result where E: Error, { match value { b"start" => Ok(Field::Start), b"end" => Ok(Field::End), _ => { let value = private::string::from_utf8_lossy(value); Err(Error::unknown_field(&*value, FIELDS)) } } } } deserializer.deserialize_identifier(FieldVisitor) } } pub struct RangeVisitor { pub expecting: &'static str, pub phantom: PhantomData, } impl<'de, Idx> Visitor<'de> for RangeVisitor where Idx: Deserialize<'de>, { type Value = (Idx, Idx); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.expecting) } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let start: Idx = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; let end: Idx = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(1, &self)); } }; Ok((start, end)) } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut start: Option = None; let mut end: Option = None; while let Some(key) = tri!(map.next_key()) { match key { Field::Start => { if start.is_some() { return Err(::duplicate_field("start")); } start = Some(tri!(map.next_value())); } Field::End => { if end.is_some() { return Err(::duplicate_field("end")); } end = Some(tri!(map.next_value())); } } } let start = match start { Some(start) => start, None => return Err(::missing_field("start")), }; let end = match end { Some(end) => end, None => return Err(::missing_field("end")), }; Ok((start, end)) } } } //////////////////////////////////////////////////////////////////////////////// // Similar to: // // #[derive(Deserialize)] // #[serde(deny_unknown_fields)] // struct RangeFrom { // start: Idx, // } impl<'de, Idx> Deserialize<'de> for RangeFrom where Idx: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let start = tri!(deserializer.deserialize_struct( "RangeFrom", range_from::FIELDS, range_from::RangeFromVisitor { expecting: "struct RangeFrom", phantom: PhantomData, }, )); Ok(start..) } } mod range_from { use crate::lib::*; use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; use crate::private; pub const FIELDS: &[&str] = &["start"]; // If this were outside of the serde crate, it would just use: // // #[derive(Deserialize)] // #[serde(field_identifier, rename_all = "lowercase")] enum Field { Start, } impl<'de> Deserialize<'de> for Field { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct FieldVisitor; impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("`start`") } fn visit_str(self, value: &str) -> Result where E: Error, { match value { "start" => Ok(Field::Start), _ => Err(Error::unknown_field(value, FIELDS)), } } fn visit_bytes(self, value: &[u8]) -> Result where E: Error, { match value { b"start" => Ok(Field::Start), _ => { let value = private::string::from_utf8_lossy(value); Err(Error::unknown_field(&*value, FIELDS)) } } } } deserializer.deserialize_identifier(FieldVisitor) } } pub struct RangeFromVisitor { pub expecting: &'static str, pub phantom: PhantomData, } impl<'de, Idx> Visitor<'de> for RangeFromVisitor where Idx: Deserialize<'de>, { type Value = Idx; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.expecting) } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let start: Idx = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; Ok(start) } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut start: Option = None; while let Some(key) = tri!(map.next_key()) { match key { Field::Start => { if start.is_some() { return Err(::duplicate_field("start")); } start = Some(tri!(map.next_value())); } } } let start = match start { Some(start) => start, None => return Err(::missing_field("start")), }; Ok(start) } } } //////////////////////////////////////////////////////////////////////////////// // Similar to: // // #[derive(Deserialize)] // #[serde(deny_unknown_fields)] // struct RangeTo { // end: Idx, // } impl<'de, Idx> Deserialize<'de> for RangeTo where Idx: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let end = tri!(deserializer.deserialize_struct( "RangeTo", range_to::FIELDS, range_to::RangeToVisitor { expecting: "struct RangeTo", phantom: PhantomData, }, )); Ok(..end) } } mod range_to { use crate::lib::*; use crate::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor}; use crate::private; pub const FIELDS: &[&str] = &["end"]; // If this were outside of the serde crate, it would just use: // // #[derive(Deserialize)] // #[serde(field_identifier, rename_all = "lowercase")] enum Field { End, } impl<'de> Deserialize<'de> for Field { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct FieldVisitor; impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("`end`") } fn visit_str(self, value: &str) -> Result where E: Error, { match value { "end" => Ok(Field::End), _ => Err(Error::unknown_field(value, FIELDS)), } } fn visit_bytes(self, value: &[u8]) -> Result where E: Error, { match value { b"end" => Ok(Field::End), _ => { let value = private::string::from_utf8_lossy(value); Err(Error::unknown_field(&*value, FIELDS)) } } } } deserializer.deserialize_identifier(FieldVisitor) } } pub struct RangeToVisitor { pub expecting: &'static str, pub phantom: PhantomData, } impl<'de, Idx> Visitor<'de> for RangeToVisitor where Idx: Deserialize<'de>, { type Value = Idx; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.expecting) } fn visit_seq(self, mut seq: A) -> Result where A: SeqAccess<'de>, { let end: Idx = match tri!(seq.next_element()) { Some(value) => value, None => { return Err(Error::invalid_length(0, &self)); } }; Ok(end) } fn visit_map(self, mut map: A) -> Result where A: MapAccess<'de>, { let mut end: Option = None; while let Some(key) = tri!(map.next_key()) { match key { Field::End => { if end.is_some() { return Err(::duplicate_field("end")); } end = Some(tri!(map.next_value())); } } } let end = match end { Some(end) => end, None => return Err(::missing_field("end")), }; Ok(end) } } } //////////////////////////////////////////////////////////////////////////////// impl<'de, T> Deserialize<'de> for Bound where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { enum Field { Unbounded, Included, Excluded, } impl<'de> Deserialize<'de> for Field { #[inline] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct FieldVisitor; impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("`Unbounded`, `Included` or `Excluded`") } fn visit_u64(self, value: u64) -> Result where E: Error, { match value { 0 => Ok(Field::Unbounded), 1 => Ok(Field::Included), 2 => Ok(Field::Excluded), _ => Err(Error::invalid_value(Unexpected::Unsigned(value), &self)), } } fn visit_str(self, value: &str) -> Result where E: Error, { match value { "Unbounded" => Ok(Field::Unbounded), "Included" => Ok(Field::Included), "Excluded" => Ok(Field::Excluded), _ => Err(Error::unknown_variant(value, VARIANTS)), } } fn visit_bytes(self, value: &[u8]) -> Result where E: Error, { match value { b"Unbounded" => Ok(Field::Unbounded), b"Included" => Ok(Field::Included), b"Excluded" => Ok(Field::Excluded), _ => match str::from_utf8(value) { Ok(value) => Err(Error::unknown_variant(value, VARIANTS)), Err(_) => { Err(Error::invalid_value(Unexpected::Bytes(value), &self)) } }, } } } deserializer.deserialize_identifier(FieldVisitor) } } struct BoundVisitor(PhantomData>); impl<'de, T> Visitor<'de> for BoundVisitor where T: Deserialize<'de>, { type Value = Bound; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("enum Bound") } fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { match tri!(data.variant()) { (Field::Unbounded, v) => v.unit_variant().map(|()| Bound::Unbounded), (Field::Included, v) => v.newtype_variant().map(Bound::Included), (Field::Excluded, v) => v.newtype_variant().map(Bound::Excluded), } } } const VARIANTS: &[&str] = &["Unbounded", "Included", "Excluded"]; deserializer.deserialize_enum("Bound", VARIANTS, BoundVisitor(PhantomData)) } } //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "result")] #[cfg_attr(docsrs, doc(cfg(feature = "result")))] impl<'de, T, E> Deserialize<'de> for Result where T: Deserialize<'de>, E: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { // If this were outside of the serde crate, it would just use: // // #[derive(Deserialize)] // #[serde(variant_identifier)] enum Field { Ok, Err, } impl<'de> Deserialize<'de> for Field { #[inline] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct FieldVisitor; impl<'de> Visitor<'de> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("`Ok` or `Err`") } fn visit_u64(self, value: u64) -> Result where E: Error, { match value { 0 => Ok(Field::Ok), 1 => Ok(Field::Err), _ => Err(Error::invalid_value(Unexpected::Unsigned(value), &self)), } } fn visit_str(self, value: &str) -> Result where E: Error, { match value { "Ok" => Ok(Field::Ok), "Err" => Ok(Field::Err), _ => Err(Error::unknown_variant(value, VARIANTS)), } } fn visit_bytes(self, value: &[u8]) -> Result where E: Error, { match value { b"Ok" => Ok(Field::Ok), b"Err" => Ok(Field::Err), _ => match str::from_utf8(value) { Ok(value) => Err(Error::unknown_variant(value, VARIANTS)), Err(_) => { Err(Error::invalid_value(Unexpected::Bytes(value), &self)) } }, } } } deserializer.deserialize_identifier(FieldVisitor) } } struct ResultVisitor(PhantomData>); impl<'de, T, E> Visitor<'de> for ResultVisitor where T: Deserialize<'de>, E: Deserialize<'de>, { type Value = Result; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("enum Result") } fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { match tri!(data.variant()) { (Field::Ok, v) => v.newtype_variant().map(Ok), (Field::Err, v) => v.newtype_variant().map(Err), } } } const VARIANTS: &[&str] = &["Ok", "Err"]; deserializer.deserialize_enum("Result", VARIANTS, ResultVisitor(PhantomData)) } } //////////////////////////////////////////////////////////////////////////////// impl<'de, T> Deserialize<'de> for Wrapping where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Deserialize::deserialize(deserializer).map(Wrapping) } } #[cfg(all(feature = "std", not(no_std_atomic)))] macro_rules! atomic_impl { ($($ty:ident $size:expr)*) => { $( #[cfg(any(no_target_has_atomic, target_has_atomic = $size))] #[cfg_attr(docsrs, doc(cfg(all(feature = "std", target_has_atomic = $size))))] impl<'de> Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Deserialize::deserialize(deserializer).map(Self::new) } } )* }; } #[cfg(all(feature = "std", not(no_std_atomic)))] atomic_impl! { AtomicBool "8" AtomicI8 "8" AtomicI16 "16" AtomicI32 "32" AtomicIsize "ptr" AtomicU8 "8" AtomicU16 "16" AtomicU32 "32" AtomicUsize "ptr" } #[cfg(all(feature = "std", not(no_std_atomic64)))] atomic_impl! { AtomicI64 "64" AtomicU64 "64" } #[cfg(any(feature = "std", not(no_core_net)))] struct FromStrVisitor { expecting: &'static str, ty: PhantomData, } #[cfg(any(feature = "std", not(no_core_net)))] impl FromStrVisitor { fn new(expecting: &'static str) -> Self { FromStrVisitor { expecting, ty: PhantomData, } } } #[cfg(any(feature = "std", not(no_core_net)))] impl<'de, T> Visitor<'de> for FromStrVisitor where T: str::FromStr, T::Err: fmt::Display, { type Value = T; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.expecting) } fn visit_str(self, s: &str) -> Result where E: Error, { s.parse().map_err(Error::custom) } } ================================================ FILE: serde_core/src/de/mod.rs ================================================ //! Generic data structure deserialization framework. //! //! The two most important traits in this module are [`Deserialize`] and //! [`Deserializer`]. //! //! - **A type that implements `Deserialize` is a data structure** that can be //! deserialized from any data format supported by Serde, and conversely //! - **A type that implements `Deserializer` is a data format** that can //! deserialize any data structure supported by Serde. //! //! # The Deserialize trait //! //! Serde provides [`Deserialize`] implementations for many Rust primitive and //! standard library types. The complete list is below. All of these can be //! deserialized using Serde out of the box. //! //! Additionally, Serde provides a procedural macro called [`serde_derive`] to //! automatically generate [`Deserialize`] implementations for structs and enums //! in your program. See the [derive section of the manual] for how to use this. //! //! In rare cases it may be necessary to implement [`Deserialize`] manually for //! some type in your program. See the [Implementing `Deserialize`] section of //! the manual for more about this. //! //! Third-party crates may provide [`Deserialize`] implementations for types //! that they expose. For example the [`linked-hash-map`] crate provides a //! [`LinkedHashMap`] type that is deserializable by Serde because the //! crate provides an implementation of [`Deserialize`] for it. //! //! # The Deserializer trait //! //! [`Deserializer`] implementations are provided by third-party crates, for //! example [`serde_json`], [`serde_yaml`] and [`postcard`]. //! //! A partial list of well-maintained formats is given on the [Serde //! website][data formats]. //! //! # Implementations of Deserialize provided by Serde //! //! This is a slightly different set of types than what is supported for //! serialization. Some types can be serialized by Serde but not deserialized. //! One example is `OsStr`. //! //! - **Primitive types**: //! - bool //! - i8, i16, i32, i64, i128, isize //! - u8, u16, u32, u64, u128, usize //! - f32, f64 //! - char //! - **Compound types**: //! - \[T; 0\] through \[T; 32\] //! - tuples up to size 16 //! - **Common standard library types**: //! - String //! - Option\ //! - Result\ //! - PhantomData\ //! - **Wrapper types**: //! - Box\ //! - Box\<\[T\]\> //! - Box\ //! - Cow\<'a, T\> //! - Cell\ //! - RefCell\ //! - Mutex\ //! - RwLock\ //! - Rc\ *(if* features = \["rc"\] *is enabled)* //! - Arc\ *(if* features = \["rc"\] *is enabled)* //! - **Collection types**: //! - BTreeMap\ //! - BTreeSet\ //! - BinaryHeap\ //! - HashMap\ //! - HashSet\ //! - LinkedList\ //! - VecDeque\ //! - Vec\ //! - **Zero-copy types**: //! - &str //! - &\[u8\] //! - **FFI types**: //! - CString //! - Box\ //! - OsString //! - **Miscellaneous standard library types**: //! - Duration //! - SystemTime //! - Path //! - PathBuf //! - Range\ //! - RangeInclusive\ //! - Bound\ //! - num::NonZero* //! - `!` *(unstable)* //! - **Net types**: //! - IpAddr //! - Ipv4Addr //! - Ipv6Addr //! - SocketAddr //! - SocketAddrV4 //! - SocketAddrV6 //! //! [Implementing `Deserialize`]: https://serde.rs/impl-deserialize.html //! [`Deserialize`]: crate::Deserialize //! [`Deserializer`]: crate::Deserializer //! [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html //! [`postcard`]: https://github.com/jamesmunns/postcard //! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map //! [`serde_derive`]: https://crates.io/crates/serde_derive //! [`serde_json`]: https://github.com/serde-rs/json //! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml //! [derive section of the manual]: https://serde.rs/derive.html //! [data formats]: https://serde.rs/#data-formats use crate::lib::*; //////////////////////////////////////////////////////////////////////////////// pub mod value; mod ignored_any; mod impls; pub use self::ignored_any::IgnoredAny; #[cfg(all(not(feature = "std"), no_core_error))] #[doc(no_inline)] pub use crate::std_error::Error as StdError; #[cfg(not(any(feature = "std", no_core_error)))] #[doc(no_inline)] pub use core::error::Error as StdError; #[cfg(feature = "std")] #[doc(no_inline)] pub use std::error::Error as StdError; //////////////////////////////////////////////////////////////////////////////// macro_rules! declare_error_trait { (Error: Sized $(+ $($supertrait:ident)::+)*) => { /// The `Error` trait allows `Deserialize` implementations to create descriptive /// error messages belonging to the `Deserializer` against which they are /// currently running. /// /// Every `Deserializer` declares an `Error` type that encompasses both /// general-purpose deserialization errors as well as errors specific to the /// particular deserialization format. For example the `Error` type of /// `serde_json` can represent errors like an invalid JSON escape sequence or an /// unterminated string literal, in addition to the error cases that are part of /// this trait. /// /// Most deserializers should only need to provide the `Error::custom` method /// and inherit the default behavior for the other methods. /// /// # Example implementation /// /// The [example data format] presented on the website shows an error /// type appropriate for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::Error` is not satisfied", ) )] pub trait Error: Sized $(+ $($supertrait)::+)* { /// Raised when there is general error when deserializing a type. /// /// The message should not be capitalized and should not end with a period. /// /// ```edition2021 /// # use std::str::FromStr; /// # /// # struct IpAddr; /// # /// # impl FromStr for IpAddr { /// # type Err = String; /// # /// # fn from_str(_: &str) -> Result { /// # unimplemented!() /// # } /// # } /// # /// use serde::de::{self, Deserialize, Deserializer}; /// /// impl<'de> Deserialize<'de> for IpAddr { /// fn deserialize(deserializer: D) -> Result /// where /// D: Deserializer<'de>, /// { /// let s = String::deserialize(deserializer)?; /// s.parse().map_err(de::Error::custom) /// } /// } /// ``` fn custom(msg: T) -> Self where T: Display; /// Raised when a `Deserialize` receives a type different from what it was /// expecting. /// /// The `unexp` argument provides information about what type was received. /// This is the type that was present in the input file or other source data /// of the Deserializer. /// /// The `exp` argument provides information about what type was being /// expected. This is the type that is written in the program. /// /// For example if we try to deserialize a String out of a JSON file /// containing an integer, the unexpected type is the integer and the /// expected type is the string. #[cold] fn invalid_type(unexp: Unexpected, exp: &dyn Expected) -> Self { Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) } /// Raised when a `Deserialize` receives a value of the right type but that /// is wrong for some other reason. /// /// The `unexp` argument provides information about what value was received. /// This is the value that was present in the input file or other source /// data of the Deserializer. /// /// The `exp` argument provides information about what value was being /// expected. This is the type that is written in the program. /// /// For example if we try to deserialize a String out of some binary data /// that is not valid UTF-8, the unexpected value is the bytes and the /// expected value is a string. #[cold] fn invalid_value(unexp: Unexpected, exp: &dyn Expected) -> Self { Error::custom(format_args!("invalid value: {}, expected {}", unexp, exp)) } /// Raised when deserializing a sequence or map and the input data contains /// too many or too few elements. /// /// The `len` argument is the number of elements encountered. The sequence /// or map may have expected more arguments or fewer arguments. /// /// The `exp` argument provides information about what data was being /// expected. For example `exp` might say that a tuple of size 6 was /// expected. #[cold] fn invalid_length(len: usize, exp: &dyn Expected) -> Self { Error::custom(format_args!("invalid length {}, expected {}", len, exp)) } /// Raised when a `Deserialize` enum type received a variant with an /// unrecognized name. #[cold] fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self { if expected.is_empty() { Error::custom(format_args!( "unknown variant `{}`, there are no variants", variant )) } else { Error::custom(format_args!( "unknown variant `{}`, expected {}", variant, OneOf { names: expected } )) } } /// Raised when a `Deserialize` struct type received a field with an /// unrecognized name. #[cold] fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self { if expected.is_empty() { Error::custom(format_args!( "unknown field `{}`, there are no fields", field )) } else { Error::custom(format_args!( "unknown field `{}`, expected {}", field, OneOf { names: expected } )) } } /// Raised when a `Deserialize` struct type expected to receive a required /// field with a particular name but that field was not present in the /// input. #[cold] fn missing_field(field: &'static str) -> Self { Error::custom(format_args!("missing field `{}`", field)) } /// Raised when a `Deserialize` struct type received more than one of the /// same field. #[cold] fn duplicate_field(field: &'static str) -> Self { Error::custom(format_args!("duplicate field `{}`", field)) } } } } #[cfg(feature = "std")] declare_error_trait!(Error: Sized + StdError); #[cfg(not(feature = "std"))] declare_error_trait!(Error: Sized + Debug + Display); /// `Unexpected` represents an unexpected invocation of any one of the `Visitor` /// trait methods. /// /// This is used as an argument to the `invalid_type`, `invalid_value`, and /// `invalid_length` methods of the `Error` trait to build error messages. /// /// ```edition2021 /// # use std::fmt; /// # /// # use serde::de::{self, Unexpected, Visitor}; /// # /// # struct Example; /// # /// # impl<'de> Visitor<'de> for Example { /// # type Value = (); /// # /// # fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// # write!(formatter, "definitely not a boolean") /// # } /// # /// fn visit_bool(self, v: bool) -> Result /// where /// E: de::Error, /// { /// Err(de::Error::invalid_type(Unexpected::Bool(v), &self)) /// } /// # } /// ``` #[derive(Copy, Clone, PartialEq, Debug)] pub enum Unexpected<'a> { /// The input contained a boolean value that was not expected. Bool(bool), /// The input contained an unsigned integer `u8`, `u16`, `u32` or `u64` that /// was not expected. Unsigned(u64), /// The input contained a signed integer `i8`, `i16`, `i32` or `i64` that /// was not expected. Signed(i64), /// The input contained a floating point `f32` or `f64` that was not /// expected. Float(f64), /// The input contained a `char` that was not expected. Char(char), /// The input contained a `&str` or `String` that was not expected. Str(&'a str), /// The input contained a `&[u8]` or `Vec` that was not expected. Bytes(&'a [u8]), /// The input contained a unit `()` that was not expected. Unit, /// The input contained an `Option` that was not expected. Option, /// The input contained a newtype struct that was not expected. NewtypeStruct, /// The input contained a sequence that was not expected. Seq, /// The input contained a map that was not expected. Map, /// The input contained an enum that was not expected. Enum, /// The input contained a unit variant that was not expected. UnitVariant, /// The input contained a newtype variant that was not expected. NewtypeVariant, /// The input contained a tuple variant that was not expected. TupleVariant, /// The input contained a struct variant that was not expected. StructVariant, /// A message stating what uncategorized thing the input contained that was /// not expected. /// /// The message should be a noun or noun phrase, not capitalized and without /// a period. An example message is "unoriginal superhero". Other(&'a str), } impl<'a> fmt::Display for Unexpected<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { use self::Unexpected::*; match *self { Bool(b) => write!(formatter, "boolean `{}`", b), Unsigned(i) => write!(formatter, "integer `{}`", i), Signed(i) => write!(formatter, "integer `{}`", i), Float(f) => write!(formatter, "floating point `{}`", WithDecimalPoint(f)), Char(c) => write!(formatter, "character `{}`", c), Str(s) => write!(formatter, "string {:?}", s), Bytes(_) => formatter.write_str("byte array"), Unit => formatter.write_str("unit value"), Option => formatter.write_str("Option value"), NewtypeStruct => formatter.write_str("newtype struct"), Seq => formatter.write_str("sequence"), Map => formatter.write_str("map"), Enum => formatter.write_str("enum"), UnitVariant => formatter.write_str("unit variant"), NewtypeVariant => formatter.write_str("newtype variant"), TupleVariant => formatter.write_str("tuple variant"), StructVariant => formatter.write_str("struct variant"), Other(other) => formatter.write_str(other), } } } /// `Expected` represents an explanation of what data a `Visitor` was expecting /// to receive. /// /// This is used as an argument to the `invalid_type`, `invalid_value`, and /// `invalid_length` methods of the `Error` trait to build error messages. The /// message should be a noun or noun phrase that completes the sentence "This /// Visitor expects to receive ...", for example the message could be "an /// integer between 0 and 64". The message should not be capitalized and should /// not end with a period. /// /// Within the context of a `Visitor` implementation, the `Visitor` itself /// (`&self`) is an implementation of this trait. /// /// ```edition2021 /// # use serde::de::{self, Unexpected, Visitor}; /// # use std::fmt; /// # /// # struct Example; /// # /// # impl<'de> Visitor<'de> for Example { /// # type Value = (); /// # /// # fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// # write!(formatter, "definitely not a boolean") /// # } /// # /// fn visit_bool(self, v: bool) -> Result /// where /// E: de::Error, /// { /// Err(de::Error::invalid_type(Unexpected::Bool(v), &self)) /// } /// # } /// ``` /// /// Outside of a `Visitor`, `&"..."` can be used. /// /// ```edition2021 /// # use serde::de::{self, Unexpected}; /// # /// # fn example() -> Result<(), E> /// # where /// # E: de::Error, /// # { /// # let v = true; /// return Err(de::Error::invalid_type( /// Unexpected::Bool(v), /// &"a negative integer", /// )); /// # } /// ``` #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::Expected` is not satisfied", ) )] pub trait Expected { /// Format an explanation of what data was being expected. Same signature as /// the `Display` and `Debug` traits. fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result; } impl<'de, T> Expected for T where T: Visitor<'de>, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.expecting(formatter) } } impl Expected for &str { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self) } } impl Display for dyn Expected + '_ { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Expected::fmt(self, formatter) } } //////////////////////////////////////////////////////////////////////////////// /// A **data structure** that can be deserialized from any data format supported /// by Serde. /// /// Serde provides `Deserialize` implementations for many Rust primitive and /// standard library types. The complete list is [here][crate::de]. All of these /// can be deserialized using Serde out of the box. /// /// Additionally, Serde provides a procedural macro called `serde_derive` to /// automatically generate `Deserialize` implementations for structs and enums /// in your program. See the [derive section of the manual][derive] for how to /// use this. /// /// In rare cases it may be necessary to implement `Deserialize` manually for /// some type in your program. See the [Implementing /// `Deserialize`][impl-deserialize] section of the manual for more about this. /// /// Third-party crates may provide `Deserialize` implementations for types that /// they expose. For example the `linked-hash-map` crate provides a /// `LinkedHashMap` type that is deserializable by Serde because the crate /// provides an implementation of `Deserialize` for it. /// /// [derive]: https://serde.rs/derive.html /// [impl-deserialize]: https://serde.rs/impl-deserialize.html /// /// # Lifetime /// /// The `'de` lifetime of this trait is the lifetime of data that may be /// borrowed by `Self` when deserialized. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( // Prevents `serde_core::de::Deserialize` appearing in the error message // in projects with no direct dependency on serde_core. message = "the trait bound `{Self}: serde::Deserialize<'de>` is not satisfied", note = "for local types consider adding `#[derive(serde::Deserialize)]` to your `{Self}` type", note = "for types from other crates check whether the crate offers a `serde` feature flag", ) )] pub trait Deserialize<'de>: Sized { /// Deserialize this value from the given Serde deserializer. /// /// See the [Implementing `Deserialize`][impl-deserialize] section of the /// manual for more information about how to implement this method. /// /// [impl-deserialize]: https://serde.rs/impl-deserialize.html fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>; /// Deserializes a value into `self` from the given Deserializer. /// /// The purpose of this method is to allow the deserializer to reuse /// resources and avoid copies. As such, if this method returns an error, /// `self` will be in an indeterminate state where some parts of the struct /// have been overwritten. Although whatever state that is will be /// memory-safe. /// /// This is generally useful when repeatedly deserializing values that /// are processed one at a time, where the value of `self` doesn't matter /// when the next deserialization occurs. /// /// If you manually implement this, your recursive deserializations should /// use `deserialize_in_place`. /// /// This method is stable and an official public API, but hidden from the /// documentation because it is almost never what newbies are looking for. /// Showing it in rustdoc would cause it to be featured more prominently /// than it deserves. #[doc(hidden)] fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> where D: Deserializer<'de>, { // Default implementation just delegates to `deserialize` impl. *place = tri!(Deserialize::deserialize(deserializer)); Ok(()) } } /// A data structure that can be deserialized without borrowing any data from /// the deserializer. /// /// This is primarily useful for trait bounds on functions. For example a /// `from_str` function may be able to deserialize a data structure that borrows /// from the input string, but a `from_reader` function may only deserialize /// owned data. /// /// ```edition2021 /// # use serde::de::{Deserialize, DeserializeOwned}; /// # use std::io::{Read, Result}; /// # /// # trait Ignore { /// fn from_str<'a, T>(s: &'a str) -> Result /// where /// T: Deserialize<'a>; /// /// fn from_reader(rdr: R) -> Result /// where /// R: Read, /// T: DeserializeOwned; /// # } /// ``` /// /// # Lifetime /// /// The relationship between `Deserialize` and `DeserializeOwned` in trait /// bounds is explained in more detail on the page [Understanding deserializer /// lifetimes]. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::DeserializeOwned` is not satisfied", ) )] pub trait DeserializeOwned: for<'de> Deserialize<'de> {} impl DeserializeOwned for T where T: for<'de> Deserialize<'de> {} /// `DeserializeSeed` is the stateful form of the `Deserialize` trait. If you /// ever find yourself looking for a way to pass data into a `Deserialize` impl, /// this trait is the way to do it. /// /// As one example of stateful deserialization consider deserializing a JSON /// array into an existing buffer. Using the `Deserialize` trait we could /// deserialize a JSON array into a `Vec` but it would be a freshly allocated /// `Vec`; there is no way for `Deserialize` to reuse a previously allocated /// buffer. Using `DeserializeSeed` instead makes this possible as in the /// example code below. /// /// The canonical API for stateless deserialization looks like this: /// /// ```edition2021 /// # use serde::Deserialize; /// # /// # enum Error {} /// # /// fn func<'de, T: Deserialize<'de>>() -> Result /// # { /// # unimplemented!() /// # } /// ``` /// /// Adjusting an API like this to support stateful deserialization is a matter /// of accepting a seed as input: /// /// ```edition2021 /// # use serde::de::DeserializeSeed; /// # /// # enum Error {} /// # /// fn func_seed<'de, T: DeserializeSeed<'de>>(seed: T) -> Result /// # { /// # let _ = seed; /// # unimplemented!() /// # } /// ``` /// /// In practice the majority of deserialization is stateless. An API expecting a /// seed can be appeased by passing `std::marker::PhantomData` as a seed in the /// case of stateless deserialization. /// /// # Lifetime /// /// The `'de` lifetime of this trait is the lifetime of data that may be /// borrowed by `Self::Value` when deserialized. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html /// /// # Example /// /// Suppose we have JSON that looks like `[[1, 2], [3, 4, 5], [6]]` and we need /// to deserialize it into a flat representation like `vec![1, 2, 3, 4, 5, 6]`. /// Allocating a brand new `Vec` for each subarray would be slow. Instead we /// would like to allocate a single `Vec` and then deserialize each subarray /// into it. This requires stateful deserialization using the `DeserializeSeed` /// trait. /// /// ```edition2021 /// use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor}; /// use std::fmt; /// use std::marker::PhantomData; /// /// // A DeserializeSeed implementation that uses stateful deserialization to /// // append array elements onto the end of an existing vector. The preexisting /// // state ("seed") in this case is the Vec. The `deserialize` method of /// // `ExtendVec` will be traversing the inner arrays of the JSON input and /// // appending each integer into the existing Vec. /// struct ExtendVec<'a, T: 'a>(&'a mut Vec); /// /// impl<'de, 'a, T> DeserializeSeed<'de> for ExtendVec<'a, T> /// where /// T: Deserialize<'de>, /// { /// // The return type of the `deserialize` method. This implementation /// // appends onto an existing vector but does not create any new data /// // structure, so the return type is (). /// type Value = (); /// /// fn deserialize(self, deserializer: D) -> Result /// where /// D: Deserializer<'de>, /// { /// // Visitor implementation that will walk an inner array of the JSON /// // input. /// struct ExtendVecVisitor<'a, T: 'a>(&'a mut Vec); /// /// impl<'de, 'a, T> Visitor<'de> for ExtendVecVisitor<'a, T> /// where /// T: Deserialize<'de>, /// { /// type Value = (); /// /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// write!(formatter, "an array of integers") /// } /// /// fn visit_seq(self, mut seq: A) -> Result<(), A::Error> /// where /// A: SeqAccess<'de>, /// { /// // Decrease the number of reallocations if there are many elements /// if let Some(size_hint) = seq.size_hint() { /// self.0.reserve(size_hint); /// } /// /// // Visit each element in the inner array and push it onto /// // the existing vector. /// while let Some(elem) = seq.next_element()? { /// self.0.push(elem); /// } /// Ok(()) /// } /// } /// /// deserializer.deserialize_seq(ExtendVecVisitor(self.0)) /// } /// } /// /// // Visitor implementation that will walk the outer array of the JSON input. /// struct FlattenedVecVisitor(PhantomData); /// /// impl<'de, T> Visitor<'de> for FlattenedVecVisitor /// where /// T: Deserialize<'de>, /// { /// // This Visitor constructs a single Vec to hold the flattened /// // contents of the inner arrays. /// type Value = Vec; /// /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// write!(formatter, "an array of arrays") /// } /// /// fn visit_seq(self, mut seq: A) -> Result, A::Error> /// where /// A: SeqAccess<'de>, /// { /// // Create a single Vec to hold the flattened contents. /// let mut vec = Vec::new(); /// /// // Each iteration through this loop is one inner array. /// while let Some(()) = seq.next_element_seed(ExtendVec(&mut vec))? { /// // Nothing to do; inner array has been appended into `vec`. /// } /// /// // Return the finished vec. /// Ok(vec) /// } /// } /// /// # fn example<'de, D>(deserializer: D) -> Result<(), D::Error> /// # where /// # D: Deserializer<'de>, /// # { /// let visitor = FlattenedVecVisitor(PhantomData); /// let flattened: Vec = deserializer.deserialize_seq(visitor)?; /// # Ok(()) /// # } /// ``` #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::DeserializeSeed<'de>` is not satisfied", ) )] pub trait DeserializeSeed<'de>: Sized { /// The type produced by using this seed. type Value; /// Equivalent to the more common `Deserialize::deserialize` method, except /// with some initial piece of data (the seed) passed in. fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>; } impl<'de, T> DeserializeSeed<'de> for PhantomData where T: Deserialize<'de>, { type Value = T; #[inline] fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { T::deserialize(deserializer) } } //////////////////////////////////////////////////////////////////////////////// /// A **data format** that can deserialize any data structure supported by /// Serde. /// /// The role of this trait is to define the deserialization half of the [Serde /// data model], which is a way to categorize every Rust data type into one of /// 29 possible types. Each method of the `Deserializer` trait corresponds to one /// of the types of the data model. /// /// Implementations of `Deserialize` map themselves into this data model by /// passing to the `Deserializer` a `Visitor` implementation that can receive /// these various types. /// /// The types that make up the Serde data model are: /// /// - **14 primitive types** /// - bool /// - i8, i16, i32, i64, i128 /// - u8, u16, u32, u64, u128 /// - f32, f64 /// - char /// - **string** /// - UTF-8 bytes with a length and no null terminator. /// - When serializing, all strings are handled equally. When deserializing, /// there are three flavors of strings: transient, owned, and borrowed. /// - **byte array** - \[u8\] /// - Similar to strings, during deserialization byte arrays can be /// transient, owned, or borrowed. /// - **option** /// - Either none or some value. /// - **unit** /// - The type of `()` in Rust. It represents an anonymous value containing /// no data. /// - **unit_struct** /// - For example `struct Unit` or `PhantomData`. It represents a named /// value containing no data. /// - **unit_variant** /// - For example the `E::A` and `E::B` in `enum E { A, B }`. /// - **newtype_struct** /// - For example `struct Millimeters(u8)`. /// - **newtype_variant** /// - For example the `E::N` in `enum E { N(u8) }`. /// - **seq** /// - A variably sized heterogeneous sequence of values, for example `Vec` /// or `HashSet`. When serializing, the length may or may not be known /// before iterating through all the data. When deserializing, the length /// is determined by looking at the serialized data. /// - **tuple** /// - A statically sized heterogeneous sequence of values for which the /// length will be known at deserialization time without looking at the /// serialized data, for example `(u8,)` or `(String, u64, Vec)` or /// `[u64; 10]`. /// - **tuple_struct** /// - A named tuple, for example `struct Rgb(u8, u8, u8)`. /// - **tuple_variant** /// - For example the `E::T` in `enum E { T(u8, u8) }`. /// - **map** /// - A heterogeneous key-value pairing, for example `BTreeMap`. /// - **struct** /// - A heterogeneous key-value pairing in which the keys are strings and /// will be known at deserialization time without looking at the serialized /// data, for example `struct S { r: u8, g: u8, b: u8 }`. /// - **struct_variant** /// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`. /// /// The `Deserializer` trait supports two entry point styles which enables /// different kinds of deserialization. /// /// 1. The `deserialize_any` method. Self-describing data formats like JSON are /// able to look at the serialized data and tell what it represents. For /// example the JSON deserializer may see an opening curly brace (`{`) and /// know that it is seeing a map. If the data format supports /// `Deserializer::deserialize_any`, it will drive the Visitor using whatever /// type it sees in the input. JSON uses this approach when deserializing /// `serde_json::Value` which is an enum that can represent any JSON /// document. Without knowing what is in a JSON document, we can deserialize /// it to `serde_json::Value` by going through /// `Deserializer::deserialize_any`. /// /// 2. The various `deserialize_*` methods. Non-self-describing formats like /// Postcard need to be told what is in the input in order to deserialize it. /// The `deserialize_*` methods are hints to the deserializer for how to /// interpret the next piece of input. Non-self-describing formats are not /// able to deserialize something like `serde_json::Value` which relies on /// `Deserializer::deserialize_any`. /// /// When implementing `Deserialize`, you should avoid relying on /// `Deserializer::deserialize_any` unless you need to be told by the /// Deserializer what type is in the input. Know that relying on /// `Deserializer::deserialize_any` means your data type will be able to /// deserialize from self-describing formats only, ruling out Postcard and many /// others. /// /// [Serde data model]: https://serde.rs/data-model.html /// /// # Lifetime /// /// The `'de` lifetime of this trait is the lifetime of data that may be /// borrowed from the input when deserializing. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html /// /// # Example implementation /// /// The [example data format] presented on the website contains example code for /// a basic JSON `Deserializer`. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::Deserializer<'de>` is not satisfied", ) )] pub trait Deserializer<'de>: Sized { /// The error type that can be returned if some error occurs during /// deserialization. type Error: Error; /// Require the `Deserializer` to figure out how to drive the visitor based /// on what data type is in the input. /// /// When implementing `Deserialize`, you should avoid relying on /// `Deserializer::deserialize_any` unless you need to be told by the /// Deserializer what type is in the input. Know that relying on /// `Deserializer::deserialize_any` means your data type will be able to /// deserialize from self-describing formats only, ruling out Postcard and /// many others. fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `bool` value. fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i8` value. fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i16` value. fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i32` value. fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i64` value. fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `i128` value. /// /// The default behavior unconditionally returns an error. fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { let _ = visitor; Err(Error::custom("i128 is not supported")) } /// Hint that the `Deserialize` type is expecting a `u8` value. fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `u16` value. fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `u32` value. fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `u64` value. fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an `u128` value. /// /// The default behavior unconditionally returns an error. fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { let _ = visitor; Err(Error::custom("u128 is not supported")) } /// Hint that the `Deserialize` type is expecting a `f32` value. fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `f64` value. fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a `char` value. fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a string value and does /// not benefit from taking ownership of buffered data owned by the /// `Deserializer`. /// /// If the `Visitor` would benefit from taking ownership of `String` data, /// indicate this to the `Deserializer` by using `deserialize_string` /// instead. fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a string value and would /// benefit from taking ownership of buffered data owned by the /// `Deserializer`. /// /// If the `Visitor` would not benefit from taking ownership of `String` /// data, indicate that to the `Deserializer` by using `deserialize_str` /// instead. fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a byte array and does not /// benefit from taking ownership of buffered data owned by the /// `Deserializer`. /// /// If the `Visitor` would benefit from taking ownership of `Vec` data, /// indicate this to the `Deserializer` by using `deserialize_byte_buf` /// instead. fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a byte array and would /// benefit from taking ownership of buffered data owned by the /// `Deserializer`. /// /// If the `Visitor` would not benefit from taking ownership of `Vec` /// data, indicate that to the `Deserializer` by using `deserialize_bytes` /// instead. fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an optional value. /// /// This allows deserializers that encode an optional value as a nullable /// value to convert the null value into `None` and a regular value into /// `Some(value)`. fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a unit value. fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a unit struct with a /// particular name. fn deserialize_unit_struct( self, name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a newtype struct with a /// particular name. fn deserialize_newtype_struct( self, name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a sequence of values. fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a sequence of values and /// knows how many values there are without looking at the serialized data. fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a tuple struct with a /// particular name and number of fields. fn deserialize_tuple_struct( self, name: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a map of key-value pairs. fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting a struct with a particular /// name and fields. fn deserialize_struct( self, name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting an enum value with a /// particular name and possible variants. fn deserialize_enum( self, name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type is expecting the name of a struct /// field or the discriminant of an enum variant. fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>; /// Hint that the `Deserialize` type needs to deserialize a value whose type /// doesn't matter because it is ignored. /// /// Deserializers for non-self-describing formats may not support this mode. fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>; /// Determine whether `Deserialize` implementations should expect to /// deserialize their human-readable form. /// /// Some types have a human-readable form that may be somewhat expensive to /// construct, as well as a binary form that is compact and efficient. /// Generally text-based formats like JSON and YAML will prefer to use the /// human-readable one and binary formats like Postcard will prefer the /// compact one. /// /// ```edition2021 /// # use std::ops::Add; /// # use std::str::FromStr; /// # /// # struct Timestamp; /// # /// # impl Timestamp { /// # const EPOCH: Timestamp = Timestamp; /// # } /// # /// # impl FromStr for Timestamp { /// # type Err = String; /// # fn from_str(_: &str) -> Result { /// # unimplemented!() /// # } /// # } /// # /// # struct Duration; /// # /// # impl Duration { /// # fn seconds(_: u64) -> Self { unimplemented!() } /// # } /// # /// # impl Add for Timestamp { /// # type Output = Timestamp; /// # fn add(self, _: Duration) -> Self::Output { /// # unimplemented!() /// # } /// # } /// # /// use serde::de::{self, Deserialize, Deserializer}; /// /// impl<'de> Deserialize<'de> for Timestamp { /// fn deserialize(deserializer: D) -> Result /// where /// D: Deserializer<'de>, /// { /// if deserializer.is_human_readable() { /// // Deserialize from a human-readable string like "2015-05-15T17:01:00Z". /// let s = String::deserialize(deserializer)?; /// Timestamp::from_str(&s).map_err(de::Error::custom) /// } else { /// // Deserialize from a compact binary representation, seconds since /// // the Unix epoch. /// let n = u64::deserialize(deserializer)?; /// Ok(Timestamp::EPOCH + Duration::seconds(n)) /// } /// } /// } /// ``` /// /// The default implementation of this method returns `true`. Data formats /// may override this to `false` to request a compact form for types that /// support one. Note that modifying this method to change a format from /// human-readable to compact or vice versa should be regarded as a breaking /// change, as a value serialized in human-readable mode is not required to /// deserialize from the same data in compact mode. #[inline] fn is_human_readable(&self) -> bool { true } // Not public API. #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] #[doc(hidden)] fn __deserialize_content_v1(self, visitor: V) -> Result where V: Visitor<'de, Value = crate::private::Content<'de>>, { self.deserialize_any(visitor) } } //////////////////////////////////////////////////////////////////////////////// /// This trait represents a visitor that walks through a deserializer. /// /// # Lifetime /// /// The `'de` lifetime of this trait is the requirement for lifetime of data /// that may be borrowed by `Self::Value`. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html /// /// # Example /// /// ```edition2021 /// # use serde::de::{self, Unexpected, Visitor}; /// # use std::fmt; /// # /// /// A visitor that deserializes a long string - a string containing at least /// /// some minimum number of bytes. /// struct LongString { /// min: usize, /// } /// /// impl<'de> Visitor<'de> for LongString { /// type Value = String; /// /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// write!(formatter, "a string containing at least {} bytes", self.min) /// } /// /// fn visit_str(self, s: &str) -> Result /// where /// E: de::Error, /// { /// if s.len() >= self.min { /// Ok(s.to_owned()) /// } else { /// Err(de::Error::invalid_value(Unexpected::Str(s), &self)) /// } /// } /// } /// ``` #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::Visitor<'de>` is not satisfied", ) )] pub trait Visitor<'de>: Sized { /// The value produced by this visitor. type Value; /// Format a message stating what data this Visitor expects to receive. /// /// This is used in error messages. The message should complete the sentence /// "This Visitor expects to receive ...", for example the message could be /// "an integer between 0 and 64". The message should not be capitalized and /// should not end with a period. /// /// ```edition2021 /// # use std::fmt; /// # /// # struct S { /// # max: usize, /// # } /// # /// # impl<'de> serde::de::Visitor<'de> for S { /// # type Value = (); /// # /// fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// write!(formatter, "an integer between 0 and {}", self.max) /// } /// # } /// ``` fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result; /// The input contains a boolean. /// /// The default implementation fails with a type error. fn visit_bool(self, v: bool) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Bool(v), &self)) } /// The input contains an `i8`. /// /// The default implementation forwards to [`visit_i64`]. /// /// [`visit_i64`]: #method.visit_i64 fn visit_i8(self, v: i8) -> Result where E: Error, { self.visit_i64(v as i64) } /// The input contains an `i16`. /// /// The default implementation forwards to [`visit_i64`]. /// /// [`visit_i64`]: #method.visit_i64 fn visit_i16(self, v: i16) -> Result where E: Error, { self.visit_i64(v as i64) } /// The input contains an `i32`. /// /// The default implementation forwards to [`visit_i64`]. /// /// [`visit_i64`]: #method.visit_i64 fn visit_i32(self, v: i32) -> Result where E: Error, { self.visit_i64(v as i64) } /// The input contains an `i64`. /// /// The default implementation fails with a type error. fn visit_i64(self, v: i64) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Signed(v), &self)) } /// The input contains a `i128`. /// /// The default implementation fails with a type error. fn visit_i128(self, v: i128) -> Result where E: Error, { let mut buf = [0u8; 58]; let mut writer = crate::format::Buf::new(&mut buf); fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as i128", v)).unwrap(); Err(Error::invalid_type( Unexpected::Other(writer.as_str()), &self, )) } /// The input contains a `u8`. /// /// The default implementation forwards to [`visit_u64`]. /// /// [`visit_u64`]: #method.visit_u64 fn visit_u8(self, v: u8) -> Result where E: Error, { self.visit_u64(v as u64) } /// The input contains a `u16`. /// /// The default implementation forwards to [`visit_u64`]. /// /// [`visit_u64`]: #method.visit_u64 fn visit_u16(self, v: u16) -> Result where E: Error, { self.visit_u64(v as u64) } /// The input contains a `u32`. /// /// The default implementation forwards to [`visit_u64`]. /// /// [`visit_u64`]: #method.visit_u64 fn visit_u32(self, v: u32) -> Result where E: Error, { self.visit_u64(v as u64) } /// The input contains a `u64`. /// /// The default implementation fails with a type error. fn visit_u64(self, v: u64) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Unsigned(v), &self)) } /// The input contains a `u128`. /// /// The default implementation fails with a type error. fn visit_u128(self, v: u128) -> Result where E: Error, { let mut buf = [0u8; 57]; let mut writer = crate::format::Buf::new(&mut buf); fmt::Write::write_fmt(&mut writer, format_args!("integer `{}` as u128", v)).unwrap(); Err(Error::invalid_type( Unexpected::Other(writer.as_str()), &self, )) } /// The input contains an `f32`. /// /// The default implementation forwards to [`visit_f64`]. /// /// [`visit_f64`]: #method.visit_f64 fn visit_f32(self, v: f32) -> Result where E: Error, { self.visit_f64(v as f64) } /// The input contains an `f64`. /// /// The default implementation fails with a type error. fn visit_f64(self, v: f64) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Float(v), &self)) } /// The input contains a `char`. /// /// The default implementation forwards to [`visit_str`] as a one-character /// string. /// /// [`visit_str`]: #method.visit_str #[inline] fn visit_char(self, v: char) -> Result where E: Error, { self.visit_str(v.encode_utf8(&mut [0u8; 4])) } /// The input contains a string. The lifetime of the string is ephemeral and /// it may be destroyed after this method returns. /// /// This method allows the `Deserializer` to avoid a copy by retaining /// ownership of any buffered data. `Deserialize` implementations that do /// not benefit from taking ownership of `String` data should indicate that /// to the deserializer by using `Deserializer::deserialize_str` rather than /// `Deserializer::deserialize_string`. /// /// It is never correct to implement `visit_string` without implementing /// `visit_str`. Implement neither, both, or just `visit_str`. fn visit_str(self, v: &str) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Str(v), &self)) } /// The input contains a string that lives at least as long as the /// `Deserializer`. /// /// This enables zero-copy deserialization of strings in some formats. For /// example JSON input containing the JSON string `"borrowed"` can be /// deserialized with zero copying into a `&'a str` as long as the input /// data outlives `'a`. /// /// The default implementation forwards to `visit_str`. #[inline] fn visit_borrowed_str(self, v: &'de str) -> Result where E: Error, { self.visit_str(v) } /// The input contains a string and ownership of the string is being given /// to the `Visitor`. /// /// This method allows the `Visitor` to avoid a copy by taking ownership of /// a string created by the `Deserializer`. `Deserialize` implementations /// that benefit from taking ownership of `String` data should indicate that /// to the deserializer by using `Deserializer::deserialize_string` rather /// than `Deserializer::deserialize_str`, although not every deserializer /// will honor such a request. /// /// It is never correct to implement `visit_string` without implementing /// `visit_str`. Implement neither, both, or just `visit_str`. /// /// The default implementation forwards to `visit_str` and then drops the /// `String`. #[inline] #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] fn visit_string(self, v: String) -> Result where E: Error, { self.visit_str(&v) } /// The input contains a byte array. The lifetime of the byte array is /// ephemeral and it may be destroyed after this method returns. /// /// This method allows the `Deserializer` to avoid a copy by retaining /// ownership of any buffered data. `Deserialize` implementations that do /// not benefit from taking ownership of `Vec` data should indicate that /// to the deserializer by using `Deserializer::deserialize_bytes` rather /// than `Deserializer::deserialize_byte_buf`. /// /// It is never correct to implement `visit_byte_buf` without implementing /// `visit_bytes`. Implement neither, both, or just `visit_bytes`. fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Bytes(v), &self)) } /// The input contains a byte array that lives at least as long as the /// `Deserializer`. /// /// This enables zero-copy deserialization of bytes in some formats. For /// example Postcard data containing bytes can be deserialized with zero /// copying into a `&'a [u8]` as long as the input data outlives `'a`. /// /// The default implementation forwards to `visit_bytes`. #[inline] fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result where E: Error, { self.visit_bytes(v) } /// The input contains a byte array and ownership of the byte array is being /// given to the `Visitor`. /// /// This method allows the `Visitor` to avoid a copy by taking ownership of /// a byte buffer created by the `Deserializer`. `Deserialize` /// implementations that benefit from taking ownership of `Vec` data /// should indicate that to the deserializer by using /// `Deserializer::deserialize_byte_buf` rather than /// `Deserializer::deserialize_bytes`, although not every deserializer will /// honor such a request. /// /// It is never correct to implement `visit_byte_buf` without implementing /// `visit_bytes`. Implement neither, both, or just `visit_bytes`. /// /// The default implementation forwards to `visit_bytes` and then drops the /// `Vec`. #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] fn visit_byte_buf(self, v: Vec) -> Result where E: Error, { self.visit_bytes(&v) } /// The input contains an optional that is absent. /// /// The default implementation fails with a type error. fn visit_none(self) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Option, &self)) } /// The input contains an optional that is present. /// /// The default implementation fails with a type error. fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { let _ = deserializer; Err(Error::invalid_type(Unexpected::Option, &self)) } /// The input contains a unit `()`. /// /// The default implementation fails with a type error. fn visit_unit(self) -> Result where E: Error, { Err(Error::invalid_type(Unexpected::Unit, &self)) } /// The input contains a newtype struct. /// /// The content of the newtype struct may be read from the given /// `Deserializer`. /// /// The default implementation fails with a type error. fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer<'de>, { let _ = deserializer; Err(Error::invalid_type(Unexpected::NewtypeStruct, &self)) } /// The input contains a sequence of elements. /// /// The default implementation fails with a type error. fn visit_seq(self, seq: A) -> Result where A: SeqAccess<'de>, { let _ = seq; Err(Error::invalid_type(Unexpected::Seq, &self)) } /// The input contains a key-value map. /// /// The default implementation fails with a type error. fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { let _ = map; Err(Error::invalid_type(Unexpected::Map, &self)) } /// The input contains an enum. /// /// The default implementation fails with a type error. fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { let _ = data; Err(Error::invalid_type(Unexpected::Enum, &self)) } // Used when deserializing a flattened Option field. Not public API. #[doc(hidden)] fn __private_visit_untagged_option(self, _: D) -> Result where D: Deserializer<'de>, { Err(()) } } //////////////////////////////////////////////////////////////////////////////// /// Provides a `Visitor` access to each element of a sequence in the input. /// /// This is a trait that a `Deserializer` passes to a `Visitor` implementation, /// which deserializes each item in a sequence. /// /// # Lifetime /// /// The `'de` lifetime of this trait is the lifetime of data that may be /// borrowed by deserialized sequence elements. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `SeqAccess` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::SeqAccess<'de>` is not satisfied", ) )] pub trait SeqAccess<'de> { /// The error type that can be returned if some error occurs during /// deserialization. type Error: Error; /// This returns `Ok(Some(value))` for the next value in the sequence, or /// `Ok(None)` if there are no more remaining items. /// /// `Deserialize` implementations should typically use /// `SeqAccess::next_element` instead. fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>; /// This returns `Ok(Some(value))` for the next value in the sequence, or /// `Ok(None)` if there are no more remaining items. /// /// This method exists as a convenience for `Deserialize` implementations. /// `SeqAccess` implementations should not override the default behavior. #[inline] fn next_element(&mut self) -> Result, Self::Error> where T: Deserialize<'de>, { self.next_element_seed(PhantomData) } /// Returns the number of elements remaining in the sequence, if known. #[inline] fn size_hint(&self) -> Option { None } } impl<'de, A> SeqAccess<'de> for &mut A where A: ?Sized + SeqAccess<'de>, { type Error = A::Error; #[inline] fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { (**self).next_element_seed(seed) } #[inline] fn next_element(&mut self) -> Result, Self::Error> where T: Deserialize<'de>, { (**self).next_element() } #[inline] fn size_hint(&self) -> Option { (**self).size_hint() } } //////////////////////////////////////////////////////////////////////////////// /// Provides a `Visitor` access to each entry of a map in the input. /// /// This is a trait that a `Deserializer` passes to a `Visitor` implementation. /// /// # Lifetime /// /// The `'de` lifetime of this trait is the lifetime of data that may be /// borrowed by deserialized map entries. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `MapAccess` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::MapAccess<'de>` is not satisfied", ) )] pub trait MapAccess<'de> { /// The error type that can be returned if some error occurs during /// deserialization. type Error: Error; /// This returns `Ok(Some(key))` for the next key in the map, or `Ok(None)` /// if there are no more remaining entries. /// /// `Deserialize` implementations should typically use /// `MapAccess::next_key` or `MapAccess::next_entry` instead. fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> where K: DeserializeSeed<'de>; /// This returns a `Ok(value)` for the next value in the map. /// /// `Deserialize` implementations should typically use /// `MapAccess::next_value` instead. /// /// # Panics /// /// Calling `next_value_seed` before `next_key_seed` is incorrect and is /// allowed to panic or return bogus results. fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>; /// This returns `Ok(Some((key, value)))` for the next (key-value) pair in /// the map, or `Ok(None)` if there are no more remaining items. /// /// `MapAccess` implementations should override the default behavior if a /// more efficient implementation is possible. /// /// `Deserialize` implementations should typically use /// `MapAccess::next_entry` instead. #[inline] fn next_entry_seed( &mut self, kseed: K, vseed: V, ) -> Result, Self::Error> where K: DeserializeSeed<'de>, V: DeserializeSeed<'de>, { match tri!(self.next_key_seed(kseed)) { Some(key) => { let value = tri!(self.next_value_seed(vseed)); Ok(Some((key, value))) } None => Ok(None), } } /// This returns `Ok(Some(key))` for the next key in the map, or `Ok(None)` /// if there are no more remaining entries. /// /// This method exists as a convenience for `Deserialize` implementations. /// `MapAccess` implementations should not override the default behavior. #[inline] fn next_key(&mut self) -> Result, Self::Error> where K: Deserialize<'de>, { self.next_key_seed(PhantomData) } /// This returns a `Ok(value)` for the next value in the map. /// /// This method exists as a convenience for `Deserialize` implementations. /// `MapAccess` implementations should not override the default behavior. /// /// # Panics /// /// Calling `next_value` before `next_key` is incorrect and is allowed to /// panic or return bogus results. #[inline] fn next_value(&mut self) -> Result where V: Deserialize<'de>, { self.next_value_seed(PhantomData) } /// This returns `Ok(Some((key, value)))` for the next (key-value) pair in /// the map, or `Ok(None)` if there are no more remaining items. /// /// This method exists as a convenience for `Deserialize` implementations. /// `MapAccess` implementations should not override the default behavior. #[inline] fn next_entry(&mut self) -> Result, Self::Error> where K: Deserialize<'de>, V: Deserialize<'de>, { self.next_entry_seed(PhantomData, PhantomData) } /// Returns the number of entries remaining in the map, if known. #[inline] fn size_hint(&self) -> Option { None } } impl<'de, A> MapAccess<'de> for &mut A where A: ?Sized + MapAccess<'de>, { type Error = A::Error; #[inline] fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> where K: DeserializeSeed<'de>, { (**self).next_key_seed(seed) } #[inline] fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, { (**self).next_value_seed(seed) } #[inline] fn next_entry_seed( &mut self, kseed: K, vseed: V, ) -> Result, Self::Error> where K: DeserializeSeed<'de>, V: DeserializeSeed<'de>, { (**self).next_entry_seed(kseed, vseed) } #[inline] fn next_entry(&mut self) -> Result, Self::Error> where K: Deserialize<'de>, V: Deserialize<'de>, { (**self).next_entry() } #[inline] fn next_key(&mut self) -> Result, Self::Error> where K: Deserialize<'de>, { (**self).next_key() } #[inline] fn next_value(&mut self) -> Result where V: Deserialize<'de>, { (**self).next_value() } #[inline] fn size_hint(&self) -> Option { (**self).size_hint() } } //////////////////////////////////////////////////////////////////////////////// /// Provides a `Visitor` access to the data of an enum in the input. /// /// `EnumAccess` is created by the `Deserializer` and passed to the /// `Visitor` in order to identify which variant of an enum to deserialize. /// /// # Lifetime /// /// The `'de` lifetime of this trait is the lifetime of data that may be /// borrowed by the deserialized enum variant. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `EnumAccess` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::EnumAccess<'de>` is not satisfied", ) )] pub trait EnumAccess<'de>: Sized { /// The error type that can be returned if some error occurs during /// deserialization. type Error: Error; /// The `Visitor` that will be used to deserialize the content of the enum /// variant. type Variant: VariantAccess<'de, Error = Self::Error>; /// `variant` is called to identify which variant to deserialize. /// /// `Deserialize` implementations should typically use `EnumAccess::variant` /// instead. fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: DeserializeSeed<'de>; /// `variant` is called to identify which variant to deserialize. /// /// This method exists as a convenience for `Deserialize` implementations. /// `EnumAccess` implementations should not override the default behavior. #[inline] fn variant(self) -> Result<(V, Self::Variant), Self::Error> where V: Deserialize<'de>, { self.variant_seed(PhantomData) } } /// `VariantAccess` is a visitor that is created by the `Deserializer` and /// passed to the `Deserialize` to deserialize the content of a particular enum /// variant. /// /// # Lifetime /// /// The `'de` lifetime of this trait is the lifetime of data that may be /// borrowed by the deserialized enum variant. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `VariantAccess` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::de::VariantAccess<'de>` is not satisfied", ) )] pub trait VariantAccess<'de>: Sized { /// The error type that can be returned if some error occurs during /// deserialization. Must match the error type of our `EnumAccess`. type Error: Error; /// Called when deserializing a variant with no values. /// /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// /// ```edition2021 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; /// # /// # impl<'de> VariantAccess<'de> for X { /// # type Error = value::Error; /// # /// fn unit_variant(self) -> Result<(), Self::Error> { /// // What the data actually contained; suppose it is a tuple variant. /// let unexp = Unexpected::TupleVariant; /// Err(de::Error::invalid_type(unexp, &"unit variant")) /// } /// # /// # fn newtype_variant_seed(self, _: T) -> Result /// # where /// # T: DeserializeSeed<'de>, /// # { unimplemented!() } /// # /// # fn tuple_variant(self, _: usize, _: V) -> Result /// # where /// # V: Visitor<'de>, /// # { unimplemented!() } /// # /// # fn struct_variant(self, _: &[&str], _: V) -> Result /// # where /// # V: Visitor<'de>, /// # { unimplemented!() } /// # } /// ``` fn unit_variant(self) -> Result<(), Self::Error>; /// Called when deserializing a variant with a single value. /// /// `Deserialize` implementations should typically use /// `VariantAccess::newtype_variant` instead. /// /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// /// ```edition2021 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; /// # /// # impl<'de> VariantAccess<'de> for X { /// # type Error = value::Error; /// # /// # fn unit_variant(self) -> Result<(), Self::Error> { /// # unimplemented!() /// # } /// # /// fn newtype_variant_seed(self, _seed: T) -> Result /// where /// T: DeserializeSeed<'de>, /// { /// // What the data actually contained; suppose it is a unit variant. /// let unexp = Unexpected::UnitVariant; /// Err(de::Error::invalid_type(unexp, &"newtype variant")) /// } /// # /// # fn tuple_variant(self, _: usize, _: V) -> Result /// # where /// # V: Visitor<'de>, /// # { unimplemented!() } /// # /// # fn struct_variant(self, _: &[&str], _: V) -> Result /// # where /// # V: Visitor<'de>, /// # { unimplemented!() } /// # } /// ``` fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>; /// Called when deserializing a variant with a single value. /// /// This method exists as a convenience for `Deserialize` implementations. /// `VariantAccess` implementations should not override the default /// behavior. #[inline] fn newtype_variant(self) -> Result where T: Deserialize<'de>, { self.newtype_variant_seed(PhantomData) } /// Called when deserializing a tuple-like variant. /// /// The `len` is the number of fields expected in the tuple variant. /// /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// /// ```edition2021 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; /// # /// # impl<'de> VariantAccess<'de> for X { /// # type Error = value::Error; /// # /// # fn unit_variant(self) -> Result<(), Self::Error> { /// # unimplemented!() /// # } /// # /// # fn newtype_variant_seed(self, _: T) -> Result /// # where /// # T: DeserializeSeed<'de>, /// # { unimplemented!() } /// # /// fn tuple_variant(self, _len: usize, _visitor: V) -> Result /// where /// V: Visitor<'de>, /// { /// // What the data actually contained; suppose it is a unit variant. /// let unexp = Unexpected::UnitVariant; /// Err(de::Error::invalid_type(unexp, &"tuple variant")) /// } /// # /// # fn struct_variant(self, _: &[&str], _: V) -> Result /// # where /// # V: Visitor<'de>, /// # { unimplemented!() } /// # } /// ``` fn tuple_variant(self, len: usize, visitor: V) -> Result where V: Visitor<'de>; /// Called when deserializing a struct-like variant. /// /// The `fields` are the names of the fields of the struct variant. /// /// If the data contains a different type of variant, the following /// `invalid_type` error should be constructed: /// /// ```edition2021 /// # use serde::de::{self, value, DeserializeSeed, Visitor, VariantAccess, Unexpected}; /// # /// # struct X; /// # /// # impl<'de> VariantAccess<'de> for X { /// # type Error = value::Error; /// # /// # fn unit_variant(self) -> Result<(), Self::Error> { /// # unimplemented!() /// # } /// # /// # fn newtype_variant_seed(self, _: T) -> Result /// # where /// # T: DeserializeSeed<'de>, /// # { unimplemented!() } /// # /// # fn tuple_variant(self, _: usize, _: V) -> Result /// # where /// # V: Visitor<'de>, /// # { unimplemented!() } /// # /// fn struct_variant( /// self, /// _fields: &'static [&'static str], /// _visitor: V, /// ) -> Result /// where /// V: Visitor<'de>, /// { /// // What the data actually contained; suppose it is a unit variant. /// let unexp = Unexpected::UnitVariant; /// Err(de::Error::invalid_type(unexp, &"struct variant")) /// } /// # } /// ``` fn struct_variant( self, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>; } //////////////////////////////////////////////////////////////////////////////// /// Converts an existing value into a `Deserializer` from which other values can /// be deserialized. /// /// # Lifetime /// /// The `'de` lifetime of this trait is the lifetime of data that may be /// borrowed from the resulting `Deserializer`. See the page [Understanding /// deserializer lifetimes] for a more detailed explanation of these lifetimes. /// /// [Understanding deserializer lifetimes]: https://serde.rs/lifetimes.html /// /// # Example /// /// ```edition2021 /// use serde::de::{value, Deserialize, IntoDeserializer}; /// use serde_derive::Deserialize; /// use std::str::FromStr; /// /// #[derive(Deserialize)] /// enum Setting { /// On, /// Off, /// } /// /// impl FromStr for Setting { /// type Err = value::Error; /// /// fn from_str(s: &str) -> Result { /// Self::deserialize(s.into_deserializer()) /// } /// } /// ``` pub trait IntoDeserializer<'de, E: Error = value::Error> { /// The type of the deserializer being converted into. type Deserializer: Deserializer<'de, Error = E>; /// Convert this value into a deserializer. fn into_deserializer(self) -> Self::Deserializer; } //////////////////////////////////////////////////////////////////////////////// /// Used in error messages. /// /// - expected `a` /// - expected `a` or `b` /// - expected one of `a`, `b`, `c` /// /// The slice of names must not be empty. struct OneOf { names: &'static [&'static str], } impl Display for OneOf { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self.names.len() { 0 => panic!(), // special case elsewhere 1 => write!(formatter, "`{}`", self.names[0]), 2 => write!(formatter, "`{}` or `{}`", self.names[0], self.names[1]), _ => { tri!(formatter.write_str("one of ")); for (i, alt) in self.names.iter().enumerate() { if i > 0 { tri!(formatter.write_str(", ")); } tri!(write!(formatter, "`{}`", alt)); } Ok(()) } } } } struct WithDecimalPoint(f64); impl Display for WithDecimalPoint { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { struct LookForDecimalPoint<'f, 'a> { formatter: &'f mut fmt::Formatter<'a>, has_decimal_point: bool, } impl<'f, 'a> fmt::Write for LookForDecimalPoint<'f, 'a> { fn write_str(&mut self, fragment: &str) -> fmt::Result { self.has_decimal_point |= fragment.contains('.'); self.formatter.write_str(fragment) } fn write_char(&mut self, ch: char) -> fmt::Result { self.has_decimal_point |= ch == '.'; self.formatter.write_char(ch) } } if self.0.is_finite() { let mut writer = LookForDecimalPoint { formatter, has_decimal_point: false, }; tri!(write!(writer, "{}", self.0)); if !writer.has_decimal_point { tri!(formatter.write_str(".0")); } } else { tri!(write!(formatter, "{}", self.0)); } Ok(()) } } ================================================ FILE: serde_core/src/de/value.rs ================================================ //! Building blocks for deserializing basic values using the `IntoDeserializer` //! trait. //! //! ```edition2021 //! use serde::de::{value, Deserialize, IntoDeserializer}; //! use serde_derive::Deserialize; //! use std::str::FromStr; //! //! #[derive(Deserialize)] //! enum Setting { //! On, //! Off, //! } //! //! impl FromStr for Setting { //! type Err = value::Error; //! //! fn from_str(s: &str) -> Result { //! Self::deserialize(s.into_deserializer()) //! } //! } //! ``` use crate::lib::*; use self::private::{First, Second}; use crate::de::{self, Deserializer, Expected, IntoDeserializer, SeqAccess, Visitor}; use crate::private::size_hint; use crate::ser; //////////////////////////////////////////////////////////////////////////////// // For structs that contain a PhantomData. We do not want the trait // bound `E: Clone` inferred by derive(Clone). macro_rules! impl_copy_clone { ($ty:ident $(<$lifetime:tt>)*) => { impl<$($lifetime,)* E> Copy for $ty<$($lifetime,)* E> {} impl<$($lifetime,)* E> Clone for $ty<$($lifetime,)* E> { fn clone(&self) -> Self { *self } } }; } //////////////////////////////////////////////////////////////////////////////// /// A minimal representation of all possible errors that can occur using the /// `IntoDeserializer` trait. #[derive(Clone, PartialEq)] pub struct Error { err: ErrorImpl, } #[cfg(any(feature = "std", feature = "alloc"))] type ErrorImpl = Box; #[cfg(not(any(feature = "std", feature = "alloc")))] type ErrorImpl = (); impl de::Error for Error { #[cfg(any(feature = "std", feature = "alloc"))] #[cold] fn custom(msg: T) -> Self where T: Display, { Error { err: msg.to_string().into_boxed_str(), } } #[cfg(not(any(feature = "std", feature = "alloc")))] #[cold] fn custom(msg: T) -> Self where T: Display, { let _ = msg; Error { err: () } } } impl ser::Error for Error { #[cold] fn custom(msg: T) -> Self where T: Display, { de::Error::custom(msg) } } impl Display for Error { #[cfg(any(feature = "std", feature = "alloc"))] fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(&self.err) } #[cfg(not(any(feature = "std", feature = "alloc")))] fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Serde deserialization error") } } impl Debug for Error { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut debug = formatter.debug_tuple("Error"); #[cfg(any(feature = "std", feature = "alloc"))] debug.field(&self.err); debug.finish() } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl error::Error for Error { fn description(&self) -> &str { &self.err } } //////////////////////////////////////////////////////////////////////////////// impl<'de, E> IntoDeserializer<'de, E> for () where E: de::Error, { type Deserializer = UnitDeserializer; fn into_deserializer(self) -> UnitDeserializer { UnitDeserializer::new() } } /// A deserializer holding a `()`. pub struct UnitDeserializer { marker: PhantomData, } impl_copy_clone!(UnitDeserializer); impl UnitDeserializer { #[allow(missing_docs)] pub fn new() -> Self { UnitDeserializer { marker: PhantomData, } } } impl<'de, E> de::Deserializer<'de> for UnitDeserializer where E: de::Error, { type Error = E; forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_unit() } fn deserialize_option(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_none() } } impl<'de, E> IntoDeserializer<'de, E> for UnitDeserializer where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl Debug for UnitDeserializer { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.debug_struct("UnitDeserializer").finish() } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer that cannot be instantiated. #[cfg(feature = "unstable")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] pub struct NeverDeserializer { never: !, marker: PhantomData, } #[cfg(feature = "unstable")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] impl<'de, E> IntoDeserializer<'de, E> for ! where E: de::Error, { type Deserializer = NeverDeserializer; fn into_deserializer(self) -> Self::Deserializer { self } } #[cfg(feature = "unstable")] impl<'de, E> de::Deserializer<'de> for NeverDeserializer where E: de::Error, { type Error = E; fn deserialize_any(self, _visitor: V) -> Result where V: de::Visitor<'de>, { self.never } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } #[cfg(feature = "unstable")] impl<'de, E> IntoDeserializer<'de, E> for NeverDeserializer where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } //////////////////////////////////////////////////////////////////////////////// macro_rules! primitive_deserializer { ($ty:ty, $doc:tt, $name:ident, $method:ident $($cast:tt)*) => { #[doc = "A deserializer holding"] #[doc = $doc] pub struct $name { value: $ty, marker: PhantomData } impl_copy_clone!($name); impl<'de, E> IntoDeserializer<'de, E> for $ty where E: de::Error, { type Deserializer = $name; fn into_deserializer(self) -> $name { $name::new(self) } } impl $name { #[allow(missing_docs)] pub fn new(value: $ty) -> Self { $name { value, marker: PhantomData, } } } impl<'de, E> de::Deserializer<'de> for $name where E: de::Error, { type Error = E; 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 } fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.$method(self.value $($cast)*) } } impl<'de, E> IntoDeserializer<'de, E> for $name where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl Debug for $name { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct(stringify!($name)) .field("value", &self.value) .finish() } } } } primitive_deserializer!(bool, "a `bool`.", BoolDeserializer, visit_bool); primitive_deserializer!(i8, "an `i8`.", I8Deserializer, visit_i8); primitive_deserializer!(i16, "an `i16`.", I16Deserializer, visit_i16); primitive_deserializer!(i32, "an `i32`.", I32Deserializer, visit_i32); primitive_deserializer!(i64, "an `i64`.", I64Deserializer, visit_i64); primitive_deserializer!(i128, "an `i128`.", I128Deserializer, visit_i128); primitive_deserializer!(isize, "an `isize`.", IsizeDeserializer, visit_i64 as i64); primitive_deserializer!(u8, "a `u8`.", U8Deserializer, visit_u8); primitive_deserializer!(u16, "a `u16`.", U16Deserializer, visit_u16); primitive_deserializer!(u64, "a `u64`.", U64Deserializer, visit_u64); primitive_deserializer!(u128, "a `u128`.", U128Deserializer, visit_u128); primitive_deserializer!(usize, "a `usize`.", UsizeDeserializer, visit_u64 as u64); primitive_deserializer!(f32, "an `f32`.", F32Deserializer, visit_f32); primitive_deserializer!(f64, "an `f64`.", F64Deserializer, visit_f64); primitive_deserializer!(char, "a `char`.", CharDeserializer, visit_char); /// A deserializer holding a `u32`. pub struct U32Deserializer { value: u32, marker: PhantomData, } impl_copy_clone!(U32Deserializer); impl<'de, E> IntoDeserializer<'de, E> for u32 where E: de::Error, { type Deserializer = U32Deserializer; fn into_deserializer(self) -> U32Deserializer { U32Deserializer::new(self) } } impl U32Deserializer { #[allow(missing_docs)] pub fn new(value: u32) -> Self { U32Deserializer { value, marker: PhantomData, } } } impl<'de, E> de::Deserializer<'de> for U32Deserializer where E: de::Error, { type Error = E; 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 identifier ignored_any } fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_u32(self.value) } fn deserialize_enum( self, name: &str, variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { let _ = name; let _ = variants; visitor.visit_enum(self) } } impl<'de, E> IntoDeserializer<'de, E> for U32Deserializer where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl<'de, E> de::EnumAccess<'de> for U32Deserializer where E: de::Error, { type Error = E; type Variant = private::UnitOnly; fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> where T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } impl Debug for U32Deserializer { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("U32Deserializer") .field("value", &self.value) .finish() } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer holding a `&str`. pub struct StrDeserializer<'a, E> { value: &'a str, marker: PhantomData, } impl_copy_clone!(StrDeserializer<'de>); impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a str where E: de::Error, { type Deserializer = StrDeserializer<'a, E>; fn into_deserializer(self) -> StrDeserializer<'a, E> { StrDeserializer::new(self) } } impl<'a, E> StrDeserializer<'a, E> { #[allow(missing_docs)] pub fn new(value: &'a str) -> Self { StrDeserializer { value, marker: PhantomData, } } } impl<'de, 'a, E> de::Deserializer<'de> for StrDeserializer<'a, E> where E: de::Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_str(self.value) } fn deserialize_enum( self, name: &str, variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { let _ = name; let _ = variants; visitor.visit_enum(self) } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } } impl<'de, 'a, E> IntoDeserializer<'de, E> for StrDeserializer<'a, E> where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl<'de, 'a, E> de::EnumAccess<'de> for StrDeserializer<'a, E> where E: de::Error, { type Error = E; type Variant = private::UnitOnly; fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> where T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } impl<'a, E> Debug for StrDeserializer<'a, E> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("StrDeserializer") .field("value", &self.value) .finish() } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer holding a `&str` with a lifetime tied to another /// deserializer. pub struct BorrowedStrDeserializer<'de, E> { value: &'de str, marker: PhantomData, } impl_copy_clone!(BorrowedStrDeserializer<'de>); impl<'de, E> BorrowedStrDeserializer<'de, E> { /// Create a new borrowed deserializer from the given string. pub fn new(value: &'de str) -> BorrowedStrDeserializer<'de, E> { BorrowedStrDeserializer { value, marker: PhantomData, } } } impl<'de, E> de::Deserializer<'de> for BorrowedStrDeserializer<'de, E> where E: de::Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_borrowed_str(self.value) } fn deserialize_enum( self, name: &str, variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { let _ = name; let _ = variants; visitor.visit_enum(self) } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } } impl<'de, E> IntoDeserializer<'de, E> for BorrowedStrDeserializer<'de, E> where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl<'de, E> de::EnumAccess<'de> for BorrowedStrDeserializer<'de, E> where E: de::Error, { type Error = E; type Variant = private::UnitOnly; fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> where T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } impl<'de, E> Debug for BorrowedStrDeserializer<'de, E> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("BorrowedStrDeserializer") .field("value", &self.value) .finish() } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer holding a `String`. #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] pub struct StringDeserializer { value: String, marker: PhantomData, } #[cfg(any(feature = "std", feature = "alloc"))] impl Clone for StringDeserializer { fn clone(&self) -> Self { StringDeserializer { value: self.value.clone(), marker: PhantomData, } } } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, E> IntoDeserializer<'de, E> for String where E: de::Error, { type Deserializer = StringDeserializer; fn into_deserializer(self) -> StringDeserializer { StringDeserializer::new(self) } } #[cfg(any(feature = "std", feature = "alloc"))] impl StringDeserializer { #[allow(missing_docs)] pub fn new(value: String) -> Self { StringDeserializer { value, marker: PhantomData, } } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, E> de::Deserializer<'de> for StringDeserializer where E: de::Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_string(self.value) } fn deserialize_enum( self, name: &str, variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { let _ = name; let _ = variants; visitor.visit_enum(self) } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, E> IntoDeserializer<'de, E> for StringDeserializer where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, E> de::EnumAccess<'de> for StringDeserializer where E: de::Error, { type Error = E; type Variant = private::UnitOnly; fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> where T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } #[cfg(any(feature = "std", feature = "alloc"))] impl Debug for StringDeserializer { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("StringDeserializer") .field("value", &self.value) .finish() } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer holding a `Cow`. #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] pub struct CowStrDeserializer<'a, E> { value: Cow<'a, str>, marker: PhantomData, } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, E> Clone for CowStrDeserializer<'a, E> { fn clone(&self) -> Self { CowStrDeserializer { value: self.value.clone(), marker: PhantomData, } } } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, 'a, E> IntoDeserializer<'de, E> for Cow<'a, str> where E: de::Error, { type Deserializer = CowStrDeserializer<'a, E>; fn into_deserializer(self) -> CowStrDeserializer<'a, E> { CowStrDeserializer::new(self) } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, E> CowStrDeserializer<'a, E> { #[allow(missing_docs)] pub fn new(value: Cow<'a, str>) -> Self { CowStrDeserializer { value, marker: PhantomData, } } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, 'a, E> de::Deserializer<'de> for CowStrDeserializer<'a, E> where E: de::Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { match self.value { Cow::Borrowed(string) => visitor.visit_str(string), Cow::Owned(string) => visitor.visit_string(string), } } fn deserialize_enum( self, name: &str, variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { let _ = name; let _ = variants; visitor.visit_enum(self) } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, 'a, E> IntoDeserializer<'de, E> for CowStrDeserializer<'a, E> where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'de, 'a, E> de::EnumAccess<'de> for CowStrDeserializer<'a, E> where E: de::Error, { type Error = E; type Variant = private::UnitOnly; fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> where T: de::DeserializeSeed<'de>, { seed.deserialize(self).map(private::unit_only) } } #[cfg(any(feature = "std", feature = "alloc"))] impl<'a, E> Debug for CowStrDeserializer<'a, E> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("CowStrDeserializer") .field("value", &self.value) .finish() } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer holding a `&[u8]`. Always calls [`Visitor::visit_bytes`]. pub struct BytesDeserializer<'a, E> { value: &'a [u8], marker: PhantomData, } impl<'a, E> BytesDeserializer<'a, E> { /// Create a new deserializer from the given bytes. pub fn new(value: &'a [u8]) -> Self { BytesDeserializer { value, marker: PhantomData, } } } impl_copy_clone!(BytesDeserializer<'a>); impl<'de, 'a, E> IntoDeserializer<'de, E> for &'a [u8] where E: de::Error, { type Deserializer = BytesDeserializer<'a, E>; fn into_deserializer(self) -> BytesDeserializer<'a, E> { BytesDeserializer::new(self) } } impl<'de, 'a, E> Deserializer<'de> for BytesDeserializer<'a, E> where E: de::Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_bytes(self.value) } 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, 'a, E> IntoDeserializer<'de, E> for BytesDeserializer<'a, E> where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl<'a, E> Debug for BytesDeserializer<'a, E> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("BytesDeserializer") .field("value", &self.value) .finish() } } /// A deserializer holding a `&[u8]` with a lifetime tied to another /// deserializer. Always calls [`Visitor::visit_borrowed_bytes`]. pub struct BorrowedBytesDeserializer<'de, E> { value: &'de [u8], marker: PhantomData, } impl<'de, E> BorrowedBytesDeserializer<'de, E> { /// Create a new borrowed deserializer from the given borrowed bytes. pub fn new(value: &'de [u8]) -> Self { BorrowedBytesDeserializer { value, marker: PhantomData, } } } impl_copy_clone!(BorrowedBytesDeserializer<'de>); impl<'de, E> Deserializer<'de> for BorrowedBytesDeserializer<'de, E> where E: de::Error, { type Error = E; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_borrowed_bytes(self.value) } 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> IntoDeserializer<'de, E> for BorrowedBytesDeserializer<'de, E> where E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl<'de, E> Debug for BorrowedBytesDeserializer<'de, E> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("BorrowedBytesDeserializer") .field("value", &self.value) .finish() } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer that iterates over a sequence. #[derive(Clone)] pub struct SeqDeserializer { iter: iter::Fuse, count: usize, marker: PhantomData, } impl SeqDeserializer where I: Iterator, { /// Construct a new `SeqDeserializer`. pub fn new(iter: I) -> Self { SeqDeserializer { iter: iter.fuse(), count: 0, marker: PhantomData, } } } impl SeqDeserializer where I: Iterator, E: de::Error, { /// Check for remaining elements after passing a `SeqDeserializer` to /// `Visitor::visit_seq`. pub fn end(self) -> Result<(), E> { let remaining = self.iter.count(); if remaining == 0 { Ok(()) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length( self.count + remaining, &ExpectedInSeq(self.count), )) } } } impl<'de, I, T, E> de::Deserializer<'de> for SeqDeserializer where I: Iterator, T: IntoDeserializer<'de, E>, E: de::Error, { type Error = E; fn deserialize_any(mut self, visitor: V) -> Result where V: de::Visitor<'de>, { let v = tri!(visitor.visit_seq(&mut self)); tri!(self.end()); Ok(v) } 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, I, T, E> IntoDeserializer<'de, E> for SeqDeserializer where I: Iterator, T: IntoDeserializer<'de, E>, E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl<'de, I, T, E> de::SeqAccess<'de> for SeqDeserializer where I: Iterator, T: IntoDeserializer<'de, E>, E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: V) -> Result, Self::Error> where V: de::DeserializeSeed<'de>, { match self.iter.next() { Some(value) => { self.count += 1; seed.deserialize(value.into_deserializer()).map(Some) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } struct ExpectedInSeq(usize); impl Expected for ExpectedInSeq { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { formatter.write_str("1 element in sequence") } else { write!(formatter, "{} elements in sequence", self.0) } } } impl Debug for SeqDeserializer where I: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("SeqDeserializer") .field("iter", &self.iter) .field("count", &self.count) .finish() } } //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T, E> IntoDeserializer<'de, E> for Vec where T: IntoDeserializer<'de, E>, E: de::Error, { type Deserializer = SeqDeserializer<::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { SeqDeserializer::new(self.into_iter()) } } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, T, E> IntoDeserializer<'de, E> for BTreeSet where T: IntoDeserializer<'de, E> + Eq + Ord, E: de::Error, { type Deserializer = SeqDeserializer<::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { SeqDeserializer::new(self.into_iter()) } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de, T, S, E> IntoDeserializer<'de, E> for HashSet where T: IntoDeserializer<'de, E> + Eq + Hash, S: BuildHasher, E: de::Error, { type Deserializer = SeqDeserializer<::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { SeqDeserializer::new(self.into_iter()) } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer holding a `SeqAccess`. #[derive(Clone, Debug)] pub struct SeqAccessDeserializer { seq: A, } impl SeqAccessDeserializer { /// Construct a new `SeqAccessDeserializer`. pub fn new(seq: A) -> Self { SeqAccessDeserializer { seq } } } impl<'de, A> de::Deserializer<'de> for SeqAccessDeserializer where A: de::SeqAccess<'de>, { type Error = A::Error; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_seq(self.seq) } 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, A> IntoDeserializer<'de, A::Error> for SeqAccessDeserializer where A: de::SeqAccess<'de>, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer that iterates over a map. pub struct MapDeserializer<'de, I, E> where I: Iterator, I::Item: private::Pair, { iter: iter::Fuse, value: Option>, count: usize, lifetime: PhantomData<&'de ()>, error: PhantomData, } impl<'de, I, E> MapDeserializer<'de, I, E> where I: Iterator, I::Item: private::Pair, { /// Construct a new `MapDeserializer`. pub fn new(iter: I) -> Self { MapDeserializer { iter: iter.fuse(), value: None, count: 0, lifetime: PhantomData, error: PhantomData, } } } impl<'de, I, E> MapDeserializer<'de, I, E> where I: Iterator, I::Item: private::Pair, E: de::Error, { /// Check for remaining elements after passing a `MapDeserializer` to /// `Visitor::visit_map`. pub fn end(self) -> Result<(), E> { let remaining = self.iter.count(); if remaining == 0 { Ok(()) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length( self.count + remaining, &ExpectedInMap(self.count), )) } } } impl<'de, I, E> MapDeserializer<'de, I, E> where I: Iterator, I::Item: private::Pair, { fn next_pair(&mut self) -> Option<(First, Second)> { match self.iter.next() { Some(kv) => { self.count += 1; Some(private::Pair::split(kv)) } None => None, } } } impl<'de, I, E> de::Deserializer<'de> for MapDeserializer<'de, I, E> where I: Iterator, I::Item: private::Pair, First: IntoDeserializer<'de, E>, Second: IntoDeserializer<'de, E>, E: de::Error, { type Error = E; fn deserialize_any(mut self, visitor: V) -> Result where V: de::Visitor<'de>, { let value = tri!(visitor.visit_map(&mut self)); tri!(self.end()); Ok(value) } fn deserialize_seq(mut self, visitor: V) -> Result where V: de::Visitor<'de>, { let value = tri!(visitor.visit_seq(&mut self)); tri!(self.end()); Ok(value) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { let _ = len; self.deserialize_seq(visitor) } 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 tuple_struct map struct enum identifier ignored_any } } impl<'de, I, E> IntoDeserializer<'de, E> for MapDeserializer<'de, I, E> where I: Iterator, I::Item: private::Pair, First: IntoDeserializer<'de, E>, Second: IntoDeserializer<'de, E>, E: de::Error, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl<'de, I, E> de::MapAccess<'de> for MapDeserializer<'de, I, E> where I: Iterator, I::Item: private::Pair, First: IntoDeserializer<'de, E>, Second: IntoDeserializer<'de, E>, E: de::Error, { type Error = E; fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> where T: de::DeserializeSeed<'de>, { match self.next_pair() { Some((key, value)) => { self.value = Some(value); seed.deserialize(key.into_deserializer()).map(Some) } None => Ok(None), } } fn next_value_seed(&mut self, seed: T) -> Result where T: de::DeserializeSeed<'de>, { let value = self.value.take(); // Panic because this indicates a bug in the program rather than an // expected failure. let value = value.expect("MapAccess::next_value called before next_key"); seed.deserialize(value.into_deserializer()) } fn next_entry_seed( &mut self, kseed: TK, vseed: TV, ) -> Result, Self::Error> where TK: de::DeserializeSeed<'de>, TV: de::DeserializeSeed<'de>, { match self.next_pair() { Some((key, value)) => { let key = tri!(kseed.deserialize(key.into_deserializer())); let value = tri!(vseed.deserialize(value.into_deserializer())); Ok(Some((key, value))) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } impl<'de, I, E> de::SeqAccess<'de> for MapDeserializer<'de, I, E> where I: Iterator, I::Item: private::Pair, First: IntoDeserializer<'de, E>, Second: IntoDeserializer<'de, E>, E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: de::DeserializeSeed<'de>, { match self.next_pair() { Some((k, v)) => { let de = PairDeserializer(k, v, PhantomData); seed.deserialize(de).map(Some) } None => Ok(None), } } fn size_hint(&self) -> Option { size_hint::from_bounds(&self.iter) } } // Cannot #[derive(Clone)] because of the bound `Second: Clone`. impl<'de, I, E> Clone for MapDeserializer<'de, I, E> where I: Iterator + Clone, I::Item: private::Pair, Second: Clone, { fn clone(&self) -> Self { MapDeserializer { iter: self.iter.clone(), value: self.value.clone(), count: self.count, lifetime: self.lifetime, error: self.error, } } } impl<'de, I, E> Debug for MapDeserializer<'de, I, E> where I: Iterator + Debug, I::Item: private::Pair, Second: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_struct("MapDeserializer") .field("iter", &self.iter) .field("value", &self.value) .field("count", &self.count) .finish() } } // Used in the `impl SeqAccess for MapDeserializer` to visit the map as a // sequence of pairs. struct PairDeserializer(A, B, PhantomData); impl<'de, A, B, E> de::Deserializer<'de> for PairDeserializer where A: IntoDeserializer<'de, E>, B: IntoDeserializer<'de, E>, E: de::Error, { type Error = E; 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 tuple_struct map struct enum identifier ignored_any } fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { self.deserialize_seq(visitor) } fn deserialize_seq(self, visitor: V) -> Result where V: de::Visitor<'de>, { let mut pair_visitor = PairVisitor(Some(self.0), Some(self.1), PhantomData); let pair = tri!(visitor.visit_seq(&mut pair_visitor)); if pair_visitor.1.is_none() { Ok(pair) } else { let remaining = pair_visitor.size_hint().unwrap(); // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length(2, &ExpectedInSeq(2 - remaining))) } } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: de::Visitor<'de>, { if len == 2 { self.deserialize_seq(visitor) } else { // First argument is the number of elements in the data, second // argument is the number of elements expected by the Deserialize. Err(de::Error::invalid_length(2, &ExpectedInSeq(len))) } } } struct PairVisitor(Option, Option, PhantomData); impl<'de, A, B, E> de::SeqAccess<'de> for PairVisitor where A: IntoDeserializer<'de, E>, B: IntoDeserializer<'de, E>, E: de::Error, { type Error = E; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: de::DeserializeSeed<'de>, { if let Some(k) = self.0.take() { seed.deserialize(k.into_deserializer()).map(Some) } else if let Some(v) = self.1.take() { seed.deserialize(v.into_deserializer()).map(Some) } else { Ok(None) } } fn size_hint(&self) -> Option { if self.0.is_some() { Some(2) } else if self.1.is_some() { Some(1) } else { Some(0) } } } struct ExpectedInMap(usize); impl Expected for ExpectedInMap { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { formatter.write_str("1 element in map") } else { write!(formatter, "{} elements in map", self.0) } } } //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl<'de, K, V, E> IntoDeserializer<'de, E> for BTreeMap where K: IntoDeserializer<'de, E> + Eq + Ord, V: IntoDeserializer<'de, E>, E: de::Error, { type Deserializer = MapDeserializer<'de, ::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { MapDeserializer::new(self.into_iter()) } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'de, K, V, S, E> IntoDeserializer<'de, E> for HashMap where K: IntoDeserializer<'de, E> + Eq + Hash, V: IntoDeserializer<'de, E>, S: BuildHasher, E: de::Error, { type Deserializer = MapDeserializer<'de, ::IntoIter, E>; fn into_deserializer(self) -> Self::Deserializer { MapDeserializer::new(self.into_iter()) } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer holding a `MapAccess`. #[derive(Clone, Debug)] pub struct MapAccessDeserializer { map: A, } impl MapAccessDeserializer { /// Construct a new `MapAccessDeserializer`. pub fn new(map: A) -> Self { MapAccessDeserializer { map } } } impl<'de, A> de::Deserializer<'de> for MapAccessDeserializer where A: de::MapAccess<'de>, { type Error = A::Error; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_map(self.map) } fn deserialize_enum( self, _name: &str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { visitor.visit_enum(self) } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct identifier ignored_any } } impl<'de, A> IntoDeserializer<'de, A::Error> for MapAccessDeserializer where A: de::MapAccess<'de>, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } impl<'de, A> de::EnumAccess<'de> for MapAccessDeserializer where A: de::MapAccess<'de>, { type Error = A::Error; type Variant = private::MapAsEnum; fn variant_seed(mut self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> where T: de::DeserializeSeed<'de>, { match tri!(self.map.next_key_seed(seed)) { Some(key) => Ok((key, private::map_as_enum(self.map))), None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")), } } } //////////////////////////////////////////////////////////////////////////////// /// A deserializer holding an `EnumAccess`. #[derive(Clone, Debug)] pub struct EnumAccessDeserializer { access: A, } impl EnumAccessDeserializer { /// Construct a new `EnumAccessDeserializer`. pub fn new(access: A) -> Self { EnumAccessDeserializer { access } } } impl<'de, A> de::Deserializer<'de> for EnumAccessDeserializer where A: de::EnumAccess<'de>, { type Error = A::Error; fn deserialize_any(self, visitor: V) -> Result where V: de::Visitor<'de>, { visitor.visit_enum(self.access) } 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, A> IntoDeserializer<'de, A::Error> for EnumAccessDeserializer where A: de::EnumAccess<'de>, { type Deserializer = Self; fn into_deserializer(self) -> Self { self } } //////////////////////////////////////////////////////////////////////////////// mod private { use crate::lib::*; use crate::de::{ self, DeserializeSeed, Deserializer, MapAccess, Unexpected, VariantAccess, Visitor, }; pub struct UnitOnly { marker: PhantomData, } pub fn unit_only(t: T) -> (T, UnitOnly) { ( t, UnitOnly { marker: PhantomData, }, ) } impl<'de, E> de::VariantAccess<'de> for UnitOnly where E: de::Error, { type Error = E; fn unit_variant(self) -> Result<(), Self::Error> { Ok(()) } fn newtype_variant_seed(self, _seed: T) -> Result where T: de::DeserializeSeed<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"newtype variant", )) } fn tuple_variant(self, _len: usize, _visitor: V) -> Result where V: de::Visitor<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"tuple variant", )) } fn struct_variant( self, _fields: &'static [&'static str], _visitor: V, ) -> Result where V: de::Visitor<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"struct variant", )) } } pub struct MapAsEnum { map: A, } pub fn map_as_enum(map: A) -> MapAsEnum { MapAsEnum { map } } impl<'de, A> VariantAccess<'de> for MapAsEnum where A: MapAccess<'de>, { type Error = A::Error; fn unit_variant(mut self) -> Result<(), Self::Error> { self.map.next_value() } fn newtype_variant_seed(mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { self.map.next_value_seed(seed) } fn tuple_variant(mut self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.map.next_value_seed(SeedTupleVariant { len, visitor }) } fn struct_variant( mut self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.map.next_value_seed(SeedStructVariant { visitor }) } } struct SeedTupleVariant { len: usize, visitor: V, } impl<'de, V> DeserializeSeed<'de> for SeedTupleVariant where V: Visitor<'de>, { type Value = V::Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_tuple(self.len, self.visitor) } } struct SeedStructVariant { visitor: V, } impl<'de, V> DeserializeSeed<'de> for SeedStructVariant where V: Visitor<'de>, { type Value = V::Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_map(self.visitor) } } /// Avoid having to restate the generic types on `MapDeserializer`. The /// `Iterator::Item` contains enough information to figure out K and V. pub trait Pair { type First; type Second; fn split(self) -> (Self::First, Self::Second); } impl Pair for (A, B) { type First = A; type Second = B; fn split(self) -> (A, B) { self } } pub type First = ::First; pub type Second = ::Second; } ================================================ FILE: serde_core/src/format.rs ================================================ use crate::lib::fmt::{self, Write}; use crate::lib::str; pub(super) struct Buf<'a> { bytes: &'a mut [u8], offset: usize, } impl<'a> Buf<'a> { pub fn new(bytes: &'a mut [u8]) -> Self { Buf { bytes, offset: 0 } } pub fn as_str(&self) -> &str { let slice = &self.bytes[..self.offset]; unsafe { str::from_utf8_unchecked(slice) } } } impl<'a> Write for Buf<'a> { fn write_str(&mut self, s: &str) -> fmt::Result { if self.offset + s.len() > self.bytes.len() { Err(fmt::Error) } else { self.bytes[self.offset..self.offset + s.len()].copy_from_slice(s.as_bytes()); self.offset += s.len(); Ok(()) } } } ================================================ FILE: serde_core/src/lib.rs ================================================ //! Serde is a framework for ***ser***ializing and ***de***serializing Rust data //! structures efficiently and generically. //! //! The `serde_core` crate contains Serde's trait definitions with **no support //! for #\[derive()\]**. //! //! In crates that derive an implementation of `Serialize` or `Deserialize`, you //! must depend on the [`serde`] crate, not `serde_core`. //! //! [`serde`]: https://crates.io/crates/serde //! //! In crates that handwrite implementations of Serde traits, or only use them //! as trait bounds, depending on `serde_core` is permitted. But `serde` //! re-exports all of these traits and can be used for this use case too. If in //! doubt, disregard `serde_core` and always use `serde`. //! //! Crates that depend on `serde_core` instead of `serde` are able to compile in //! parallel with `serde_derive` even when `serde`'s "derive" feature is turned on, //! as shown in the following build timings. //! //!
//! //! //! //! //!
When serde_json depends on serde
//! //!
//! //! //! //! //!
When serde_json depends on serde_core
//////////////////////////////////////////////////////////////////////////////// // Serde types in rustdoc of other crates get linked to here. #![doc(html_root_url = "https://docs.rs/serde_core/1.0.228")] // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. #![cfg_attr(docsrs, feature(doc_cfg, rustdoc_internals))] #![cfg_attr(docsrs, allow(internal_features))] // Unstable functionality only if the user asks for it. For tracking and // discussion of these features please refer to this issue: // // https://github.com/serde-rs/serde/issues/812 #![cfg_attr(feature = "unstable", feature(never_type))] #![allow(unknown_lints, bare_trait_objects, deprecated)] // Ignored clippy and clippy_pedantic lints #![allow( // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 clippy::unnested_or_patterns, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7768 clippy::semicolon_if_nothing_returned, // not available in our oldest supported compiler clippy::empty_enums, clippy::type_repetition_in_bounds, // https://github.com/rust-lang/rust-clippy/issues/8772 // integer and float ser/de requires these sorts of casts clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_sign_loss, // things are often more readable this way clippy::cast_lossless, clippy::module_name_repetitions, clippy::single_match_else, clippy::type_complexity, clippy::use_self, clippy::zero_prefixed_literal, // correctly used clippy::derive_partial_eq_without_eq, clippy::enum_glob_use, clippy::explicit_auto_deref, clippy::incompatible_msrv, clippy::let_underscore_untyped, clippy::map_err_ignore, clippy::new_without_default, clippy::result_unit_err, clippy::wildcard_imports, // not practical clippy::needless_pass_by_value, clippy::similar_names, clippy::too_many_lines, // preference clippy::doc_markdown, clippy::elidable_lifetime_names, clippy::needless_lifetimes, clippy::unseparated_literal_suffix, // false positive clippy::needless_doctest_main, // noisy clippy::missing_errors_doc, clippy::must_use_candidate, )] // Restrictions #![deny(clippy::question_mark_used)] // Rustc lints. #![deny(missing_docs, unused_imports)] //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "alloc")] extern crate alloc; #[macro_use] mod crate_root; #[macro_use] mod macros; crate_root!(); #[macro_export] #[doc(hidden)] macro_rules! __require_serde_not_serde_core { () => { ::core::compile_error!( "Serde derive requires a dependency on the serde crate, not serde_core" ); }; } ================================================ FILE: serde_core/src/macros.rs ================================================ // Super explicit first paragraph because this shows up at the top level and // trips up people who are just looking for basic Serialize / Deserialize // documentation. /// Helper macro when implementing the `Deserializer` part of a new data format /// for Serde. /// /// Some [`Deserializer`] implementations for self-describing formats do not /// care what hint the [`Visitor`] gives them, they just want to blindly call /// the [`Visitor`] method corresponding to the data they can tell is in the /// input. This requires repetitive implementations of all the [`Deserializer`] /// trait methods. /// /// ```edition2021 /// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; /// # /// # struct MyDeserializer; /// # /// # impl<'de> Deserializer<'de> for MyDeserializer { /// # type Error = value::Error; /// # /// # fn deserialize_any(self, _: V) -> Result /// # where /// # V: Visitor<'de>, /// # { /// # unimplemented!() /// # } /// # /// #[inline] /// fn deserialize_bool(self, visitor: V) -> Result /// where /// V: Visitor<'de>, /// { /// self.deserialize_any(visitor) /// } /// # /// # forward_to_deserialize_any! { /// # 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 /// # } /// # } /// ``` /// /// The `forward_to_deserialize_any!` macro implements these simple forwarding /// methods so that they forward directly to [`Deserializer::deserialize_any`]. /// You can choose which methods to forward. /// /// ```edition2021 /// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; /// # /// # struct MyDeserializer; /// # /// impl<'de> Deserializer<'de> for MyDeserializer { /// # type Error = value::Error; /// # /// fn deserialize_any(self, visitor: V) -> Result /// where /// V: Visitor<'de>, /// { /// /* ... */ /// # let _ = visitor; /// # unimplemented!() /// } /// /// 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 /// } /// } /// ``` /// /// The macro assumes the convention that your `Deserializer` lifetime parameter /// is called `'de` and that the `Visitor` type parameters on each method are /// called `V`. A different type parameter and a different lifetime can be /// specified explicitly if necessary. /// /// ```edition2021 /// # use serde::forward_to_deserialize_any; /// # use serde::de::{value, Deserializer, Visitor}; /// # use std::marker::PhantomData; /// # /// # struct MyDeserializer(PhantomData); /// # /// # impl<'q, V> Deserializer<'q> for MyDeserializer { /// # type Error = value::Error; /// # /// # fn deserialize_any(self, visitor: W) -> Result /// # where /// # W: Visitor<'q>, /// # { /// # unimplemented!() /// # } /// # /// 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 /// } /// # } /// ``` /// /// [`Deserializer`]: crate::Deserializer /// [`Visitor`]: crate::de::Visitor /// [`Deserializer::deserialize_any`]: crate::Deserializer::deserialize_any #[macro_export(local_inner_macros)] macro_rules! forward_to_deserialize_any { (<$visitor:ident: Visitor<$lifetime:tt>> $($func:ident)*) => { $(forward_to_deserialize_any_helper!{$func<$lifetime, $visitor>})* }; // This case must be after the previous one. ($($func:ident)*) => { $(forward_to_deserialize_any_helper!{$func<'de, V>})* }; } #[doc(hidden)] #[macro_export] macro_rules! forward_to_deserialize_any_method { ($func:ident<$l:tt, $v:ident>($($arg:ident : $ty:ty),*)) => { #[inline] fn $func<$v>(self, $($arg: $ty,)* visitor: $v) -> $crate::__private::Result<$v::Value, >::Error> where $v: $crate::de::Visitor<$l>, { $( let _ = $arg; )* self.deserialize_any(visitor) } }; } #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! forward_to_deserialize_any_helper { (bool<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_bool<$l, $v>()} }; (i8<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_i8<$l, $v>()} }; (i16<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_i16<$l, $v>()} }; (i32<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_i32<$l, $v>()} }; (i64<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_i64<$l, $v>()} }; (i128<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_i128<$l, $v>()} }; (u8<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_u8<$l, $v>()} }; (u16<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_u16<$l, $v>()} }; (u32<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_u32<$l, $v>()} }; (u64<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_u64<$l, $v>()} }; (u128<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_u128<$l, $v>()} }; (f32<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_f32<$l, $v>()} }; (f64<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_f64<$l, $v>()} }; (char<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_char<$l, $v>()} }; (str<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_str<$l, $v>()} }; (string<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_string<$l, $v>()} }; (bytes<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_bytes<$l, $v>()} }; (byte_buf<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_byte_buf<$l, $v>()} }; (option<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_option<$l, $v>()} }; (unit<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_unit<$l, $v>()} }; (unit_struct<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_unit_struct<$l, $v>(name: &'static str)} }; (newtype_struct<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_newtype_struct<$l, $v>(name: &'static str)} }; (seq<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_seq<$l, $v>()} }; (tuple<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_tuple<$l, $v>(len: usize)} }; (tuple_struct<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_tuple_struct<$l, $v>(name: &'static str, len: usize)} }; (map<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_map<$l, $v>()} }; (struct<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_struct<$l, $v>(name: &'static str, fields: &'static [&'static str])} }; (enum<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_enum<$l, $v>(name: &'static str, variants: &'static [&'static str])} }; (identifier<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_identifier<$l, $v>()} }; (ignored_any<$l:tt, $v:ident>) => { forward_to_deserialize_any_method!{deserialize_ignored_any<$l, $v>()} }; } ================================================ FILE: serde_core/src/private/content.rs ================================================ use crate::lib::*; // Used from generated code to buffer the contents of the Deserializer when // deserializing untagged enums and internally tagged enums. // // Not public API. Use serde-value instead. // // Obsoleted by format-specific buffer types (https://github.com/serde-rs/serde/pull/2912). #[doc(hidden)] pub enum Content<'de> { Bool(bool), U8(u8), U16(u16), U32(u32), U64(u64), I8(i8), I16(i16), I32(i32), I64(i64), F32(f32), F64(f64), Char(char), String(String), Str(&'de str), ByteBuf(Vec), Bytes(&'de [u8]), None, Some(Box>), Unit, Newtype(Box>), Seq(Vec>), Map(Vec<(Content<'de>, Content<'de>)>), } ================================================ FILE: serde_core/src/private/doc.rs ================================================ // Used only by Serde doc tests. Not public API. use crate::lib::*; use crate::ser; #[doc(hidden)] #[derive(Debug)] pub struct Error; #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl ser::Error for Error { fn custom(_: T) -> Self where T: Display, { unimplemented!() } } #[cfg(feature = "std")] #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl error::Error for Error { fn description(&self) -> &str { unimplemented!() } } #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl Display for Error { fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { unimplemented!() } } #[doc(hidden)] #[macro_export] macro_rules! __private_serialize { () => { trait Serialize { fn serialize(&self, serializer: S) -> Result where S: $crate::Serializer; } }; } #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! __serialize_unimplemented { ($($func:ident)*) => { $( __serialize_unimplemented_helper!($func); )* }; } #[doc(hidden)] #[macro_export] macro_rules! __serialize_unimplemented_method { ($func:ident $(<$t:ident>)* ($($arg:ty),*) -> $ret:ident) => { fn $func $(<$t>)* (self $(, _: $arg)*) -> $crate::__private::Result where $($t: ?Sized + $crate::Serialize,)* { unimplemented!() } }; } #[doc(hidden)] #[macro_export(local_inner_macros)] macro_rules! __serialize_unimplemented_helper { (bool) => { __serialize_unimplemented_method!(serialize_bool(bool) -> Ok); }; (i8) => { __serialize_unimplemented_method!(serialize_i8(i8) -> Ok); }; (i16) => { __serialize_unimplemented_method!(serialize_i16(i16) -> Ok); }; (i32) => { __serialize_unimplemented_method!(serialize_i32(i32) -> Ok); }; (i64) => { __serialize_unimplemented_method!(serialize_i64(i64) -> Ok); }; (u8) => { __serialize_unimplemented_method!(serialize_u8(u8) -> Ok); }; (u16) => { __serialize_unimplemented_method!(serialize_u16(u16) -> Ok); }; (u32) => { __serialize_unimplemented_method!(serialize_u32(u32) -> Ok); }; (u64) => { __serialize_unimplemented_method!(serialize_u64(u64) -> Ok); }; (f32) => { __serialize_unimplemented_method!(serialize_f32(f32) -> Ok); }; (f64) => { __serialize_unimplemented_method!(serialize_f64(f64) -> Ok); }; (char) => { __serialize_unimplemented_method!(serialize_char(char) -> Ok); }; (str) => { __serialize_unimplemented_method!(serialize_str(&str) -> Ok); }; (bytes) => { __serialize_unimplemented_method!(serialize_bytes(&[u8]) -> Ok); }; (none) => { __serialize_unimplemented_method!(serialize_none() -> Ok); }; (some) => { __serialize_unimplemented_method!(serialize_some(&T) -> Ok); }; (unit) => { __serialize_unimplemented_method!(serialize_unit() -> Ok); }; (unit_struct) => { __serialize_unimplemented_method!(serialize_unit_struct(&str) -> Ok); }; (unit_variant) => { __serialize_unimplemented_method!(serialize_unit_variant(&str, u32, &str) -> Ok); }; (newtype_struct) => { __serialize_unimplemented_method!(serialize_newtype_struct(&str, &T) -> Ok); }; (newtype_variant) => { __serialize_unimplemented_method!(serialize_newtype_variant(&str, u32, &str, &T) -> Ok); }; (seq) => { type SerializeSeq = $crate::ser::Impossible; __serialize_unimplemented_method!(serialize_seq(Option) -> SerializeSeq); }; (tuple) => { type SerializeTuple = $crate::ser::Impossible; __serialize_unimplemented_method!(serialize_tuple(usize) -> SerializeTuple); }; (tuple_struct) => { type SerializeTupleStruct = $crate::ser::Impossible; __serialize_unimplemented_method!(serialize_tuple_struct(&str, usize) -> SerializeTupleStruct); }; (tuple_variant) => { type SerializeTupleVariant = $crate::ser::Impossible; __serialize_unimplemented_method!(serialize_tuple_variant(&str, u32, &str, usize) -> SerializeTupleVariant); }; (map) => { type SerializeMap = $crate::ser::Impossible; __serialize_unimplemented_method!(serialize_map(Option) -> SerializeMap); }; (struct) => { type SerializeStruct = $crate::ser::Impossible; __serialize_unimplemented_method!(serialize_struct(&str, usize) -> SerializeStruct); }; (struct_variant) => { type SerializeStructVariant = $crate::ser::Impossible; __serialize_unimplemented_method!(serialize_struct_variant(&str, u32, &str, usize) -> SerializeStructVariant); }; } ================================================ FILE: serde_core/src/private/mod.rs ================================================ #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] mod content; mod seed; // FIXME: #[cfg(doctest)] once https://github.com/rust-lang/rust/issues/67295 is fixed. #[doc(hidden)] pub mod doc; #[doc(hidden)] pub mod size_hint; #[doc(hidden)] pub mod string; #[cfg(all(not(no_serde_derive), any(feature = "std", feature = "alloc")))] #[doc(hidden)] pub use self::content::Content; #[doc(hidden)] pub use self::seed::InPlaceSeed; #[doc(hidden)] pub use crate::lib::result::Result; ================================================ FILE: serde_core/src/private/seed.rs ================================================ use crate::de::{Deserialize, DeserializeSeed, Deserializer}; /// A DeserializeSeed helper for implementing deserialize_in_place Visitors. /// /// Wraps a mutable reference and calls deserialize_in_place on it. pub struct InPlaceSeed<'a, T: 'a>(pub &'a mut T); #[cfg_attr(not(no_diagnostic_namespace), diagnostic::do_not_recommend)] impl<'a, 'de, T> DeserializeSeed<'de> for InPlaceSeed<'a, T> where T: Deserialize<'de>, { type Value = (); fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { T::deserialize_in_place(deserializer, self.0) } } ================================================ FILE: serde_core/src/private/size_hint.rs ================================================ #[cfg(any(feature = "std", feature = "alloc"))] use crate::lib::*; pub fn from_bounds(iter: &I) -> Option where I: Iterator, { helper(iter.size_hint()) } #[cfg(any(feature = "std", feature = "alloc"))] pub fn cautious(hint: Option) -> usize { const MAX_PREALLOC_BYTES: usize = 1024 * 1024; if mem::size_of::() == 0 { 0 } else { cmp::min( hint.unwrap_or(0), MAX_PREALLOC_BYTES / mem::size_of::(), ) } } fn helper(bounds: (usize, Option)) -> Option { match bounds { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } ================================================ FILE: serde_core/src/private/string.rs ================================================ use crate::lib::*; #[cfg(any(feature = "std", feature = "alloc"))] #[doc(hidden)] pub fn from_utf8_lossy(bytes: &[u8]) -> Cow<'_, str> { String::from_utf8_lossy(bytes) } // The generated code calls this like: // // let value = &_serde::__private::from_utf8_lossy(bytes); // Err(_serde::de::Error::unknown_variant(value, VARIANTS)) // // so it is okay for the return type to be different from the std case as long // as the above works. #[cfg(not(any(feature = "std", feature = "alloc")))] #[doc(hidden)] pub fn from_utf8_lossy(bytes: &[u8]) -> &str { // Three unicode replacement characters if it fails. They look like a // white-on-black question mark. The user will recognize it as invalid // UTF-8. str::from_utf8(bytes).unwrap_or("\u{fffd}\u{fffd}\u{fffd}") } ================================================ FILE: serde_core/src/ser/fmt.rs ================================================ use crate::lib::*; use crate::ser::{Error, Impossible, Serialize, Serializer}; impl Error for fmt::Error { fn custom(_msg: T) -> Self { fmt::Error } } macro_rules! fmt_primitives { ($($f:ident: $t:ty,)*) => { $( fn $f(self, v: $t) -> fmt::Result { Display::fmt(&v, self) } )* }; } /// ```edition2021 /// use serde::ser::Serialize; /// use serde_derive::Serialize; /// use std::fmt::{self, Display}; /// /// #[derive(Serialize)] /// #[serde(rename_all = "kebab-case")] /// pub enum MessageType { /// StartRequest, /// EndRequest, /// } /// /// impl Display for MessageType { /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { /// self.serialize(f) /// } /// } /// ``` impl<'a> Serializer for &mut fmt::Formatter<'a> { type Ok = (); type Error = fmt::Error; type SerializeSeq = Impossible<(), fmt::Error>; type SerializeTuple = Impossible<(), fmt::Error>; type SerializeTupleStruct = Impossible<(), fmt::Error>; type SerializeTupleVariant = Impossible<(), fmt::Error>; type SerializeMap = Impossible<(), fmt::Error>; type SerializeStruct = Impossible<(), fmt::Error>; type SerializeStructVariant = Impossible<(), fmt::Error>; fmt_primitives! { serialize_bool: bool, serialize_i8: i8, serialize_i16: i16, serialize_i32: i32, serialize_i64: i64, serialize_i128: i128, serialize_u8: u8, serialize_u16: u16, serialize_u32: u32, serialize_u64: u64, serialize_u128: u128, serialize_f32: f32, serialize_f64: f64, serialize_char: char, serialize_str: &str, serialize_unit_struct: &'static str, } fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, ) -> fmt::Result { Display::fmt(variant, self) } fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> fmt::Result where T: ?Sized + Serialize, { Serialize::serialize(value, self) } fn serialize_bytes(self, _v: &[u8]) -> fmt::Result { Err(fmt::Error) } fn serialize_none(self) -> fmt::Result { Err(fmt::Error) } fn serialize_some(self, _value: &T) -> fmt::Result where T: ?Sized + Serialize, { Err(fmt::Error) } fn serialize_unit(self) -> fmt::Result { Err(fmt::Error) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, _variant: &'static str, _value: &T, ) -> fmt::Result where T: ?Sized + Serialize, { Err(fmt::Error) } fn serialize_seq(self, _len: Option) -> Result { Err(fmt::Error) } fn serialize_tuple(self, _len: usize) -> Result { Err(fmt::Error) } fn serialize_tuple_struct( self, _name: &'static str, _len: usize, ) -> Result { Err(fmt::Error) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize, ) -> Result { Err(fmt::Error) } fn serialize_map(self, _len: Option) -> Result { Err(fmt::Error) } fn serialize_struct( self, _name: &'static str, _len: usize, ) -> Result { Err(fmt::Error) } fn serialize_struct_variant( self, _name: &'static str, _variant_index: u32, _variant: &'static str, _len: usize, ) -> Result { Err(fmt::Error) } fn collect_str(self, value: &T) -> fmt::Result where T: ?Sized + Display, { Display::fmt(value, self) } } ================================================ FILE: serde_core/src/ser/impls.rs ================================================ use crate::lib::*; use crate::ser::{Error, Serialize, SerializeTuple, Serializer}; //////////////////////////////////////////////////////////////////////////////// macro_rules! primitive_impl { ($ty:ident, $method:ident $($cast:tt)*) => { impl Serialize for $ty { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.$method(*self $($cast)*) } } } } primitive_impl!(bool, serialize_bool); primitive_impl!(isize, serialize_i64 as i64); primitive_impl!(i8, serialize_i8); primitive_impl!(i16, serialize_i16); primitive_impl!(i32, serialize_i32); primitive_impl!(i64, serialize_i64); primitive_impl!(i128, serialize_i128); primitive_impl!(usize, serialize_u64 as u64); primitive_impl!(u8, serialize_u8); primitive_impl!(u16, serialize_u16); primitive_impl!(u32, serialize_u32); primitive_impl!(u64, serialize_u64); primitive_impl!(u128, serialize_u128); primitive_impl!(f32, serialize_f32); primitive_impl!(f64, serialize_f64); primitive_impl!(char, serialize_char); //////////////////////////////////////////////////////////////////////////////// impl Serialize for str { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_str(self) } } #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl Serialize for String { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_str(self) } } impl<'a> Serialize for fmt::Arguments<'a> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.collect_str(self) } } //////////////////////////////////////////////////////////////////////////////// #[cfg(any(feature = "std", not(no_core_cstr)))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for CStr { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_bytes(self.to_bytes()) } } #[cfg(any(feature = "std", all(not(no_core_cstr), feature = "alloc")))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] impl Serialize for CString { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_bytes(self.to_bytes()) } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for Option where T: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { match *self { Some(ref value) => serializer.serialize_some(value), None => serializer.serialize_none(), } } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for PhantomData where T: ?Sized, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_unit_struct("PhantomData") } } //////////////////////////////////////////////////////////////////////////////// // Does not require T: Serialize. impl Serialize for [T; 0] { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { tri!(serializer.serialize_tuple(0)).end() } } macro_rules! array_impls { ($($len:tt)+) => { $( impl Serialize for [T; $len] where T: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut seq = tri!(serializer.serialize_tuple($len)); for e in self { tri!(seq.serialize_element(e)); } seq.end() } } )+ } } array_impls! { 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 } //////////////////////////////////////////////////////////////////////////////// impl Serialize for [T] where T: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.collect_seq(self) } } macro_rules! seq_impl { ( $(#[$attr:meta])* $ty:ident ) => { $(#[$attr])* impl Serialize for $ty where T: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.collect_seq(self) } } } } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BinaryHeap } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeSet } seq_impl! { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] HashSet } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] LinkedList } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] Vec } seq_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] VecDeque } //////////////////////////////////////////////////////////////////////////////// impl Serialize for Range where Idx: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use super::SerializeStruct; let mut state = tri!(serializer.serialize_struct("Range", 2)); tri!(state.serialize_field("start", &self.start)); tri!(state.serialize_field("end", &self.end)); state.end() } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for RangeFrom where Idx: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use super::SerializeStruct; let mut state = tri!(serializer.serialize_struct("RangeFrom", 1)); tri!(state.serialize_field("start", &self.start)); state.end() } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for RangeInclusive where Idx: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use super::SerializeStruct; let mut state = tri!(serializer.serialize_struct("RangeInclusive", 2)); tri!(state.serialize_field("start", &self.start())); tri!(state.serialize_field("end", &self.end())); state.end() } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for RangeTo where Idx: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use super::SerializeStruct; let mut state = tri!(serializer.serialize_struct("RangeTo", 1)); tri!(state.serialize_field("end", &self.end)); state.end() } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for Bound where T: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match *self { Bound::Unbounded => serializer.serialize_unit_variant("Bound", 0, "Unbounded"), Bound::Included(ref value) => { serializer.serialize_newtype_variant("Bound", 1, "Included", value) } Bound::Excluded(ref value) => { serializer.serialize_newtype_variant("Bound", 2, "Excluded", value) } } } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for () { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_unit() } } #[cfg(feature = "unstable")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))] impl Serialize for ! { fn serialize(&self, _serializer: S) -> Result where S: Serializer, { *self } } //////////////////////////////////////////////////////////////////////////////// macro_rules! tuple_impls { ($($len:expr => ($($n:tt $name:ident)+))+) => { $( #[cfg_attr(docsrs, doc(hidden))] impl<$($name),+> Serialize for ($($name,)+) where $($name: Serialize,)+ { tuple_impl_body!($len => ($($n)+)); } )+ }; } macro_rules! tuple_impl_body { ($len:expr => ($($n:tt)+)) => { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut tuple = tri!(serializer.serialize_tuple($len)); $( tri!(tuple.serialize_element(&self.$n)); )+ tuple.end() } }; } #[cfg_attr(docsrs, doc(fake_variadic))] #[cfg_attr( docsrs, doc = "This trait is implemented for tuples up to 16 items long." )] impl Serialize for (T,) where T: Serialize, { tuple_impl_body!(1 => (0)); } tuple_impls! { 2 => (0 T0 1 T1) 3 => (0 T0 1 T1 2 T2) 4 => (0 T0 1 T1 2 T2 3 T3) 5 => (0 T0 1 T1 2 T2 3 T3 4 T4) 6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5) 7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6) 8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7) 9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8) 10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9) 11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10) 12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11) 13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12) 14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13) 15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14) 16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15) } //////////////////////////////////////////////////////////////////////////////// macro_rules! map_impl { ( $(#[$attr:meta])* $ty:ident ) => { $(#[$attr])* impl Serialize for $ty where K: Serialize, V: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.collect_map(self) } } } } map_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] BTreeMap } map_impl! { #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] HashMap } //////////////////////////////////////////////////////////////////////////////// macro_rules! deref_impl { ( $(#[$attr:meta])* <$($desc:tt)+ ) => { $(#[$attr])* impl <$($desc)+ { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { (**self).serialize(serializer) } } }; } deref_impl! { <'a, T> Serialize for &'a T where T: ?Sized + Serialize } deref_impl! { <'a, T> Serialize for &'a mut T where T: ?Sized + Serialize } deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] Serialize for Box where T: ?Sized + Serialize } deref_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// /// Serializing a data structure containing `Rc` will serialize a copy of /// the contents of the `Rc` each time the `Rc` is referenced within the /// data structure. Serialization will not attempt to deduplicate these /// repeated data. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Serialize for Rc where T: ?Sized + Serialize } deref_impl! { /// This impl requires the [`"rc"`] Cargo feature of Serde. /// /// Serializing a data structure containing `Arc` will serialize a copy of /// the contents of the `Arc` each time the `Arc` is referenced within the /// data structure. Serialization will not attempt to deduplicate these /// repeated data. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr(docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))))] Serialize for Arc where T: ?Sized + Serialize } deref_impl! { #[cfg(any(feature = "std", feature = "alloc"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))] <'a, T> Serialize for Cow<'a, T> where T: ?Sized + Serialize + ToOwned } //////////////////////////////////////////////////////////////////////////////// /// This impl requires the [`"rc"`] Cargo feature of Serde. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr( docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] impl Serialize for RcWeak where T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.upgrade().serialize(serializer) } } /// This impl requires the [`"rc"`] Cargo feature of Serde. /// /// [`"rc"`]: https://serde.rs/feature-flags.html#-features-rc #[cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))] #[cfg_attr( docsrs, doc(cfg(all(feature = "rc", any(feature = "std", feature = "alloc")))) )] impl Serialize for ArcWeak where T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.upgrade().serialize(serializer) } } //////////////////////////////////////////////////////////////////////////////// macro_rules! nonzero_integers { ($($T:ident,)+) => { $( impl Serialize for num::$T { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.get().serialize(serializer) } } )+ } } nonzero_integers! { NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize, } impl Serialize for Cell where T: Serialize + Copy, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.get().serialize(serializer) } } impl Serialize for RefCell where T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match self.try_borrow() { Ok(value) => value.serialize(serializer), Err(_) => Err(S::Error::custom("already mutably borrowed")), } } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for Mutex where T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match self.lock() { Ok(locked) => locked.serialize(serializer), Err(_) => Err(S::Error::custom("lock poison error while serializing")), } } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for RwLock where T: ?Sized + Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match self.read() { Ok(locked) => locked.serialize(serializer), Err(_) => Err(S::Error::custom("lock poison error while serializing")), } } } //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "result")] #[cfg_attr(docsrs, doc(cfg(feature = "result")))] impl Serialize for Result where T: Serialize, E: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match *self { Result::Ok(ref value) => serializer.serialize_newtype_variant("Result", 0, "Ok", value), Result::Err(ref value) => { serializer.serialize_newtype_variant("Result", 1, "Err", value) } } } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for Duration { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use super::SerializeStruct; let mut state = tri!(serializer.serialize_struct("Duration", 2)); tri!(state.serialize_field("secs", &self.as_secs())); tri!(state.serialize_field("nanos", &self.subsec_nanos())); state.end() } } //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for SystemTime { fn serialize(&self, serializer: S) -> Result where S: Serializer, { use super::SerializeStruct; let duration_since_epoch = match self.duration_since(UNIX_EPOCH) { Ok(duration_since_epoch) => duration_since_epoch, Err(_) => return Err(S::Error::custom("SystemTime must be later than UNIX_EPOCH")), }; let mut state = tri!(serializer.serialize_struct("SystemTime", 2)); tri!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs())); tri!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos())); state.end() } } //////////////////////////////////////////////////////////////////////////////// /// Serialize a value that implements `Display` as a string, when that string is /// statically known to never have more than a constant `MAX_LEN` bytes. /// /// Panics if the `Display` impl tries to write more than `MAX_LEN` bytes. #[cfg(any(feature = "std", not(no_core_net)))] macro_rules! serialize_display_bounded_length { ($value:expr, $max:expr, $serializer:expr) => {{ let mut buffer = [0u8; $max]; let mut writer = crate::format::Buf::new(&mut buffer); write!(&mut writer, "{}", $value).unwrap(); $serializer.serialize_str(writer.as_str()) }}; } #[cfg(any(feature = "std", not(no_core_net)))] impl Serialize for net::IpAddr { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if serializer.is_human_readable() { match *self { net::IpAddr::V4(ref a) => a.serialize(serializer), net::IpAddr::V6(ref a) => a.serialize(serializer), } } else { match *self { net::IpAddr::V4(ref a) => { serializer.serialize_newtype_variant("IpAddr", 0, "V4", a) } net::IpAddr::V6(ref a) => { serializer.serialize_newtype_variant("IpAddr", 1, "V6", a) } } } } } #[cfg(any(feature = "std", not(no_core_net)))] const DEC_DIGITS_LUT: &[u8] = b"\ 0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ 4041424344454647484950515253545556575859\ 6061626364656667686970717273747576777879\ 8081828384858687888990919293949596979899"; #[cfg(any(feature = "std", not(no_core_net)))] #[inline] fn format_u8(mut n: u8, out: &mut [u8]) -> usize { if n >= 100 { let d1 = ((n % 100) << 1) as usize; n /= 100; out[0] = b'0' + n; out[1] = DEC_DIGITS_LUT[d1]; out[2] = DEC_DIGITS_LUT[d1 + 1]; 3 } else if n >= 10 { let d1 = (n << 1) as usize; out[0] = DEC_DIGITS_LUT[d1]; out[1] = DEC_DIGITS_LUT[d1 + 1]; 2 } else { out[0] = b'0' + n; 1 } } #[cfg(any(feature = "std", not(no_core_net)))] #[test] fn test_format_u8() { let mut i = 0u8; loop { let mut buf = [0u8; 3]; let written = format_u8(i, &mut buf); assert_eq!(i.to_string().as_bytes(), &buf[..written]); match i.checked_add(1) { Some(next) => i = next, None => break, } } } #[cfg(any(feature = "std", not(no_core_net)))] impl Serialize for net::Ipv4Addr { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if serializer.is_human_readable() { const MAX_LEN: usize = 15; debug_assert_eq!(MAX_LEN, "101.102.103.104".len()); let mut buf = [b'.'; MAX_LEN]; let mut written = format_u8(self.octets()[0], &mut buf); for oct in &self.octets()[1..] { // Skip over delimiters that we initialized buf with written += format_u8(*oct, &mut buf[written + 1..]) + 1; } // Safety: We've only written ASCII bytes to the buffer, so it is valid UTF-8 let buf = unsafe { str::from_utf8_unchecked(&buf[..written]) }; serializer.serialize_str(buf) } else { self.octets().serialize(serializer) } } } #[cfg(any(feature = "std", not(no_core_net)))] impl Serialize for net::Ipv6Addr { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if serializer.is_human_readable() { const MAX_LEN: usize = 39; debug_assert_eq!(MAX_LEN, "1001:1002:1003:1004:1005:1006:1007:1008".len()); serialize_display_bounded_length!(self, MAX_LEN, serializer) } else { self.octets().serialize(serializer) } } } #[cfg(any(feature = "std", not(no_core_net)))] impl Serialize for net::SocketAddr { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if serializer.is_human_readable() { match *self { net::SocketAddr::V4(ref addr) => addr.serialize(serializer), net::SocketAddr::V6(ref addr) => addr.serialize(serializer), } } else { match *self { net::SocketAddr::V4(ref addr) => { serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr) } net::SocketAddr::V6(ref addr) => { serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr) } } } } } #[cfg(any(feature = "std", not(no_core_net)))] impl Serialize for net::SocketAddrV4 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if serializer.is_human_readable() { const MAX_LEN: usize = 21; debug_assert_eq!(MAX_LEN, "101.102.103.104:65000".len()); serialize_display_bounded_length!(self, MAX_LEN, serializer) } else { (self.ip(), self.port()).serialize(serializer) } } } #[cfg(any(feature = "std", not(no_core_net)))] impl Serialize for net::SocketAddrV6 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { if serializer.is_human_readable() { const MAX_LEN: usize = 58; debug_assert_eq!( MAX_LEN, "[1001:1002:1003:1004:1005:1006:1007:1008%4294967295]:65000".len() ); serialize_display_bounded_length!(self, MAX_LEN, serializer) } else { (self.ip(), self.port()).serialize(serializer) } } } //////////////////////////////////////////////////////////////////////////////// #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for Path { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match self.to_str() { Some(s) => s.serialize(serializer), None => Err(Error::custom("path contains invalid UTF-8 characters")), } } } #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Serialize for PathBuf { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.as_path().serialize(serializer) } } #[cfg(all(feature = "std", any(unix, windows)))] #[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))] impl Serialize for OsStr { #[cfg(unix)] fn serialize(&self, serializer: S) -> Result where S: Serializer, { use std::os::unix::ffi::OsStrExt; serializer.serialize_newtype_variant("OsString", 0, "Unix", self.as_bytes()) } #[cfg(windows)] fn serialize(&self, serializer: S) -> Result where S: Serializer, { use std::os::windows::ffi::OsStrExt; let val = self.encode_wide().collect::>(); serializer.serialize_newtype_variant("OsString", 1, "Windows", &val) } } #[cfg(all(feature = "std", any(unix, windows)))] #[cfg_attr(docsrs, doc(cfg(all(feature = "std", any(unix, windows)))))] impl Serialize for OsString { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.as_os_str().serialize(serializer) } } //////////////////////////////////////////////////////////////////////////////// impl Serialize for Wrapping where T: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.0.serialize(serializer) } } #[cfg(not(no_core_num_saturating))] impl Serialize for Saturating where T: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.0.serialize(serializer) } } impl Serialize for Reverse where T: Serialize, { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.0.serialize(serializer) } } //////////////////////////////////////////////////////////////////////////////// #[cfg(all(feature = "std", not(no_std_atomic)))] macro_rules! atomic_impl { ($($ty:ident $size:expr)*) => { $( #[cfg(any(no_target_has_atomic, target_has_atomic = $size))] #[cfg_attr(docsrs, doc(cfg(all(feature = "std", target_has_atomic = $size))))] impl Serialize for $ty { fn serialize(&self, serializer: S) -> Result where S: Serializer, { // Matches the atomic ordering used in libcore for the Debug impl self.load(Ordering::Relaxed).serialize(serializer) } } )* } } #[cfg(all(feature = "std", not(no_std_atomic)))] atomic_impl! { AtomicBool "8" AtomicI8 "8" AtomicI16 "16" AtomicI32 "32" AtomicIsize "ptr" AtomicU8 "8" AtomicU16 "16" AtomicU32 "32" AtomicUsize "ptr" } #[cfg(all(feature = "std", not(no_std_atomic64)))] atomic_impl! { AtomicI64 "64" AtomicU64 "64" } ================================================ FILE: serde_core/src/ser/impossible.rs ================================================ //! This module contains `Impossible` serializer and its implementations. use crate::lib::*; use crate::ser::{ self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, }; /// Helper type for implementing a `Serializer` that does not support /// serializing one of the compound types. /// /// This type cannot be instantiated, but implements every one of the traits /// corresponding to the [`Serializer`] compound types: [`SerializeSeq`], /// [`SerializeTuple`], [`SerializeTupleStruct`], [`SerializeTupleVariant`], /// [`SerializeMap`], [`SerializeStruct`], and [`SerializeStructVariant`]. /// /// ```edition2021 /// # use serde::ser::{Serializer, Impossible}; /// # use serde_core::__private::doc::Error; /// # /// # struct MySerializer; /// # /// impl Serializer for MySerializer { /// type Ok = (); /// type Error = Error; /// /// type SerializeSeq = Impossible<(), Error>; /// /* other associated types */ /// /// /// This data format does not support serializing sequences. /// fn serialize_seq(self, /// len: Option) /// -> Result { /// // Given Impossible cannot be instantiated, the only /// // thing we can do here is to return an error. /// # stringify! { /// Err(...) /// # }; /// # unimplemented!() /// } /// /// /* other Serializer methods */ /// # serde_core::__serialize_unimplemented! { /// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes none some /// # unit unit_struct unit_variant newtype_struct newtype_variant /// # tuple tuple_struct tuple_variant map struct struct_variant /// # } /// } /// ``` /// /// [`Serializer`]: crate::Serializer /// [`SerializeSeq`]: crate::ser::SerializeSeq /// [`SerializeTuple`]: crate::ser::SerializeTuple /// [`SerializeTupleStruct`]: crate::ser::SerializeTupleStruct /// [`SerializeTupleVariant`]: crate::ser::SerializeTupleVariant /// [`SerializeMap`]: crate::ser::SerializeMap /// [`SerializeStruct`]: crate::ser::SerializeStruct /// [`SerializeStructVariant`]: crate::ser::SerializeStructVariant pub struct Impossible { void: Void, ok: PhantomData, error: PhantomData, } enum Void {} impl SerializeSeq for Impossible where Error: ser::Error, { type Ok = Ok; type Error = Error; fn serialize_element(&mut self, value: &T) -> Result<(), Error> where T: ?Sized + Serialize, { let _ = value; match self.void {} } fn end(self) -> Result { match self.void {} } } impl SerializeTuple for Impossible where Error: ser::Error, { type Ok = Ok; type Error = Error; fn serialize_element(&mut self, value: &T) -> Result<(), Error> where T: ?Sized + Serialize, { let _ = value; match self.void {} } fn end(self) -> Result { match self.void {} } } impl SerializeTupleStruct for Impossible where Error: ser::Error, { type Ok = Ok; type Error = Error; fn serialize_field(&mut self, value: &T) -> Result<(), Error> where T: ?Sized + Serialize, { let _ = value; match self.void {} } fn end(self) -> Result { match self.void {} } } impl SerializeTupleVariant for Impossible where Error: ser::Error, { type Ok = Ok; type Error = Error; fn serialize_field(&mut self, value: &T) -> Result<(), Error> where T: ?Sized + Serialize, { let _ = value; match self.void {} } fn end(self) -> Result { match self.void {} } } impl SerializeMap for Impossible where Error: ser::Error, { type Ok = Ok; type Error = Error; fn serialize_key(&mut self, key: &T) -> Result<(), Error> where T: ?Sized + Serialize, { let _ = key; match self.void {} } fn serialize_value(&mut self, value: &T) -> Result<(), Error> where T: ?Sized + Serialize, { let _ = value; match self.void {} } fn end(self) -> Result { match self.void {} } } impl SerializeStruct for Impossible where Error: ser::Error, { type Ok = Ok; type Error = Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> where T: ?Sized + Serialize, { let _ = key; let _ = value; match self.void {} } fn end(self) -> Result { match self.void {} } } impl SerializeStructVariant for Impossible where Error: ser::Error, { type Ok = Ok; type Error = Error; fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Error> where T: ?Sized + Serialize, { let _ = key; let _ = value; match self.void {} } fn end(self) -> Result { match self.void {} } } ================================================ FILE: serde_core/src/ser/mod.rs ================================================ //! Generic data structure serialization framework. //! //! The two most important traits in this module are [`Serialize`] and //! [`Serializer`]. //! //! - **A type that implements `Serialize` is a data structure** that can be //! serialized to any data format supported by Serde, and conversely //! - **A type that implements `Serializer` is a data format** that can //! serialize any data structure supported by Serde. //! //! # The Serialize trait //! //! Serde provides [`Serialize`] implementations for many Rust primitive and //! standard library types. The complete list is below. All of these can be //! serialized using Serde out of the box. //! //! Additionally, Serde provides a procedural macro called [`serde_derive`] to //! automatically generate [`Serialize`] implementations for structs and enums //! in your program. See the [derive section of the manual] for how to use this. //! //! In rare cases it may be necessary to implement [`Serialize`] manually for //! some type in your program. See the [Implementing `Serialize`] section of the //! manual for more about this. //! //! Third-party crates may provide [`Serialize`] implementations for types that //! they expose. For example the [`linked-hash-map`] crate provides a //! [`LinkedHashMap`] type that is serializable by Serde because the crate //! provides an implementation of [`Serialize`] for it. //! //! # The Serializer trait //! //! [`Serializer`] implementations are provided by third-party crates, for //! example [`serde_json`], [`serde_yaml`] and [`postcard`]. //! //! A partial list of well-maintained formats is given on the [Serde //! website][data formats]. //! //! # Implementations of Serialize provided by Serde //! //! - **Primitive types**: //! - bool //! - i8, i16, i32, i64, i128, isize //! - u8, u16, u32, u64, u128, usize //! - f32, f64 //! - char //! - str //! - &T and &mut T //! - **Compound types**: //! - \[T\] //! - \[T; 0\] through \[T; 32\] //! - tuples up to size 16 //! - **Common standard library types**: //! - String //! - Option\ //! - Result\ //! - PhantomData\ //! - **Wrapper types**: //! - Box\ //! - Cow\<'a, T\> //! - Cell\ //! - RefCell\ //! - Mutex\ //! - RwLock\ //! - Rc\ *(if* features = \["rc"\] *is enabled)* //! - Arc\ *(if* features = \["rc"\] *is enabled)* //! - **Collection types**: //! - BTreeMap\ //! - BTreeSet\ //! - BinaryHeap\ //! - HashMap\ //! - HashSet\ //! - LinkedList\ //! - VecDeque\ //! - Vec\ //! - **FFI types**: //! - CStr //! - CString //! - OsStr //! - OsString //! - **Miscellaneous standard library types**: //! - Duration //! - SystemTime //! - Path //! - PathBuf //! - Range\ //! - RangeInclusive\ //! - Bound\ //! - num::NonZero* //! - `!` *(unstable)* //! - **Net types**: //! - IpAddr //! - Ipv4Addr //! - Ipv6Addr //! - SocketAddr //! - SocketAddrV4 //! - SocketAddrV6 //! //! [Implementing `Serialize`]: https://serde.rs/impl-serialize.html //! [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html //! [`Serialize`]: crate::Serialize //! [`Serializer`]: crate::Serializer //! [`postcard`]: https://github.com/jamesmunns/postcard //! [`linked-hash-map`]: https://crates.io/crates/linked-hash-map //! [`serde_derive`]: https://crates.io/crates/serde_derive //! [`serde_json`]: https://github.com/serde-rs/json //! [`serde_yaml`]: https://github.com/dtolnay/serde-yaml //! [derive section of the manual]: https://serde.rs/derive.html //! [data formats]: https://serde.rs/#data-formats use crate::lib::*; mod fmt; mod impls; mod impossible; pub use self::impossible::Impossible; #[cfg(all(not(feature = "std"), no_core_error))] #[doc(no_inline)] pub use crate::std_error::Error as StdError; #[cfg(not(any(feature = "std", no_core_error)))] #[doc(no_inline)] pub use core::error::Error as StdError; #[cfg(feature = "std")] #[doc(no_inline)] pub use std::error::Error as StdError; //////////////////////////////////////////////////////////////////////////////// macro_rules! declare_error_trait { (Error: Sized $(+ $($supertrait:ident)::+)*) => { /// Trait used by `Serialize` implementations to generically construct /// errors belonging to the `Serializer` against which they are /// currently running. /// /// # Example implementation /// /// The [example data format] presented on the website shows an error /// type appropriate for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::ser::Error` is not satisfied", ) )] pub trait Error: Sized $(+ $($supertrait)::+)* { /// Used when a [`Serialize`] implementation encounters any error /// while serializing a type. /// /// The message should not be capitalized and should not end with a /// period. /// /// For example, a filesystem [`Path`] may refuse to serialize /// itself if it contains invalid UTF-8 data. /// /// ```edition2021 /// # struct Path; /// # /// # impl Path { /// # fn to_str(&self) -> Option<&str> { /// # unimplemented!() /// # } /// # } /// # /// use serde::ser::{self, Serialize, Serializer}; /// /// impl Serialize for Path { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match self.to_str() { /// Some(s) => serializer.serialize_str(s), /// None => Err(ser::Error::custom("path contains invalid UTF-8 characters")), /// } /// } /// } /// ``` /// /// [`Path`]: std::path::Path /// [`Serialize`]: crate::Serialize fn custom(msg: T) -> Self where T: Display; } } } #[cfg(feature = "std")] declare_error_trait!(Error: Sized + StdError); #[cfg(not(feature = "std"))] declare_error_trait!(Error: Sized + Debug + Display); //////////////////////////////////////////////////////////////////////////////// /// A **data structure** that can be serialized into any data format supported /// by Serde. /// /// Serde provides `Serialize` implementations for many Rust primitive and /// standard library types. The complete list is [here][crate::ser]. All of /// these can be serialized using Serde out of the box. /// /// Additionally, Serde provides a procedural macro called [`serde_derive`] to /// automatically generate `Serialize` implementations for structs and enums in /// your program. See the [derive section of the manual] for how to use this. /// /// In rare cases it may be necessary to implement `Serialize` manually for some /// type in your program. See the [Implementing `Serialize`] section of the /// manual for more about this. /// /// Third-party crates may provide `Serialize` implementations for types that /// they expose. For example the [`linked-hash-map`] crate provides a /// [`LinkedHashMap`] type that is serializable by Serde because the crate /// provides an implementation of `Serialize` for it. /// /// [Implementing `Serialize`]: https://serde.rs/impl-serialize.html /// [`LinkedHashMap`]: https://docs.rs/linked-hash-map/*/linked_hash_map/struct.LinkedHashMap.html /// [`linked-hash-map`]: https://crates.io/crates/linked-hash-map /// [`serde_derive`]: https://crates.io/crates/serde_derive /// [derive section of the manual]: https://serde.rs/derive.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( // Prevents `serde_core::ser::Serialize` appearing in the error message // in projects with no direct dependency on serde_core. message = "the trait bound `{Self}: serde::Serialize` is not satisfied", note = "for local types consider adding `#[derive(serde::Serialize)]` to your `{Self}` type", note = "for types from other crates check whether the crate offers a `serde` feature flag", ) )] pub trait Serialize { /// Serialize this value into the given Serde serializer. /// /// See the [Implementing `Serialize`] section of the manual for more /// information about how to implement this method. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Person { /// name: String, /// age: u8, /// phones: Vec, /// } /// /// // This is what #[derive(Serialize)] would generate. /// impl Serialize for Person { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut s = serializer.serialize_struct("Person", 3)?; /// s.serialize_field("name", &self.name)?; /// s.serialize_field("age", &self.age)?; /// s.serialize_field("phones", &self.phones)?; /// s.end() /// } /// } /// ``` /// /// [Implementing `Serialize`]: https://serde.rs/impl-serialize.html fn serialize(&self, serializer: S) -> Result where S: Serializer; } //////////////////////////////////////////////////////////////////////////////// /// A **data format** that can serialize any data structure supported by Serde. /// /// The role of this trait is to define the serialization half of the [Serde /// data model], which is a way to categorize every Rust data structure into one /// of 29 possible types. Each method of the `Serializer` trait corresponds to /// one of the types of the data model. /// /// Implementations of `Serialize` map themselves into this data model by /// invoking exactly one of the `Serializer` methods. /// /// The types that make up the Serde data model are: /// /// - **14 primitive types** /// - bool /// - i8, i16, i32, i64, i128 /// - u8, u16, u32, u64, u128 /// - f32, f64 /// - char /// - **string** /// - UTF-8 bytes with a length and no null terminator. /// - When serializing, all strings are handled equally. When deserializing, /// there are three flavors of strings: transient, owned, and borrowed. /// - **byte array** - \[u8\] /// - Similar to strings, during deserialization byte arrays can be /// transient, owned, or borrowed. /// - **option** /// - Either none or some value. /// - **unit** /// - The type of `()` in Rust. It represents an anonymous value containing /// no data. /// - **unit_struct** /// - For example `struct Unit` or `PhantomData`. It represents a named /// value containing no data. /// - **unit_variant** /// - For example the `E::A` and `E::B` in `enum E { A, B }`. /// - **newtype_struct** /// - For example `struct Millimeters(u8)`. /// - **newtype_variant** /// - For example the `E::N` in `enum E { N(u8) }`. /// - **seq** /// - A variably sized heterogeneous sequence of values, for example /// `Vec` or `HashSet`. When serializing, the length may or may not /// be known before iterating through all the data. When deserializing, /// the length is determined by looking at the serialized data. /// - **tuple** /// - A statically sized heterogeneous sequence of values for which the /// length will be known at deserialization time without looking at the /// serialized data, for example `(u8,)` or `(String, u64, Vec)` or /// `[u64; 10]`. /// - **tuple_struct** /// - A named tuple, for example `struct Rgb(u8, u8, u8)`. /// - **tuple_variant** /// - For example the `E::T` in `enum E { T(u8, u8) }`. /// - **map** /// - A heterogeneous key-value pairing, for example `BTreeMap`. /// - **struct** /// - A heterogeneous key-value pairing in which the keys are strings and /// will be known at deserialization time without looking at the /// serialized data, for example `struct S { r: u8, g: u8, b: u8 }`. /// - **struct_variant** /// - For example the `E::S` in `enum E { S { r: u8, g: u8, b: u8 } }`. /// /// Many Serde serializers produce text or binary data as output, for example /// JSON or Postcard. This is not a requirement of the `Serializer` trait, and /// there are serializers that do not produce text or binary output. One example /// is the `serde_json::value::Serializer` (distinct from the main `serde_json` /// serializer) that produces a `serde_json::Value` data structure in memory as /// output. /// /// [Serde data model]: https://serde.rs/data-model.html /// /// # Example implementation /// /// The [example data format] presented on the website contains example code for /// a basic JSON `Serializer`. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::Serializer` is not satisfied", ) )] pub trait Serializer: Sized { /// The output type produced by this `Serializer` during successful /// serialization. Most serializers that produce text or binary output /// should set `Ok = ()` and serialize into an [`io::Write`] or buffer /// contained within the `Serializer` instance. Serializers that build /// in-memory data structures may be simplified by using `Ok` to propagate /// the data structure around. /// /// [`io::Write`]: std::io::Write type Ok; /// The error type when some error occurs during serialization. type Error: Error; /// Type returned from [`serialize_seq`] for serializing the content of the /// sequence. /// /// [`serialize_seq`]: #tymethod.serialize_seq type SerializeSeq: SerializeSeq; /// Type returned from [`serialize_tuple`] for serializing the content of /// the tuple. /// /// [`serialize_tuple`]: #tymethod.serialize_tuple type SerializeTuple: SerializeTuple; /// Type returned from [`serialize_tuple_struct`] for serializing the /// content of the tuple struct. /// /// [`serialize_tuple_struct`]: #tymethod.serialize_tuple_struct type SerializeTupleStruct: SerializeTupleStruct; /// Type returned from [`serialize_tuple_variant`] for serializing the /// content of the tuple variant. /// /// [`serialize_tuple_variant`]: #tymethod.serialize_tuple_variant type SerializeTupleVariant: SerializeTupleVariant; /// Type returned from [`serialize_map`] for serializing the content of the /// map. /// /// [`serialize_map`]: #tymethod.serialize_map type SerializeMap: SerializeMap; /// Type returned from [`serialize_struct`] for serializing the content of /// the struct. /// /// [`serialize_struct`]: #tymethod.serialize_struct type SerializeStruct: SerializeStruct; /// Type returned from [`serialize_struct_variant`] for serializing the /// content of the struct variant. /// /// [`serialize_struct_variant`]: #tymethod.serialize_struct_variant type SerializeStructVariant: SerializeStructVariant; /// Serialize a `bool` value. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for bool { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_bool(*self) /// } /// } /// ``` fn serialize_bool(self, v: bool) -> Result; /// Serialize an `i8` value. /// /// If the format does not differentiate between `i8` and `i64`, a /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for i8 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_i8(*self) /// } /// } /// ``` fn serialize_i8(self, v: i8) -> Result; /// Serialize an `i16` value. /// /// If the format does not differentiate between `i16` and `i64`, a /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for i16 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_i16(*self) /// } /// } /// ``` fn serialize_i16(self, v: i16) -> Result; /// Serialize an `i32` value. /// /// If the format does not differentiate between `i32` and `i64`, a /// reasonable implementation would be to cast the value to `i64` and /// forward to `serialize_i64`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for i32 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_i32(*self) /// } /// } /// ``` fn serialize_i32(self, v: i32) -> Result; /// Serialize an `i64` value. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for i64 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_i64(*self) /// } /// } /// ``` fn serialize_i64(self, v: i64) -> Result; /// Serialize an `i128` value. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for i128 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_i128(*self) /// } /// } /// ``` /// /// The default behavior unconditionally returns an error. fn serialize_i128(self, v: i128) -> Result { let _ = v; Err(Error::custom("i128 is not supported")) } /// Serialize a `u8` value. /// /// If the format does not differentiate between `u8` and `u64`, a /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for u8 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_u8(*self) /// } /// } /// ``` fn serialize_u8(self, v: u8) -> Result; /// Serialize a `u16` value. /// /// If the format does not differentiate between `u16` and `u64`, a /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for u16 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_u16(*self) /// } /// } /// ``` fn serialize_u16(self, v: u16) -> Result; /// Serialize a `u32` value. /// /// If the format does not differentiate between `u32` and `u64`, a /// reasonable implementation would be to cast the value to `u64` and /// forward to `serialize_u64`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for u32 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_u32(*self) /// } /// } /// ``` fn serialize_u32(self, v: u32) -> Result; /// Serialize a `u64` value. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for u64 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_u64(*self) /// } /// } /// ``` fn serialize_u64(self, v: u64) -> Result; /// Serialize a `u128` value. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for u128 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_u128(*self) /// } /// } /// ``` /// /// The default behavior unconditionally returns an error. fn serialize_u128(self, v: u128) -> Result { let _ = v; Err(Error::custom("u128 is not supported")) } /// Serialize an `f32` value. /// /// If the format does not differentiate between `f32` and `f64`, a /// reasonable implementation would be to cast the value to `f64` and /// forward to `serialize_f64`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for f32 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_f32(*self) /// } /// } /// ``` fn serialize_f32(self, v: f32) -> Result; /// Serialize an `f64` value. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for f64 { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_f64(*self) /// } /// } /// ``` fn serialize_f64(self, v: f64) -> Result; /// Serialize a character. /// /// If the format does not support characters, it is reasonable to serialize /// it as a single element `str` or a `u32`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for char { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_char(*self) /// } /// } /// ``` fn serialize_char(self, v: char) -> Result; /// Serialize a `&str`. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for str { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_str(self) /// } /// } /// ``` fn serialize_str(self, v: &str) -> Result; /// Serialize a chunk of raw byte data. /// /// Enables serializers to serialize byte slices more compactly or more /// efficiently than other types of slices. If no efficient implementation /// is available, a reasonable implementation would be to forward to /// `serialize_seq`. If forwarded, the implementation looks usually just /// like this: /// /// ```edition2021 /// # use serde::ser::{Serializer, SerializeSeq}; /// # use serde_core::__private::doc::Error; /// # /// # struct MySerializer; /// # /// # impl Serializer for MySerializer { /// # type Ok = (); /// # type Error = Error; /// # /// fn serialize_bytes(self, v: &[u8]) -> Result { /// let mut seq = self.serialize_seq(Some(v.len()))?; /// for b in v { /// seq.serialize_element(b)?; /// } /// seq.end() /// } /// # /// # serde_core::__serialize_unimplemented! { /// # bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str none some /// # unit unit_struct unit_variant newtype_struct newtype_variant /// # seq tuple tuple_struct tuple_variant map struct struct_variant /// # } /// # } /// ``` fn serialize_bytes(self, v: &[u8]) -> Result; /// Serialize a [`None`] value. /// /// ```edition2021 /// # use serde::{Serialize, Serializer}; /// # /// # enum Option { /// # Some(T), /// # None, /// # } /// # /// # use self::Option::{Some, None}; /// # /// impl Serialize for Option /// where /// T: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match *self { /// Some(ref value) => serializer.serialize_some(value), /// None => serializer.serialize_none(), /// } /// } /// } /// # /// # fn main() {} /// ``` /// /// [`None`]: core::option::Option::None fn serialize_none(self) -> Result; /// Serialize a [`Some(T)`] value. /// /// ```edition2021 /// # use serde::{Serialize, Serializer}; /// # /// # enum Option { /// # Some(T), /// # None, /// # } /// # /// # use self::Option::{Some, None}; /// # /// impl Serialize for Option /// where /// T: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match *self { /// Some(ref value) => serializer.serialize_some(value), /// None => serializer.serialize_none(), /// } /// } /// } /// # /// # fn main() {} /// ``` /// /// [`Some(T)`]: core::option::Option::Some fn serialize_some(self, value: &T) -> Result where T: ?Sized + Serialize; /// Serialize a `()` value. /// /// ```edition2021 /// # use serde::Serializer; /// # /// # serde_core::__private_serialize!(); /// # /// impl Serialize for () { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_unit() /// } /// } /// ``` fn serialize_unit(self) -> Result; /// Serialize a unit struct like `struct Unit` or `PhantomData`. /// /// A reasonable implementation would be to forward to `serialize_unit`. /// /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// struct Nothing; /// /// impl Serialize for Nothing { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_unit_struct("Nothing") /// } /// } /// ``` fn serialize_unit_struct(self, name: &'static str) -> Result; /// Serialize a unit variant like `E::A` in `enum E { A, B }`. /// /// The `name` is the name of the enum, the `variant_index` is the index of /// this variant within the enum, and the `variant` is the name of the /// variant. /// /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// enum E { /// A, /// B, /// } /// /// impl Serialize for E { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match *self { /// E::A => serializer.serialize_unit_variant("E", 0, "A"), /// E::B => serializer.serialize_unit_variant("E", 1, "B"), /// } /// } /// } /// ``` fn serialize_unit_variant( self, name: &'static str, variant_index: u32, variant: &'static str, ) -> Result; /// Serialize a newtype struct like `struct Millimeters(u8)`. /// /// Serializers are encouraged to treat newtype structs as insignificant /// wrappers around the data they contain. A reasonable implementation would /// be to forward to `value.serialize(self)`. /// /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// struct Millimeters(u8); /// /// impl Serialize for Millimeters { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.serialize_newtype_struct("Millimeters", &self.0) /// } /// } /// ``` fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize; /// Serialize a newtype variant like `E::N` in `enum E { N(u8) }`. /// /// The `name` is the name of the enum, the `variant_index` is the index of /// this variant within the enum, and the `variant` is the name of the /// variant. The `value` is the data contained within this newtype variant. /// /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// enum E { /// M(String), /// N(u8), /// } /// /// impl Serialize for E { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match *self { /// E::M(ref s) => serializer.serialize_newtype_variant("E", 0, "M", s), /// E::N(n) => serializer.serialize_newtype_variant("E", 1, "N", &n), /// } /// } /// } /// ``` fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize; /// Begin to serialize a variably sized sequence. This call must be /// followed by zero or more calls to `serialize_element`, then a call to /// `end`. /// /// The argument is the number of elements in the sequence, which may or may /// not be computable before the sequence is iterated. Some serializers only /// support sequences whose length is known up front. /// /// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct Vec(PhantomData); /// # /// # impl Vec { /// # fn len(&self) -> usize { /// # unimplemented!() /// # } /// # } /// # /// # impl<'a, T> IntoIterator for &'a Vec { /// # type Item = &'a T; /// # type IntoIter = Box>; /// # /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # /// use serde::ser::{Serialize, SerializeSeq, Serializer}; /// /// impl Serialize for Vec /// where /// T: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut seq = serializer.serialize_seq(Some(self.len()))?; /// for element in self { /// seq.serialize_element(element)?; /// } /// seq.end() /// } /// } /// ``` fn serialize_seq(self, len: Option) -> Result; /// Begin to serialize a statically sized sequence whose length will be /// known at deserialization time without looking at the serialized data. /// This call must be followed by zero or more calls to `serialize_element`, /// then a call to `end`. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// # mod fool { /// # trait Serialize {} /// impl Serialize for (A, B, C) /// # {} /// # } /// # /// # struct Tuple3(A, B, C); /// # /// # impl Serialize for Tuple3 /// where /// A: Serialize, /// B: Serialize, /// C: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut tup = serializer.serialize_tuple(3)?; /// tup.serialize_element(&self.0)?; /// tup.serialize_element(&self.1)?; /// tup.serialize_element(&self.2)?; /// tup.end() /// } /// } /// ``` /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// const VRAM_SIZE: usize = 386; /// struct Vram([u16; VRAM_SIZE]); /// /// impl Serialize for Vram { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut seq = serializer.serialize_tuple(VRAM_SIZE)?; /// for element in &self.0[..] { /// seq.serialize_element(element)?; /// } /// seq.end() /// } /// } /// ``` fn serialize_tuple(self, len: usize) -> Result; /// Begin to serialize a tuple struct like `struct Rgb(u8, u8, u8)`. This /// call must be followed by zero or more calls to `serialize_field`, then a /// call to `end`. /// /// The `name` is the name of the tuple struct and the `len` is the number /// of data fields that will be serialized. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; /// /// struct Rgb(u8, u8, u8); /// /// impl Serialize for Rgb { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; /// ts.serialize_field(&self.0)?; /// ts.serialize_field(&self.1)?; /// ts.serialize_field(&self.2)?; /// ts.end() /// } /// } /// ``` fn serialize_tuple_struct( self, name: &'static str, len: usize, ) -> Result; /// Begin to serialize a tuple variant like `E::T` in `enum E { T(u8, u8) /// }`. This call must be followed by zero or more calls to /// `serialize_field`, then a call to `end`. /// /// The `name` is the name of the enum, the `variant_index` is the index of /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer}; /// /// enum E { /// T(u8, u8), /// U(String, u32, u32), /// } /// /// impl Serialize for E { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match *self { /// E::T(ref a, ref b) => { /// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?; /// tv.serialize_field(a)?; /// tv.serialize_field(b)?; /// tv.end() /// } /// E::U(ref a, ref b, ref c) => { /// let mut tv = serializer.serialize_tuple_variant("E", 1, "U", 3)?; /// tv.serialize_field(a)?; /// tv.serialize_field(b)?; /// tv.serialize_field(c)?; /// tv.end() /// } /// } /// } /// } /// ``` fn serialize_tuple_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result; /// Begin to serialize a map. This call must be followed by zero or more /// calls to `serialize_key` and `serialize_value`, then a call to `end`. /// /// The argument is the number of elements in the map, which may or may not /// be computable before the map is iterated. Some serializers only support /// maps whose length is known up front. /// /// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct HashMap(PhantomData, PhantomData); /// # /// # impl HashMap { /// # fn len(&self) -> usize { /// # unimplemented!() /// # } /// # } /// # /// # impl<'a, K, V> IntoIterator for &'a HashMap { /// # type Item = (&'a K, &'a V); /// # type IntoIter = Box>; /// # /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # /// use serde::ser::{Serialize, SerializeMap, Serializer}; /// /// impl Serialize for HashMap /// where /// K: Serialize, /// V: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut map = serializer.serialize_map(Some(self.len()))?; /// for (k, v) in self { /// map.serialize_entry(k, v)?; /// } /// map.end() /// } /// } /// ``` fn serialize_map(self, len: Option) -> Result; /// Begin to serialize a struct like `struct Rgb { r: u8, g: u8, b: u8 }`. /// This call must be followed by zero or more calls to `serialize_field`, /// then a call to `end`. /// /// The `name` is the name of the struct and the `len` is the number of /// data fields that will be serialized. `len` does not include fields /// which are skipped with [`SerializeStruct::skip_field`]. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Rgb { /// r: u8, /// g: u8, /// b: u8, /// } /// /// impl Serialize for Rgb { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut rgb = serializer.serialize_struct("Rgb", 3)?; /// rgb.serialize_field("r", &self.r)?; /// rgb.serialize_field("g", &self.g)?; /// rgb.serialize_field("b", &self.b)?; /// rgb.end() /// } /// } /// ``` fn serialize_struct( self, name: &'static str, len: usize, ) -> Result; /// Begin to serialize a struct variant like `E::S` in `enum E { S { r: u8, /// g: u8, b: u8 } }`. This call must be followed by zero or more calls to /// `serialize_field`, then a call to `end`. /// /// The `name` is the name of the enum, the `variant_index` is the index of /// this variant within the enum, the `variant` is the name of the variant, /// and the `len` is the number of data fields that will be serialized. /// `len` does not include fields which are skipped with /// [`SerializeStructVariant::skip_field`]. /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; /// /// enum E { /// S { r: u8, g: u8, b: u8 }, /// } /// /// impl Serialize for E { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match *self { /// E::S { /// ref r, /// ref g, /// ref b, /// } => { /// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; /// sv.serialize_field("r", r)?; /// sv.serialize_field("g", g)?; /// sv.serialize_field("b", b)?; /// sv.end() /// } /// } /// } /// } /// ``` fn serialize_struct_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result; /// Collect an iterator as a sequence. /// /// The default implementation serializes each item yielded by the iterator /// using [`serialize_seq`]. Implementors should not need to override this /// method. /// /// ```edition2021 /// use serde::{Serialize, Serializer}; /// /// struct SecretlyOneHigher { /// data: Vec, /// } /// /// impl Serialize for SecretlyOneHigher { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.collect_seq(self.data.iter().map(|x| x + 1)) /// } /// } /// ``` /// /// [`serialize_seq`]: #tymethod.serialize_seq fn collect_seq(self, iter: I) -> Result where I: IntoIterator, ::Item: Serialize, { let mut iter = iter.into_iter(); let mut serializer = tri!(self.serialize_seq(iterator_len_hint(&iter))); tri!(iter.try_for_each(|item| serializer.serialize_element(&item))); serializer.end() } /// Collect an iterator as a map. /// /// The default implementation serializes each pair yielded by the iterator /// using [`serialize_map`]. Implementors should not need to override this /// method. /// /// ```edition2021 /// use serde::{Serialize, Serializer}; /// use std::collections::BTreeSet; /// /// struct MapToUnit { /// keys: BTreeSet, /// } /// /// // Serializes as a map in which the values are all unit. /// impl Serialize for MapToUnit { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.collect_map(self.keys.iter().map(|k| (k, ()))) /// } /// } /// ``` /// /// [`serialize_map`]: #tymethod.serialize_map fn collect_map(self, iter: I) -> Result where K: Serialize, V: Serialize, I: IntoIterator, { let mut iter = iter.into_iter(); let mut serializer = tri!(self.serialize_map(iterator_len_hint(&iter))); tri!(iter.try_for_each(|(key, value)| serializer.serialize_entry(&key, &value))); serializer.end() } /// Serialize a string produced by an implementation of `Display`. /// /// The default implementation builds a heap-allocated [`String`] and /// delegates to [`serialize_str`]. Serializers are encouraged to provide a /// more efficient implementation if possible. /// /// ```edition2021 /// # struct DateTime; /// # /// # impl DateTime { /// # fn naive_local(&self) -> () { () } /// # fn offset(&self) -> () { () } /// # } /// # /// use serde::{Serialize, Serializer}; /// /// impl Serialize for DateTime { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.collect_str(&format_args!("{:?}{:?}", self.naive_local(), self.offset())) /// } /// } /// ``` /// /// [`serialize_str`]: Self::serialize_str #[cfg(any(feature = "std", feature = "alloc"))] fn collect_str(self, value: &T) -> Result where T: ?Sized + Display, { self.serialize_str(&value.to_string()) } /// Serialize a string produced by an implementation of `Display`. /// /// Serializers that use `no_std` are required to provide an implementation /// of this method. If no more sensible behavior is possible, the /// implementation is expected to return an error. /// /// ```edition2021 /// # struct DateTime; /// # /// # impl DateTime { /// # fn naive_local(&self) -> () { () } /// # fn offset(&self) -> () { () } /// # } /// # /// use serde::{Serialize, Serializer}; /// /// impl Serialize for DateTime { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// serializer.collect_str(&format_args!("{:?}{:?}", self.naive_local(), self.offset())) /// } /// } /// ``` #[cfg(not(any(feature = "std", feature = "alloc")))] fn collect_str(self, value: &T) -> Result where T: ?Sized + Display; /// Determine whether `Serialize` implementations should serialize in /// human-readable form. /// /// Some types have a human-readable form that may be somewhat expensive to /// construct, as well as a binary form that is compact and efficient. /// Generally text-based formats like JSON and YAML will prefer to use the /// human-readable one and binary formats like Postcard will prefer the /// compact one. /// /// ```edition2021 /// # use std::fmt::{self, Display}; /// # /// # struct Timestamp; /// # /// # impl Timestamp { /// # fn seconds_since_epoch(&self) -> u64 { unimplemented!() } /// # } /// # /// # impl Display for Timestamp { /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { /// # unimplemented!() /// # } /// # } /// # /// use serde::{Serialize, Serializer}; /// /// impl Serialize for Timestamp { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// if serializer.is_human_readable() { /// // Serialize to a human-readable string "2015-05-15T17:01:00Z". /// self.to_string().serialize(serializer) /// } else { /// // Serialize to a compact binary representation. /// self.seconds_since_epoch().serialize(serializer) /// } /// } /// } /// ``` /// /// The default implementation of this method returns `true`. Data formats /// may override this to `false` to request a compact form for types that /// support one. Note that modifying this method to change a format from /// human-readable to compact or vice versa should be regarded as a breaking /// change, as a value serialized in human-readable mode is not required to /// deserialize from the same data in compact mode. #[inline] fn is_human_readable(&self) -> bool { true } } /// Returned from `Serializer::serialize_seq`. /// /// # Example use /// /// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct Vec(PhantomData); /// # /// # impl Vec { /// # fn len(&self) -> usize { /// # unimplemented!() /// # } /// # } /// # /// # impl<'a, T> IntoIterator for &'a Vec { /// # type Item = &'a T; /// # type IntoIter = Box>; /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # /// use serde::ser::{Serialize, SerializeSeq, Serializer}; /// /// impl Serialize for Vec /// where /// T: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut seq = serializer.serialize_seq(Some(self.len()))?; /// for element in self { /// seq.serialize_element(element)?; /// } /// seq.end() /// } /// } /// ``` /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `SerializeSeq` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::ser::SerializeSeq` is not satisfied", ) )] pub trait SerializeSeq { /// Must match the `Ok` type of our `Serializer`. type Ok; /// Must match the `Error` type of our `Serializer`. type Error: Error; /// Serialize a sequence element. fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize; /// Finish serializing a sequence. fn end(self) -> Result; } /// Returned from `Serializer::serialize_tuple`. /// /// # Example use /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// # mod fool { /// # trait Serialize {} /// impl Serialize for (A, B, C) /// # {} /// # } /// # /// # struct Tuple3(A, B, C); /// # /// # impl Serialize for Tuple3 /// where /// A: Serialize, /// B: Serialize, /// C: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut tup = serializer.serialize_tuple(3)?; /// tup.serialize_element(&self.0)?; /// tup.serialize_element(&self.1)?; /// tup.serialize_element(&self.2)?; /// tup.end() /// } /// } /// ``` /// /// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct Array(PhantomData); /// # /// # impl Array { /// # fn len(&self) -> usize { /// # unimplemented!() /// # } /// # } /// # /// # impl<'a, T> IntoIterator for &'a Array { /// # type Item = &'a T; /// # type IntoIter = Box>; /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # /// use serde::ser::{Serialize, SerializeTuple, Serializer}; /// /// # mod fool { /// # trait Serialize {} /// impl Serialize for [T; 16] /// # {} /// # } /// # /// # impl Serialize for Array /// where /// T: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut seq = serializer.serialize_tuple(16)?; /// for element in self { /// seq.serialize_element(element)?; /// } /// seq.end() /// } /// } /// ``` /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `SerializeTuple` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::ser::SerializeTuple` is not satisfied", ) )] pub trait SerializeTuple { /// Must match the `Ok` type of our `Serializer`. type Ok; /// Must match the `Error` type of our `Serializer`. type Error: Error; /// Serialize a tuple element. fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize; /// Finish serializing a tuple. fn end(self) -> Result; } /// Returned from `Serializer::serialize_tuple_struct`. /// /// # Example use /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeTupleStruct, Serializer}; /// /// struct Rgb(u8, u8, u8); /// /// impl Serialize for Rgb { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut ts = serializer.serialize_tuple_struct("Rgb", 3)?; /// ts.serialize_field(&self.0)?; /// ts.serialize_field(&self.1)?; /// ts.serialize_field(&self.2)?; /// ts.end() /// } /// } /// ``` /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `SerializeTupleStruct` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::ser::SerializeTupleStruct` is not satisfied", ) )] pub trait SerializeTupleStruct { /// Must match the `Ok` type of our `Serializer`. type Ok; /// Must match the `Error` type of our `Serializer`. type Error: Error; /// Serialize a tuple struct field. fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize; /// Finish serializing a tuple struct. fn end(self) -> Result; } /// Returned from `Serializer::serialize_tuple_variant`. /// /// # Example use /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeTupleVariant, Serializer}; /// /// enum E { /// T(u8, u8), /// U(String, u32, u32), /// } /// /// impl Serialize for E { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match *self { /// E::T(ref a, ref b) => { /// let mut tv = serializer.serialize_tuple_variant("E", 0, "T", 2)?; /// tv.serialize_field(a)?; /// tv.serialize_field(b)?; /// tv.end() /// } /// E::U(ref a, ref b, ref c) => { /// let mut tv = serializer.serialize_tuple_variant("E", 1, "U", 3)?; /// tv.serialize_field(a)?; /// tv.serialize_field(b)?; /// tv.serialize_field(c)?; /// tv.end() /// } /// } /// } /// } /// ``` /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `SerializeTupleVariant` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::ser::SerializeTupleVariant` is not satisfied", ) )] pub trait SerializeTupleVariant { /// Must match the `Ok` type of our `Serializer`. type Ok; /// Must match the `Error` type of our `Serializer`. type Error: Error; /// Serialize a tuple variant field. fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize; /// Finish serializing a tuple variant. fn end(self) -> Result; } /// Returned from `Serializer::serialize_map`. /// /// # Example use /// /// ```edition2021 /// # use std::marker::PhantomData; /// # /// # struct HashMap(PhantomData, PhantomData); /// # /// # impl HashMap { /// # fn len(&self) -> usize { /// # unimplemented!() /// # } /// # } /// # /// # impl<'a, K, V> IntoIterator for &'a HashMap { /// # type Item = (&'a K, &'a V); /// # type IntoIter = Box>; /// # /// # fn into_iter(self) -> Self::IntoIter { /// # unimplemented!() /// # } /// # } /// # /// use serde::ser::{Serialize, SerializeMap, Serializer}; /// /// impl Serialize for HashMap /// where /// K: Serialize, /// V: Serialize, /// { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut map = serializer.serialize_map(Some(self.len()))?; /// for (k, v) in self { /// map.serialize_entry(k, v)?; /// } /// map.end() /// } /// } /// ``` /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `SerializeMap` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::ser::SerializeMap` is not satisfied", ) )] pub trait SerializeMap { /// Must match the `Ok` type of our `Serializer`. type Ok; /// Must match the `Error` type of our `Serializer`. type Error: Error; /// Serialize a map key. /// /// If possible, `Serialize` implementations are encouraged to use /// `serialize_entry` instead as it may be implemented more efficiently in /// some formats compared to a pair of calls to `serialize_key` and /// `serialize_value`. fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize; /// Serialize a map value. /// /// # Panics /// /// Calling `serialize_value` before `serialize_key` is incorrect and is /// allowed to panic or produce bogus results. fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize; /// Serialize a map entry consisting of a key and a value. /// /// Some [`Serialize`] types are not able to hold a key and value in memory /// at the same time so `SerializeMap` implementations are required to /// support [`serialize_key`] and [`serialize_value`] individually. The /// `serialize_entry` method allows serializers to optimize for the case /// where key and value are both available. [`Serialize`] implementations /// are encouraged to use `serialize_entry` if possible. /// /// The default implementation delegates to [`serialize_key`] and /// [`serialize_value`]. This is appropriate for serializers that do not /// care about performance or are not able to optimize `serialize_entry` any /// better than this. /// /// [`Serialize`]: crate::Serialize /// [`serialize_key`]: Self::serialize_key /// [`serialize_value`]: Self::serialize_value fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where K: ?Sized + Serialize, V: ?Sized + Serialize, { tri!(self.serialize_key(key)); self.serialize_value(value) } /// Finish serializing a map. fn end(self) -> Result; } /// Returned from `Serializer::serialize_struct`. /// /// # Example use /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStruct, Serializer}; /// /// struct Rgb { /// r: u8, /// g: u8, /// b: u8, /// } /// /// impl Serialize for Rgb { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// let mut rgb = serializer.serialize_struct("Rgb", 3)?; /// rgb.serialize_field("r", &self.r)?; /// rgb.serialize_field("g", &self.g)?; /// rgb.serialize_field("b", &self.b)?; /// rgb.end() /// } /// } /// ``` /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `SerializeStruct` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::ser::SerializeStruct` is not satisfied", ) )] pub trait SerializeStruct { /// Must match the `Ok` type of our `Serializer`. type Ok; /// Must match the `Error` type of our `Serializer`. type Error: Error; /// Serialize a struct field. fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize; /// Indicate that a struct field has been skipped. /// /// The default implementation does nothing. #[inline] fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { let _ = key; Ok(()) } /// Finish serializing a struct. fn end(self) -> Result; } /// Returned from `Serializer::serialize_struct_variant`. /// /// # Example use /// /// ```edition2021 /// use serde::ser::{Serialize, SerializeStructVariant, Serializer}; /// /// enum E { /// S { r: u8, g: u8, b: u8 }, /// } /// /// impl Serialize for E { /// fn serialize(&self, serializer: S) -> Result /// where /// S: Serializer, /// { /// match *self { /// E::S { /// ref r, /// ref g, /// ref b, /// } => { /// let mut sv = serializer.serialize_struct_variant("E", 0, "S", 3)?; /// sv.serialize_field("r", r)?; /// sv.serialize_field("g", g)?; /// sv.serialize_field("b", b)?; /// sv.end() /// } /// } /// } /// } /// ``` /// /// # Example implementation /// /// The [example data format] presented on the website demonstrates an /// implementation of `SerializeStructVariant` for a basic JSON data format. /// /// [example data format]: https://serde.rs/data-format.html #[cfg_attr( not(no_diagnostic_namespace), diagnostic::on_unimplemented( message = "the trait bound `{Self}: serde::ser::SerializeStructVariant` is not satisfied", ) )] pub trait SerializeStructVariant { /// Must match the `Ok` type of our `Serializer`. type Ok; /// Must match the `Error` type of our `Serializer`. type Error: Error; /// Serialize a struct variant field. fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize; /// Indicate that a struct variant field has been skipped. /// /// The default implementation does nothing. #[inline] fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { let _ = key; Ok(()) } /// Finish serializing a struct variant. fn end(self) -> Result; } fn iterator_len_hint(iter: &I) -> Option where I: Iterator, { match iter.size_hint() { (lo, Some(hi)) if lo == hi => Some(lo), _ => None, } } ================================================ FILE: serde_core/src/std_error.rs ================================================ use crate::lib::{Debug, Display}; /// Either a re-export of std::error::Error or a new identical trait, depending /// on whether Serde's "std" feature is enabled. /// /// Serde's error traits [`serde::ser::Error`] and [`serde::de::Error`] require /// [`std::error::Error`] as a supertrait, but only when Serde is built with /// "std" enabled. Data formats that don't care about no\_std support should /// generally provide their error types with a `std::error::Error` impl /// directly: /// /// ```edition2021 /// #[derive(Debug)] /// struct MySerError {...} /// /// impl serde::ser::Error for MySerError {...} /// /// impl std::fmt::Display for MySerError {...} /// /// // We don't support no_std! /// impl std::error::Error for MySerError {} /// ``` /// /// Data formats that *do* support no\_std may either have a "std" feature of /// their own: /// /// ```toml /// [features] /// std = ["serde/std"] /// ``` /// /// ```edition2021 /// #[cfg(feature = "std")] /// impl std::error::Error for MySerError {} /// ``` /// /// ... or else provide the std Error impl unconditionally via Serde's /// re-export: /// /// ```edition2021 /// impl serde::ser::StdError for MySerError {} /// ``` pub trait Error: Debug + Display { /// The underlying cause of this error, if any. fn source(&self) -> Option<&(dyn Error + 'static)> { None } } ================================================ FILE: serde_derive/Cargo.toml ================================================ [package] name = "serde_derive" version = "1.0.228" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["no-std", "no-std::no-alloc"] description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" documentation = "https://serde.rs/derive.html" edition = "2021" exclude = ["build.rs"] homepage = "https://serde.rs" keywords = ["serde", "serialization", "no_std", "derive"] license = "MIT OR Apache-2.0" readme = "crates-io.md" repository = "https://github.com/serde-rs/serde" rust-version = "1.71" [features] default = [] deserialize_in_place = [] [lib] name = "serde_derive" proc-macro = true [dependencies] proc-macro2 = { workspace = true, features = ["proc-macro"] } quote = { workspace = true, features = ["proc-macro"] } syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] } [dev-dependencies] serde = { version = "1", path = "../serde" } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = [ "--generate-link-to-definition", "--generate-macro-expansion", "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", ] ================================================ FILE: serde_derive/build.rs ================================================ fn main() { // Warning: build.rs is not published to crates.io. println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rustc-cfg=check_cfg"); println!("cargo:rustc-check-cfg=cfg(check_cfg)"); println!("cargo:rustc-check-cfg=cfg(exhaustive)"); } ================================================ FILE: serde_derive/src/bound.rs ================================================ use crate::internals::ast::{Container, Data}; use crate::internals::{attr, ungroup}; use proc_macro2::Span; use std::collections::HashSet; use syn::punctuated::{Pair, Punctuated}; use syn::Token; // Remove the default from every type parameter because in the generated impls // they look like associated types: "error: associated type bindings are not // allowed here". pub fn without_defaults(generics: &syn::Generics) -> syn::Generics { syn::Generics { params: generics .params .iter() .map(|param| match param { syn::GenericParam::Type(param) => syn::GenericParam::Type(syn::TypeParam { eq_token: None, default: None, ..param.clone() }), _ => param.clone(), }) .collect(), ..generics.clone() } } pub fn with_where_predicates( generics: &syn::Generics, predicates: &[syn::WherePredicate], ) -> syn::Generics { let mut generics = generics.clone(); let dst_predicates = &mut generics.make_where_clause().predicates; for predicate in predicates { dst_predicates.push(predicate.clone()); } generics } pub fn with_where_predicates_from_fields( cont: &Container, generics: &syn::Generics, from_field: fn(&attr::Field) -> Option<&[syn::WherePredicate]>, ) -> syn::Generics { let mut generics = generics.clone(); let dst_predicates = &mut generics.make_where_clause().predicates; for field in cont.data.all_fields() { let Some(predicate_slice) = from_field(&field.attrs) else { continue; }; for inner_predicate in predicate_slice { dst_predicates.push(inner_predicate.clone()); } } generics } pub fn with_where_predicates_from_variants( cont: &Container, generics: &syn::Generics, from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>, ) -> syn::Generics { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => { return generics.clone(); } }; let mut generics = generics.clone(); let dst_predicates = &mut generics.make_where_clause().predicates; for variant in variants { let Some(predicate_slice) = from_variant(&variant.attrs) else { continue; }; for inner_predicate in predicate_slice { dst_predicates.push(inner_predicate.clone()); } } generics } // Puts the given bound on any generic type parameters that are used in fields // for which filter returns true. // // For example, the following struct needs the bound `A: Serialize, B: // Serialize`. // // struct S<'b, A, B: 'b, C> { // a: A, // b: Option<&'b B> // #[serde(skip_serializing)] // c: C, // } pub fn with_bound( cont: &Container, generics: &syn::Generics, filter: fn(&attr::Field, Option<&attr::Variant>) -> bool, bound: &syn::Path, ) -> syn::Generics { struct FindTyParams<'ast> { // Set of all generic type parameters on the current struct (A, B, C in // the example). Initialized up front. all_type_params: HashSet, // Set of generic type parameters used in fields for which filter // returns true (A and B in the example). Filled in as the visitor sees // them. relevant_type_params: HashSet, // Fields whose type is an associated type of one of the generic type // parameters. associated_type_usage: Vec<&'ast syn::TypePath>, } impl<'ast> FindTyParams<'ast> { fn visit_field(&mut self, field: &'ast syn::Field) { if let syn::Type::Path(ty) = ungroup(&field.ty) { if let Some(Pair::Punctuated(t, _)) = ty.path.segments.pairs().next() { if self.all_type_params.contains(&t.ident) { self.associated_type_usage.push(ty); } } } self.visit_type(&field.ty); } fn visit_path(&mut self, path: &'ast syn::Path) { if let Some(seg) = path.segments.last() { if seg.ident == "PhantomData" { // Hardcoded exception, because PhantomData implements // Serialize and Deserialize whether or not T implements it. return; } } if path.leading_colon.is_none() && path.segments.len() == 1 { let id = &path.segments[0].ident; if self.all_type_params.contains(id) { self.relevant_type_params.insert(id.clone()); } } for segment in &path.segments { self.visit_path_segment(segment); } } // Everything below is simply traversing the syntax tree. fn visit_type(&mut self, ty: &'ast syn::Type) { match ty { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::Type::Array(ty) => self.visit_type(&ty.elem), syn::Type::BareFn(ty) => { for arg in &ty.inputs { self.visit_type(&arg.ty); } self.visit_return_type(&ty.output); } syn::Type::Group(ty) => self.visit_type(&ty.elem), syn::Type::ImplTrait(ty) => { for bound in &ty.bounds { self.visit_type_param_bound(bound); } } syn::Type::Macro(ty) => self.visit_macro(&ty.mac), syn::Type::Paren(ty) => self.visit_type(&ty.elem), syn::Type::Path(ty) => { if let Some(qself) = &ty.qself { self.visit_type(&qself.ty); } self.visit_path(&ty.path); } syn::Type::Ptr(ty) => self.visit_type(&ty.elem), syn::Type::Reference(ty) => self.visit_type(&ty.elem), syn::Type::Slice(ty) => self.visit_type(&ty.elem), syn::Type::TraitObject(ty) => { for bound in &ty.bounds { self.visit_type_param_bound(bound); } } syn::Type::Tuple(ty) => { for elem in &ty.elems { self.visit_type(elem); } } syn::Type::Infer(_) | syn::Type::Never(_) | syn::Type::Verbatim(_) => {} _ => {} } } fn visit_path_segment(&mut self, segment: &'ast syn::PathSegment) { self.visit_path_arguments(&segment.arguments); } fn visit_path_arguments(&mut self, arguments: &'ast syn::PathArguments) { match arguments { syn::PathArguments::None => {} syn::PathArguments::AngleBracketed(arguments) => { for arg in &arguments.args { match arg { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::GenericArgument::Type(arg) => self.visit_type(arg), syn::GenericArgument::AssocType(arg) => self.visit_type(&arg.ty), syn::GenericArgument::Lifetime(_) | syn::GenericArgument::Const(_) | syn::GenericArgument::AssocConst(_) | syn::GenericArgument::Constraint(_) => {} _ => {} } } } syn::PathArguments::Parenthesized(arguments) => { for argument in &arguments.inputs { self.visit_type(argument); } self.visit_return_type(&arguments.output); } } } fn visit_return_type(&mut self, return_type: &'ast syn::ReturnType) { match return_type { syn::ReturnType::Default => {} syn::ReturnType::Type(_, output) => self.visit_type(output), } } fn visit_type_param_bound(&mut self, bound: &'ast syn::TypeParamBound) { match bound { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::TypeParamBound::Trait(bound) => self.visit_path(&bound.path), syn::TypeParamBound::Lifetime(_) | syn::TypeParamBound::PreciseCapture(_) | syn::TypeParamBound::Verbatim(_) => {} _ => {} } } // Type parameter should not be considered used by a macro path. // // struct TypeMacro { // mac: T!(), // marker: PhantomData, // } fn visit_macro(&mut self, _mac: &'ast syn::Macro) {} } let all_type_params = generics .type_params() .map(|param| param.ident.clone()) .collect(); let mut visitor = FindTyParams { all_type_params, relevant_type_params: HashSet::new(), associated_type_usage: Vec::new(), }; match &cont.data { Data::Enum(variants) => { for variant in variants { for field in &variant.fields { if filter(&field.attrs, Some(&variant.attrs)) { visitor.visit_field(field.original); } } } } Data::Struct(_, fields) => { for field in fields { if filter(&field.attrs, None) { visitor.visit_field(field.original); } } } } let relevant_type_params = visitor.relevant_type_params; let associated_type_usage = visitor.associated_type_usage; fn make_where_bounded_type( bounded_ty: syn::TypePath, bound: &syn::Path, ) -> syn::WherePredicate { syn::WherePredicate::Type(syn::PredicateType { lifetimes: None, // the type parameter that is being bounded e.g. T bounded_ty: syn::Type::Path(bounded_ty), colon_token: ::default(), // the bound e.g. Serialize bounds: { let mut punct = Punctuated::new(); punct.push(syn::TypeParamBound::Trait(syn::TraitBound { paren_token: None, modifier: syn::TraitBoundModifier::None, lifetimes: None, path: bound.clone(), })); punct }, }) } let mut dst_generics = generics.clone(); let dst_predicates = &mut dst_generics.make_where_clause().predicates; for param in generics.type_params() { let id = ¶m.ident; if !relevant_type_params.contains(id) { continue; } let bounded_ty = syn::TypePath { qself: None, path: id.clone().into(), }; dst_predicates.push(make_where_bounded_type(bounded_ty, bound)); } for bounded_ty in associated_type_usage { dst_predicates.push(make_where_bounded_type(bounded_ty.clone(), bound)); } dst_generics } pub fn with_self_bound( cont: &Container, generics: &syn::Generics, bound: &syn::Path, ) -> syn::Generics { let mut generics = generics.clone(); generics .make_where_clause() .predicates .push(syn::WherePredicate::Type(syn::PredicateType { lifetimes: None, // the type that is being bounded e.g. MyStruct<'a, T> bounded_ty: type_of_item(cont), colon_token: ::default(), // the bound e.g. Default bounds: vec![syn::TypeParamBound::Trait(syn::TraitBound { paren_token: None, modifier: syn::TraitBoundModifier::None, lifetimes: None, path: bound.clone(), })] .into_iter() .collect(), })); generics } pub fn with_lifetime_bound(generics: &syn::Generics, lifetime: &str) -> syn::Generics { let bound = syn::Lifetime::new(lifetime, Span::call_site()); let def = syn::LifetimeParam { attrs: Vec::new(), lifetime: bound.clone(), colon_token: None, bounds: Punctuated::new(), }; let params = Some(syn::GenericParam::Lifetime(def)) .into_iter() .chain(generics.params.iter().cloned().map(|mut param| { match &mut param { syn::GenericParam::Lifetime(param) => { param.bounds.push(bound.clone()); } syn::GenericParam::Type(param) => { param .bounds .push(syn::TypeParamBound::Lifetime(bound.clone())); } syn::GenericParam::Const(_) => {} } param })) .collect(); syn::Generics { params, ..generics.clone() } } fn type_of_item(cont: &Container) -> syn::Type { syn::Type::Path(syn::TypePath { qself: None, path: syn::Path { leading_colon: None, segments: vec![syn::PathSegment { ident: cont.ident.clone(), arguments: syn::PathArguments::AngleBracketed( syn::AngleBracketedGenericArguments { colon2_token: None, lt_token: ::default(), args: cont .generics .params .iter() .map(|param| match param { syn::GenericParam::Type(param) => { syn::GenericArgument::Type(syn::Type::Path(syn::TypePath { qself: None, path: param.ident.clone().into(), })) } syn::GenericParam::Lifetime(param) => { syn::GenericArgument::Lifetime(param.lifetime.clone()) } syn::GenericParam::Const(_) => { panic!("Serde does not support const generics yet"); } }) .collect(), gt_token: ]>::default(), }, ), }] .into_iter() .collect(), }, }) } ================================================ FILE: serde_derive/src/de/enum_.rs ================================================ use crate::de::enum_adjacently; use crate::de::enum_externally; use crate::de::enum_internally; use crate::de::enum_untagged; use crate::de::identifier; use crate::de::{field_i, FieldWithAliases, Parameters}; use crate::fragment::{Expr, Fragment, Stmts}; use crate::internals::ast::Variant; use crate::internals::attr; use crate::private; use proc_macro2::TokenStream; use quote::quote; /// Generates `Deserialize::deserialize` body for an `enum Enum {...}` pub(super) fn deserialize( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { // The variants have already been checked (in ast.rs) that all untagged variants appear at the end match variants.iter().position(|var| var.attrs.untagged()) { Some(variant_idx) => { let (tagged, untagged) = variants.split_at(variant_idx); let tagged_frag = Expr(deserialize_homogeneous_enum(params, tagged, cattrs)); // Ignore any error associated with non-untagged deserialization so that we // can fall through to the untagged variants. This may be infallible so we // need to provide the error type. let first_attempt = quote! { if let _serde::#private::Result::<_, __D::Error>::Ok(__ok) = (|| #tagged_frag)() { return _serde::#private::Ok(__ok); } }; enum_untagged::deserialize(params, untagged, cattrs, Some(first_attempt)) } None => deserialize_homogeneous_enum(params, variants, cattrs), } } fn deserialize_homogeneous_enum( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { match cattrs.tag() { attr::TagType::External => enum_externally::deserialize(params, variants, cattrs), attr::TagType::Internal { tag } => { enum_internally::deserialize(params, variants, cattrs, tag) } attr::TagType::Adjacent { tag, content } => { enum_adjacently::deserialize(params, variants, cattrs, tag, content) } attr::TagType::None => enum_untagged::deserialize(params, variants, cattrs, None), } } pub fn prepare_enum_variant_enum(variants: &[Variant]) -> (TokenStream, Stmts) { let deserialized_variants = variants .iter() .enumerate() .filter(|&(_i, variant)| !variant.attrs.skip_deserializing()); let fallthrough = deserialized_variants .clone() .find(|(_i, variant)| variant.attrs.other()) .map(|(i, _variant)| { let ignore_variant = field_i(i); quote!(_serde::#private::Ok(__Field::#ignore_variant)) }); let variants_stmt = { let variant_names = deserialized_variants .clone() .flat_map(|(_i, variant)| variant.attrs.aliases()); quote! { #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ]; } }; let deserialized_variants: Vec<_> = deserialized_variants .map(|(i, variant)| FieldWithAliases { ident: field_i(i), aliases: variant.attrs.aliases(), }) .collect(); let variant_visitor = Stmts(identifier::deserialize_generated( &deserialized_variants, false, // variant identifiers do not depend on the presence of flatten fields true, None, fallthrough, )); (variants_stmt, variant_visitor) } ================================================ FILE: serde_derive/src/de/enum_adjacently.rs ================================================ //! Deserialization for adjacently tagged enums: //! //! ```ignore //! #[serde(tag = "...", content = "...")] //! enum Enum {} //! ``` use crate::de::enum_; use crate::de::enum_untagged; use crate::de::{field_i, Parameters}; use crate::fragment::{Fragment, Match}; use crate::internals::ast::{Style, Variant}; use crate::internals::attr; use crate::private; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; /// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag, content)]` attributes pub(super) fn deserialize( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, tag: &str, content: &str, ) -> Fragment { let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants); let mut variant_arms = Vec::new(); for (i, variant) in variants.iter().enumerate() { if variant.attrs.skip_deserializing() { continue; } let variant_index = field_i(i); let block = Match(enum_untagged::deserialize_variant(params, variant, cattrs)); variant_arms.push(quote! { __Field::#variant_index => #block }); } let rust_name = params.type_name(); let expecting = format!("adjacently tagged enum {}", rust_name); let expecting = cattrs.expecting().unwrap_or(&expecting); let type_name = cattrs.name().deserialize_name(); let deny_unknown_fields = cattrs.deny_unknown_fields(); // If unknown fields are allowed, we pick the visitor that can step over // those. Otherwise we pick the visitor that fails on unknown keys. let field_visitor_ty = if deny_unknown_fields { quote! { _serde::#private::de::TagOrContentFieldVisitor } } else { quote! { _serde::#private::de::TagContentOtherFieldVisitor } }; let mut missing_content = quote! { _serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#content)) }; let mut missing_content_fallthrough = quote!(); let mut missing_content_arms = Vec::new(); for (i, variant) in variants.iter().enumerate() { if variant.attrs.skip_deserializing() { continue; } let variant_index = field_i(i); let variant_ident = &variant.ident; let arm = match variant.style { Style::Unit => quote! { _serde::#private::Ok(#this_value::#variant_ident) }, Style::Newtype if variant.attrs.deserialize_with().is_none() => { let span = variant.original.span(); let func = quote_spanned!(span=> _serde::#private::de::missing_field); quote! { #func(#content).map(#this_value::#variant_ident) } } _ => { missing_content_fallthrough = quote!(_ => #missing_content); continue; } }; missing_content_arms.push(quote! { __Field::#variant_index => #arm, }); } if !missing_content_arms.is_empty() { missing_content = quote! { match __field { #(#missing_content_arms)* #missing_content_fallthrough } }; } // Advance the map by one key, returning early in case of error. let next_key = quote! { _serde::de::MapAccess::next_key_seed(&mut __map, #field_visitor_ty { tag: #tag, content: #content, })? }; let variant_from_map = quote! { _serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::AdjacentlyTaggedEnumVariantSeed::<__Field> { enum_name: #rust_name, variants: VARIANTS, fields_enum: _serde::#private::PhantomData })? }; // 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. let next_relevant_key = if deny_unknown_fields { next_key } else { quote!({ let mut __rk : _serde::#private::Option<_serde::#private::de::TagOrContentField> = _serde::#private::None; while let _serde::#private::Some(__k) = #next_key { match __k { _serde::#private::de::TagContentOtherField::Other => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; continue; }, _serde::#private::de::TagContentOtherField::Tag => { __rk = _serde::#private::Some(_serde::#private::de::TagOrContentField::Tag); break; } _serde::#private::de::TagContentOtherField::Content => { __rk = _serde::#private::Some(_serde::#private::de::TagOrContentField::Content); break; } } } __rk }) }; // Step through remaining keys, looking for duplicates of previously-seen // keys. When unknown fields are denied, any key that isn't a duplicate will // at this point immediately produce an error. let visit_remaining_keys = quote! { match #next_relevant_key { _serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => { _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag)) } _serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => { _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content)) } _serde::#private::None => _serde::#private::Ok(__ret), } }; let finish_content_then_tag = if variant_arms.is_empty() { quote! { match #variant_from_map {} } } else { quote! { let __seed = __Seed { variant: #variant_from_map, marker: _serde::#private::PhantomData, lifetime: _serde::#private::PhantomData, }; let __deserializer = _serde::#private::de::ContentDeserializer::<__A::Error>::new(__content); let __ret = _serde::de::DeserializeSeed::deserialize(__seed, __deserializer)?; // Visit remaining keys, looking for duplicates. #visit_remaining_keys } }; quote_block! { #variant_visitor #variants_stmt #[doc(hidden)] struct __Seed #de_impl_generics #where_clause { variant: __Field, marker: _serde::#private::PhantomData<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Seed #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::#private::Result where __D: _serde::Deserializer<#delife>, { match self.variant { #(#variant_arms)* } } } #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::#private::PhantomData<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result where __A: _serde::de::MapAccess<#delife>, { // Visit the first relevant key. match #next_relevant_key { // First key is the tag. _serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => { // Parse the tag. let __field = #variant_from_map; // Visit the second key. match #next_relevant_key { // Second key is a duplicate of the tag. _serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => { _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#tag)) } // Second key is the content. _serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => { let __ret = _serde::de::MapAccess::next_value_seed(&mut __map, __Seed { variant: __field, marker: _serde::#private::PhantomData, lifetime: _serde::#private::PhantomData, })?; // Visit remaining keys, looking for duplicates. #visit_remaining_keys } // There is no second key; might be okay if the we have a unit variant. _serde::#private::None => #missing_content } } // First key is the content. _serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => { // Buffer up the content. let __content = _serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::ContentVisitor::new())?; // Visit the second key. match #next_relevant_key { // Second key is the tag. _serde::#private::Some(_serde::#private::de::TagOrContentField::Tag) => { #finish_content_then_tag } // Second key is a duplicate of the content. _serde::#private::Some(_serde::#private::de::TagOrContentField::Content) => { _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#content)) } // There is no second key. _serde::#private::None => { _serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#tag)) } } } // There is no first key. _serde::#private::None => { _serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#tag)) } } } fn visit_seq<__A>(self, mut __seq: __A) -> _serde::#private::Result where __A: _serde::de::SeqAccess<#delife>, { // Visit the first element - the tag. match _serde::de::SeqAccess::next_element(&mut __seq) { _serde::#private::Ok(_serde::#private::Some(__variant)) => { // Visit the second element - the content. match _serde::de::SeqAccess::next_element_seed( &mut __seq, __Seed { variant: __variant, marker: _serde::#private::PhantomData, lifetime: _serde::#private::PhantomData, }, ) { _serde::#private::Ok(_serde::#private::Some(__ret)) => _serde::#private::Ok(__ret), // There is no second element. _serde::#private::Ok(_serde::#private::None) => { _serde::#private::Err(_serde::de::Error::invalid_length(1, &self)) } _serde::#private::Err(__err) => _serde::#private::Err(__err), } } // There is no first element. _serde::#private::Ok(_serde::#private::None) => { _serde::#private::Err(_serde::de::Error::invalid_length(0, &self)) } _serde::#private::Err(__err) => _serde::#private::Err(__err), } } } #[doc(hidden)] const FIELDS: &'static [&'static str] = &[#tag, #content]; _serde::Deserializer::deserialize_struct( __deserializer, #type_name, FIELDS, __Visitor { marker: _serde::#private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData, }, ) } } ================================================ FILE: serde_derive/src/de/enum_externally.rs ================================================ //! Deserialization for externally tagged enums: //! //! ```ignore //! enum Enum {} //! ``` use crate::de::enum_; use crate::de::struct_; use crate::de::tuple; use crate::de::{ expr_is_missing, field_i, unwrap_to_variant_closure, wrap_deserialize_field_with, wrap_deserialize_with, Parameters, StructForm, TupleForm, }; use crate::fragment::{Expr, Fragment, Match}; use crate::internals::ast::{Field, Style, Variant}; use crate::internals::attr; use crate::private; use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; /// Generates `Deserialize::deserialize` body for an `enum Enum {...}` without additional attributes pub(super) fn deserialize( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); let type_name = cattrs.name().deserialize_name(); let expecting = format!("enum {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants); // Match arms to extract a variant from a string let variant_arms = variants .iter() .enumerate() .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) .map(|(i, variant)| { let variant_name = field_i(i); let block = Match(deserialize_externally_tagged_variant( params, variant, cattrs, )); quote! { _serde::#private::Ok((__Field::#variant_name, __variant)) => #block } }); let all_skipped = variants .iter() .all(|variant| variant.attrs.skip_deserializing()); let match_variant = if all_skipped { // This is an empty enum like `enum Impossible {}` or an enum in which // all variants have `#[serde(skip_deserializing)]`. quote! { // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::#private::Err(__err) = _serde::de::EnumAccess::variant::<__Field>(__data); // _serde::#private::Err(__err) _serde::#private::Result::map( _serde::de::EnumAccess::variant::<__Field>(__data), |(__impossible, _)| match __impossible {}) } } else { quote! { match _serde::de::EnumAccess::variant(__data) { #(#variant_arms)* _serde::#private::Err(__err) => _serde::#private::Err(__err), } } }; quote_block! { #variant_visitor #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::#private::PhantomData<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } fn visit_enum<__A>(self, __data: __A) -> _serde::#private::Result where __A: _serde::de::EnumAccess<#delife>, { #match_variant } } #variants_stmt _serde::Deserializer::deserialize_enum( __deserializer, #type_name, VARIANTS, __Visitor { marker: _serde::#private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData, }, ) } } fn deserialize_externally_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, ) -> Fragment { if let Some(path) = variant.attrs.deserialize_with() { let (wrapper, wrapper_ty, unwrap_fn) = wrap_deserialize_variant_with(params, variant, path); return quote_block! { #wrapper _serde::#private::Result::map( _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn) }; } let variant_ident = &variant.ident; match variant.style { Style::Unit => { let this_value = ¶ms.this_value; quote_block! { _serde::de::VariantAccess::unit_variant(__variant)?; _serde::#private::Ok(#this_value::#variant_ident) } } Style::Newtype => deserialize_externally_tagged_newtype_variant( variant_ident, params, &variant.fields[0], cattrs, ), Style::Tuple => tuple::deserialize( params, &variant.fields, cattrs, TupleForm::ExternallyTagged(variant_ident), ), Style::Struct => struct_::deserialize( params, &variant.fields, cattrs, StructForm::ExternallyTagged(variant_ident), ), } } fn wrap_deserialize_variant_with( params: &Parameters, variant: &Variant, deserialize_with: &syn::ExprPath, ) -> (TokenStream, TokenStream, TokenStream) { let field_tys = variant.fields.iter().map(|field| field.ty); let (wrapper, wrapper_ty) = wrap_deserialize_with(params, "e!((#(#field_tys),*)), deserialize_with); let unwrap_fn = unwrap_to_variant_closure(params, variant, true); (wrapper, wrapper_ty, unwrap_fn) } fn deserialize_externally_tagged_newtype_variant( variant_ident: &syn::Ident, params: &Parameters, field: &Field, cattrs: &attr::Container, ) -> Fragment { let this_value = ¶ms.this_value; if field.attrs.skip_deserializing() { let default = Expr(expr_is_missing(field, cattrs)); return quote_block! { _serde::de::VariantAccess::unit_variant(__variant)?; _serde::#private::Ok(#this_value::#variant_ident(#default)) }; } match field.attrs.deserialize_with() { None => { let field_ty = field.ty; let span = field.original.span(); let func = quote_spanned!(span=> _serde::de::VariantAccess::newtype_variant::<#field_ty>); quote_expr! { _serde::#private::Result::map(#func(__variant), #this_value::#variant_ident) } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote_block! { #wrapper _serde::#private::Result::map( _serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), |__wrapper| #this_value::#variant_ident(__wrapper.value)) } } } } ================================================ FILE: serde_derive/src/de/enum_internally.rs ================================================ //! Deserialization for internally tagged enums: //! //! ```ignore //! #[serde(tag = "...")] //! enum Enum {} //! ``` use crate::de::enum_; use crate::de::enum_untagged; use crate::de::struct_; use crate::de::{ effective_style, expr_is_missing, field_i, unwrap_to_variant_closure, Parameters, StructForm, }; use crate::fragment::{Expr, Fragment, Match}; use crate::internals::ast::{Style, Variant}; use crate::internals::attr; use crate::private; use quote::quote; /// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag)]` attribute pub(super) fn deserialize( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, tag: &str, ) -> Fragment { let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants); // Match arms to extract a variant from a string let variant_arms = variants .iter() .enumerate() .filter(|&(_, variant)| !variant.attrs.skip_deserializing()) .map(|(i, variant)| { let variant_name = field_i(i); let block = Match(deserialize_internally_tagged_variant( params, variant, cattrs, )); quote! { __Field::#variant_name => #block } }); let expecting = format!("internally tagged enum {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); quote_block! { #variant_visitor #variants_stmt let (__tag, __content) = _serde::Deserializer::deserialize_any( __deserializer, _serde::#private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?; let __deserializer = _serde::#private::de::ContentDeserializer::<__D::Error>::new(__content); match __tag { #(#variant_arms)* } } } // Generates significant part of the visit_seq and visit_map bodies of visitors // for the variants of internally tagged enum. fn deserialize_internally_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, ) -> Fragment { if let Some(path) = variant.attrs.deserialize_with() { let unwrap_fn = unwrap_to_variant_closure(params, variant, false); return quote_block! { _serde::#private::Result::map(#path(__deserializer), #unwrap_fn) }; } let variant_ident = &variant.ident; match effective_style(variant) { Style::Unit => { let this_value = ¶ms.this_value; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); let default = variant.fields.first().map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); quote_block! { _serde::Deserializer::deserialize_any(__deserializer, _serde::#private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?; _serde::#private::Ok(#this_value::#variant_ident #default) } } Style::Newtype => { enum_untagged::deserialize_newtype_variant(variant_ident, params, &variant.fields[0]) } Style::Struct => struct_::deserialize( params, &variant.fields, cattrs, StructForm::InternallyTagged(variant_ident), ), Style::Tuple => unreachable!("checked in serde_derive_internals"), } } ================================================ FILE: serde_derive/src/de/enum_untagged.rs ================================================ //! Deserialization for untagged enums: //! //! ```ignore //! #[serde(untagged)] //! enum Enum {} //! ``` use crate::de::struct_; use crate::de::tuple; use crate::de::{ effective_style, expr_is_missing, unwrap_to_variant_closure, Parameters, StructForm, TupleForm, }; use crate::fragment::{Expr, Fragment}; use crate::internals::ast::{Field, Style, Variant}; use crate::internals::attr; use crate::private; use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; /// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(untagged)]` attribute pub(super) fn deserialize( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, first_attempt: Option, ) -> Fragment { let attempts = variants .iter() .filter(|variant| !variant.attrs.skip_deserializing()) .map(|variant| Expr(deserialize_variant(params, variant, cattrs))); // TODO this message could be better by saving the errors from the failed // attempts. The heuristic used by TOML was to count the number of fields // processed before an error, and use the error that happened after the // largest number of fields. I'm not sure I like that. Maybe it would be // better to save all the errors and combine them into one message that // explains why none of the variants matched. let fallthrough_msg = format!( "data did not match any variant of untagged enum {}", params.type_name() ); let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg); let private2 = private; quote_block! { let __content = _serde::de::DeserializeSeed::deserialize(_serde::#private::de::ContentVisitor::new(), __deserializer)?; let __deserializer = _serde::#private::de::ContentRefDeserializer::<__D::Error>::new(&__content); #first_attempt #( if let _serde::#private2::Ok(__ok) = #attempts { return _serde::#private2::Ok(__ok); } )* _serde::#private::Err(_serde::de::Error::custom(#fallthrough_msg)) } } // Also used by adjacently tagged enums pub(super) fn deserialize_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, ) -> Fragment { if let Some(path) = variant.attrs.deserialize_with() { let unwrap_fn = unwrap_to_variant_closure(params, variant, false); return quote_block! { _serde::#private::Result::map(#path(__deserializer), #unwrap_fn) }; } let variant_ident = &variant.ident; match effective_style(variant) { Style::Unit => { let this_value = ¶ms.this_value; let type_name = params.type_name(); let variant_name = variant.ident.to_string(); let default = variant.fields.first().map(|field| { let default = Expr(expr_is_missing(field, cattrs)); quote!((#default)) }); quote_expr! { match _serde::Deserializer::deserialize_any( __deserializer, _serde::#private::de::UntaggedUnitVisitor::new(#type_name, #variant_name) ) { _serde::#private::Ok(()) => _serde::#private::Ok(#this_value::#variant_ident #default), _serde::#private::Err(__err) => _serde::#private::Err(__err), } } } Style::Newtype => deserialize_newtype_variant(variant_ident, params, &variant.fields[0]), Style::Tuple => tuple::deserialize( params, &variant.fields, cattrs, TupleForm::Untagged(variant_ident), ), Style::Struct => struct_::deserialize( params, &variant.fields, cattrs, StructForm::Untagged(variant_ident), ), } } // Also used by internally tagged enums // Implicitly (via `generate_variant`) used by adjacently tagged enums pub(super) fn deserialize_newtype_variant( variant_ident: &syn::Ident, params: &Parameters, field: &Field, ) -> Fragment { let this_value = ¶ms.this_value; let field_ty = field.ty; match field.attrs.deserialize_with() { None => { let span = field.original.span(); let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); quote_expr! { _serde::#private::Result::map(#func(__deserializer), #this_value::#variant_ident) } } Some(path) => { quote_block! { let __value: _serde::#private::Result<#field_ty, _> = #path(__deserializer); _serde::#private::Result::map(__value, #this_value::#variant_ident) } } } } ================================================ FILE: serde_derive/src/de/identifier.rs ================================================ //! Deserialization of struct field identifiers and enum variant identifiers by //! way of a Rust enum. use crate::de::{FieldWithAliases, Parameters}; use crate::fragment::{Fragment, Stmts}; use crate::internals::ast::{Style, Variant}; use crate::internals::attr; use crate::private; use proc_macro2::{Literal, TokenStream}; use quote::{quote, ToTokens}; // Generates `Deserialize::deserialize` body for an enum with // `serde(field_identifier)` or `serde(variant_identifier)` attribute. pub(super) fn deserialize_custom( params: &Parameters, variants: &[Variant], cattrs: &attr::Container, ) -> Fragment { let is_variant = match cattrs.identifier() { attr::Identifier::Variant => true, attr::Identifier::Field => false, attr::Identifier::No => unreachable!(), }; let this_type = params.this_type.to_token_stream(); let this_value = params.this_value.to_token_stream(); let (ordinary, fallthrough, fallthrough_borrowed) = if let Some(last) = variants.last() { let last_ident = &last.ident; if last.attrs.other() { // Process `serde(other)` attribute. It would always be found on the // last variant (checked in `check_identifier`), so all preceding // are ordinary variants. let ordinary = &variants[..variants.len() - 1]; let fallthrough = quote!(_serde::#private::Ok(#this_value::#last_ident)); (ordinary, Some(fallthrough), None) } else if let Style::Newtype = last.style { let ordinary = &variants[..variants.len() - 1]; let fallthrough = |value| { quote! { _serde::#private::Result::map( _serde::Deserialize::deserialize( _serde::#private::de::IdentifierDeserializer::from(#value) ), #this_value::#last_ident) } }; ( ordinary, Some(fallthrough(quote!(__value))), Some(fallthrough(quote!(_serde::#private::de::Borrowed( __value )))), ) } else { (variants, None, None) } } else { (variants, None, None) }; let idents_aliases: Vec<_> = ordinary .iter() .map(|variant| FieldWithAliases { ident: variant.ident.clone(), aliases: variant.attrs.aliases(), }) .collect(); let names = idents_aliases.iter().flat_map(|variant| variant.aliases); let names_const = if fallthrough.is_some() { None } else if is_variant { let variants = quote! { #[doc(hidden)] const VARIANTS: &'static [&'static str] = &[ #(#names),* ]; }; Some(variants) } else { let fields = quote! { #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#names),* ]; }; Some(fields) }; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); let visitor_impl = Stmts(deserialize_identifier( &this_value, &idents_aliases, is_variant, fallthrough, fallthrough_borrowed, false, cattrs.expecting(), )); quote_block! { #names_const #[doc(hidden)] struct __FieldVisitor #de_impl_generics #where_clause { marker: _serde::#private::PhantomData<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __FieldVisitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; #visitor_impl } let __visitor = __FieldVisitor { marker: _serde::#private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData, }; _serde::Deserializer::deserialize_identifier(__deserializer, __visitor) } } pub(super) fn deserialize_generated( deserialized_fields: &[FieldWithAliases], has_flatten: bool, is_variant: bool, ignore_variant: Option, fallthrough: Option, ) -> Fragment { let this_value = quote!(__Field); let field_idents: &Vec<_> = &deserialized_fields .iter() .map(|field| &field.ident) .collect(); let visitor_impl = Stmts(deserialize_identifier( &this_value, deserialized_fields, is_variant, fallthrough, None, !is_variant && has_flatten, None, )); let lifetime = if !is_variant && has_flatten { Some(quote!(<'de>)) } else { None }; quote_block! { #[allow(non_camel_case_types)] #[doc(hidden)] enum __Field #lifetime { #(#field_idents,)* #ignore_variant } #[doc(hidden)] struct __FieldVisitor; #[automatically_derived] impl<'de> _serde::de::Visitor<'de> for __FieldVisitor { type Value = __Field #lifetime; #visitor_impl } #[automatically_derived] impl<'de> _serde::Deserialize<'de> for __Field #lifetime { #[inline] fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result where __D: _serde::Deserializer<'de>, { _serde::Deserializer::deserialize_identifier(__deserializer, __FieldVisitor) } } } } fn deserialize_identifier( this_value: &TokenStream, deserialized_fields: &[FieldWithAliases], is_variant: bool, fallthrough: Option, fallthrough_borrowed: Option, collect_other_fields: bool, expecting: Option<&str>, ) -> Fragment { let str_mapping = deserialized_fields.iter().map(|field| { let ident = &field.ident; let aliases = field.aliases; let private2 = private; // `aliases` also contains a main name quote! { #( #aliases => _serde::#private2::Ok(#this_value::#ident), )* } }); let bytes_mapping = deserialized_fields.iter().map(|field| { let ident = &field.ident; // `aliases` also contains a main name let aliases = field .aliases .iter() .map(|alias| Literal::byte_string(alias.value.as_bytes())); let private2 = private; quote! { #( #aliases => _serde::#private2::Ok(#this_value::#ident), )* } }); let expecting = expecting.unwrap_or(if is_variant { "variant identifier" } else { "field identifier" }); let bytes_to_str = if fallthrough.is_some() || collect_other_fields { None } else { Some(quote! { let __value = &_serde::#private::from_utf8_lossy(__value); }) }; let ( value_as_str_content, value_as_borrowed_str_content, value_as_bytes_content, value_as_borrowed_bytes_content, ) = if collect_other_fields { ( Some(quote! { let __value = _serde::#private::de::Content::String(_serde::#private::ToString::to_string(__value)); }), Some(quote! { let __value = _serde::#private::de::Content::Str(__value); }), Some(quote! { let __value = _serde::#private::de::Content::ByteBuf(__value.to_vec()); }), Some(quote! { let __value = _serde::#private::de::Content::Bytes(__value); }), ) } else { (None, None, None, None) }; let fallthrough_arm_tokens; let fallthrough_arm = if let Some(fallthrough) = &fallthrough { fallthrough } else if is_variant { fallthrough_arm_tokens = quote! { _serde::#private::Err(_serde::de::Error::unknown_variant(__value, VARIANTS)) }; &fallthrough_arm_tokens } else { fallthrough_arm_tokens = quote! { _serde::#private::Err(_serde::de::Error::unknown_field(__value, FIELDS)) }; &fallthrough_arm_tokens }; let visit_other = if collect_other_fields { quote! { fn visit_bool<__E>(self, __value: bool) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Bool(__value))) } fn visit_i8<__E>(self, __value: i8) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I8(__value))) } fn visit_i16<__E>(self, __value: i16) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I16(__value))) } fn visit_i32<__E>(self, __value: i32) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I32(__value))) } fn visit_i64<__E>(self, __value: i64) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::I64(__value))) } fn visit_u8<__E>(self, __value: u8) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U8(__value))) } fn visit_u16<__E>(self, __value: u16) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U16(__value))) } fn visit_u32<__E>(self, __value: u32) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U32(__value))) } fn visit_u64<__E>(self, __value: u64) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::U64(__value))) } fn visit_f32<__E>(self, __value: f32) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::F32(__value))) } fn visit_f64<__E>(self, __value: f64) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::F64(__value))) } fn visit_char<__E>(self, __value: char) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Char(__value))) } fn visit_unit<__E>(self) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(__Field::__other(_serde::#private::de::Content::Unit)) } } } else { let u64_mapping = deserialized_fields.iter().enumerate().map(|(i, field)| { let i = i as u64; let ident = &field.ident; 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, deserialized_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! { fn visit_u64<__E>(self, __value: u64) -> _serde::#private::Result where __E: _serde::de::Error, { match __value { #(#u64_mapping,)* _ => #u64_fallthrough_arm, } } } }; 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); Some(quote! { fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::#private::Result where __E: _serde::de::Error, { match __value { #(#str_mapping)* _ => { #value_as_borrowed_str_content #fallthrough_borrowed_arm } } } fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::#private::Result where __E: _serde::de::Error, { match __value { #(#bytes_mapping)* _ => { #bytes_to_str #value_as_borrowed_bytes_content #fallthrough_borrowed_arm } } } }) } else { None }; quote_block! { fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } #visit_other fn visit_str<__E>(self, __value: &str) -> _serde::#private::Result where __E: _serde::de::Error, { match __value { #(#str_mapping)* _ => { #value_as_str_content #fallthrough_arm } } } fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::#private::Result where __E: _serde::de::Error, { match __value { #(#bytes_mapping)* _ => { #bytes_to_str #value_as_bytes_content #fallthrough_arm } } } #visit_borrowed } } ================================================ FILE: serde_derive/src/de/struct_.rs ================================================ use crate::de::identifier; use crate::de::{ deserialize_seq, expr_is_missing, field_i, has_flatten, wrap_deserialize_field_with, FieldWithAliases, Parameters, StructForm, }; #[cfg(feature = "deserialize_in_place")] use crate::de::{deserialize_seq_in_place, place_lifetime}; use crate::fragment::{Expr, Fragment, Match, Stmts}; use crate::internals::ast::Field; use crate::internals::attr; use crate::private; use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; /// Generates `Deserialize::deserialize` body for a `struct Struct {...}` pub(super) fn deserialize( params: &Parameters, fields: &[Field], cattrs: &attr::Container, form: StructForm, ) -> Fragment { let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); // If there are getters (implying private fields), construct the local type // and use an `Into` conversion to get the remote type. If there are no // getters then construct the target type directly. let construct = if params.has_getter { let local = ¶ms.local; quote!(#local) } else { quote!(#this_value) }; let type_path = match form { StructForm::Struct => construct, StructForm::ExternallyTagged(variant_ident) | StructForm::InternallyTagged(variant_ident) | StructForm::Untagged(variant_ident) => quote!(#construct::#variant_ident), }; let expecting = match form { StructForm::Struct => format!("struct {}", params.type_name()), StructForm::ExternallyTagged(variant_ident) | StructForm::InternallyTagged(variant_ident) | StructForm::Untagged(variant_ident) => { format!("struct variant {}::{}", params.type_name(), variant_ident) } }; let expecting = cattrs.expecting().unwrap_or(&expecting); let deserialized_fields: Vec<_> = fields .iter() .enumerate() // Skip fields that shouldn't be deserialized or that were flattened, // so they don't appear in the storage in their literal form .filter(|&(_, field)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(i, field)| FieldWithAliases { ident: field_i(i), aliases: field.attrs.aliases(), }) .collect(); let has_flatten = has_flatten(fields); let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, has_flatten); // untagged struct variants do not get a visit_seq method. The same applies to // structs that only have a map representation. let visit_seq = match form { StructForm::Untagged(_) => None, _ if has_flatten => None, _ => { let mut_seq = if deserialized_fields.is_empty() { quote!(_) } else { quote!(mut __seq) }; let visit_seq = Stmts(deserialize_seq( &type_path, params, fields, true, cattrs, expecting, )); Some(quote! { #[inline] fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } }) } }; let visit_map = Stmts(deserialize_map( &type_path, params, fields, cattrs, has_flatten, )); let visitor_seed = match form { StructForm::ExternallyTagged(..) if has_flatten => Some(quote! { #[automatically_derived] impl #de_impl_generics _serde::de::DeserializeSeed<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn deserialize<__D>(self, __deserializer: __D) -> _serde::#private::Result where __D: _serde::Deserializer<#delife>, { _serde::Deserializer::deserialize_map(__deserializer, self) } } }), _ => None, }; let fields_stmt = if has_flatten { None } else { let field_names = deserialized_fields.iter().flat_map(|field| field.aliases); Some(quote! { #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; }) }; let visitor_expr = quote! { __Visitor { marker: _serde::#private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData, } }; let dispatch = match form { StructForm::Struct if has_flatten => quote! { _serde::Deserializer::deserialize_map(__deserializer, #visitor_expr) }, StructForm::Struct => { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, #visitor_expr) } } StructForm::ExternallyTagged(_) if has_flatten => quote! { _serde::de::VariantAccess::newtype_variant_seed(__variant, #visitor_expr) }, StructForm::ExternallyTagged(_) => quote! { _serde::de::VariantAccess::struct_variant(__variant, FIELDS, #visitor_expr) }, StructForm::InternallyTagged(_) => quote! { _serde::Deserializer::deserialize_any(__deserializer, #visitor_expr) }, StructForm::Untagged(_) => quote! { _serde::Deserializer::deserialize_any(__deserializer, #visitor_expr) }, }; quote_block! { #field_visitor #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::#private::PhantomData<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } #visit_seq #[inline] fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result where __A: _serde::de::MapAccess<#delife>, { #visit_map } } #visitor_seed #fields_stmt #dispatch } } fn deserialize_map( struct_path: &TokenStream, params: &Parameters, fields: &[Field], cattrs: &attr::Container, has_flatten: bool, ) -> Fragment { // Create the field names for the fields. let fields_names: Vec<_> = fields .iter() .enumerate() .map(|(i, field)| (field, field_i(i))) .collect(); // Declare each field that will be deserialized. let let_values = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let field_ty = field.ty; quote! { let mut #name: _serde::#private::Option<#field_ty> = _serde::#private::None; } }); // Collect contents for flatten fields into a buffer let let_collect = if has_flatten { Some(quote! { let mut __collect = _serde::#private::Vec::<_serde::#private::Option<( _serde::#private::de::Content, _serde::#private::de::Content )>>::new(); }) } else { None }; // Match arms to extract a value for a field. let value_arms = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let deser_name = field.attrs.name().deserialize_name(); let visit = match field.attrs.deserialize_with() { None => { let field_ty = field.ty; let span = field.original.span(); let func = quote_spanned!(span=> _serde::de::MapAccess::next_value::<#field_ty>); quote! { #func(&mut __map)? } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) { _serde::#private::Ok(__wrapper) => __wrapper.value, _serde::#private::Err(__err) => { return _serde::#private::Err(__err); } } }) } }; quote! { __Field::#name => { if _serde::#private::Option::is_some(&#name) { return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name)); } #name = _serde::#private::Some(#visit); } } }); // Visit ignored values to consume them let ignored_arm = if has_flatten { Some(quote! { __Field::__other(__name) => { __collect.push(_serde::#private::Some(( __name, _serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::ContentVisitor::new())?))); } }) } else if cattrs.deny_unknown_fields() { None } else { Some(quote! { _ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; } }) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?; _serde::#private::Option::map( _serde::de::MapAccess::next_key::<__Field>(&mut __map)?, |__impossible| match __impossible {}); } } else { quote! { while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? { match __key { #(#value_arms)* #ignored_arm } } } }; let extract_values = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing() && !field.attrs.flatten()) .map(|(field, name)| { let missing_expr = Match(expr_is_missing(field, cattrs)); quote! { let #name = match #name { _serde::#private::Some(#name) => #name, _serde::#private::None => #missing_expr }; } }); let extract_collected = fields_names .iter() .filter(|&&(field, _)| field.attrs.flatten() && !field.attrs.skip_deserializing()) .map(|(field, name)| { let field_ty = field.ty; let func = match field.attrs.deserialize_with() { None => { let span = field.original.span(); quote_spanned!(span=> _serde::de::Deserialize::deserialize) } Some(path) => quote!(#path), }; quote! { let #name: #field_ty = #func( _serde::#private::de::FlatMapDeserializer( &mut __collect, _serde::#private::PhantomData))?; } }); let collected_deny_unknown_fields = if has_flatten && cattrs.deny_unknown_fields() { Some(quote! { if let _serde::#private::Some(_serde::#private::Some((__key, _))) = __collect.into_iter().filter(_serde::#private::Option::is_some).next() { if let _serde::#private::Some(__key) = _serde::#private::de::content_as_str(&__key) { return _serde::#private::Err( _serde::de::Error::custom(format_args!("unknown field `{}`", &__key))); } else { return _serde::#private::Err( _serde::de::Error::custom(format_args!("unexpected map key"))); } } }) } else { None }; let result = fields_names.iter().map(|(field, name)| { let member = &field.member; if field.attrs.skip_deserializing() { let value = Expr(expr_is_missing(field, cattrs)); quote!(#member: #value) } else { quote!(#member: #name) } }); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: Self::Value = _serde::#private::Default::default(); )), // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: Self::Value = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; let mut result = quote!(#struct_path { #(#result),* }); if params.has_getter { let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { _serde::#private::Into::<#this_type #ty_generics>::into(#result) }; } quote_block! { #(#let_values)* #let_collect #match_keys #let_default #(#extract_values)* #(#extract_collected)* #collected_deny_unknown_fields _serde::#private::Ok(#result) } } /// Generates `Deserialize::deserialize_in_place` body for a `struct Struct {...}` #[cfg(feature = "deserialize_in_place")] pub(super) fn deserialize_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Option { // for now we do not support in_place deserialization for structs that // are represented as map. if has_flatten(fields) { return None; } let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); let expecting = format!("struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); let deserialized_fields: Vec<_> = fields .iter() .enumerate() .filter(|&(_, field)| !field.attrs.skip_deserializing()) .map(|(i, field)| FieldWithAliases { ident: field_i(i), aliases: field.attrs.aliases(), }) .collect(); let field_visitor = deserialize_field_identifier(&deserialized_fields, cattrs, false); let mut_seq = if deserialized_fields.is_empty() { quote!(_) } else { quote!(mut __seq) }; let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let visit_map = Stmts(deserialize_map_in_place(params, fields, cattrs)); let field_names = deserialized_fields.iter().flat_map(|field| field.aliases); let type_name = cattrs.name().deserialize_name(); let in_place_impl_generics = de_impl_generics.in_place(); let in_place_ty_generics = de_ty_generics.in_place(); let place_life = place_lifetime(); Some(quote_block! { #field_visitor #[doc(hidden)] struct __Visitor #in_place_impl_generics #where_clause { place: &#place_life mut #this_type #ty_generics, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { type Value = (); fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } #[inline] fn visit_seq<__A>(self, #mut_seq: __A) -> _serde::#private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } #[inline] fn visit_map<__A>(self, mut __map: __A) -> _serde::#private::Result where __A: _serde::de::MapAccess<#delife>, { #visit_map } } #[doc(hidden)] const FIELDS: &'static [&'static str] = &[ #(#field_names),* ]; _serde::Deserializer::deserialize_struct(__deserializer, #type_name, FIELDS, __Visitor { place: __place, lifetime: _serde::#private::PhantomData, }) }) } #[cfg(feature = "deserialize_in_place")] fn deserialize_map_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { assert!( !has_flatten(fields), "inplace deserialization of maps does not support flatten fields" ); // Create the field names for the fields. let fields_names: Vec<_> = fields .iter() .enumerate() .map(|(i, field)| (field, field_i(i))) .collect(); // For deserialize_in_place, declare booleans for each field that will be // deserialized. let let_flags = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(_, name)| { quote! { let mut #name: bool = false; } }); // Match arms to extract a value for a field. let value_arms_from = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(field, name)| { let deser_name = field.attrs.name().deserialize_name(); let member = &field.member; let visit = match field.attrs.deserialize_with() { None => { quote! { _serde::de::MapAccess::next_value_seed(&mut __map, _serde::#private::de::InPlaceSeed(&mut self.place.#member))? } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper self.place.#member = match _serde::de::MapAccess::next_value::<#wrapper_ty>(&mut __map) { _serde::#private::Ok(__wrapper) => __wrapper.value, _serde::#private::Err(__err) => { return _serde::#private::Err(__err); } }; }) } }; quote! { __Field::#name => { if #name { return _serde::#private::Err(<__A::Error as _serde::de::Error>::duplicate_field(#deser_name)); } #visit; #name = true; } } }); // Visit ignored values to consume them let ignored_arm = if cattrs.deny_unknown_fields() { None } else { Some(quote! { _ => { let _ = _serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?; } }) }; let all_skipped = fields.iter().all(|field| field.attrs.skip_deserializing()); let match_keys = if cattrs.deny_unknown_fields() && all_skipped { quote! { // FIXME: Once feature(exhaustive_patterns) is stable: // let _serde::#private::None::<__Field> = _serde::de::MapAccess::next_key(&mut __map)?; _serde::#private::Option::map( _serde::de::MapAccess::next_key::<__Field>(&mut __map)?, |__impossible| match __impossible {}); } } else { quote! { while let _serde::#private::Some(__key) = _serde::de::MapAccess::next_key::<__Field>(&mut __map)? { match __key { #(#value_arms_from)* #ignored_arm } } } }; let check_flags = fields_names .iter() .filter(|&&(field, _)| !field.attrs.skip_deserializing()) .map(|(field, name)| { let missing_expr = expr_is_missing(field, cattrs); // If missing_expr unconditionally returns an error, don't try // to assign its value to self.place. if field.attrs.default().is_none() && cattrs.default().is_none() && field.attrs.deserialize_with().is_some() { let missing_expr = Stmts(missing_expr); quote! { if !#name { #missing_expr; } } } else { let member = &field.member; let missing_expr = Expr(missing_expr); quote! { if !#name { self.place.#member = #missing_expr; }; } } }); let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: #this_type #ty_generics = _serde::#private::Default::default(); )), // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; quote_block! { #(#let_flags)* #match_keys #let_default #(#check_flags)* _serde::#private::Ok(()) } } /// Generates enum and its `Deserialize` implementation that represents each /// non-skipped field of the struct fn deserialize_field_identifier( deserialized_fields: &[FieldWithAliases], cattrs: &attr::Container, has_flatten: bool, ) -> Stmts { let (ignore_variant, fallthrough) = if 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(identifier::deserialize_generated( deserialized_fields, has_flatten, false, ignore_variant, fallthrough, )) } ================================================ FILE: serde_derive/src/de/tuple.rs ================================================ use crate::de::{deserialize_seq, has_flatten, Parameters, TupleForm}; #[cfg(feature = "deserialize_in_place")] use crate::de::{deserialize_seq_in_place, place_lifetime}; use crate::fragment::{Fragment, Stmts}; use crate::internals::ast::Field; use crate::internals::attr; use crate::private; use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; /// Generates `Deserialize::deserialize` body for a `struct Tuple(...);` including `struct Newtype(T);` pub(super) fn deserialize( params: &Parameters, fields: &[Field], cattrs: &attr::Container, form: TupleForm, ) -> Fragment { assert!( !has_flatten(fields), "tuples and tuple variants cannot have flatten fields" ); let field_count = fields .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); // If there are getters (implying private fields), construct the local type // and use an `Into` conversion to get the remote type. If there are no // getters then construct the target type directly. let construct = if params.has_getter { let local = ¶ms.local; quote!(#local) } else { quote!(#this_value) }; let type_path = match form { TupleForm::Tuple => construct, TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident) => { quote!(#construct::#variant_ident) } }; let expecting = match form { TupleForm::Tuple => format!("tuple struct {}", params.type_name()), TupleForm::ExternallyTagged(variant_ident) | TupleForm::Untagged(variant_ident) => { format!("tuple variant {}::{}", params.type_name(), variant_ident) } }; let expecting = cattrs.expecting().unwrap_or(&expecting); let nfields = fields.len(); let visit_newtype_struct = match form { TupleForm::Tuple if nfields == 1 => { Some(deserialize_newtype_struct(&type_path, params, &fields[0])) } _ => None, }; let visit_seq = Stmts(deserialize_seq( &type_path, params, fields, false, cattrs, expecting, )); let visitor_expr = quote! { __Visitor { marker: _serde::#private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData, } }; let dispatch = match form { TupleForm::Tuple if nfields == 1 => { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr) } } TupleForm::Tuple => { let type_name = cattrs.name().deserialize_name(); quote! { _serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr) } } TupleForm::ExternallyTagged(_) => quote! { _serde::de::VariantAccess::tuple_variant(__variant, #field_count, #visitor_expr) }, TupleForm::Untagged(_) => quote! { _serde::Deserializer::deserialize_tuple(__deserializer, #field_count, #visitor_expr) }, }; let visitor_var = if field_count == 0 { quote!(_) } else { quote!(mut __seq) }; quote_block! { #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::#private::PhantomData<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } #visit_newtype_struct #[inline] fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::#private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } } #dispatch } } fn deserialize_newtype_struct( type_path: &TokenStream, params: &Parameters, field: &Field, ) -> TokenStream { let delife = params.borrowed.de_lifetime(); let field_ty = field.ty; let deserializer_var = quote!(__e); let value = match field.attrs.deserialize_with() { None => { let span = field.original.span(); let func = quote_spanned!(span=> <#field_ty as _serde::Deserialize>::deserialize); quote! { #func(#deserializer_var)? } } Some(path) => { // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(with = "...")] // ^^^^^ quote_spanned! {path.span()=> #path(#deserializer_var)? } } }; let mut result = quote!(#type_path(__field0)); if params.has_getter { let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { _serde::#private::Into::<#this_type #ty_generics>::into(#result) }; } quote! { #[inline] fn visit_newtype_struct<__E>(self, #deserializer_var: __E) -> _serde::#private::Result where __E: _serde::Deserializer<#delife>, { let __field0: #field_ty = #value; _serde::#private::Ok(#result) } } } /// Generates `Deserialize::deserialize_in_place` body for a `struct Tuple(...);` including `struct Newtype(T);` #[cfg(feature = "deserialize_in_place")] pub(super) fn deserialize_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { assert!( !has_flatten(fields), "tuples and tuple variants cannot have flatten fields" ); let field_count = fields .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); let expecting = format!("tuple struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); let nfields = fields.len(); let visit_newtype_struct = if nfields == 1 { // 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 where __E: _serde::Deserializer<#delife>, { _serde::Deserialize::deserialize_in_place(__e, &mut self.place.0) } }) } else { None }; let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, expecting)); let visitor_expr = quote! { __Visitor { place: __place, lifetime: _serde::#private::PhantomData, } }; let type_name = cattrs.name().deserialize_name(); let dispatch = if nfields == 1 { quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr)) } else { quote!(_serde::Deserializer::deserialize_tuple_struct(__deserializer, #type_name, #field_count, #visitor_expr)) }; let visitor_var = if field_count == 0 { quote!(_) } else { quote!(mut __seq) }; let in_place_impl_generics = de_impl_generics.in_place(); let in_place_ty_generics = de_ty_generics.in_place(); let place_life = place_lifetime(); quote_block! { #[doc(hidden)] struct __Visitor #in_place_impl_generics #where_clause { place: &#place_life mut #this_type #ty_generics, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #in_place_impl_generics _serde::de::Visitor<#delife> for __Visitor #in_place_ty_generics #where_clause { type Value = (); fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } #visit_newtype_struct #[inline] fn visit_seq<__A>(self, #visitor_var: __A) -> _serde::#private::Result where __A: _serde::de::SeqAccess<#delife>, { #visit_seq } } #dispatch } } ================================================ FILE: serde_derive/src/de/unit.rs ================================================ use crate::de::Parameters; use crate::fragment::Fragment; use crate::internals::attr; use crate::private; use quote::quote; /// Generates `Deserialize::deserialize` body for a `struct Unit;` pub(super) fn deserialize(params: &Parameters, cattrs: &attr::Container) -> Fragment { let this_type = ¶ms.this_type; let this_value = ¶ms.this_value; let type_name = cattrs.name().deserialize_name(); let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); let expecting = format!("unit struct {}", params.type_name()); let expecting = cattrs.expecting().unwrap_or(&expecting); quote_block! { #[doc(hidden)] struct __Visitor #de_impl_generics #where_clause { marker: _serde::#private::PhantomData<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #de_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_ty_generics #where_clause { type Value = #this_type #ty_generics; fn expecting(&self, __formatter: &mut _serde::#private::Formatter) -> _serde::#private::fmt::Result { _serde::#private::Formatter::write_str(__formatter, #expecting) } #[inline] fn visit_unit<__E>(self) -> _serde::#private::Result where __E: _serde::de::Error, { _serde::#private::Ok(#this_value) } } _serde::Deserializer::deserialize_unit_struct( __deserializer, #type_name, __Visitor { marker: _serde::#private::PhantomData::<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData, }, ) } } ================================================ FILE: serde_derive/src/de.rs ================================================ use crate::deprecated::allow_deprecated; use crate::fragment::{Expr, Fragment, Stmts}; use crate::internals::ast::{Container, Data, Field, Style, Variant}; use crate::internals::name::Name; use crate::internals::{attr, replace_receiver, ungroup, Ctxt, Derive}; use crate::{bound, dummy, pretend, private, this}; use proc_macro2::{Span, TokenStream}; use quote::{quote, quote_spanned, ToTokens}; use std::collections::BTreeSet; use std::ptr; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{parse_quote, Ident, Index, Member}; mod enum_; mod enum_adjacently; mod enum_externally; mod enum_internally; mod enum_untagged; mod identifier; mod struct_; mod tuple; mod unit; pub fn expand_derive_deserialize(input: &mut syn::DeriveInput) -> syn::Result { replace_receiver(input); let ctxt = Ctxt::new(); let Some(cont) = Container::from_ast(&ctxt, input, Derive::Deserialize, &private.ident()) else { return Err(ctxt.check().unwrap_err()); }; precondition(&ctxt, &cont); ctxt.check()?; let ident = &cont.ident; let params = Parameters::new(&cont); let (de_impl_generics, _, ty_generics, where_clause) = params.generics_with_de_lifetime(); let body = Stmts(deserialize_body(&cont, ¶ms)); let delife = params.borrowed.de_lifetime(); let allow_deprecated = allow_deprecated(input); let impl_block = if let Some(remote) = cont.attrs.remote() { let vis = &input.vis; let used = pretend::pretend_used(&cont, params.is_packed); quote! { #[automatically_derived] #allow_deprecated impl #de_impl_generics #ident #ty_generics #where_clause { #vis fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result<#remote #ty_generics, __D::Error> where __D: _serde::Deserializer<#delife>, { #used #body } } } } else { let fn_deserialize_in_place = deserialize_in_place_body(&cont, ¶ms); quote! { #[automatically_derived] #allow_deprecated impl #de_impl_generics _serde::Deserialize<#delife> for #ident #ty_generics #where_clause { fn deserialize<__D>(__deserializer: __D) -> _serde::#private::Result where __D: _serde::Deserializer<#delife>, { #body } #fn_deserialize_in_place } } }; Ok(dummy::wrap_in_const( cont.attrs.custom_serde_path(), impl_block, )) } fn precondition(cx: &Ctxt, cont: &Container) { precondition_sized(cx, cont); precondition_no_de_lifetime(cx, cont); } fn precondition_sized(cx: &Ctxt, cont: &Container) { if let Data::Struct(_, fields) = &cont.data { if let Some(last) = fields.last() { if let syn::Type::Slice(_) = ungroup(last.ty) { cx.error_spanned_by( cont.original, "cannot deserialize a dynamically sized struct", ); } } } } fn precondition_no_de_lifetime(cx: &Ctxt, cont: &Container) { if let BorrowedLifetimes::Borrowed(_) = borrowed_lifetimes(cont) { for param in cont.generics.lifetimes() { if param.lifetime.to_string() == "'de" { cx.error_spanned_by( ¶m.lifetime, "cannot deserialize when there is a lifetime parameter called 'de", ); return; } } } } struct Parameters { /// Name of the type the `derive` is on. local: syn::Ident, /// Path to the type the impl is for. Either a single `Ident` for local /// types (does not include generic parameters) or `some::remote::Path` for /// remote types. this_type: syn::Path, /// Same as `this_type` but using `::` for generic parameters for use in /// expression position. this_value: syn::Path, /// Generics including any explicit and inferred bounds for the impl. generics: syn::Generics, /// Lifetimes borrowed from the deserializer. These will become bounds on /// the `'de` lifetime of the deserializer. borrowed: BorrowedLifetimes, /// At least one field has a serde(getter) attribute, implying that the /// remote type has a private field. has_getter: bool, /// Type has a repr(packed) attribute. is_packed: bool, } impl Parameters { fn new(cont: &Container) -> Self { let local = cont.ident.clone(); let this_type = this::this_type(cont); let this_value = this::this_value(cont); let borrowed = borrowed_lifetimes(cont); let generics = build_generics(cont, &borrowed); let has_getter = cont.data.has_getter(); let is_packed = cont.attrs.is_packed(); Parameters { local, this_type, this_value, generics, borrowed, has_getter, is_packed, } } /// Type name to use in error messages and `&'static str` arguments to /// various Deserializer methods. fn type_name(&self) -> String { self.this_type.segments.last().unwrap().ident.to_string() } /// Split the data structure's generics into the pieces to use for its /// `Deserialize` impl, augmented with an additional `'de` lifetime for use /// as the `Deserialize` trait's lifetime. fn generics_with_de_lifetime( &self, ) -> ( DeImplGenerics, DeTypeGenerics, syn::TypeGenerics, Option<&syn::WhereClause>, ) { let de_impl_generics = DeImplGenerics(self); let de_ty_generics = DeTypeGenerics(self); let (_, ty_generics, where_clause) = self.generics.split_for_impl(); (de_impl_generics, de_ty_generics, ty_generics, where_clause) } } // All the generics in the input, plus a bound `T: Deserialize` for each generic // field type that will be deserialized by us, plus a bound `T: Default` for // each generic field type that will be set to a default value. fn build_generics(cont: &Container, borrowed: &BorrowedLifetimes) -> syn::Generics { let generics = bound::without_defaults(cont.generics); let generics = bound::with_where_predicates_from_fields(cont, &generics, attr::Field::de_bound); let generics = bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::de_bound); match cont.attrs.de_bound() { Some(predicates) => bound::with_where_predicates(&generics, predicates), None => { let generics = match *cont.attrs.default() { attr::Default::Default => bound::with_self_bound( cont, &generics, &parse_quote!(_serde::#private::Default), ), attr::Default::None | attr::Default::Path(_) => generics, }; let delife = borrowed.de_lifetime(); let generics = bound::with_bound( cont, &generics, needs_deserialize_bound, &parse_quote!(_serde::Deserialize<#delife>), ); bound::with_bound( cont, &generics, requires_default, &parse_quote!(_serde::#private::Default), ) } } } // Fields with a `skip_deserializing` or `deserialize_with` attribute, or which // belong to a variant with a `skip_deserializing` or `deserialize_with` // attribute, are not deserialized by us so we do not generate a bound. Fields // with a `bound` attribute specify their own bound so we do not generate one. // All other fields may need a `T: Deserialize` bound where T is the type of the // field. fn needs_deserialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { !field.skip_deserializing() && field.deserialize_with().is_none() && field.de_bound().is_none() && variant.map_or(true, |variant| { !variant.skip_deserializing() && variant.deserialize_with().is_none() && variant.de_bound().is_none() }) } // Fields with a `default` attribute (not `default=...`), and fields with a // `skip_deserializing` attribute that do not also have `default=...`. fn requires_default(field: &attr::Field, _variant: Option<&attr::Variant>) -> bool { if let attr::Default::Default = *field.default() { true } else { false } } enum BorrowedLifetimes { Borrowed(BTreeSet), Static, } impl BorrowedLifetimes { fn de_lifetime(&self) -> syn::Lifetime { match *self { BorrowedLifetimes::Borrowed(_) => syn::Lifetime::new("'de", Span::call_site()), BorrowedLifetimes::Static => syn::Lifetime::new("'static", Span::call_site()), } } fn de_lifetime_param(&self) -> Option { match self { BorrowedLifetimes::Borrowed(bounds) => Some(syn::LifetimeParam { attrs: Vec::new(), lifetime: syn::Lifetime::new("'de", Span::call_site()), colon_token: None, bounds: bounds.iter().cloned().collect(), }), BorrowedLifetimes::Static => None, } } } // The union of lifetimes borrowed by each field of the container. // // These turn into bounds on the `'de` lifetime of the Deserialize impl. If // lifetimes `'a` and `'b` are borrowed but `'c` is not, the impl is: // // impl<'de: 'a + 'b, 'a, 'b, 'c> Deserialize<'de> for S<'a, 'b, 'c> // // If any borrowed lifetime is `'static`, then `'de: 'static` would be redundant // and we use plain `'static` instead of `'de`. fn borrowed_lifetimes(cont: &Container) -> BorrowedLifetimes { let mut lifetimes = BTreeSet::new(); for field in cont.data.all_fields() { if !field.attrs.skip_deserializing() { lifetimes.extend(field.attrs.borrowed_lifetimes().iter().cloned()); } } if lifetimes.iter().any(|b| b.to_string() == "'static") { BorrowedLifetimes::Static } else { BorrowedLifetimes::Borrowed(lifetimes) } } fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment { if cont.attrs.transparent() { deserialize_transparent(cont, params) } else if let Some(type_from) = cont.attrs.type_from() { deserialize_from(type_from) } else if let Some(type_try_from) = cont.attrs.type_try_from() { deserialize_try_from(type_try_from) } else if let attr::Identifier::No = cont.attrs.identifier() { match &cont.data { Data::Enum(variants) => enum_::deserialize(params, variants, &cont.attrs), Data::Struct(Style::Struct, fields) => { struct_::deserialize(params, fields, &cont.attrs, StructForm::Struct) } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { tuple::deserialize(params, fields, &cont.attrs, TupleForm::Tuple) } Data::Struct(Style::Unit, _) => unit::deserialize(params, &cont.attrs), } } else { match &cont.data { Data::Enum(variants) => identifier::deserialize_custom(params, variants, &cont.attrs), Data::Struct(_, _) => unreachable!("checked in serde_derive_internals"), } } } #[cfg(feature = "deserialize_in_place")] fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option { // Only remote derives have getters, and we do not generate // deserialize_in_place for remote derives. assert!(!params.has_getter); if cont.attrs.transparent() || cont.attrs.type_from().is_some() || cont.attrs.type_try_from().is_some() || cont.attrs.identifier().is_some() || cont .data .all_fields() .all(|f| f.attrs.deserialize_with().is_some()) { return None; } let code = match &cont.data { Data::Struct(Style::Struct, fields) => { struct_::deserialize_in_place(params, fields, &cont.attrs)? } Data::Struct(Style::Tuple, fields) | Data::Struct(Style::Newtype, fields) => { tuple::deserialize_in_place(params, fields, &cont.attrs) } Data::Enum(_) | Data::Struct(Style::Unit, _) => { return None; } }; let delife = params.borrowed.de_lifetime(); let stmts = Stmts(code); let fn_deserialize_in_place = quote_block! { fn deserialize_in_place<__D>(__deserializer: __D, __place: &mut Self) -> _serde::#private::Result<(), __D::Error> where __D: _serde::Deserializer<#delife>, { #stmts } }; Some(Stmts(fn_deserialize_in_place)) } #[cfg(not(feature = "deserialize_in_place"))] fn deserialize_in_place_body(_cont: &Container, _params: &Parameters) -> Option { None } /// Generates `Deserialize::deserialize` body for a type with `#[serde(transparent)]` attribute fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment { let fields = match &cont.data { Data::Struct(_, fields) => fields, Data::Enum(_) => unreachable!(), }; let this_value = ¶ms.this_value; let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap(); let path = match transparent_field.attrs.deserialize_with() { Some(path) => quote!(#path), None => { let span = transparent_field.original.span(); quote_spanned!(span=> _serde::Deserialize::deserialize) } }; let assign = fields.iter().map(|field| { let member = &field.member; if ptr::eq(field, transparent_field) { quote!(#member: __transparent) } else { let value = match field.attrs.default() { attr::Default::Default => quote!(_serde::#private::Default::default()), // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ attr::Default::Path(path) => quote_spanned!(path.span()=> #path()), attr::Default::None => quote!(_serde::#private::PhantomData), }; quote!(#member: #value) } }); quote_block! { _serde::#private::Result::map( #path(__deserializer), |__transparent| #this_value { #(#assign),* }) } } /// Generates `Deserialize::deserialize` body for a type with `#[serde(from)]` attribute fn deserialize_from(type_from: &syn::Type) -> Fragment { quote_block! { _serde::#private::Result::map( <#type_from as _serde::Deserialize>::deserialize(__deserializer), _serde::#private::From::from) } } /// Generates `Deserialize::deserialize` body for a type with `#[serde(try_from)]` attribute fn deserialize_try_from(type_try_from: &syn::Type) -> Fragment { quote_block! { _serde::#private::Result::and_then( <#type_try_from as _serde::Deserialize>::deserialize(__deserializer), |v| _serde::#private::TryFrom::try_from(v).map_err(_serde::de::Error::custom)) } } enum TupleForm<'a> { Tuple, /// Contains a variant name ExternallyTagged(&'a syn::Ident), /// Contains a variant name Untagged(&'a syn::Ident), } fn deserialize_seq( type_path: &TokenStream, params: &Parameters, fields: &[Field], is_struct: bool, cattrs: &attr::Container, expecting: &str, ) -> Fragment { let vars = (0..fields.len()).map(field_i as fn(_) -> _); let deserialized_count = fields .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let expecting = if deserialized_count == 1 { format!("{} with 1 element", expecting) } else { format!("{} with {} elements", expecting, deserialized_count) }; let expecting = cattrs.expecting().unwrap_or(&expecting); let mut index_in_seq = 0_usize; let let_values = vars.clone().zip(fields).map(|(var, field)| { if field.attrs.skip_deserializing() { let default = Expr(expr_is_missing(field, cattrs)); quote! { let #var = #default; } } else { let visit = match field.attrs.deserialize_with() { None => { let field_ty = field.ty; let span = field.original.span(); let func = quote_spanned!(span=> _serde::de::SeqAccess::next_element::<#field_ty>); quote!(#func(&mut __seq)?) } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper _serde::#private::Option::map( _serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq)?, |__wrap| __wrap.value) }) } }; let value_if_none = expr_is_missing_seq(None, index_in_seq, field, cattrs, expecting); let assign = quote! { let #var = match #visit { _serde::#private::Some(__value) => __value, _serde::#private::None => #value_if_none, }; }; index_in_seq += 1; assign } }); let mut result = if is_struct { let names = fields.iter().map(|f| &f.member); quote! { #type_path { #( #names: #vars ),* } } } else { quote! { #type_path ( #(#vars),* ) } }; if params.has_getter { let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); result = quote! { _serde::#private::Into::<#this_type #ty_generics>::into(#result) }; } let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: Self::Value = _serde::#private::Default::default(); )), // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: Self::Value = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; quote_block! { #let_default #(#let_values)* _serde::#private::Ok(#result) } } #[cfg(feature = "deserialize_in_place")] fn deserialize_seq_in_place( params: &Parameters, fields: &[Field], cattrs: &attr::Container, expecting: &str, ) -> Fragment { let deserialized_count = fields .iter() .filter(|field| !field.attrs.skip_deserializing()) .count(); let expecting = if deserialized_count == 1 { format!("{} with 1 element", expecting) } else { format!("{} with {} elements", expecting, deserialized_count) }; let expecting = cattrs.expecting().unwrap_or(&expecting); let mut index_in_seq = 0usize; let write_values = fields.iter().map(|field| { let member = &field.member; if field.attrs.skip_deserializing() { let default = Expr(expr_is_missing(field, cattrs)); quote! { self.place.#member = #default; } } else { let value_if_none = expr_is_missing_seq(Some(quote!(self.place.#member = )), index_in_seq, field, cattrs, expecting); let write = match field.attrs.deserialize_with() { None => { quote! { if let _serde::#private::None = _serde::de::SeqAccess::next_element_seed(&mut __seq, _serde::#private::de::InPlaceSeed(&mut self.place.#member))? { #value_if_none; } } } Some(path) => { let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path); quote!({ #wrapper match _serde::de::SeqAccess::next_element::<#wrapper_ty>(&mut __seq) { _serde::#private::Ok(_serde::#private::Some(__wrap)) => { self.place.#member = __wrap.value; } _serde::#private::Ok(_serde::#private::None) => { #value_if_none; } _serde::#private::Err(__err) => { return _serde::#private::Err(__err); } } }) } }; index_in_seq += 1; write } }); let this_type = ¶ms.this_type; let (_, ty_generics, _) = params.generics.split_for_impl(); let let_default = match cattrs.default() { attr::Default::Default => Some(quote!( let __default: #this_type #ty_generics = _serde::#private::Default::default(); )), // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ attr::Default::Path(path) => Some(quote_spanned!(path.span()=> let __default: #this_type #ty_generics = #path(); )), attr::Default::None => { // We don't need the default value, to prevent an unused variable warning // we'll leave the line empty. None } }; quote_block! { #let_default #(#write_values)* _serde::#private::Ok(()) } } enum StructForm<'a> { Struct, /// Contains a variant name ExternallyTagged(&'a syn::Ident), /// Contains a variant name InternallyTagged(&'a syn::Ident), /// Contains a variant name Untagged(&'a syn::Ident), } struct FieldWithAliases<'a> { ident: Ident, aliases: &'a BTreeSet, } pub(crate) fn field_i(i: usize) -> Ident { Ident::new(&format!("__field{}", i), Span::call_site()) } /// This function wraps the expression in `#[serde(deserialize_with = "...")]` /// in a trait to prevent it from accessing the internal `Deserialize` state. fn wrap_deserialize_with( params: &Parameters, value_ty: &TokenStream, deserialize_with: &syn::ExprPath, ) -> (TokenStream, TokenStream) { let this_type = ¶ms.this_type; let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = params.generics_with_de_lifetime(); let delife = params.borrowed.de_lifetime(); let deserializer_var = quote!(__deserializer); // If #deserialize_with returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(with = "...")] // ^^^^^ let value = quote_spanned! {deserialize_with.span()=> #deserialize_with(#deserializer_var)? }; let wrapper = quote! { #[doc(hidden)] struct __DeserializeWith #de_impl_generics #where_clause { value: #value_ty, phantom: _serde::#private::PhantomData<#this_type #ty_generics>, lifetime: _serde::#private::PhantomData<&#delife ()>, } #[automatically_derived] impl #de_impl_generics _serde::Deserialize<#delife> for __DeserializeWith #de_ty_generics #where_clause { fn deserialize<__D>(#deserializer_var: __D) -> _serde::#private::Result where __D: _serde::Deserializer<#delife>, { _serde::#private::Ok(__DeserializeWith { value: #value, phantom: _serde::#private::PhantomData, lifetime: _serde::#private::PhantomData, }) } } }; let wrapper_ty = quote!(__DeserializeWith #de_ty_generics); (wrapper, wrapper_ty) } fn wrap_deserialize_field_with( params: &Parameters, field_ty: &syn::Type, deserialize_with: &syn::ExprPath, ) -> (TokenStream, TokenStream) { wrap_deserialize_with(params, "e!(#field_ty), deserialize_with) } // Generates closure that converts single input parameter to the final value. fn unwrap_to_variant_closure( params: &Parameters, variant: &Variant, with_wrapper: bool, ) -> TokenStream { let this_value = ¶ms.this_value; let variant_ident = &variant.ident; let (arg, wrapper) = if with_wrapper { (quote! { __wrap }, quote! { __wrap.value }) } else { let field_tys = variant.fields.iter().map(|field| field.ty); (quote! { __wrap: (#(#field_tys),*) }, quote! { __wrap }) }; let field_access = (0..variant.fields.len()).map(|n| { Member::Unnamed(Index { index: n as u32, span: Span::call_site(), }) }); match variant.style { Style::Struct if variant.fields.len() == 1 => { let member = &variant.fields[0].member; quote! { |#arg| #this_value::#variant_ident { #member: #wrapper } } } Style::Struct => { let members = variant.fields.iter().map(|field| &field.member); quote! { |#arg| #this_value::#variant_ident { #(#members: #wrapper.#field_access),* } } } Style::Tuple => quote! { |#arg| #this_value::#variant_ident(#(#wrapper.#field_access),*) }, Style::Newtype => quote! { |#arg| #this_value::#variant_ident(#wrapper) }, Style::Unit => quote! { |#arg| #this_value::#variant_ident }, } } fn expr_is_missing(field: &Field, cattrs: &attr::Container) -> Fragment { match field.attrs.default() { attr::Default::Default => { let span = field.original.span(); let func = quote_spanned!(span=> _serde::#private::Default::default); return quote_expr!(#func()); } attr::Default::Path(path) => { // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ return Fragment::Expr(quote_spanned!(path.span()=> #path())); } attr::Default::None => { /* below */ } } match *cattrs.default() { attr::Default::Default | attr::Default::Path(_) => { let member = &field.member; return quote_expr!(__default.#member); } attr::Default::None => { /* below */ } } let name = field.attrs.name().deserialize_name(); match field.attrs.deserialize_with() { None => { let span = field.original.span(); let func = quote_spanned!(span=> _serde::#private::de::missing_field); quote_expr! { #func(#name)? } } Some(_) => { quote_expr! { return _serde::#private::Err(<__A::Error as _serde::de::Error>::missing_field(#name)) } } } } fn expr_is_missing_seq( assign_to: Option, 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) => { // If #path returns wrong type, error will be reported here (^^^^^). // We attach span of the path to the function so it will be reported // on the #[serde(default = "...")] // ^^^^^ 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 { match variant.style { Style::Newtype if variant.fields[0].attrs.skip_deserializing() => Style::Unit, other => other, } } /// True if there is any field with a `#[serde(flatten)]` attribute, other than /// fields which are skipped. fn has_flatten(fields: &[Field]) -> bool { fields .iter() .any(|field| field.attrs.flatten() && !field.attrs.skip_deserializing()) } struct DeImplGenerics<'a>(&'a Parameters); #[cfg(feature = "deserialize_in_place")] struct InPlaceImplGenerics<'a>(&'a Parameters); impl<'a> ToTokens for DeImplGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut generics = self.0.generics.clone(); if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() { generics.params = Some(syn::GenericParam::Lifetime(de_lifetime)) .into_iter() .chain(generics.params) .collect(); } let (impl_generics, _, _) = generics.split_for_impl(); impl_generics.to_tokens(tokens); } } #[cfg(feature = "deserialize_in_place")] impl<'a> ToTokens for InPlaceImplGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let place_lifetime = place_lifetime(); let mut generics = self.0.generics.clone(); // Add lifetime for `&'place mut Self, and `'a: 'place` for param in &mut generics.params { match param { syn::GenericParam::Lifetime(param) => { param.bounds.push(place_lifetime.lifetime.clone()); } syn::GenericParam::Type(param) => { param.bounds.push(syn::TypeParamBound::Lifetime( place_lifetime.lifetime.clone(), )); } syn::GenericParam::Const(_) => {} } } generics.params = Some(syn::GenericParam::Lifetime(place_lifetime)) .into_iter() .chain(generics.params) .collect(); if let Some(de_lifetime) = self.0.borrowed.de_lifetime_param() { generics.params = Some(syn::GenericParam::Lifetime(de_lifetime)) .into_iter() .chain(generics.params) .collect(); } let (impl_generics, _, _) = generics.split_for_impl(); impl_generics.to_tokens(tokens); } } #[cfg(feature = "deserialize_in_place")] impl<'a> DeImplGenerics<'a> { fn in_place(self) -> InPlaceImplGenerics<'a> { InPlaceImplGenerics(self.0) } } struct DeTypeGenerics<'a>(&'a Parameters); #[cfg(feature = "deserialize_in_place")] struct InPlaceTypeGenerics<'a>(&'a Parameters); fn de_type_generics_to_tokens( mut generics: syn::Generics, borrowed: &BorrowedLifetimes, tokens: &mut TokenStream, ) { if borrowed.de_lifetime_param().is_some() { let def = syn::LifetimeParam { attrs: Vec::new(), lifetime: syn::Lifetime::new("'de", Span::call_site()), colon_token: None, bounds: Punctuated::new(), }; // Prepend 'de lifetime to list of generics generics.params = Some(syn::GenericParam::Lifetime(def)) .into_iter() .chain(generics.params) .collect(); } let (_, ty_generics, _) = generics.split_for_impl(); ty_generics.to_tokens(tokens); } impl<'a> ToTokens for DeTypeGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { de_type_generics_to_tokens(self.0.generics.clone(), &self.0.borrowed, tokens); } } #[cfg(feature = "deserialize_in_place")] impl<'a> ToTokens for InPlaceTypeGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut generics = self.0.generics.clone(); generics.params = Some(syn::GenericParam::Lifetime(place_lifetime())) .into_iter() .chain(generics.params) .collect(); de_type_generics_to_tokens(generics, &self.0.borrowed, tokens); } } #[cfg(feature = "deserialize_in_place")] impl<'a> DeTypeGenerics<'a> { fn in_place(self) -> InPlaceTypeGenerics<'a> { InPlaceTypeGenerics(self.0) } } #[cfg(feature = "deserialize_in_place")] fn place_lifetime() -> syn::LifetimeParam { syn::LifetimeParam { attrs: Vec::new(), lifetime: syn::Lifetime::new("'place", Span::call_site()), colon_token: None, bounds: Punctuated::new(), } } ================================================ FILE: serde_derive/src/deprecated.rs ================================================ use proc_macro2::TokenStream; use quote::quote; pub fn allow_deprecated(input: &syn::DeriveInput) -> Option { if should_allow_deprecated(input) { Some(quote! { #[allow(deprecated)] }) } else { None } } /// Determine if an `#[allow(deprecated)]` should be added to the derived impl. /// /// This should happen if the derive input or an enum variant it contains has /// one of: /// - `#[deprecated]` /// - `#[allow(deprecated)]` fn should_allow_deprecated(input: &syn::DeriveInput) -> bool { if contains_deprecated(&input.attrs) { return true; } if let syn::Data::Enum(data_enum) = &input.data { for variant in &data_enum.variants { if contains_deprecated(&variant.attrs) { return true; } } } false } /// Check whether the given attributes contains one of: /// - `#[deprecated]` /// - `#[allow(deprecated)]` fn contains_deprecated(attrs: &[syn::Attribute]) -> bool { for attr in attrs { if attr.path().is_ident("deprecated") { return true; } if let syn::Meta::List(meta_list) = &attr.meta { if meta_list.path.is_ident("allow") { let mut allow_deprecated = false; let _ = meta_list.parse_nested_meta(|meta| { if meta.path.is_ident("deprecated") { allow_deprecated = true; } Ok(()) }); if allow_deprecated { return true; } } } } false } ================================================ FILE: serde_derive/src/dummy.rs ================================================ use proc_macro2::TokenStream; use quote::quote; pub fn wrap_in_const(serde_path: Option<&syn::Path>, code: TokenStream) -> TokenStream { let use_serde = match serde_path { Some(path) => quote! { use #path as _serde; }, None => quote! { #[allow(unused_extern_crates, clippy::useless_attribute)] extern crate serde as _serde; }, }; quote! { #[doc(hidden)] #[allow( non_upper_case_globals, unused_attributes, unused_qualifications, clippy::absolute_paths, )] const _: () = { #use_serde _serde::__require_serde_not_serde_core!(); #code }; } } ================================================ FILE: serde_derive/src/fragment.rs ================================================ use proc_macro2::TokenStream; use quote::ToTokens; use syn::{token, Token}; pub enum Fragment { /// Tokens that can be used as an expression. Expr(TokenStream), /// Tokens that can be used inside a block. The surrounding curly braces are /// not part of these tokens. Block(TokenStream), } macro_rules! quote_expr { ($($tt:tt)*) => { $crate::fragment::Fragment::Expr(quote!($($tt)*)) } } macro_rules! quote_block { ($($tt:tt)*) => { $crate::fragment::Fragment::Block(quote!($($tt)*)) } } /// Interpolate a fragment in place of an expression. This involves surrounding /// Block fragments in curly braces. pub struct Expr(pub Fragment); impl ToTokens for Expr { fn to_tokens(&self, out: &mut TokenStream) { match &self.0 { Fragment::Expr(expr) => expr.to_tokens(out), Fragment::Block(block) => { token::Brace::default().surround(out, |out| block.to_tokens(out)); } } } } /// Interpolate a fragment as the statements of a block. pub struct Stmts(pub Fragment); impl ToTokens for Stmts { fn to_tokens(&self, out: &mut TokenStream) { match &self.0 { Fragment::Expr(expr) => expr.to_tokens(out), Fragment::Block(block) => block.to_tokens(out), } } } /// Interpolate a fragment as the value part of a `match` expression. This /// involves putting a comma after expressions and curly braces around blocks. pub struct Match(pub Fragment); impl ToTokens for Match { fn to_tokens(&self, out: &mut TokenStream) { match &self.0 { Fragment::Expr(expr) => { expr.to_tokens(out); ::default().to_tokens(out); } Fragment::Block(block) => { token::Brace::default().surround(out, |out| block.to_tokens(out)); } } } } impl AsRef for Fragment { fn as_ref(&self) -> &TokenStream { match self { Fragment::Expr(expr) => expr, Fragment::Block(block) => block, } } } ================================================ FILE: serde_derive/src/internals/ast.rs ================================================ //! A Serde ast, parsed from the Syn ast and ready to generate Rust code. use crate::internals::{attr, check, Ctxt, Derive}; use proc_macro2::Ident; use syn::punctuated::Punctuated; use syn::Token; /// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`, /// parsed into an internal representation. pub struct Container<'a> { /// The struct or enum name (without generics). pub ident: syn::Ident, /// Attributes on the structure, parsed for Serde. pub attrs: attr::Container, /// The contents of the struct or enum. pub data: Data<'a>, /// Any generics on the struct or enum. pub generics: &'a syn::Generics, /// Original input. pub original: &'a syn::DeriveInput, } /// The fields of a struct or enum. /// /// Analogous to `syn::Data`. pub enum Data<'a> { Enum(Vec>), Struct(Style, Vec>), } /// A variant of an enum. pub struct Variant<'a> { pub ident: syn::Ident, pub attrs: attr::Variant, pub style: Style, pub fields: Vec>, pub original: &'a syn::Variant, } /// A field of a struct. pub struct Field<'a> { pub member: syn::Member, pub attrs: attr::Field, pub ty: &'a syn::Type, pub original: &'a syn::Field, } #[derive(Copy, Clone)] pub enum Style { /// Named fields. Struct, /// Many unnamed fields. Tuple, /// One unnamed field. Newtype, /// No fields. Unit, } impl<'a> Container<'a> { /// Convert the raw Syn ast into a parsed container object, collecting errors in `cx`. pub fn from_ast( cx: &Ctxt, item: &'a syn::DeriveInput, derive: Derive, private: &Ident, ) -> Option> { let attrs = attr::Container::from_ast(cx, item); let mut data = match &item.data { syn::Data::Enum(data) => { Data::Enum(enum_from_ast(cx, &data.variants, attrs.default(), private)) } syn::Data::Struct(data) => { let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default(), private); Data::Struct(style, fields) } syn::Data::Union(_) => { cx.error_spanned_by(item, "Serde does not support derive for unions"); return None; } }; match &mut data { Data::Enum(variants) => { for variant in variants { variant.attrs.rename_by_rules(attrs.rename_all_rules()); for field in &mut variant.fields { field.attrs.rename_by_rules( variant .attrs .rename_all_rules() .or(attrs.rename_all_fields_rules()), ); } } } Data::Struct(_, fields) => { for field in fields { field.attrs.rename_by_rules(attrs.rename_all_rules()); } } } let mut item = Container { ident: item.ident.clone(), attrs, data, generics: &item.generics, original: item, }; check::check(cx, &mut item, derive); Some(item) } } impl<'a> Data<'a> { pub fn all_fields(&'a self) -> Box> + 'a> { match self { Data::Enum(variants) => { Box::new(variants.iter().flat_map(|variant| variant.fields.iter())) } Data::Struct(_, fields) => Box::new(fields.iter()), } } pub fn has_getter(&self) -> bool { self.all_fields().any(|f| f.attrs.getter().is_some()) } } fn enum_from_ast<'a>( cx: &Ctxt, variants: &'a Punctuated, container_default: &attr::Default, private: &Ident, ) -> Vec> { let variants: Vec = variants .iter() .map(|variant| { let attrs = attr::Variant::from_ast(cx, variant); let (style, fields) = struct_from_ast( cx, &variant.fields, Some(&attrs), container_default, private, ); Variant { ident: variant.ident.clone(), attrs, style, fields, original: variant, } }) .collect(); let index_of_last_tagged_variant = variants .iter() .rposition(|variant| !variant.attrs.untagged()); if let Some(index_of_last_tagged_variant) = index_of_last_tagged_variant { for variant in &variants[..index_of_last_tagged_variant] { if variant.attrs.untagged() { cx.error_spanned_by(&variant.ident, "all variants with the #[serde(untagged)] attribute must be placed at the end of the enum"); } } } variants } fn struct_from_ast<'a>( cx: &Ctxt, fields: &'a syn::Fields, attrs: Option<&attr::Variant>, container_default: &attr::Default, private: &Ident, ) -> (Style, Vec>) { match fields { syn::Fields::Named(fields) => ( Style::Struct, fields_from_ast(cx, &fields.named, attrs, container_default, private), ), syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => ( Style::Newtype, fields_from_ast(cx, &fields.unnamed, attrs, container_default, private), ), syn::Fields::Unnamed(fields) => ( Style::Tuple, fields_from_ast(cx, &fields.unnamed, attrs, container_default, private), ), syn::Fields::Unit => (Style::Unit, Vec::new()), } } fn fields_from_ast<'a>( cx: &Ctxt, fields: &'a Punctuated, attrs: Option<&attr::Variant>, container_default: &attr::Default, private: &Ident, ) -> Vec> { let mut dst_fields = Vec::with_capacity(fields.len()); for field in fields { dst_fields.push(Field { member: match &field.ident { Some(ident) => syn::Member::Named(ident.clone()), None => syn::Member::Unnamed(dst_fields.len().into()), }, attrs: attr::Field::from_ast( cx, dst_fields.len(), field, attrs, container_default, private, ), ty: &field.ty, original: field, }); } dst_fields } ================================================ FILE: serde_derive/src/internals/attr.rs ================================================ use crate::internals::name::{MultiName, Name}; use crate::internals::symbol::*; use crate::internals::{ungroup, Ctxt}; use proc_macro2::{Spacing, Span, TokenStream, TokenTree}; use quote::ToTokens; use std::collections::BTreeSet; use std::iter::FromIterator; use syn::meta::ParseNestedMeta; use syn::parse::ParseStream; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{token, Ident, Lifetime, Token}; // This module handles parsing of `#[serde(...)]` attributes. The entrypoints // are `attr::Container::from_ast`, `attr::Variant::from_ast`, and // `attr::Field::from_ast`. Each returns an instance of the corresponding // struct. Note that none of them return a Result. Unrecognized, malformed, or // duplicated attributes result in a span_err but otherwise are ignored. The // user will see errors simultaneously for all bad attributes in the crate // rather than just the first. pub use crate::internals::case::RenameRule; pub(crate) struct Attr<'c, T> { cx: &'c Ctxt, name: Symbol, tokens: TokenStream, value: Option, } impl<'c, T> Attr<'c, T> { fn none(cx: &'c Ctxt, name: Symbol) -> Self { Attr { cx, name, tokens: TokenStream::new(), value: None, } } fn set(&mut self, obj: A, value: T) { let tokens = obj.into_token_stream(); if self.value.is_some() { let msg = format!("duplicate serde attribute `{}`", self.name); self.cx.error_spanned_by(tokens, msg); } else { self.tokens = tokens; self.value = Some(value); } } fn set_opt(&mut self, obj: A, value: Option) { if let Some(value) = value { self.set(obj, value); } } fn set_if_none(&mut self, value: T) { if self.value.is_none() { self.value = Some(value); } } pub(crate) fn get(self) -> Option { self.value } fn get_with_tokens(self) -> Option<(TokenStream, T)> { match self.value { Some(v) => Some((self.tokens, v)), None => None, } } } struct BoolAttr<'c>(Attr<'c, ()>); impl<'c> BoolAttr<'c> { fn none(cx: &'c Ctxt, name: Symbol) -> Self { BoolAttr(Attr::none(cx, name)) } fn set_true(&mut self, obj: A) { self.0.set(obj, ()); } fn get(&self) -> bool { self.0.value.is_some() } } pub(crate) struct VecAttr<'c, T> { cx: &'c Ctxt, name: Symbol, first_dup_tokens: TokenStream, values: Vec, } impl<'c, T> VecAttr<'c, T> { fn none(cx: &'c Ctxt, name: Symbol) -> Self { VecAttr { cx, name, first_dup_tokens: TokenStream::new(), values: Vec::new(), } } fn insert(&mut self, obj: A, value: T) { if self.values.len() == 1 { self.first_dup_tokens = obj.into_token_stream(); } self.values.push(value); } fn at_most_one(mut self) -> Option { if self.values.len() > 1 { let dup_token = self.first_dup_tokens; let msg = format!("duplicate serde attribute `{}`", self.name); self.cx.error_spanned_by(dup_token, msg); None } else { self.values.pop() } } pub(crate) fn get(self) -> Vec { self.values } } fn unraw(ident: &Ident) -> Ident { Ident::new(ident.to_string().trim_start_matches("r#"), ident.span()) } #[derive(Copy, Clone)] pub struct RenameAllRules { pub serialize: RenameRule, pub deserialize: RenameRule, } impl RenameAllRules { /// Returns a new `RenameAllRules` with the individual rules of `self` and /// `other_rules` joined by `RenameRules::or`. pub fn or(self, other_rules: Self) -> Self { Self { serialize: self.serialize.or(other_rules.serialize), deserialize: self.deserialize.or(other_rules.deserialize), } } } /// Represents struct or enum attribute information. pub struct Container { name: MultiName, transparent: bool, deny_unknown_fields: bool, default: Default, rename_all_rules: RenameAllRules, rename_all_fields_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, tag: TagType, type_from: Option, type_try_from: Option, type_into: Option, remote: Option, identifier: Identifier, serde_path: Option, is_packed: bool, /// Error message generated when type can't be deserialized expecting: Option, non_exhaustive: bool, } /// Styles of representing an enum. pub enum TagType { /// The default. /// /// ```json /// {"variant1": {"key1": "value1", "key2": "value2"}} /// ``` External, /// `#[serde(tag = "type")]` /// /// ```json /// {"type": "variant1", "key1": "value1", "key2": "value2"} /// ``` Internal { tag: String }, /// `#[serde(tag = "t", content = "c")]` /// /// ```json /// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}} /// ``` Adjacent { tag: String, content: String }, /// `#[serde(untagged)]` /// /// ```json /// {"key1": "value1", "key2": "value2"} /// ``` None, } /// Whether this enum represents the fields of a struct or the variants of an /// enum. #[derive(Copy, Clone)] pub enum Identifier { /// It does not. No, /// This enum represents the fields of a struct. All of the variants must be /// unit variants, except possibly one which is annotated with /// `#[serde(other)]` and is a newtype variant. Field, /// This enum represents the variants of an enum. All of the variants must /// be unit variants. Variant, } impl Identifier { #[cfg(feature = "deserialize_in_place")] pub fn is_some(self) -> bool { match self { Identifier::No => false, Identifier::Field | Identifier::Variant => true, } } } impl Container { /// Extract out the `#[serde(...)]` attributes from an item. pub fn from_ast(cx: &Ctxt, item: &syn::DeriveInput) -> Self { let mut ser_name = Attr::none(cx, RENAME); let mut de_name = Attr::none(cx, RENAME); let mut transparent = BoolAttr::none(cx, TRANSPARENT); let mut deny_unknown_fields = BoolAttr::none(cx, DENY_UNKNOWN_FIELDS); let mut default = Attr::none(cx, DEFAULT); let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); let mut rename_all_fields_ser_rule = Attr::none(cx, RENAME_ALL_FIELDS); let mut rename_all_fields_de_rule = Attr::none(cx, RENAME_ALL_FIELDS); let mut ser_bound = Attr::none(cx, BOUND); let mut de_bound = Attr::none(cx, BOUND); let mut untagged = BoolAttr::none(cx, UNTAGGED); let mut internal_tag = Attr::none(cx, TAG); let mut content = Attr::none(cx, CONTENT); let mut type_from = Attr::none(cx, FROM); let mut type_try_from = Attr::none(cx, TRY_FROM); let mut type_into = Attr::none(cx, INTO); let mut remote = Attr::none(cx, REMOTE); let mut field_identifier = BoolAttr::none(cx, FIELD_IDENTIFIER); let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER); let mut serde_path = Attr::none(cx, CRATE); let mut expecting = Attr::none(cx, EXPECTING); let mut non_exhaustive = false; for attr in &item.attrs { if attr.path() != SERDE { non_exhaustive |= matches!(&attr.meta, syn::Meta::Path(path) if path == NON_EXHAUSTIVE); continue; } if let syn::Meta::List(meta) = &attr.meta { if meta.tokens.is_empty() { continue; } } if let Err(err) = attr.parse_nested_meta(|meta| { if meta.path == RENAME { // #[serde(rename = "foo")] // #[serde(rename(serialize = "foo", deserialize = "bar"))] let (ser, de) = get_renames(cx, RENAME, &meta)?; ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); de_name.set_opt(&meta.path, de.as_ref().map(Name::from)); } else if meta.path == RENAME_ALL { // #[serde(rename_all = "foo")] // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] let one_name = meta.input.peek(Token![=]); let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; if let Some(ser) = ser { match RenameRule::from_str(&ser.value()) { Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), Err(err) => cx.error_spanned_by(ser, err), } } if let Some(de) = de { match RenameRule::from_str(&de.value()) { Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), Err(err) => { if !one_name { cx.error_spanned_by(de, err); } } } } } else if meta.path == RENAME_ALL_FIELDS { // #[serde(rename_all_fields = "foo")] // #[serde(rename_all_fields(serialize = "foo", deserialize = "bar"))] let one_name = meta.input.peek(Token![=]); let (ser, de) = get_renames(cx, RENAME_ALL_FIELDS, &meta)?; match item.data { syn::Data::Enum(_) => { if let Some(ser) = ser { match RenameRule::from_str(&ser.value()) { Ok(rename_rule) => { rename_all_fields_ser_rule.set(&meta.path, rename_rule); } Err(err) => cx.error_spanned_by(ser, err), } } if let Some(de) = de { match RenameRule::from_str(&de.value()) { Ok(rename_rule) => { rename_all_fields_de_rule.set(&meta.path, rename_rule); } Err(err) => { if !one_name { cx.error_spanned_by(de, err); } } } } } syn::Data::Struct(_) => { let msg = "#[serde(rename_all_fields)] can only be used on enums"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(rename_all_fields)] can only be used on enums"; cx.syn_error(meta.error(msg)); } } } else if meta.path == TRANSPARENT { // #[serde(transparent)] transparent.set_true(meta.path); } else if meta.path == DENY_UNKNOWN_FIELDS { // #[serde(deny_unknown_fields)] deny_unknown_fields.set_true(meta.path); } else if meta.path == DEFAULT { if meta.input.peek(Token![=]) { // #[serde(default = "...")] if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { match &item.data { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { default.set(&meta.path, Default::Path(path)); } syn::Fields::Unit => { let msg = "#[serde(default = \"...\")] can only be used on structs that have fields"; cx.syn_error(meta.error(msg)); } }, syn::Data::Enum(_) => { let msg = "#[serde(default = \"...\")] can only be used on structs"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(default = \"...\")] can only be used on structs"; cx.syn_error(meta.error(msg)); } } } } else { // #[serde(default)] match &item.data { syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) | syn::Fields::Unnamed(_) => { default.set(meta.path, Default::Default); } syn::Fields::Unit => { let msg = "#[serde(default)] can only be used on structs that have fields"; cx.error_spanned_by(fields, msg); } }, syn::Data::Enum(_) => { let msg = "#[serde(default)] can only be used on structs"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(default)] can only be used on structs"; cx.syn_error(meta.error(msg)); } } } } else if meta.path == BOUND { // #[serde(bound = "T: SomeBound")] // #[serde(bound(serialize = "...", deserialize = "..."))] let (ser, de) = get_where_predicates(cx, &meta)?; ser_bound.set_opt(&meta.path, ser); de_bound.set_opt(&meta.path, de); } else if meta.path == UNTAGGED { // #[serde(untagged)] match item.data { syn::Data::Enum(_) => { untagged.set_true(&meta.path); } syn::Data::Struct(_) => { let msg = "#[serde(untagged)] can only be used on enums"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(untagged)] can only be used on enums"; cx.syn_error(meta.error(msg)); } } } else if meta.path == TAG { // #[serde(tag = "type")] if let Some(s) = get_lit_str(cx, TAG, &meta)? { match &item.data { syn::Data::Enum(_) => { internal_tag.set(&meta.path, s.value()); } syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields { syn::Fields::Named(_) => { internal_tag.set(&meta.path, s.value()); } syn::Fields::Unnamed(_) | syn::Fields::Unit => { let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields"; cx.syn_error(meta.error(msg)); } }, syn::Data::Union(_) => { let msg = "#[serde(tag = \"...\")] can only be used on enums and structs with named fields"; cx.syn_error(meta.error(msg)); } } } } else if meta.path == CONTENT { // #[serde(content = "c")] if let Some(s) = get_lit_str(cx, CONTENT, &meta)? { match &item.data { syn::Data::Enum(_) => { content.set(&meta.path, s.value()); } syn::Data::Struct(_) => { let msg = "#[serde(content = \"...\")] can only be used on enums"; cx.syn_error(meta.error(msg)); } syn::Data::Union(_) => { let msg = "#[serde(content = \"...\")] can only be used on enums"; cx.syn_error(meta.error(msg)); } } } } else if meta.path == FROM { // #[serde(from = "Type")] if let Some(from_ty) = parse_lit_into_ty(cx, FROM, &meta)? { type_from.set_opt(&meta.path, Some(from_ty)); } } else if meta.path == TRY_FROM { // #[serde(try_from = "Type")] if let Some(try_from_ty) = parse_lit_into_ty(cx, TRY_FROM, &meta)? { type_try_from.set_opt(&meta.path, Some(try_from_ty)); } } else if meta.path == INTO { // #[serde(into = "Type")] if let Some(into_ty) = parse_lit_into_ty(cx, INTO, &meta)? { type_into.set_opt(&meta.path, Some(into_ty)); } } else if meta.path == REMOTE { // #[serde(remote = "...")] if let Some(path) = parse_lit_into_path(cx, REMOTE, &meta)? { if is_primitive_path(&path, "Self") { remote.set(&meta.path, item.ident.clone().into()); } else { remote.set(&meta.path, path); } } } else if meta.path == FIELD_IDENTIFIER { // #[serde(field_identifier)] field_identifier.set_true(&meta.path); } else if meta.path == VARIANT_IDENTIFIER { // #[serde(variant_identifier)] variant_identifier.set_true(&meta.path); } else if meta.path == CRATE { // #[serde(crate = "foo")] if let Some(path) = parse_lit_into_path(cx, CRATE, &meta)? { serde_path.set(&meta.path, path); } } else if meta.path == EXPECTING { // #[serde(expecting = "a message")] if let Some(s) = get_lit_str(cx, EXPECTING, &meta)? { expecting.set(&meta.path, s.value()); } } else { let path = meta.path.to_token_stream().to_string().replace(' ', ""); return Err( meta.error(format_args!("unknown serde container attribute `{}`", path)) ); } Ok(()) }) { cx.syn_error(err); } } let mut is_packed = false; for attr in &item.attrs { if attr.path() == REPR { let _ = attr.parse_args_with(|input: ParseStream| { while let Some(token) = input.parse()? { if let TokenTree::Ident(ident) = token { is_packed |= ident == "packed"; } } Ok(()) }); } } Container { name: MultiName::from_attrs(Name::from(&unraw(&item.ident)), ser_name, de_name, None), transparent: transparent.get(), deny_unknown_fields: deny_unknown_fields.get(), default: default.get().unwrap_or(Default::None), rename_all_rules: RenameAllRules { serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), }, rename_all_fields_rules: RenameAllRules { serialize: rename_all_fields_ser_rule.get().unwrap_or(RenameRule::None), deserialize: rename_all_fields_de_rule.get().unwrap_or(RenameRule::None), }, ser_bound: ser_bound.get(), de_bound: de_bound.get(), tag: decide_tag(cx, item, untagged, internal_tag, content), type_from: type_from.get(), type_try_from: type_try_from.get(), type_into: type_into.get(), remote: remote.get(), identifier: decide_identifier(cx, item, field_identifier, variant_identifier), serde_path: serde_path.get(), is_packed, expecting: expecting.get(), non_exhaustive, } } pub fn name(&self) -> &MultiName { &self.name } pub fn rename_all_rules(&self) -> RenameAllRules { self.rename_all_rules } pub fn rename_all_fields_rules(&self) -> RenameAllRules { self.rename_all_fields_rules } pub fn transparent(&self) -> bool { self.transparent } pub fn deny_unknown_fields(&self) -> bool { self.deny_unknown_fields } pub fn default(&self) -> &Default { &self.default } pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { self.ser_bound.as_ref().map(|vec| &vec[..]) } pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } pub fn tag(&self) -> &TagType { &self.tag } pub fn type_from(&self) -> Option<&syn::Type> { self.type_from.as_ref() } pub fn type_try_from(&self) -> Option<&syn::Type> { self.type_try_from.as_ref() } pub fn type_into(&self) -> Option<&syn::Type> { self.type_into.as_ref() } pub fn remote(&self) -> Option<&syn::Path> { self.remote.as_ref() } pub fn is_packed(&self) -> bool { self.is_packed } pub fn identifier(&self) -> Identifier { self.identifier } pub fn custom_serde_path(&self) -> Option<&syn::Path> { self.serde_path.as_ref() } /// Error message generated when type can't be deserialized. /// If `None`, default message will be used pub fn expecting(&self) -> Option<&str> { self.expecting.as_ref().map(String::as_ref) } pub fn non_exhaustive(&self) -> bool { self.non_exhaustive } } fn decide_tag( cx: &Ctxt, item: &syn::DeriveInput, untagged: BoolAttr, internal_tag: Attr, content: Attr, ) -> TagType { match ( untagged.0.get_with_tokens(), internal_tag.get_with_tokens(), content.get_with_tokens(), ) { (None, None, None) => TagType::External, (Some(_), None, None) => TagType::None, (None, Some((_, tag)), None) => { // Check that there are no tuple variants. if let syn::Data::Enum(data) = &item.data { for variant in &data.variants { match &variant.fields { syn::Fields::Named(_) | syn::Fields::Unit => {} syn::Fields::Unnamed(fields) => { if fields.unnamed.len() != 1 { let msg = "#[serde(tag = \"...\")] cannot be used with tuple variants"; cx.error_spanned_by(variant, msg); break; } } } } } TagType::Internal { tag } } (Some((untagged_tokens, ())), Some((tag_tokens, _)), None) => { let msg = "enum cannot be both untagged and internally tagged"; cx.error_spanned_by(untagged_tokens, msg); cx.error_spanned_by(tag_tokens, msg); TagType::External // doesn't matter, will error } (None, None, Some((content_tokens, _))) => { let msg = "#[serde(tag = \"...\", content = \"...\")] must be used together"; cx.error_spanned_by(content_tokens, msg); TagType::External } (Some((untagged_tokens, ())), None, Some((content_tokens, _))) => { let msg = "untagged enum cannot have #[serde(content = \"...\")]"; cx.error_spanned_by(untagged_tokens, msg); cx.error_spanned_by(content_tokens, msg); TagType::External } (None, Some((_, tag)), Some((_, content))) => TagType::Adjacent { tag, content }, (Some((untagged_tokens, ())), Some((tag_tokens, _)), Some((content_tokens, _))) => { let msg = "untagged enum cannot have #[serde(tag = \"...\", content = \"...\")]"; cx.error_spanned_by(untagged_tokens, msg); cx.error_spanned_by(tag_tokens, msg); cx.error_spanned_by(content_tokens, msg); TagType::External } } } fn decide_identifier( cx: &Ctxt, item: &syn::DeriveInput, field_identifier: BoolAttr, variant_identifier: BoolAttr, ) -> Identifier { match ( &item.data, field_identifier.0.get_with_tokens(), variant_identifier.0.get_with_tokens(), ) { (_, None, None) => Identifier::No, (_, Some((field_identifier_tokens, ())), Some((variant_identifier_tokens, ()))) => { let msg = "#[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set"; cx.error_spanned_by(field_identifier_tokens, msg); cx.error_spanned_by(variant_identifier_tokens, msg); Identifier::No } (syn::Data::Enum(_), Some(_), None) => Identifier::Field, (syn::Data::Enum(_), None, Some(_)) => Identifier::Variant, (syn::Data::Struct(syn::DataStruct { struct_token, .. }), Some(_), None) => { let msg = "#[serde(field_identifier)] can only be used on an enum"; cx.error_spanned_by(struct_token, msg); Identifier::No } (syn::Data::Union(syn::DataUnion { union_token, .. }), Some(_), None) => { let msg = "#[serde(field_identifier)] can only be used on an enum"; cx.error_spanned_by(union_token, msg); Identifier::No } (syn::Data::Struct(syn::DataStruct { struct_token, .. }), None, Some(_)) => { let msg = "#[serde(variant_identifier)] can only be used on an enum"; cx.error_spanned_by(struct_token, msg); Identifier::No } (syn::Data::Union(syn::DataUnion { union_token, .. }), None, Some(_)) => { let msg = "#[serde(variant_identifier)] can only be used on an enum"; cx.error_spanned_by(union_token, msg); Identifier::No } } } /// Represents variant attribute information pub struct Variant { name: MultiName, rename_all_rules: RenameAllRules, ser_bound: Option>, de_bound: Option>, skip_deserializing: bool, skip_serializing: bool, other: bool, serialize_with: Option, deserialize_with: Option, borrow: Option, untagged: bool, } struct BorrowAttribute { path: syn::Path, lifetimes: Option>, } impl Variant { pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self { let mut ser_name = Attr::none(cx, RENAME); let mut de_name = Attr::none(cx, RENAME); let mut de_aliases = VecAttr::none(cx, RENAME); let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING); let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING); let mut rename_all_ser_rule = Attr::none(cx, RENAME_ALL); let mut rename_all_de_rule = Attr::none(cx, RENAME_ALL); let mut ser_bound = Attr::none(cx, BOUND); let mut de_bound = Attr::none(cx, BOUND); let mut other = BoolAttr::none(cx, OTHER); let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); let mut borrow = Attr::none(cx, BORROW); let mut untagged = BoolAttr::none(cx, UNTAGGED); for attr in &variant.attrs { if attr.path() != SERDE { continue; } if let syn::Meta::List(meta) = &attr.meta { if meta.tokens.is_empty() { continue; } } if let Err(err) = attr.parse_nested_meta(|meta| { if meta.path == RENAME { // #[serde(rename = "foo")] // #[serde(rename(serialize = "foo", deserialize = "bar"))] let (ser, de) = get_multiple_renames(cx, &meta)?; ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); for de_value in de { de_name.set_if_none(Name::from(&de_value)); de_aliases.insert(&meta.path, Name::from(&de_value)); } } else if meta.path == ALIAS { // #[serde(alias = "foo")] if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { de_aliases.insert(&meta.path, Name::from(&s)); } } else if meta.path == RENAME_ALL { // #[serde(rename_all = "foo")] // #[serde(rename_all(serialize = "foo", deserialize = "bar"))] let one_name = meta.input.peek(Token![=]); let (ser, de) = get_renames(cx, RENAME_ALL, &meta)?; if let Some(ser) = ser { match RenameRule::from_str(&ser.value()) { Ok(rename_rule) => rename_all_ser_rule.set(&meta.path, rename_rule), Err(err) => cx.error_spanned_by(ser, err), } } if let Some(de) = de { match RenameRule::from_str(&de.value()) { Ok(rename_rule) => rename_all_de_rule.set(&meta.path, rename_rule), Err(err) => { if !one_name { cx.error_spanned_by(de, err); } } } } } else if meta.path == SKIP { // #[serde(skip)] skip_serializing.set_true(&meta.path); skip_deserializing.set_true(&meta.path); } else if meta.path == SKIP_DESERIALIZING { // #[serde(skip_deserializing)] skip_deserializing.set_true(&meta.path); } else if meta.path == SKIP_SERIALIZING { // #[serde(skip_serializing)] skip_serializing.set_true(&meta.path); } else if meta.path == OTHER { // #[serde(other)] other.set_true(&meta.path); } else if meta.path == BOUND { // #[serde(bound = "T: SomeBound")] // #[serde(bound(serialize = "...", deserialize = "..."))] let (ser, de) = get_where_predicates(cx, &meta)?; ser_bound.set_opt(&meta.path, ser); de_bound.set_opt(&meta.path, de); } else if meta.path == WITH { // #[serde(with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { let mut ser_path = path.clone(); ser_path .path .segments .push(Ident::new("serialize", ser_path.span()).into()); serialize_with.set(&meta.path, ser_path); let mut de_path = path; de_path .path .segments .push(Ident::new("deserialize", de_path.span()).into()); deserialize_with.set(&meta.path, de_path); } } else if meta.path == SERIALIZE_WITH { // #[serde(serialize_with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { serialize_with.set(&meta.path, path); } } else if meta.path == DESERIALIZE_WITH { // #[serde(deserialize_with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { deserialize_with.set(&meta.path, path); } } else if meta.path == BORROW { let borrow_attribute = if meta.input.peek(Token![=]) { // #[serde(borrow = "'a + 'b")] let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; BorrowAttribute { path: meta.path.clone(), lifetimes: Some(lifetimes), } } else { // #[serde(borrow)] BorrowAttribute { path: meta.path.clone(), lifetimes: None, } }; match &variant.fields { syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { borrow.set(&meta.path, borrow_attribute); } _ => { let msg = "#[serde(borrow)] may only be used on newtype variants"; cx.error_spanned_by(variant, msg); } } } else if meta.path == UNTAGGED { untagged.set_true(&meta.path); } else { let path = meta.path.to_token_stream().to_string().replace(' ', ""); return Err( meta.error(format_args!("unknown serde variant attribute `{}`", path)) ); } Ok(()) }) { cx.syn_error(err); } } Variant { name: MultiName::from_attrs( Name::from(&unraw(&variant.ident)), ser_name, de_name, Some(de_aliases), ), rename_all_rules: RenameAllRules { serialize: rename_all_ser_rule.get().unwrap_or(RenameRule::None), deserialize: rename_all_de_rule.get().unwrap_or(RenameRule::None), }, ser_bound: ser_bound.get(), de_bound: de_bound.get(), skip_deserializing: skip_deserializing.get(), skip_serializing: skip_serializing.get(), other: other.get(), serialize_with: serialize_with.get(), deserialize_with: deserialize_with.get(), borrow: borrow.get(), untagged: untagged.get(), } } pub fn name(&self) -> &MultiName { &self.name } pub fn aliases(&self) -> &BTreeSet { self.name.deserialize_aliases() } pub fn rename_by_rules(&mut self, rules: RenameAllRules) { if !self.name.serialize_renamed { self.name.serialize.value = rules.serialize.apply_to_variant(&self.name.serialize.value); } if !self.name.deserialize_renamed { self.name.deserialize.value = rules .deserialize .apply_to_variant(&self.name.deserialize.value); } self.name .deserialize_aliases .insert(self.name.deserialize.clone()); } pub fn rename_all_rules(&self) -> RenameAllRules { self.rename_all_rules } pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { self.ser_bound.as_ref().map(|vec| &vec[..]) } pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } pub fn skip_deserializing(&self) -> bool { self.skip_deserializing } pub fn skip_serializing(&self) -> bool { self.skip_serializing } pub fn other(&self) -> bool { self.other } pub fn serialize_with(&self) -> Option<&syn::ExprPath> { self.serialize_with.as_ref() } pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { self.deserialize_with.as_ref() } pub fn untagged(&self) -> bool { self.untagged } } /// Represents field attribute information pub struct Field { name: MultiName, skip_serializing: bool, skip_deserializing: bool, skip_serializing_if: Option, default: Default, serialize_with: Option, deserialize_with: Option, ser_bound: Option>, de_bound: Option>, borrowed_lifetimes: BTreeSet, getter: Option, flatten: bool, transparent: bool, } /// Represents the default to use for a field when deserializing. pub enum Default { /// Field must always be specified because it does not have a default. None, /// The default is given by `std::default::Default::default()`. Default, /// The default is given by this function. Path(syn::ExprPath), } impl Default { pub fn is_none(&self) -> bool { match self { Default::None => true, Default::Default | Default::Path(_) => false, } } } impl Field { /// Extract out the `#[serde(...)]` attributes from a struct field. pub fn from_ast( cx: &Ctxt, index: usize, field: &syn::Field, attrs: Option<&Variant>, container_default: &Default, private: &Ident, ) -> Self { let mut ser_name = Attr::none(cx, RENAME); let mut de_name = Attr::none(cx, RENAME); let mut de_aliases = VecAttr::none(cx, RENAME); let mut skip_serializing = BoolAttr::none(cx, SKIP_SERIALIZING); let mut skip_deserializing = BoolAttr::none(cx, SKIP_DESERIALIZING); let mut skip_serializing_if = Attr::none(cx, SKIP_SERIALIZING_IF); let mut default = Attr::none(cx, DEFAULT); let mut serialize_with = Attr::none(cx, SERIALIZE_WITH); let mut deserialize_with = Attr::none(cx, DESERIALIZE_WITH); let mut ser_bound = Attr::none(cx, BOUND); let mut de_bound = Attr::none(cx, BOUND); let mut borrowed_lifetimes = Attr::none(cx, BORROW); let mut getter = Attr::none(cx, GETTER); let mut flatten = BoolAttr::none(cx, FLATTEN); let ident = match &field.ident { Some(ident) => Name::from(&unraw(ident)), None => Name { value: index.to_string(), span: Span::call_site(), }, }; if let Some(borrow_attribute) = attrs.and_then(|variant| variant.borrow.as_ref()) { if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { if let Some(lifetimes) = &borrow_attribute.lifetimes { for lifetime in lifetimes { if !borrowable.contains(lifetime) { let msg = format!("field `{}` does not have lifetime {}", ident, lifetime); cx.error_spanned_by(field, msg); } } borrowed_lifetimes.set(&borrow_attribute.path, lifetimes.clone()); } else { borrowed_lifetimes.set(&borrow_attribute.path, borrowable); } } } for attr in &field.attrs { if attr.path() != SERDE { continue; } if let syn::Meta::List(meta) = &attr.meta { if meta.tokens.is_empty() { continue; } } if let Err(err) = attr.parse_nested_meta(|meta| { if meta.path == RENAME { // #[serde(rename = "foo")] // #[serde(rename(serialize = "foo", deserialize = "bar"))] let (ser, de) = get_multiple_renames(cx, &meta)?; ser_name.set_opt(&meta.path, ser.as_ref().map(Name::from)); for de_value in de { de_name.set_if_none(Name::from(&de_value)); de_aliases.insert(&meta.path, Name::from(&de_value)); } } else if meta.path == ALIAS { // #[serde(alias = "foo")] if let Some(s) = get_lit_str(cx, ALIAS, &meta)? { de_aliases.insert(&meta.path, Name::from(&s)); } } else if meta.path == DEFAULT { if meta.input.peek(Token![=]) { // #[serde(default = "...")] if let Some(path) = parse_lit_into_expr_path(cx, DEFAULT, &meta)? { default.set(&meta.path, Default::Path(path)); } } else { // #[serde(default)] default.set(&meta.path, Default::Default); } } else if meta.path == SKIP_SERIALIZING { // #[serde(skip_serializing)] skip_serializing.set_true(&meta.path); } else if meta.path == SKIP_DESERIALIZING { // #[serde(skip_deserializing)] skip_deserializing.set_true(&meta.path); } else if meta.path == SKIP { // #[serde(skip)] skip_serializing.set_true(&meta.path); skip_deserializing.set_true(&meta.path); } else if meta.path == SKIP_SERIALIZING_IF { // #[serde(skip_serializing_if = "...")] if let Some(path) = parse_lit_into_expr_path(cx, SKIP_SERIALIZING_IF, &meta)? { skip_serializing_if.set(&meta.path, path); } } else if meta.path == SERIALIZE_WITH { // #[serde(serialize_with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, SERIALIZE_WITH, &meta)? { serialize_with.set(&meta.path, path); } } else if meta.path == DESERIALIZE_WITH { // #[serde(deserialize_with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, DESERIALIZE_WITH, &meta)? { deserialize_with.set(&meta.path, path); } } else if meta.path == WITH { // #[serde(with = "...")] if let Some(path) = parse_lit_into_expr_path(cx, WITH, &meta)? { let mut ser_path = path.clone(); ser_path .path .segments .push(Ident::new("serialize", ser_path.span()).into()); serialize_with.set(&meta.path, ser_path); let mut de_path = path; de_path .path .segments .push(Ident::new("deserialize", de_path.span()).into()); deserialize_with.set(&meta.path, de_path); } } else if meta.path == BOUND { // #[serde(bound = "T: SomeBound")] // #[serde(bound(serialize = "...", deserialize = "..."))] let (ser, de) = get_where_predicates(cx, &meta)?; ser_bound.set_opt(&meta.path, ser); de_bound.set_opt(&meta.path, de); } else if meta.path == BORROW { if meta.input.peek(Token![=]) { // #[serde(borrow = "'a + 'b")] let lifetimes = parse_lit_into_lifetimes(cx, &meta)?; if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { for lifetime in &lifetimes { if !borrowable.contains(lifetime) { let msg = format!( "field `{}` does not have lifetime {}", ident, lifetime, ); cx.error_spanned_by(field, msg); } } borrowed_lifetimes.set(&meta.path, lifetimes); } } else { // #[serde(borrow)] if let Ok(borrowable) = borrowable_lifetimes(cx, &ident, field) { borrowed_lifetimes.set(&meta.path, borrowable); } } } else if meta.path == GETTER { // #[serde(getter = "...")] if let Some(path) = parse_lit_into_expr_path(cx, GETTER, &meta)? { getter.set(&meta.path, path); } } else if meta.path == FLATTEN { // #[serde(flatten)] flatten.set_true(&meta.path); } else { let path = meta.path.to_token_stream().to_string().replace(' ', ""); return Err( meta.error(format_args!("unknown serde field attribute `{}`", path)) ); } Ok(()) }) { cx.syn_error(err); } } // If skip_deserializing, initialize the field to Default::default() unless a // different default is specified by `#[serde(default = "...")]` on // ourselves or our container (e.g. the struct we are in). if container_default.is_none() && skip_deserializing.0.value.is_some() { default.set_if_none(Default::Default); } let mut borrowed_lifetimes = borrowed_lifetimes.get().unwrap_or_default(); if !borrowed_lifetimes.is_empty() { // Cow and Cow<[u8]> never borrow by default: // // impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T> // // A #[serde(borrow)] attribute enables borrowing that corresponds // roughly to these impls: // // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, str> // impl<'de: 'a, 'a> Deserialize<'de> for Cow<'a, [u8]> if is_cow(&field.ty, is_str) { let mut path = syn::Path { leading_colon: None, segments: Punctuated::new(), }; let span = Span::call_site(); path.segments.push(Ident::new("_serde", span).into()); path.segments.push(private.clone().into()); path.segments.push(Ident::new("de", span).into()); path.segments .push(Ident::new("borrow_cow_str", span).into()); let expr = syn::ExprPath { attrs: Vec::new(), qself: None, path, }; deserialize_with.set_if_none(expr); } else if is_cow(&field.ty, is_slice_u8) { let mut path = syn::Path { leading_colon: None, segments: Punctuated::new(), }; let span = Span::call_site(); path.segments.push(Ident::new("_serde", span).into()); path.segments.push(private.clone().into()); path.segments.push(Ident::new("de", span).into()); path.segments .push(Ident::new("borrow_cow_bytes", span).into()); let expr = syn::ExprPath { attrs: Vec::new(), qself: None, path, }; deserialize_with.set_if_none(expr); } } else if is_implicitly_borrowed(&field.ty) { // Types &str and &[u8] are always implicitly borrowed. No need for // a #[serde(borrow)]. collect_lifetimes(&field.ty, &mut borrowed_lifetimes); } Field { name: MultiName::from_attrs(ident, ser_name, de_name, Some(de_aliases)), skip_serializing: skip_serializing.get(), skip_deserializing: skip_deserializing.get(), skip_serializing_if: skip_serializing_if.get(), default: default.get().unwrap_or(Default::None), serialize_with: serialize_with.get(), deserialize_with: deserialize_with.get(), ser_bound: ser_bound.get(), de_bound: de_bound.get(), borrowed_lifetimes, getter: getter.get(), flatten: flatten.get(), transparent: false, } } pub fn name(&self) -> &MultiName { &self.name } pub fn aliases(&self) -> &BTreeSet { self.name.deserialize_aliases() } pub fn rename_by_rules(&mut self, rules: RenameAllRules) { if !self.name.serialize_renamed { self.name.serialize.value = rules.serialize.apply_to_field(&self.name.serialize.value); } if !self.name.deserialize_renamed { self.name.deserialize.value = rules .deserialize .apply_to_field(&self.name.deserialize.value); } self.name .deserialize_aliases .insert(self.name.deserialize.clone()); } pub fn skip_serializing(&self) -> bool { self.skip_serializing } pub fn skip_deserializing(&self) -> bool { self.skip_deserializing } pub fn skip_serializing_if(&self) -> Option<&syn::ExprPath> { self.skip_serializing_if.as_ref() } pub fn default(&self) -> &Default { &self.default } pub fn serialize_with(&self) -> Option<&syn::ExprPath> { self.serialize_with.as_ref() } pub fn deserialize_with(&self) -> Option<&syn::ExprPath> { self.deserialize_with.as_ref() } pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> { self.ser_bound.as_ref().map(|vec| &vec[..]) } pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> { self.de_bound.as_ref().map(|vec| &vec[..]) } pub fn borrowed_lifetimes(&self) -> &BTreeSet { &self.borrowed_lifetimes } pub fn getter(&self) -> Option<&syn::ExprPath> { self.getter.as_ref() } pub fn flatten(&self) -> bool { self.flatten } pub fn transparent(&self) -> bool { self.transparent } pub fn mark_transparent(&mut self) { self.transparent = true; } } type SerAndDe = (Option, Option); fn get_ser_and_de<'c, T, F, R>( cx: &'c Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, f: F, ) -> syn::Result<(VecAttr<'c, T>, VecAttr<'c, T>)> where T: Clone, F: Fn(&Ctxt, Symbol, Symbol, &ParseNestedMeta) -> syn::Result, R: Into>, { let mut ser_meta = VecAttr::none(cx, attr_name); let mut de_meta = VecAttr::none(cx, attr_name); let lookahead = meta.input.lookahead1(); if lookahead.peek(Token![=]) { if let Some(both) = f(cx, attr_name, attr_name, meta)?.into() { ser_meta.insert(&meta.path, both.clone()); de_meta.insert(&meta.path, both); } } else if lookahead.peek(token::Paren) { meta.parse_nested_meta(|meta| { if meta.path == SERIALIZE { if let Some(v) = f(cx, attr_name, SERIALIZE, &meta)?.into() { ser_meta.insert(&meta.path, v); } } else if meta.path == DESERIALIZE { if let Some(v) = f(cx, attr_name, DESERIALIZE, &meta)?.into() { de_meta.insert(&meta.path, v); } } else { return Err(meta.error(format_args!( "malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`", attr_name, ))); } Ok(()) })?; } else { return Err(lookahead.error()); } Ok((ser_meta, de_meta)) } fn get_renames( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let (ser, de) = get_ser_and_de(cx, attr_name, meta, get_lit_str2)?; Ok((ser.at_most_one(), de.at_most_one())) } fn get_multiple_renames( cx: &Ctxt, meta: &ParseNestedMeta, ) -> syn::Result<(Option, Vec)> { let (ser, de) = get_ser_and_de(cx, RENAME, meta, get_lit_str2)?; Ok((ser.at_most_one(), de.get())) } fn get_where_predicates( cx: &Ctxt, meta: &ParseNestedMeta, ) -> syn::Result>> { let (ser, de) = get_ser_and_de(cx, BOUND, meta, parse_lit_into_where)?; Ok((ser.at_most_one(), de.at_most_one())) } fn get_lit_str( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { get_lit_str2(cx, attr_name, attr_name, meta) } fn get_lit_str2( cx: &Ctxt, attr_name: Symbol, meta_item_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let expr: syn::Expr = meta.value()?.parse()?; let mut value = &expr; while let syn::Expr::Group(e) = value { value = &e.expr; } if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit), .. }) = value { let suffix = lit.suffix(); if !suffix.is_empty() { cx.error_spanned_by( lit, format!("unexpected suffix `{}` on string literal", suffix), ); } Ok(Some(lit.clone())) } else { cx.error_spanned_by( expr, format!( "expected serde {} attribute to be a string: `{} = \"...\"`", attr_name, meta_item_name ), ); Ok(None) } } fn parse_lit_into_path( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let Some(string) = get_lit_str(cx, attr_name, meta)? else { return Ok(None); }; Ok(match string.parse() { Ok(path) => Some(path), Err(_) => { cx.error_spanned_by( &string, format!("failed to parse path: {:?}", string.value()), ); None } }) } fn parse_lit_into_expr_path( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let Some(string) = get_lit_str(cx, attr_name, meta)? else { return Ok(None); }; Ok(match string.parse() { Ok(expr) => Some(expr), Err(_) => { cx.error_spanned_by( &string, format!("failed to parse path: {:?}", string.value()), ); None } }) } fn parse_lit_into_where( cx: &Ctxt, attr_name: Symbol, meta_item_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let Some(string) = get_lit_str2(cx, attr_name, meta_item_name, meta)? else { return Ok(Vec::new()); }; Ok( match string.parse_with(Punctuated::::parse_terminated) { Ok(predicates) => Vec::from_iter(predicates), Err(err) => { cx.error_spanned_by(string, err); Vec::new() } }, ) } fn parse_lit_into_ty( cx: &Ctxt, attr_name: Symbol, meta: &ParseNestedMeta, ) -> syn::Result> { let Some(string) = get_lit_str(cx, attr_name, meta)? else { return Ok(None); }; Ok(match string.parse() { Ok(ty) => Some(ty), Err(_) => { cx.error_spanned_by( &string, format!("failed to parse type: {} = {:?}", attr_name, string.value()), ); None } }) } // Parses a string literal like "'a + 'b + 'c" containing a nonempty list of // lifetimes separated by `+`. fn parse_lit_into_lifetimes( cx: &Ctxt, meta: &ParseNestedMeta, ) -> syn::Result> { let Some(string) = get_lit_str(cx, BORROW, meta)? else { return Ok(BTreeSet::new()); }; if let Ok(lifetimes) = string.parse_with(|input: ParseStream| { let mut set = BTreeSet::new(); while !input.is_empty() { let lifetime: Lifetime = input.parse()?; if !set.insert(lifetime.clone()) { cx.error_spanned_by( &string, format!("duplicate borrowed lifetime `{}`", lifetime), ); } if input.is_empty() { break; } input.parse::()?; } Ok(set) }) { if lifetimes.is_empty() { cx.error_spanned_by(string, "at least one lifetime must be borrowed"); } return Ok(lifetimes); } cx.error_spanned_by( &string, format!("failed to parse borrowed lifetimes: {:?}", string.value()), ); Ok(BTreeSet::new()) } fn is_implicitly_borrowed(ty: &syn::Type) -> bool { is_implicitly_borrowed_reference(ty) || is_option(ty, is_implicitly_borrowed_reference) } fn is_implicitly_borrowed_reference(ty: &syn::Type) -> bool { is_reference(ty, is_str) || is_reference(ty, is_slice_u8) } // Whether the type looks like it might be `std::borrow::Cow` where elem="T". // This can have false negatives and false positives. // // False negative: // // use std::borrow::Cow as Pig; // // #[derive(Deserialize)] // struct S<'a> { // #[serde(borrow)] // pig: Pig<'a, str>, // } // // False positive: // // type str = [i16]; // // #[derive(Deserialize)] // struct S<'a> { // #[serde(borrow)] // cow: Cow<'a, str>, // } fn is_cow(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { let path = match ungroup(ty) { syn::Type::Path(ty) => &ty.path, _ => { return false; } }; let Some(seg) = path.segments.last() else { return false; }; let args = match &seg.arguments { syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args, _ => { return false; } }; seg.ident == "Cow" && args.len() == 2 && match (&args[0], &args[1]) { (syn::GenericArgument::Lifetime(_), syn::GenericArgument::Type(arg)) => elem(arg), _ => false, } } fn is_option(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { let path = match ungroup(ty) { syn::Type::Path(ty) => &ty.path, _ => { return false; } }; let Some(seg) = path.segments.last() else { return false; }; let args = match &seg.arguments { syn::PathArguments::AngleBracketed(bracketed) => &bracketed.args, _ => { return false; } }; seg.ident == "Option" && args.len() == 1 && match &args[0] { syn::GenericArgument::Type(arg) => elem(arg), _ => false, } } // Whether the type looks like it might be `&T` where elem="T". This can have // false negatives and false positives. // // False negative: // // type Yarn = str; // // #[derive(Deserialize)] // struct S<'a> { // r: &'a Yarn, // } // // False positive: // // type str = [i16]; // // #[derive(Deserialize)] // struct S<'a> { // r: &'a str, // } fn is_reference(ty: &syn::Type, elem: fn(&syn::Type) -> bool) -> bool { match ungroup(ty) { syn::Type::Reference(ty) => ty.mutability.is_none() && elem(&ty.elem), _ => false, } } fn is_str(ty: &syn::Type) -> bool { is_primitive_type(ty, "str") } fn is_slice_u8(ty: &syn::Type) -> bool { match ungroup(ty) { syn::Type::Slice(ty) => is_primitive_type(&ty.elem, "u8"), _ => false, } } fn is_primitive_type(ty: &syn::Type, primitive: &str) -> bool { match ungroup(ty) { syn::Type::Path(ty) => ty.qself.is_none() && is_primitive_path(&ty.path, primitive), _ => false, } } fn is_primitive_path(path: &syn::Path, primitive: &str) -> bool { path.leading_colon.is_none() && path.segments.len() == 1 && path.segments[0].ident == primitive && path.segments[0].arguments.is_empty() } // All lifetimes that this type could borrow from a Deserializer. // // For example a type `S<'a, 'b>` could borrow `'a` and `'b`. On the other hand // a type `for<'a> fn(&'a str)` could not borrow `'a` from the Deserializer. // // This is used when there is an explicit or implicit `#[serde(borrow)]` // attribute on the field so there must be at least one borrowable lifetime. fn borrowable_lifetimes( cx: &Ctxt, name: &Name, field: &syn::Field, ) -> Result, ()> { let mut lifetimes = BTreeSet::new(); collect_lifetimes(&field.ty, &mut lifetimes); if lifetimes.is_empty() { let msg = format!("field `{}` has no lifetimes to borrow", name); cx.error_spanned_by(field, msg); Err(()) } else { Ok(lifetimes) } } fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { match ty { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] syn::Type::Slice(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Array(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Ptr(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Reference(ty) => { out.extend(ty.lifetime.iter().cloned()); collect_lifetimes(&ty.elem, out); } syn::Type::Tuple(ty) => { for elem in &ty.elems { collect_lifetimes(elem, out); } } syn::Type::Path(ty) => { if let Some(qself) = &ty.qself { collect_lifetimes(&qself.ty, out); } for seg in &ty.path.segments { if let syn::PathArguments::AngleBracketed(bracketed) = &seg.arguments { for arg in &bracketed.args { match arg { syn::GenericArgument::Lifetime(lifetime) => { out.insert(lifetime.clone()); } syn::GenericArgument::Type(ty) => { collect_lifetimes(ty, out); } syn::GenericArgument::AssocType(binding) => { collect_lifetimes(&binding.ty, out); } syn::GenericArgument::Const(_) | syn::GenericArgument::AssocConst(_) | syn::GenericArgument::Constraint(_) | _ => {} } } } } } syn::Type::Paren(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Group(ty) => { collect_lifetimes(&ty.elem, out); } syn::Type::Macro(ty) => { collect_lifetimes_from_tokens(ty.mac.tokens.clone(), out); } syn::Type::BareFn(_) | syn::Type::Never(_) | syn::Type::TraitObject(_) | syn::Type::ImplTrait(_) | syn::Type::Infer(_) | syn::Type::Verbatim(_) => {} _ => {} } } fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet) { let mut iter = tokens.into_iter(); while let Some(tt) = iter.next() { match &tt { TokenTree::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => { if let Some(TokenTree::Ident(ident)) = iter.next() { out.insert(syn::Lifetime { apostrophe: op.span(), ident, }); } } TokenTree::Group(group) => { let tokens = group.stream(); collect_lifetimes_from_tokens(tokens, out); } _ => {} } } } ================================================ FILE: serde_derive/src/internals/case.rs ================================================ //! Code to convert the Rust-styled field/variant (e.g. `my_field`, `MyType`) to the //! case of the source (e.g. `my-field`, `MY_FIELD`). use self::RenameRule::*; use std::fmt::{self, Debug, Display}; /// The different possible ways to change case of fields in a struct, or variants in an enum. #[derive(Copy, Clone, PartialEq)] pub enum RenameRule { /// Don't apply a default rename rule. None, /// Rename direct children to "lowercase" style. LowerCase, /// Rename direct children to "UPPERCASE" style. UpperCase, /// Rename direct children to "PascalCase" style, as typically used for /// enum variants. PascalCase, /// Rename direct children to "camelCase" style. CamelCase, /// Rename direct children to "snake_case" style, as commonly used for /// fields. SnakeCase, /// Rename direct children to "SCREAMING_SNAKE_CASE" style, as commonly /// used for constants. ScreamingSnakeCase, /// Rename direct children to "kebab-case" style. KebabCase, /// Rename direct children to "SCREAMING-KEBAB-CASE" style. ScreamingKebabCase, } static RENAME_RULES: &[(&str, RenameRule)] = &[ ("lowercase", LowerCase), ("UPPERCASE", UpperCase), ("PascalCase", PascalCase), ("camelCase", CamelCase), ("snake_case", SnakeCase), ("SCREAMING_SNAKE_CASE", ScreamingSnakeCase), ("kebab-case", KebabCase), ("SCREAMING-KEBAB-CASE", ScreamingKebabCase), ]; impl RenameRule { pub fn from_str(rename_all_str: &str) -> Result { for (name, rule) in RENAME_RULES { if rename_all_str == *name { return Ok(*rule); } } Err(ParseError { unknown: rename_all_str, }) } /// Apply a renaming rule to an enum variant, returning the version expected in the source. pub fn apply_to_variant(self, variant: &str) -> String { match self { None | PascalCase => variant.to_owned(), LowerCase => variant.to_ascii_lowercase(), UpperCase => variant.to_ascii_uppercase(), CamelCase => variant[..1].to_ascii_lowercase() + &variant[1..], SnakeCase => { let mut snake = String::new(); for (i, ch) in variant.char_indices() { if i > 0 && ch.is_uppercase() { snake.push('_'); } snake.push(ch.to_ascii_lowercase()); } snake } ScreamingSnakeCase => SnakeCase.apply_to_variant(variant).to_ascii_uppercase(), KebabCase => SnakeCase.apply_to_variant(variant).replace('_', "-"), ScreamingKebabCase => ScreamingSnakeCase .apply_to_variant(variant) .replace('_', "-"), } } /// Apply a renaming rule to a struct field, returning the version expected in the source. pub fn apply_to_field(self, field: &str) -> String { match self { None | LowerCase | SnakeCase => field.to_owned(), UpperCase => field.to_ascii_uppercase(), PascalCase => { let mut pascal = String::new(); let mut capitalize = true; for ch in field.chars() { if ch == '_' { capitalize = true; } else if capitalize { pascal.push(ch.to_ascii_uppercase()); capitalize = false; } else { pascal.push(ch); } } pascal } CamelCase => { let pascal = PascalCase.apply_to_field(field); pascal[..1].to_ascii_lowercase() + &pascal[1..] } ScreamingSnakeCase => field.to_ascii_uppercase(), KebabCase => field.replace('_', "-"), ScreamingKebabCase => ScreamingSnakeCase.apply_to_field(field).replace('_', "-"), } } /// Returns the `RenameRule` if it is not `None`, `rule_b` otherwise. pub fn or(self, rule_b: Self) -> Self { match self { None => rule_b, _ => self, } } } pub struct ParseError<'a> { unknown: &'a str, } impl<'a> Display for ParseError<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("unknown rename rule `rename_all = ")?; Debug::fmt(self.unknown, f)?; f.write_str("`, expected one of ")?; for (i, (name, _rule)) in RENAME_RULES.iter().enumerate() { if i > 0 { f.write_str(", ")?; } Debug::fmt(name, f)?; } Ok(()) } } #[test] fn rename_variants() { for &(original, lower, upper, camel, snake, screaming, kebab, screaming_kebab) in &[ ( "Outcome", "outcome", "OUTCOME", "outcome", "outcome", "OUTCOME", "outcome", "OUTCOME", ), ( "VeryTasty", "verytasty", "VERYTASTY", "veryTasty", "very_tasty", "VERY_TASTY", "very-tasty", "VERY-TASTY", ), ("A", "a", "A", "a", "a", "A", "a", "A"), ("Z42", "z42", "Z42", "z42", "z42", "Z42", "z42", "Z42"), ] { assert_eq!(None.apply_to_variant(original), original); assert_eq!(LowerCase.apply_to_variant(original), lower); assert_eq!(UpperCase.apply_to_variant(original), upper); assert_eq!(PascalCase.apply_to_variant(original), original); assert_eq!(CamelCase.apply_to_variant(original), camel); assert_eq!(SnakeCase.apply_to_variant(original), snake); assert_eq!(ScreamingSnakeCase.apply_to_variant(original), screaming); assert_eq!(KebabCase.apply_to_variant(original), kebab); assert_eq!( ScreamingKebabCase.apply_to_variant(original), screaming_kebab ); } } #[test] fn rename_fields() { for &(original, upper, pascal, camel, screaming, kebab, screaming_kebab) in &[ ( "outcome", "OUTCOME", "Outcome", "outcome", "OUTCOME", "outcome", "OUTCOME", ), ( "very_tasty", "VERY_TASTY", "VeryTasty", "veryTasty", "VERY_TASTY", "very-tasty", "VERY-TASTY", ), ("a", "A", "A", "a", "A", "a", "A"), ("z42", "Z42", "Z42", "z42", "Z42", "z42", "Z42"), ] { assert_eq!(None.apply_to_field(original), original); assert_eq!(UpperCase.apply_to_field(original), upper); assert_eq!(PascalCase.apply_to_field(original), pascal); assert_eq!(CamelCase.apply_to_field(original), camel); assert_eq!(SnakeCase.apply_to_field(original), original); assert_eq!(ScreamingSnakeCase.apply_to_field(original), screaming); assert_eq!(KebabCase.apply_to_field(original), kebab); assert_eq!(ScreamingKebabCase.apply_to_field(original), screaming_kebab); } } ================================================ FILE: serde_derive/src/internals/check.rs ================================================ use crate::internals::ast::{Container, Data, Field, Style}; use crate::internals::attr::{Default, Identifier, TagType}; use crate::internals::{ungroup, Ctxt, Derive}; use syn::{Member, Type}; // Cross-cutting checks that require looking at more than a single attrs object. // Simpler checks should happen when parsing and building the attrs. pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) { check_default_on_tuple(cx, cont); check_remote_generic(cx, cont); check_getter(cx, cont); check_flatten(cx, cont); check_identifier(cx, cont); check_variant_skip_attrs(cx, cont); check_internal_tag_field_name_conflict(cx, cont); check_adjacent_tag_conflict(cx, cont); check_transparent(cx, cont, derive); check_from_and_try_from(cx, cont); } // 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 type: // // #[serde(remote = "Generic")] // struct Generic {…} // // or none of them, i.e. defining impls for one concrete instantiation of the // remote type only: // // #[serde(remote = "Generic")] // struct ConcreteDef {…} // fn check_remote_generic(cx: &Ctxt, cont: &Container) { if let Some(remote) = cont.attrs.remote() { let local_has_generic = !cont.generics.params.is_empty(); let remote_has_generic = !remote.segments.last().unwrap().arguments.is_none(); if local_has_generic && remote_has_generic { cx.error_spanned_by(remote, "remove generic parameters from this path"); } } } // Getters are only allowed inside structs (not enums) with the `remote` // attribute. fn check_getter(cx: &Ctxt, cont: &Container) { match cont.data { Data::Enum(_) => { if cont.data.has_getter() { cx.error_spanned_by( cont.original, "#[serde(getter = \"...\")] is not allowed in an enum", ); } } Data::Struct(_, _) => { if cont.data.has_getter() && cont.attrs.remote().is_none() { cx.error_spanned_by( cont.original, "#[serde(getter = \"...\")] can only be used in structs that have #[serde(remote = \"...\")]", ); } } } } // Flattening has some restrictions we can test. fn check_flatten(cx: &Ctxt, cont: &Container) { match &cont.data { Data::Enum(variants) => { for variant in variants { for field in &variant.fields { check_flatten_field(cx, variant.style, field); } } } Data::Struct(style, fields) => { for field in fields { check_flatten_field(cx, *style, field); } } } } fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) { if !field.attrs.flatten() { return; } match style { Style::Tuple => { cx.error_spanned_by( field.original, "#[serde(flatten)] cannot be used on tuple structs", ); } Style::Newtype => { cx.error_spanned_by( field.original, "#[serde(flatten)] cannot be used on newtype structs", ); } _ => {} } } // The `other` attribute must be used at most once and it must be the last // variant of an enum. // // Inside a `variant_identifier` all variants must be unit variants. Inside a // `field_identifier` all but possibly one variant must be unit variants. The // last variant may be a newtype variant which is an implicit "other" case. fn check_identifier(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => return, }; for (i, variant) in variants.iter().enumerate() { match ( variant.style, cont.attrs.identifier(), variant.attrs.other(), cont.attrs.tag(), ) { // The `other` attribute may not be used in a variant_identifier. (_, Identifier::Variant, true, _) => { cx.error_spanned_by( variant.original, "#[serde(other)] may not be used on a variant identifier", ); } // Variant with `other` attribute cannot appear in untagged enum (_, Identifier::No, true, &TagType::None) => { cx.error_spanned_by( variant.original, "#[serde(other)] cannot appear on untagged enum", ); } // Variant with `other` attribute must be the last one. (Style::Unit, Identifier::Field, true, _) | (Style::Unit, Identifier::No, true, _) => { if i < variants.len() - 1 { cx.error_spanned_by( variant.original, "#[serde(other)] must be on the last variant", ); } } // Variant with `other` attribute must be a unit variant. (_, Identifier::Field, true, _) | (_, Identifier::No, true, _) => { cx.error_spanned_by( variant.original, "#[serde(other)] must be on a unit variant", ); } // Any sort of variant is allowed if this is not an identifier. (_, Identifier::No, false, _) => {} // Unit variant without `other` attribute is always fine. (Style::Unit, _, false, _) => {} // The last field is allowed to be a newtype catch-all. (Style::Newtype, Identifier::Field, false, _) => { if i < variants.len() - 1 { cx.error_spanned_by( variant.original, format!("`{}` must be the last variant", variant.ident), ); } } (_, Identifier::Field, false, _) => { cx.error_spanned_by( variant.original, "#[serde(field_identifier)] may only contain unit variants", ); } (_, Identifier::Variant, false, _) => { cx.error_spanned_by( variant.original, "#[serde(variant_identifier)] may only contain unit variants", ); } } } } // Skip-(de)serializing attributes are not allowed on variants marked // (de)serialize_with. fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => return, }; for variant in variants { if variant.attrs.serialize_with().is_some() { if variant.attrs.skip_serializing() { cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)]", variant.ident ), ); } for field in &variant.fields { let member = member_message(&field.member); if field.attrs.skip_serializing() { cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing)]", variant.ident, member ), ); } if field.attrs.skip_serializing_if().is_some() { cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(serialize_with)] and a field {} marked with #[serde(skip_serializing_if)]", variant.ident, member ), ); } } } if variant.attrs.deserialize_with().is_some() { if variant.attrs.skip_deserializing() { cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)]", variant.ident ), ); } for field in &variant.fields { if field.attrs.skip_deserializing() { let member = member_message(&field.member); cx.error_spanned_by( variant.original, format!( "variant `{}` cannot have both #[serde(deserialize_with)] and a field {} marked with #[serde(skip_deserializing)]", variant.ident, member ), ); } } } } } // The tag of an internally-tagged struct variant must not be the same as either // one of its fields, as this would result in duplicate keys in the serialized // output and/or ambiguity in the to-be-deserialized input. fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => return, }; let tag = match cont.attrs.tag() { TagType::Internal { tag } => tag.as_str(), TagType::External | TagType::Adjacent { .. } | TagType::None => return, }; let diagnose_conflict = || { cx.error_spanned_by( cont.original, format!("variant field name `{}` conflicts with internal tag", tag), ); }; for variant in variants { match variant.style { Style::Struct => { if variant.attrs.untagged() { continue; } for field in &variant.fields { let check_ser = !(field.attrs.skip_serializing() || variant.attrs.skip_serializing()); let check_de = !(field.attrs.skip_deserializing() || variant.attrs.skip_deserializing()); let name = field.attrs.name(); let ser_name = name.serialize_name(); if check_ser && ser_name.value == tag { diagnose_conflict(); return; } for de_name in field.attrs.aliases() { if check_de && de_name.value == tag { diagnose_conflict(); return; } } } } Style::Unit | Style::Newtype | Style::Tuple => {} } } } // In the case of adjacently-tagged enums, the type and the contents tag must // differ, for the same reason. fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) { let (type_tag, content_tag) = match cont.attrs.tag() { TagType::Adjacent { tag, content } => (tag, content), TagType::Internal { .. } | TagType::External | TagType::None => return, }; if type_tag == content_tag { cx.error_spanned_by( cont.original, format!( "enum tags `{}` for type and content conflict with each other", type_tag ), ); } } // Enums and unit structs cannot be transparent. fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) { if !cont.attrs.transparent() { return; } if cont.attrs.type_from().is_some() { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed with #[serde(from = \"...\")]", ); } if cont.attrs.type_try_from().is_some() { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed with #[serde(try_from = \"...\")]", ); } if cont.attrs.type_into().is_some() { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed with #[serde(into = \"...\")]", ); } let fields = match &mut cont.data { Data::Enum(_) => { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed on an enum", ); return; } Data::Struct(Style::Unit, _) => { cx.error_spanned_by( cont.original, "#[serde(transparent)] is not allowed on a unit struct", ); return; } Data::Struct(_, fields) => fields, }; let mut transparent_field = None; for field in fields { if allow_transparent(field, derive) { if transparent_field.is_some() { cx.error_spanned_by( cont.original, "#[serde(transparent)] requires struct to have at most one transparent field", ); return; } transparent_field = Some(field); } } match transparent_field { Some(transparent_field) => transparent_field.attrs.mark_transparent(), None => match derive { Derive::Serialize => { cx.error_spanned_by( cont.original, "#[serde(transparent)] requires at least one field that is not skipped", ); } Derive::Deserialize => { cx.error_spanned_by( cont.original, "#[serde(transparent)] requires at least one field that is neither skipped nor has a default", ); } }, } } fn member_message(member: &Member) -> String { match member { Member::Named(ident) => format!("`{}`", ident), Member::Unnamed(i) => format!("#{}", i.index), } } fn allow_transparent(field: &Field, derive: Derive) -> bool { if let Type::Path(ty) = ungroup(field.ty) { if let Some(seg) = ty.path.segments.last() { if seg.ident == "PhantomData" { return false; } } } match derive { Derive::Serialize => !field.attrs.skip_serializing(), Derive::Deserialize => !field.attrs.skip_deserializing() && field.attrs.default().is_none(), } } fn check_from_and_try_from(cx: &Ctxt, cont: &mut Container) { if cont.attrs.type_from().is_some() && cont.attrs.type_try_from().is_some() { cx.error_spanned_by( cont.original, "#[serde(from = \"...\")] and #[serde(try_from = \"...\")] conflict with each other", ); } } ================================================ FILE: serde_derive/src/internals/ctxt.rs ================================================ use quote::ToTokens; use std::cell::RefCell; use std::fmt::Display; use std::thread; /// A type to collect errors together and format them. /// /// Dropping this object will cause a panic. It must be consumed using `check`. /// /// References can be shared since this type uses run-time exclusive mut checking. #[derive(Default)] pub struct Ctxt { // The contents will be set to `None` during checking. This is so that checking can be // enforced. errors: RefCell>>, } impl Ctxt { /// Create a new context object. /// /// This object contains no errors, but will still trigger a panic if it is not `check`ed. pub fn new() -> Self { Ctxt { errors: RefCell::new(Some(Vec::new())), } } /// Add an error to the context object with a tokenizable object. /// /// The object is used for spanning in error messages. pub fn error_spanned_by(&self, obj: A, msg: T) { self.errors .borrow_mut() .as_mut() .unwrap() // Curb monomorphization from generating too many identical methods. .push(syn::Error::new_spanned(obj.into_token_stream(), msg)); } /// Add one of Syn's parse errors. pub fn syn_error(&self, err: syn::Error) { self.errors.borrow_mut().as_mut().unwrap().push(err); } /// Consume this object, producing a formatted error string if there are errors. pub fn check(self) -> syn::Result<()> { let mut errors = self.errors.borrow_mut().take().unwrap().into_iter(); let Some(mut combined) = errors.next() else { return Ok(()); }; for rest in errors { combined.combine(rest); } Err(combined) } } impl Drop for Ctxt { fn drop(&mut self) { if !thread::panicking() && self.errors.borrow().is_some() { panic!("forgot to check for errors"); } } } ================================================ FILE: serde_derive/src/internals/mod.rs ================================================ pub mod ast; pub mod attr; pub mod name; mod case; mod check; mod ctxt; mod receiver; mod respan; mod symbol; use syn::Type; pub use self::ctxt::Ctxt; pub use self::receiver::replace_receiver; #[derive(Copy, Clone)] pub enum Derive { Serialize, Deserialize, } pub fn ungroup(mut ty: &Type) -> &Type { while let Type::Group(group) = ty { ty = &group.elem; } ty } ================================================ FILE: serde_derive/src/internals/name.rs ================================================ use crate::internals::attr::{Attr, VecAttr}; use proc_macro2::{Ident, Span, TokenStream}; use quote::ToTokens; use std::cmp::Ordering; use std::collections::BTreeSet; use std::fmt::{self, Display}; use syn::LitStr; pub struct MultiName { pub(crate) serialize: Name, pub(crate) serialize_renamed: bool, pub(crate) deserialize: Name, pub(crate) deserialize_renamed: bool, pub(crate) deserialize_aliases: BTreeSet, } impl MultiName { pub(crate) fn from_attrs( source_name: Name, ser_name: Attr, de_name: Attr, de_aliases: Option>, ) -> Self { let mut alias_set = BTreeSet::new(); if let Some(de_aliases) = de_aliases { for alias_name in de_aliases.get() { alias_set.insert(alias_name); } } let ser_name = ser_name.get(); let ser_renamed = ser_name.is_some(); let de_name = de_name.get(); let de_renamed = de_name.is_some(); MultiName { serialize: ser_name.unwrap_or_else(|| source_name.clone()), serialize_renamed: ser_renamed, deserialize: de_name.unwrap_or(source_name), deserialize_renamed: de_renamed, deserialize_aliases: alias_set, } } /// Return the container name for the container when serializing. pub fn serialize_name(&self) -> &Name { &self.serialize } /// Return the container name for the container when deserializing. pub fn deserialize_name(&self) -> &Name { &self.deserialize } pub(crate) fn deserialize_aliases(&self) -> &BTreeSet { &self.deserialize_aliases } } #[derive(Clone)] pub struct Name { pub value: String, pub span: Span, } impl ToTokens for Name { fn to_tokens(&self, tokens: &mut TokenStream) { LitStr::new(&self.value, self.span).to_tokens(tokens); } } impl Ord for Name { fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(&self.value, &other.value) } } impl PartialOrd for Name { fn partial_cmp(&self, other: &Self) -> Option { Some(Ord::cmp(self, other)) } } impl Eq for Name {} impl PartialEq for Name { fn eq(&self, other: &Self) -> bool { self.value == other.value } } impl From<&Ident> for Name { fn from(ident: &Ident) -> Self { Name { value: ident.to_string(), span: ident.span(), } } } impl From<&LitStr> for Name { fn from(lit: &LitStr) -> Self { Name { value: lit.value(), span: lit.span(), } } } impl Display for Name { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.value, formatter) } } ================================================ FILE: serde_derive/src/internals/receiver.rs ================================================ use crate::internals::respan::respan; use proc_macro2::Span; use quote::ToTokens; use std::mem; use syn::{ parse_quote, Data, DeriveInput, Expr, ExprPath, GenericArgument, GenericParam, Generics, Macro, Path, PathArguments, QSelf, ReturnType, Token, Type, TypeParamBound, TypePath, WherePredicate, }; pub fn replace_receiver(input: &mut DeriveInput) { let self_ty = { let ident = &input.ident; let ty_generics = input.generics.split_for_impl().1; parse_quote!(#ident #ty_generics) }; let mut visitor = ReplaceReceiver(&self_ty); visitor.visit_generics_mut(&mut input.generics); visitor.visit_data_mut(&mut input.data); } struct ReplaceReceiver<'a>(&'a TypePath); impl ReplaceReceiver<'_> { fn self_ty(&self, span: Span) -> TypePath { let tokens = self.0.to_token_stream(); let respanned = respan(tokens, span); syn::parse2(respanned).unwrap() } fn self_to_qself(&self, qself: &mut Option, path: &mut Path) { if path.leading_colon.is_some() || path.segments[0].ident != "Self" { return; } if path.segments.len() == 1 { self.self_to_expr_path(path); return; } let span = path.segments[0].ident.span(); *qself = Some(QSelf { lt_token: Token![<](span), ty: Box::new(Type::Path(self.self_ty(span))), position: 0, as_token: None, gt_token: Token![>](span), }); path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap()); let segments = mem::take(&mut path.segments); path.segments = segments.into_pairs().skip(1).collect(); } fn self_to_expr_path(&self, path: &mut Path) { let self_ty = self.self_ty(path.segments[0].ident.span()); let variant = mem::replace(path, self_ty.path); for segment in &mut path.segments { if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments { if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() { bracketed.colon2_token = Some(::default()); } } } if variant.segments.len() > 1 { path.segments.push_punct(::default()); path.segments.extend(variant.segments.into_pairs().skip(1)); } } } impl ReplaceReceiver<'_> { // `Self` -> `Receiver` fn visit_type_mut(&mut self, ty: &mut Type) { let span = if let Type::Path(node) = ty { if node.qself.is_none() && node.path.is_ident("Self") { node.path.segments[0].ident.span() } else { self.visit_type_path_mut(node); return; } } else { self.visit_type_mut_impl(ty); return; }; *ty = Type::Path(self.self_ty(span)); } // `Self::Assoc` -> `::Assoc` fn visit_type_path_mut(&mut self, ty: &mut TypePath) { if ty.qself.is_none() { self.self_to_qself(&mut ty.qself, &mut ty.path); } self.visit_type_path_mut_impl(ty); } // `Self::method` -> `::method` fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) { if expr.qself.is_none() { self.self_to_qself(&mut expr.qself, &mut expr.path); } self.visit_expr_path_mut_impl(expr); } // Everything below is simply traversing the syntax tree. fn visit_type_mut_impl(&mut self, ty: &mut Type) { match ty { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Type::Array(ty) => { self.visit_type_mut(&mut ty.elem); self.visit_expr_mut(&mut ty.len); } Type::BareFn(ty) => { for arg in &mut ty.inputs { self.visit_type_mut(&mut arg.ty); } self.visit_return_type_mut(&mut ty.output); } Type::Group(ty) => self.visit_type_mut(&mut ty.elem), Type::ImplTrait(ty) => { for bound in &mut ty.bounds { self.visit_type_param_bound_mut(bound); } } Type::Macro(ty) => self.visit_macro_mut(&mut ty.mac), Type::Paren(ty) => self.visit_type_mut(&mut ty.elem), Type::Path(ty) => { if let Some(qself) = &mut ty.qself { self.visit_type_mut(&mut qself.ty); } self.visit_path_mut(&mut ty.path); } Type::Ptr(ty) => self.visit_type_mut(&mut ty.elem), Type::Reference(ty) => self.visit_type_mut(&mut ty.elem), Type::Slice(ty) => self.visit_type_mut(&mut ty.elem), Type::TraitObject(ty) => { for bound in &mut ty.bounds { self.visit_type_param_bound_mut(bound); } } Type::Tuple(ty) => { for elem in &mut ty.elems { self.visit_type_mut(elem); } } Type::Infer(_) | Type::Never(_) | Type::Verbatim(_) => {} _ => {} } } fn visit_type_path_mut_impl(&mut self, ty: &mut TypePath) { if let Some(qself) = &mut ty.qself { self.visit_type_mut(&mut qself.ty); } self.visit_path_mut(&mut ty.path); } fn visit_expr_path_mut_impl(&mut self, expr: &mut ExprPath) { if let Some(qself) = &mut expr.qself { self.visit_type_mut(&mut qself.ty); } self.visit_path_mut(&mut expr.path); } fn visit_path_mut(&mut self, path: &mut Path) { for segment in &mut path.segments { self.visit_path_arguments_mut(&mut segment.arguments); } } fn visit_path_arguments_mut(&mut self, arguments: &mut PathArguments) { match arguments { PathArguments::None => {} PathArguments::AngleBracketed(arguments) => { for arg in &mut arguments.args { match arg { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] GenericArgument::Type(arg) => self.visit_type_mut(arg), GenericArgument::AssocType(arg) => self.visit_type_mut(&mut arg.ty), GenericArgument::Lifetime(_) | GenericArgument::Const(_) | GenericArgument::AssocConst(_) | GenericArgument::Constraint(_) => {} _ => {} } } } PathArguments::Parenthesized(arguments) => { for argument in &mut arguments.inputs { self.visit_type_mut(argument); } self.visit_return_type_mut(&mut arguments.output); } } } fn visit_return_type_mut(&mut self, return_type: &mut ReturnType) { match return_type { ReturnType::Default => {} ReturnType::Type(_, output) => self.visit_type_mut(output), } } fn visit_type_param_bound_mut(&mut self, bound: &mut TypeParamBound) { match bound { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] TypeParamBound::Trait(bound) => self.visit_path_mut(&mut bound.path), TypeParamBound::Lifetime(_) | TypeParamBound::PreciseCapture(_) | TypeParamBound::Verbatim(_) => {} _ => {} } } fn visit_generics_mut(&mut self, generics: &mut Generics) { for param in &mut generics.params { match param { GenericParam::Type(param) => { for bound in &mut param.bounds { self.visit_type_param_bound_mut(bound); } } GenericParam::Lifetime(_) | GenericParam::Const(_) => {} } } if let Some(where_clause) = &mut generics.where_clause { for predicate in &mut where_clause.predicates { match predicate { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] WherePredicate::Type(predicate) => { self.visit_type_mut(&mut predicate.bounded_ty); for bound in &mut predicate.bounds { self.visit_type_param_bound_mut(bound); } } WherePredicate::Lifetime(_) => {} _ => {} } } } } fn visit_data_mut(&mut self, data: &mut Data) { match data { Data::Struct(data) => { for field in &mut data.fields { self.visit_type_mut(&mut field.ty); } } Data::Enum(data) => { for variant in &mut data.variants { for field in &mut variant.fields { self.visit_type_mut(&mut field.ty); } } } Data::Union(_) => {} } } fn visit_expr_mut(&mut self, expr: &mut Expr) { match expr { Expr::Binary(expr) => { self.visit_expr_mut(&mut expr.left); self.visit_expr_mut(&mut expr.right); } Expr::Call(expr) => { self.visit_expr_mut(&mut expr.func); for arg in &mut expr.args { self.visit_expr_mut(arg); } } Expr::Cast(expr) => { self.visit_expr_mut(&mut expr.expr); self.visit_type_mut(&mut expr.ty); } Expr::Field(expr) => self.visit_expr_mut(&mut expr.base), Expr::Index(expr) => { self.visit_expr_mut(&mut expr.expr); self.visit_expr_mut(&mut expr.index); } Expr::Paren(expr) => self.visit_expr_mut(&mut expr.expr), Expr::Path(expr) => self.visit_expr_path_mut(expr), Expr::Unary(expr) => self.visit_expr_mut(&mut expr.expr), _ => {} } } fn visit_macro_mut(&mut self, _mac: &mut Macro) {} } ================================================ FILE: serde_derive/src/internals/respan.rs ================================================ use proc_macro2::{Group, Span, TokenStream, TokenTree}; pub(crate) fn respan(stream: TokenStream, span: Span) -> TokenStream { stream .into_iter() .map(|token| respan_token(token, span)) .collect() } fn respan_token(mut token: TokenTree, span: Span) -> TokenTree { if let TokenTree::Group(g) = &mut token { *g = Group::new(g.delimiter(), respan(g.stream(), span)); } token.set_span(span); token } ================================================ FILE: serde_derive/src/internals/symbol.rs ================================================ use std::fmt::{self, Display}; use syn::{Ident, Path}; #[derive(Copy, Clone)] pub struct Symbol(&'static str); pub const ALIAS: Symbol = Symbol("alias"); pub const BORROW: Symbol = Symbol("borrow"); pub const BOUND: Symbol = Symbol("bound"); pub const CONTENT: Symbol = Symbol("content"); pub const CRATE: Symbol = Symbol("crate"); pub const DEFAULT: Symbol = Symbol("default"); pub const DENY_UNKNOWN_FIELDS: Symbol = Symbol("deny_unknown_fields"); pub const DESERIALIZE: Symbol = Symbol("deserialize"); pub const DESERIALIZE_WITH: Symbol = Symbol("deserialize_with"); pub const EXPECTING: Symbol = Symbol("expecting"); pub const FIELD_IDENTIFIER: Symbol = Symbol("field_identifier"); pub const FLATTEN: Symbol = Symbol("flatten"); pub const FROM: Symbol = Symbol("from"); pub const GETTER: Symbol = Symbol("getter"); pub const INTO: Symbol = Symbol("into"); pub const NON_EXHAUSTIVE: Symbol = Symbol("non_exhaustive"); pub const OTHER: Symbol = Symbol("other"); pub const REMOTE: Symbol = Symbol("remote"); pub const RENAME: Symbol = Symbol("rename"); pub const RENAME_ALL: Symbol = Symbol("rename_all"); pub const RENAME_ALL_FIELDS: Symbol = Symbol("rename_all_fields"); pub const REPR: Symbol = Symbol("repr"); pub const SERDE: Symbol = Symbol("serde"); pub const SERIALIZE: Symbol = Symbol("serialize"); pub const SERIALIZE_WITH: Symbol = Symbol("serialize_with"); pub const SKIP: Symbol = Symbol("skip"); pub const SKIP_DESERIALIZING: Symbol = Symbol("skip_deserializing"); pub const SKIP_SERIALIZING: Symbol = Symbol("skip_serializing"); pub const SKIP_SERIALIZING_IF: Symbol = Symbol("skip_serializing_if"); pub const TAG: Symbol = Symbol("tag"); pub const TRANSPARENT: Symbol = Symbol("transparent"); pub const TRY_FROM: Symbol = Symbol("try_from"); pub const UNTAGGED: Symbol = Symbol("untagged"); pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier"); pub const WITH: Symbol = Symbol("with"); impl PartialEq for Ident { fn eq(&self, word: &Symbol) -> bool { self == word.0 } } impl PartialEq for &Ident { fn eq(&self, word: &Symbol) -> bool { *self == word.0 } } impl PartialEq for Path { fn eq(&self, word: &Symbol) -> bool { self.is_ident(word.0) } } impl PartialEq for &Path { fn eq(&self, word: &Symbol) -> bool { self.is_ident(word.0) } } impl Display for Symbol { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.0) } } ================================================ FILE: serde_derive/src/lib.rs ================================================ //! This crate provides Serde's two derive macros. //! //! ```edition2021 //! # use serde_derive::{Deserialize, Serialize}; //! # //! #[derive(Serialize, Deserialize)] //! # struct S; //! # //! # fn main() {} //! ``` //! //! Please refer to [https://serde.rs/derive.html] for how to set this up. //! //! [https://serde.rs/derive.html]: https://serde.rs/derive.html #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.228")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( // clippy false positive: https://github.com/rust-lang/rust-clippy/issues/7054 clippy::branches_sharing_code, clippy::cognitive_complexity, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575 clippy::collapsible_match, clippy::derive_partial_eq_without_eq, clippy::enum_variant_names, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797 clippy::manual_map, clippy::match_like_matches_macro, clippy::needless_lifetimes, clippy::needless_pass_by_value, clippy::too_many_arguments, clippy::trivially_copy_pass_by_ref, clippy::used_underscore_binding, clippy::wildcard_in_or_patterns, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 clippy::unnested_or_patterns, )] // Ignored clippy_pedantic lints #![allow( clippy::cast_possible_truncation, clippy::checked_conversions, clippy::doc_markdown, clippy::elidable_lifetime_names, clippy::enum_glob_use, clippy::indexing_slicing, clippy::items_after_statements, clippy::let_underscore_untyped, clippy::manual_assert, clippy::map_err_ignore, clippy::match_same_arms, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984 clippy::match_wildcard_for_single_variants, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::uninlined_format_args, clippy::unseparated_literal_suffix, clippy::unused_self, clippy::use_self, clippy::wildcard_imports )] #![cfg_attr(all(test, exhaustive), feature(non_exhaustive_omitted_patterns_lint))] #![allow(unknown_lints, mismatched_lifetime_syntaxes)] extern crate proc_macro2; extern crate quote; extern crate syn; extern crate proc_macro; mod internals; use proc_macro::TokenStream; use proc_macro2::{Ident, Span}; use quote::{ToTokens, TokenStreamExt as _}; use syn::parse_macro_input; use syn::DeriveInput; #[macro_use] mod bound; #[macro_use] mod fragment; mod de; mod deprecated; mod dummy; mod pretend; mod ser; mod this; #[allow(non_camel_case_types)] struct private; impl private { fn ident(&self) -> Ident { Ident::new( concat!("__private", env!("CARGO_PKG_VERSION_PATCH")), Span::call_site(), ) } } impl ToTokens for private { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { tokens.append(self.ident()); } } #[proc_macro_derive(Serialize, attributes(serde))] pub fn derive_serialize(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as DeriveInput); ser::expand_derive_serialize(&mut input) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_derive(Deserialize, attributes(serde))] pub fn derive_deserialize(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as DeriveInput); de::expand_derive_deserialize(&mut input) .unwrap_or_else(syn::Error::into_compile_error) .into() } ================================================ FILE: serde_derive/src/pretend.rs ================================================ use crate::internals::ast::{Container, Data, Field, Style, Variant}; use crate::private; use proc_macro2::TokenStream; use quote::{format_ident, quote}; // Suppress dead_code warnings that would otherwise appear when using a remote // derive. Other than this pretend code, a struct annotated with remote derive // never has its fields referenced and an enum annotated with remote derive // never has its variants constructed. // // warning: field is never used: `i` // --> src/main.rs:4:20 // | // 4 | struct StructDef { i: i32 } // | ^^^^^^ // // warning: variant is never constructed: `V` // --> src/main.rs:8:16 // | // 8 | enum EnumDef { V } // | ^ // pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream { let pretend_fields = pretend_fields_used(cont, is_packed); let pretend_variants = pretend_variants_used(cont); quote! { #pretend_fields #pretend_variants } } // For structs with named fields, expands to: // // match None::<&T> { // Some(T { a: __v0, b: __v1 }) => {} // _ => {} // } // // For packed structs on sufficiently new rustc, expands to: // // match None::<&T> { // Some(__v @ T { a: _, b: _ }) => { // let _ = addr_of!(__v.a); // let _ = addr_of!(__v.b); // } // _ => {} // } // // For packed structs on older rustc, we assume Sized and !Drop, and expand to: // // match None:: { // Some(T { a: __v0, b: __v1 }) => {} // _ => {} // } // // For enums, expands to the following but only including struct variants: // // match None::<&T> { // Some(T::A { a: __v0 }) => {} // Some(T::B { b: __v0 }) => {} // _ => {} // } // fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream { match &cont.data { Data::Enum(variants) => pretend_fields_used_enum(cont, variants), Data::Struct(Style::Struct | Style::Tuple | Style::Newtype, fields) => { if is_packed { pretend_fields_used_struct_packed(cont, fields) } else { pretend_fields_used_struct(cont, fields) } } Data::Struct(Style::Unit, _) => quote!(), } } fn pretend_fields_used_struct(cont: &Container, fields: &[Field]) -> TokenStream { let type_ident = &cont.ident; let (_, ty_generics, _) = cont.generics.split_for_impl(); let members = fields.iter().map(|field| &field.member); let placeholders = (0usize..).map(|i| format_ident!("__v{}", i)); quote! { match _serde::#private::None::<&#type_ident #ty_generics> { _serde::#private::Some(#type_ident { #(#members: #placeholders),* }) => {} _ => {} } } } fn pretend_fields_used_struct_packed(cont: &Container, fields: &[Field]) -> TokenStream { let type_ident = &cont.ident; let (_, ty_generics, _) = cont.generics.split_for_impl(); let members = fields.iter().map(|field| &field.member).collect::>(); let private2 = private; quote! { match _serde::#private::None::<&#type_ident #ty_generics> { _serde::#private::Some(__v @ #type_ident { #(#members: _),* }) => { #( let _ = _serde::#private2::ptr::addr_of!(__v.#members); )* } _ => {} } } } fn pretend_fields_used_enum(cont: &Container, variants: &[Variant]) -> TokenStream { let type_ident = &cont.ident; let (_, ty_generics, _) = cont.generics.split_for_impl(); let mut patterns = Vec::new(); for variant in variants { match variant.style { Style::Struct | Style::Tuple | Style::Newtype => { let variant_ident = &variant.ident; let members = variant.fields.iter().map(|field| &field.member); let placeholders = (0usize..).map(|i| format_ident!("__v{}", i)); patterns.push(quote!(#type_ident::#variant_ident { #(#members: #placeholders),* })); } Style::Unit => {} } } let private2 = private; quote! { match _serde::#private::None::<&#type_ident #ty_generics> { #( _serde::#private2::Some(#patterns) => {} )* _ => {} } } } // Expands to one of these per enum variant: // // match None { // Some((__v0, __v1,)) => { // let _ = E::V { a: __v0, b: __v1 }; // } // _ => {} // } // fn pretend_variants_used(cont: &Container) -> TokenStream { let variants = match &cont.data { Data::Enum(variants) => variants, Data::Struct(_, _) => { return quote!(); } }; let type_ident = &cont.ident; let (_, ty_generics, _) = cont.generics.split_for_impl(); let turbofish = ty_generics.as_turbofish(); let cases = variants.iter().map(|variant| { let variant_ident = &variant.ident; let placeholders = &(0..variant.fields.len()) .map(|i| format_ident!("__v{}", i)) .collect::>(); let pat = match variant.style { Style::Struct => { let members = variant.fields.iter().map(|field| &field.member); quote!({ #(#members: #placeholders),* }) } Style::Tuple | Style::Newtype => quote!(( #(#placeholders),* )), Style::Unit => quote!(), }; quote! { match _serde::#private::None { _serde::#private::Some((#(#placeholders,)*)) => { let _ = #type_ident::#variant_ident #turbofish #pat; } _ => {} } } }); quote!(#(#cases)*) } ================================================ FILE: serde_derive/src/ser.rs ================================================ use crate::de::field_i; use crate::deprecated::allow_deprecated; use crate::fragment::{Fragment, Match, Stmts}; use crate::internals::ast::{Container, Data, Field, Style, Variant}; use crate::internals::name::Name; use crate::internals::{attr, replace_receiver, Ctxt, Derive}; use crate::{bound, dummy, pretend, private, this}; use proc_macro2::{Span, TokenStream}; use quote::{quote, quote_spanned}; use syn::spanned::Spanned; use syn::{parse_quote, Ident, Index, Member}; pub fn expand_derive_serialize(input: &mut syn::DeriveInput) -> syn::Result { replace_receiver(input); let ctxt = Ctxt::new(); let Some(cont) = Container::from_ast(&ctxt, input, Derive::Serialize, &private.ident()) else { return Err(ctxt.check().unwrap_err()); }; precondition(&ctxt, &cont); ctxt.check()?; let ident = &cont.ident; let params = Parameters::new(&cont); let (impl_generics, ty_generics, where_clause) = params.generics.split_for_impl(); let body = Stmts(serialize_body(&cont, ¶ms)); let allow_deprecated = allow_deprecated(input); let impl_block = if let Some(remote) = cont.attrs.remote() { let vis = &input.vis; let used = pretend::pretend_used(&cont, params.is_packed); quote! { #[automatically_derived] #allow_deprecated impl #impl_generics #ident #ty_generics #where_clause { #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { #used #body } } } } else { quote! { #[automatically_derived] #allow_deprecated impl #impl_generics _serde::Serialize for #ident #ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { #body } } } }; Ok(dummy::wrap_in_const( cont.attrs.custom_serde_path(), impl_block, )) } fn precondition(cx: &Ctxt, cont: &Container) { match cont.attrs.identifier() { attr::Identifier::No => {} attr::Identifier::Field => { cx.error_spanned_by(cont.original, "field identifiers cannot be serialized"); } attr::Identifier::Variant => { cx.error_spanned_by(cont.original, "variant identifiers cannot be serialized"); } } } struct Parameters { /// Variable holding the value being serialized. Either `self` for local /// types or `__self` for remote types. self_var: Ident, /// Path to the type the impl is for. Either a single `Ident` for local /// types (does not include generic parameters) or `some::remote::Path` for /// remote types. this_type: syn::Path, /// Same as `this_type` but using `::` for generic parameters for use in /// expression position. this_value: syn::Path, /// Generics including any explicit and inferred bounds for the impl. generics: syn::Generics, /// Type has a `serde(remote = "...")` attribute. is_remote: bool, /// Type has a repr(packed) attribute. is_packed: bool, } impl Parameters { fn new(cont: &Container) -> Self { let is_remote = cont.attrs.remote().is_some(); let self_var = if is_remote { Ident::new("__self", Span::call_site()) } else { Ident::new("self", Span::call_site()) }; let this_type = this::this_type(cont); let this_value = this::this_value(cont); let is_packed = cont.attrs.is_packed(); let generics = build_generics(cont); Parameters { self_var, this_type, this_value, generics, is_remote, is_packed, } } /// Type name to use in error messages and `&'static str` arguments to /// various Serializer methods. fn type_name(&self) -> String { self.this_type.segments.last().unwrap().ident.to_string() } } // All the generics in the input, plus a bound `T: Serialize` for each generic // field type that will be serialized by us. fn build_generics(cont: &Container) -> syn::Generics { let generics = bound::without_defaults(cont.generics); let generics = bound::with_where_predicates_from_fields(cont, &generics, attr::Field::ser_bound); let generics = bound::with_where_predicates_from_variants(cont, &generics, attr::Variant::ser_bound); match cont.attrs.ser_bound() { Some(predicates) => bound::with_where_predicates(&generics, predicates), None => bound::with_bound( cont, &generics, needs_serialize_bound, &parse_quote!(_serde::Serialize), ), } } // Fields with a `skip_serializing` or `serialize_with` attribute, or which // belong to a variant with a `skip_serializing` or `serialize_with` attribute, // are not serialized by us so we do not generate a bound. Fields with a `bound` // attribute specify their own bound so we do not generate one. All other fields // may need a `T: Serialize` bound where T is the type of the field. fn needs_serialize_bound(field: &attr::Field, variant: Option<&attr::Variant>) -> bool { !field.skip_serializing() && field.serialize_with().is_none() && field.ser_bound().is_none() && variant.map_or(true, |variant| { !variant.skip_serializing() && variant.serialize_with().is_none() && variant.ser_bound().is_none() }) } fn serialize_body(cont: &Container, params: &Parameters) -> Fragment { if cont.attrs.transparent() { serialize_transparent(cont, params) } else if let Some(type_into) = cont.attrs.type_into() { serialize_into(params, type_into) } else { match &cont.data { Data::Enum(variants) => serialize_enum(params, variants, &cont.attrs), Data::Struct(Style::Struct, fields) => serialize_struct(params, fields, &cont.attrs), Data::Struct(Style::Tuple, fields) => { serialize_tuple_struct(params, fields, &cont.attrs) } Data::Struct(Style::Newtype, fields) => { serialize_newtype_struct(params, &fields[0], &cont.attrs) } Data::Struct(Style::Unit, _) => serialize_unit_struct(&cont.attrs), } } } fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment { let fields = match &cont.data { Data::Struct(_, fields) => fields, Data::Enum(_) => unreachable!(), }; let self_var = ¶ms.self_var; let transparent_field = fields.iter().find(|f| f.attrs.transparent()).unwrap(); let member = &transparent_field.member; let path = match transparent_field.attrs.serialize_with() { Some(path) => quote!(#path), None => { let span = transparent_field.original.span(); quote_spanned!(span=> _serde::Serialize::serialize) } }; quote_block! { #path(&#self_var.#member, __serializer) } } fn serialize_into(params: &Parameters, type_into: &syn::Type) -> Fragment { let self_var = ¶ms.self_var; quote_block! { _serde::Serialize::serialize( &_serde::#private::Into::<#type_into>::into(_serde::#private::Clone::clone(#self_var)), __serializer) } } fn serialize_unit_struct(cattrs: &attr::Container) -> Fragment { let type_name = cattrs.name().serialize_name(); quote_expr! { _serde::Serializer::serialize_unit_struct(__serializer, #type_name) } } fn serialize_newtype_struct( params: &Parameters, field: &Field, cattrs: &attr::Container, ) -> Fragment { let type_name = cattrs.name().serialize_name(); let mut field_expr = get_member( params, field, &Member::Unnamed(Index { index: 0, span: Span::call_site(), }), ); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_struct); quote_expr! { #func(__serializer, #type_name, #field_expr) } } fn serialize_tuple_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { let serialize_stmts = serialize_tuple_struct_visitor(fields, params, false, &TupleTrait::SerializeTupleStruct); let type_name = cattrs.name().serialize_name(); let mut serialized_fields = fields .iter() .enumerate() .filter(|(_, field)| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); let len = serialized_fields .map(|(i, field)| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let index = syn::Index { index: i as u32, span: Span::call_site(), }; let field_expr = get_member(params, field, &Member::Unnamed(index)); quote!(if #path(#field_expr) { 0 } else { 1 }) } }) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_tuple_struct(__serializer, #type_name, #len)?; #(#serialize_stmts)* _serde::ser::SerializeTupleStruct::end(__serde_state) } } fn serialize_struct(params: &Parameters, fields: &[Field], cattrs: &attr::Container) -> Fragment { assert!( fields.len() as u64 <= u64::from(u32::MAX), "too many fields in {}: {}, maximum supported count is {}", cattrs.name().serialize_name(), fields.len(), u32::MAX, ); let has_non_skipped_flatten = fields .iter() .any(|field| field.attrs.flatten() && !field.attrs.skip_serializing()); if has_non_skipped_flatten { serialize_struct_as_map(params, fields, cattrs) } else { serialize_struct_as_struct(params, fields, cattrs) } } fn serialize_struct_tag_field(cattrs: &attr::Container, struct_trait: &StructTrait) -> TokenStream { match cattrs.tag() { attr::TagType::Internal { tag } => { let type_name = cattrs.name().serialize_name(); let func = struct_trait.serialize_field(Span::call_site()); quote! { #func(&mut __serde_state, #tag, #type_name)?; } } _ => quote! {}, } } fn serialize_struct_as_struct( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { let serialize_fields = serialize_struct_visitor(fields, params, false, &StructTrait::SerializeStruct); let type_name = cattrs.name().serialize_name(); let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeStruct); let tag_field_exists = !tag_field.is_empty(); let mut serialized_fields = fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); let len = serialized_fields .map(|field| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let field_expr = get_member(params, field, &field.member); quote!(if #path(#field_expr) { 0 } else { 1 }) } }) .fold( quote!(#tag_field_exists as usize), |sum, expr| quote!(#sum + #expr), ); quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_struct(__serializer, #type_name, #len)?; #tag_field #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } } fn serialize_struct_as_map( params: &Parameters, fields: &[Field], cattrs: &attr::Container, ) -> Fragment { let serialize_fields = serialize_struct_visitor(fields, params, false, &StructTrait::SerializeMap); let tag_field = serialize_struct_tag_field(cattrs, &StructTrait::SerializeMap); let tag_field_exists = !tag_field.is_empty(); let mut serialized_fields = fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some() || tag_field_exists); quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_map(__serializer, _serde::#private::None)?; #tag_field #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } fn serialize_enum(params: &Parameters, variants: &[Variant], cattrs: &attr::Container) -> Fragment { assert!(variants.len() as u64 <= u64::from(u32::MAX)); let self_var = ¶ms.self_var; let mut arms: Vec<_> = variants .iter() .enumerate() .map(|(variant_index, variant)| { serialize_variant(params, variant, variant_index as u32, cattrs) }) .collect(); if cattrs.remote().is_some() && cattrs.non_exhaustive() { arms.push(quote! { ref unrecognized => _serde::#private::Err(_serde::ser::Error::custom(_serde::#private::ser::CannotSerializeVariant(unrecognized))), }); } quote_expr! { match *#self_var { #(#arms)* } } } fn serialize_variant( params: &Parameters, variant: &Variant, variant_index: u32, cattrs: &attr::Container, ) -> TokenStream { let this_value = ¶ms.this_value; let variant_ident = &variant.ident; if variant.attrs.skip_serializing() { let skipped_msg = format!( "the enum variant {}::{} cannot be serialized", params.type_name(), variant_ident ); let skipped_err = quote! { _serde::#private::Err(_serde::ser::Error::custom(#skipped_msg)) }; let fields_pat = match variant.style { Style::Unit => quote!(), Style::Newtype | Style::Tuple => quote!((..)), Style::Struct => quote!({ .. }), }; quote! { #this_value::#variant_ident #fields_pat => #skipped_err, } } else { // variant wasn't skipped let case = match variant.style { Style::Unit => { quote! { #this_value::#variant_ident } } Style::Newtype => { quote! { #this_value::#variant_ident(ref __field0) } } Style::Tuple => { let field_names = (0..variant.fields.len()).map(field_i); quote! { #this_value::#variant_ident(#(ref #field_names),*) } } Style::Struct => { let members = variant.fields.iter().map(|f| &f.member); quote! { #this_value::#variant_ident { #(ref #members),* } } } }; let body = Match(match (cattrs.tag(), variant.attrs.untagged()) { (attr::TagType::External, false) => { serialize_externally_tagged_variant(params, variant, variant_index, cattrs) } (attr::TagType::Internal { tag }, false) => { serialize_internally_tagged_variant(params, variant, cattrs, tag) } (attr::TagType::Adjacent { tag, content }, false) => { serialize_adjacently_tagged_variant( params, variant, cattrs, variant_index, tag, content, ) } (attr::TagType::None, _) | (_, true) => { serialize_untagged_variant(params, variant, cattrs) } }); quote! { #case => #body } } } fn serialize_externally_tagged_variant( params: &Parameters, variant: &Variant, variant_index: u32, cattrs: &attr::Container, ) -> Fragment { let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, variant); return quote_expr! { _serde::Serializer::serialize_newtype_variant( __serializer, #type_name, #variant_index, #variant_name, #ser, ) }; } match effective_style(variant) { Style::Unit => { quote_expr! { _serde::Serializer::serialize_unit_variant( __serializer, #type_name, #variant_index, #variant_name, ) } } Style::Newtype => { let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::Serializer::serialize_newtype_variant); quote_expr! { #func( __serializer, #type_name, #variant_index, #variant_name, #field_expr, ) } } Style::Tuple => serialize_tuple_variant( TupleVariant::ExternallyTagged { type_name, variant_index, variant_name, }, params, &variant.fields, ), Style::Struct => serialize_struct_variant( StructVariant::ExternallyTagged { variant_index, variant_name, }, params, &variant.fields, type_name, ), } } fn serialize_internally_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, tag: &str, ) -> Fragment { let type_name = cattrs.name().serialize_name(); let variant_name = variant.attrs.name().serialize_name(); let enum_ident_str = params.type_name(); let variant_ident_str = variant.ident.to_string(); if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, variant); return quote_expr! { _serde::#private::ser::serialize_tagged_newtype( __serializer, #enum_ident_str, #variant_ident_str, #tag, #variant_name, #ser, ) }; } match effective_style(variant) { Style::Unit => { quote_block! { let mut __struct = _serde::Serializer::serialize_struct( __serializer, #type_name, 1)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #variant_name)?; _serde::ser::SerializeStruct::end(__struct) } } Style::Newtype => { let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::#private::ser::serialize_tagged_newtype); quote_expr! { #func( __serializer, #enum_ident_str, #variant_ident_str, #tag, #variant_name, #field_expr, ) } } Style::Struct => serialize_struct_variant( StructVariant::InternallyTagged { tag, variant_name }, params, &variant.fields, type_name, ), Style::Tuple => unreachable!("checked in serde_derive_internals"), } } fn serialize_adjacently_tagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, variant_index: u32, tag: &str, content: &str, ) -> Fragment { let this_type = ¶ms.this_type; let type_name = cattrs.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 ser = wrap_serialize_variant_with(params, path, variant); quote_expr! { _serde::Serialize::serialize(#ser, __serializer) } } else { match effective_style(variant) { Style::Unit => { return quote_block! { let mut __struct = _serde::Serializer::serialize_struct( __serializer, #type_name, 1)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #serialize_variant)?; _serde::ser::SerializeStruct::end(__struct) }; } Style::Newtype => { let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field); return quote_block! { let mut __struct = _serde::Serializer::serialize_struct( __serializer, #type_name, 2)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #serialize_variant)?; #func( &mut __struct, #content, #field_expr)?; _serde::ser::SerializeStruct::end(__struct) }; } Style::Tuple => { serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields) } Style::Struct => serialize_struct_variant( StructVariant::Untagged, params, &variant.fields, variant_name, ), } }); let fields_ty = variant.fields.iter().map(|f| &f.ty); let fields_ident: &[_] = &match variant.style { Style::Unit => { if variant.attrs.serialize_with().is_some() { vec![] } else { unreachable!() } } Style::Newtype => vec![Member::Named(field_i(0))], Style::Tuple => (0..variant.fields.len()) .map(|i| Member::Named(field_i(i))) .collect(), Style::Struct => variant.fields.iter().map(|f| f.member.clone()).collect(), }; let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let wrapper_generics = if fields_ident.is_empty() { params.generics.clone() } else { bound::with_lifetime_bound(¶ms.generics, "'__a") }; let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); quote_block! { #[doc(hidden)] struct __AdjacentlyTagged #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), phantom: _serde::#private::PhantomData<#this_type #ty_generics>, } #[automatically_derived] impl #wrapper_impl_generics _serde::Serialize for __AdjacentlyTagged #wrapper_ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { // Elements that have skip_serializing will be unused. #[allow(unused_variables)] let (#(#fields_ident,)*) = self.data; #inner } } let mut __struct = _serde::Serializer::serialize_struct( __serializer, #type_name, 2)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #tag, #serialize_variant)?; _serde::ser::SerializeStruct::serialize_field( &mut __struct, #content, &__AdjacentlyTagged { data: (#(#fields_ident,)*), phantom: _serde::#private::PhantomData::<#this_type #ty_generics>, })?; _serde::ser::SerializeStruct::end(__struct) } } fn serialize_untagged_variant( params: &Parameters, variant: &Variant, cattrs: &attr::Container, ) -> Fragment { if let Some(path) = variant.attrs.serialize_with() { let ser = wrap_serialize_variant_with(params, path, variant); return quote_expr! { _serde::Serialize::serialize(#ser, __serializer) }; } match effective_style(variant) { Style::Unit => { quote_expr! { _serde::Serializer::serialize_unit(__serializer) } } Style::Newtype => { let field = &variant.fields[0]; let mut field_expr = quote!(__field0); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = quote_spanned!(span=> _serde::Serialize::serialize); quote_expr! { #func(#field_expr, __serializer) } } Style::Tuple => serialize_tuple_variant(TupleVariant::Untagged, params, &variant.fields), Style::Struct => { let type_name = cattrs.name().serialize_name(); serialize_struct_variant(StructVariant::Untagged, params, &variant.fields, type_name) } } } enum TupleVariant<'a> { ExternallyTagged { type_name: &'a Name, variant_index: u32, variant_name: &'a Name, }, Untagged, } fn serialize_tuple_variant( context: TupleVariant, params: &Parameters, fields: &[Field], ) -> Fragment { let tuple_trait = match context { TupleVariant::ExternallyTagged { .. } => TupleTrait::SerializeTupleVariant, TupleVariant::Untagged => TupleTrait::SerializeTuple, }; let serialize_stmts = serialize_tuple_struct_visitor(fields, params, true, &tuple_trait); let mut serialized_fields = fields .iter() .enumerate() .filter(|(_, field)| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); let len = serialized_fields .map(|(i, field)| match field.attrs.skip_serializing_if() { None => quote!(1), Some(path) => { let field_expr = field_i(i); quote!(if #path(#field_expr) { 0 } else { 1 }) } }) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); match context { TupleVariant::ExternallyTagged { type_name, variant_index, variant_name, } => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_tuple_variant( __serializer, #type_name, #variant_index, #variant_name, #len)?; #(#serialize_stmts)* _serde::ser::SerializeTupleVariant::end(__serde_state) } } TupleVariant::Untagged => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_tuple( __serializer, #len)?; #(#serialize_stmts)* _serde::ser::SerializeTuple::end(__serde_state) } } } } enum StructVariant<'a> { ExternallyTagged { variant_index: u32, variant_name: &'a Name, }, InternallyTagged { tag: &'a str, variant_name: &'a Name, }, Untagged, } fn serialize_struct_variant( context: StructVariant, params: &Parameters, fields: &[Field], name: &Name, ) -> Fragment { if fields.iter().any(|field| field.attrs.flatten()) { return serialize_struct_variant_with_flatten(context, params, fields, name); } let struct_trait = match context { StructVariant::ExternallyTagged { .. } => StructTrait::SerializeStructVariant, StructVariant::InternallyTagged { .. } | StructVariant::Untagged => { StructTrait::SerializeStruct } }; let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); let mut serialized_fields = fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); let len = serialized_fields .map(|field| { let member = &field.member; match field.attrs.skip_serializing_if() { Some(path) => quote!(if #path(#member) { 0 } else { 1 }), None => quote!(1), } }) .fold(quote!(0), |sum, expr| quote!(#sum + #expr)); match context { StructVariant::ExternallyTagged { variant_index, variant_name, } => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_struct_variant( __serializer, #name, #variant_index, #variant_name, #len, )?; #(#serialize_fields)* _serde::ser::SerializeStructVariant::end(__serde_state) } } StructVariant::InternallyTagged { tag, variant_name } => { quote_block! { let mut __serde_state = _serde::Serializer::serialize_struct( __serializer, #name, #len + 1, )?; _serde::ser::SerializeStruct::serialize_field( &mut __serde_state, #tag, #variant_name, )?; #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } } StructVariant::Untagged => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_struct( __serializer, #name, #len, )?; #(#serialize_fields)* _serde::ser::SerializeStruct::end(__serde_state) } } } } fn serialize_struct_variant_with_flatten( context: StructVariant, params: &Parameters, fields: &[Field], name: &Name, ) -> Fragment { let struct_trait = StructTrait::SerializeMap; let serialize_fields = serialize_struct_visitor(fields, params, true, &struct_trait); let mut serialized_fields = fields .iter() .filter(|&field| !field.attrs.skip_serializing()) .peekable(); let let_mut = mut_if(serialized_fields.peek().is_some()); match context { StructVariant::ExternallyTagged { variant_index, variant_name, } => { let this_type = ¶ms.this_type; let fields_ty = fields.iter().map(|f| &f.ty); let members = &fields.iter().map(|f| &f.member).collect::>(); let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let wrapper_generics = bound::with_lifetime_bound(¶ms.generics, "'__a"); let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); quote_block! { #[doc(hidden)] struct __EnumFlatten #wrapper_generics #where_clause { data: (#(&'__a #fields_ty,)*), phantom: _serde::#private::PhantomData<#this_type #ty_generics>, } #[automatically_derived] impl #wrapper_impl_generics _serde::Serialize for __EnumFlatten #wrapper_ty_generics #where_clause { fn serialize<__S>(&self, __serializer: __S) -> _serde::#private::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { let (#(#members,)*) = self.data; let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, _serde::#private::None)?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } _serde::Serializer::serialize_newtype_variant( __serializer, #name, #variant_index, #variant_name, &__EnumFlatten { data: (#(#members,)*), phantom: _serde::#private::PhantomData::<#this_type #ty_generics>, }) } } StructVariant::InternallyTagged { tag, variant_name } => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, _serde::#private::None)?; _serde::ser::SerializeMap::serialize_entry( &mut __serde_state, #tag, #variant_name, )?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } StructVariant::Untagged => { quote_block! { let #let_mut __serde_state = _serde::Serializer::serialize_map( __serializer, _serde::#private::None)?; #(#serialize_fields)* _serde::ser::SerializeMap::end(__serde_state) } } } } fn serialize_tuple_struct_visitor( fields: &[Field], params: &Parameters, is_enum: bool, tuple_trait: &TupleTrait, ) -> Vec { let mut dst_fields = Vec::new(); for (i, field) in fields.iter().enumerate() { if field.attrs.skip_serializing() { continue; } let mut field_expr = if is_enum { let id = field_i(i); quote!(#id) } else { get_member( params, field, &Member::Unnamed(Index { index: i as u32, span: Span::call_site(), }), ) }; let skip = field .attrs .skip_serializing_if() .map(|path| quote!(#path(#field_expr))); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let func = tuple_trait.serialize_element(span); let ser = quote! { #func(&mut __serde_state, #field_expr)?; }; dst_fields.push(match skip { None => ser, Some(skip) => quote!(if !#skip { #ser }), }); } dst_fields } fn serialize_struct_visitor( fields: &[Field], params: &Parameters, is_enum: bool, struct_trait: &StructTrait, ) -> Vec { let mut dst_fields = Vec::new(); for field in fields { if field.attrs.skip_serializing() { continue; } let member = &field.member; let mut field_expr = if is_enum { quote!(#member) } else { get_member(params, field, member) }; let key_expr = field.attrs.name().serialize_name(); let skip = field .attrs .skip_serializing_if() .map(|path| quote!(#path(#field_expr))); if let Some(path) = field.attrs.serialize_with() { field_expr = wrap_serialize_field_with(params, field.ty, path, &field_expr); } let span = field.original.span(); let ser = if field.attrs.flatten() { let func = quote_spanned!(span=> _serde::Serialize::serialize); quote! { #func(&#field_expr, _serde::#private::ser::FlatMapSerializer(&mut __serde_state))?; } } else { let func = struct_trait.serialize_field(span); quote! { #func(&mut __serde_state, #key_expr, #field_expr)?; } }; dst_fields.push(match skip { None => ser, Some(skip) => { if let Some(skip_func) = struct_trait.skip_field(span) { quote! { if !#skip { #ser } else { #skip_func(&mut __serde_state, #key_expr)?; } } } else { quote! { if !#skip { #ser } } } } }); } dst_fields } fn wrap_serialize_field_with( params: &Parameters, field_ty: &syn::Type, serialize_with: &syn::ExprPath, field_expr: &TokenStream, ) -> TokenStream { wrap_serialize_with(params, serialize_with, &[field_ty], &[quote!(#field_expr)]) } fn wrap_serialize_variant_with( params: &Parameters, serialize_with: &syn::ExprPath, variant: &Variant, ) -> TokenStream { let field_tys: Vec<_> = variant.fields.iter().map(|field| field.ty).collect(); let field_exprs: Vec<_> = variant .fields .iter() .map(|field| { let id = match &field.member { Member::Named(ident) => ident.clone(), Member::Unnamed(member) => field_i(member.index as usize), }; quote!(#id) }) .collect(); wrap_serialize_with( params, serialize_with, field_tys.as_slice(), field_exprs.as_slice(), ) } fn wrap_serialize_with( params: &Parameters, serialize_with: &syn::ExprPath, field_tys: &[&syn::Type], field_exprs: &[TokenStream], ) -> TokenStream { let this_type = ¶ms.this_type; let (_, ty_generics, where_clause) = params.generics.split_for_impl(); let wrapper_generics = if field_exprs.is_empty() { params.generics.clone() } else { bound::with_lifetime_bound(¶ms.generics, "'__a") }; let (wrapper_impl_generics, wrapper_ty_generics, _) = wrapper_generics.split_for_impl(); let field_access = (0..field_exprs.len()).map(|n| { Member::Unnamed(Index { index: n as u32, span: Span::call_site(), }) }); let self_var = quote!(self); let serializer_var = quote!(__s); // If #serialize_with returns wrong type, error will be reported on here. // We attach span of the path to this piece so error will be reported // on the #[serde(with = "...")] // ^^^^^ let wrapper_serialize = quote_spanned! {serialize_with.span()=> #serialize_with(#(#self_var.values.#field_access, )* #serializer_var) }; quote!(&{ #[doc(hidden)] struct __SerializeWith #wrapper_impl_generics #where_clause { values: (#(&'__a #field_tys, )*), phantom: _serde::#private::PhantomData<#this_type #ty_generics>, } #[automatically_derived] impl #wrapper_impl_generics _serde::Serialize for __SerializeWith #wrapper_ty_generics #where_clause { fn serialize<__S>(&#self_var, #serializer_var: __S) -> _serde::#private::Result<__S::Ok, __S::Error> where __S: _serde::Serializer, { #wrapper_serialize } } __SerializeWith { values: (#(#field_exprs, )*), phantom: _serde::#private::PhantomData::<#this_type #ty_generics>, } }) } // Serialization of an empty struct results in code like: // // let mut __serde_state = serializer.serialize_struct("S", 0)?; // _serde::ser::SerializeStruct::end(__serde_state) // // where we want to omit the `mut` to avoid a warning. fn mut_if(is_mut: bool) -> Option { if is_mut { Some(quote!(mut)) } else { None } } fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream { let self_var = ¶ms.self_var; match (params.is_remote, field.attrs.getter()) { (false, None) => { if params.is_packed { quote!(&{#self_var.#member}) } else { quote!(&#self_var.#member) } } (true, None) => { let inner = if params.is_packed { quote!(&{#self_var.#member}) } else { quote!(&#self_var.#member) }; let ty = field.ty; quote!(_serde::#private::ser::constrain::<#ty>(#inner)) } (true, Some(getter)) => { let ty = field.ty; quote!(_serde::#private::ser::constrain::<#ty>(&#getter(#self_var))) } (false, Some(_)) => { unreachable!("getter is only allowed for remote impls"); } } } fn effective_style(variant: &Variant) -> Style { match variant.style { Style::Newtype if variant.fields[0].attrs.skip_serializing() => Style::Unit, other => other, } } enum StructTrait { SerializeMap, SerializeStruct, SerializeStructVariant, } impl StructTrait { fn serialize_field(&self, span: Span) -> TokenStream { match *self { StructTrait::SerializeMap => { quote_spanned!(span=> _serde::ser::SerializeMap::serialize_entry) } StructTrait::SerializeStruct => { quote_spanned!(span=> _serde::ser::SerializeStruct::serialize_field) } StructTrait::SerializeStructVariant => { quote_spanned!(span=> _serde::ser::SerializeStructVariant::serialize_field) } } } fn skip_field(&self, span: Span) -> Option { match *self { StructTrait::SerializeMap => None, StructTrait::SerializeStruct => { Some(quote_spanned!(span=> _serde::ser::SerializeStruct::skip_field)) } StructTrait::SerializeStructVariant => { Some(quote_spanned!(span=> _serde::ser::SerializeStructVariant::skip_field)) } } } } enum TupleTrait { SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, } impl TupleTrait { fn serialize_element(&self, span: Span) -> TokenStream { match *self { TupleTrait::SerializeTuple => { quote_spanned!(span=> _serde::ser::SerializeTuple::serialize_element) } TupleTrait::SerializeTupleStruct => { quote_spanned!(span=> _serde::ser::SerializeTupleStruct::serialize_field) } TupleTrait::SerializeTupleVariant => { quote_spanned!(span=> _serde::ser::SerializeTupleVariant::serialize_field) } } } } ================================================ FILE: serde_derive/src/this.rs ================================================ use crate::internals::ast::Container; use syn::{Path, PathArguments, Token}; pub fn this_type(cont: &Container) -> Path { if let Some(remote) = cont.attrs.remote() { let mut this = remote.clone(); for segment in &mut this.segments { if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments { arguments.colon2_token = None; } } this } else { Path::from(cont.ident.clone()) } } pub fn this_value(cont: &Container) -> Path { if let Some(remote) = cont.attrs.remote() { let mut this = remote.clone(); for segment in &mut this.segments { if let PathArguments::AngleBracketed(arguments) = &mut segment.arguments { if arguments.colon2_token.is_none() { arguments.colon2_token = Some(Token![::](arguments.lt_token.span)); } } } this } else { Path::from(cont.ident.clone()) } } ================================================ FILE: serde_derive_internals/Cargo.toml ================================================ [package] name = "serde_derive_internals" version = "0.29.1" authors = ["Erick Tryzelaar ", "David Tolnay "] description = "AST representation used by Serde derive macros. Unstable." documentation = "https://docs.rs/serde_derive_internals" edition = "2021" exclude = ["build.rs"] homepage = "https://serde.rs" keywords = ["serde", "serialization"] license = "MIT OR Apache-2.0" repository = "https://github.com/serde-rs/serde" rust-version = "1.71" [lib] path = "lib.rs" [dependencies] proc-macro2 = { workspace = true } quote = { workspace = true } syn = { workspace = true, features = ["clone-impls", "derive", "parsing", "printing"] } [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = [ "--generate-link-to-definition", "--generate-macro-expansion", "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", ] ================================================ FILE: serde_derive_internals/build.rs ================================================ use std::path::Path; fn main() { // Warning: build.rs is not published to crates.io. println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=src/mod.rs"); println!("cargo:rustc-cfg=check_cfg"); println!("cargo:rustc-check-cfg=cfg(check_cfg)"); println!("cargo:rustc-check-cfg=cfg(exhaustive)"); println!("cargo:rustc-check-cfg=cfg(serde_build_from_git)"); println!("cargo:rustc-check-cfg=cfg(feature, values(\"deserialize_in_place\"))"); // Sometimes on Windows the git checkout does not correctly wire up the // symlink from serde_derive_internals/src to serde_derive/src/internals. // When this happens we'll just build based on relative paths within the git // repo. let mod_behind_symlink = Path::new("src/mod.rs"); if !mod_behind_symlink.exists() { println!("cargo:rustc-cfg=serde_build_from_git"); } } ================================================ FILE: serde_derive_internals/lib.rs ================================================ #![doc(html_root_url = "https://docs.rs/serde_derive_internals/0.29.1")] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] // Ignored clippy lints #![allow( clippy::cognitive_complexity, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7575 clippy::collapsible_match, clippy::derive_partial_eq_without_eq, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797 clippy::manual_map, clippy::missing_panics_doc, clippy::needless_lifetimes, clippy::redundant_field_names, clippy::result_unit_err, clippy::should_implement_trait, clippy::trivially_copy_pass_by_ref, clippy::wildcard_in_or_patterns, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704 clippy::unnested_or_patterns, )] // Ignored clippy_pedantic lints #![allow( clippy::doc_markdown, clippy::elidable_lifetime_names, clippy::enum_glob_use, clippy::items_after_statements, clippy::let_underscore_untyped, clippy::manual_assert, clippy::match_same_arms, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984 clippy::match_wildcard_for_single_variants, clippy::missing_errors_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::return_self_not_must_use, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, clippy::too_many_lines, clippy::uninlined_format_args, clippy::unused_self, clippy::wildcard_imports )] #![allow(unknown_lints, mismatched_lifetime_syntaxes)] extern crate proc_macro2; extern crate quote; extern crate syn; #[cfg_attr(serde_build_from_git, path = "../serde_derive/src/internals/mod.rs")] #[cfg_attr(not(serde_build_from_git), path = "src/mod.rs")] mod internals; pub use internals::*; ================================================ FILE: test_suite/Cargo.toml ================================================ [package] name = "serde_test_suite" version = "0.0.0" authors = ["Erick Tryzelaar ", "David Tolnay "] edition = "2021" publish = false [features] unstable = ["serde/unstable"] [dependencies] serde = { path = "../serde" } [dev-dependencies] automod = "1.0.1" foldhash = "0.2" rustversion = "1.0" serde = { path = "../serde", features = ["rc"] } serde_derive = { path = "../serde_derive", features = ["deserialize_in_place"] } serde_test = "1.0.176" trybuild = { version = "1.0.108", features = ["diff"] } ================================================ FILE: test_suite/no_std/.gitignore ================================================ /target/ /Cargo.lock ================================================ FILE: test_suite/no_std/Cargo.toml ================================================ [package] name = "serde_derive_tests_no_std" version = "0.0.0" authors = ["David Tolnay "] edition = "2021" publish = false [dependencies] libc = { version = "0.2", default-features = false } serde = { path = "../../serde", default-features = false } serde_derive = { path = "../../serde_derive" } [profile.dev] panic = "abort" [profile.release] panic = "abort" [workspace] ================================================ FILE: test_suite/no_std/src/main.rs ================================================ #![no_std] #![no_main] use core::ffi::c_int; #[no_mangle] extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int { 0 } #[panic_handler] fn panic(_info: &core::panic::PanicInfo) -> ! { unsafe { libc::abort(); } } ////////////////////////////////////////////////////////////////////////////// use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Unit; #[derive(Serialize, Deserialize)] pub struct Newtype(u8); #[derive(Serialize, Deserialize)] pub struct Tuple(u8, u8); #[derive(Serialize, Deserialize)] pub struct Struct { f: u8, } #[derive(Serialize, Deserialize)] pub enum Enum { Unit, Newtype(u8), Tuple(u8, u8), Struct { f: u8 }, } ================================================ FILE: test_suite/tests/bytes/mod.rs ================================================ use serde::de::{Deserializer, Error, SeqAccess, Visitor}; use std::fmt; pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { deserializer.deserialize_byte_buf(ByteBufVisitor) } struct ByteBufVisitor; impl<'de> Visitor<'de> for ByteBufVisitor { type Value = Vec; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("byte array") } fn visit_seq(self, mut visitor: V) -> Result where V: SeqAccess<'de>, { let mut values = Vec::new(); while let Some(value) = visitor.next_element()? { values.push(value); } Ok(values) } fn visit_bytes(self, v: &[u8]) -> Result where E: Error, { Ok(v.to_vec()) } fn visit_byte_buf(self, v: Vec) -> Result where E: Error, { Ok(v) } fn visit_str(self, v: &str) -> Result where E: Error, { Ok(v.as_bytes().to_vec()) } fn visit_string(self, v: String) -> Result where E: Error, { Ok(v.into_bytes()) } } ================================================ FILE: test_suite/tests/compiletest.rs ================================================ #[cfg_attr(target_os = "emscripten", ignore = "disabled on Emscripten")] #[rustversion::attr(not(nightly), ignore = "requires nightly")] #[cfg_attr(miri, ignore = "incompatible with miri")] #[allow(unused_attributes)] #[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/**/*.rs"); } ================================================ FILE: test_suite/tests/macros/mod.rs ================================================ #![allow(unused_macro_rules)] use serde_test::Token; use std::iter; macro_rules! btreeset { () => { BTreeSet::new() }; ($($value:expr),+) => {{ let mut set = BTreeSet::new(); $(set.insert($value);)+ set }}; } macro_rules! btreemap { () => { BTreeMap::new() }; ($($key:expr => $value:expr),+) => {{ let mut map = BTreeMap::new(); $(map.insert($key, $value);)+ map }}; } macro_rules! hashset { () => { HashSet::new() }; ($($value:expr),+) => {{ let mut set = HashSet::new(); $(set.insert($value);)+ set }}; ($hasher:ty; $($value:expr),+) => {{ let mut set = HashSet::<_, $hasher>::default(); $(set.insert($value);)+ set }}; } macro_rules! hashmap { () => { HashMap::new() }; ($($key:expr => $value:expr),+) => {{ let mut map = HashMap::new(); $(map.insert($key, $value);)+ map }}; ($hasher:ty; $($key:expr => $value:expr),+) => {{ let mut map = HashMap::<_, _, $hasher>::default(); $(map.insert($key, $value);)+ map }}; } pub trait SingleTokenIntoIterator { fn into_iter(self) -> iter::Once; } impl SingleTokenIntoIterator for Token { fn into_iter(self) -> iter::Once { iter::once(self) } } macro_rules! seq { ($($elem:expr),* $(,)?) => {{ use crate::macros::SingleTokenIntoIterator; let mut vec = Vec::new(); $( as Extend>::extend(&mut vec, $elem.into_iter());)* vec }}; } ================================================ FILE: test_suite/tests/regression/issue1904.rs ================================================ #![allow(dead_code)] // we do not read enum fields use serde_derive::Deserialize; #[derive(Deserialize)] pub struct Nested; #[derive(Deserialize)] pub enum ExternallyTagged1 { Tuple(f64, String), Flatten { #[serde(flatten)] nested: Nested, }, } #[derive(Deserialize)] pub enum ExternallyTagged2 { Flatten { #[serde(flatten)] nested: Nested, }, Tuple(f64, String), } // Internally tagged enums cannot contain tuple variants so not tested here #[derive(Deserialize)] #[serde(tag = "tag", content = "content")] pub enum AdjacentlyTagged1 { Tuple(f64, String), Flatten { #[serde(flatten)] nested: Nested, }, } #[derive(Deserialize)] #[serde(tag = "tag", content = "content")] pub enum AdjacentlyTagged2 { Flatten { #[serde(flatten)] nested: Nested, }, Tuple(f64, String), } #[derive(Deserialize)] #[serde(untagged)] pub enum Untagged1 { Tuple(f64, String), Flatten { #[serde(flatten)] nested: Nested, }, } #[derive(Deserialize)] #[serde(untagged)] pub enum Untagged2 { Flatten { #[serde(flatten)] nested: Nested, }, Tuple(f64, String), } ================================================ FILE: test_suite/tests/regression/issue2371.rs ================================================ #![allow(dead_code)] use serde_derive::Deserialize; #[derive(Deserialize)] pub struct Nested; #[derive(Deserialize)] pub enum ExternallyTagged { Flatten { #[serde(flatten)] #[allow(dead_code)] nested: Nested, #[allow(dead_code)] string: &'static str, }, } #[derive(Deserialize)] #[serde(tag = "tag")] pub enum InternallyTagged { Flatten { #[serde(flatten)] #[allow(dead_code)] nested: Nested, #[allow(dead_code)] string: &'static str, }, } #[derive(Deserialize)] #[serde(tag = "tag", content = "content")] pub enum AdjacentlyTagged { Flatten { #[serde(flatten)] #[allow(dead_code)] nested: Nested, #[allow(dead_code)] string: &'static str, }, } #[derive(Deserialize)] #[serde(untagged)] pub enum UntaggedWorkaround { Flatten { #[serde(flatten)] #[allow(dead_code)] nested: Nested, #[allow(dead_code)] string: &'static str, }, } ================================================ FILE: test_suite/tests/regression/issue2409.rs ================================================ #![allow(dead_code)] use serde_derive::Deserialize; macro_rules! bug { ($serde_path:literal) => { #[derive(Deserialize)] #[serde(crate = $serde_path)] pub struct Struct; }; } bug!("serde"); ================================================ FILE: test_suite/tests/regression/issue2415.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde()] #[allow(dead_code)] pub struct S; ================================================ FILE: test_suite/tests/regression/issue2565.rs ================================================ use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_tokens, Token}; #[derive(Serialize, Deserialize, Debug, PartialEq)] enum Enum { Simple { a: i32, }, Flatten { #[serde(flatten)] flatten: (), a: i32, }, } #[test] fn simple_variant() { assert_tokens( &Enum::Simple { a: 42 }, &[ Token::StructVariant { name: "Enum", variant: "Simple", len: 1, }, Token::Str("a"), Token::I32(42), Token::StructVariantEnd, ], ); } #[test] fn flatten_variant() { assert_tokens( &Enum::Flatten { flatten: (), a: 42 }, &[ Token::NewtypeVariant { name: "Enum", variant: "Flatten", }, Token::Map { len: None }, Token::Str("a"), Token::I32(42), Token::MapEnd, ], ); } ================================================ FILE: test_suite/tests/regression/issue2792.rs ================================================ #![allow(dead_code)] // we do not read enum fields use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(deny_unknown_fields)] pub enum A { B { c: String, }, D { #[serde(flatten)] e: E, }, } #[derive(Deserialize)] pub struct E {} ================================================ FILE: test_suite/tests/regression/issue2844.rs ================================================ #![allow(clippy::trivially_copy_pass_by_ref, dead_code)] use serde_derive::{Deserialize, Serialize}; macro_rules! declare_in_macro { ($with:literal) => { #[derive(Serialize, Deserialize)] pub struct S { #[serde(with = $with)] f: i32, } }; } declare_in_macro!("with"); mod with { use serde::{Deserializer, Serializer}; pub fn serialize(_: &i32, _: S) -> Result where S: Serializer, { unimplemented!() } pub fn deserialize<'de, D>(_: D) -> Result where D: Deserializer<'de>, { unimplemented!() } } ================================================ FILE: test_suite/tests/regression/issue2846.rs ================================================ #![allow(clippy::trivially_copy_pass_by_ref, dead_code)] use serde_derive::Deserialize; macro_rules! declare_in_macro { ($with:literal) => { #[derive(Deserialize)] pub struct S( #[serde(with = $with)] #[allow(dead_code)] i32, ); }; } declare_in_macro!("with"); mod with { use serde::Deserializer; pub fn deserialize<'de, D>(_: D) -> Result where D: Deserializer<'de>, { unimplemented!() } } ================================================ FILE: test_suite/tests/regression.rs ================================================ mod regression { automod::dir!("tests/regression"); } ================================================ FILE: test_suite/tests/test_annotations.rs ================================================ #![allow( clippy::cast_lossless, clippy::derive_partial_eq_without_eq, clippy::from_over_into, // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422 clippy::nonstandard_macro_braces, clippy::too_many_lines, clippy::trivially_copy_pass_by_ref, clippy::type_repetition_in_bounds, clippy::uninlined_format_args, )] use serde::de::{self, Deserialize, Deserializer, IgnoredAny, MapAccess, Unexpected, Visitor}; use serde::ser::{Serialize, Serializer}; use serde_derive::{Deserialize, Serialize}; use serde_test::{ assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error, assert_tokens, Token, }; use std::collections::{BTreeMap, HashMap}; use std::convert::TryFrom; use std::fmt; use std::marker::PhantomData; trait MyDefault: Sized { fn my_default() -> Self; } trait ShouldSkip: Sized { fn should_skip(&self) -> bool; } trait SerializeWith: Sized { fn serialize_with(&self, ser: S) -> Result where S: Serializer; } trait DeserializeWith: Sized { fn deserialize_with<'de, D>(de: D) -> Result where D: Deserializer<'de>; } impl MyDefault for i32 { fn my_default() -> Self { 123 } } impl ShouldSkip for i32 { fn should_skip(&self) -> bool { *self == 123 } } impl SerializeWith for i32 { fn serialize_with(&self, ser: S) -> Result where S: Serializer, { if *self == 123 { true.serialize(ser) } else { false.serialize(ser) } } } impl DeserializeWith for i32 { fn deserialize_with<'de, D>(de: D) -> Result where D: Deserializer<'de>, { if Deserialize::deserialize(de)? { Ok(123) } else { Ok(2) } } } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct DefaultStruct where C: MyDefault, E: MyDefault, { a1: A, #[serde(default)] a2: B, #[serde(default = "MyDefault::my_default")] a3: C, #[serde(skip_deserializing)] a4: D, #[serde(skip_deserializing, default = "MyDefault::my_default")] a5: E, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct DefaultTupleStruct( A, #[serde(default)] B, #[serde(default = "MyDefault::my_default")] C, ) where C: MyDefault; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct CollectOther { a: u32, b: u32, #[serde(flatten)] extra: HashMap, } #[test] fn test_default_struct() { assert_de_tokens( &DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123, }, &[ Token::Struct { name: "DefaultStruct", len: 3, }, Token::Str("a1"), Token::I32(1), Token::Str("a2"), Token::I32(2), Token::Str("a3"), Token::I32(3), Token::Str("a4"), Token::I32(4), Token::Str("a5"), Token::I32(5), Token::StructEnd, ], ); assert_de_tokens( &DefaultStruct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123, }, &[ Token::Struct { name: "DefaultStruct", len: 3, }, Token::Str("a1"), Token::I32(1), Token::StructEnd, ], ); } #[test] fn test_default_tuple() { assert_de_tokens( &DefaultTupleStruct(1, 2, 3), &[ Token::TupleStruct { name: "DefaultTupleStruct", len: 3, }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleStructEnd, ], ); assert_de_tokens( &DefaultTupleStruct(1, 0, 123), &[ Token::TupleStruct { name: "DefaultTupleStruct", len: 3, }, Token::I32(1), Token::TupleStructEnd, ], ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum DefaultStructVariant where C: MyDefault, E: MyDefault, { Struct { a1: A, #[serde(default)] a2: B, #[serde(default = "MyDefault::my_default")] a3: C, #[serde(skip_deserializing)] a4: D, #[serde(skip_deserializing, default = "MyDefault::my_default")] a5: E, }, } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum DefaultTupleVariant where C: MyDefault, { Tuple( A, #[serde(default)] B, #[serde(default = "MyDefault::my_default")] C, ), } #[test] fn test_default_struct_variant() { assert_de_tokens( &DefaultStructVariant::Struct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123, }, &[ Token::StructVariant { name: "DefaultStructVariant", variant: "Struct", len: 3, }, Token::Str("a1"), Token::I32(1), Token::Str("a2"), Token::I32(2), Token::Str("a3"), Token::I32(3), Token::Str("a4"), Token::I32(4), Token::Str("a5"), Token::I32(5), Token::StructVariantEnd, ], ); assert_de_tokens( &DefaultStructVariant::Struct { a1: 1, a2: 0, a3: 123, a4: 0, a5: 123, }, &[ Token::StructVariant { name: "DefaultStructVariant", variant: "Struct", len: 3, }, Token::Str("a1"), Token::I32(1), Token::StructVariantEnd, ], ); } #[test] fn test_default_tuple_variant() { assert_de_tokens( &DefaultTupleVariant::Tuple(1, 2, 3), &[ Token::TupleVariant { name: "DefaultTupleVariant", variant: "Tuple", len: 3, }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleVariantEnd, ], ); assert_de_tokens( &DefaultTupleVariant::Tuple(1, 0, 123), &[ Token::TupleVariant { name: "DefaultTupleVariant", variant: "Tuple", len: 3, }, Token::I32(1), Token::TupleVariantEnd, ], ); } // Does not implement std::default::Default. #[derive(Debug, PartialEq, Deserialize)] struct NoStdDefault(i8); impl MyDefault for NoStdDefault { fn my_default() -> Self { NoStdDefault(123) } } #[derive(Debug, PartialEq, Deserialize)] struct ContainsNoStdDefault { #[serde(default = "MyDefault::my_default")] a: A, } // Tests that a struct field does not need to implement std::default::Default if // it is annotated with `default=...`. #[test] fn test_no_std_default() { assert_de_tokens( &ContainsNoStdDefault { a: NoStdDefault(123), }, &[ Token::Struct { name: "ContainsNoStdDefault", len: 1, }, Token::StructEnd, ], ); assert_de_tokens( &ContainsNoStdDefault { a: NoStdDefault(8) }, &[ Token::Struct { name: "ContainsNoStdDefault", len: 1, }, Token::Str("a"), Token::NewtypeStruct { name: "NoStdDefault", }, Token::I8(8), Token::StructEnd, ], ); } // Does not implement Deserialize. #[derive(Debug, PartialEq)] struct NotDeserializeStruct(i8); impl Default for NotDeserializeStruct { fn default() -> Self { NotDeserializeStruct(123) } } impl DeserializeWith for NotDeserializeStruct { fn deserialize_with<'de, D>(_: D) -> Result where D: Deserializer<'de>, { panic!() } } // Does not implement Deserialize. #[derive(Debug, PartialEq)] enum NotDeserializeEnum { Trouble, } impl MyDefault for NotDeserializeEnum { fn my_default() -> Self { NotDeserializeEnum::Trouble } } #[derive(Debug, PartialEq, Deserialize)] struct ContainsNotDeserialize { #[serde(skip_deserializing)] a: A, #[serde(skip_deserializing, default)] b: B, #[serde(deserialize_with = "DeserializeWith::deserialize_with", default)] c: C, #[serde(skip_deserializing, default = "MyDefault::my_default")] e: E, } // Tests that a struct field does not need to implement Deserialize if it is // annotated with skip_deserializing, whether using the std Default or a // custom default. #[test] fn test_elt_not_deserialize() { assert_de_tokens( &ContainsNotDeserialize { a: NotDeserializeStruct(123), b: NotDeserializeStruct(123), c: NotDeserializeStruct(123), e: NotDeserializeEnum::Trouble, }, &[ Token::Struct { name: "ContainsNotDeserialize", len: 1, }, Token::StructEnd, ], ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] struct DenyUnknown { a1: i32, } #[test] fn test_ignore_unknown() { // 'Default' allows unknown. Basic smoke test of ignore... assert_de_tokens( &DefaultStruct { a1: 1, a2: 2, a3: 3, a4: 0, a5: 123, }, &[ Token::Struct { name: "DefaultStruct", len: 3, }, Token::Str("whoops1"), Token::I32(2), Token::Str("a1"), Token::I32(1), Token::Str("whoops2"), Token::Seq { len: Some(1) }, Token::I32(2), Token::SeqEnd, Token::Str("a2"), Token::I32(2), Token::Str("whoops3"), Token::I32(2), Token::Str("a3"), Token::I32(3), Token::StructEnd, ], ); assert_de_tokens_error::( &[ Token::Struct { name: "DenyUnknown", len: 1, }, Token::Str("a1"), Token::I32(1), Token::Str("whoops"), ], "unknown field `whoops`, expected `a1`", ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename = "Superhero")] struct RenameStruct { a1: i32, #[serde(rename = "a3")] a2: i32, } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename(serialize = "SuperheroSer", deserialize = "SuperheroDe"))] struct RenameStructSerializeDeserialize { a1: i32, #[serde(rename(serialize = "a4", deserialize = "a5"))] a2: i32, } #[derive(Debug, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] struct AliasStruct { a1: i32, #[serde(alias = "a3")] a2: i32, #[serde(alias = "a5", rename = "a6")] a4: i32, } #[test] fn test_rename_struct() { assert_tokens( &RenameStruct { a1: 1, a2: 2 }, &[ Token::Struct { name: "Superhero", len: 2, }, Token::Str("a1"), Token::I32(1), Token::Str("a3"), Token::I32(2), Token::StructEnd, ], ); assert_ser_tokens( &RenameStructSerializeDeserialize { a1: 1, a2: 2 }, &[ Token::Struct { name: "SuperheroSer", len: 2, }, Token::Str("a1"), Token::I32(1), Token::Str("a4"), Token::I32(2), Token::StructEnd, ], ); assert_de_tokens( &RenameStructSerializeDeserialize { a1: 1, a2: 2 }, &[ Token::Struct { name: "SuperheroDe", len: 2, }, Token::Str("a1"), Token::I32(1), Token::Str("a5"), Token::I32(2), Token::StructEnd, ], ); assert_de_tokens( &AliasStruct { a1: 1, a2: 2, a4: 3, }, &[ Token::Struct { name: "AliasStruct", len: 3, }, Token::Str("a1"), Token::I32(1), Token::Str("a2"), Token::I32(2), Token::Str("a5"), Token::I32(3), Token::StructEnd, ], ); assert_de_tokens( &AliasStruct { a1: 1, a2: 2, a4: 3, }, &[ Token::Struct { name: "AliasStruct", len: 3, }, Token::Str("a1"), Token::I32(1), Token::Str("a3"), Token::I32(2), Token::Str("a6"), Token::I32(3), Token::StructEnd, ], ); } #[test] fn test_unknown_field_rename_struct() { assert_de_tokens_error::( &[ Token::Struct { name: "AliasStruct", len: 3, }, Token::Str("a1"), Token::I32(1), Token::Str("a3"), Token::I32(2), Token::Str("a4"), Token::I32(3), ], "unknown field `a4`, expected one of `a1`, `a2`, `a3`, `a5`, `a6`", ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename = "Superhero")] enum RenameEnum { #[serde(rename = "bruce_wayne")] Batman, #[serde(rename = "clark_kent")] Superman(i8), #[serde(rename = "diana_prince")] WonderWoman(i8, i8), #[serde(rename = "barry_allan")] Flash { #[serde(rename = "b")] a: i32, }, } #[derive(Debug, PartialEq, Deserialize, Serialize)] #[serde(rename(serialize = "SuperheroSer", deserialize = "SuperheroDe"))] enum RenameEnumSerializeDeserialize
{ #[serde(rename(serialize = "dick_grayson", deserialize = "jason_todd"))] Robin { a: i8, #[serde(rename(serialize = "c"))] #[serde(rename(deserialize = "d"))] b: A, }, } #[derive(Debug, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] enum AliasEnum { #[serde(rename = "sailor_moon", alias = "usagi_tsukino")] SailorMoon { a: i8, #[serde(alias = "c")] b: i8, #[serde(alias = "e", rename = "f")] d: i8, }, } #[test] fn test_rename_enum() { assert_tokens( &RenameEnum::Batman, &[Token::UnitVariant { name: "Superhero", variant: "bruce_wayne", }], ); assert_tokens( &RenameEnum::Superman(0), &[ Token::NewtypeVariant { name: "Superhero", variant: "clark_kent", }, Token::I8(0), ], ); assert_tokens( &RenameEnum::WonderWoman(0, 1), &[ Token::TupleVariant { name: "Superhero", variant: "diana_prince", len: 2, }, Token::I8(0), Token::I8(1), Token::TupleVariantEnd, ], ); assert_tokens( &RenameEnum::Flash { a: 1 }, &[ Token::StructVariant { name: "Superhero", variant: "barry_allan", len: 1, }, Token::Str("b"), Token::I32(1), Token::StructVariantEnd, ], ); assert_ser_tokens( &RenameEnumSerializeDeserialize::Robin { a: 0, b: String::new(), }, &[ Token::StructVariant { name: "SuperheroSer", variant: "dick_grayson", len: 2, }, Token::Str("a"), Token::I8(0), Token::Str("c"), Token::Str(""), Token::StructVariantEnd, ], ); assert_de_tokens( &RenameEnumSerializeDeserialize::Robin { a: 0, b: String::new(), }, &[ Token::StructVariant { name: "SuperheroDe", variant: "jason_todd", len: 2, }, Token::Str("a"), Token::I8(0), Token::Str("d"), Token::Str(""), Token::StructVariantEnd, ], ); assert_de_tokens( &AliasEnum::SailorMoon { a: 0, b: 1, d: 2 }, &[ Token::StructVariant { name: "AliasEnum", variant: "sailor_moon", len: 5, }, Token::Str("a"), Token::I8(0), Token::Str("b"), Token::I8(1), Token::Str("e"), Token::I8(2), Token::StructVariantEnd, ], ); assert_de_tokens( &AliasEnum::SailorMoon { a: 0, b: 1, d: 2 }, &[ Token::StructVariant { name: "AliasEnum", variant: "usagi_tsukino", len: 5, }, Token::Str("a"), Token::I8(0), Token::Str("c"), Token::I8(1), Token::Str("f"), Token::I8(2), Token::StructVariantEnd, ], ); } #[test] fn test_unknown_field_rename_enum() { assert_de_tokens_error::( &[Token::StructVariant { name: "AliasEnum", variant: "SailorMoon", len: 3, }], "unknown variant `SailorMoon`, expected `sailor_moon` or `usagi_tsukino`", ); assert_de_tokens_error::( &[ Token::StructVariant { name: "AliasEnum", variant: "usagi_tsukino", len: 5, }, Token::Str("a"), Token::I8(0), Token::Str("c"), Token::I8(1), Token::Str("d"), Token::I8(2), ], "unknown field `d`, expected one of `a`, `b`, `c`, `e`, `f`", ); } #[derive(Debug, PartialEq, Serialize)] struct SkipSerializingStruct<'a, B, C> where C: ShouldSkip, { a: &'a i8, #[serde(skip_serializing)] b: B, #[serde(skip_serializing_if = "ShouldSkip::should_skip")] c: C, } #[test] fn test_skip_serializing_struct() { let a = 1; assert_ser_tokens( &SkipSerializingStruct { a: &a, b: 2, c: 3 }, &[ Token::Struct { name: "SkipSerializingStruct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("c"), Token::I32(3), Token::StructEnd, ], ); assert_ser_tokens( &SkipSerializingStruct { a: &a, b: 2, c: 123, }, &[ Token::Struct { name: "SkipSerializingStruct", len: 1, }, Token::Str("a"), Token::I8(1), Token::StructEnd, ], ); } #[derive(Debug, PartialEq, Serialize)] struct SkipSerializingTupleStruct<'a, B, C>( &'a i8, #[serde(skip_serializing)] B, #[serde(skip_serializing_if = "ShouldSkip::should_skip")] C, ) where C: ShouldSkip; #[test] fn test_skip_serializing_tuple_struct() { let a = 1; assert_ser_tokens( &SkipSerializingTupleStruct(&a, 2, 3), &[ Token::TupleStruct { name: "SkipSerializingTupleStruct", len: 2, }, Token::I8(1), Token::I32(3), Token::TupleStructEnd, ], ); assert_ser_tokens( &SkipSerializingTupleStruct(&a, 2, 123), &[ Token::TupleStruct { name: "SkipSerializingTupleStruct", len: 1, }, Token::I8(1), Token::TupleStructEnd, ], ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct SkipStruct { a: i8, #[serde(skip)] b: B, } #[test] fn test_skip_struct() { assert_ser_tokens( &SkipStruct { a: 1, b: 2 }, &[ Token::Struct { name: "SkipStruct", len: 1, }, Token::Str("a"), Token::I8(1), Token::StructEnd, ], ); assert_de_tokens( &SkipStruct { a: 1, b: 0 }, &[ Token::Struct { name: "SkipStruct", len: 1, }, Token::Str("a"), Token::I8(1), Token::StructEnd, ], ); } #[derive(Debug, PartialEq, Serialize)] enum SkipSerializingEnum<'a, B, C> where C: ShouldSkip, { Struct { a: &'a i8, #[serde(skip_serializing)] _b: B, #[serde(skip_serializing_if = "ShouldSkip::should_skip")] c: C, }, Tuple( &'a i8, #[serde(skip_serializing)] B, #[serde(skip_serializing_if = "ShouldSkip::should_skip")] C, ), } #[test] fn test_skip_serializing_enum() { let a = 1; assert_ser_tokens( &SkipSerializingEnum::Struct { a: &a, _b: 2, c: 3 }, &[ Token::StructVariant { name: "SkipSerializingEnum", variant: "Struct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("c"), Token::I32(3), Token::StructVariantEnd, ], ); assert_ser_tokens( &SkipSerializingEnum::Struct { a: &a, _b: 2, c: 123, }, &[ Token::StructVariant { name: "SkipSerializingEnum", variant: "Struct", len: 1, }, Token::Str("a"), Token::I8(1), Token::StructVariantEnd, ], ); assert_ser_tokens( &SkipSerializingEnum::Tuple(&a, 2, 3), &[ Token::TupleVariant { name: "SkipSerializingEnum", variant: "Tuple", len: 2, }, Token::I8(1), Token::I32(3), Token::TupleVariantEnd, ], ); assert_ser_tokens( &SkipSerializingEnum::Tuple(&a, 2, 123), &[ Token::TupleVariant { name: "SkipSerializingEnum", variant: "Tuple", len: 1, }, Token::I8(1), Token::TupleVariantEnd, ], ); } #[derive(Debug, PartialEq)] struct NotSerializeStruct(i8); #[derive(Debug, PartialEq)] enum NotSerializeEnum { Trouble, } impl SerializeWith for NotSerializeEnum { fn serialize_with(&self, ser: S) -> Result where S: Serializer, { "trouble".serialize(ser) } } #[derive(Debug, PartialEq, Serialize)] struct ContainsNotSerialize<'a, B, C, D> where B: 'a, D: SerializeWith, { a: &'a Option, #[serde(skip_serializing)] b: &'a B, #[serde(skip_serializing)] c: Option, #[serde(serialize_with = "SerializeWith::serialize_with")] d: D, } #[test] fn test_elt_not_serialize() { let a = 1; assert_ser_tokens( &ContainsNotSerialize { a: &Some(a), b: &NotSerializeStruct(2), c: Some(NotSerializeEnum::Trouble), d: NotSerializeEnum::Trouble, }, &[ Token::Struct { name: "ContainsNotSerialize", len: 2, }, Token::Str("a"), Token::Some, Token::I8(1), Token::Str("d"), Token::Str("trouble"), Token::StructEnd, ], ); } #[derive(Debug, PartialEq, Serialize)] struct SerializeWithStruct<'a, B> where B: SerializeWith, { a: &'a i8, #[serde(serialize_with = "SerializeWith::serialize_with")] b: B, } #[test] fn test_serialize_with_struct() { let a = 1; assert_ser_tokens( &SerializeWithStruct { a: &a, b: 2 }, &[ Token::Struct { name: "SerializeWithStruct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::Bool(false), Token::StructEnd, ], ); assert_ser_tokens( &SerializeWithStruct { a: &a, b: 123 }, &[ Token::Struct { name: "SerializeWithStruct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::Bool(true), Token::StructEnd, ], ); } #[derive(Debug, PartialEq, Serialize)] enum SerializeWithEnum<'a, B> where B: SerializeWith, { Struct { a: &'a i8, #[serde(serialize_with = "SerializeWith::serialize_with")] b: B, }, } #[test] fn test_serialize_with_enum() { let a = 1; assert_ser_tokens( &SerializeWithEnum::Struct { a: &a, b: 2 }, &[ Token::StructVariant { name: "SerializeWithEnum", variant: "Struct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::Bool(false), Token::StructVariantEnd, ], ); assert_ser_tokens( &SerializeWithEnum::Struct { a: &a, b: 123 }, &[ Token::StructVariant { name: "SerializeWithEnum", variant: "Struct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::Bool(true), Token::StructVariantEnd, ], ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum WithVariant { #[serde(serialize_with = "serialize_unit_variant_as_i8")] #[serde(deserialize_with = "deserialize_i8_as_unit_variant")] Unit, #[serde(serialize_with = "SerializeWith::serialize_with")] #[serde(deserialize_with = "DeserializeWith::deserialize_with")] Newtype(i32), #[serde(serialize_with = "serialize_variant_as_string")] #[serde(deserialize_with = "deserialize_string_as_variant")] Tuple(String, u8), #[serde(serialize_with = "serialize_variant_as_string")] #[serde(deserialize_with = "deserialize_string_as_variant")] Struct { f1: String, f2: u8 }, } fn serialize_unit_variant_as_i8(serializer: S) -> Result where S: Serializer, { serializer.serialize_i8(0) } fn deserialize_i8_as_unit_variant<'de, D>(deserializer: D) -> Result<(), D::Error> where D: Deserializer<'de>, { let n = i8::deserialize(deserializer)?; match n { 0 => Ok(()), _ => Err(de::Error::invalid_value(Unexpected::Signed(n as i64), &"0")), } } fn serialize_variant_as_string(f1: &str, f2: &u8, serializer: S) -> Result where S: Serializer, { serializer.collect_str(&format_args!("{};{:?}", f1, f2)) } fn deserialize_string_as_variant<'de, D>(deserializer: D) -> Result<(String, u8), D::Error> where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; let mut pieces = s.split(';'); let Some(f1) = pieces.next() else { return Err(de::Error::invalid_length(0, &"2")); }; let Some(f2) = pieces.next() else { return Err(de::Error::invalid_length(1, &"2")); }; let Ok(f2) = f2.parse() else { return Err(de::Error::invalid_value( Unexpected::Str(f2), &"an 8-bit signed integer", )); }; Ok((f1.into(), f2)) } #[test] fn test_serialize_with_variant() { assert_ser_tokens( &WithVariant::Unit, &[ Token::NewtypeVariant { name: "WithVariant", variant: "Unit", }, Token::I8(0), ], ); assert_ser_tokens( &WithVariant::Newtype(123), &[ Token::NewtypeVariant { name: "WithVariant", variant: "Newtype", }, Token::Bool(true), ], ); assert_ser_tokens( &WithVariant::Tuple("hello".into(), 0), &[ Token::NewtypeVariant { name: "WithVariant", variant: "Tuple", }, Token::Str("hello;0"), ], ); assert_ser_tokens( &WithVariant::Struct { f1: "world".into(), f2: 1, }, &[ Token::NewtypeVariant { name: "WithVariant", variant: "Struct", }, Token::Str("world;1"), ], ); } #[test] fn test_deserialize_with_variant() { assert_de_tokens( &WithVariant::Unit, &[ Token::NewtypeVariant { name: "WithVariant", variant: "Unit", }, Token::I8(0), ], ); assert_de_tokens( &WithVariant::Newtype(123), &[ Token::NewtypeVariant { name: "WithVariant", variant: "Newtype", }, Token::Bool(true), ], ); assert_de_tokens( &WithVariant::Tuple("hello".into(), 0), &[ Token::NewtypeVariant { name: "WithVariant", variant: "Tuple", }, Token::Str("hello;0"), ], ); assert_de_tokens( &WithVariant::Struct { f1: "world".into(), f2: 1, }, &[ Token::NewtypeVariant { name: "WithVariant", variant: "Struct", }, Token::Str("world;1"), ], ); } #[derive(Debug, PartialEq, Deserialize)] struct DeserializeWithStruct where B: DeserializeWith, { a: i8, #[serde(deserialize_with = "DeserializeWith::deserialize_with")] b: B, } #[test] fn test_deserialize_with_struct() { assert_de_tokens( &DeserializeWithStruct { a: 1, b: 2 }, &[ Token::Struct { name: "DeserializeWithStruct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::Bool(false), Token::StructEnd, ], ); assert_de_tokens( &DeserializeWithStruct { a: 1, b: 123 }, &[ Token::Struct { name: "DeserializeWithStruct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::Bool(true), Token::StructEnd, ], ); } #[derive(Debug, PartialEq, Deserialize)] enum DeserializeWithEnum where B: DeserializeWith, { Struct { a: i8, #[serde(deserialize_with = "DeserializeWith::deserialize_with")] b: B, }, } #[test] fn test_deserialize_with_enum() { assert_de_tokens( &DeserializeWithEnum::Struct { a: 1, b: 2 }, &[ Token::StructVariant { name: "DeserializeWithEnum", variant: "Struct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::Bool(false), Token::StructVariantEnd, ], ); assert_de_tokens( &DeserializeWithEnum::Struct { a: 1, b: 123 }, &[ Token::StructVariant { name: "DeserializeWithEnum", variant: "Struct", len: 2, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::Bool(true), Token::StructVariantEnd, ], ); } #[test] fn test_missing_renamed_field_struct() { assert_de_tokens_error::( &[ Token::Struct { name: "Superhero", len: 2, }, Token::Str("a1"), Token::I32(1), Token::StructEnd, ], "missing field `a3`", ); assert_de_tokens_error::( &[ Token::Struct { name: "SuperheroDe", len: 2, }, Token::Str("a1"), Token::I32(1), Token::StructEnd, ], "missing field `a5`", ); } #[test] fn test_missing_renamed_field_enum() { assert_de_tokens_error::( &[ Token::StructVariant { name: "Superhero", variant: "barry_allan", len: 1, }, Token::StructVariantEnd, ], "missing field `b`", ); assert_de_tokens_error::>( &[ Token::StructVariant { name: "SuperheroDe", variant: "jason_todd", len: 2, }, Token::Str("a"), Token::I8(0), Token::StructVariantEnd, ], "missing field `d`", ); } #[derive(Debug, PartialEq, Deserialize)] enum InvalidLengthEnum { A(i32, i32, i32), B(#[serde(skip_deserializing)] i32, i32, i32), } #[test] fn test_invalid_length_enum() { assert_de_tokens_error::( &[ Token::TupleVariant { name: "InvalidLengthEnum", variant: "A", len: 3, }, Token::I32(1), Token::TupleVariantEnd, ], "invalid length 1, expected tuple variant InvalidLengthEnum::A with 3 elements", ); assert_de_tokens_error::( &[ Token::TupleVariant { name: "InvalidLengthEnum", variant: "B", len: 2, }, Token::I32(1), Token::TupleVariantEnd, ], "invalid length 1, expected tuple variant InvalidLengthEnum::B with 2 elements", ); } #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] #[serde(into = "EnumToU32", from = "EnumToU32")] struct StructFromEnum(Option); impl Into for StructFromEnum { fn into(self) -> EnumToU32 { match self { StructFromEnum(v) => v.into(), } } } impl From for StructFromEnum { fn from(v: EnumToU32) -> Self { StructFromEnum(v.into()) } } #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] #[serde(into = "Option", from = "Option")] enum EnumToU32 { One, Two, Three, Four, Nothing, } impl Into> for EnumToU32 { fn into(self) -> Option { match self { EnumToU32::One => Some(1), EnumToU32::Two => Some(2), EnumToU32::Three => Some(3), EnumToU32::Four => Some(4), EnumToU32::Nothing => None, } } } impl From> for EnumToU32 { fn from(v: Option) -> Self { match v { Some(1) => EnumToU32::One, Some(2) => EnumToU32::Two, Some(3) => EnumToU32::Three, Some(4) => EnumToU32::Four, _ => EnumToU32::Nothing, } } } #[derive(Clone, Deserialize, PartialEq, Debug)] #[serde(try_from = "u32")] enum TryFromU32 { One, Two, } impl TryFrom for TryFromU32 { type Error = String; fn try_from(value: u32) -> Result { match value { 1 => Ok(TryFromU32::One), 2 => Ok(TryFromU32::Two), _ => Err("out of range".to_owned()), } } } #[test] fn test_from_into_traits() { assert_ser_tokens(&EnumToU32::One, &[Token::Some, Token::U32(1)]); assert_ser_tokens(&EnumToU32::Nothing, &[Token::None]); assert_de_tokens(&EnumToU32::Two, &[Token::Some, Token::U32(2)]); assert_ser_tokens(&StructFromEnum(Some(5)), &[Token::None]); assert_ser_tokens(&StructFromEnum(None), &[Token::None]); assert_de_tokens(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]); assert_de_tokens(&TryFromU32::Two, &[Token::U32(2)]); assert_de_tokens_error::(&[Token::U32(5)], "out of range"); } #[test] fn test_collect_other() { let mut extra = HashMap::new(); extra.insert("c".into(), 3); assert_tokens( &CollectOther { a: 1, b: 2, extra }, &[ Token::Map { len: None }, Token::Str("a"), Token::U32(1), Token::Str("b"), Token::U32(2), Token::Str("c"), Token::U32(3), Token::MapEnd, ], ); } #[test] fn test_partially_untagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Exp { Lambda(u32, Box), #[serde(untagged)] App(Box, Box), #[serde(untagged)] Var(u32), } use Exp::*; let data = Lambda(0, Box::new(App(Box::new(Var(0)), Box::new(Var(0))))); assert_tokens( &data, &[ Token::TupleVariant { name: "Exp", variant: "Lambda", len: 2, }, Token::U32(0), Token::Tuple { len: 2 }, Token::U32(0), Token::U32(0), Token::TupleEnd, Token::TupleVariantEnd, ], ); } #[test] fn test_partially_untagged_enum_generic() { trait Trait { type Assoc; type Assoc2; } #[derive(Serialize, Deserialize, PartialEq, Debug)] enum E where A: Trait, { A(A::Assoc), #[serde(untagged)] B(A::Assoc2), } impl Trait for () { type Assoc = T; type Assoc2 = bool; } type MyE = E<(), bool, u32>; use E::*; assert_tokens::(&B(true), &[Token::Bool(true)]); assert_tokens::( &A(5), &[ Token::NewtypeVariant { name: "E", variant: "A", }, Token::U32(5), ], ); } #[test] fn test_partially_untagged_enum_desugared() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Test { A(u32, u32), B(u32), #[serde(untagged)] C(u32), #[serde(untagged)] D(u32, u32), } use Test::*; mod desugared { use super::*; #[derive(Serialize, Deserialize, PartialEq, Debug)] pub(super) enum Test { A(u32, u32), B(u32), } } use desugared::Test as TestTagged; #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(untagged)] enum TestUntagged { Tagged(TestTagged), C(u32), D(u32, u32), } impl From for TestUntagged { fn from(test: Test) -> Self { match test { A(x, y) => TestUntagged::Tagged(TestTagged::A(x, y)), B(x) => TestUntagged::Tagged(TestTagged::B(x)), C(x) => TestUntagged::C(x), D(x, y) => TestUntagged::D(x, y), } } } fn assert_tokens_desugared(value: Test, tokens: &[Token]) { assert_tokens(&value, tokens); let desugared: TestUntagged = value.into(); assert_tokens(&desugared, tokens); } assert_tokens_desugared( A(0, 1), &[ Token::TupleVariant { name: "Test", variant: "A", len: 2, }, Token::U32(0), Token::U32(1), Token::TupleVariantEnd, ], ); assert_tokens_desugared( B(1), &[ Token::NewtypeVariant { name: "Test", variant: "B", }, Token::U32(1), ], ); assert_tokens_desugared(C(2), &[Token::U32(2)]); assert_tokens_desugared( D(3, 5), &[ Token::Tuple { len: 2 }, Token::U32(3), Token::U32(5), Token::TupleEnd, ], ); } #[test] fn test_partially_untagged_internally_tagged_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "t")] enum Data { A, B, #[serde(untagged)] Var(u32), } let data = Data::A; assert_de_tokens( &data, &[ Token::Map { len: None }, Token::Str("t"), Token::Str("A"), Token::MapEnd, ], ); let data = Data::Var(42); assert_de_tokens(&data, &[Token::U32(42)]); // TODO test error output } #[test] fn test_transparent_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(transparent)] struct Transparent { #[serde(skip)] a: bool, b: u32, #[serde(skip)] c: bool, d: PhantomData<()>, } assert_tokens( &Transparent { a: false, b: 1, c: false, d: PhantomData, }, &[Token::U32(1)], ); } #[test] fn test_transparent_tuple_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(transparent)] struct Transparent( #[serde(skip)] bool, u32, #[serde(skip)] bool, PhantomData<()>, ); assert_tokens(&Transparent(false, 1, false, PhantomData), &[Token::U32(1)]); } #[test] fn test_expecting_message() { #[derive(Deserialize, PartialEq, Debug)] #[serde(expecting = "something strange...")] struct Unit; #[derive(Deserialize)] #[serde(expecting = "something strange...")] struct Newtype(bool); #[derive(Deserialize)] #[serde(expecting = "something strange...")] struct Tuple(u32, bool); #[derive(Deserialize)] #[serde(expecting = "something strange...")] struct Struct { #[allow(dead_code)] question: String, #[allow(dead_code)] answer: u32, } assert_de_tokens_error::( &[Token::Str("Unit")], r#"invalid type: string "Unit", expected something strange..."#, ); assert_de_tokens_error::( &[Token::Str("Newtype")], r#"invalid type: string "Newtype", expected something strange..."#, ); assert_de_tokens_error::( &[Token::Str("Tuple")], r#"invalid type: string "Tuple", expected something strange..."#, ); assert_de_tokens_error::( &[Token::Str("Struct")], r#"invalid type: string "Struct", expected something strange..."#, ); } #[test] fn test_expecting_message_externally_tagged_enum() { #[derive(Deserialize)] #[serde(expecting = "something strange...")] enum Enum { ExternallyTagged, } assert_de_tokens_error::( &[Token::Str("ExternallyTagged")], r#"invalid type: string "ExternallyTagged", expected something strange..."#, ); // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Enum { name: "Enum" }, Token::Unit], "invalid type: unit value, expected variant identifier", ); } #[test] fn test_expecting_message_identifier_enum() { #[derive(Deserialize)] #[serde(field_identifier)] #[serde(expecting = "something strange...")] enum FieldEnum { Field, } #[derive(Deserialize)] #[serde(variant_identifier)] #[serde(expecting = "something strange...")] enum VariantEnum { Variant, } assert_de_tokens_error::( &[Token::Unit], "invalid type: unit value, expected something strange...", ); assert_de_tokens_error::( &[ Token::Enum { name: "FieldEnum" }, Token::Str("Unknown"), Token::None, ], "invalid type: map, expected something strange...", ); assert_de_tokens_error::( &[Token::Unit], "invalid type: unit value, expected something strange...", ); assert_de_tokens_error::( &[ Token::Enum { name: "VariantEnum", }, Token::Str("Unknown"), Token::None, ], "invalid type: map, expected something strange...", ); } mod flatten { use super::*; #[test] fn complex() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Outer { y: u32, #[serde(flatten)] first: First, #[serde(flatten)] second: Second, z: u32, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct First { a: u32, b: bool, c: Vec, d: String, e: Option, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Second { f: u32, } assert_de_tokens( &Outer { y: 0, first: First { a: 1, b: true, c: vec!["a".into(), "b".into()], d: "c".into(), e: Some(2), }, second: Second { f: 3 }, z: 4, }, &[ Token::Map { len: None }, Token::Str("y"), Token::U32(0), Token::Str("a"), Token::U32(1), Token::Str("b"), Token::Bool(true), Token::Str("c"), Token::Seq { len: Some(2) }, Token::Str("a"), Token::Str("b"), Token::SeqEnd, Token::Str("d"), Token::Str("c"), Token::Str("e"), Token::U64(2), Token::Str("f"), Token::U32(3), Token::Str("z"), Token::U32(4), Token::MapEnd, ], ); assert_ser_tokens( &Outer { y: 0, first: First { a: 1, b: true, c: vec!["a".into(), "b".into()], d: "c".into(), e: Some(2), }, second: Second { f: 3 }, z: 4, }, &[ Token::Map { len: None }, Token::Str("y"), Token::U32(0), Token::Str("a"), Token::U32(1), Token::Str("b"), Token::Bool(true), Token::Str("c"), Token::Seq { len: Some(2) }, Token::Str("a"), Token::Str("b"), Token::SeqEnd, Token::Str("d"), Token::Str("c"), Token::Str("e"), Token::Some, Token::U64(2), Token::Str("f"), Token::U32(3), Token::Str("z"), Token::U32(4), Token::MapEnd, ], ); } #[test] fn map_twice() { #[derive(Debug, PartialEq, Deserialize)] struct Outer { #[serde(flatten)] first: BTreeMap, #[serde(flatten)] between: Inner, #[serde(flatten)] second: BTreeMap, } #[derive(Debug, PartialEq, Deserialize)] struct Inner { y: String, } assert_de_tokens( &Outer { first: { let mut first = BTreeMap::new(); first.insert("x".to_owned(), "X".to_owned()); first.insert("y".to_owned(), "Y".to_owned()); first }, between: Inner { y: "Y".to_owned() }, second: { let mut second = BTreeMap::new(); second.insert("x".to_owned(), "X".to_owned()); second }, }, &[ Token::Map { len: None }, Token::Str("x"), Token::Str("X"), Token::Str("y"), Token::Str("Y"), Token::MapEnd, ], ); } #[test] fn unsupported_type() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Outer { outer: String, #[serde(flatten)] inner: String, } assert_ser_tokens_error( &Outer { outer: "foo".into(), inner: "bar".into(), }, &[ Token::Map { len: None }, Token::Str("outer"), Token::Str("foo"), ], "can only flatten structs and maps (got a string)", ); assert_de_tokens_error::( &[ Token::Map { len: None }, Token::Str("outer"), Token::Str("foo"), Token::Str("a"), Token::Str("b"), Token::MapEnd, ], "can only flatten structs and maps", ); } #[test] fn unknown_field() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] struct Outer { dummy: String, #[serde(flatten)] inner: Inner, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Inner { foo: HashMap, } assert_de_tokens_error::( &[ Token::Struct { name: "Outer", len: 1, }, Token::Str("dummy"), Token::Str("23"), Token::Str("foo"), Token::Map { len: None }, Token::Str("a"), Token::U32(1), Token::Str("b"), Token::U32(2), Token::MapEnd, Token::Str("bar"), Token::U32(23), Token::StructEnd, ], "unknown field `bar`", ); } #[test] fn non_string_keys() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct TestStruct { name: String, age: u32, #[serde(flatten)] mapping: HashMap, } let mut mapping = HashMap::new(); mapping.insert(0, 42); assert_tokens( &TestStruct { name: "peter".into(), age: 3, mapping, }, &[ Token::Map { len: None }, Token::Str("name"), Token::Str("peter"), Token::Str("age"), Token::U32(3), Token::U32(0), Token::U32(42), Token::MapEnd, ], ); } #[test] fn lifetime_propagation() { #[derive(Deserialize, Serialize, Debug, PartialEq)] struct A { #[serde(flatten)] t: T, } #[derive(Deserialize, Serialize, Debug, PartialEq)] struct B<'a> { #[serde(flatten, borrow)] t: HashMap<&'a str, u32>, } #[derive(Deserialize, Serialize, Debug, PartialEq)] struct C<'a> { #[serde(flatten, borrow)] t: HashMap<&'a [u8], u32>, } let mut owned_map = HashMap::new(); owned_map.insert("x".to_string(), 42u32); assert_tokens( &A { t: owned_map }, &[ Token::Map { len: None }, Token::Str("x"), Token::U32(42), Token::MapEnd, ], ); let mut borrowed_map = HashMap::new(); borrowed_map.insert("x", 42u32); assert_ser_tokens( &B { t: borrowed_map.clone(), }, &[ Token::Map { len: None }, Token::BorrowedStr("x"), Token::U32(42), Token::MapEnd, ], ); assert_de_tokens( &B { t: borrowed_map }, &[ Token::Map { len: None }, Token::BorrowedStr("x"), Token::U32(42), Token::MapEnd, ], ); let mut borrowed_map = HashMap::new(); borrowed_map.insert(&b"x"[..], 42u32); assert_ser_tokens( &C { t: borrowed_map.clone(), }, &[ Token::Map { len: None }, Token::Seq { len: Some(1) }, Token::U8(120), Token::SeqEnd, Token::U32(42), Token::MapEnd, ], ); assert_de_tokens( &C { t: borrowed_map }, &[ Token::Map { len: None }, Token::BorrowedBytes(b"x"), Token::U32(42), Token::MapEnd, ], ); } // Regression test for https://github.com/serde-rs/serde/issues/1904 #[test] fn enum_tuple_and_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Outer { Tuple(f64, i32), Flatten { #[serde(flatten)] nested: Nested, }, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Nested { a: i32, b: i32, } assert_tokens( &Outer::Tuple(1.2, 3), &[ Token::TupleVariant { name: "Outer", variant: "Tuple", len: 2, }, Token::F64(1.2), Token::I32(3), Token::TupleVariantEnd, ], ); assert_tokens( &Outer::Flatten { nested: Nested { a: 1, b: 2 }, }, &[ Token::NewtypeVariant { name: "Outer", variant: "Flatten", }, Token::Map { len: None }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::MapEnd, ], ); } #[test] fn option() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Outer { #[serde(flatten)] inner1: Option, #[serde(flatten)] inner2: Option, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Inner1 { inner1: i32, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Inner2 { inner2: i32, } assert_tokens( &Outer { inner1: Some(Inner1 { inner1: 1 }), inner2: Some(Inner2 { inner2: 2 }), }, &[ Token::Map { len: None }, Token::Str("inner1"), Token::I32(1), Token::Str("inner2"), Token::I32(2), Token::MapEnd, ], ); assert_tokens( &Outer { inner1: Some(Inner1 { inner1: 1 }), inner2: None, }, &[ Token::Map { len: None }, Token::Str("inner1"), Token::I32(1), Token::MapEnd, ], ); assert_tokens( &Outer { inner1: None, inner2: Some(Inner2 { inner2: 2 }), }, &[ Token::Map { len: None }, Token::Str("inner2"), Token::I32(2), Token::MapEnd, ], ); assert_tokens( &Outer { inner1: None, inner2: None, }, &[Token::Map { len: None }, Token::MapEnd], ); } #[test] fn ignored_any() { #[derive(Deserialize, PartialEq, Debug)] struct Outer { #[serde(flatten)] inner: IgnoredAny, } assert_de_tokens( &Outer { inner: IgnoredAny }, &[Token::Map { len: None }, Token::MapEnd], ); assert_de_tokens( &Outer { inner: IgnoredAny }, &[ Token::Struct { name: "DoNotMatter", len: 0, }, Token::StructEnd, ], ); } #[test] fn flatten_any_after_flatten_struct() { #[derive(PartialEq, Debug)] struct Any; impl<'de> Deserialize<'de> for Any { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct AnyVisitor; impl<'de> Visitor<'de> for AnyVisitor { type Value = Any; fn expecting(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { unimplemented!() } fn visit_map(self, mut map: M) -> Result where M: MapAccess<'de>, { while let Some((Any, Any)) = map.next_entry()? {} Ok(Any) } } deserializer.deserialize_any(AnyVisitor) } } #[derive(Deserialize, PartialEq, Debug)] struct Outer { #[serde(flatten)] inner: Inner, #[serde(flatten)] extra: Any, } #[derive(Deserialize, PartialEq, Debug)] struct Inner { inner: i32, } let s = Outer { inner: Inner { inner: 0 }, extra: Any, }; assert_de_tokens( &s, &[ Token::Map { len: None }, Token::Str("inner"), Token::I32(0), Token::MapEnd, ], ); } #[test] fn alias() { #[derive(Debug, PartialEq, Deserialize)] struct Outer { #[serde(flatten)] a: AliasStruct, b: i32, } assert_de_tokens( &Outer { a: AliasStruct { a1: 1, a2: 2, a4: 4, }, b: 7, }, &[ Token::Struct { name: "Outer", len: 4, }, Token::Str("a1"), Token::I32(1), Token::Str("a2"), Token::I32(2), Token::Str("a5"), Token::I32(4), Token::Str("b"), Token::I32(7), Token::StructEnd, ], ); assert_de_tokens( &Outer { a: AliasStruct { a1: 1, a2: 2, a4: 4, }, b: 7, }, &[ Token::Struct { name: "Outer", len: 4, }, Token::Str("a1"), Token::I32(1), Token::Str("a2"), Token::I32(2), Token::Str("a6"), Token::I32(4), Token::Str("b"), Token::I32(7), Token::StructEnd, ], ); } mod unit { use super::*; #[test] fn unit() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Response { #[serde(flatten)] data: T, status: usize, } assert_tokens( &Response { data: (), status: 0, }, &[ Token::Map { len: None }, Token::Str("status"), Token::U64(0), Token::MapEnd, ], ); } #[test] fn unit_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Response { #[serde(flatten)] data: T, status: usize, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Unit; assert_tokens( &Response { data: Unit, status: 0, }, &[ Token::Map { len: None }, Token::Str("status"), Token::U64(0), Token::MapEnd, ], ); } } mod enum_ { use super::*; mod externally_tagged { use super::*; use std::iter::FromIterator; #[test] fn straightforward() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Data { A { a: i32, #[serde(flatten)] flat: Flat, }, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Flat { b: i32, } let data = Data::A { a: 0, flat: Flat { b: 0 }, }; assert_tokens( &data, &[ Token::NewtypeVariant { name: "Data", variant: "A", }, Token::Map { len: None }, Token::Str("a"), Token::I32(0), Token::Str("b"), Token::I32(0), Token::MapEnd, ], ); } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Flatten { #[serde(flatten)] data: Enum, #[serde(flatten)] extra: HashMap, } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum Enum { Unit, Newtype(HashMap), Tuple(u32, u32), Struct { index: u32, value: u32 }, } #[test] fn unit() { let value = Flatten { data: Enum::Unit, extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), }; assert_tokens( &value, &[ Token::Map { len: None }, // data Token::Str("Unit"), // variant Token::Unit, // extra Token::Str("extra_key"), Token::Str("extra value"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: None }, // extra Token::Str("extra_key"), Token::Str("extra value"), // data Token::Str("Unit"), // variant Token::Unit, Token::MapEnd, ], ); } #[test] fn newtype() { let value = Flatten { data: Enum::Newtype(HashMap::from_iter([("key".into(), "value".into())])), extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), }; assert_tokens( &value, &[ Token::Map { len: None }, // data Token::Str("Newtype"), // variant Token::Map { len: Some(1) }, Token::Str("key"), Token::Str("value"), Token::MapEnd, // extra Token::Str("extra_key"), Token::Str("extra value"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: None }, // extra Token::Str("extra_key"), Token::Str("extra value"), // data Token::Str("Newtype"), // variant Token::Map { len: Some(1) }, Token::Str("key"), Token::Str("value"), Token::MapEnd, Token::MapEnd, ], ); } // Reaches crate::private::de::content::VariantDeserializer::tuple_variant // Content::Seq case // via FlatMapDeserializer::deserialize_enum #[test] fn tuple() { let value = Flatten { data: Enum::Tuple(0, 42), extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), }; assert_tokens( &value, &[ Token::Map { len: None }, // data Token::Str("Tuple"), // variant Token::Seq { len: Some(2) }, Token::U32(0), Token::U32(42), Token::SeqEnd, // extra Token::Str("extra_key"), Token::Str("extra value"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: None }, // extra Token::Str("extra_key"), Token::Str("extra value"), // data Token::Str("Tuple"), // variant Token::Seq { len: Some(2) }, Token::U32(0), Token::U32(42), Token::SeqEnd, Token::MapEnd, ], ); } // Reaches crate::private::de::content::VariantDeserializer::struct_variant // Content::Seq case // via FlatMapDeserializer::deserialize_enum #[test] fn struct_from_seq() { let value = Flatten { data: Enum::Struct { index: 0, value: 42, }, extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), }; assert_de_tokens( &value, &[ Token::Map { len: None }, // data Token::Str("Struct"), // variant Token::Seq { len: Some(2) }, Token::U32(0), // index Token::U32(42), // value Token::SeqEnd, // extra Token::Str("extra_key"), Token::Str("extra value"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: None }, // extra Token::Str("extra_key"), Token::Str("extra value"), // data Token::Str("Struct"), // variant Token::Seq { len: Some(2) }, Token::U32(0), // index Token::U32(42), // value Token::SeqEnd, Token::MapEnd, ], ); } // Reaches crate::private::de::content::VariantDeserializer::struct_variant // Content::Map case // via FlatMapDeserializer::deserialize_enum #[test] fn struct_from_map() { let value = Flatten { data: Enum::Struct { index: 0, value: 42, }, extra: HashMap::from_iter([("extra_key".into(), "extra value".into())]), }; assert_tokens( &value, &[ Token::Map { len: None }, // data Token::Str("Struct"), // variant Token::Struct { len: 2, name: "Struct", }, Token::Str("index"), Token::U32(0), Token::Str("value"), Token::U32(42), Token::StructEnd, // extra Token::Str("extra_key"), Token::Str("extra value"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: None }, // extra Token::Str("extra_key"), Token::Str("extra value"), // data 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::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 { Unit, Newtype(NewtypeVariant), Struct { index: u32, value: u32 }, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct NewtypeVariant { value: u32, } #[test] fn unit() { let value = Flatten { outer: 42, data: NewtypeWrapper(Enum::Unit), }; // Field order: outer, [tag] assert_tokens( &value, &[ Token::Map { len: None }, // outer Token::Str("outer"), Token::U32(42), // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Unit", }, // content missing Token::MapEnd, ], ); // Field order: [tag], outer assert_de_tokens( &value, &[ Token::Map { len: None }, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Unit", }, // content missing // outer Token::Str("outer"), Token::U32(42), Token::MapEnd, ], ); // Field order: outer, [tag, content] assert_de_tokens( &value, &[ Token::Map { len: None }, // outer Token::Str("outer"), Token::U32(42), // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Unit", }, // content Token::Str("content"), Token::Unit, Token::MapEnd, ], ); // Field order: outer, [content, tag] assert_de_tokens( &value, &[ Token::Map { len: None }, // outer Token::Str("outer"), Token::U32(42), // content Token::Str("content"), Token::Unit, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Unit", }, Token::MapEnd, ], ); // Field order: [tag, content], outer assert_de_tokens( &value, &[ Token::Map { len: None }, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Unit", }, // content Token::Str("content"), Token::Unit, // outer Token::Str("outer"), Token::U32(42), Token::MapEnd, ], ); // Field order: [content, tag], outer assert_de_tokens( &value, &[ Token::Map { len: None }, // content Token::Str("content"), Token::Unit, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Unit", }, // outer Token::Str("outer"), Token::U32(42), Token::MapEnd, ], ); // Field order: [tag], outer, [content] assert_de_tokens( &value, &[ Token::Map { len: None }, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Unit", }, // outer Token::Str("outer"), Token::U32(42), // content Token::Str("content"), Token::Unit, Token::MapEnd, ], ); // Field order: [content], outer, [tag] assert_de_tokens( &value, &[ Token::Map { len: None }, // content Token::Str("content"), Token::Unit, // outer Token::Str("outer"), Token::U32(42), // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Unit", }, Token::MapEnd, ], ); } #[test] fn newtype() { let value = Flatten { outer: 42, data: NewtypeWrapper(Enum::Newtype(NewtypeVariant { value: 23 })), }; // Field order: outer, [tag, content] assert_tokens( &value, &[ Token::Map { len: None }, // outer Token::Str("outer"), Token::U32(42), // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Newtype", }, // content Token::Str("content"), Token::Struct { len: 1, name: "NewtypeVariant", }, Token::Str("value"), Token::U32(23), Token::StructEnd, Token::MapEnd, ], ); // Field order: outer, [content, tag] assert_de_tokens( &value, &[ Token::Map { len: None }, // outer Token::Str("outer"), Token::U32(42), // content Token::Str("content"), Token::Struct { len: 1, name: "NewtypeVariant", }, Token::Str("value"), Token::U32(23), Token::StructEnd, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Newtype", }, Token::MapEnd, ], ); // Field order: [tag, content], outer assert_de_tokens( &value, &[ Token::Map { len: None }, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Newtype", }, // content Token::Str("content"), Token::Struct { len: 1, name: "NewtypeVariant", }, Token::Str("value"), Token::U32(23), Token::StructEnd, // outer Token::Str("outer"), Token::U32(42), Token::MapEnd, ], ); // Field order: [content, tag], outer assert_de_tokens( &value, &[ Token::Map { len: None }, // content Token::Str("content"), Token::Struct { len: 1, name: "NewtypeVariant", }, Token::Str("value"), Token::U32(23), Token::StructEnd, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Newtype", }, // outer Token::Str("outer"), Token::U32(42), Token::MapEnd, ], ); // Field order: [tag], outer, [content] assert_de_tokens( &value, &[ Token::Map { len: None }, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Newtype", }, // outer Token::Str("outer"), Token::U32(42), // content Token::Str("content"), Token::Struct { len: 1, name: "NewtypeVariant", }, Token::Str("value"), Token::U32(23), Token::StructEnd, Token::MapEnd, ], ); // Field order: [content], outer, [tag] assert_de_tokens( &value, &[ Token::Map { len: None }, // content Token::Str("content"), Token::Struct { len: 1, name: "NewtypeVariant", }, Token::Str("value"), Token::U32(23), Token::StructEnd, // outer Token::Str("outer"), Token::U32(42), // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Newtype", }, Token::MapEnd, ], ); } #[test] fn struct_() { let value = Flatten { outer: 42, data: NewtypeWrapper(Enum::Struct { index: 0, value: 42, }), }; // Field order: outer, [tag, content] assert_tokens( &value, &[ Token::Map { len: None }, // outer Token::Str("outer"), Token::U32(42), // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Struct", }, // content 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, ], ); // Field order: outer, [content, tag] assert_de_tokens( &value, &[ Token::Map { len: None }, // outer Token::Str("outer"), Token::U32(42), // content Token::Str("content"), Token::Struct { len: 2, name: "Struct", }, Token::Str("index"), Token::U32(0), Token::Str("value"), Token::U32(42), Token::StructEnd, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Struct", }, Token::MapEnd, ], ); // Field order: [tag, content], outer assert_de_tokens( &value, &[ Token::Map { len: None }, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Struct", }, // content Token::Str("content"), Token::Struct { len: 2, name: "Struct", }, Token::Str("index"), Token::U32(0), Token::Str("value"), Token::U32(42), Token::StructEnd, // outer Token::Str("outer"), Token::U32(42), Token::MapEnd, ], ); // Field order: [content, tag], outer assert_de_tokens( &value, &[ Token::Map { len: None }, // content Token::Str("content"), Token::Struct { len: 2, name: "Struct", }, Token::Str("index"), Token::U32(0), Token::Str("value"), Token::U32(42), Token::StructEnd, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Struct", }, // outer Token::Str("outer"), Token::U32(42), Token::MapEnd, ], ); // Field order: [tag], outer, [content] assert_de_tokens( &value, &[ Token::Map { len: None }, // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Struct", }, // outer Token::Str("outer"), Token::U32(42), // content 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, ], ); // Field order: [content], outer, [tag] assert_de_tokens( &value, &[ Token::Map { len: None }, // content Token::Str("content"), Token::Struct { len: 2, name: "Struct", }, Token::Str("index"), Token::U32(0), Token::Str("value"), Token::U32(42), Token::StructEnd, // outer Token::Str("outer"), Token::U32(42), // tag Token::Str("tag"), Token::UnitVariant { name: "Enum", variant: "Struct", }, 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 }, } let value = Flatten { x: X::B { b: 1 }, y: Y::D { d: 2 }, }; assert_tokens( &value, &[ Token::Map { len: None }, // x Token::Str("typeX"), Token::Str("B"), Token::Str("b"), Token::I32(1), // y Token::Str("typeY"), Token::Str("D"), Token::Str("d"), Token::I32(2), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: None }, // y Token::Str("typeY"), Token::Str("D"), Token::Str("d"), Token::I32(2), // x Token::Str("typeX"), Token::Str("B"), Token::Str("b"), Token::I32(1), Token::MapEnd, ], ); } #[test] fn unit_enum_with_unknown_fields() { #[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, } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "typeY")] enum Y { B { c: u32 }, } let value = Flatten { x: X::A, y: Y::B { c: 0 }, }; assert_tokens( &value, &[ Token::Map { len: None }, // x Token::Str("typeX"), Token::Str("A"), // y Token::Str("typeY"), Token::Str("B"), Token::Str("c"), Token::U32(0), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: None }, // y Token::Str("typeY"), Token::Str("B"), Token::Str("c"), Token::U32(0), // x Token::Str("typeX"), Token::Str("A"), 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, ], ); } } } } ================================================ FILE: test_suite/tests/test_borrow.rs ================================================ #![allow( clippy::derive_partial_eq_without_eq, clippy::items_after_statements, clippy::used_underscore_binding, // We use lots of declarations inside function bodies to avoid conflicts, // but they aren't used. We just want to make sure they compile. dead_code, )] use serde::de::value::{BorrowedStrDeserializer, MapDeserializer}; use serde::de::{Deserialize, Deserializer, IntoDeserializer}; use serde_derive::Deserialize; use serde_test::{assert_de_tokens, assert_de_tokens_error, Token}; use std::borrow::Cow; #[test] fn test_borrowed_str() { assert_de_tokens(&"borrowed", &[Token::BorrowedStr("borrowed")]); } #[test] fn test_borrowed_str_from_string() { assert_de_tokens_error::<&str>( &[Token::String("borrowed")], "invalid type: string \"borrowed\", expected a borrowed string", ); } #[test] fn test_borrowed_str_from_str() { assert_de_tokens_error::<&str>( &[Token::Str("borrowed")], "invalid type: string \"borrowed\", expected a borrowed string", ); } #[test] fn test_string_from_borrowed_str() { assert_de_tokens(&"owned".to_owned(), &[Token::BorrowedStr("owned")]); } #[test] fn test_borrowed_bytes() { assert_de_tokens(&&b"borrowed"[..], &[Token::BorrowedBytes(b"borrowed")]); } #[test] fn test_borrowed_bytes_from_bytebuf() { assert_de_tokens_error::<&[u8]>( &[Token::ByteBuf(b"borrowed")], "invalid type: byte array, expected a borrowed byte array", ); } #[test] fn test_borrowed_bytes_from_bytes() { assert_de_tokens_error::<&[u8]>( &[Token::Bytes(b"borrowed")], "invalid type: byte array, expected a borrowed byte array", ); } #[test] fn test_tuple() { assert_de_tokens( &("str", &b"bytes"[..]), &[ Token::Tuple { len: 2 }, Token::BorrowedStr("str"), Token::BorrowedBytes(b"bytes"), Token::TupleEnd, ], ); } #[test] fn test_struct() { #[derive(Deserialize, Debug, PartialEq)] struct Borrowing<'a, 'b> { bs: &'a str, bb: &'b [u8], } assert_de_tokens( &Borrowing { bs: "str", bb: b"bytes", }, &[ Token::Struct { name: "Borrowing", len: 2, }, Token::BorrowedStr("bs"), Token::BorrowedStr("str"), Token::BorrowedStr("bb"), Token::BorrowedBytes(b"bytes"), Token::StructEnd, ], ); } #[test] fn test_field_identifier() { #[derive(Deserialize, Debug, PartialEq)] #[serde(field_identifier)] enum FieldStr<'a> { #[serde(borrow)] Str(&'a str), } assert_de_tokens(&FieldStr::Str("value"), &[Token::BorrowedStr("value")]); #[derive(Deserialize, Debug, PartialEq)] #[serde(field_identifier)] enum FieldBytes<'a> { #[serde(borrow)] Bytes(&'a [u8]), } assert_de_tokens( &FieldBytes::Bytes(b"value"), &[Token::BorrowedBytes(b"value")], ); } #[test] fn test_cow() { #[derive(Deserialize)] struct Cows<'a, 'b> { copied: Cow<'a, str>, #[serde(borrow)] borrowed: Cow<'b, str>, } struct BorrowedStr(&'static str); impl<'de> IntoDeserializer<'de> for BorrowedStr { type Deserializer = BorrowedStrDeserializer<'de, serde::de::value::Error>; fn into_deserializer(self) -> Self::Deserializer { BorrowedStrDeserializer::new(self.0) } } let de = MapDeserializer::new(IntoIterator::into_iter([ ("copied", BorrowedStr("copied")), ("borrowed", BorrowedStr("borrowed")), ])); let cows = Cows::deserialize(de).unwrap(); match cows.copied { Cow::Owned(ref s) if s == "copied" => {} _ => panic!("expected a copied string"), } match cows.borrowed { Cow::Borrowed("borrowed") => {} _ => panic!("expected a borrowed string"), } } #[test] fn test_lifetimes() { #[derive(Deserialize)] pub struct Cows<'a, 'b> { _copied: Cow<'a, str>, #[serde(borrow)] _borrowed: Cow<'b, str>, } // Tests that `'de: 'a` is not required by the Deserialize impl. fn _cows_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Cows<'a, 'b> where D: Deserializer<'de>, { Deserialize::deserialize(deserializer).unwrap() } #[derive(Deserialize)] pub struct Wrap<'a, 'b> { #[serde(borrow = "'b")] _cows: Cows<'a, 'b>, } // Tests that `'de: 'a` is not required by the Deserialize impl. fn _wrap_lifetimes<'de: 'b, 'a, 'b, D>(deserializer: D) -> Wrap<'a, 'b> where D: Deserializer<'de>, { Deserialize::deserialize(deserializer).unwrap() } } ================================================ FILE: test_suite/tests/test_de.rs ================================================ #![allow( clippy::cast_lossless, clippy::decimal_literal_representation, clippy::derive_partial_eq_without_eq, clippy::empty_enums, clippy::manual_assert, clippy::needless_pass_by_value, clippy::uninlined_format_args, clippy::unreadable_literal )] #![cfg_attr(feature = "unstable", feature(never_type))] use serde::de::value::{F32Deserializer, F64Deserializer}; use serde::de::{Deserialize, DeserializeOwned, Deserializer, IntoDeserializer}; use serde_derive::Deserialize; use serde_test::{assert_de_tokens, Configure, Token}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::default::Default; use std::ffi::{CStr, CString, OsString}; use std::fmt::Debug; use std::iter; use std::net; use std::num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Saturating, Wrapping, }; use std::ops::Bound; use std::path::{Path, PathBuf}; use std::rc::{Rc, Weak as RcWeak}; use std::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, Ordering, }; #[cfg(target_arch = "x86_64")] use std::sync::atomic::{AtomicI64, AtomicU64}; use std::sync::{Arc, Weak as ArcWeak}; use std::time::{Duration, UNIX_EPOCH}; #[macro_use] mod macros; ////////////////////////////////////////////////////////////////////////// #[derive(Copy, Clone, PartialEq, Debug, Deserialize)] struct UnitStruct; #[derive(Copy, Clone, PartialEq, Debug, Deserialize)] struct GenericUnitStruct; #[derive(PartialEq, Debug, Deserialize)] struct NewtypeStruct(i32); #[derive(PartialEq, Debug, Deserialize)] struct TupleStruct(i32, i32, i32); #[derive(PartialEq, Debug, Deserialize)] struct Struct { a: i32, b: i32, #[serde(skip_deserializing)] c: i32, } #[derive(PartialEq, Debug, Deserialize)] #[serde(default)] struct StructDefault { a: i32, b: T, } impl Default for StructDefault { fn default() -> Self { StructDefault { a: 100, b: "default".to_string(), } } } #[derive(PartialEq, Debug, Deserialize)] struct StructSkipAll { #[serde(skip_deserializing)] a: i32, } #[derive(PartialEq, Debug, Deserialize)] #[serde(default)] struct StructSkipDefault { #[serde(skip_deserializing)] a: i32, } #[derive(PartialEq, Debug, Deserialize)] #[serde(default)] pub struct StructSkipDefaultGeneric { #[serde(skip_deserializing)] t: T, } impl Default for StructSkipDefault { fn default() -> Self { StructSkipDefault { a: 16 } } } #[derive(PartialEq, Debug, Deserialize)] #[serde(deny_unknown_fields)] struct StructSkipAllDenyUnknown { #[serde(skip_deserializing)] a: i32, } #[derive(Default, PartialEq, Debug)] struct NotDeserializable; #[derive(PartialEq, Debug, Deserialize)] enum Enum { #[allow(dead_code)] #[serde(skip_deserializing)] Skipped, Unit, Simple(i32), Seq(i32, i32, i32), Map { a: i32, b: i32, c: i32, }, SimpleWithSkipped(#[serde(skip_deserializing)] NotDeserializable), } #[derive(PartialEq, Debug, Deserialize)] enum EnumOther { Unit, #[serde(other)] Other, } #[derive(PartialEq, Debug)] struct IgnoredAny; impl<'de> Deserialize<'de> for IgnoredAny { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { serde::de::IgnoredAny::deserialize(deserializer)?; Ok(IgnoredAny) } } ////////////////////////////////////////////////////////////////////////// #[track_caller] fn test<'de, T>(value: T, tokens: &'de [Token]) where T: Deserialize<'de> + PartialEq + Debug, { // Test ser/de roundtripping assert_de_tokens(&value, tokens); // Test that the tokens are ignorable assert_de_tokens_ignore(tokens); } #[derive(Debug)] struct SkipPartialEq(T); impl<'de, T> Deserialize<'de> for SkipPartialEq where T: Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { T::deserialize(deserializer).map(SkipPartialEq) } } impl PartialEq for SkipPartialEq { fn eq(&self, _other: &Self) -> bool { true } } #[track_caller] fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) { #[derive(PartialEq, Debug, Deserialize)] struct IgnoreBase { a: i32, } // Embed the tokens to be ignored in the normal token // stream for an IgnoreBase type let concated_tokens: Vec = vec![ Token::Map { len: Some(2) }, Token::Str("a"), Token::I32(1), Token::Str("ignored"), ] .into_iter() .chain(ignorable_tokens.iter().copied()) .chain(iter::once(Token::MapEnd)) .collect(); let expected = IgnoreBase { a: 1 }; assert_de_tokens(&expected, &concated_tokens); } ////////////////////////////////////////////////////////////////////////// #[test] fn test_bool() { test(true, &[Token::Bool(true)]); test(false, &[Token::Bool(false)]); } #[test] fn test_i8() { let test = test::; // from signed test(-128, &[Token::I8(-128)]); test(-128, &[Token::I16(-128)]); test(-128, &[Token::I32(-128)]); test(-128, &[Token::I64(-128)]); test(127, &[Token::I8(127)]); test(127, &[Token::I16(127)]); test(127, &[Token::I32(127)]); test(127, &[Token::I64(127)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(127, &[Token::U8(127)]); test(127, &[Token::U16(127)]); test(127, &[Token::U32(127)]); test(127, &[Token::U64(127)]); } #[test] fn test_i16() { let test = test::; // from signed test(-128, &[Token::I8(-128)]); test(-32768, &[Token::I16(-32768)]); test(-32768, &[Token::I32(-32768)]); test(-32768, &[Token::I64(-32768)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(32767, &[Token::I32(32767)]); test(32767, &[Token::I64(32767)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(32767, &[Token::U16(32767)]); test(32767, &[Token::U32(32767)]); test(32767, &[Token::U64(32767)]); } #[test] fn test_i32() { let test = test::; // from signed test(-128, &[Token::I8(-128)]); test(-32768, &[Token::I16(-32768)]); test(-2147483648, &[Token::I32(-2147483648)]); test(-2147483648, &[Token::I64(-2147483648)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(2147483647, &[Token::I64(2147483647)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(2147483647, &[Token::U32(2147483647)]); test(2147483647, &[Token::U64(2147483647)]); } #[test] fn test_i64() { let test = test::; // from signed test(-128, &[Token::I8(-128)]); test(-32768, &[Token::I16(-32768)]); test(-2147483648, &[Token::I32(-2147483648)]); test(-9223372036854775808, &[Token::I64(-9223372036854775808)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(9223372036854775807, &[Token::I64(9223372036854775807)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(9223372036854775807, &[Token::U64(9223372036854775807)]); } #[test] fn test_i128() { let test = test::; // from signed test(-128, &[Token::I8(-128)]); test(-32768, &[Token::I16(-32768)]); test(-2147483648, &[Token::I32(-2147483648)]); test(-9223372036854775808, &[Token::I64(-9223372036854775808)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(9223372036854775807, &[Token::I64(9223372036854775807)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(18446744073709551615, &[Token::U64(18446744073709551615)]); } #[test] fn test_isize() { let test = test::; // from signed test(-10, &[Token::I8(-10)]); test(-10, &[Token::I16(-10)]); test(-10, &[Token::I32(-10)]); test(-10, &[Token::I64(-10)]); test(10, &[Token::I8(10)]); test(10, &[Token::I16(10)]); test(10, &[Token::I32(10)]); test(10, &[Token::I64(10)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(10, &[Token::U8(10)]); test(10, &[Token::U16(10)]); test(10, &[Token::U32(10)]); test(10, &[Token::U64(10)]); } #[test] fn test_u8() { let test = test::; // from signed test(0, &[Token::I8(0)]); test(0, &[Token::I16(0)]); test(0, &[Token::I32(0)]); test(0, &[Token::I64(0)]); test(127, &[Token::I8(127)]); test(255, &[Token::I16(255)]); test(255, &[Token::I32(255)]); test(255, &[Token::I64(255)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(255, &[Token::U16(255)]); test(255, &[Token::U32(255)]); test(255, &[Token::U64(255)]); } #[test] fn test_u16() { let test = test::; // from signed test(0, &[Token::I8(0)]); test(0, &[Token::I16(0)]); test(0, &[Token::I32(0)]); test(0, &[Token::I64(0)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(65535, &[Token::I32(65535)]); test(65535, &[Token::I64(65535)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(65535, &[Token::U32(65535)]); test(65535, &[Token::U64(65535)]); } #[test] fn test_u32() { let test = test::; // from signed test(0, &[Token::I8(0)]); test(0, &[Token::I16(0)]); test(0, &[Token::I32(0)]); test(0, &[Token::I64(0)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(4294967295, &[Token::I64(4294967295)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(4294967295, &[Token::U64(4294967295)]); } #[test] fn test_u64() { let test = test::; // from signed test(0, &[Token::I8(0)]); test(0, &[Token::I16(0)]); test(0, &[Token::I32(0)]); test(0, &[Token::I64(0)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(9223372036854775807, &[Token::I64(9223372036854775807)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(18446744073709551615, &[Token::U64(18446744073709551615)]); } #[test] fn test_u128() { let test = test::; // from signed test(0, &[Token::I8(0)]); test(0, &[Token::I16(0)]); test(0, &[Token::I32(0)]); test(0, &[Token::I64(0)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(9223372036854775807, &[Token::I64(9223372036854775807)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(18446744073709551615, &[Token::U64(18446744073709551615)]); } #[test] fn test_usize() { let test = test::; // from signed test(0, &[Token::I8(0)]); test(0, &[Token::I16(0)]); test(0, &[Token::I32(0)]); test(0, &[Token::I64(0)]); test(10, &[Token::I8(10)]); test(10, &[Token::I16(10)]); test(10, &[Token::I32(10)]); test(10, &[Token::I64(10)]); // from unsigned test(0, &[Token::U8(0)]); test(0, &[Token::U16(0)]); test(0, &[Token::U32(0)]); test(0, &[Token::U64(0)]); test(10, &[Token::U8(10)]); test(10, &[Token::U16(10)]); test(10, &[Token::U32(10)]); test(10, &[Token::U64(10)]); } #[test] fn test_nonzero_i8() { let test = |value, tokens| test(NonZeroI8::new(value).unwrap(), tokens); // from signed test(-128, &[Token::I8(-128)]); test(-128, &[Token::I16(-128)]); test(-128, &[Token::I32(-128)]); test(-128, &[Token::I64(-128)]); test(127, &[Token::I8(127)]); test(127, &[Token::I16(127)]); test(127, &[Token::I32(127)]); test(127, &[Token::I64(127)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(127, &[Token::U8(127)]); test(127, &[Token::U16(127)]); test(127, &[Token::U32(127)]); test(127, &[Token::U64(127)]); } #[test] fn test_nonzero_i16() { let test = |value, tokens| test(NonZeroI16::new(value).unwrap(), tokens); // from signed test(-128, &[Token::I8(-128)]); test(-32768, &[Token::I16(-32768)]); test(-32768, &[Token::I32(-32768)]); test(-32768, &[Token::I64(-32768)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(32767, &[Token::I32(32767)]); test(32767, &[Token::I64(32767)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(32767, &[Token::U16(32767)]); test(32767, &[Token::U32(32767)]); test(32767, &[Token::U64(32767)]); } #[test] fn test_nonzero_i32() { let test = |value, tokens| test(NonZeroI32::new(value).unwrap(), tokens); // from signed test(-128, &[Token::I8(-128)]); test(-32768, &[Token::I16(-32768)]); test(-2147483648, &[Token::I32(-2147483648)]); test(-2147483648, &[Token::I64(-2147483648)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(2147483647, &[Token::I64(2147483647)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(2147483647, &[Token::U32(2147483647)]); test(2147483647, &[Token::U64(2147483647)]); } #[test] fn test_nonzero_i64() { let test = |value, tokens| test(NonZeroI64::new(value).unwrap(), tokens); // from signed test(-128, &[Token::I8(-128)]); test(-32768, &[Token::I16(-32768)]); test(-2147483648, &[Token::I32(-2147483648)]); test(-9223372036854775808, &[Token::I64(-9223372036854775808)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(9223372036854775807, &[Token::I64(9223372036854775807)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(9223372036854775807, &[Token::U64(9223372036854775807)]); } #[test] fn test_nonzero_i128() { let test = |value, tokens| test(NonZeroI128::new(value).unwrap(), tokens); // from signed test(-128, &[Token::I8(-128)]); test(-32768, &[Token::I16(-32768)]); test(-2147483648, &[Token::I32(-2147483648)]); test(-9223372036854775808, &[Token::I64(-9223372036854775808)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(9223372036854775807, &[Token::I64(9223372036854775807)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(18446744073709551615, &[Token::U64(18446744073709551615)]); } #[test] fn test_nonzero_isize() { let test = |value, tokens| test(NonZeroIsize::new(value).unwrap(), tokens); // from signed test(-10, &[Token::I8(-10)]); test(-10, &[Token::I16(-10)]); test(-10, &[Token::I32(-10)]); test(-10, &[Token::I64(-10)]); test(10, &[Token::I8(10)]); test(10, &[Token::I16(10)]); test(10, &[Token::I32(10)]); test(10, &[Token::I64(10)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(10, &[Token::U8(10)]); test(10, &[Token::U16(10)]); test(10, &[Token::U32(10)]); test(10, &[Token::U64(10)]); } #[test] fn test_nonzero_u8() { let test = |value, tokens| test(NonZeroU8::new(value).unwrap(), tokens); // from signed test(1, &[Token::I8(1)]); test(1, &[Token::I16(1)]); test(1, &[Token::I32(1)]); test(1, &[Token::I64(1)]); test(127, &[Token::I8(127)]); test(255, &[Token::I16(255)]); test(255, &[Token::I32(255)]); test(255, &[Token::I64(255)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(255, &[Token::U16(255)]); test(255, &[Token::U32(255)]); test(255, &[Token::U64(255)]); } #[test] fn test_nonzero_u16() { let test = |value, tokens| test(NonZeroU16::new(value).unwrap(), tokens); // from signed test(1, &[Token::I8(1)]); test(1, &[Token::I16(1)]); test(1, &[Token::I32(1)]); test(1, &[Token::I64(1)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(65535, &[Token::I32(65535)]); test(65535, &[Token::I64(65535)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(65535, &[Token::U32(65535)]); test(65535, &[Token::U64(65535)]); } #[test] fn test_nonzero_u32() { let test = |value, tokens| test(NonZeroU32::new(value).unwrap(), tokens); // from signed test(1, &[Token::I8(1)]); test(1, &[Token::I16(1)]); test(1, &[Token::I32(1)]); test(1, &[Token::I64(1)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(4294967295, &[Token::I64(4294967295)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(4294967295, &[Token::U64(4294967295)]); } #[test] fn test_nonzero_u64() { let test = |value, tokens| test(NonZeroU64::new(value).unwrap(), tokens); // from signed test(1, &[Token::I8(1)]); test(1, &[Token::I16(1)]); test(1, &[Token::I32(1)]); test(1, &[Token::I64(1)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(9223372036854775807, &[Token::I64(9223372036854775807)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(18446744073709551615, &[Token::U64(18446744073709551615)]); } #[test] fn test_nonzero_u128() { let test = |value, tokens| test(NonZeroU128::new(value).unwrap(), tokens); // from signed test(1, &[Token::I8(1)]); test(1, &[Token::I16(1)]); test(1, &[Token::I32(1)]); test(1, &[Token::I64(1)]); test(127, &[Token::I8(127)]); test(32767, &[Token::I16(32767)]); test(2147483647, &[Token::I32(2147483647)]); test(9223372036854775807, &[Token::I64(9223372036854775807)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(255, &[Token::U8(255)]); test(65535, &[Token::U16(65535)]); test(4294967295, &[Token::U32(4294967295)]); test(18446744073709551615, &[Token::U64(18446744073709551615)]); } #[test] fn test_nonzero_usize() { let test = |value, tokens| test(NonZeroUsize::new(value).unwrap(), tokens); // from signed test(1, &[Token::I8(1)]); test(1, &[Token::I16(1)]); test(1, &[Token::I32(1)]); test(1, &[Token::I64(1)]); test(10, &[Token::I8(10)]); test(10, &[Token::I16(10)]); test(10, &[Token::I32(10)]); test(10, &[Token::I64(10)]); // from unsigned test(1, &[Token::U8(1)]); test(1, &[Token::U16(1)]); test(1, &[Token::U32(1)]); test(1, &[Token::U64(1)]); test(10, &[Token::U8(10)]); test(10, &[Token::U16(10)]); test(10, &[Token::U32(10)]); test(10, &[Token::U64(10)]); } #[test] fn test_f32() { let test = test::; test(1.11, &[Token::F32(1.11)]); test(1.11, &[Token::F64(1.11)]); } #[test] fn test_f64() { let test = test::; test(1.11f32 as f64, &[Token::F32(1.11)]); test(1.11, &[Token::F64(1.11)]); } #[test] fn test_nan() { let f32_deserializer = F32Deserializer::::new; let f64_deserializer = F64Deserializer::::new; let pos_f32_nan = f32_deserializer(f32::NAN.copysign(1.0)); let pos_f64_nan = f64_deserializer(f64::NAN.copysign(1.0)); assert!(f32::deserialize(pos_f32_nan).unwrap().is_sign_positive()); assert!(f32::deserialize(pos_f64_nan).unwrap().is_sign_positive()); assert!(f64::deserialize(pos_f32_nan).unwrap().is_sign_positive()); assert!(f64::deserialize(pos_f64_nan).unwrap().is_sign_positive()); let neg_f32_nan = f32_deserializer(f32::NAN.copysign(-1.0)); let neg_f64_nan = f64_deserializer(f64::NAN.copysign(-1.0)); assert!(f32::deserialize(neg_f32_nan).unwrap().is_sign_negative()); assert!(f32::deserialize(neg_f64_nan).unwrap().is_sign_negative()); assert!(f64::deserialize(neg_f32_nan).unwrap().is_sign_negative()); assert!(f64::deserialize(neg_f64_nan).unwrap().is_sign_negative()); } #[test] fn test_char() { test('a', &[Token::Char('a')]); test('a', &[Token::Str("a")]); test('a', &[Token::String("a")]); } #[test] fn test_string() { test("abc".to_owned(), &[Token::Str("abc")]); test("abc".to_owned(), &[Token::String("abc")]); test("a".to_owned(), &[Token::Char('a')]); } #[test] fn test_option() { test(None::, &[Token::Unit]); test(None::, &[Token::None]); test(Some(1), &[Token::Some, Token::I32(1)]); } #[test] fn test_result() { test( Ok::(0), &[ Token::Enum { name: "Result" }, Token::Str("Ok"), Token::I32(0), ], ); test( Err::(1), &[ Token::Enum { name: "Result" }, Token::Str("Err"), Token::I32(1), ], ); } #[test] fn test_unit() { test((), &[Token::Unit]); } #[test] fn test_unit_struct() { test(UnitStruct, &[Token::Unit]); test(UnitStruct, &[Token::UnitStruct { name: "UnitStruct" }]); } #[test] fn test_generic_unit_struct() { test(GenericUnitStruct::<8>, &[Token::Unit]); test( GenericUnitStruct::<8>, &[Token::UnitStruct { name: "GenericUnitStruct", }], ); } #[test] fn test_newtype_struct() { test( NewtypeStruct(1), &[ Token::NewtypeStruct { name: "NewtypeStruct", }, Token::I32(1), ], ); } #[test] fn test_tuple_struct() { test( TupleStruct(1, 2, 3), &[ Token::Seq { len: Some(3) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::SeqEnd, ], ); test( TupleStruct(1, 2, 3), &[ Token::Seq { len: None }, Token::I32(1), Token::I32(2), Token::I32(3), Token::SeqEnd, ], ); test( TupleStruct(1, 2, 3), &[ Token::TupleStruct { name: "TupleStruct", len: 3, }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleStructEnd, ], ); test( TupleStruct(1, 2, 3), &[ Token::TupleStruct { name: "TupleStruct", len: 3, }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleStructEnd, ], ); } #[test] fn test_btreeset() { test( BTreeSet::::new(), &[Token::Seq { len: Some(0) }, Token::SeqEnd], ); test( btreeset![btreeset![], btreeset![1], btreeset![2, 3]], &[ Token::Seq { len: Some(3) }, Token::Seq { len: Some(0) }, Token::SeqEnd, Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd, Token::Seq { len: Some(2) }, Token::I32(2), Token::I32(3), Token::SeqEnd, Token::SeqEnd, ], ); test( BTreeSet::::new(), &[ Token::TupleStruct { name: "Anything", len: 0, }, Token::TupleStructEnd, ], ); } #[test] fn test_hashset() { test( HashSet::::new(), &[Token::Seq { len: Some(0) }, Token::SeqEnd], ); test( hashset![1, 2, 3], &[ Token::Seq { len: Some(3) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::SeqEnd, ], ); test( HashSet::::new(), &[ Token::TupleStruct { name: "Anything", len: 0, }, Token::TupleStructEnd, ], ); test( hashset![foldhash::fast::FixedState; 1, 2, 3], &[ Token::Seq { len: Some(3) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::SeqEnd, ], ); } #[test] fn test_vec() { test( Vec::::new(), &[Token::Seq { len: Some(0) }, Token::SeqEnd], ); test( vec![vec![], vec![1], vec![2, 3]], &[ Token::Seq { len: Some(3) }, Token::Seq { len: Some(0) }, Token::SeqEnd, Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd, Token::Seq { len: Some(2) }, Token::I32(2), Token::I32(3), Token::SeqEnd, Token::SeqEnd, ], ); test( Vec::::new(), &[ Token::TupleStruct { name: "Anything", len: 0, }, Token::TupleStructEnd, ], ); } #[test] fn test_array() { test([0; 0], &[Token::Seq { len: Some(0) }, Token::SeqEnd]); test([0; 0], &[Token::Tuple { len: 0 }, Token::TupleEnd]); test( ([0; 0], [1], [2, 3]), &[ Token::Seq { len: Some(3) }, Token::Seq { len: Some(0) }, Token::SeqEnd, Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd, Token::Seq { len: Some(2) }, Token::I32(2), Token::I32(3), Token::SeqEnd, Token::SeqEnd, ], ); test( ([0; 0], [1], [2, 3]), &[ Token::Tuple { len: 3 }, Token::Tuple { len: 0 }, Token::TupleEnd, Token::Tuple { len: 1 }, Token::I32(1), Token::TupleEnd, Token::Tuple { len: 2 }, Token::I32(2), Token::I32(3), Token::TupleEnd, Token::TupleEnd, ], ); test( [0; 0], &[ Token::TupleStruct { name: "Anything", len: 0, }, Token::TupleStructEnd, ], ); } #[test] fn test_tuple() { test( (1,), &[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd], ); test( (1, 2, 3), &[ Token::Seq { len: Some(3) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::SeqEnd, ], ); test( (1,), &[Token::Tuple { len: 1 }, Token::I32(1), Token::TupleEnd], ); test( (1, 2, 3), &[ Token::Tuple { len: 3 }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleEnd, ], ); } #[test] fn test_btreemap() { test( BTreeMap::::new(), &[Token::Map { len: Some(0) }, Token::MapEnd], ); test( btreemap![1 => 2], &[ Token::Map { len: Some(1) }, Token::I32(1), Token::I32(2), Token::MapEnd, ], ); test( btreemap![1 => 2, 3 => 4], &[ Token::Map { len: Some(2) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::I32(4), Token::MapEnd, ], ); test( btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]], &[ Token::Map { len: Some(2) }, Token::I32(1), Token::Map { len: Some(0) }, Token::MapEnd, Token::I32(2), Token::Map { len: Some(2) }, Token::I32(3), Token::I32(4), Token::I32(5), Token::I32(6), Token::MapEnd, Token::MapEnd, ], ); test( BTreeMap::::new(), &[ Token::Struct { name: "Anything", len: 0, }, Token::StructEnd, ], ); } #[test] fn test_hashmap() { test( HashMap::::new(), &[Token::Map { len: Some(0) }, Token::MapEnd], ); test( hashmap![1 => 2], &[ Token::Map { len: Some(1) }, Token::I32(1), Token::I32(2), Token::MapEnd, ], ); test( hashmap![1 => 2, 3 => 4], &[ Token::Map { len: Some(2) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::I32(4), Token::MapEnd, ], ); test( hashmap![1 => hashmap![], 2 => hashmap![3 => 4, 5 => 6]], &[ Token::Map { len: Some(2) }, Token::I32(1), Token::Map { len: Some(0) }, Token::MapEnd, Token::I32(2), Token::Map { len: Some(2) }, Token::I32(3), Token::I32(4), Token::I32(5), Token::I32(6), Token::MapEnd, Token::MapEnd, ], ); test( HashMap::::new(), &[ Token::Struct { name: "Anything", len: 0, }, Token::StructEnd, ], ); test( hashmap![foldhash::fast::FixedState; 1 => 2, 3 => 4], &[ Token::Map { len: Some(2) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::I32(4), Token::MapEnd, ], ); } #[test] fn test_struct() { test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::U8(0), Token::I32(1), Token::U8(1), Token::I32(2), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::U16(0), Token::I32(1), Token::U16(1), Token::I32(2), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::U32(0), Token::I32(1), Token::U32(1), Token::I32(2), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::U64(0), Token::I32(1), Token::U64(1), Token::I32(2), Token::MapEnd, ], ); // Mixed key types test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::U8(0), Token::I32(1), Token::U64(1), Token::I32(2), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::U8(0), Token::I32(1), Token::Str("b"), Token::I32(2), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Struct { name: "Struct", len: 2, }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::StructEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Seq { len: Some(3) }, Token::I32(1), Token::I32(2), Token::SeqEnd, ], ); } #[test] fn test_struct_borrowed_keys() { test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::BorrowedStr("a"), Token::I32(1), Token::BorrowedStr("b"), Token::I32(2), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Struct { name: "Struct", len: 2, }, Token::BorrowedStr("a"), Token::I32(1), Token::BorrowedStr("b"), Token::I32(2), Token::StructEnd, ], ); } #[test] fn test_struct_owned_keys() { test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::String("a"), Token::I32(1), Token::String("b"), Token::I32(2), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Struct { name: "Struct", len: 2, }, Token::String("a"), Token::I32(1), Token::String("b"), Token::I32(2), Token::StructEnd, ], ); } #[test] fn test_struct_with_skip() { test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::Str("c"), Token::I32(3), Token::Str("d"), Token::I32(4), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Map { len: Some(3) }, Token::U8(0), Token::I32(1), Token::U16(1), Token::I32(2), Token::U32(2), Token::I32(3), Token::U64(3), Token::I32(4), Token::MapEnd, ], ); test( Struct { a: 1, b: 2, c: 0 }, &[ Token::Struct { name: "Struct", len: 2, }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::Str("c"), Token::I32(3), Token::Str("d"), Token::I32(4), Token::StructEnd, ], ); } #[test] fn test_struct_skip_all() { test( StructSkipAll { a: 0 }, &[ Token::Struct { name: "StructSkipAll", len: 0, }, Token::StructEnd, ], ); test( StructSkipAll { a: 0 }, &[ Token::Struct { name: "StructSkipAll", len: 0, }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::StructEnd, ], ); } #[test] fn test_struct_skip_default() { test( StructSkipDefault { a: 16 }, &[ Token::Struct { name: "StructSkipDefault", len: 0, }, Token::StructEnd, ], ); } #[test] fn test_struct_skip_all_deny_unknown() { test( StructSkipAllDenyUnknown { a: 0 }, &[ Token::Struct { name: "StructSkipAllDenyUnknown", len: 0, }, Token::StructEnd, ], ); } #[test] fn test_struct_default() { test( StructDefault { a: 50, b: "overwritten".to_string(), }, &[ Token::Struct { name: "StructDefault", len: 2, }, Token::Str("a"), Token::I32(50), Token::Str("b"), Token::String("overwritten"), Token::StructEnd, ], ); test( StructDefault { a: 100, b: "default".to_string(), }, &[ Token::Struct { name: "StructDefault", len: 2, }, Token::StructEnd, ], ); } #[test] fn test_enum_unit() { test( Enum::Unit, &[Token::UnitVariant { name: "Enum", variant: "Unit", }], ); } #[test] fn test_enum_simple() { test( Enum::Simple(1), &[ Token::NewtypeVariant { name: "Enum", variant: "Simple", }, Token::I32(1), ], ); } #[test] fn test_enum_simple_with_skipped() { test( Enum::SimpleWithSkipped(NotDeserializable), &[Token::UnitVariant { name: "Enum", variant: "SimpleWithSkipped", }], ); } #[test] fn test_enum_seq() { test( Enum::Seq(1, 2, 3), &[ Token::TupleVariant { name: "Enum", variant: "Seq", len: 3, }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleVariantEnd, ], ); } #[test] fn test_enum_map() { test( Enum::Map { a: 1, b: 2, c: 3 }, &[ Token::StructVariant { name: "Enum", variant: "Map", len: 3, }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::Str("c"), Token::I32(3), Token::StructVariantEnd, ], ); } #[test] fn test_enum_unit_usize() { test( Enum::Unit, &[Token::Enum { name: "Enum" }, Token::U32(0), Token::Unit], ); } #[test] fn test_enum_unit_bytes() { test( Enum::Unit, &[ Token::Enum { name: "Enum" }, Token::Bytes(b"Unit"), Token::Unit, ], ); } #[test] fn test_enum_other_unit() { test( EnumOther::Unit, &[ Token::Enum { name: "EnumOther" }, Token::Str("Unit"), Token::Unit, ], ); test( EnumOther::Unit, &[Token::Enum { name: "EnumOther" }, Token::U8(0), Token::Unit], ); test( EnumOther::Unit, &[ Token::Enum { name: "EnumOther" }, Token::U16(0), Token::Unit, ], ); test( EnumOther::Unit, &[ Token::Enum { name: "EnumOther" }, Token::U32(0), Token::Unit, ], ); test( EnumOther::Unit, &[ Token::Enum { name: "EnumOther" }, Token::U64(0), Token::Unit, ], ); } #[test] fn test_enum_other() { test( EnumOther::Other, &[ Token::Enum { name: "EnumOther" }, Token::Str("Foo"), Token::Unit, ], ); test( EnumOther::Other, &[ Token::Enum { name: "EnumOther" }, Token::U8(42), Token::Unit, ], ); test( EnumOther::Other, &[ Token::Enum { name: "EnumOther" }, Token::U16(42), Token::Unit, ], ); test( EnumOther::Other, &[ Token::Enum { name: "EnumOther" }, Token::U32(42), Token::Unit, ], ); test( EnumOther::Other, &[ Token::Enum { name: "EnumOther" }, Token::U64(42), Token::Unit, ], ); } #[test] fn test_box() { test(Box::new(0i32), &[Token::I32(0)]); } #[test] fn test_boxed_slice() { test( Box::new([0, 1, 2]), &[ Token::Seq { len: Some(3) }, Token::I32(0), Token::I32(1), Token::I32(2), Token::SeqEnd, ], ); } #[test] fn test_duration() { test( Duration::new(1, 2), &[ Token::Struct { name: "Duration", len: 2, }, Token::Str("secs"), Token::U64(1), Token::Str("nanos"), Token::U32(2), Token::StructEnd, ], ); test( Duration::new(1, 2), &[ Token::Seq { len: Some(2) }, Token::I64(1), Token::I64(2), Token::SeqEnd, ], ); } #[test] fn test_system_time() { test( UNIX_EPOCH + Duration::new(1, 2), &[ Token::Struct { name: "SystemTime", len: 2, }, Token::Str("secs_since_epoch"), Token::U64(1), Token::Str("nanos_since_epoch"), Token::U32(2), Token::StructEnd, ], ); test( UNIX_EPOCH + Duration::new(1, 2), &[ Token::Seq { len: Some(2) }, Token::I64(1), Token::I64(2), Token::SeqEnd, ], ); } #[test] fn test_range() { test( 1u32..2u32, &[ Token::Struct { name: "Range", len: 2, }, Token::Str("start"), Token::U32(1), Token::Str("end"), Token::U32(2), Token::StructEnd, ], ); test( 1u32..2u32, &[ Token::Seq { len: Some(2) }, Token::U64(1), Token::U64(2), Token::SeqEnd, ], ); } #[test] fn test_range_inclusive() { test( 1u32..=2u32, &[ Token::Struct { name: "RangeInclusive", len: 2, }, Token::Str("start"), Token::U32(1), Token::Str("end"), Token::U32(2), Token::StructEnd, ], ); test( 1u32..=2u32, &[ Token::Seq { len: Some(2) }, Token::U64(1), Token::U64(2), Token::SeqEnd, ], ); } #[test] fn test_range_from() { test( 1u32.., &[ Token::Struct { name: "RangeFrom", len: 1, }, Token::Str("start"), Token::U32(1), Token::StructEnd, ], ); test( 1u32.., &[Token::Seq { len: Some(1) }, Token::U32(1), Token::SeqEnd], ); } #[test] fn test_range_to() { test( ..2u32, &[ Token::Struct { name: "RangeTo", len: 1, }, Token::Str("end"), Token::U32(2), Token::StructEnd, ], ); test( ..2u32, &[Token::Seq { len: Some(1) }, Token::U32(2), Token::SeqEnd], ); } #[test] fn test_bound() { test( Bound::Unbounded::<()>, &[ Token::Enum { name: "Bound" }, Token::Str("Unbounded"), Token::Unit, ], ); test( Bound::Included(0), &[ Token::Enum { name: "Bound" }, Token::Str("Included"), Token::U8(0), ], ); test( Bound::Excluded(0), &[ Token::Enum { name: "Bound" }, Token::Str("Excluded"), Token::U8(0), ], ); } #[test] fn test_path() { test( Path::new("/usr/local/lib"), &[Token::BorrowedStr("/usr/local/lib")], ); test( Path::new("/usr/local/lib"), &[Token::BorrowedBytes(b"/usr/local/lib")], ); } #[test] fn test_path_buf() { test( PathBuf::from("/usr/local/lib"), &[Token::Str("/usr/local/lib")], ); test( PathBuf::from("/usr/local/lib"), &[Token::String("/usr/local/lib")], ); test( PathBuf::from("/usr/local/lib"), &[Token::Bytes(b"/usr/local/lib")], ); test( PathBuf::from("/usr/local/lib"), &[Token::ByteBuf(b"/usr/local/lib")], ); } #[test] fn test_boxed_path() { test( PathBuf::from("/usr/local/lib").into_boxed_path(), &[Token::Str("/usr/local/lib")], ); test( PathBuf::from("/usr/local/lib").into_boxed_path(), &[Token::String("/usr/local/lib")], ); test( PathBuf::from("/usr/local/lib").into_boxed_path(), &[Token::Bytes(b"/usr/local/lib")], ); test( PathBuf::from("/usr/local/lib").into_boxed_path(), &[Token::ByteBuf(b"/usr/local/lib")], ); } #[test] fn test_cstring() { test(CString::new("abc").unwrap(), &[Token::Bytes(b"abc")]); } #[test] fn test_rc() { test(Rc::new(true), &[Token::Bool(true)]); } #[test] fn test_rc_weak_some() { test( SkipPartialEq(RcWeak::::new()), &[Token::Some, Token::Bool(true)], ); } #[test] fn test_rc_weak_none() { test(SkipPartialEq(RcWeak::::new()), &[Token::None]); } #[test] fn test_arc() { test(Arc::new(true), &[Token::Bool(true)]); } #[test] fn test_arc_weak_some() { test( SkipPartialEq(ArcWeak::::new()), &[Token::Some, Token::Bool(true)], ); } #[test] fn test_arc_weak_none() { test(SkipPartialEq(ArcWeak::::new()), &[Token::None]); } #[test] fn test_wrapping() { test(Wrapping(1usize), &[Token::U32(1)]); test(Wrapping(1usize), &[Token::U64(1)]); } #[test] fn test_saturating() { test(Saturating(1usize), &[Token::U32(1)]); test(Saturating(1usize), &[Token::U64(1)]); test(Saturating(0u8), &[Token::I8(0)]); test(Saturating(0u16), &[Token::I16(0)]); // saturate input values at the minimum or maximum value test(Saturating(u8::MAX), &[Token::U16(u16::MAX)]); test(Saturating(u8::MAX), &[Token::U16(u8::MAX as u16 + 1)]); test(Saturating(u16::MAX), &[Token::U32(u32::MAX)]); test(Saturating(u32::MAX), &[Token::U64(u64::MAX)]); test(Saturating(u8::MIN), &[Token::I8(i8::MIN)]); test(Saturating(u16::MIN), &[Token::I16(i16::MIN)]); test(Saturating(u32::MIN), &[Token::I32(i32::MIN)]); test(Saturating(i8::MIN), &[Token::I16(i16::MIN)]); test(Saturating(i16::MIN), &[Token::I32(i32::MIN)]); test(Saturating(i32::MIN), &[Token::I64(i64::MIN)]); test(Saturating(u8::MIN), &[Token::I8(-1)]); test(Saturating(u16::MIN), &[Token::I16(-1)]); #[cfg(target_pointer_width = "64")] { test(Saturating(usize::MIN), &[Token::U64(u64::MIN)]); test(Saturating(usize::MAX), &[Token::U64(u64::MAX)]); test(Saturating(isize::MIN), &[Token::I64(i64::MIN)]); test(Saturating(isize::MAX), &[Token::I64(i64::MAX)]); test(Saturating(0usize), &[Token::I64(i64::MIN)]); test( Saturating(9_223_372_036_854_775_807usize), &[Token::I64(i64::MAX)], ); } } #[test] fn test_rc_dst() { test(Rc::::from("s"), &[Token::Str("s")]); test( Rc::<[bool]>::from(&[true][..]), &[ Token::Seq { len: Some(1) }, Token::Bool(true), Token::SeqEnd, ], ); } #[test] fn test_arc_dst() { test(Arc::::from("s"), &[Token::Str("s")]); test( Arc::<[bool]>::from(&[true][..]), &[ Token::Seq { len: Some(1) }, Token::Bool(true), Token::SeqEnd, ], ); } #[test] fn test_ignored_any() { test(IgnoredAny, &[Token::Str("s")]); test( IgnoredAny, &[ Token::Seq { len: Some(1) }, Token::Bool(true), Token::SeqEnd, ], ); test( IgnoredAny, &[Token::Enum { name: "E" }, Token::Str("Rust"), Token::Unit], ); } #[test] fn test_net_ipv4addr_readable() { test( "1.2.3.4".parse::().unwrap().readable(), &[Token::Str("1.2.3.4")], ); } #[test] fn test_net_ipv6addr_readable() { test( "::1".parse::().unwrap().readable(), &[Token::Str("::1")], ); } #[test] fn test_net_ipaddr_readable() { test( "1.2.3.4".parse::().unwrap().readable(), &[Token::Str("1.2.3.4")], ); } #[test] fn test_net_socketaddr_readable() { test( "1.2.3.4:1234" .parse::() .unwrap() .readable(), &[Token::Str("1.2.3.4:1234")], ); test( "1.2.3.4:1234" .parse::() .unwrap() .readable(), &[Token::Str("1.2.3.4:1234")], ); test( "[::1]:1234" .parse::() .unwrap() .readable(), &[Token::Str("[::1]:1234")], ); } #[test] fn test_net_ipv4addr_compact() { test( net::Ipv4Addr::from(*b"1234").compact(), &seq![ Token::Tuple { len: 4 }, b"1234".iter().copied().map(Token::U8), Token::TupleEnd ], ); } #[test] fn test_net_ipv6addr_compact() { test( net::Ipv6Addr::from(*b"1234567890123456").compact(), &seq![ Token::Tuple { len: 4 }, b"1234567890123456".iter().copied().map(Token::U8), Token::TupleEnd ], ); } #[test] fn test_net_ipaddr_compact() { test( net::IpAddr::from(*b"1234").compact(), &seq![ Token::NewtypeVariant { name: "IpAddr", variant: "V4" }, Token::Tuple { len: 4 }, b"1234".iter().copied().map(Token::U8), Token::TupleEnd ], ); } #[test] fn test_net_socketaddr_compact() { test( net::SocketAddr::from((*b"1234567890123456", 1234)).compact(), &seq![ Token::NewtypeVariant { name: "SocketAddr", variant: "V6" }, Token::Tuple { len: 2 }, Token::Tuple { len: 16 }, b"1234567890123456".iter().copied().map(Token::U8), Token::TupleEnd, Token::U16(1234), Token::TupleEnd ], ); test( net::SocketAddr::from((*b"1234", 1234)).compact(), &seq![ Token::NewtypeVariant { name: "SocketAddr", variant: "V4" }, Token::Tuple { len: 2 }, Token::Tuple { len: 4 }, b"1234".iter().copied().map(Token::U8), Token::TupleEnd, Token::U16(1234), Token::TupleEnd ], ); test( net::SocketAddrV4::new(net::Ipv4Addr::from(*b"1234"), 1234).compact(), &seq![ Token::Tuple { len: 2 }, Token::Tuple { len: 4 }, b"1234".iter().copied().map(Token::U8), Token::TupleEnd, Token::U16(1234), Token::TupleEnd ], ); test( net::SocketAddrV6::new(net::Ipv6Addr::from(*b"1234567890123456"), 1234, 0, 0).compact(), &seq![ Token::Tuple { len: 2 }, Token::Tuple { len: 16 }, b"1234567890123456".iter().copied().map(Token::U8), Token::TupleEnd, Token::U16(1234), Token::TupleEnd ], ); } #[cfg(feature = "unstable")] #[test] fn test_never_result() { test( Ok::(0), &[ Token::NewtypeVariant { name: "Result", variant: "Ok", }, Token::U8(0), ], ); } #[cfg(unix)] #[test] fn test_osstring() { use std::os::unix::ffi::OsStringExt; let value = OsString::from_vec(vec![1, 2, 3]); let tokens = [ Token::Enum { name: "OsString" }, Token::Str("Unix"), Token::Seq { len: Some(2) }, Token::U8(1), Token::U8(2), Token::U8(3), Token::SeqEnd, ]; assert_de_tokens(&value, &tokens); assert_de_tokens_ignore(&tokens); } #[cfg(windows)] #[test] fn test_osstring() { use std::os::windows::ffi::OsStringExt; let value = OsString::from_wide(&[1, 2, 3]); let tokens = [ Token::Enum { name: "OsString" }, Token::Str("Windows"), Token::Seq { len: Some(2) }, Token::U16(1), Token::U16(2), Token::U16(3), Token::SeqEnd, ]; assert_de_tokens(&value, &tokens); assert_de_tokens_ignore(&tokens); } #[test] fn test_cstr() { assert_de_tokens::>( &CString::new("abc").unwrap().into_boxed_c_str(), &[Token::Bytes(b"abc")], ); } #[test] fn test_atomics() { fn test(load: L, val: T) where L: Fn(&A, Ordering) -> T, A: DeserializeOwned, T: PartialEq + Debug + Copy + for<'de> IntoDeserializer<'de>, { match A::deserialize(val.into_deserializer()) { Ok(v) => { let loaded = load(&v, Ordering::Relaxed); assert_eq!(val, loaded); } Err(e) => panic!("tokens failed to deserialize: {}", e), } } test(AtomicBool::load, true); test(AtomicI8::load, -127i8); test(AtomicI16::load, -510i16); test(AtomicI32::load, -131072i32); test(AtomicIsize::load, -131072isize); test(AtomicU8::load, 127u8); test(AtomicU16::load, 510u16); test(AtomicU32::load, 131072u32); test(AtomicUsize::load, 131072usize); #[cfg(target_arch = "x86_64")] { test(AtomicI64::load, -8589934592i64); test(AtomicU64::load, 8589934592u64); } } ================================================ FILE: test_suite/tests/test_de_error.rs ================================================ #![allow( clippy::derive_partial_eq_without_eq, clippy::empty_enums, clippy::unreadable_literal )] #![cfg_attr(feature = "unstable", feature(never_type))] use serde::de::{Deserialize, IntoDeserializer}; use serde_derive::Deserialize; use serde_test::{assert_de_tokens_error, Token}; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::ffi::{CStr, CString}; use std::num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping, }; use std::time::{Duration, SystemTime}; #[derive(Copy, Clone, PartialEq, Debug, Deserialize)] struct UnitStruct; #[derive(PartialEq, Debug, Deserialize)] struct Struct { a: i32, b: i32, #[serde(skip_deserializing)] c: i32, } #[derive(PartialEq, Debug, Deserialize)] #[serde(deny_unknown_fields)] struct StructDenyUnknown { a: i32, #[serde(skip_deserializing)] b: i32, } #[derive(PartialEq, Debug, Deserialize)] #[serde(deny_unknown_fields)] struct StructSkipAllDenyUnknown { #[serde(skip_deserializing)] a: i32, } #[derive(Default, PartialEq, Debug)] struct NotDeserializable; #[derive(PartialEq, Debug, Deserialize)] enum Enum { #[allow(dead_code)] #[serde(skip_deserializing)] Skipped, Unit, Simple(i32), Seq(i32, i32, i32), Map { a: i32, b: i32, c: i32, }, SimpleWithSkipped(#[serde(skip_deserializing)] NotDeserializable), } #[derive(PartialEq, Debug, Deserialize)] enum EnumSkipAll { #[allow(dead_code)] #[serde(skip_deserializing)] Skipped, } #[test] fn test_i8() { let test = assert_de_tokens_error::; // from signed test( &[Token::I16(-129)], "invalid value: integer `-129`, expected i8", ); test( &[Token::I32(-129)], "invalid value: integer `-129`, expected i8", ); test( &[Token::I64(-129)], "invalid value: integer `-129`, expected i8", ); test( &[Token::I16(128)], "invalid value: integer `128`, expected i8", ); test( &[Token::I32(128)], "invalid value: integer `128`, expected i8", ); test( &[Token::I64(128)], "invalid value: integer `128`, expected i8", ); // from unsigned test( &[Token::U8(128)], "invalid value: integer `128`, expected i8", ); test( &[Token::U16(128)], "invalid value: integer `128`, expected i8", ); test( &[Token::U32(128)], "invalid value: integer `128`, expected i8", ); test( &[Token::U64(128)], "invalid value: integer `128`, expected i8", ); } #[test] fn test_i16() { let test = assert_de_tokens_error::; // from signed test( &[Token::I32(-32769)], "invalid value: integer `-32769`, expected i16", ); test( &[Token::I64(-32769)], "invalid value: integer `-32769`, expected i16", ); test( &[Token::I32(32768)], "invalid value: integer `32768`, expected i16", ); test( &[Token::I64(32768)], "invalid value: integer `32768`, expected i16", ); // from unsigned test( &[Token::U16(32768)], "invalid value: integer `32768`, expected i16", ); test( &[Token::U32(32768)], "invalid value: integer `32768`, expected i16", ); test( &[Token::U64(32768)], "invalid value: integer `32768`, expected i16", ); } #[test] fn test_i32() { let test = assert_de_tokens_error::; // from signed test( &[Token::I64(-2147483649)], "invalid value: integer `-2147483649`, expected i32", ); test( &[Token::I64(2147483648)], "invalid value: integer `2147483648`, expected i32", ); // from unsigned test( &[Token::U32(2147483648)], "invalid value: integer `2147483648`, expected i32", ); test( &[Token::U64(2147483648)], "invalid value: integer `2147483648`, expected i32", ); } #[test] fn test_i64() { let test = assert_de_tokens_error::; // from unsigned test( &[Token::U64(9223372036854775808)], "invalid value: integer `9223372036854775808`, expected i64", ); } #[test] fn test_i128() { let deserializer = ::into_deserializer(1); let error = <&str>::deserialize(deserializer).unwrap_err(); assert_eq!( error.to_string(), "invalid type: integer `1` as i128, expected a borrowed string", ); } #[test] fn test_u8() { let test = assert_de_tokens_error::; // from signed test(&[Token::I8(-1)], "invalid value: integer `-1`, expected u8"); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected u8", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected u8", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected u8", ); test( &[Token::I16(256)], "invalid value: integer `256`, expected u8", ); test( &[Token::I32(256)], "invalid value: integer `256`, expected u8", ); test( &[Token::I64(256)], "invalid value: integer `256`, expected u8", ); // from unsigned test( &[Token::U16(256)], "invalid value: integer `256`, expected u8", ); test( &[Token::U32(256)], "invalid value: integer `256`, expected u8", ); test( &[Token::U64(256)], "invalid value: integer `256`, expected u8", ); } #[test] fn test_u16() { let test = assert_de_tokens_error::; // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected u16", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected u16", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected u16", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected u16", ); test( &[Token::I32(65536)], "invalid value: integer `65536`, expected u16", ); test( &[Token::I64(65536)], "invalid value: integer `65536`, expected u16", ); // from unsigned test( &[Token::U32(65536)], "invalid value: integer `65536`, expected u16", ); test( &[Token::U64(65536)], "invalid value: integer `65536`, expected u16", ); } #[test] fn test_u32() { let test = assert_de_tokens_error::; // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected u32", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected u32", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected u32", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected u32", ); test( &[Token::I64(4294967296)], "invalid value: integer `4294967296`, expected u32", ); // from unsigned test( &[Token::U64(4294967296)], "invalid value: integer `4294967296`, expected u32", ); } #[test] fn test_u64() { let test = assert_de_tokens_error::; // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected u64", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected u64", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected u64", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected u64", ); let deserializer = ::into_deserializer(1); let error = <&str>::deserialize(deserializer).unwrap_err(); assert_eq!( error.to_string(), "invalid type: integer `1`, expected a borrowed string", ); } #[test] fn test_u128() { let test = assert_de_tokens_error::; // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected u128", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected u128", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected u128", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected u128", ); let deserializer = ::into_deserializer(1); let error = <&str>::deserialize(deserializer).unwrap_err(); assert_eq!( error.to_string(), "invalid type: integer `1` as u128, expected a borrowed string", ); } #[test] fn test_usize() { let test = assert_de_tokens_error::; // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected usize", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected usize", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected usize", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected usize", ); } #[test] fn test_nonzero_i8() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero i8", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero i8", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero i8", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero i8", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero i8", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero i8", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero i8", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero i8", ); // from signed test( &[Token::I16(-129)], "invalid value: integer `-129`, expected a nonzero i8", ); test( &[Token::I32(-129)], "invalid value: integer `-129`, expected a nonzero i8", ); test( &[Token::I64(-129)], "invalid value: integer `-129`, expected a nonzero i8", ); test( &[Token::I16(128)], "invalid value: integer `128`, expected a nonzero i8", ); test( &[Token::I32(128)], "invalid value: integer `128`, expected a nonzero i8", ); test( &[Token::I64(128)], "invalid value: integer `128`, expected a nonzero i8", ); // from unsigned test( &[Token::U8(128)], "invalid value: integer `128`, expected a nonzero i8", ); test( &[Token::U16(128)], "invalid value: integer `128`, expected a nonzero i8", ); test( &[Token::U32(128)], "invalid value: integer `128`, expected a nonzero i8", ); test( &[Token::U64(128)], "invalid value: integer `128`, expected a nonzero i8", ); } #[test] fn test_nonzero_i16() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero i16", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero i16", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero i16", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero i16", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero i16", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero i16", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero i16", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero i16", ); // from signed test( &[Token::I32(-32769)], "invalid value: integer `-32769`, expected a nonzero i16", ); test( &[Token::I64(-32769)], "invalid value: integer `-32769`, expected a nonzero i16", ); test( &[Token::I32(32768)], "invalid value: integer `32768`, expected a nonzero i16", ); test( &[Token::I64(32768)], "invalid value: integer `32768`, expected a nonzero i16", ); // from unsigned test( &[Token::U16(32768)], "invalid value: integer `32768`, expected a nonzero i16", ); test( &[Token::U32(32768)], "invalid value: integer `32768`, expected a nonzero i16", ); test( &[Token::U64(32768)], "invalid value: integer `32768`, expected a nonzero i16", ); } #[test] fn test_nonzero_i32() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero i32", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero i32", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero i32", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero i32", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero i32", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero i32", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero i32", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero i32", ); // from signed test( &[Token::I64(-2147483649)], "invalid value: integer `-2147483649`, expected a nonzero i32", ); test( &[Token::I64(2147483648)], "invalid value: integer `2147483648`, expected a nonzero i32", ); // from unsigned test( &[Token::U32(2147483648)], "invalid value: integer `2147483648`, expected a nonzero i32", ); test( &[Token::U64(2147483648)], "invalid value: integer `2147483648`, expected a nonzero i32", ); } #[test] fn test_nonzero_i64() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero i64", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero i64", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero i64", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero i64", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero i64", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero i64", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero i64", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero i64", ); // from unsigned test( &[Token::U64(9223372036854775808)], "invalid value: integer `9223372036854775808`, expected a nonzero i64", ); } #[test] fn test_nonzero_i128() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero i128", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero i128", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero i128", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero i128", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero i128", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero i128", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero i128", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero i128", ); } #[test] fn test_nonzero_isize() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero isize", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero isize", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero isize", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero isize", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero isize", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero isize", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero isize", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero isize", ); } #[test] fn test_nonzero_u8() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero u8", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero u8", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero u8", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero u8", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero u8", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero u8", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero u8", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero u8", ); // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected a nonzero u8", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected a nonzero u8", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected a nonzero u8", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected a nonzero u8", ); test( &[Token::I16(256)], "invalid value: integer `256`, expected a nonzero u8", ); test( &[Token::I32(256)], "invalid value: integer `256`, expected a nonzero u8", ); test( &[Token::I64(256)], "invalid value: integer `256`, expected a nonzero u8", ); // from unsigned test( &[Token::U16(256)], "invalid value: integer `256`, expected a nonzero u8", ); test( &[Token::U32(256)], "invalid value: integer `256`, expected a nonzero u8", ); test( &[Token::U64(256)], "invalid value: integer `256`, expected a nonzero u8", ); } #[test] fn test_nonzero_u16() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero u16", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero u16", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero u16", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero u16", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero u16", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero u16", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero u16", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero u16", ); // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected a nonzero u16", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected a nonzero u16", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected a nonzero u16", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected a nonzero u16", ); test( &[Token::I32(65536)], "invalid value: integer `65536`, expected a nonzero u16", ); test( &[Token::I64(65536)], "invalid value: integer `65536`, expected a nonzero u16", ); // from unsigned test( &[Token::U32(65536)], "invalid value: integer `65536`, expected a nonzero u16", ); test( &[Token::U64(65536)], "invalid value: integer `65536`, expected a nonzero u16", ); } #[test] fn test_nonzero_u32() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero u32", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero u32", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero u32", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero u32", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero u32", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero u32", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero u32", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero u32", ); // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected a nonzero u32", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected a nonzero u32", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected a nonzero u32", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected a nonzero u32", ); test( &[Token::I64(4294967296)], "invalid value: integer `4294967296`, expected a nonzero u32", ); // from unsigned test( &[Token::U64(4294967296)], "invalid value: integer `4294967296`, expected a nonzero u32", ); } #[test] fn test_nonzero_u64() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero u64", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero u64", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero u64", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero u64", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero u64", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero u64", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero u64", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero u64", ); // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected a nonzero u64", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected a nonzero u64", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected a nonzero u64", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected a nonzero u64", ); } #[test] fn test_nonzero_u128() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero u128", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero u128", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero u128", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero u128", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero u128", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero u128", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero u128", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero u128", ); // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected a nonzero u128", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected a nonzero u128", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected a nonzero u128", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected a nonzero u128", ); } #[test] fn test_nonzero_usize() { let test = assert_de_tokens_error::; // from zero test( &[Token::I8(0)], "invalid value: integer `0`, expected a nonzero usize", ); test( &[Token::I16(0)], "invalid value: integer `0`, expected a nonzero usize", ); test( &[Token::I32(0)], "invalid value: integer `0`, expected a nonzero usize", ); test( &[Token::I64(0)], "invalid value: integer `0`, expected a nonzero usize", ); test( &[Token::U8(0)], "invalid value: integer `0`, expected a nonzero usize", ); test( &[Token::U16(0)], "invalid value: integer `0`, expected a nonzero usize", ); test( &[Token::U32(0)], "invalid value: integer `0`, expected a nonzero usize", ); test( &[Token::U64(0)], "invalid value: integer `0`, expected a nonzero usize", ); // from signed test( &[Token::I8(-1)], "invalid value: integer `-1`, expected a nonzero usize", ); test( &[Token::I16(-1)], "invalid value: integer `-1`, expected a nonzero usize", ); test( &[Token::I32(-1)], "invalid value: integer `-1`, expected a nonzero usize", ); test( &[Token::I64(-1)], "invalid value: integer `-1`, expected a nonzero usize", ); } #[test] fn test_unknown_field() { assert_de_tokens_error::( &[ Token::Struct { name: "StructDenyUnknown", len: 1, }, Token::Str("a"), Token::I32(0), Token::Str("d"), ], "unknown field `d`, expected `a`", ); } #[test] fn test_skipped_field_is_unknown() { assert_de_tokens_error::( &[ Token::Struct { name: "StructDenyUnknown", len: 1, }, Token::Str("b"), ], "unknown field `b`, expected `a`", ); } #[test] fn test_skip_all_deny_unknown() { assert_de_tokens_error::( &[ Token::Struct { name: "StructSkipAllDenyUnknown", len: 0, }, Token::Str("a"), ], "unknown field `a`, there are no fields", ); } #[test] fn test_unknown_variant() { assert_de_tokens_error::( &[ Token::UnitVariant { name: "Enum", variant: "Foo" }, ], "unknown variant `Foo`, expected one of `Unit`, `Simple`, `Seq`, `Map`, `SimpleWithSkipped`", ); } #[test] fn test_enum_skipped_variant() { assert_de_tokens_error::( &[ Token::UnitVariant { name: "Enum", variant: "Skipped" }, ], "unknown variant `Skipped`, expected one of `Unit`, `Simple`, `Seq`, `Map`, `SimpleWithSkipped`", ); } #[test] fn test_enum_skip_all() { assert_de_tokens_error::( &[Token::UnitVariant { name: "EnumSkipAll", variant: "Skipped", }], "unknown variant `Skipped`, there are no variants", ); } #[test] fn test_duplicate_field_struct() { assert_de_tokens_error::( &[ Token::Map { len: Some(3) }, Token::Str("a"), Token::I32(1), Token::Str("a"), ], "duplicate field `a`", ); } #[test] fn test_duplicate_field_enum() { assert_de_tokens_error::( &[ Token::StructVariant { name: "Enum", variant: "Map", len: 3, }, Token::Str("a"), Token::I32(1), Token::Str("a"), ], "duplicate field `a`", ); } #[test] fn test_enum_out_of_range() { assert_de_tokens_error::( &[Token::Enum { name: "Enum" }, Token::U32(5), Token::Unit], "invalid value: integer `5`, expected variant index 0 <= i < 5", ); } #[test] fn test_short_tuple() { assert_de_tokens_error::<(u8, u8, u8)>( &[Token::Tuple { len: 1 }, Token::U8(1), Token::TupleEnd], "invalid length 1, expected a tuple of size 3", ); } #[test] fn test_short_array() { assert_de_tokens_error::<[u8; 3]>( &[Token::Seq { len: Some(1) }, Token::U8(1), Token::SeqEnd], "invalid length 1, expected an array of length 3", ); } #[test] fn test_cstring_internal_null() { assert_de_tokens_error::( &[Token::Bytes(b"a\0c")], "nul byte found in provided data at position: 1", ); } #[test] fn test_cstring_internal_null_end() { assert_de_tokens_error::( &[Token::Bytes(b"ac\0")], "nul byte found in provided data at position: 2", ); } #[test] fn test_unit_from_empty_seq() { assert_de_tokens_error::<()>( &[Token::Seq { len: Some(0) }, Token::SeqEnd], "invalid type: sequence, expected unit", ); } #[test] fn test_unit_from_empty_seq_without_len() { assert_de_tokens_error::<()>( &[Token::Seq { len: None }, Token::SeqEnd], "invalid type: sequence, expected unit", ); } #[test] fn test_unit_from_tuple_struct() { assert_de_tokens_error::<()>( &[ Token::TupleStruct { name: "Anything", len: 0, }, Token::TupleStructEnd, ], "invalid type: sequence, expected unit", ); } #[test] fn test_string_from_unit() { assert_de_tokens_error::( &[Token::Unit], "invalid type: unit value, expected a string", ); } #[test] fn test_btreeset_from_unit() { assert_de_tokens_error::>( &[Token::Unit], "invalid type: unit value, expected a sequence", ); } #[test] fn test_btreeset_from_unit_struct() { assert_de_tokens_error::>( &[Token::UnitStruct { name: "Anything" }], "invalid type: unit value, expected a sequence", ); } #[test] fn test_hashset_from_unit() { assert_de_tokens_error::>( &[Token::Unit], "invalid type: unit value, expected a sequence", ); } #[test] fn test_hashset_from_unit_struct() { assert_de_tokens_error::>( &[Token::UnitStruct { name: "Anything" }], "invalid type: unit value, expected a sequence", ); } #[test] fn test_vec_from_unit() { assert_de_tokens_error::>( &[Token::Unit], "invalid type: unit value, expected a sequence", ); } #[test] fn test_vec_from_unit_struct() { assert_de_tokens_error::>( &[Token::UnitStruct { name: "Anything" }], "invalid type: unit value, expected a sequence", ); } #[test] fn test_zero_array_from_unit() { assert_de_tokens_error::<[isize; 0]>( &[Token::Unit], "invalid type: unit value, expected an empty array", ); } #[test] fn test_zero_array_from_unit_struct() { assert_de_tokens_error::<[isize; 0]>( &[Token::UnitStruct { name: "Anything" }], "invalid type: unit value, expected an empty array", ); } #[test] fn test_btreemap_from_unit() { assert_de_tokens_error::>( &[Token::Unit], "invalid type: unit value, expected a map", ); } #[test] fn test_btreemap_from_unit_struct() { assert_de_tokens_error::>( &[Token::UnitStruct { name: "Anything" }], "invalid type: unit value, expected a map", ); } #[test] fn test_hashmap_from_unit() { assert_de_tokens_error::>( &[Token::Unit], "invalid type: unit value, expected a map", ); } #[test] fn test_hashmap_from_unit_struct() { assert_de_tokens_error::>( &[Token::UnitStruct { name: "Anything" }], "invalid type: unit value, expected a map", ); } #[test] fn test_bool_from_string() { assert_de_tokens_error::( &[Token::Str("false")], "invalid type: string \"false\", expected a boolean", ); } #[test] fn test_number_from_string() { assert_de_tokens_error::( &[Token::Str("1")], "invalid type: string \"1\", expected isize", ); } #[test] fn test_integer_from_float() { assert_de_tokens_error::( &[Token::F32(0.0)], "invalid type: floating point `0.0`, expected isize", ); } #[test] fn test_nan_no_decimal_point() { assert_de_tokens_error::( &[Token::F32(f32::NAN)], "invalid type: floating point `NaN`, expected isize", ); } #[test] fn test_unit_struct_from_seq() { assert_de_tokens_error::( &[Token::Seq { len: Some(0) }, Token::SeqEnd], "invalid type: sequence, expected unit struct UnitStruct", ); } #[test] fn test_wrapping_overflow() { assert_de_tokens_error::>( &[Token::U32(65_536)], "invalid value: integer `65536`, expected u16", ); } #[test] fn test_duration_overflow_seq() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, Token::U64(u64::MAX), Token::U32(1_000_000_000), Token::SeqEnd, ], "overflow deserializing Duration", ); } #[test] fn test_duration_overflow_struct() { assert_de_tokens_error::( &[ Token::Struct { name: "Duration", len: 2, }, Token::Str("secs"), Token::U64(u64::MAX), Token::Str("nanos"), Token::U32(1_000_000_000), Token::StructEnd, ], "overflow deserializing Duration", ); } #[test] fn test_systemtime_overflow_seq() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, Token::U64(u64::MAX), Token::U32(1_000_000_000), Token::SeqEnd, ], "overflow deserializing SystemTime epoch offset", ); } #[test] fn test_systemtime_overflow_struct() { assert_de_tokens_error::( &[ Token::Struct { name: "SystemTime", len: 2, }, Token::Str("secs_since_epoch"), Token::U64(u64::MAX), Token::Str("nanos_since_epoch"), Token::U32(1_000_000_000), Token::StructEnd, ], "overflow deserializing SystemTime epoch offset", ); } #[test] fn test_systemtime_overflow() { assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, Token::U64(u64::MAX), Token::U32(0), Token::SeqEnd, ], "overflow deserializing SystemTime", ); } #[test] fn test_cstr_internal_null() { assert_de_tokens_error::>( &[Token::Bytes(b"a\0c")], "nul byte found in provided data at position: 1", ); } #[test] fn test_cstr_internal_null_end() { assert_de_tokens_error::>( &[Token::Bytes(b"ac\0")], "nul byte found in provided data at position: 2", ); } #[cfg(feature = "unstable")] #[test] fn test_never_type() { assert_de_tokens_error::(&[], "cannot deserialize `!`"); assert_de_tokens_error::>( &[Token::NewtypeVariant { name: "Result", variant: "Err", }], "cannot deserialize `!`", ); } ================================================ FILE: test_suite/tests/test_deprecated.rs ================================================ #![deny(deprecated)] #![allow(dead_code)] use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] #[deprecated] enum DeprecatedEnum { A, B, } #[derive(Serialize, Deserialize)] #[deprecated] struct DeprecatedStruct { a: bool, } #[derive(Serialize, Deserialize)] enum DeprecatedVariant { A, #[deprecated] B, } #[derive(Serialize, Deserialize)] struct DeprecatedField { #[deprecated] a: bool, } ================================================ FILE: test_suite/tests/test_enum_adjacently_tagged.rs ================================================ #![deny(trivial_numeric_casts)] #![allow( clippy::derive_partial_eq_without_eq, clippy::enum_variant_names, clippy::redundant_field_names, clippy::too_many_lines )] use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "t", content = "c")] enum AdjacentlyTagged { Unit, Newtype(T), Tuple(u8, u8), Struct { f: u8 }, } mod unit { use super::*; #[test] fn map_str_tag_only() { // Map: tag only assert_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 1, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::StructEnd, ], ); // Map: tag only and incorrect hint for number of elements assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::StructEnd, ], ); } #[test] fn map_int_tag_only() { // Map: tag (as number) only assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 1, }, Token::U16(0), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::StructEnd, ], ); } #[test] fn map_bytes_tag_only() { // Map: tag only assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 1, }, Token::Bytes(b"t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::StructEnd, ], ); // Map: tag only assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 1, }, Token::BorrowedBytes(b"t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::StructEnd, ], ); } #[test] fn map_str_tag_content() { // Map: tag + content assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::Str("c"), Token::Unit, Token::StructEnd, ], ); // Map: content + tag assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("c"), Token::Unit, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::StructEnd, ], ); // Map: tag + content + excess fields (f, g, h) assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("f"), Token::Unit, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::Str("g"), Token::Unit, Token::Str("c"), Token::Unit, Token::Str("h"), Token::Unit, Token::StructEnd, ], ); } #[test] fn map_int_tag_content() { // Map: tag (as number) + content (as number) assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::U8(0), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::U8(1), Token::Unit, Token::StructEnd, ], ); // Map: content (as number) + tag (as number) assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::U64(1), Token::Unit, Token::U64(0), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::StructEnd, ], ); } #[test] fn map_bytes_tag_content() { // Map: tag + content assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::BorrowedBytes(b"t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::BorrowedBytes(b"c"), Token::Unit, Token::StructEnd, ], ); // Map: content + tag assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Bytes(b"c"), Token::Unit, Token::Bytes(b"t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::StructEnd, ], ); } #[test] fn seq_tag_content() { // Seq: tag and content assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Seq { len: Some(2) }, Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::Unit, Token::SeqEnd, ], ); // Seq: tag (as string) and content assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Seq { len: None }, Token::Str("Unit"), // tag Token::Unit, // content Token::SeqEnd, ], ); // Seq: tag (as borrowed string) and content assert_de_tokens( &AdjacentlyTagged::Unit::, &[ Token::Seq { len: None }, Token::BorrowedStr("Unit"), // tag Token::Unit, // content Token::SeqEnd, ], ); } } mod newtype { use super::*; #[test] fn map_tag_only() { // optional newtype with no content field assert_de_tokens( &AdjacentlyTagged::Newtype::>(None), &[ Token::Struct { name: "AdjacentlyTagged", len: 1, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Newtype", }, Token::StructEnd, ], ); } #[test] fn map_tag_content() { let value = AdjacentlyTagged::Newtype::(1); // Map: tag + content assert_tokens( &value, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Newtype", }, Token::Str("c"), Token::U8(1), Token::StructEnd, ], ); // Map: content + tag assert_de_tokens( &value, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("c"), Token::U8(1), Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Newtype", }, Token::StructEnd, ], ); } #[test] fn seq() { let value = AdjacentlyTagged::Newtype::(1); // Seq: tag and content assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::UnitVariant { name: "AdjacentlyTagged", variant: "Newtype", }, Token::U8(1), Token::SeqEnd, ], ); // Seq: tag (as string) and content assert_de_tokens( &value, &[ Token::Seq { len: None }, Token::Str("Newtype"), // tag Token::U8(1), // content Token::SeqEnd, ], ); // Seq: tag (as borrowed string) and content assert_de_tokens( &value, &[ Token::Seq { len: None }, Token::BorrowedStr("Newtype"), // tag Token::U8(1), // content Token::SeqEnd, ], ); } } #[test] fn newtype_with_newtype() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct NewtypeStruct(u32); assert_de_tokens( &AdjacentlyTagged::Newtype(NewtypeStruct(5)), &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("c"), Token::NewtypeStruct { name: "NewtypeStruct", }, Token::U32(5), Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Newtype", }, Token::StructEnd, ], ); } mod tuple { use super::*; #[test] fn map() { let value = AdjacentlyTagged::Tuple::(1, 1); // Map: tag + content assert_tokens( &value, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Tuple", }, Token::Str("c"), Token::Tuple { len: 2 }, Token::U8(1), Token::U8(1), Token::TupleEnd, Token::StructEnd, ], ); // Map: content + tag assert_de_tokens( &value, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("c"), Token::Tuple { len: 2 }, Token::U8(1), Token::U8(1), Token::TupleEnd, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Tuple", }, Token::StructEnd, ], ); } #[test] fn seq() { let value = AdjacentlyTagged::Tuple::(1, 1); // Seq: tag + content assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::UnitVariant { name: "AdjacentlyTagged", variant: "Tuple", }, Token::Tuple { len: 2 }, Token::U8(1), Token::U8(1), Token::TupleEnd, Token::SeqEnd, ], ); } } mod struct_ { use super::*; #[test] fn map() { let value = AdjacentlyTagged::Struct:: { f: 1 }; // Map: tag + content assert_tokens( &value, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Struct", }, Token::Str("c"), Token::Struct { name: "Struct", len: 1, }, Token::Str("f"), Token::U8(1), Token::StructEnd, Token::StructEnd, ], ); // Map: content + tag assert_de_tokens( &value, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("c"), Token::Struct { name: "Struct", len: 1, }, Token::Str("f"), Token::U8(1), Token::StructEnd, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Struct", }, Token::StructEnd, ], ); } #[test] fn seq() { let value = AdjacentlyTagged::Struct:: { f: 1 }; // Seq: tag + content assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::UnitVariant { name: "AdjacentlyTagged", variant: "Struct", }, Token::Struct { name: "Struct", len: 1, }, Token::Str("f"), Token::U8(1), Token::StructEnd, Token::SeqEnd, ], ); } } #[test] fn struct_with_flatten() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "t", content = "c")] enum Data { A { a: i32, #[serde(flatten)] flat: Flat, }, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Flat { b: i32, } let data = Data::A { a: 0, flat: Flat { b: 0 }, }; assert_tokens( &data, &[ Token::Struct { name: "Data", len: 2, }, Token::Str("t"), Token::UnitVariant { name: "Data", variant: "A", }, Token::Str("c"), Token::Map { len: None }, Token::Str("a"), Token::I32(0), Token::Str("b"), Token::I32(0), Token::MapEnd, Token::StructEnd, ], ); } #[test] fn expecting_message() { #[derive(Deserialize)] #[serde(tag = "tag", content = "content")] #[serde(expecting = "something strange...")] enum Enum { AdjacentlyTagged, } assert_de_tokens_error::( &[Token::Str("AdjacentlyTagged")], r#"invalid type: string "AdjacentlyTagged", expected something strange..."#, ); assert_de_tokens_error::( &[Token::Map { len: None }, Token::Unit], r#"invalid type: unit value, expected "tag", "content", or other ignored fields"#, ); // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], "invalid type: unit value, expected variant of enum Enum", ); } #[test] fn partially_untagged() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(tag = "t", content = "c")] enum Data { A(u32), B, #[serde(untagged)] Var(u32), } let data = Data::A(7); assert_de_tokens( &data, &[ Token::Map { len: None }, Token::Str("t"), Token::Str("A"), Token::Str("c"), Token::U32(7), Token::MapEnd, ], ); let data = Data::Var(42); assert_de_tokens(&data, &[Token::U32(42)]); // TODO test error output } #[test] fn deny_unknown_fields() { #[derive(Debug, PartialEq, Deserialize)] #[serde(tag = "t", content = "c", deny_unknown_fields)] enum AdjacentlyTagged { Unit, } assert_de_tokens( &AdjacentlyTagged::Unit, &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::Str("c"), Token::Unit, Token::StructEnd, ], ); assert_de_tokens_error::( &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("t"), Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::Str("c"), Token::Unit, Token::Str("h"), ], r#"invalid value: string "h", expected "t" or "c""#, ); assert_de_tokens_error::( &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("h"), ], r#"invalid value: string "h", expected "t" or "c""#, ); assert_de_tokens_error::( &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Str("c"), Token::Unit, Token::Str("h"), ], r#"invalid value: string "h", expected "t" or "c""#, ); assert_de_tokens_error::( &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::U64(0), // tag field Token::UnitVariant { name: "AdjacentlyTagged", variant: "Unit", }, Token::U64(3), ], r#"invalid value: integer `3`, expected "t" or "c""#, ); assert_de_tokens_error::( &[ Token::Struct { name: "AdjacentlyTagged", len: 2, }, Token::Bytes(b"c"), Token::Unit, Token::Bytes(b"h"), ], r#"invalid value: byte array, expected "t" or "c""#, ); } ================================================ FILE: test_suite/tests/test_enum_internally_tagged.rs ================================================ #![deny(trivial_numeric_casts)] #![allow( clippy::derive_partial_eq_without_eq, clippy::enum_variant_names, clippy::redundant_field_names, clippy::too_many_lines )] mod bytes; use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; use std::collections::BTreeMap; use std::iter::FromIterator; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Unit; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Newtype(BTreeMap); #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Struct { f: u8, } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum Enum { Unit, Newtype(u8), Tuple(u8, u8), Struct { f: u8 }, } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum InternallyTagged { Unit, NewtypeUnit(()), NewtypeUnitStruct(Unit), NewtypeNewtype(Newtype), NewtypeMap(BTreeMap), NewtypeStruct(Struct), NewtypeEnum(Enum), Struct { a: u8 }, StructEnum { enum_: Enum }, } #[test] fn unit() { assert_tokens( &InternallyTagged::Unit, &[ Token::Struct { name: "InternallyTagged", len: 1, }, Token::Str("tag"), Token::Str("Unit"), Token::StructEnd, ], ); assert_de_tokens( &InternallyTagged::Unit, &[ Token::Struct { name: "InternallyTagged", len: 1, }, Token::BorrowedStr("tag"), Token::BorrowedStr("Unit"), Token::StructEnd, ], ); assert_de_tokens( &InternallyTagged::Unit, &[ Token::Map { len: Some(1) }, Token::Str("tag"), Token::Str("Unit"), Token::MapEnd, ], ); assert_de_tokens( &InternallyTagged::Unit, &[ Token::Map { len: Some(1) }, Token::BorrowedStr("tag"), Token::BorrowedStr("Unit"), Token::MapEnd, ], ); assert_de_tokens( &InternallyTagged::Unit, &[ Token::Seq { len: Some(1) }, Token::Str("Unit"), // tag Token::SeqEnd, ], ); assert_de_tokens( &InternallyTagged::Unit, &[ Token::Seq { len: Some(1) }, Token::BorrowedStr("Unit"), // tag Token::SeqEnd, ], ); } #[test] fn newtype_unit() { let value = InternallyTagged::NewtypeUnit(()); assert_tokens( &value, &[ Token::Map { len: Some(1) }, Token::Str("tag"), Token::Str("NewtypeUnit"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(1) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeUnit"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 1, }, Token::Str("tag"), Token::Str("NewtypeUnit"), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 1, }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeUnit"), Token::StructEnd, ], ); } #[test] fn newtype_unit_struct() { let value = InternallyTagged::NewtypeUnitStruct(Unit); assert_tokens( &value, &[ Token::Map { len: Some(1) }, Token::Str("tag"), Token::Str("NewtypeUnitStruct"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(1) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeUnitStruct"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 1, }, Token::Str("tag"), Token::Str("NewtypeUnitStruct"), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 1, }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeUnitStruct"), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Seq { len: Some(1) }, Token::Str("NewtypeUnitStruct"), // tag Token::SeqEnd, ], ); assert_de_tokens( &value, &[ Token::Seq { len: Some(1) }, Token::BorrowedStr("NewtypeUnitStruct"), // tag Token::SeqEnd, ], ); } #[test] fn newtype_newtype() { assert_tokens( &InternallyTagged::NewtypeNewtype(Newtype(BTreeMap::new())), &[ Token::Map { len: Some(1) }, Token::Str("tag"), Token::Str("NewtypeNewtype"), Token::MapEnd, ], ); } #[test] fn newtype_map() { let value = InternallyTagged::NewtypeMap(BTreeMap::new()); // Special case: empty map assert_tokens( &value, &[ Token::Map { len: Some(1) }, Token::Str("tag"), Token::Str("NewtypeMap"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(1) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeMap"), Token::MapEnd, ], ); let value = InternallyTagged::NewtypeMap(BTreeMap::from_iter([( "field".to_string(), "value".to_string(), )])); // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("NewtypeMap"), Token::Str("field"), Token::Str("value"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeMap"), Token::BorrowedStr("field"), Token::BorrowedStr("value"), Token::MapEnd, ], ); // General case: tag field ("tag") is not the first field assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("field"), Token::Str("value"), Token::Str("tag"), Token::Str("NewtypeMap"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("field"), Token::BorrowedStr("value"), Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeMap"), Token::MapEnd, ], ); assert_de_tokens_error::( &[ Token::Seq { len: Some(2) }, Token::Str("NewtypeMap"), // tag Token::Map { len: Some(0) }, Token::MapEnd, Token::SeqEnd, ], "invalid type: sequence, expected a map", ); } #[test] fn newtype_struct() { let value = InternallyTagged::NewtypeStruct(Struct { f: 6 }); // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ Token::Struct { name: "Struct", len: 2, }, Token::Str("tag"), Token::Str("NewtypeStruct"), Token::Str("f"), Token::U8(6), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "Struct", len: 2, }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeStruct"), Token::BorrowedStr("f"), Token::U8(6), Token::StructEnd, ], ); // General case: tag field ("tag") is not the first field assert_de_tokens( &value, &[ Token::Struct { name: "Struct", len: 2, }, Token::Str("f"), Token::U8(6), Token::Str("tag"), Token::Str("NewtypeStruct"), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "Struct", len: 2, }, Token::BorrowedStr("f"), Token::U8(6), Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeStruct"), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::Str("NewtypeStruct"), // tag Token::U8(6), Token::SeqEnd, ], ); assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::BorrowedStr("NewtypeStruct"), // tag Token::U8(6), Token::SeqEnd, ], ); } mod newtype_enum { use super::*; #[test] fn unit() { let value = InternallyTagged::NewtypeEnum(Enum::Unit); // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::Str("Unit"), Token::Unit, Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::BorrowedStr("Unit"), Token::Unit, Token::MapEnd, ], ); // General case: tag field ("tag") is not the first field assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("Unit"), Token::Unit, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("Unit"), Token::Unit, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::MapEnd, ], ); } #[test] fn newtype() { let value = InternallyTagged::NewtypeEnum(Enum::Newtype(1)); // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::Str("Newtype"), Token::U8(1), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::BorrowedStr("Newtype"), Token::U8(1), Token::MapEnd, ], ); // General case: tag field ("tag") is not the first field assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("Newtype"), Token::U8(1), Token::Str("tag"), Token::Str("NewtypeEnum"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("Newtype"), Token::U8(1), Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::MapEnd, ], ); } #[test] fn tuple() { let value = InternallyTagged::NewtypeEnum(Enum::Tuple(1, 1)); // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::Str("Tuple"), Token::TupleStruct { name: "Tuple", len: 2, }, Token::U8(1), Token::U8(1), Token::TupleStructEnd, Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::BorrowedStr("Tuple"), Token::TupleStruct { name: "Tuple", len: 2, }, Token::U8(1), Token::U8(1), Token::TupleStructEnd, Token::MapEnd, ], ); // Special case: tag field ("tag") is not the first field // Reaches crate::private::de::content::VariantDeserializer::tuple_variant // Content::Seq case // via ContentDeserializer::deserialize_enum assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("Tuple"), Token::TupleStruct { name: "Tuple", len: 2, }, Token::U8(1), Token::U8(1), Token::TupleStructEnd, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("Tuple"), Token::TupleStruct { name: "Tuple", len: 2, }, Token::U8(1), Token::U8(1), Token::TupleStructEnd, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::MapEnd, ], ); } #[test] fn struct_() { let value = InternallyTagged::NewtypeEnum(Enum::Struct { f: 1 }); // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::Str("Struct"), Token::Struct { name: "Struct", len: 1, }, Token::Str("f"), Token::U8(1), Token::StructEnd, Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::BorrowedStr("Struct"), Token::Struct { name: "Struct", len: 1, }, Token::BorrowedStr("f"), Token::U8(1), Token::StructEnd, Token::MapEnd, ], ); // General case: tag field ("tag") is not the first field // Reaches crate::private::de::content::VariantDeserializer::struct_variant // Content::Map case // via ContentDeserializer::deserialize_enum assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("Struct"), Token::Struct { name: "Struct", len: 1, }, Token::Str("f"), Token::U8(1), Token::StructEnd, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("Struct"), Token::Struct { name: "Struct", len: 1, }, Token::BorrowedStr("f"), Token::U8(1), Token::StructEnd, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::MapEnd, ], ); // Special case: tag field ("tag") is the first field assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::Str("Struct"), Token::Seq { len: Some(1) }, Token::U8(1), // f Token::SeqEnd, Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::BorrowedStr("Struct"), Token::Seq { len: Some(1) }, Token::U8(1), // f Token::SeqEnd, Token::MapEnd, ], ); // General case: tag field ("tag") is not the first field // Reaches crate::private::de::content::VariantDeserializer::struct_variant // Content::Seq case // via ContentDeserializer::deserialize_enum assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("Struct"), Token::Seq { len: Some(1) }, Token::U8(1), // f Token::SeqEnd, Token::Str("tag"), Token::Str("NewtypeEnum"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("Struct"), Token::Seq { len: Some(1) }, Token::U8(1), // f Token::SeqEnd, Token::BorrowedStr("tag"), Token::BorrowedStr("NewtypeEnum"), Token::MapEnd, ], ); } } #[test] fn struct_() { let value = InternallyTagged::Struct { a: 1 }; // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::Str("tag"), Token::Str("Struct"), Token::Str("a"), Token::U8(1), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::BorrowedStr("tag"), Token::BorrowedStr("Struct"), Token::BorrowedStr("a"), Token::U8(1), Token::StructEnd, ], ); // General case: tag field ("tag") is not the first field assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::Str("a"), Token::U8(1), Token::Str("tag"), Token::Str("Struct"), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::BorrowedStr("a"), Token::U8(1), Token::BorrowedStr("tag"), Token::BorrowedStr("Struct"), Token::StructEnd, ], ); // Special case: tag field ("tag") is the first field assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("Struct"), Token::Str("a"), Token::U8(1), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("tag"), Token::BorrowedStr("Struct"), Token::BorrowedStr("a"), Token::U8(1), Token::MapEnd, ], ); // General case: tag field ("tag") is not the first field assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("a"), Token::U8(1), Token::Str("tag"), Token::Str("Struct"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("a"), Token::U8(1), Token::BorrowedStr("tag"), Token::BorrowedStr("Struct"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::Str("Struct"), // tag Token::U8(1), Token::SeqEnd, ], ); assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::BorrowedStr("Struct"), // tag Token::U8(1), Token::SeqEnd, ], ); } mod struct_enum { use super::*; #[test] fn unit() { assert_de_tokens( &Enum::Unit, &[ Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, ], ); let value = InternallyTagged::StructEnum { enum_: Enum::Unit }; // Special case: tag field ("tag") is the first field assert_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::Str("tag"), Token::Str("StructEnum"), Token::Str("enum_"), Token::Enum { name: "Enum" }, Token::Str("Unit"), Token::Unit, Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::BorrowedStr("tag"), Token::BorrowedStr("StructEnum"), Token::BorrowedStr("enum_"), Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, Token::StructEnd, ], ); // General case: tag field ("tag") is not the first field assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::Str("enum_"), Token::Enum { name: "Enum" }, Token::Str("Unit"), Token::Unit, Token::Str("tag"), Token::Str("StructEnum"), Token::StructEnd, ], ); assert_de_tokens( &value, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::BorrowedStr("enum_"), Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, Token::BorrowedStr("tag"), Token::BorrowedStr("StructEnum"), Token::StructEnd, ], ); // Special case: tag field ("tag") is the first field assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("StructEnum"), Token::Str("enum_"), Token::Enum { name: "Enum" }, Token::Str("Unit"), Token::Unit, Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("tag"), Token::BorrowedStr("StructEnum"), Token::BorrowedStr("enum_"), Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, Token::MapEnd, ], ); // General case: tag field ("tag") is not the first field assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::Str("enum_"), Token::Enum { name: "Enum" }, Token::Str("Unit"), Token::Unit, Token::Str("tag"), Token::Str("StructEnum"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Map { len: Some(2) }, Token::BorrowedStr("enum_"), Token::Enum { name: "Enum" }, Token::BorrowedStr("Unit"), Token::Unit, Token::BorrowedStr("tag"), Token::BorrowedStr("StructEnum"), Token::MapEnd, ], ); assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::Str("StructEnum"), // tag Token::Enum { name: "Enum" }, // enum_ Token::Str("Unit"), Token::Unit, Token::SeqEnd, ], ); assert_de_tokens( &value, &[ Token::Seq { len: Some(2) }, Token::BorrowedStr("StructEnum"), // tag Token::Enum { name: "Enum" }, // enum_ Token::BorrowedStr("Unit"), Token::Unit, Token::SeqEnd, ], ); } } #[test] fn wrong_tag() { assert_de_tokens_error::( &[Token::Map { len: Some(0) }, Token::MapEnd], "missing field `tag`", ); assert_de_tokens_error::( &[ Token::Map { len: Some(1) }, Token::Str("tag"), Token::Str("Z"), Token::MapEnd, ], "unknown variant `Z`, expected one of \ `Unit`, \ `NewtypeUnit`, \ `NewtypeUnitStruct`, \ `NewtypeNewtype`, \ `NewtypeMap`, \ `NewtypeStruct`, \ `NewtypeEnum`, \ `Struct`, \ `StructEnum`", ); } #[test] fn untagged_variant() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum InternallyTagged { Tagged { a: u8, }, #[serde(untagged)] Untagged { tag: String, b: u8, }, } assert_de_tokens( &InternallyTagged::Tagged { a: 1 }, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("Tagged"), Token::Str("a"), Token::U8(1), Token::MapEnd, ], ); assert_tokens( &InternallyTagged::Tagged { a: 1 }, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::Str("tag"), Token::Str("Tagged"), Token::Str("a"), Token::U8(1), Token::StructEnd, ], ); assert_de_tokens( &InternallyTagged::Untagged { tag: "Foo".to_owned(), b: 2, }, &[ Token::Map { len: Some(2) }, Token::Str("tag"), Token::Str("Foo"), Token::Str("b"), Token::U8(2), Token::MapEnd, ], ); assert_tokens( &InternallyTagged::Untagged { tag: "Foo".to_owned(), b: 2, }, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::Str("tag"), Token::Str("Foo"), Token::Str("b"), Token::U8(2), Token::StructEnd, ], ); assert_tokens( &InternallyTagged::Untagged { tag: "Tagged".to_owned(), b: 2, }, &[ Token::Struct { name: "InternallyTagged", len: 2, }, Token::Str("tag"), Token::Str("Tagged"), Token::Str("b"), Token::U8(2), Token::StructEnd, ], ); } mod string_and_bytes { use super::*; #[derive(Debug, PartialEq, Deserialize)] #[serde(tag = "tag")] enum InternallyTagged { String { string: String, }, Bytes { #[serde(with = "bytes")] bytes: Vec, }, } #[test] fn string_from_string() { assert_de_tokens( &InternallyTagged::String { string: "\0".to_owned(), }, &[ Token::Struct { name: "String", len: 2, }, Token::Str("tag"), Token::Str("String"), Token::Str("string"), Token::Str("\0"), Token::StructEnd, ], ); assert_de_tokens( &InternallyTagged::String { string: "\0".to_owned(), }, &[ Token::Struct { name: "String", len: 2, }, Token::Str("tag"), Token::Str("String"), Token::Str("string"), Token::String("\0"), Token::StructEnd, ], ); } #[test] fn string_from_bytes() { assert_de_tokens( &InternallyTagged::String { string: "\0".to_owned(), }, &[ Token::Struct { name: "String", len: 2, }, Token::Str("tag"), Token::Str("String"), Token::Str("string"), Token::Bytes(b"\0"), Token::StructEnd, ], ); assert_de_tokens( &InternallyTagged::String { string: "\0".to_owned(), }, &[ Token::Struct { name: "String", len: 2, }, Token::Str("tag"), Token::Str("String"), Token::Str("string"), Token::ByteBuf(b"\0"), Token::StructEnd, ], ); } #[test] fn bytes_from_string() { assert_de_tokens( &InternallyTagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Bytes", len: 2, }, Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::Str("\0"), Token::StructEnd, ], ); assert_de_tokens( &InternallyTagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Bytes", len: 2, }, Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::String("\0"), Token::StructEnd, ], ); } #[test] fn bytes_from_bytes() { assert_de_tokens( &InternallyTagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Bytes", len: 2, }, Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::Bytes(b"\0"), Token::StructEnd, ], ); assert_de_tokens( &InternallyTagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Bytes", len: 2, }, Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::ByteBuf(b"\0"), Token::StructEnd, ], ); } #[test] fn bytes_from_seq() { assert_de_tokens( &InternallyTagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Bytes", len: 2, }, Token::Str("tag"), Token::Str("Bytes"), Token::Str("bytes"), Token::Seq { len: Some(1) }, Token::U8(0), Token::SeqEnd, Token::StructEnd, ], ); } } #[test] fn borrow() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum Input<'a> { Package { name: &'a str }, } assert_tokens( &Input::Package { name: "borrowed" }, &[ Token::Struct { name: "Input", len: 2, }, Token::BorrowedStr("tag"), Token::BorrowedStr("Package"), Token::BorrowedStr("name"), Token::BorrowedStr("borrowed"), Token::StructEnd, ], ); } #[test] fn with_skipped_conflict() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum Data { A, #[serde(skip)] #[allow(dead_code)] B { t: String, }, C { #[serde(default, skip)] t: String, }, } let data = Data::C { t: String::new() }; assert_tokens( &data, &[ Token::Struct { name: "Data", len: 1, }, Token::Str("tag"), Token::Str("C"), Token::StructEnd, ], ); } #[test] fn containing_flatten() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag")] enum Data { A { a: i32, #[serde(flatten)] flat: Flat, }, } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Flat { b: i32, } let data = Data::A { a: 0, flat: Flat { b: 0 }, }; assert_tokens( &data, &[ Token::Map { len: None }, Token::Str("tag"), Token::Str("A"), Token::Str("a"), Token::I32(0), Token::Str("b"), Token::I32(0), Token::MapEnd, ], ); } #[test] fn unit_variant_with_unknown_fields() { let value = InternallyTagged::Unit; assert_de_tokens( &value, &[ Token::Map { len: None }, Token::Str("tag"), Token::Str("Unit"), Token::Str("b"), Token::I32(0), Token::MapEnd, ], ); // Unknown elements are not allowed in sequences assert_de_tokens_error::( &[ Token::Seq { len: None }, Token::Str("Unit"), // tag Token::I32(0), Token::SeqEnd, ], "invalid length 1, expected 0 elements in sequence", ); } #[test] fn expecting_message() { #[derive(Deserialize)] #[serde(tag = "tag")] #[serde(expecting = "something strange...")] enum Enum { InternallyTagged, } assert_de_tokens_error::( &[Token::Str("InternallyTagged")], r#"invalid type: string "InternallyTagged", expected something strange..."#, ); // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message assert_de_tokens_error::( &[Token::Map { len: None }, Token::Str("tag"), Token::Unit], "invalid type: unit value, expected variant identifier", ); } ================================================ FILE: test_suite/tests/test_enum_untagged.rs ================================================ #![deny(trivial_numeric_casts)] #![allow( clippy::derive_partial_eq_without_eq, clippy::enum_variant_names, clippy::redundant_field_names, clippy::too_many_lines )] mod bytes; use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; use std::collections::BTreeMap; #[test] fn complex() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum Untagged { A { a: u8 }, B { b: u8 }, C, D(u8), E(String), F(u8, u8), } assert_tokens( &Untagged::A { a: 1 }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("a"), Token::U8(1), Token::StructEnd, ], ); assert_tokens( &Untagged::B { b: 2 }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("b"), Token::U8(2), Token::StructEnd, ], ); // Serializes to unit, deserializes from either depending on format's // preference. assert_tokens(&Untagged::C, &[Token::Unit]); assert_de_tokens(&Untagged::C, &[Token::None]); assert_tokens(&Untagged::D(4), &[Token::U8(4)]); assert_tokens(&Untagged::E("e".to_owned()), &[Token::Str("e")]); assert_tokens( &Untagged::F(1, 2), &[ Token::Tuple { len: 2 }, Token::U8(1), Token::U8(2), Token::TupleEnd, ], ); assert_de_tokens_error::( &[Token::Tuple { len: 1 }, Token::U8(1), Token::TupleEnd], "data did not match any variant of untagged enum Untagged", ); assert_de_tokens_error::( &[ Token::Tuple { len: 3 }, Token::U8(1), Token::U8(2), Token::U8(3), Token::TupleEnd, ], "data did not match any variant of untagged enum Untagged", ); } #[test] fn newtype_unit_and_empty_map() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Unit; #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum Message { Unit(Unit), Map(BTreeMap), } assert_tokens( &Message::Map(BTreeMap::new()), &[Token::Map { len: Some(0) }, Token::MapEnd], ); } // Reaches crate::private::de::content::ContentRefDeserializer::deserialize_newtype_struct #[test] fn newtype_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] struct NewtypeStruct(u32); #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum E { Newtype(NewtypeStruct), Null, } let value = E::Newtype(NewtypeStruct(5)); // Content::Newtype case assert_tokens( &value, &[ Token::NewtypeStruct { name: "NewtypeStruct", }, Token::U32(5), ], ); // _ case assert_de_tokens(&value, &[Token::U32(5)]); } mod newtype_enum { use super::*; #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum Outer { Inner(Inner), } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum Inner { Unit, Newtype(u8), Tuple0(), Tuple2(u8, u8), Struct { f: u8 }, EmptyStruct {}, } // Reaches crate::private::de::content::VariantRefDeserializer::unit_variant #[test] fn unit() { assert_tokens( &Outer::Inner(Inner::Unit), &[Token::UnitVariant { name: "Inner", variant: "Unit", }], ); } // Reaches crate::private::de::content::VariantRefDeserializer::newtype_variant_seed #[test] fn newtype() { assert_tokens( &Outer::Inner(Inner::Newtype(1)), &[ Token::NewtypeVariant { name: "Inner", variant: "Newtype", }, Token::U8(1), ], ); } // Reaches crate::private::de::content::VariantRefDeserializer::tuple_variant #[test] fn tuple0() { assert_tokens( &Outer::Inner(Inner::Tuple0()), &[ Token::TupleVariant { name: "Inner", variant: "Tuple0", len: 0, }, Token::TupleVariantEnd, ], ); } // Reaches crate::private::de::content::VariantRefDeserializer::tuple_variant #[test] fn tuple2() { assert_tokens( &Outer::Inner(Inner::Tuple2(1, 1)), &[ Token::TupleVariant { name: "Inner", variant: "Tuple2", len: 2, }, Token::U8(1), Token::U8(1), Token::TupleVariantEnd, ], ); } // Reaches crate::private::de::content::VariantRefDeserializer::struct_variant // Content::Map case #[test] fn struct_from_map() { assert_tokens( &Outer::Inner(Inner::Struct { f: 1 }), &[ Token::StructVariant { name: "Inner", variant: "Struct", len: 1, }, Token::Str("f"), Token::U8(1), Token::StructVariantEnd, ], ); } // Reaches crate::private::de::content::VariantRefDeserializer::struct_variant // Content::Seq case #[test] fn struct_from_seq() { assert_de_tokens( &Outer::Inner(Inner::Struct { f: 1 }), &[ Token::Map { len: Some(1) }, // tag Token::Str("Struct"), // content Token::Seq { len: Some(1) }, Token::U8(1), Token::SeqEnd, Token::MapEnd, ], ); } // Reaches crate::private::de::content::VariantRefDeserializer::struct_variant // Content::Map case // Special case - empty map #[test] fn empty_struct_from_map() { assert_de_tokens( &Outer::Inner(Inner::EmptyStruct {}), &[ Token::Map { len: Some(1) }, // tag Token::Str("EmptyStruct"), // content Token::Map { len: Some(0) }, Token::MapEnd, Token::MapEnd, ], ); } // Reaches crate::private::de::content::VariantRefDeserializer::struct_variant // Content::Seq case // Special case - empty seq #[test] fn empty_struct_from_seq() { assert_de_tokens( &Outer::Inner(Inner::EmptyStruct {}), &[ Token::Map { len: Some(1) }, // tag Token::Str("EmptyStruct"), // content Token::Seq { len: Some(0) }, Token::SeqEnd, Token::MapEnd, ], ); } } // Reaches crate::private::de::content::ContentRefDeserializer::deserialize_option mod with_optional_field { use super::*; #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum Enum { Struct { optional: Option }, Null, } #[test] fn some() { assert_tokens( &Enum::Struct { optional: Some(42) }, &[ Token::Struct { name: "Enum", len: 1, }, Token::Str("optional"), Token::Some, Token::U32(42), Token::StructEnd, ], ); } #[test] fn some_without_marker() { assert_de_tokens( &Enum::Struct { optional: Some(42) }, &[ Token::Struct { name: "Enum", len: 1, }, Token::Str("optional"), Token::U32(42), Token::StructEnd, ], ); } #[test] fn none() { assert_tokens( &Enum::Struct { optional: None }, &[ Token::Struct { name: "Enum", len: 1, }, Token::Str("optional"), Token::None, Token::StructEnd, ], ); } #[test] fn unit() { assert_de_tokens( &Enum::Struct { optional: None }, &[ Token::Map { len: None }, Token::Str("optional"), Token::Unit, Token::MapEnd, ], ); } } #[test] fn string_and_bytes() { #[derive(Debug, PartialEq, Deserialize)] #[serde(untagged)] enum Untagged { String { string: String, }, Bytes { #[serde(with = "bytes")] bytes: Vec, }, } assert_de_tokens( &Untagged::String { string: "\0".to_owned(), }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("string"), Token::Str("\0"), Token::StructEnd, ], ); assert_de_tokens( &Untagged::String { string: "\0".to_owned(), }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("string"), Token::String("\0"), Token::StructEnd, ], ); assert_de_tokens( &Untagged::String { string: "\0".to_owned(), }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("string"), Token::Bytes(b"\0"), Token::StructEnd, ], ); assert_de_tokens( &Untagged::String { string: "\0".to_owned(), }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("string"), Token::ByteBuf(b"\0"), Token::StructEnd, ], ); assert_de_tokens( &Untagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("bytes"), Token::Str("\0"), Token::StructEnd, ], ); assert_de_tokens( &Untagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("bytes"), Token::String("\0"), Token::StructEnd, ], ); assert_de_tokens( &Untagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("bytes"), Token::Bytes(b"\0"), Token::StructEnd, ], ); assert_de_tokens( &Untagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("bytes"), Token::ByteBuf(b"\0"), Token::StructEnd, ], ); assert_de_tokens( &Untagged::Bytes { bytes: vec![0] }, &[ Token::Struct { name: "Untagged", len: 1, }, Token::Str("bytes"), Token::Seq { len: Some(1) }, Token::U8(0), Token::SeqEnd, Token::StructEnd, ], ); } #[test] fn contains_flatten() { #[derive(Serialize, Deserialize, PartialEq, Debug)] #[serde(untagged)] enum Data { A { a: i32, #[serde(flatten)] flat: Flat, }, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Flat { b: i32, } let data = Data::A { a: 0, flat: Flat { b: 0 }, }; assert_tokens( &data, &[ Token::Map { len: None }, Token::Str("a"), Token::I32(0), Token::Str("b"), Token::I32(0), Token::MapEnd, ], ); } #[test] fn contains_flatten_with_integer_key() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] pub enum Untagged { Variant { #[serde(flatten)] map: BTreeMap, }, } assert_tokens( &Untagged::Variant { map: { let mut map = BTreeMap::new(); map.insert(100, "BTreeMap".to_owned()); map }, }, &[ Token::Map { len: None }, Token::U64(100), Token::Str("BTreeMap"), Token::MapEnd, ], ); } #[test] fn expecting_message() { #[derive(Deserialize)] #[serde(untagged)] #[serde(expecting = "something strange...")] enum Enum { Untagged, } assert_de_tokens_error::(&[Token::Str("Untagged")], "something strange..."); } ================================================ FILE: test_suite/tests/test_gen.rs ================================================ // These just test that serde_derive is able to produce code that compiles // successfully when there are a variety of generics and non-(de)serializable // types involved. #![deny(warnings)] #![allow( confusable_idents, unknown_lints, mixed_script_confusables, clippy::derive_partial_eq_without_eq, clippy::extra_unused_type_parameters, clippy::items_after_statements, clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate, // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422 clippy::nonstandard_macro_braces, clippy::ptr_arg, clippy::too_many_lines, clippy::trivially_copy_pass_by_ref, clippy::type_repetition_in_bounds, // We use lots of declarations inside function bodies to avoid conflicts, // but they aren't used. We just want to make sure they compile. dead_code, )] #![deny(clippy::collection_is_never_read)] use serde::de::{Deserialize, DeserializeOwned, Deserializer}; use serde::ser::{Serialize, Serializer}; use serde_derive::{Deserialize, Serialize}; use std::borrow::Cow; use std::marker::PhantomData; use std::option::Option as StdOption; use std::result::Result as StdResult; // Try to trip up the generated code if it fails to use fully qualified paths. #[allow(dead_code)] struct Result; #[allow(dead_code)] struct Ok; #[allow(dead_code)] struct Err; #[allow(dead_code)] struct Option; #[allow(dead_code)] struct Some; #[allow(dead_code)] struct None; ////////////////////////////////////////////////////////////////////////// #[test] fn test_gen() { #[derive(Serialize, Deserialize)] struct With { t: T, #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] x: X, } assert::>(); #[derive(Serialize, Deserialize)] struct WithTogether { t: T, #[serde(with = "both_x")] x: X, } assert::>(); #[derive(Serialize, Deserialize)] struct WithRef<'a, T: 'a> { #[serde(skip_deserializing)] t: StdOption<&'a T>, #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] x: X, } assert::>(); #[derive(Serialize, Deserialize)] struct PhantomX { x: PhantomData, } assert::(); #[derive(Serialize, Deserialize)] struct PhantomT { t: PhantomData, } assert::>(); #[derive(Serialize, Deserialize)] struct NoBounds { t: T, option: StdOption, boxed: Box, option_boxed: StdOption>, } assert::>(); #[derive(Serialize, Deserialize)] enum EnumWith { Unit, Newtype(#[serde(serialize_with = "ser_x", deserialize_with = "de_x")] X), Tuple( T, #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] X, ), Struct { t: T, #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] x: X, }, } assert::>(); #[derive(Serialize)] struct MultipleRef<'a, 'b, 'c, T> where T: 'c, 'c: 'b, 'b: 'a, { t: T, rrrt: &'a &'b &'c T, } assert_ser::>(); #[derive(Serialize, Deserialize)] struct Newtype(#[serde(serialize_with = "ser_x", deserialize_with = "de_x")] X); assert::(); #[derive(Serialize, Deserialize)] struct Tuple( T, #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] X, ); assert::>(); #[derive(Serialize, Deserialize)] enum TreeNode { Split { left: Box>, right: Box>, }, Leaf { data: D, }, } assert::>(); #[derive(Serialize, Deserialize)] struct ListNode { data: D, next: Box>, } assert::>(); #[derive(Serialize, Deserialize)] struct RecursiveA { b: Box, } assert::(); #[derive(Serialize, Deserialize)] enum RecursiveB { A(RecursiveA), } assert::(); #[derive(Serialize, Deserialize)] struct RecursiveGenericA { t: T, b: Box>, } assert::>(); #[derive(Serialize, Deserialize)] enum RecursiveGenericB { T(T), A(RecursiveGenericA), } assert::>(); #[derive(Serialize)] struct OptionStatic<'a> { a: StdOption<&'a str>, b: StdOption<&'static str>, } assert_ser::(); #[derive(Serialize, Deserialize)] #[serde(bound = "D: SerializeWith + DeserializeWith")] struct WithTraits1 { #[serde( serialize_with = "SerializeWith::serialize_with", deserialize_with = "DeserializeWith::deserialize_with" )] d: D, #[serde( serialize_with = "SerializeWith::serialize_with", deserialize_with = "DeserializeWith::deserialize_with", bound = "E: SerializeWith + DeserializeWith" )] e: E, } assert::>(); #[derive(Serialize, Deserialize)] #[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))] struct WithTraits2 { #[serde( serialize_with = "SerializeWith::serialize_with", deserialize_with = "DeserializeWith::deserialize_with" )] d: D, #[serde( serialize_with = "SerializeWith::serialize_with", bound(serialize = "E: SerializeWith") )] #[serde( deserialize_with = "DeserializeWith::deserialize_with", bound(deserialize = "E: DeserializeWith") )] e: E, } assert::>(); #[derive(Serialize, Deserialize)] #[serde(bound = "D: SerializeWith + DeserializeWith")] enum VariantWithTraits1 { #[serde( serialize_with = "SerializeWith::serialize_with", deserialize_with = "DeserializeWith::deserialize_with" )] D(D), #[serde( serialize_with = "SerializeWith::serialize_with", deserialize_with = "DeserializeWith::deserialize_with", bound = "E: SerializeWith + DeserializeWith" )] E(E), } assert::>(); #[derive(Serialize, Deserialize)] #[serde(bound(serialize = "D: SerializeWith", deserialize = "D: DeserializeWith"))] enum VariantWithTraits2 { #[serde( serialize_with = "SerializeWith::serialize_with", deserialize_with = "DeserializeWith::deserialize_with" )] D(D), #[serde( serialize_with = "SerializeWith::serialize_with", bound(serialize = "E: SerializeWith") )] #[serde( deserialize_with = "DeserializeWith::deserialize_with", bound(deserialize = "E: DeserializeWith") )] E(E), } assert::>(); type PhantomDataAlias = PhantomData; #[derive(Serialize, Deserialize)] #[serde(bound = "")] struct PhantomDataWrapper { #[serde(default)] field: PhantomDataAlias, } assert::>(); #[derive(Serialize, Deserialize)] struct CowStr<'a>(Cow<'a, str>); assert::(); #[derive(Serialize, Deserialize)] #[serde(bound(deserialize = "T::Owned: DeserializeOwned"))] struct CowT<'a, T: ?Sized + 'a + ToOwned>(Cow<'a, T>); assert::>(); #[derive(Serialize, Deserialize)] struct EmptyStruct {} assert::(); #[derive(Serialize, Deserialize)] enum EmptyEnumVariant { EmptyStruct {}, } assert::(); #[derive(Serialize, Deserialize)] pub struct NonAsciiIdents { σ: f64, } #[derive(Serialize, Deserialize)] pub struct EmptyBraced {} #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct EmptyBracedDenyUnknown {} #[derive(Serialize, Deserialize)] pub struct BracedSkipAll { #[serde(skip_deserializing)] f: u8, } #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct BracedSkipAllDenyUnknown { #[serde(skip_deserializing)] f: u8, } #[derive(Serialize, Deserialize)] pub struct EmptyTuple(); #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct EmptyTupleDenyUnknown(); #[derive(Serialize, Deserialize)] pub struct TupleSkipAll(#[serde(skip_deserializing)] u8); #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct TupleSkipAllDenyUnknown(#[serde(skip_deserializing)] u8); #[derive(Serialize, Deserialize)] pub enum EmptyEnum {} #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub enum EmptyEnumDenyUnknown {} #[derive(Serialize, Deserialize)] pub enum EnumSkipAll { #[serde(skip_deserializing)] #[allow(dead_code)] Variant, } #[derive(Serialize, Deserialize)] pub enum EmptyVariants { Braced {}, Tuple(), BracedSkip { #[serde(skip_deserializing)] f: u8, }, TupleSkip(#[serde(skip_deserializing)] u8), } #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub enum EmptyVariantsDenyUnknown { Braced {}, Tuple(), BracedSkip { #[serde(skip_deserializing)] f: u8, }, TupleSkip(#[serde(skip_deserializing)] u8), } #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct UnitDenyUnknown; #[derive(Serialize, Deserialize)] pub struct EmptyArray { empty: [X; 0], } pub enum Or { A(A), B(B), } #[derive(Serialize, Deserialize)] #[serde(untagged, remote = "Or")] pub enum OrDef { A(A), B(B), } struct Str<'a>(&'a str); #[derive(Serialize, Deserialize)] #[serde(remote = "Str")] struct StrDef<'a>(&'a str); #[derive(Serialize, Deserialize)] pub struct Remote<'a> { #[serde(with = "OrDef")] or: Or, #[serde(borrow, with = "StrDef")] s: Str<'a>, } #[derive(Serialize, Deserialize)] pub enum BorrowVariant<'a> { #[serde(borrow, with = "StrDef")] S(Str<'a>), } mod vis { use serde_derive::{Deserialize, Serialize}; pub struct S; #[derive(Serialize, Deserialize)] #[serde(remote = "S")] pub struct SDef; } // This would not work if SDef::serialize / deserialize are private. #[derive(Serialize, Deserialize)] pub struct RemoteVisibility { #[serde(with = "vis::SDef")] s: vis::S, } #[derive(Serialize, Deserialize)] #[serde(remote = "Self")] pub struct RemoteSelf; #[derive(Serialize, Deserialize)] enum ExternallyTaggedVariantWith { #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] #[allow(dead_code)] Newtype(X), #[serde(serialize_with = "serialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")] #[allow(dead_code)] Tuple(String, u8), #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] #[allow(dead_code)] Struct1 { x: X }, #[serde(serialize_with = "serialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")] #[allow(dead_code)] Struct { f1: String, f2: u8 }, #[serde(serialize_with = "serialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")] #[allow(dead_code)] Unit, } assert_ser::(); #[derive(Serialize, Deserialize)] #[serde(tag = "t")] enum InternallyTaggedVariantWith { #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] #[allow(dead_code)] Newtype(X), #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] #[allow(dead_code)] Struct1 { x: X }, #[serde(serialize_with = "serialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")] #[allow(dead_code)] Struct { f1: String, f2: u8 }, #[serde(serialize_with = "serialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")] #[allow(dead_code)] Unit, } assert_ser::(); #[derive(Serialize, Deserialize)] #[serde(tag = "t", content = "c")] enum AdjacentlyTaggedVariantWith { #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] #[allow(dead_code)] Newtype(X), #[serde(serialize_with = "serialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")] #[allow(dead_code)] Tuple(String, u8), #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] #[allow(dead_code)] Struct1 { x: X }, #[serde(serialize_with = "serialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")] #[allow(dead_code)] Struct { f1: String, f2: u8 }, #[serde(serialize_with = "serialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")] #[allow(dead_code)] Unit, } assert_ser::(); #[derive(Serialize, Deserialize)] #[serde(untagged)] enum UntaggedVariantWith { #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] #[allow(dead_code)] Newtype(X), #[serde(serialize_with = "serialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")] #[allow(dead_code)] Tuple(String, u8), #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] #[allow(dead_code)] Struct1 { x: X }, #[serde(serialize_with = "serialize_some_other_variant")] #[serde(deserialize_with = "deserialize_some_other_variant")] #[allow(dead_code)] Struct { f1: String, f2: u8 }, #[serde(serialize_with = "serialize_some_unit_variant")] #[serde(deserialize_with = "deserialize_some_unit_variant")] #[allow(dead_code)] Unit, } assert_ser::(); #[derive(Serialize, Deserialize)] struct FlattenWith { #[serde(flatten, serialize_with = "ser_x", deserialize_with = "de_x")] x: X, } assert::(); #[derive(Serialize, Deserialize)] pub struct Flatten { #[serde(flatten)] t: T, } #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct FlattenDenyUnknown { #[serde(flatten)] t: T, } #[derive(Serialize, Deserialize)] pub struct SkipDeserializing { #[serde(skip_deserializing)] flat: T, } #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct SkipDeserializingDenyUnknown { #[serde(skip_deserializing)] flat: T, } #[derive(Serialize, Deserialize)] pub struct StaticStrStruct<'a> { a: &'a str, b: &'static str, } #[derive(Serialize, Deserialize)] pub struct StaticStrTupleStruct<'a>(&'a str, &'static str); #[derive(Serialize, Deserialize)] pub struct StaticStrNewtypeStruct(&'static str); #[derive(Serialize, Deserialize)] pub enum StaticStrEnum<'a> { Struct { a: &'a str, b: &'static str }, Tuple(&'a str, &'static str), Newtype(&'static str), } #[derive(Serialize, Deserialize)] struct SkippedStaticStr { #[serde(skip_deserializing)] skipped: &'static str, other: isize, } assert::(); macro_rules! T { () => { () }; } #[derive(Serialize, Deserialize)] struct TypeMacro { mac: T!(), marker: PhantomData, } assert::>(); #[derive(Serialize)] struct BigArray { #[serde(serialize_with = "<[_]>::serialize")] array: [u8; 256], } assert_ser::(); trait AssocSerde { type Assoc; } struct NoSerdeImpl; impl AssocSerde for NoSerdeImpl { type Assoc = u32; } #[derive(Serialize, Deserialize)] struct AssocDerive { assoc: T::Assoc, } assert::>(); #[derive(Serialize, Deserialize)] struct AssocDeriveMulti { s: S, assoc: T::Assoc, } assert::>(); #[derive(Serialize)] #[serde(tag = "t", content = "c")] enum EmptyAdjacentlyTagged { #[allow(dead_code)] Struct {}, #[allow(dead_code)] Tuple(), } assert_ser::(); mod restricted { mod inner { use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] #[allow(dead_code)] struct Restricted { pub(super) a: usize, pub(in super::inner) b: usize, } } } #[derive(Deserialize)] #[serde(tag = "t", content = "c")] pub enum AdjacentlyTaggedVoid {} #[derive(Serialize, Deserialize)] enum SkippedVariant { #[serde(skip)] #[allow(dead_code)] T(T), Unit, } assert::>(); #[derive(Deserialize)] pub struct ImplicitlyBorrowedOption<'a> { option: std::option::Option<&'a str>, } #[derive(Serialize, Deserialize)] #[serde(untagged)] #[allow(dead_code)] pub enum UntaggedNewtypeVariantWith { Newtype( #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] X, ), } #[derive(Serialize, Deserialize)] #[serde(transparent)] #[allow(dead_code)] pub struct TransparentWith { #[serde(serialize_with = "ser_x")] #[serde(deserialize_with = "de_x")] x: X, } #[derive(Deserialize)] #[serde(untagged)] #[allow(dead_code)] pub enum UntaggedWithBorrow<'a> { Single( #[serde(borrow)] #[allow(dead_code)] RelObject<'a>, ), Many( #[serde(borrow)] #[allow(dead_code)] Vec>, ), } #[derive(Deserialize)] pub struct RelObject<'a> { ty: &'a str, id: String, } #[derive(Serialize, Deserialize)] pub struct FlattenSkipSerializing { #[serde(flatten, skip_serializing)] #[allow(dead_code)] flat: T, } #[derive(Serialize, Deserialize)] pub struct FlattenSkipSerializingIf { #[serde(flatten, skip_serializing_if = "StdOption::is_none")] flat: StdOption, } #[derive(Serialize, Deserialize)] pub struct FlattenSkipDeserializing { #[serde(flatten, skip_deserializing)] flat: T, } #[derive(Serialize, Deserialize)] #[serde(untagged)] pub enum Inner { Builder { s: T, #[serde(flatten)] o: T, }, Default { s: T, }, } // https://github.com/serde-rs/serde/issues/1804 #[derive(Serialize, Deserialize)] pub enum Message { #[serde(skip)] #[allow(dead_code)] String(String), #[serde(other)] Unknown, } #[derive(Serialize)] #[repr(C, packed)] #[allow(dead_code)] struct Packed { x: u8, y: u16, } macro_rules! deriving { ($field:ty) => { #[derive(Deserialize)] pub struct MacroRules<'a> { field: $field, } }; } deriving!(&'a str); macro_rules! mac { ($($tt:tt)*) => { $($tt)* }; } #[derive(Deserialize)] pub struct BorrowLifetimeInsideMacro<'a> { #[serde(borrow = "'a")] pub f: mac!(Cow<'a, str>), } #[derive(Serialize)] pub struct Struct { #[serde(serialize_with = "vec_first_element")] pub vec: Vec, } assert_ser::(); #[derive(Deserialize)] #[serde(bound(deserialize = "[&'de str; N]: Copy"))] pub struct GenericUnitStruct; } ////////////////////////////////////////////////////////////////////////// fn assert() {} fn assert_ser() {} trait SerializeWith { fn serialize_with(_: &Self, _: S) -> StdResult; } trait DeserializeWith: Sized { fn deserialize_with<'de, D: Deserializer<'de>>(_: D) -> StdResult; } // Implements neither Serialize nor Deserialize pub struct X; pub fn ser_x(_: &X, _: S) -> StdResult { unimplemented!() } pub fn de_x<'de, D: Deserializer<'de>>(_: D) -> StdResult { unimplemented!() } mod both_x { pub use super::{de_x as deserialize, ser_x as serialize}; } impl SerializeWith for X { fn serialize_with(_: &Self, _: S) -> StdResult { unimplemented!() } } impl DeserializeWith for X { fn deserialize_with<'de, D: Deserializer<'de>>(_: D) -> StdResult { unimplemented!() } } pub fn serialize_some_unit_variant(_: S) -> StdResult where S: Serializer, { unimplemented!() } pub fn deserialize_some_unit_variant<'de, D>(_: D) -> StdResult<(), D::Error> where D: Deserializer<'de>, { unimplemented!() } pub fn serialize_some_other_variant(_: &str, _: &u8, _: S) -> StdResult where S: Serializer, { unimplemented!() } pub fn deserialize_some_other_variant<'de, D>(_: D) -> StdResult<(String, u8), D::Error> where D: Deserializer<'de>, { unimplemented!() } pub fn is_zero(n: &u8) -> bool { *n == 0 } fn vec_first_element(vec: &[T], serializer: S) -> StdResult where T: Serialize, S: Serializer, { vec.first().serialize(serializer) } ////////////////////////////////////////////////////////////////////////// #[derive(Debug, PartialEq, Deserialize)] #[serde(tag = "tag")] pub enum InternallyTagged { #[serde(deserialize_with = "deserialize_generic")] Unit, #[serde(deserialize_with = "deserialize_generic")] Newtype(i32), #[serde(deserialize_with = "deserialize_generic")] Struct { f1: String, f2: u8 }, } fn deserialize_generic<'de, T, D>(deserializer: D) -> StdResult where T: Deserialize<'de>, D: Deserializer<'de>, { T::deserialize(deserializer) } ////////////////////////////////////////////////////////////////////////// #[repr(C, packed)] pub struct RemotePacked { pub a: u16, pub b: u32, } #[derive(Serialize)] #[repr(C, packed)] #[serde(remote = "RemotePacked")] pub struct RemotePackedDef { a: u16, b: u32, } impl Drop for RemotePackedDef { fn drop(&mut self) {} } #[repr(C, packed)] pub struct RemotePackedNonCopy { pub a: u16, pub b: String, } #[derive(Deserialize)] #[repr(C, packed)] #[serde(remote = "RemotePackedNonCopy")] pub struct RemotePackedNonCopyDef { a: u16, b: String, } impl Drop for RemotePackedNonCopyDef { fn drop(&mut self) {} } ================================================ FILE: test_suite/tests/test_identifier.rs ================================================ //! Tests for `#[serde(field_identifier)]` and `#[serde(variant_identifier)]` #![allow(clippy::derive_partial_eq_without_eq)] use serde_derive::Deserialize; use serde_test::{assert_de_tokens, assert_de_tokens_error, Token}; mod variant_identifier { use super::*; #[derive(Deserialize, Debug, PartialEq)] #[serde(variant_identifier)] enum V { Aaa, #[serde(alias = "Ccc", alias = "Ddd")] Bbb, } #[test] fn variant1() { assert_de_tokens(&V::Aaa, &[Token::U8(0)]); assert_de_tokens(&V::Aaa, &[Token::U16(0)]); assert_de_tokens(&V::Aaa, &[Token::U32(0)]); 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::( &[Token::U8(42)], "invalid value: integer `42`, expected variant index 0 <= i < 2", ); assert_de_tokens_error::( &[Token::U16(42)], "invalid value: integer `42`, expected variant index 0 <= i < 2", ); assert_de_tokens_error::( &[Token::U32(42)], "invalid value: integer `42`, expected variant index 0 <= i < 2", ); assert_de_tokens_error::( &[Token::U64(42)], "invalid value: integer `42`, expected variant index 0 <= i < 2", ); assert_de_tokens_error::( &[Token::Str("Unknown")], "unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`", ); assert_de_tokens_error::( &[Token::Bytes(b"Unknown")], "unknown variant `Unknown`, expected one of `Aaa`, `Bbb`, `Ccc`, `Ddd`", ); } } mod field_identifier { use super::*; #[derive(Deserialize, Debug, PartialEq)] #[serde(field_identifier, rename_all = "snake_case")] enum F { Aaa, #[serde(alias = "ccc", alias = "ddd")] Bbb, } #[test] fn field1() { assert_de_tokens(&F::Aaa, &[Token::U8(0)]); assert_de_tokens(&F::Aaa, &[Token::U16(0)]); assert_de_tokens(&F::Aaa, &[Token::U32(0)]); 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 aliases() { assert_de_tokens(&F::Bbb, &[Token::U8(1)]); assert_de_tokens(&F::Bbb, &[Token::U16(1)]); assert_de_tokens(&F::Bbb, &[Token::U32(1)]); assert_de_tokens(&F::Bbb, &[Token::U64(1)]); assert_de_tokens(&F::Bbb, &[Token::Str("bbb")]); assert_de_tokens(&F::Bbb, &[Token::Bytes(b"bbb")]); assert_de_tokens(&F::Bbb, &[Token::Str("ccc")]); assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ccc")]); assert_de_tokens(&F::Bbb, &[Token::Str("ddd")]); assert_de_tokens(&F::Bbb, &[Token::Bytes(b"ddd")]); } #[test] fn unknown() { assert_de_tokens_error::( &[Token::U8(42)], "invalid value: integer `42`, expected field index 0 <= i < 2", ); assert_de_tokens_error::( &[Token::U16(42)], "invalid value: integer `42`, expected field index 0 <= i < 2", ); assert_de_tokens_error::( &[Token::U32(42)], "invalid value: integer `42`, expected field index 0 <= i < 2", ); assert_de_tokens_error::( &[Token::U64(42)], "invalid value: integer `42`, expected field index 0 <= i < 2", ); assert_de_tokens_error::( &[Token::Str("unknown")], "unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`", ); assert_de_tokens_error::( &[Token::Bytes(b"unknown")], "unknown field `unknown`, expected one of `aaa`, `bbb`, `ccc`, `ddd`", ); } #[test] fn 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)]); 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 { 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")]); } } ================================================ FILE: test_suite/tests/test_ignored_any.rs ================================================ #![allow(clippy::derive_partial_eq_without_eq)] use serde::de::value::{Error, MapDeserializer, SeqDeserializer}; use serde::de::{ Deserialize, DeserializeSeed, Deserializer, EnumAccess, IgnoredAny, IntoDeserializer, VariantAccess, Visitor, }; use serde::forward_to_deserialize_any; use serde_derive::Deserialize; #[derive(PartialEq, Debug, Deserialize)] enum Target { Unit, Newtype(i32), Tuple(i32, i32), Struct { a: i32 }, } struct Enum(&'static str); impl<'de> Deserializer<'de> for Enum { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_enum(self) } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } impl<'de> EnumAccess<'de> for Enum { type Error = Error; type Variant = Self; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: DeserializeSeed<'de>, { let v = seed.deserialize(self.0.into_deserializer())?; Ok((v, self)) } } impl<'de> VariantAccess<'de> for Enum { type Error = Error; fn unit_variant(self) -> Result<(), Self::Error> { Ok(()) } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { seed.deserialize(10i32.into_deserializer()) } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { let seq = SeqDeserializer::new(vec![1i32, 2].into_iter()); visitor.visit_seq(seq) } fn struct_variant( self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let map = MapDeserializer::new(vec![("a", 10i32)].into_iter()); visitor.visit_map(map) } } #[test] fn test_deserialize_enum() { // First just make sure the Deserializer impl works assert_eq!(Target::Unit, Target::deserialize(Enum("Unit")).unwrap()); assert_eq!( Target::Newtype(10), Target::deserialize(Enum("Newtype")).unwrap() ); assert_eq!( Target::Tuple(1, 2), Target::deserialize(Enum("Tuple")).unwrap() ); assert_eq!( Target::Struct { a: 10 }, Target::deserialize(Enum("Struct")).unwrap() ); // Now try IgnoredAny IgnoredAny::deserialize(Enum("Unit")).unwrap(); IgnoredAny::deserialize(Enum("Newtype")).unwrap(); IgnoredAny::deserialize(Enum("Tuple")).unwrap(); IgnoredAny::deserialize(Enum("Struct")).unwrap(); } ================================================ FILE: test_suite/tests/test_macros.rs ================================================ #![deny(trivial_numeric_casts)] #![allow( clippy::derive_partial_eq_without_eq, clippy::enum_variant_names, clippy::redundant_field_names, clippy::too_many_lines )] use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_de_tokens, assert_ser_tokens, assert_tokens, Token}; use std::marker::PhantomData; // That tests that the derived Serialize implementation doesn't trigger // any warning about `serializer` not being used, in case of empty enums. #[derive(Serialize)] #[allow(dead_code)] #[deny(unused_variables)] enum Void {} #[derive(Debug, PartialEq, Serialize, Deserialize)] struct NamedUnit; #[derive(Debug, PartialEq, Serialize)] struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C); #[derive(Debug, PartialEq, Deserialize)] struct DeNamedTuple(A, B, C); #[derive(Debug, PartialEq, Serialize)] struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> { a: &'a A, b: &'b mut B, c: C, } #[derive(Debug, PartialEq, Deserialize)] struct DeNamedMap { a: A, b: B, c: C, } #[derive(Debug, PartialEq, Serialize)] enum SerEnum<'a, B: 'a, C: 'a, D> where D: 'a, { Unit, Seq(i8, B, &'a C, &'a mut D), Map { a: i8, b: B, c: &'a C, d: &'a mut D }, // Make sure we can support more than one variant. _Unit2, _Seq2(i8, B, &'a C, &'a mut D), _Map2 { a: i8, b: B, c: &'a C, d: &'a mut D }, } #[derive(Debug, PartialEq, Serialize, Deserialize)] enum DeEnum { Unit, Seq(i8, B, C, D), Map { a: i8, b: B, c: C, d: D }, // Make sure we can support more than one variant. _Unit2, _Seq2(i8, B, C, D), _Map2 { a: i8, b: B, c: C, d: D }, } #[derive(Serialize)] enum Lifetimes<'a> { LifetimeSeq(&'a i32), NoLifetimeSeq(i32), LifetimeMap { a: &'a i32 }, NoLifetimeMap { a: i32 }, } #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct GenericStruct { x: T, } #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct GenericNewTypeStruct(T); #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct GenericTupleStruct(T, U); #[derive(Debug, PartialEq, Serialize, Deserialize)] pub enum GenericEnum { Unit, NewType(T), Seq(T, U), Map { x: T, y: U }, } trait AssociatedType { type X; } impl AssociatedType for i32 { type X = i32; } #[derive(Debug, PartialEq, Serialize, Deserialize)] struct DefaultTyParam = i32> { phantom: PhantomData, } #[test] fn test_named_unit() { assert_tokens(&NamedUnit, &[Token::UnitStruct { name: "NamedUnit" }]); } #[test] fn test_ser_named_tuple() { let a = 5; let mut b = 6; let c = 7; assert_ser_tokens( &SerNamedTuple(&a, &mut b, c), &[ Token::TupleStruct { name: "SerNamedTuple", len: 3, }, Token::I32(5), Token::I32(6), Token::I32(7), Token::TupleStructEnd, ], ); } #[test] fn test_de_named_tuple() { assert_de_tokens( &DeNamedTuple(5, 6, 7), &[ Token::Seq { len: Some(3) }, Token::I32(5), Token::I32(6), Token::I32(7), Token::SeqEnd, ], ); assert_de_tokens( &DeNamedTuple(5, 6, 7), &[ Token::TupleStruct { name: "DeNamedTuple", len: 3, }, Token::I32(5), Token::I32(6), Token::I32(7), Token::TupleStructEnd, ], ); } #[test] fn test_ser_named_map() { let a = 5; let mut b = 6; let c = 7; assert_ser_tokens( &SerNamedMap { a: &a, b: &mut b, c: c, }, &[ Token::Struct { name: "SerNamedMap", len: 3, }, Token::Str("a"), Token::I32(5), Token::Str("b"), Token::I32(6), Token::Str("c"), Token::I32(7), Token::StructEnd, ], ); } #[test] fn test_de_named_map() { assert_de_tokens( &DeNamedMap { a: 5, b: 6, c: 7 }, &[ Token::Struct { name: "DeNamedMap", len: 3, }, Token::Str("a"), Token::I32(5), Token::Str("b"), Token::I32(6), Token::Str("c"), Token::I32(7), Token::StructEnd, ], ); } #[test] fn test_ser_enum_unit() { assert_ser_tokens( &SerEnum::Unit::, &[Token::UnitVariant { name: "SerEnum", variant: "Unit", }], ); } #[test] fn test_ser_enum_seq() { let a = 1; let b = 2; let c = 3; let mut d = 4; assert_ser_tokens( &SerEnum::Seq(a, b, &c, &mut d), &[ Token::TupleVariant { name: "SerEnum", variant: "Seq", len: 4, }, Token::I8(1), Token::I32(2), Token::I32(3), Token::I32(4), Token::TupleVariantEnd, ], ); } #[test] fn test_ser_enum_map() { let a = 1; let b = 2; let c = 3; let mut d = 4; assert_ser_tokens( &SerEnum::Map { a: a, b: b, c: &c, d: &mut d, }, &[ Token::StructVariant { name: "SerEnum", variant: "Map", len: 4, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::I32(2), Token::Str("c"), Token::I32(3), Token::Str("d"), Token::I32(4), Token::StructVariantEnd, ], ); } #[test] fn test_de_enum_unit() { assert_tokens( &DeEnum::Unit::, &[Token::UnitVariant { name: "DeEnum", variant: "Unit", }], ); } #[test] fn test_de_enum_seq() { let a = 1; let b = 2; let c = 3; let d = 4; assert_tokens( &DeEnum::Seq(a, b, c, d), &[ Token::TupleVariant { name: "DeEnum", variant: "Seq", len: 4, }, Token::I8(1), Token::I32(2), Token::I32(3), Token::I32(4), Token::TupleVariantEnd, ], ); } #[test] fn test_de_enum_map() { let a = 1; let b = 2; let c = 3; let d = 4; assert_tokens( &DeEnum::Map { a: a, b: b, c: c, d: d, }, &[ Token::StructVariant { name: "DeEnum", variant: "Map", len: 4, }, Token::Str("a"), Token::I8(1), Token::Str("b"), Token::I32(2), Token::Str("c"), Token::I32(3), Token::Str("d"), Token::I32(4), Token::StructVariantEnd, ], ); } #[test] fn test_lifetimes() { let value = 5; assert_ser_tokens( &Lifetimes::LifetimeSeq(&value), &[ Token::NewtypeVariant { name: "Lifetimes", variant: "LifetimeSeq", }, Token::I32(5), ], ); assert_ser_tokens( &Lifetimes::NoLifetimeSeq(5), &[ Token::NewtypeVariant { name: "Lifetimes", variant: "NoLifetimeSeq", }, Token::I32(5), ], ); assert_ser_tokens( &Lifetimes::LifetimeMap { a: &value }, &[ Token::StructVariant { name: "Lifetimes", variant: "LifetimeMap", len: 1, }, Token::Str("a"), Token::I32(5), Token::StructVariantEnd, ], ); assert_ser_tokens( &Lifetimes::NoLifetimeMap { a: 5 }, &[ Token::StructVariant { name: "Lifetimes", variant: "NoLifetimeMap", len: 1, }, Token::Str("a"), Token::I32(5), Token::StructVariantEnd, ], ); } #[test] fn test_generic_struct() { assert_tokens( &GenericStruct { x: 5u32 }, &[ Token::Struct { name: "GenericStruct", len: 1, }, Token::Str("x"), Token::U32(5), Token::StructEnd, ], ); } #[test] fn test_generic_newtype_struct() { assert_tokens( &GenericNewTypeStruct(5u32), &[ Token::NewtypeStruct { name: "GenericNewTypeStruct", }, Token::U32(5), ], ); } #[test] fn test_generic_tuple_struct() { assert_tokens( &GenericTupleStruct(5u32, 6u32), &[ Token::TupleStruct { name: "GenericTupleStruct", len: 2, }, Token::U32(5), Token::U32(6), Token::TupleStructEnd, ], ); } #[test] fn test_generic_enum_unit() { assert_tokens( &GenericEnum::Unit::, &[Token::UnitVariant { name: "GenericEnum", variant: "Unit", }], ); } #[test] fn test_generic_enum_newtype() { assert_tokens( &GenericEnum::NewType::(5), &[ Token::NewtypeVariant { name: "GenericEnum", variant: "NewType", }, Token::U32(5), ], ); } #[test] fn test_generic_enum_seq() { assert_tokens( &GenericEnum::Seq::(5, 6), &[ Token::TupleVariant { name: "GenericEnum", variant: "Seq", len: 2, }, Token::U32(5), Token::U32(6), Token::TupleVariantEnd, ], ); } #[test] fn test_generic_enum_map() { assert_tokens( &GenericEnum::Map:: { x: 5, y: 6 }, &[ Token::StructVariant { name: "GenericEnum", variant: "Map", len: 2, }, Token::Str("x"), Token::U32(5), Token::Str("y"), Token::U32(6), Token::StructVariantEnd, ], ); } #[test] fn test_default_ty_param() { assert_tokens( &DefaultTyParam:: { phantom: PhantomData, }, &[ Token::Struct { name: "DefaultTyParam", len: 1, }, Token::Str("phantom"), Token::UnitStruct { name: "PhantomData", }, Token::StructEnd, ], ); } #[test] fn test_enum_state_field() { #[derive(Debug, PartialEq, Serialize, Deserialize)] enum SomeEnum { Key { key: char, state: bool }, } assert_tokens( &SomeEnum::Key { key: 'a', state: true, }, &[ Token::StructVariant { name: "SomeEnum", variant: "Key", len: 2, }, Token::Str("key"), Token::Char('a'), Token::Str("state"), Token::Bool(true), Token::StructVariantEnd, ], ); } #[test] fn test_internally_tagged_struct() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub struct Struct { a: u8, } assert_tokens( &Struct { a: 1 }, &[ Token::Struct { name: "Struct", len: 2, }, Token::Str("type"), Token::Str("Struct"), Token::Str("a"), Token::U8(1), Token::StructEnd, ], ); assert_de_tokens( &Struct { a: 1 }, &[ Token::Struct { name: "Struct", len: 1, }, Token::Str("a"), Token::U8(1), Token::StructEnd, ], ); } #[test] fn test_internally_tagged_braced_struct_with_zero_fields() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] struct S {} assert_tokens( &S {}, &[ Token::Struct { name: "S", len: 1 }, Token::Str("type"), Token::Str("S"), Token::StructEnd, ], ); } #[test] fn test_internally_tagged_struct_with_flattened_field() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag_struct")] pub struct Struct { #[serde(flatten)] pub flat: Enum, } #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "tag_enum", content = "content")] pub enum Enum { A(u64), } assert_tokens( &Struct { flat: Enum::A(0) }, &[ Token::Map { len: None }, Token::Str("tag_struct"), Token::Str("Struct"), Token::Str("tag_enum"), Token::UnitVariant { name: "Enum", variant: "A", }, Token::Str("content"), Token::U64(0), Token::MapEnd, ], ); assert_de_tokens( &Struct { flat: Enum::A(0) }, &[ Token::Map { len: None }, Token::Str("tag_enum"), Token::Str("A"), Token::Str("content"), Token::U64(0), Token::MapEnd, ], ); } #[test] fn test_rename_all() { #[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(rename_all = "snake_case")] enum E { #[serde(rename_all = "camelCase")] Serialize { serialize: bool, serialize_seq: bool, }, #[serde(rename_all = "kebab-case")] SerializeSeq { serialize: bool, serialize_seq: bool, }, #[serde(rename_all = "SCREAMING_SNAKE_CASE")] SerializeMap { serialize: bool, serialize_seq: bool, }, } #[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(rename_all = "PascalCase")] struct S { serialize: bool, serialize_seq: bool, } #[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(rename_all = "SCREAMING-KEBAB-CASE")] struct ScreamingKebab { serialize: bool, serialize_seq: bool, } assert_tokens( &E::Serialize { serialize: true, serialize_seq: true, }, &[ Token::StructVariant { name: "E", variant: "serialize", len: 2, }, Token::Str("serialize"), Token::Bool(true), Token::Str("serializeSeq"), Token::Bool(true), Token::StructVariantEnd, ], ); assert_tokens( &E::SerializeSeq { serialize: true, serialize_seq: true, }, &[ Token::StructVariant { name: "E", variant: "serialize_seq", len: 2, }, Token::Str("serialize"), Token::Bool(true), Token::Str("serialize-seq"), Token::Bool(true), Token::StructVariantEnd, ], ); assert_tokens( &E::SerializeMap { serialize: true, serialize_seq: true, }, &[ Token::StructVariant { name: "E", variant: "serialize_map", len: 2, }, Token::Str("SERIALIZE"), Token::Bool(true), Token::Str("SERIALIZE_SEQ"), Token::Bool(true), Token::StructVariantEnd, ], ); assert_tokens( &S { serialize: true, serialize_seq: true, }, &[ Token::Struct { name: "S", len: 2 }, Token::Str("Serialize"), Token::Bool(true), Token::Str("SerializeSeq"), Token::Bool(true), Token::StructEnd, ], ); assert_tokens( &ScreamingKebab { serialize: true, serialize_seq: true, }, &[ Token::Struct { name: "ScreamingKebab", len: 2, }, Token::Str("SERIALIZE"), Token::Bool(true), Token::Str("SERIALIZE-SEQ"), Token::Bool(true), Token::StructEnd, ], ); } #[test] fn test_rename_all_fields() { #[derive(Serialize, Deserialize, Debug, PartialEq)] #[serde(rename_all_fields = "kebab-case")] enum E { V1, V2(bool), V3 { a_field: bool, another_field: bool, #[serde(rename = "last-field")] yet_another_field: bool, }, #[serde(rename_all = "snake_case")] V4 { a_field: bool, }, } assert_tokens( &E::V3 { a_field: true, another_field: true, yet_another_field: true, }, &[ Token::StructVariant { name: "E", variant: "V3", len: 3, }, Token::Str("a-field"), Token::Bool(true), Token::Str("another-field"), Token::Bool(true), Token::Str("last-field"), Token::Bool(true), Token::StructVariantEnd, ], ); assert_tokens( &E::V4 { a_field: true }, &[ Token::StructVariant { name: "E", variant: "V4", len: 1, }, Token::Str("a_field"), Token::Bool(true), Token::StructVariantEnd, ], ); } #[test] fn test_packed_struct_can_derive_serialize() { #[derive(Copy, Clone, Serialize)] #[repr(packed, C)] #[allow(dead_code)] struct PackedC { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(C, packed)] #[allow(dead_code)] struct CPacked { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(C, packed(2))] #[allow(dead_code)] struct CPacked2 { t: f32, } #[derive(Copy, Clone, Serialize)] #[repr(packed(2), C)] #[allow(dead_code)] struct Packed2C { t: f32, } } ================================================ FILE: test_suite/tests/test_remote.rs ================================================ #![allow(clippy::redundant_field_names, dead_code)] use serde_derive::{Deserialize, Serialize}; mod remote { pub struct Unit; pub struct PrimitivePriv(u8); #[allow(dead_code)] pub struct PrimitivePub(pub u8); pub struct NewtypePriv(Unit); #[allow(dead_code)] pub struct NewtypePub(pub Unit); pub struct TuplePriv(u8, Unit); #[allow(dead_code)] pub struct TuplePub(pub u8, pub Unit); pub struct StructPriv { a: u8, b: Unit, } #[allow(dead_code)] pub struct StructPub { pub a: u8, pub b: Unit, } impl PrimitivePriv { pub fn new(a: u8) -> Self { PrimitivePriv(a) } pub fn get(&self) -> u8 { self.0 } } impl NewtypePriv { pub fn new(a: Unit) -> Self { NewtypePriv(a) } pub fn get(&self) -> &Unit { &self.0 } } impl TuplePriv { pub fn new(a: u8, b: Unit) -> Self { TuplePriv(a, b) } pub fn first(&self) -> u8 { self.0 } pub fn second(&self) -> &Unit { &self.1 } } impl StructPriv { pub fn new(a: u8, b: Unit) -> Self { StructPriv { a: a, b: b } } pub fn a(&self) -> u8 { self.a } pub fn b(&self) -> &Unit { &self.b } } pub struct StructGeneric { pub value: T, } impl StructGeneric { #[allow(dead_code)] pub fn get_value(&self) -> &T { &self.value } } #[allow(dead_code)] pub enum EnumGeneric { Variant(T), } } #[derive(Serialize, Deserialize)] #[allow(dead_code)] struct Test { #[serde(with = "UnitDef")] unit: remote::Unit, #[serde(with = "PrimitivePrivDef")] primitive_priv: remote::PrimitivePriv, #[serde(with = "PrimitivePubDef")] primitive_pub: remote::PrimitivePub, #[serde(with = "NewtypePrivDef")] newtype_priv: remote::NewtypePriv, #[serde(with = "NewtypePubDef")] newtype_pub: remote::NewtypePub, #[serde(with = "TuplePrivDef")] tuple_priv: remote::TuplePriv, #[serde(with = "TuplePubDef")] tuple_pub: remote::TuplePub, #[serde(with = "StructPrivDef")] struct_priv: remote::StructPriv, #[serde(with = "StructPubDef")] struct_pub: remote::StructPub, #[serde(with = "StructConcrete")] struct_concrete: remote::StructGeneric, #[serde(with = "EnumConcrete")] enum_concrete: remote::EnumGeneric, #[serde(with = "ErrorKindDef")] io_error_kind: ErrorKind, } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::Unit")] #[allow(dead_code)] struct UnitDef; #[derive(Serialize, Deserialize)] #[serde(remote = "remote::PrimitivePriv")] struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::PrimitivePub")] #[allow(dead_code)] struct PrimitivePubDef(u8); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::NewtypePriv")] struct NewtypePrivDef(#[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::NewtypePub")] #[allow(dead_code)] struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::TuplePriv")] struct TuplePrivDef( #[serde(getter = "remote::TuplePriv::first")] u8, #[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit, ); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::TuplePub")] #[allow(dead_code)] struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructPriv")] struct StructPrivDef { #[serde(getter = "remote::StructPriv::a")] a: u8, #[serde(getter = "remote::StructPriv::b")] #[serde(with = "UnitDef")] b: remote::Unit, } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructPub")] #[allow(dead_code)] struct StructPubDef { a: u8, #[serde(with = "UnitDef")] b: remote::Unit, } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructGeneric")] struct StructGenericWithGetterDef { #[serde(getter = "remote::StructGeneric::get_value")] value: T, } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructGeneric")] #[allow(dead_code)] struct StructConcrete { value: u8, } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::EnumGeneric")] #[allow(dead_code)] enum EnumConcrete { Variant(u8), } #[derive(Debug)] #[allow(dead_code)] enum ErrorKind { NotFound, PermissionDenied, #[allow(dead_code)] ConnectionRefused, } #[derive(Serialize, Deserialize)] #[serde(remote = "ErrorKind")] #[non_exhaustive] #[allow(dead_code)] enum ErrorKindDef { NotFound, PermissionDenied, // ... } impl From for remote::PrimitivePriv { fn from(def: PrimitivePrivDef) -> Self { remote::PrimitivePriv::new(def.0) } } impl From for remote::NewtypePriv { fn from(def: NewtypePrivDef) -> Self { remote::NewtypePriv::new(def.0) } } impl From for remote::TuplePriv { fn from(def: TuplePrivDef) -> Self { remote::TuplePriv::new(def.0, def.1) } } impl From for remote::StructPriv { fn from(def: StructPrivDef) -> Self { remote::StructPriv::new(def.a, def.b) } } impl From> for remote::StructGeneric { fn from(def: StructGenericWithGetterDef) -> Self { remote::StructGeneric { value: def.value } } } ================================================ FILE: test_suite/tests/test_roundtrip.rs ================================================ use serde_test::{assert_tokens, Configure, Token}; use std::net; #[macro_use] #[allow(unused_macros)] mod macros; #[test] fn ip_addr_roundtrip() { assert_tokens( &net::IpAddr::from(*b"1234").compact(), &seq![ Token::NewtypeVariant { name: "IpAddr", variant: "V4" }, Token::Tuple { len: 4 }, b"1234".iter().copied().map(Token::U8), Token::TupleEnd, ], ); } #[test] fn socket_addr_roundtrip() { assert_tokens( &net::SocketAddr::from((*b"1234567890123456", 1234)).compact(), &seq![ Token::NewtypeVariant { name: "SocketAddr", variant: "V6" }, Token::Tuple { len: 2 }, Token::Tuple { len: 16 }, b"1234567890123456".iter().copied().map(Token::U8), Token::TupleEnd, Token::U16(1234), Token::TupleEnd, ], ); } ================================================ FILE: test_suite/tests/test_self.rs ================================================ #![allow(clippy::used_underscore_binding, dead_code)] use serde_derive::{Deserialize, Serialize}; #[test] fn test_self() { pub trait Trait { type Assoc; } #[derive(Deserialize, Serialize)] pub struct Generics> where Self: Trait, ::Assoc: Sized, { _f: T, } impl> Trait for Generics { type Assoc = Self; } #[derive(Deserialize, Serialize)] pub struct Struct { _f1: Box, _f2: Box<::Assoc>, _f4: [(); Self::ASSOC], _f5: [(); Self::assoc()], } impl Struct { const ASSOC: usize = 1; const fn assoc() -> usize { 0 } } impl Trait for Struct { type Assoc = Self; } #[derive(Deserialize, Serialize)] pub struct Tuple( Box, Box<::Assoc>, [(); Self::ASSOC], [(); Self::assoc()], ); impl Tuple { const ASSOC: usize = 1; const fn assoc() -> usize { 0 } } impl Trait for Tuple { type Assoc = Self; } #[derive(Deserialize, Serialize)] pub enum Enum { Struct { _f1: Box, _f2: Box<::Assoc>, _f4: [(); Self::ASSOC], _f5: [(); Self::assoc()], }, Tuple( Box, Box<::Assoc>, [(); Self::ASSOC], [(); Self::assoc()], ), } impl Enum { const ASSOC: usize = 1; const fn assoc() -> usize { 0 } } impl Trait for Enum { type Assoc = Self; } } ================================================ FILE: test_suite/tests/test_ser.rs ================================================ #![allow(clippy::derive_partial_eq_without_eq, clippy::unreadable_literal)] #![cfg_attr(feature = "unstable", feature(never_type))] use serde_derive::Serialize; use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token}; use std::cell::RefCell; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::ffi::CString; use std::net; use std::num::{Saturating, Wrapping}; use std::ops::Bound; use std::path::{Path, PathBuf}; use std::rc::{Rc, Weak as RcWeak}; #[cfg(unix)] use std::str; use std::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, }; #[cfg(target_arch = "x86_64")] use std::sync::atomic::{AtomicI64, AtomicU64}; use std::sync::{Arc, Mutex, RwLock, Weak as ArcWeak}; use std::time::{Duration, UNIX_EPOCH}; #[macro_use] mod macros; ////////////////////////////////////////////////////////////////////////// #[derive(Serialize)] struct UnitStruct; #[derive(Serialize)] struct TupleStruct(i32, i32, i32); #[derive(Serialize)] struct Struct { a: i32, b: i32, c: i32, } #[derive(PartialEq, Debug)] struct NotSerializable; #[derive(Serialize, PartialEq, Debug)] enum Enum { Unit, One(i32), Seq(i32, i32), Map { a: i32, b: i32, }, #[serde(skip_serializing)] SkippedUnit, #[serde(skip_serializing)] SkippedOne(i32), #[serde(skip_serializing)] SkippedSeq(i32, i32), #[serde(skip_serializing)] SkippedMap { _a: i32, _b: i32, }, OneWithSkipped(#[serde(skip_serializing)] NotSerializable), } ////////////////////////////////////////////////////////////////////////// #[test] fn test_unit() { assert_ser_tokens(&(), &[Token::Unit]); } #[test] fn test_bool() { assert_ser_tokens(&true, &[Token::Bool(true)]); assert_ser_tokens(&false, &[Token::Bool(false)]); } #[test] fn test_isizes() { assert_ser_tokens(&0i8, &[Token::I8(0)]); assert_ser_tokens(&0i16, &[Token::I16(0)]); assert_ser_tokens(&0i32, &[Token::I32(0)]); assert_ser_tokens(&0i64, &[Token::I64(0)]); } #[test] fn test_usizes() { assert_ser_tokens(&0u8, &[Token::U8(0)]); assert_ser_tokens(&0u16, &[Token::U16(0)]); assert_ser_tokens(&0u32, &[Token::U32(0)]); assert_ser_tokens(&0u64, &[Token::U64(0)]); } #[test] fn test_floats() { assert_ser_tokens(&0f32, &[Token::F32(0.)]); assert_ser_tokens(&0f64, &[Token::F64(0.)]); } #[test] fn test_char() { assert_ser_tokens(&'a', &[Token::Char('a')]); } #[test] fn test_str() { assert_ser_tokens(&"abc", &[Token::Str("abc")]); assert_ser_tokens(&"abc".to_owned(), &[Token::Str("abc")]); } #[test] fn test_option() { assert_ser_tokens(&None::, &[Token::None]); assert_ser_tokens(&Some(1), &[Token::Some, Token::I32(1)]); } #[test] fn test_result() { assert_ser_tokens( &Ok::(0), &[ Token::NewtypeVariant { name: "Result", variant: "Ok", }, Token::I32(0), ], ); assert_ser_tokens( &Err::(1), &[ Token::NewtypeVariant { name: "Result", variant: "Err", }, Token::I32(1), ], ); } #[test] fn test_slice() { assert_ser_tokens(&[0][..0], &[Token::Seq { len: Some(0) }, Token::SeqEnd]); assert_ser_tokens( &[1, 2, 3][..], &[ Token::Seq { len: Some(3) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::SeqEnd, ], ); } #[test] fn test_array() { assert_ser_tokens(&[0; 0], &[Token::Tuple { len: 0 }, Token::TupleEnd]); assert_ser_tokens( &[1, 2, 3], &[ Token::Tuple { len: 3 }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleEnd, ], ); } #[test] fn test_vec() { assert_ser_tokens( &Vec::::new(), &[Token::Seq { len: Some(0) }, Token::SeqEnd], ); assert_ser_tokens( &vec![vec![], vec![1], vec![2, 3]], &[ Token::Seq { len: Some(3) }, Token::Seq { len: Some(0) }, Token::SeqEnd, Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd, Token::Seq { len: Some(2) }, Token::I32(2), Token::I32(3), Token::SeqEnd, Token::SeqEnd, ], ); } #[test] fn test_btreeset() { assert_ser_tokens( &BTreeSet::::new(), &[Token::Seq { len: Some(0) }, Token::SeqEnd], ); assert_ser_tokens( &btreeset![1], &[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd], ); } #[test] fn test_hashset() { assert_ser_tokens( &HashSet::::new(), &[Token::Seq { len: Some(0) }, Token::SeqEnd], ); assert_ser_tokens( &hashset![1], &[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd], ); assert_ser_tokens( &hashset![foldhash::fast::FixedState; 1], &[Token::Seq { len: Some(1) }, Token::I32(1), Token::SeqEnd], ); } #[test] fn test_tuple() { assert_ser_tokens( &(1,), &[Token::Tuple { len: 1 }, Token::I32(1), Token::TupleEnd], ); assert_ser_tokens( &(1, 2, 3), &[ Token::Tuple { len: 3 }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleEnd, ], ); } #[test] fn test_btreemap() { assert_ser_tokens( &btreemap![1 => 2], &[ Token::Map { len: Some(1) }, Token::I32(1), Token::I32(2), Token::MapEnd, ], ); assert_ser_tokens( &btreemap![1 => 2, 3 => 4], &[ Token::Map { len: Some(2) }, Token::I32(1), Token::I32(2), Token::I32(3), Token::I32(4), Token::MapEnd, ], ); assert_ser_tokens( &btreemap![1 => btreemap![], 2 => btreemap![3 => 4, 5 => 6]], &[ Token::Map { len: Some(2) }, Token::I32(1), Token::Map { len: Some(0) }, Token::MapEnd, Token::I32(2), Token::Map { len: Some(2) }, Token::I32(3), Token::I32(4), Token::I32(5), Token::I32(6), Token::MapEnd, Token::MapEnd, ], ); } #[test] fn test_hashmap() { assert_ser_tokens( &HashMap::::new(), &[Token::Map { len: Some(0) }, Token::MapEnd], ); assert_ser_tokens( &hashmap![1 => 2], &[ Token::Map { len: Some(1) }, Token::I32(1), Token::I32(2), Token::MapEnd, ], ); assert_ser_tokens( &hashmap![foldhash::fast::FixedState; 1 => 2], &[ Token::Map { len: Some(1) }, Token::I32(1), Token::I32(2), Token::MapEnd, ], ); } #[test] fn test_unit_struct() { assert_ser_tokens(&UnitStruct, &[Token::UnitStruct { name: "UnitStruct" }]); } #[test] fn test_tuple_struct() { assert_ser_tokens( &TupleStruct(1, 2, 3), &[ Token::TupleStruct { name: "TupleStruct", len: 3, }, Token::I32(1), Token::I32(2), Token::I32(3), Token::TupleStructEnd, ], ); } #[test] fn test_struct() { assert_ser_tokens( &Struct { a: 1, b: 2, c: 3 }, &[ Token::Struct { name: "Struct", len: 3, }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::Str("c"), Token::I32(3), Token::StructEnd, ], ); } #[test] fn test_enum() { assert_ser_tokens( &Enum::Unit, &[Token::UnitVariant { name: "Enum", variant: "Unit", }], ); assert_ser_tokens( &Enum::One(42), &[ Token::NewtypeVariant { name: "Enum", variant: "One", }, Token::I32(42), ], ); assert_ser_tokens( &Enum::Seq(1, 2), &[ Token::TupleVariant { name: "Enum", variant: "Seq", len: 2, }, Token::I32(1), Token::I32(2), Token::TupleVariantEnd, ], ); assert_ser_tokens( &Enum::Map { a: 1, b: 2 }, &[ Token::StructVariant { name: "Enum", variant: "Map", len: 2, }, Token::Str("a"), Token::I32(1), Token::Str("b"), Token::I32(2), Token::StructVariantEnd, ], ); assert_ser_tokens( &Enum::OneWithSkipped(NotSerializable), &[Token::UnitVariant { name: "Enum", variant: "OneWithSkipped", }], ); } #[test] fn test_box() { assert_ser_tokens(&Box::new(0i32), &[Token::I32(0)]); } #[test] fn test_boxed_slice() { assert_ser_tokens( &Box::new([0, 1, 2]), &[ Token::Tuple { len: 3 }, Token::I32(0), Token::I32(1), Token::I32(2), Token::TupleEnd, ], ); } #[test] fn test_duration() { assert_ser_tokens( &Duration::new(1, 2), &[ Token::Struct { name: "Duration", len: 2, }, Token::Str("secs"), Token::U64(1), Token::Str("nanos"), Token::U32(2), Token::StructEnd, ], ); } #[test] fn test_system_time() { let system_time = UNIX_EPOCH + Duration::new(1, 200); assert_ser_tokens( &system_time, &[ Token::Struct { name: "SystemTime", len: 2, }, Token::Str("secs_since_epoch"), Token::U64(1), Token::Str("nanos_since_epoch"), Token::U32(200), Token::StructEnd, ], ); } #[test] fn test_range() { assert_ser_tokens( &(1u32..2u32), &[ Token::Struct { name: "Range", len: 2, }, Token::Str("start"), Token::U32(1), Token::Str("end"), Token::U32(2), Token::StructEnd, ], ); } #[test] fn test_range_inclusive() { assert_ser_tokens( &(1u32..=2u32), &[ Token::Struct { name: "RangeInclusive", len: 2, }, Token::Str("start"), Token::U32(1), Token::Str("end"), Token::U32(2), Token::StructEnd, ], ); } #[test] fn test_range_from() { assert_ser_tokens( &(1u32..), &[ Token::Struct { name: "RangeFrom", len: 1, }, Token::Str("start"), Token::U32(1), Token::StructEnd, ], ); } #[test] fn test_range_to() { assert_ser_tokens( &(..2u32), &[ Token::Struct { name: "RangeTo", len: 1, }, Token::Str("end"), Token::U32(2), Token::StructEnd, ], ); } #[test] fn test_bound() { assert_ser_tokens( &Bound::Unbounded::<()>, &[ Token::Enum { name: "Bound" }, Token::Str("Unbounded"), Token::Unit, ], ); assert_ser_tokens( &Bound::Included(0u8), &[ Token::Enum { name: "Bound" }, Token::Str("Included"), Token::U8(0), ], ); assert_ser_tokens( &Bound::Excluded(0u8), &[ Token::Enum { name: "Bound" }, Token::Str("Excluded"), Token::U8(0), ], ); } #[test] fn test_path() { assert_ser_tokens( &Path::new("/usr/local/lib"), &[Token::Str("/usr/local/lib")], ); } #[test] fn test_path_buf() { assert_ser_tokens( &PathBuf::from("/usr/local/lib"), &[Token::Str("/usr/local/lib")], ); } #[test] fn test_cstring() { assert_ser_tokens(&CString::new("abc").unwrap(), &[Token::Bytes(b"abc")]); } #[test] fn test_cstr() { let cstring = CString::new("abc").unwrap(); assert_ser_tokens(cstring.as_c_str(), &[Token::Bytes(b"abc")]); } #[test] fn test_rc() { assert_ser_tokens(&Rc::new(true), &[Token::Bool(true)]); } #[test] fn test_rc_weak_some() { let rc = Rc::new(true); assert_ser_tokens(&Rc::downgrade(&rc), &[Token::Some, Token::Bool(true)]); } #[test] fn test_rc_weak_none() { assert_ser_tokens(&RcWeak::::new(), &[Token::None]); } #[test] fn test_arc() { assert_ser_tokens(&Arc::new(true), &[Token::Bool(true)]); } #[test] fn test_arc_weak_some() { let arc = Arc::new(true); assert_ser_tokens(&Arc::downgrade(&arc), &[Token::Some, Token::Bool(true)]); } #[test] fn test_arc_weak_none() { assert_ser_tokens(&ArcWeak::::new(), &[Token::None]); } #[test] fn test_wrapping() { assert_ser_tokens(&Wrapping(1usize), &[Token::U64(1)]); } #[test] fn test_saturating() { assert_ser_tokens(&Saturating(1usize), &[Token::U64(1)]); } #[test] fn test_rc_dst() { assert_ser_tokens(&Rc::::from("s"), &[Token::Str("s")]); assert_ser_tokens( &Rc::<[bool]>::from(&[true][..]), &[ Token::Seq { len: Some(1) }, Token::Bool(true), Token::SeqEnd, ], ); } #[test] fn test_arc_dst() { assert_ser_tokens(&Arc::::from("s"), &[Token::Str("s")]); assert_ser_tokens( &Arc::<[bool]>::from(&[true][..]), &[ Token::Seq { len: Some(1) }, Token::Bool(true), Token::SeqEnd, ], ); } #[test] fn test_fmt_arguments() { assert_ser_tokens(&format_args!("{}{}", 1, 'a'), &[Token::Str("1a")]); } #[test] fn test_atomic() { assert_ser_tokens(&AtomicBool::new(false), &[Token::Bool(false)]); assert_ser_tokens(&AtomicBool::new(true), &[Token::Bool(true)]); assert_ser_tokens(&AtomicI8::new(63i8), &[Token::I8(63i8)]); assert_ser_tokens(&AtomicI16::new(-318i16), &[Token::I16(-318i16)]); assert_ser_tokens(&AtomicI32::new(65792i32), &[Token::I32(65792i32)]); assert_ser_tokens(&AtomicIsize::new(-65792isize), &[Token::I64(-65792i64)]); assert_ser_tokens(&AtomicU8::new(192u8), &[Token::U8(192u8)]); assert_ser_tokens(&AtomicU16::new(510u16), &[Token::U16(510u16)]); assert_ser_tokens(&AtomicU32::new(131072u32), &[Token::U32(131072u32)]); assert_ser_tokens(&AtomicUsize::new(655360usize), &[Token::U64(655360u64)]); } #[cfg(target_arch = "x86_64")] #[test] fn test_atomic64() { assert_ser_tokens( &AtomicI64::new(-4295032832i64), &[Token::I64(-4295032832i64)], ); assert_ser_tokens( &AtomicU64::new(12884901888u64), &[Token::U64(12884901888u64)], ); } #[test] fn test_net_ipv4addr_readable() { assert_ser_tokens( &"1.2.3.4".parse::().unwrap().readable(), &[Token::Str("1.2.3.4")], ); } #[test] fn test_net_ipv6addr_readable() { assert_ser_tokens( &"::1".parse::().unwrap().readable(), &[Token::Str("::1")], ); } #[test] fn test_net_ipaddr_readable() { assert_ser_tokens( &"1.2.3.4".parse::().unwrap().readable(), &[Token::Str("1.2.3.4")], ); } #[test] fn test_net_socketaddr_readable() { assert_ser_tokens( &"1.2.3.4:1234" .parse::() .unwrap() .readable(), &[Token::Str("1.2.3.4:1234")], ); assert_ser_tokens( &"1.2.3.4:1234" .parse::() .unwrap() .readable(), &[Token::Str("1.2.3.4:1234")], ); assert_ser_tokens( &"[::1]:1234" .parse::() .unwrap() .readable(), &[Token::Str("[::1]:1234")], ); } #[test] fn test_net_ipv4addr_compact() { assert_ser_tokens( &net::Ipv4Addr::from(*b"1234").compact(), &seq![ Token::Tuple { len: 4 }, b"1234".iter().copied().map(Token::U8), Token::TupleEnd, ], ); } #[test] fn test_net_ipv6addr_compact() { assert_ser_tokens( &net::Ipv6Addr::from(*b"1234567890123456").compact(), &seq![ Token::Tuple { len: 16 }, b"1234567890123456".iter().copied().map(Token::U8), Token::TupleEnd, ], ); } #[test] fn test_net_ipaddr_compact() { assert_ser_tokens( &net::IpAddr::from(*b"1234").compact(), &seq![ Token::NewtypeVariant { name: "IpAddr", variant: "V4" }, Token::Tuple { len: 4 }, b"1234".iter().copied().map(Token::U8), Token::TupleEnd, ], ); } #[test] fn test_net_socketaddr_compact() { assert_ser_tokens( &net::SocketAddr::from((*b"1234567890123456", 1234)).compact(), &seq![ Token::NewtypeVariant { name: "SocketAddr", variant: "V6" }, Token::Tuple { len: 2 }, Token::Tuple { len: 16 }, b"1234567890123456".iter().copied().map(Token::U8), Token::TupleEnd, Token::U16(1234), Token::TupleEnd, ], ); assert_ser_tokens( &net::SocketAddrV4::new(net::Ipv4Addr::from(*b"1234"), 1234).compact(), &seq![ Token::Tuple { len: 2 }, Token::Tuple { len: 4 }, b"1234".iter().copied().map(Token::U8), Token::TupleEnd, Token::U16(1234), Token::TupleEnd, ], ); assert_ser_tokens( &net::SocketAddrV6::new(net::Ipv6Addr::from(*b"1234567890123456"), 1234, 0, 0).compact(), &seq![ Token::Tuple { len: 2 }, Token::Tuple { len: 16 }, b"1234567890123456".iter().copied().map(Token::U8), Token::TupleEnd, Token::U16(1234), Token::TupleEnd, ], ); } #[cfg(feature = "unstable")] #[test] fn test_never_result() { assert_ser_tokens( &Ok::(0), &[ Token::NewtypeVariant { name: "Result", variant: "Ok", }, Token::U8(0), ], ); } #[test] #[cfg(unix)] fn test_cannot_serialize_paths() { use std::ffi::OsStr; use std::os::unix::ffi::OsStrExt; assert_ser_tokens_error( &Path::new(OsStr::from_bytes(b"Hello \xF0\x90\x80World")), &[], "path contains invalid UTF-8 characters", ); } #[test] fn test_cannot_serialize_mutably_borrowed_ref_cell() { let ref_cell = RefCell::new(42); let _reference = ref_cell.borrow_mut(); assert_ser_tokens_error(&ref_cell, &[], "already mutably borrowed"); } #[test] fn test_enum_skipped() { assert_ser_tokens_error( &Enum::SkippedUnit, &[], "the enum variant Enum::SkippedUnit cannot be serialized", ); assert_ser_tokens_error( &Enum::SkippedOne(42), &[], "the enum variant Enum::SkippedOne cannot be serialized", ); assert_ser_tokens_error( &Enum::SkippedSeq(1, 2), &[], "the enum variant Enum::SkippedSeq cannot be serialized", ); assert_ser_tokens_error( &Enum::SkippedMap { _a: 1, _b: 2 }, &[], "the enum variant Enum::SkippedMap cannot be serialized", ); } #[test] fn test_integer128() { assert_ser_tokens_error(&1i128, &[], "i128 is not supported"); assert_ser_tokens_error(&1u128, &[], "u128 is not supported"); } #[test] fn test_refcell_dst() { assert_ser_tokens( &RefCell::new([true]) as &RefCell<[bool]>, &[ Token::Seq { len: Some(1) }, Token::Bool(true), Token::SeqEnd, ], ); } #[test] fn test_mutex_dst() { assert_ser_tokens( &Mutex::new([true]) as &Mutex<[bool]>, &[ Token::Seq { len: Some(1) }, Token::Bool(true), Token::SeqEnd, ], ); } #[test] fn test_rwlock_dst() { assert_ser_tokens( &RwLock::new([true]) as &RwLock<[bool]>, &[ Token::Seq { len: Some(1) }, Token::Bool(true), Token::SeqEnd, ], ); } ================================================ FILE: test_suite/tests/test_serde_path.rs ================================================ #![allow( clippy::elidable_lifetime_names, clippy::extra_unused_type_parameters, clippy::needless_lifetimes, clippy::type_repetition_in_bounds )] #[test] fn test_gen_custom_serde() { #[derive(serde_derive::Serialize, serde_derive::Deserialize)] #[serde(crate = "fake_serde")] struct Foo; // Would be overlapping if serde::Serialize were implemented impl AssertNotSerdeSerialize for Foo {} // Would be overlapping if serde::Deserialize were implemented impl<'a> AssertNotSerdeDeserialize<'a> for Foo {} fake_serde::assert::(); } mod fake_serde { pub use serde::*; pub fn assert() where T: Serialize, T: for<'a> Deserialize<'a>, { } #[allow(dead_code)] pub trait Serialize { fn serialize(&self, serializer: S) -> Result; } #[allow(dead_code)] pub trait Deserialize<'a>: Sized { fn deserialize>(deserializer: D) -> Result; } } pub trait AssertNotSerdeSerialize {} impl AssertNotSerdeSerialize for T {} pub trait AssertNotSerdeDeserialize<'a> {} impl<'a, T: serde::Deserialize<'a>> AssertNotSerdeDeserialize<'a> for T {} ================================================ FILE: test_suite/tests/test_unstable.rs ================================================ #![deny(warnings)] #![allow(clippy::derive_partial_eq_without_eq)] // This test target is convoluted with the actual #[test] in a separate file to // get it so that the stable compiler does not need to parse the code of the // test. If the test were written with #[cfg(feature = "unstable")] #[test] // right here, the stable compiler would fail to parse those raw identifiers // even if the cfg were not enabled. #[cfg(feature = "unstable")] mod unstable; ================================================ FILE: test_suite/tests/test_value.rs ================================================ #![allow(clippy::derive_partial_eq_without_eq, clippy::similar_names)] use serde::de::value::{self, MapAccessDeserializer}; use serde::de::{Deserialize, Deserializer, IntoDeserializer, MapAccess, Visitor}; use serde_derive::Deserialize; use serde_test::{assert_de_tokens, Token}; use std::fmt; #[test] fn test_u32_to_enum() { #[derive(Deserialize, Debug, PartialEq)] enum E { A, B, } let deserializer = IntoDeserializer::::into_deserializer(1u32); let e: E = E::deserialize(deserializer).unwrap(); assert_eq!(E::B, e); } #[test] fn test_integer128() { let de_u128 = IntoDeserializer::::into_deserializer(1u128); let de_i128 = IntoDeserializer::::into_deserializer(1i128); // u128 to u128 assert_eq!(1u128, u128::deserialize(de_u128).unwrap()); // u128 to i128 assert_eq!(1i128, i128::deserialize(de_u128).unwrap()); // i128 to u128 assert_eq!(1u128, u128::deserialize(de_i128).unwrap()); // i128 to i128 assert_eq!(1i128, i128::deserialize(de_i128).unwrap()); } #[test] fn test_map_access_to_enum() { #[derive(PartialEq, Debug)] struct Potential(PotentialKind); #[derive(PartialEq, Debug, Deserialize)] enum PotentialKind { Airebo(Airebo), } #[derive(PartialEq, Debug, Deserialize)] struct Airebo { lj_sigma: f64, } impl<'de> Deserialize<'de> for Potential { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct PotentialVisitor; impl<'de> Visitor<'de> for PotentialVisitor { type Value = Potential; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a map") } fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { Deserialize::deserialize(MapAccessDeserializer::new(map)).map(Potential) } } deserializer.deserialize_any(PotentialVisitor) } } let expected = Potential(PotentialKind::Airebo(Airebo { lj_sigma: 14.0 })); assert_de_tokens( &expected, &[ Token::Map { len: Some(1) }, Token::Str("Airebo"), Token::Map { len: Some(1) }, Token::Str("lj_sigma"), Token::F64(14.0), Token::MapEnd, Token::MapEnd, ], ); } ================================================ FILE: test_suite/tests/ui/borrow/bad_lifetimes.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct Test<'a> { #[serde(borrow = "zzz")] s: &'a str, } fn main() {} ================================================ FILE: test_suite/tests/ui/borrow/bad_lifetimes.stderr ================================================ error: failed to parse borrowed lifetimes: "zzz" --> tests/ui/borrow/bad_lifetimes.rs:5:22 | 5 | #[serde(borrow = "zzz")] | ^^^^^ ================================================ FILE: test_suite/tests/ui/borrow/duplicate_lifetime.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct Test<'a> { #[serde(borrow = "'a + 'a")] s: &'a str, } fn main() {} ================================================ FILE: test_suite/tests/ui/borrow/duplicate_lifetime.stderr ================================================ error: duplicate borrowed lifetime `'a` --> tests/ui/borrow/duplicate_lifetime.rs:5:22 | 5 | #[serde(borrow = "'a + 'a")] | ^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/borrow/duplicate_variant.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct Str<'a>(&'a str); #[derive(Deserialize)] enum Test<'a> { #[serde(borrow)] S(#[serde(borrow)] Str<'a>), } fn main() {} ================================================ FILE: test_suite/tests/ui/borrow/duplicate_variant.stderr ================================================ error: duplicate serde attribute `borrow` --> tests/ui/borrow/duplicate_variant.rs:9:15 | 9 | S(#[serde(borrow)] Str<'a>), | ^^^^^^ ================================================ FILE: test_suite/tests/ui/borrow/empty_lifetimes.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct Test<'a> { #[serde(borrow = "")] r: &'a str, #[serde(borrow = " ")] s: &'a str, } fn main() {} ================================================ FILE: test_suite/tests/ui/borrow/empty_lifetimes.stderr ================================================ error: at least one lifetime must be borrowed --> tests/ui/borrow/empty_lifetimes.rs:5:22 | 5 | #[serde(borrow = "")] | ^^ error: at least one lifetime must be borrowed --> tests/ui/borrow/empty_lifetimes.rs:7:22 | 7 | #[serde(borrow = " ")] | ^^^^ ================================================ FILE: test_suite/tests/ui/borrow/no_lifetimes.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct Test { #[serde(borrow)] s: String, } fn main() {} ================================================ FILE: test_suite/tests/ui/borrow/no_lifetimes.stderr ================================================ error: field `s` has no lifetimes to borrow --> tests/ui/borrow/no_lifetimes.rs:5:5 | 5 | / #[serde(borrow)] 6 | | s: String, | |_____________^ ================================================ FILE: test_suite/tests/ui/borrow/struct_variant.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct Str<'a>(&'a str); #[derive(Deserialize)] enum Test<'a> { #[serde(borrow)] S { s: Str<'a> }, } fn main() {} ================================================ FILE: test_suite/tests/ui/borrow/struct_variant.stderr ================================================ error: #[serde(borrow)] may only be used on newtype variants --> tests/ui/borrow/struct_variant.rs:8:5 | 8 | / #[serde(borrow)] 9 | | S { s: Str<'a> }, | |____________________^ ================================================ FILE: test_suite/tests/ui/borrow/wrong_lifetime.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct Test<'a> { #[serde(borrow = "'b")] s: &'a str, } fn main() {} ================================================ FILE: test_suite/tests/ui/borrow/wrong_lifetime.stderr ================================================ error: field `s` does not have lifetime 'b --> tests/ui/borrow/wrong_lifetime.rs:5:5 | 5 | / #[serde(borrow = "'b")] 6 | | s: &'a str, | |______________^ ================================================ FILE: test_suite/tests/ui/conflict/adjacent-tag.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(tag = "conflict", content = "conflict")] enum E { A, B, } fn main() {} ================================================ FILE: test_suite/tests/ui/conflict/adjacent-tag.stderr ================================================ error: enum tags `conflict` for type and content conflict with each other --> tests/ui/conflict/adjacent-tag.rs:4:1 | 4 | / #[serde(tag = "conflict", content = "conflict")] 5 | | enum E { 6 | | A, 7 | | B, 8 | | } | |_^ ================================================ FILE: test_suite/tests/ui/conflict/alias-enum.rs ================================================ #![allow(non_camel_case_types)] use serde_derive::Deserialize; #[derive(Deserialize)] enum E { S1 { #[serde(alias = "a", alias = "b", alias = "c")] a: (), // Warning on "c" and "b" #[serde(alias = "c")] b: (), #[serde(skip_deserializing)] c: (), }, S2 { #[serde(alias = "b", alias = "c")] a: (), // Warning on "c" #[serde(rename = "c")] b: (), }, #[serde(rename_all = "UPPERCASE")] S3 { #[serde(alias = "B", alias = "c")] a: (), // Warning on "b" because this collides with the "B" above after // applying rename rules b: (), }, } #[derive(Deserialize)] enum E1 { #[serde(alias = "a", alias = "b", alias = "c")] a, // Warning on "c" and "b" #[serde(alias = "c")] b, #[serde(skip_deserializing)] c, } #[derive(Deserialize)] enum E2 { #[serde(alias = "b", alias = "c")] a, // Warning on "c" #[serde(rename = "c")] b, } #[derive(Deserialize)] #[serde(rename_all = "UPPERCASE")] enum E3 { #[serde(alias = "B", alias = "c")] a, // Warning on "b" because this collides with the "B" above after applying // rename rules b, } fn main() { __FAIL__; } ================================================ FILE: test_suite/tests/ui/conflict/alias-enum.stderr ================================================ error[E0425]: cannot find value `__FAIL__` in this scope --> tests/ui/conflict/alias-enum.rs:74:5 | 74 | __FAIL__; | ^^^^^^^^ not found in this scope warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:13:9 | 8 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... 13 | b: (), | ^ no value can reach this | = note: `#[warn(unreachable_patterns)]` (part of `#[warn(unused)]`) on by default warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:12:25 | 8 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... 12 | #[serde(alias = "c")] | ^^^ no value can reach this warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:24:26 | 20 | #[serde(alias = "b", alias = "c")] | --- matches all the relevant values ... 24 | #[serde(rename = "c")] | ^^^ no value can reach this warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:35:9 | 30 | #[serde(alias = "B", alias = "c")] | --- matches all the relevant values ... 35 | b: (), | ^ no value can reach this warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:46:5 | 41 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... 46 | b, | ^ no value can reach this warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:45:21 | 41 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... 45 | #[serde(alias = "c")] | ^^^ no value can reach this warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:58:22 | 54 | #[serde(alias = "b", alias = "c")] | --- matches all the relevant values ... 58 | #[serde(rename = "c")] | ^^^ no value can reach this warning: unreachable pattern --> tests/ui/conflict/alias-enum.rs:70:5 | 65 | #[serde(alias = "B", alias = "c")] | --- matches all the relevant values ... 70 | b, | ^ no value can reach this ================================================ FILE: test_suite/tests/ui/conflict/alias.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct S1 { #[serde(alias = "a", alias = "b", alias = "c")] a: (), // Warning on "c" and "b" #[serde(alias = "c")] b: (), #[serde(skip_deserializing)] c: (), } #[derive(Deserialize)] struct S2 { #[serde(alias = "b", alias = "c")] a: (), // Warning on "c" #[serde(rename = "c")] b: (), } #[derive(Deserialize)] #[serde(rename_all = "UPPERCASE")] struct S3 { #[serde(alias = "B", alias = "c")] a: (), // Warning on "b" because this collides with the "B" above after applying // rename rules b: (), } fn main() { __FAIL__; } ================================================ FILE: test_suite/tests/ui/conflict/alias.stderr ================================================ error[E0425]: cannot find value `__FAIL__` in this scope --> tests/ui/conflict/alias.rs:38:5 | 38 | __FAIL__; | ^^^^^^^^ not found in this scope warning: unreachable pattern --> tests/ui/conflict/alias.rs:10:5 | 5 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... 10 | b: (), | ^ no value can reach this | = note: `#[warn(unreachable_patterns)]` (part of `#[warn(unused)]`) on by default warning: unreachable pattern --> tests/ui/conflict/alias.rs:9:21 | 5 | #[serde(alias = "a", alias = "b", alias = "c")] | --- matches all the relevant values ... 9 | #[serde(alias = "c")] | ^^^ no value can reach this warning: unreachable pattern --> tests/ui/conflict/alias.rs:22:22 | 18 | #[serde(alias = "b", alias = "c")] | --- matches all the relevant values ... 22 | #[serde(rename = "c")] | ^^^ no value can reach this warning: unreachable pattern --> tests/ui/conflict/alias.rs:34:5 | 29 | #[serde(alias = "B", alias = "c")] | --- matches all the relevant values ... 34 | b: (), | ^ no value can reach this ================================================ FILE: test_suite/tests/ui/conflict/flatten-newtype-struct.rs ================================================ use serde_derive::Serialize; use std::collections::HashMap; #[derive(Serialize)] struct Foo(#[serde(flatten)] HashMap); fn main() {} ================================================ FILE: test_suite/tests/ui/conflict/flatten-newtype-struct.stderr ================================================ error: #[serde(flatten)] cannot be used on newtype structs --> tests/ui/conflict/flatten-newtype-struct.rs:5:12 | 5 | struct Foo(#[serde(flatten)] HashMap); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/conflict/flatten-tuple-struct.rs ================================================ use serde_derive::Serialize; use std::collections::HashMap; #[derive(Serialize)] struct Foo(u32, #[serde(flatten)] HashMap); fn main() {} ================================================ FILE: test_suite/tests/ui/conflict/flatten-tuple-struct.stderr ================================================ error: #[serde(flatten)] cannot be used on tuple structs --> tests/ui/conflict/flatten-tuple-struct.rs:5:17 | 5 | struct Foo(u32, #[serde(flatten)] HashMap); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/conflict/from-try-from.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(from = "u64", try_from = "u64")] struct S { a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/conflict/from-try-from.stderr ================================================ error: #[serde(from = "...")] and #[serde(try_from = "...")] conflict with each other --> tests/ui/conflict/from-try-from.rs:4:1 | 4 | / #[serde(from = "u64", try_from = "u64")] 5 | | struct S { 6 | | a: u8, 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/conflict/internal-tag-alias.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(tag = "conflict")] enum E { A { #[serde(alias = "conflict")] x: (), }, } fn main() {} ================================================ FILE: test_suite/tests/ui/conflict/internal-tag-alias.stderr ================================================ error: variant field name `conflict` conflicts with internal tag --> tests/ui/conflict/internal-tag-alias.rs:4:1 | 4 | / #[serde(tag = "conflict")] 5 | | enum E { 6 | | A { 7 | | #[serde(alias = "conflict")] 8 | | x: (), 9 | | }, 10 | | } | |_^ ================================================ FILE: test_suite/tests/ui/conflict/internal-tag.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(tag = "conflict")] enum E { A { #[serde(rename = "conflict")] x: (), }, } fn main() {} ================================================ FILE: test_suite/tests/ui/conflict/internal-tag.stderr ================================================ error: variant field name `conflict` conflicts with internal tag --> tests/ui/conflict/internal-tag.rs:4:1 | 4 | / #[serde(tag = "conflict")] 5 | | enum E { 6 | | A { 7 | | #[serde(rename = "conflict")] 8 | | x: (), 9 | | }, 10 | | } | |_^ ================================================ FILE: test_suite/tests/ui/default-attribute/enum.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default)] enum E { S { f: u8 }, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/enum.stderr ================================================ error: #[serde(default)] can only be used on structs --> tests/ui/default-attribute/enum.rs:4:9 | 4 | #[serde(default)] | ^^^^^^^ ================================================ FILE: test_suite/tests/ui/default-attribute/enum_path.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default = "default_e")] enum E { S { f: u8 }, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/enum_path.stderr ================================================ error: #[serde(default = "...")] can only be used on structs --> tests/ui/default-attribute/enum_path.rs:4:9 | 4 | #[serde(default = "default_e")] | ^^^^^^^^^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs ================================================ // Tests that type error points to the path in attribute use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(tag = "tag", content = "content")] enum Enum { // Newtype variants do not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), Tuple(u8, #[serde(default = "main")] i8), Struct { #[serde(default = "main")] f1: u8, f2: u8, #[serde(default = "main")] f3: i8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.stderr ================================================ error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:10:33 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... 10 | Tuple(u8, #[serde(default = "main")] i8), | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:12:27 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... 12 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_adjacently_tagged.rs:15:27 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... 15 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs ================================================ // Tests that type error points to the path in attribute use serde_derive::Deserialize; #[derive(Deserialize)] enum Enum { // Newtype variants do not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), Tuple(u8, #[serde(default = "main")] i8), Struct { #[serde(default = "main")] f1: u8, f2: u8, #[serde(default = "main")] f3: i8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_enum_externally_tagged.stderr ================================================ error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:9:33 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... 9 | Tuple(u8, #[serde(default = "main")] i8), | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:11:27 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... 11 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_externally_tagged.rs:14:27 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... 14 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs ================================================ // Tests that type error points to the path in attribute use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(tag = "tag")] enum Enum { // Newtype variants do not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), // Tuple variants are not supported in internally tagged enums Struct { #[serde(default = "main")] f1: u8, f2: u8, #[serde(default = "main")] f3: i8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_enum_internally_tagged.stderr ================================================ error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:12:27 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... 12 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_internally_tagged.rs:15:27 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... 15 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.rs ================================================ // Tests that type error points to the path in attribute use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(untagged)] enum Enum { // Newtype variants do not use the provided path, so it is forbidden here // Newtype(#[serde(default = "main")] u8), Tuple(u8, #[serde(default = "main")] i8), Struct { #[serde(default = "main")] f1: u8, f2: u8, #[serde(default = "main")] f3: i8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_enum_untagged.stderr ================================================ error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:10:33 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... 10 | Tuple(u8, #[serde(default = "main")] i8), | ^^^^^^ expected `i8`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:12:27 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... 12 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_enum_untagged.rs:15:27 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... 15 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_newtype.rs ================================================ // Tests that type error points to the path in attribute use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default = "main")] struct Newtype(#[serde(default = "main")] u8); fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_newtype.stderr ================================================ error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_newtype.rs:6:19 | 6 | #[serde(default = "main")] | ^^^^^^ expected `Newtype`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_newtype.rs:7:34 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types 6 | #[serde(default = "main")] 7 | struct Newtype(#[serde(default = "main")] u8); | ^^^^^^ expected `u8`, found `()` error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_newtype.rs:6:19 | 6 | #[serde(default = "main")] | ^^^^^^ expected `Newtype`, found `()` 7 | struct Newtype(#[serde(default = "main")] u8); | ------- expected due to this error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_newtype.rs:7:34 | 5 | #[derive(Deserialize)] | ----------- expected due to the type of this binding 6 | #[serde(default = "main")] 7 | struct Newtype(#[serde(default = "main")] u8); | ^^^^^^ expected `u8`, found `()` ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_struct.rs ================================================ // Tests that type error points to the path in attribute use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default = "main")] struct Struct { #[serde(default = "main")] f1: u8, f2: u8, #[serde(default = "main")] f3: i8, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_struct.stderr ================================================ error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_struct.rs:6:19 | 6 | #[serde(default = "main")] | ^^^^^^ expected `Struct`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_struct.rs:8:23 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `u8` | `match` arms have incompatible types ... 8 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_struct.rs:11:23 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types ... 11 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_struct.rs:6:19 | 6 | #[serde(default = "main")] | ^^^^^^ expected `Struct`, found `()` 7 | struct Struct { | ------ expected due to this error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_struct.rs:8:23 | 5 | #[derive(Deserialize)] | ----------- expected due to the type of this binding ... 8 | #[serde(default = "main")] | ^^^^^^ expected `u8`, found `()` error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_struct.rs:11:23 | 5 | #[derive(Deserialize)] | ----------- expected due to the type of this binding ... 11 | #[serde(default = "main")] | ^^^^^^ expected `i8`, found `()` ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_tuple.rs ================================================ // Tests that type error points to the path in attribute use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default = "main")] struct Tuple(u8, #[serde(default = "main")] i8); fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/incorrect_type_tuple.stderr ================================================ error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_tuple.rs:6:19 | 6 | #[serde(default = "main")] | ^^^^^^ expected `Tuple`, found `()` error[E0308]: `match` arms have incompatible types --> tests/ui/default-attribute/incorrect_type_tuple.rs:7:36 | 5 | #[derive(Deserialize)] | ----------- | | | this is found to be of type `i8` | `match` arms have incompatible types 6 | #[serde(default = "main")] 7 | struct Tuple(u8, #[serde(default = "main")] i8); | ^^^^^^ expected `i8`, found `()` error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_tuple.rs:6:19 | 6 | #[serde(default = "main")] | ^^^^^^ expected `Tuple`, found `()` 7 | struct Tuple(u8, #[serde(default = "main")] i8); | ----- expected due to this error[E0308]: mismatched types --> tests/ui/default-attribute/incorrect_type_tuple.rs:7:36 | 5 | #[derive(Deserialize)] | ----------- expected due to the type of this binding 6 | #[serde(default = "main")] 7 | struct Tuple(u8, #[serde(default = "main")] i8); | ^^^^^^ expected `i8`, found `()` ================================================ FILE: test_suite/tests/ui/default-attribute/tuple_struct.rs ================================================ 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 means 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() {} ================================================ FILE: test_suite/tests/ui/default-attribute/tuple_struct.stderr ================================================ 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); | ^^ ================================================ FILE: test_suite/tests/ui/default-attribute/tuple_struct_path.rs ================================================ use serde_derive::Deserialize; fn d() -> 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 means 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() {} ================================================ FILE: test_suite/tests/ui/default-attribute/tuple_struct_path.stderr ================================================ 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); | ^^ ================================================ FILE: test_suite/tests/ui/default-attribute/union.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default)] union Union { f: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/union.stderr ================================================ error: #[serde(default)] can only be used on structs --> tests/ui/default-attribute/union.rs:4:9 | 4 | #[serde(default)] | ^^^^^^^ error: Serde does not support derive for unions --> tests/ui/default-attribute/union.rs:4:1 | 4 | / #[serde(default)] 5 | | union Union { 6 | | f: u8, 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/default-attribute/union_path.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default = "default_u")] union Union { f: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/union_path.stderr ================================================ error: #[serde(default = "...")] can only be used on structs --> tests/ui/default-attribute/union_path.rs:4:9 | 4 | #[serde(default = "default_u")] | ^^^^^^^^^^^^^^^^^^^^^ error: Serde does not support derive for unions --> tests/ui/default-attribute/union_path.rs:4:1 | 4 | / #[serde(default = "default_u")] 5 | | union Union { 6 | | f: u8, 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/default-attribute/unit.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default)] struct Unit; fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/unit.stderr ================================================ error: #[serde(default)] can only be used on structs that have fields --> tests/ui/default-attribute/unit.rs:3:10 | 3 | #[derive(Deserialize)] | ^^^^^^^^^^^ | = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) ================================================ FILE: test_suite/tests/ui/default-attribute/unit_path.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(default = "default_u")] struct Unit; fn main() {} ================================================ FILE: test_suite/tests/ui/default-attribute/unit_path.stderr ================================================ error: #[serde(default = "...")] can only be used on structs that have fields --> tests/ui/default-attribute/unit_path.rs:4:9 | 4 | #[serde(default = "default_u")] | ^^^^^^^^^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/deprecated/deprecated_de_with.rs ================================================ #![deny(deprecated)] use serde::Deserializer; use serde_derive::Deserialize; #[derive(Deserialize)] pub struct Struct { #[serde(deserialize_with = "deprecated_with")] pub field: i32, } #[deprecated] fn deprecated_with<'de, D>(_deserializer: D) -> Result where D: Deserializer<'de>, { unimplemented!() } fn main() {} ================================================ FILE: test_suite/tests/ui/deprecated/deprecated_de_with.stderr ================================================ error: use of deprecated function `deprecated_with` --> tests/ui/deprecated/deprecated_de_with.rs:8:32 | 8 | #[serde(deserialize_with = "deprecated_with")] | ^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> tests/ui/deprecated/deprecated_de_with.rs:1:9 | 1 | #![deny(deprecated)] | ^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/deprecated/deprecated_ser_with.rs ================================================ #![deny(deprecated)] use serde::Serializer; use serde_derive::Serialize; #[derive(Serialize)] pub struct Struct { #[serde(serialize_with = "deprecated_with")] pub field: i32, } #[deprecated] fn deprecated_with(_field: &i32, _serializer: S) -> Result where S: Serializer, { unimplemented!() } fn main() {} ================================================ FILE: test_suite/tests/ui/deprecated/deprecated_ser_with.stderr ================================================ error: use of deprecated function `deprecated_with` --> tests/ui/deprecated/deprecated_ser_with.rs:8:30 | 8 | #[serde(serialize_with = "deprecated_with")] | ^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> tests/ui/deprecated/deprecated_ser_with.rs:1:9 | 1 | #![deny(deprecated)] | ^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/duplicate-attribute/rename-and-ser.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename = "x", serialize = "y")] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/duplicate-attribute/rename-and-ser.stderr ================================================ error: unknown serde field attribute `serialize` --> tests/ui/duplicate-attribute/rename-and-ser.rs:5:27 | 5 | #[serde(rename = "x", serialize = "y")] | ^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/duplicate-attribute/rename-ser-rename-ser.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename(serialize = "x"), rename(serialize = "y"))] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/duplicate-attribute/rename-ser-rename-ser.stderr ================================================ error: duplicate serde attribute `rename` --> tests/ui/duplicate-attribute/rename-ser-rename-ser.rs:5:38 | 5 | #[serde(rename(serialize = "x"), rename(serialize = "y"))] | ^^^^^^ ================================================ FILE: test_suite/tests/ui/duplicate-attribute/rename-ser-rename.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename(serialize = "x"))] #[serde(rename = "y")] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/duplicate-attribute/rename-ser-rename.stderr ================================================ error: duplicate serde attribute `rename` --> tests/ui/duplicate-attribute/rename-ser-rename.rs:6:13 | 6 | #[serde(rename = "y")] | ^^^^^^ ================================================ FILE: test_suite/tests/ui/duplicate-attribute/rename-ser-ser.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename(serialize = "x", serialize = "y"))] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/duplicate-attribute/rename-ser-ser.stderr ================================================ error: duplicate serde attribute `rename` --> tests/ui/duplicate-attribute/rename-ser-ser.rs:5:37 | 5 | #[serde(rename(serialize = "x", serialize = "y"))] | ^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/duplicate-attribute/two-rename-ser.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename(serialize = "x"))] #[serde(rename(serialize = "y"))] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/duplicate-attribute/two-rename-ser.stderr ================================================ error: duplicate serde attribute `rename` --> tests/ui/duplicate-attribute/two-rename-ser.rs:6:13 | 6 | #[serde(rename(serialize = "y"))] | ^^^^^^ ================================================ FILE: test_suite/tests/ui/duplicate-attribute/with-and-serialize-with.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(with = "w", serialize_with = "s")] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/duplicate-attribute/with-and-serialize-with.stderr ================================================ error: duplicate serde attribute `serialize_with` --> tests/ui/duplicate-attribute/with-and-serialize-with.rs:5:25 | 5 | #[serde(with = "w", serialize_with = "s")] | ^^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/enum-representation/content-no-tag.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(content = "c")] enum E { A(u8), B(String), } fn main() {} ================================================ FILE: test_suite/tests/ui/enum-representation/content-no-tag.stderr ================================================ error: #[serde(tag = "...", content = "...")] must be used together --> tests/ui/enum-representation/content-no-tag.rs:4:9 | 4 | #[serde(content = "c")] | ^^^^^^^ ================================================ FILE: test_suite/tests/ui/enum-representation/internal-tuple-variant.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(tag = "type")] enum E { Tuple(u8, u8), } fn main() {} ================================================ FILE: test_suite/tests/ui/enum-representation/internal-tuple-variant.stderr ================================================ error: #[serde(tag = "...")] cannot be used with tuple variants --> tests/ui/enum-representation/internal-tuple-variant.rs:6:5 | 6 | Tuple(u8, u8), | ^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/enum-representation/partially_tagged_wrong_order.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum E { #[serde(untagged)] A(u8), B(String), } fn main() {} ================================================ FILE: test_suite/tests/ui/enum-representation/partially_tagged_wrong_order.stderr ================================================ error: all variants with the #[serde(untagged)] attribute must be placed at the end of the enum --> tests/ui/enum-representation/partially_tagged_wrong_order.rs:6:5 | 6 | A(u8), | ^ ================================================ FILE: test_suite/tests/ui/enum-representation/untagged-and-adjacent.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(untagged)] #[serde(tag = "t", content = "c")] enum E { A(u8), B(String), } fn main() {} ================================================ FILE: test_suite/tests/ui/enum-representation/untagged-and-adjacent.stderr ================================================ error: untagged enum cannot have #[serde(tag = "...", content = "...")] --> tests/ui/enum-representation/untagged-and-adjacent.rs:4:9 | 4 | #[serde(untagged)] | ^^^^^^^^ error: untagged enum cannot have #[serde(tag = "...", content = "...")] --> tests/ui/enum-representation/untagged-and-adjacent.rs:5:9 | 5 | #[serde(tag = "t", content = "c")] | ^^^ error: untagged enum cannot have #[serde(tag = "...", content = "...")] --> tests/ui/enum-representation/untagged-and-adjacent.rs:5:20 | 5 | #[serde(tag = "t", content = "c")] | ^^^^^^^ ================================================ FILE: test_suite/tests/ui/enum-representation/untagged-and-content.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(untagged)] #[serde(content = "c")] enum E { A(u8), B(String), } fn main() {} ================================================ FILE: test_suite/tests/ui/enum-representation/untagged-and-content.stderr ================================================ error: untagged enum cannot have #[serde(content = "...")] --> tests/ui/enum-representation/untagged-and-content.rs:4:9 | 4 | #[serde(untagged)] | ^^^^^^^^ error: untagged enum cannot have #[serde(content = "...")] --> tests/ui/enum-representation/untagged-and-content.rs:5:9 | 5 | #[serde(content = "c")] | ^^^^^^^ ================================================ FILE: test_suite/tests/ui/enum-representation/untagged-and-internal.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(untagged)] #[serde(tag = "type")] enum E { A(u8), B(String), } fn main() {} ================================================ FILE: test_suite/tests/ui/enum-representation/untagged-and-internal.stderr ================================================ error: enum cannot be both untagged and internally tagged --> tests/ui/enum-representation/untagged-and-internal.rs:4:9 | 4 | #[serde(untagged)] | ^^^^^^^^ error: enum cannot be both untagged and internally tagged --> tests/ui/enum-representation/untagged-and-internal.rs:5:9 | 5 | #[serde(tag = "type")] | ^^^ ================================================ FILE: test_suite/tests/ui/enum-representation/untagged-struct.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(untagged)] struct S; fn main() {} ================================================ FILE: test_suite/tests/ui/enum-representation/untagged-struct.stderr ================================================ error: #[serde(untagged)] can only be used on enums --> tests/ui/enum-representation/untagged-struct.rs:4:9 | 4 | #[serde(untagged)] | ^^^^^^^^ ================================================ FILE: test_suite/tests/ui/expected-string/boolean.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename = true)] boolean: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/expected-string/boolean.stderr ================================================ error: expected serde rename attribute to be a string: `rename = "..."` --> tests/ui/expected-string/boolean.rs:5:22 | 5 | #[serde(rename = true)] | ^^^^ ================================================ FILE: test_suite/tests/ui/expected-string/byte_character.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename = b'a')] byte_character: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/expected-string/byte_character.stderr ================================================ error: expected serde rename attribute to be a string: `rename = "..."` --> tests/ui/expected-string/byte_character.rs:5:22 | 5 | #[serde(rename = b'a')] | ^^^^ ================================================ FILE: test_suite/tests/ui/expected-string/byte_string.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename = b"byte string")] byte_string: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/expected-string/byte_string.stderr ================================================ error: expected serde rename attribute to be a string: `rename = "..."` --> tests/ui/expected-string/byte_string.rs:5:22 | 5 | #[serde(rename = b"byte string")] | ^^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/expected-string/character.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename = 'a')] character: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/expected-string/character.stderr ================================================ error: expected serde rename attribute to be a string: `rename = "..."` --> tests/ui/expected-string/character.rs:5:22 | 5 | #[serde(rename = 'a')] | ^^^ ================================================ FILE: test_suite/tests/ui/expected-string/float.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename = 3.14)] float: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/expected-string/float.stderr ================================================ error: expected serde rename attribute to be a string: `rename = "..."` --> tests/ui/expected-string/float.rs:5:22 | 5 | #[serde(rename = 3.14)] | ^^^^ ================================================ FILE: test_suite/tests/ui/expected-string/integer.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename = 100)] integer: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/expected-string/integer.stderr ================================================ error: expected serde rename attribute to be a string: `rename = "..."` --> tests/ui/expected-string/integer.rs:5:22 | 5 | #[serde(rename = 100)] | ^^^ ================================================ FILE: test_suite/tests/ui/identifier/both.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(field_identifier, variant_identifier)] enum F { A, B, } fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/both.stderr ================================================ error: #[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set --> tests/ui/identifier/both.rs:4:9 | 4 | #[serde(field_identifier, variant_identifier)] | ^^^^^^^^^^^^^^^^ error: #[serde(field_identifier)] and #[serde(variant_identifier)] cannot both be set --> tests/ui/identifier/both.rs:4:27 | 4 | #[serde(field_identifier, variant_identifier)] | ^^^^^^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/identifier/field_struct.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(field_identifier)] struct S; fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/field_struct.stderr ================================================ error: #[serde(field_identifier)] can only be used on an enum --> tests/ui/identifier/field_struct.rs:5:1 | 5 | struct S; | ^^^^^^ ================================================ FILE: test_suite/tests/ui/identifier/field_tuple.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(field_identifier)] enum F { A, B(u8, u8), } fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/field_tuple.stderr ================================================ error: #[serde(field_identifier)] may only contain unit variants --> tests/ui/identifier/field_tuple.rs:7:5 | 7 | B(u8, u8), | ^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/identifier/newtype_not_last.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(field_identifier)] enum F { A, Other(String), B, } fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/newtype_not_last.stderr ================================================ error: `Other` must be the last variant --> tests/ui/identifier/newtype_not_last.rs:7:5 | 7 | Other(String), | ^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/identifier/not_unit.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(field_identifier)] enum F { A, #[serde(other)] Other(u8, u8), } fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/not_unit.stderr ================================================ error: #[serde(other)] must be on a unit variant --> tests/ui/identifier/not_unit.rs:7:5 | 7 | / #[serde(other)] 8 | | Other(u8, u8), | |_________________^ ================================================ FILE: test_suite/tests/ui/identifier/other_not_last.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(field_identifier)] enum F { A, #[serde(other)] Other, B, } fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/other_not_last.stderr ================================================ error: #[serde(other)] must be on the last variant --> tests/ui/identifier/other_not_last.rs:7:5 | 7 | / #[serde(other)] 8 | | Other, | |_________^ ================================================ FILE: test_suite/tests/ui/identifier/other_untagged.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(untagged)] enum F { #[serde(other)] Other, } fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/other_untagged.stderr ================================================ error: #[serde(other)] cannot appear on untagged enum --> tests/ui/identifier/other_untagged.rs:6:5 | 6 | / #[serde(other)] 7 | | Other, | |_________^ ================================================ FILE: test_suite/tests/ui/identifier/other_variant.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(variant_identifier)] enum F { #[serde(other)] Other, } fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/other_variant.stderr ================================================ error: #[serde(other)] may not be used on a variant identifier --> tests/ui/identifier/other_variant.rs:6:5 | 6 | / #[serde(other)] 7 | | Other, | |_________^ ================================================ FILE: test_suite/tests/ui/identifier/variant_struct.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(variant_identifier)] struct S; fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/variant_struct.stderr ================================================ error: #[serde(variant_identifier)] can only be used on an enum --> tests/ui/identifier/variant_struct.rs:5:1 | 5 | struct S; | ^^^^^^ ================================================ FILE: test_suite/tests/ui/identifier/variant_tuple.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(variant_identifier)] enum F { A, B(u8, u8), } fn main() {} ================================================ FILE: test_suite/tests/ui/identifier/variant_tuple.stderr ================================================ error: #[serde(variant_identifier)] may only contain unit variants --> tests/ui/identifier/variant_tuple.rs:7:5 | 7 | B(u8, u8), | ^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/malformed/bound.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(bound(unknown))] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/malformed/bound.stderr ================================================ error: malformed bound attribute, expected `bound(serialize = ..., deserialize = ...)` --> tests/ui/malformed/bound.rs:5:19 | 5 | #[serde(bound(unknown))] | ^^^^^^^ ================================================ FILE: test_suite/tests/ui/malformed/cut_off.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(rename =)] struct S; fn main() {} ================================================ FILE: test_suite/tests/ui/malformed/cut_off.stderr ================================================ error: unexpected end of input, expected an expression --> tests/ui/malformed/cut_off.rs:4:17 | 4 | #[serde(rename =)] | ^ ================================================ FILE: test_suite/tests/ui/malformed/not_list.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde] #[serde = "?"] struct S; fn main() {} ================================================ FILE: test_suite/tests/ui/malformed/not_list.stderr ================================================ error: expected attribute arguments in parentheses: #[serde(...)] --> tests/ui/malformed/not_list.rs:4:3 | 4 | #[serde] | ^^^^^ error: expected parentheses: #[serde(...)] --> tests/ui/malformed/not_list.rs:5:9 | 5 | #[serde = "?"] | ^ ================================================ FILE: test_suite/tests/ui/malformed/rename.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(rename(unknown))] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/malformed/rename.stderr ================================================ error: malformed rename attribute, expected `rename(serialize = ..., deserialize = ...)` --> tests/ui/malformed/rename.rs:5:20 | 5 | #[serde(rename(unknown))] | ^^^^^^^ ================================================ FILE: test_suite/tests/ui/malformed/str_suffix.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(bound = ""huh)] pub struct Struct { #[serde(rename = ""what)] pub field: i32, } fn main() {} ================================================ FILE: test_suite/tests/ui/malformed/str_suffix.stderr ================================================ error: unexpected suffix `huh` on string literal --> tests/ui/malformed/str_suffix.rs:4:17 | 4 | #[serde(bound = ""huh)] | ^^^^^ error: unexpected suffix `what` on string literal --> tests/ui/malformed/str_suffix.rs:6:22 | 6 | #[serde(rename = ""what)] | ^^^^^^ ================================================ FILE: test_suite/tests/ui/malformed/trailing_expr.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(skip_serializing_if, x.is_empty())] x: Vec<()>, } fn main() {} ================================================ FILE: test_suite/tests/ui/malformed/trailing_expr.stderr ================================================ error: expected `=` --> tests/ui/malformed/trailing_expr.rs:5:32 | 5 | #[serde(skip_serializing_if, x.is_empty())] | ^ ================================================ FILE: test_suite/tests/ui/precondition/deserialize_de_lifetime.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct S<'de> { s: &'de str, } fn main() {} ================================================ FILE: test_suite/tests/ui/precondition/deserialize_de_lifetime.stderr ================================================ error: cannot deserialize when there is a lifetime parameter called 'de --> tests/ui/precondition/deserialize_de_lifetime.rs:4:10 | 4 | struct S<'de> { | ^^^ ================================================ FILE: test_suite/tests/ui/precondition/deserialize_dst.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] struct S { string: String, slice: [u8], } fn main() {} ================================================ FILE: test_suite/tests/ui/precondition/deserialize_dst.stderr ================================================ error: cannot deserialize a dynamically sized struct --> tests/ui/precondition/deserialize_dst.rs:4:1 | 4 | / struct S { 5 | | string: String, 6 | | slice: [u8], 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/precondition/serialize_field_identifier.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(field_identifier)] enum F { A, B, } fn main() {} ================================================ FILE: test_suite/tests/ui/precondition/serialize_field_identifier.stderr ================================================ error: field identifiers cannot be serialized --> tests/ui/precondition/serialize_field_identifier.rs:4:1 | 4 | / #[serde(field_identifier)] 5 | | enum F { 6 | | A, 7 | | B, 8 | | } | |_^ ================================================ FILE: test_suite/tests/ui/precondition/serialize_variant_identifier.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(variant_identifier)] enum F { A, B, } fn main() {} ================================================ FILE: test_suite/tests/ui/precondition/serialize_variant_identifier.stderr ================================================ error: variant identifiers cannot be serialized --> tests/ui/precondition/serialize_variant_identifier.rs:4:1 | 4 | / #[serde(variant_identifier)] 5 | | enum F { 6 | | A, 7 | | B, 8 | | } | |_^ ================================================ FILE: test_suite/tests/ui/remote/bad_getter.rs ================================================ use serde_derive::Serialize; mod remote { pub struct S { a: u8, } } #[derive(Serialize)] #[serde(remote = "remote::S")] struct S { #[serde(getter = "~~~")] a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/bad_getter.stderr ================================================ error: failed to parse path: "~~~" --> tests/ui/remote/bad_getter.rs:12:22 | 12 | #[serde(getter = "~~~")] | ^^^^^ ================================================ FILE: test_suite/tests/ui/remote/bad_remote.rs ================================================ use serde_derive::Serialize; mod remote { pub struct S { a: u8, } } #[derive(Serialize)] #[serde(remote = "~~~")] struct S { a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/bad_remote.stderr ================================================ error: failed to parse path: "~~~" --> tests/ui/remote/bad_remote.rs:10:18 | 10 | #[serde(remote = "~~~")] | ^^^^^ ================================================ FILE: test_suite/tests/ui/remote/double_generic.rs ================================================ use serde_derive::{Deserialize, Serialize}; mod remote { pub struct Struct { pub t: T, pub u: U, } } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructGeneric")] struct StructDef { t: u8, u: U, } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/double_generic.stderr ================================================ error: remove generic parameters from this path --> tests/ui/remote/double_generic.rs:11:18 | 11 | #[serde(remote = "remote::StructGeneric")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/remote/enum_getter.rs ================================================ use serde_derive::Serialize; mod remote { pub enum E { A { a: u8 }, } } #[derive(Serialize)] #[serde(remote = "remote::E")] pub enum E { A { #[serde(getter = "get_a")] a: u8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/enum_getter.stderr ================================================ error: #[serde(getter = "...")] is not allowed in an enum --> tests/ui/remote/enum_getter.rs:10:1 | 10 | / #[serde(remote = "remote::E")] 11 | | pub enum E { 12 | | A { 13 | | #[serde(getter = "get_a")] 14 | | a: u8, 15 | | }, 16 | | } | |_^ ================================================ FILE: test_suite/tests/ui/remote/missing_field.rs ================================================ use serde_derive::{Deserialize, Serialize}; mod remote { pub struct S { pub a: u8, pub b: u8, } } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::S")] struct S { a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/missing_field.stderr ================================================ error[E0063]: missing field `b` in initializer of `remote::S` --> tests/ui/remote/missing_field.rs:11:18 | 11 | #[serde(remote = "remote::S")] | ^^^^^^^^^^^ missing `b` ================================================ FILE: test_suite/tests/ui/remote/nonremote_getter.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde(getter = "S::get")] a: u8, } impl S { fn get(&self) -> u8 { self.a } } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/nonremote_getter.stderr ================================================ error: #[serde(getter = "...")] can only be used in structs that have #[serde(remote = "...")] --> tests/ui/remote/nonremote_getter.rs:4:1 | 4 | / struct S { 5 | | #[serde(getter = "S::get")] 6 | | a: u8, 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/remote/unknown_field.rs ================================================ use serde_derive::{Deserialize, Serialize}; mod remote { pub struct S { pub a: u8, } } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::S")] struct S { b: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/unknown_field.stderr ================================================ error[E0609]: no field `b` on type `&remote::S` --> tests/ui/remote/unknown_field.rs:12:5 | 12 | b: u8, | ^ unknown field | help: a field with a similar name exists | 12 - b: u8, 12 + a: u8, | error[E0560]: struct `remote::S` has no field named `b` --> tests/ui/remote/unknown_field.rs:12:5 | 12 | b: u8, | ^ `remote::S` does not have this field | = note: all struct fields are already assigned ================================================ FILE: test_suite/tests/ui/remote/wrong_de.rs ================================================ use serde_derive::Deserialize; mod remote { pub struct S(pub u16); } #[derive(Deserialize)] #[serde(remote = "remote::S")] struct S(u8); fn main() {} ================================================ FILE: test_suite/tests/ui/remote/wrong_de.stderr ================================================ error[E0308]: mismatched types --> tests/ui/remote/wrong_de.rs:7:10 | 7 | #[derive(Deserialize)] | ^^^^^^^^^^^ expected `u16`, found `u8` 8 | #[serde(remote = "remote::S")] | ----------- arguments to this struct are incorrect | note: tuple struct defined here --> tests/ui/remote/wrong_de.rs:4:16 | 4 | pub struct S(pub u16); | ^ = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) ================================================ FILE: test_suite/tests/ui/remote/wrong_getter.rs ================================================ use serde_derive::Serialize; mod remote { pub struct S { a: u8, } impl S { pub fn get(&self) -> u16 { self.a as u16 } } } #[derive(Serialize)] #[serde(remote = "remote::S")] struct S { #[serde(getter = "remote::S::get")] a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/wrong_getter.stderr ================================================ error[E0308]: mismatched types --> tests/ui/remote/wrong_getter.rs:15:10 | 15 | #[derive(Serialize)] | ^^^^^^^^^ | | | expected `&u8`, found `&u16` | arguments to this function are incorrect | = note: expected reference `&u8` found reference `&u16` note: function defined here --> $WORKSPACE/serde/src/private/ser.rs | | pub fn constrain(t: &T) -> &T { | ^^^^^^^^^ = note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info) ================================================ FILE: test_suite/tests/ui/remote/wrong_ser.rs ================================================ use serde_derive::Serialize; mod remote { pub struct S { pub a: u16, } } #[derive(Serialize)] #[serde(remote = "remote::S")] struct S { a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/remote/wrong_ser.stderr ================================================ error[E0308]: mismatched types --> tests/ui/remote/wrong_ser.rs:9:10 | 9 | #[derive(Serialize)] | ^^^^^^^^^ | | | expected `&u8`, found `&u16` | arguments to this function are incorrect | = note: expected reference `&u8` found reference `&u16` note: function defined here --> $WORKSPACE/serde/src/private/ser.rs | | pub fn constrain(t: &T) -> &T { | ^^^^^^^^^ = note: this error originates in the derive macro `Serialize` (in Nightly builds, run with -Z macro-backtrace for more info) ================================================ FILE: test_suite/tests/ui/rename/container_unknown_rename_rule.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(rename_all = "abc")] struct S { name: u8, long_name: u8, very_long_name: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/rename/container_unknown_rename_rule.stderr ================================================ error: unknown rename rule `rename_all = "abc"`, expected one of "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE", "kebab-case", "SCREAMING-KEBAB-CASE" --> tests/ui/rename/container_unknown_rename_rule.rs:4:22 | 4 | #[serde(rename_all = "abc")] | ^^^^^ ================================================ FILE: test_suite/tests/ui/rename/variant_unknown_rename_rule.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum S { #[serde(rename_all = "abc")] V { name: u8, long_name: u8, very_long_name: u8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/rename/variant_unknown_rename_rule.stderr ================================================ error: unknown rename rule `rename_all = "abc"`, expected one of "lowercase", "UPPERCASE", "PascalCase", "camelCase", "snake_case", "SCREAMING_SNAKE_CASE", "kebab-case", "SCREAMING-KEBAB-CASE" --> tests/ui/rename/variant_unknown_rename_rule.rs:5:26 | 5 | #[serde(rename_all = "abc")] | ^^^^^ ================================================ FILE: test_suite/tests/ui/struct-representation/internally-tagged-tuple.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(tag = "type")] struct S(u8, u8); fn main() {} ================================================ FILE: test_suite/tests/ui/struct-representation/internally-tagged-tuple.stderr ================================================ error: #[serde(tag = "...")] can only be used on enums and structs with named fields --> tests/ui/struct-representation/internally-tagged-tuple.rs:4:9 | 4 | #[serde(tag = "type")] | ^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/struct-representation/internally-tagged-unit.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(tag = "type")] struct U; fn main() {} ================================================ FILE: test_suite/tests/ui/struct-representation/internally-tagged-unit.stderr ================================================ error: #[serde(tag = "...")] can only be used on enums and structs with named fields --> tests/ui/struct-representation/internally-tagged-unit.rs:4:9 | 4 | #[serde(tag = "type")] | ^^^^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/transparent/at_most_one.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(transparent)] struct S { a: u8, b: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/transparent/at_most_one.stderr ================================================ error: #[serde(transparent)] requires struct to have at most one transparent field --> tests/ui/transparent/at_most_one.rs:4:1 | 4 | / #[serde(transparent)] 5 | | struct S { 6 | | a: u8, 7 | | b: u8, 8 | | } | |_^ ================================================ FILE: test_suite/tests/ui/transparent/de_at_least_one.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(transparent)] struct S { #[serde(skip)] a: u8, #[serde(default)] b: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/transparent/de_at_least_one.stderr ================================================ error: #[serde(transparent)] requires at least one field that is neither skipped nor has a default --> tests/ui/transparent/de_at_least_one.rs:4:1 | 4 | / #[serde(transparent)] 5 | | struct S { 6 | | #[serde(skip)] 7 | | a: u8, 8 | | #[serde(default)] 9 | | b: u8, 10 | | } | |_^ ================================================ FILE: test_suite/tests/ui/transparent/enum.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(transparent)] enum E {} fn main() {} ================================================ FILE: test_suite/tests/ui/transparent/enum.stderr ================================================ error: #[serde(transparent)] is not allowed on an enum --> tests/ui/transparent/enum.rs:4:1 | 4 | / #[serde(transparent)] 5 | | enum E {} | |_________^ ================================================ FILE: test_suite/tests/ui/transparent/ser_at_least_one.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(transparent)] struct S { #[serde(skip)] a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/transparent/ser_at_least_one.stderr ================================================ error: #[serde(transparent)] requires at least one field that is not skipped --> tests/ui/transparent/ser_at_least_one.rs:4:1 | 4 | / #[serde(transparent)] 5 | | struct S { 6 | | #[serde(skip)] 7 | | a: u8, 8 | | } | |_^ ================================================ FILE: test_suite/tests/ui/transparent/unit_struct.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(transparent)] struct S; fn main() {} ================================================ FILE: test_suite/tests/ui/transparent/unit_struct.stderr ================================================ error: #[serde(transparent)] is not allowed on a unit struct --> tests/ui/transparent/unit_struct.rs:4:1 | 4 | / #[serde(transparent)] 5 | | struct S; | |_________^ ================================================ FILE: test_suite/tests/ui/transparent/with_from.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(transparent, from = "u64")] struct S { a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/transparent/with_from.stderr ================================================ error: #[serde(transparent)] is not allowed with #[serde(from = "...")] --> tests/ui/transparent/with_from.rs:4:1 | 4 | / #[serde(transparent, from = "u64")] 5 | | struct S { 6 | | a: u8, 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/transparent/with_into.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(transparent, into = "u64")] struct S { a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/transparent/with_into.stderr ================================================ error: #[serde(transparent)] is not allowed with #[serde(into = "...")] --> tests/ui/transparent/with_into.rs:4:1 | 4 | / #[serde(transparent, into = "u64")] 5 | | struct S { 6 | | a: u8, 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/transparent/with_try_from.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(transparent, try_from = "u64")] struct S { a: u8, } fn main() {} ================================================ FILE: test_suite/tests/ui/transparent/with_try_from.stderr ================================================ error: #[serde(transparent)] is not allowed with #[serde(try_from = "...")] --> tests/ui/transparent/with_try_from.rs:4:1 | 4 | / #[serde(transparent, try_from = "u64")] 5 | | struct S { 6 | | a: u8, 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/type-attribute/from.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] #[serde(from = "Option tests/ui/type-attribute/from.rs:4:16 | 4 | #[serde(from = "Option tests/ui/type-attribute/into.rs:4:16 | 4 | #[serde(into = "Option tests/ui/type-attribute/try_from.rs:4:20 | 4 | #[serde(try_from = "Option tests/ui/unexpected-literal/container.rs:4:9 | 4 | #[serde("literal")] | ^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/unexpected-literal/field.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct S { #[serde("literal")] x: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/unexpected-literal/field.stderr ================================================ error: unexpected literal in nested attribute, expected ident --> tests/ui/unexpected-literal/field.rs:5:13 | 5 | #[serde("literal")] | ^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/unexpected-literal/variant.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum E { #[serde("literal")] V, } fn main() {} ================================================ FILE: test_suite/tests/ui/unexpected-literal/variant.stderr ================================================ error: unexpected literal in nested attribute, expected ident --> tests/ui/unexpected-literal/variant.rs:5:13 | 5 | #[serde("literal")] | ^^^^^^^^^ ================================================ FILE: test_suite/tests/ui/unimplemented/required_by_dependency.rs ================================================ struct MyStruct; fn main() { serde_test::assert_ser_tokens(&MyStruct, &[]); serde_test::assert_de_tokens(&MyStruct, &[]); } ================================================ FILE: test_suite/tests/ui/unimplemented/required_by_dependency.stderr ================================================ error[E0277]: the trait bound `MyStruct: serde::Serialize` is not satisfied --> tests/ui/unimplemented/required_by_dependency.rs:4:35 | 4 | serde_test::assert_ser_tokens(&MyStruct, &[]); | ----------------------------- ^^^^^^^^^ unsatisfied trait bound | | | required by a bound introduced by this call | help: the trait `serde_core::ser::Serialize` is not implemented for `MyStruct` --> tests/ui/unimplemented/required_by_dependency.rs:1:1 | 1 | struct MyStruct; | ^^^^^^^^^^^^^^^ = note: for local types consider adding `#[derive(serde::Serialize)]` to your `MyStruct` type = note: for types from other crates check whether the crate offers a `serde` feature flag = help: the following other types implement trait `serde_core::ser::Serialize`: &'a T &'a mut T () (T,) (T0, T1) (T0, T1, T2) (T0, T1, T2, T3) (T0, T1, T2, T3, T4) and $N others note: required by a bound in `assert_ser_tokens` --> $CARGO/serde_test-$VERSION/src/assert.rs | | pub fn assert_ser_tokens(value: &T, tokens: &[Token]) | ----------------- required by a bound in this function | where | T: ?Sized + Serialize, | ^^^^^^^^^ required by this bound in `assert_ser_tokens` error[E0277]: the trait bound `MyStruct: serde::Deserialize<'de>` is not satisfied --> tests/ui/unimplemented/required_by_dependency.rs:5:34 | 5 | serde_test::assert_de_tokens(&MyStruct, &[]); | ---------------------------- ^^^^^^^^^ unsatisfied trait bound | | | required by a bound introduced by this call | help: the trait `serde_core::de::Deserialize<'_>` is not implemented for `MyStruct` --> tests/ui/unimplemented/required_by_dependency.rs:1:1 | 1 | struct MyStruct; | ^^^^^^^^^^^^^^^ = note: for local types consider adding `#[derive(serde::Deserialize)]` to your `MyStruct` type = note: for types from other crates check whether the crate offers a `serde` feature flag = help: the following other types implement trait `serde_core::de::Deserialize<'de>`: &'a Path &'a [u8] &'a str () (T,) (T0, T1) (T0, T1, T2) (T0, T1, T2, T3) and $N others note: required by a bound in `assert_de_tokens` --> $CARGO/serde_test-$VERSION/src/assert.rs | | pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token]) | ---------------- required by a bound in this function | where | T: Deserialize<'de> + PartialEq + Debug, | ^^^^^^^^^^^^^^^^ required by this bound in `assert_de_tokens` error[E0277]: can't compare `MyStruct` with `MyStruct` --> tests/ui/unimplemented/required_by_dependency.rs:5:34 | 5 | serde_test::assert_de_tokens(&MyStruct, &[]); | ---------------------------- ^^^^^^^^^ no implementation for `MyStruct == MyStruct` | | | required by a bound introduced by this call | = help: the trait `PartialEq` is not implemented for `MyStruct` note: required by a bound in `assert_de_tokens` --> $CARGO/serde_test-$VERSION/src/assert.rs | | pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token]) | ---------------- required by a bound in this function | where | T: Deserialize<'de> + PartialEq + Debug, | ^^^^^^^^^ required by this bound in `assert_de_tokens` help: consider annotating `MyStruct` with `#[derive(PartialEq)]` | 1 + #[derive(PartialEq)] 2 | struct MyStruct; | error[E0277]: `MyStruct` doesn't implement `Debug` --> tests/ui/unimplemented/required_by_dependency.rs:5:34 | 5 | serde_test::assert_de_tokens(&MyStruct, &[]); | ---------------------------- ^^^^^^^^^ the trait `Debug` is not implemented for `MyStruct` | | | required by a bound introduced by this call | = note: add `#[derive(Debug)]` to `MyStruct` or manually `impl Debug for MyStruct` note: required by a bound in `assert_de_tokens` --> $CARGO/serde_test-$VERSION/src/assert.rs | | pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token]) | ---------------- required by a bound in this function | where | T: Deserialize<'de> + PartialEq + Debug, | ^^^^^ required by this bound in `assert_de_tokens` help: consider annotating `MyStruct` with `#[derive(Debug)]` | 1 + #[derive(Debug)] 2 | struct MyStruct; | ================================================ FILE: test_suite/tests/ui/unimplemented/required_locally.rs ================================================ use serde::de::Deserialize; use serde::ser::Serialize; fn to_string(_: &T) -> String where T: Serialize, { unimplemented!() } fn from_str<'de, T>(_: &'de str) -> T where T: Deserialize<'de>, { unimplemented!() } struct MyStruct; fn main() { to_string(&MyStruct); let _: MyStruct = from_str(""); } ================================================ FILE: test_suite/tests/ui/unimplemented/required_locally.stderr ================================================ error[E0277]: the trait bound `MyStruct: serde::Serialize` is not satisfied --> tests/ui/unimplemented/required_locally.rs:21:15 | 21 | to_string(&MyStruct); | --------- ^^^^^^^^^ unsatisfied trait bound | | | required by a bound introduced by this call | help: the trait `Serialize` is not implemented for `MyStruct` --> tests/ui/unimplemented/required_locally.rs:18:1 | 18 | struct MyStruct; | ^^^^^^^^^^^^^^^ = note: for local types consider adding `#[derive(serde::Serialize)]` to your `MyStruct` type = note: for types from other crates check whether the crate offers a `serde` feature flag = help: the following other types implement trait `Serialize`: &'a T &'a mut T () (T,) (T0, T1) (T0, T1, T2) (T0, T1, T2, T3) (T0, T1, T2, T3, T4) and $N others note: required by a bound in `to_string` --> tests/ui/unimplemented/required_locally.rs:6:8 | 4 | fn to_string(_: &T) -> String | --------- required by a bound in this function 5 | where 6 | T: Serialize, | ^^^^^^^^^ required by this bound in `to_string` error[E0277]: the trait bound `MyStruct: serde::Deserialize<'de>` is not satisfied --> tests/ui/unimplemented/required_locally.rs:22:23 | 22 | let _: MyStruct = from_str(""); | ^^^^^^^^^^^^ unsatisfied trait bound | help: the trait `Deserialize<'_>` is not implemented for `MyStruct` --> tests/ui/unimplemented/required_locally.rs:18:1 | 18 | struct MyStruct; | ^^^^^^^^^^^^^^^ = note: for local types consider adding `#[derive(serde::Deserialize)]` to your `MyStruct` type = note: for types from other crates check whether the crate offers a `serde` feature flag = help: the following other types implement trait `Deserialize<'de>`: &'a Path &'a [u8] &'a str () (T,) (T0, T1) (T0, T1, T2) (T0, T1, T2, T3) and $N others note: required by a bound in `from_str` --> tests/ui/unimplemented/required_locally.rs:13:8 | 11 | fn from_str<'de, T>(_: &'de str) -> T | -------- required by a bound in this function 12 | where 13 | T: Deserialize<'de>, | ^^^^^^^^^^^^^^^^ required by this bound in `from_str` ================================================ FILE: test_suite/tests/ui/unknown-attribute/container.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] #[serde(abc = "xyz")] struct A { x: u32, } fn main() {} ================================================ FILE: test_suite/tests/ui/unknown-attribute/container.stderr ================================================ error: unknown serde container attribute `abc` --> tests/ui/unknown-attribute/container.rs:4:9 | 4 | #[serde(abc = "xyz")] | ^^^ ================================================ FILE: test_suite/tests/ui/unknown-attribute/field.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] struct C { #[serde(abc = "xyz")] x: u32, } fn main() {} ================================================ FILE: test_suite/tests/ui/unknown-attribute/field.stderr ================================================ error: unknown serde field attribute `abc` --> tests/ui/unknown-attribute/field.rs:5:13 | 5 | #[serde(abc = "xyz")] | ^^^ ================================================ FILE: test_suite/tests/ui/unknown-attribute/variant.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum E { #[serde(abc = "xyz")] V, } fn main() {} ================================================ FILE: test_suite/tests/ui/unknown-attribute/variant.stderr ================================================ error: unknown serde variant attribute `abc` --> tests/ui/unknown-attribute/variant.rs:5:13 | 5 | #[serde(abc = "xyz")] | ^^^ ================================================ FILE: test_suite/tests/ui/unsupported/union_de.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] union Union { x: u8, y: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/unsupported/union_de.stderr ================================================ error: Serde does not support derive for unions --> tests/ui/unsupported/union_de.rs:4:1 | 4 | / union Union { 5 | | x: u8, 6 | | y: (), 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/unsupported/union_ser.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] union Union { x: u8, y: (), } fn main() {} ================================================ FILE: test_suite/tests/ui/unsupported/union_ser.stderr ================================================ error: Serde does not support derive for unions --> tests/ui/unsupported/union_ser.rs:4:1 | 4 | / union Union { 5 | | x: u8, 6 | | y: (), 7 | | } | |_^ ================================================ FILE: test_suite/tests/ui/with/incorrect_type.rs ================================================ use serde_derive::{Deserialize, Serialize}; mod w { use serde::{Deserializer, Serializer}; pub fn deserialize<'de, D: Deserializer<'de>>(_: D) -> Result<(), D::Error> { unimplemented!() } pub fn serialize(_: S) -> Result { unimplemented!() } } #[derive(Serialize, Deserialize)] struct W(#[serde(with = "w")] u8, u8); #[derive(Serialize, Deserialize)] struct S(#[serde(serialize_with = "w::serialize")] u8, u8); #[derive(Serialize, Deserialize)] struct D(#[serde(deserialize_with = "w::deserialize")] u8, u8); fn main() {} ================================================ FILE: test_suite/tests/ui/with/incorrect_type.stderr ================================================ error[E0277]: the trait bound `&u8: serde::Serializer` is not satisfied --> tests/ui/with/incorrect_type.rs:14:10 | 14 | #[derive(Serialize, Deserialize)] | ^^^^^^^^^ the trait `Serializer` is not implemented for `&u8` 15 | struct W(#[serde(with = "w")] u8, u8); | --- required by a bound introduced by this call | help: the trait `Serializer` is implemented for `&mut Formatter<'a>` --> $WORKSPACE/serde_core/src/ser/fmt.rs | | impl<'a> Serializer for &mut fmt::Formatter<'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `w::serialize` --> tests/ui/with/incorrect_type.rs:9:28 | 9 | pub fn serialize(_: S) -> Result { | ^^^^^^^^^^ required by this bound in `serialize` error[E0061]: this function takes 1 argument but 2 arguments were supplied --> tests/ui/with/incorrect_type.rs:15:25 | 14 | #[derive(Serialize, Deserialize)] | --------- unexpected argument #2 of type `__S` 15 | struct W(#[serde(with = "w")] u8, u8); | ^^^ | note: function defined here --> tests/ui/with/incorrect_type.rs:9:12 | 9 | pub fn serialize(_: S) -> Result { | ^^^^^^^^^ error[E0277]: the trait bound `&u8: serde::Serializer` is not satisfied --> tests/ui/with/incorrect_type.rs:15:25 | 15 | struct W(#[serde(with = "w")] u8, u8); | ^^^ the trait `Serializer` is not implemented for `&u8` | help: the trait `Serializer` is implemented for `&mut Formatter<'a>` --> $WORKSPACE/serde_core/src/ser/fmt.rs | | impl<'a> Serializer for &mut fmt::Formatter<'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: `?` operator has incompatible types --> tests/ui/with/incorrect_type.rs:15:25 | 15 | struct W(#[serde(with = "w")] u8, u8); | ^^^ expected `u8`, found `()` | = note: `?` operator cannot convert from `()` to `u8` error[E0277]: the trait bound `&u8: serde::Serializer` is not satisfied --> tests/ui/with/incorrect_type.rs:17:10 | 17 | #[derive(Serialize, Deserialize)] | ^^^^^^^^^ the trait `Serializer` is not implemented for `&u8` 18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8); | -------------- required by a bound introduced by this call | help: the trait `Serializer` is implemented for `&mut Formatter<'a>` --> $WORKSPACE/serde_core/src/ser/fmt.rs | | impl<'a> Serializer for &mut fmt::Formatter<'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `w::serialize` --> tests/ui/with/incorrect_type.rs:9:28 | 9 | pub fn serialize(_: S) -> Result { | ^^^^^^^^^^ required by this bound in `serialize` error[E0061]: this function takes 1 argument but 2 arguments were supplied --> tests/ui/with/incorrect_type.rs:18:35 | 17 | #[derive(Serialize, Deserialize)] | --------- unexpected argument #2 of type `__S` 18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8); | ^^^^^^^^^^^^^^ | note: function defined here --> tests/ui/with/incorrect_type.rs:9:12 | 9 | pub fn serialize(_: S) -> Result { | ^^^^^^^^^ error[E0277]: the trait bound `&u8: serde::Serializer` is not satisfied --> tests/ui/with/incorrect_type.rs:18:35 | 18 | struct S(#[serde(serialize_with = "w::serialize")] u8, u8); | ^^^^^^^^^^^^^^ the trait `Serializer` is not implemented for `&u8` | help: the trait `Serializer` is implemented for `&mut Formatter<'a>` --> $WORKSPACE/serde_core/src/ser/fmt.rs | | impl<'a> Serializer for &mut fmt::Formatter<'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: `?` operator has incompatible types --> tests/ui/with/incorrect_type.rs:21:37 | 21 | struct D(#[serde(deserialize_with = "w::deserialize")] u8, u8); | ^^^^^^^^^^^^^^^^ expected `u8`, found `()` | = note: `?` operator cannot convert from `()` to `u8` ================================================ FILE: test_suite/tests/ui/with-variant/skip_de_newtype_field.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] enum Enum { #[serde(deserialize_with = "deserialize_some_newtype_variant")] Newtype(#[serde(skip_deserializing)] String), } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_de_newtype_field.stderr ================================================ error: variant `Newtype` cannot have both #[serde(deserialize_with)] and a field #0 marked with #[serde(skip_deserializing)] --> tests/ui/with-variant/skip_de_newtype_field.rs:5:5 | 5 | / #[serde(deserialize_with = "deserialize_some_newtype_variant")] 6 | | Newtype(#[serde(skip_deserializing)] String), | |________________________________________________^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_de_struct_field.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] enum Enum { #[serde(deserialize_with = "deserialize_some_other_variant")] Struct { #[serde(skip_deserializing)] f1: String, f2: u8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_de_struct_field.stderr ================================================ error: variant `Struct` cannot have both #[serde(deserialize_with)] and a field `f1` marked with #[serde(skip_deserializing)] --> tests/ui/with-variant/skip_de_struct_field.rs:5:5 | 5 | / #[serde(deserialize_with = "deserialize_some_other_variant")] 6 | | Struct { 7 | | #[serde(skip_deserializing)] 8 | | f1: String, 9 | | f2: u8, 10 | | }, | |_____^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_de_tuple_field.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] enum Enum { #[serde(deserialize_with = "deserialize_some_other_variant")] Tuple(#[serde(skip_deserializing)] String, u8), } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_de_tuple_field.stderr ================================================ error: variant `Tuple` cannot have both #[serde(deserialize_with)] and a field #0 marked with #[serde(skip_deserializing)] --> tests/ui/with-variant/skip_de_tuple_field.rs:5:5 | 5 | / #[serde(deserialize_with = "deserialize_some_other_variant")] 6 | | Tuple(#[serde(skip_deserializing)] String, u8), | |__________________________________________________^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_de_whole_variant.rs ================================================ use serde_derive::Deserialize; #[derive(Deserialize)] enum Enum { #[serde(deserialize_with = "deserialize_some_unit_variant")] #[serde(skip_deserializing)] Unit, } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_de_whole_variant.stderr ================================================ error: variant `Unit` cannot have both #[serde(deserialize_with)] and #[serde(skip_deserializing)] --> tests/ui/with-variant/skip_de_whole_variant.rs:5:5 | 5 | / #[serde(deserialize_with = "deserialize_some_unit_variant")] 6 | | #[serde(skip_deserializing)] 7 | | Unit, | |________^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_newtype_field.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum Enum { #[serde(serialize_with = "serialize_some_newtype_variant")] Newtype(#[serde(skip_serializing)] String), } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_newtype_field.stderr ================================================ error: variant `Newtype` cannot have both #[serde(serialize_with)] and a field #0 marked with #[serde(skip_serializing)] --> tests/ui/with-variant/skip_ser_newtype_field.rs:5:5 | 5 | / #[serde(serialize_with = "serialize_some_newtype_variant")] 6 | | Newtype(#[serde(skip_serializing)] String), | |______________________________________________^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_newtype_field_if.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum Enum { #[serde(serialize_with = "serialize_some_newtype_variant")] Newtype(#[serde(skip_serializing_if = "always")] String), } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_newtype_field_if.stderr ================================================ error: variant `Newtype` cannot have both #[serde(serialize_with)] and a field #0 marked with #[serde(skip_serializing_if)] --> tests/ui/with-variant/skip_ser_newtype_field_if.rs:5:5 | 5 | / #[serde(serialize_with = "serialize_some_newtype_variant")] 6 | | Newtype(#[serde(skip_serializing_if = "always")] String), | |____________________________________________________________^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_struct_field.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum Enum { #[serde(serialize_with = "serialize_some_other_variant")] Struct { #[serde(skip_serializing)] f1: String, f2: u8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_struct_field.stderr ================================================ error: variant `Struct` cannot have both #[serde(serialize_with)] and a field `f1` marked with #[serde(skip_serializing)] --> tests/ui/with-variant/skip_ser_struct_field.rs:5:5 | 5 | / #[serde(serialize_with = "serialize_some_other_variant")] 6 | | Struct { 7 | | #[serde(skip_serializing)] 8 | | f1: String, 9 | | f2: u8, 10 | | }, | |_____^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_struct_field_if.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum Enum { #[serde(serialize_with = "serialize_some_newtype_variant")] Struct { #[serde(skip_serializing_if = "always")] f1: String, f2: u8, }, } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_struct_field_if.stderr ================================================ error: variant `Struct` cannot have both #[serde(serialize_with)] and a field `f1` marked with #[serde(skip_serializing_if)] --> tests/ui/with-variant/skip_ser_struct_field_if.rs:5:5 | 5 | / #[serde(serialize_with = "serialize_some_newtype_variant")] 6 | | Struct { 7 | | #[serde(skip_serializing_if = "always")] 8 | | f1: String, 9 | | f2: u8, 10 | | }, | |_____^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_tuple_field.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum Enum { #[serde(serialize_with = "serialize_some_other_variant")] Tuple(#[serde(skip_serializing)] String, u8), } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_tuple_field.stderr ================================================ error: variant `Tuple` cannot have both #[serde(serialize_with)] and a field #0 marked with #[serde(skip_serializing)] --> tests/ui/with-variant/skip_ser_tuple_field.rs:5:5 | 5 | / #[serde(serialize_with = "serialize_some_other_variant")] 6 | | Tuple(#[serde(skip_serializing)] String, u8), | |________________________________________________^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_tuple_field_if.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum Enum { #[serde(serialize_with = "serialize_some_other_variant")] Tuple(#[serde(skip_serializing_if = "always")] String, u8), } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_tuple_field_if.stderr ================================================ error: variant `Tuple` cannot have both #[serde(serialize_with)] and a field #0 marked with #[serde(skip_serializing_if)] --> tests/ui/with-variant/skip_ser_tuple_field_if.rs:5:5 | 5 | / #[serde(serialize_with = "serialize_some_other_variant")] 6 | | Tuple(#[serde(skip_serializing_if = "always")] String, u8), | |______________________________________________________________^ ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_whole_variant.rs ================================================ use serde_derive::Serialize; #[derive(Serialize)] enum Enum { #[serde(serialize_with = "serialize_some_unit_variant")] #[serde(skip_serializing)] Unit, } fn main() {} ================================================ FILE: test_suite/tests/ui/with-variant/skip_ser_whole_variant.stderr ================================================ error: variant `Unit` cannot have both #[serde(serialize_with)] and #[serde(skip_serializing)] --> tests/ui/with-variant/skip_ser_whole_variant.rs:5:5 | 5 | / #[serde(serialize_with = "serialize_some_unit_variant")] 6 | | #[serde(skip_serializing)] 7 | | Unit, | |________^ ================================================ FILE: test_suite/tests/unstable/mod.rs ================================================ use serde_derive::{Deserialize, Serialize}; use serde_test::{assert_tokens, Token}; #[test] fn test_raw_identifiers() { #[derive(Debug, PartialEq, Serialize, Deserialize)] #[allow(non_camel_case_types)] enum r#type { r#type { r#type: () }, } assert_tokens( &r#type::r#type { r#type: () }, &[ Token::StructVariant { name: "type", variant: "type", len: 1, }, Token::Str("type"), Token::Unit, Token::StructVariantEnd, ], ); }