serde_norway-0.9.38/.cargo_vcs_info.json0000644000000001360000000000100136360ustar { "git": { "sha1": "06a3a32c66958ca7c666b2d2facd820baca262cf" }, "path_in_vcs": "" }serde_norway-0.9.38/.github/FUNDING.yml000064400000000000000000000000201046102023000155730ustar 00000000000000github: cafkafk serde_norway-0.9.38/.github/dependabot.yml000064400000000000000000000010171046102023000166150ustar 00000000000000# To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file version: 2 updates: - package-ecosystem: "cargo" # See documentation for possible values directory: "/" # Location of package manifests schedule: interval: "weekly" serde_norway-0.9.38/.github/workflows/audit.yml000064400000000000000000000005401046102023000176530ustar 00000000000000name: Security audit on: schedule: - cron: '0 0 * * *' push: paths: - '**/Cargo.toml' - '**/Cargo.lock' jobs: security_audit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: taiki-e/install-action@cargo-deny - name: Scan for vulnerabilities run: cargo deny check advisories serde_norway-0.9.38/.github/workflows/ci.yml000064400000000000000000000052751046102023000171520ustar 00000000000000name: CI on: push: pull_request: workflow_dispatch: schedule: [cron: "40 1 * * *"] permissions: contents: read env: RUSTFLAGS: -Dwarnings jobs: pre_ci: uses: dtolnay/.github/.github/workflows/pre_ci.yml@master test: name: Rust ${{matrix.rust}} needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest strategy: fail-fast: false matrix: rust: [nightly, beta, stable, 1.64.0] timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} - name: Enable type layout randomization run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV if: matrix.rust == 'nightly' - run: cargo build - run: cargo test doc: name: Documentation needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 env: RUSTDOCFLAGS: -Dwarnings steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - uses: dtolnay/install@cargo-docs-rs - run: cargo docs-rs clippy: name: Clippy runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@clippy - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic miri: name: Miri needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@miri - run: cargo miri setup - run: cargo miri test env: MIRIFLAGS: -Zmiri-strict-provenance minimal: name: Minimal versions needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - run: cargo generate-lockfile -Z minimal-versions - run: cargo check --locked fuzz: name: Fuzz needs: pre_ci if: needs.pre_ci.outputs.continue runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly - uses: dtolnay/install@cargo-fuzz - run: cargo fuzz check outdated: name: Outdated runs-on: ubuntu-latest if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - uses: actions/checkout@v4 - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1 serde_norway-0.9.38/.github/workflows/conventional-commits.yml000064400000000000000000000006531046102023000227220ustar 00000000000000name: Conventional Commits on: push: branches: [ main ] pull_request: branches: [ main ] concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} cancel-in-progress: true jobs: build: name: Conventional Commits runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: webiny/action-conventional-commits@v1.3.0 serde_norway-0.9.38/.gitignore000064400000000000000000000000161046102023000144130ustar 00000000000000target result serde_norway-0.9.38/Cargo.toml0000644000000034030000000000100116340ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.64" name = "serde_norway" version = "0.9.38" authors = [ "Christina Sørensen ", "David Tolnay ", ] build = false autobins = false autoexamples = false autotests = false autobenches = false description = "YAML data format for Serde" readme = "README.md" keywords = [ "yaml", "serde", "serialization", ] categories = [ "encoding", "parser-implementations", ] license = "MIT OR Apache-2.0" repository = "https://github.com/cafkafk/serde-yaml" [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [lib] name = "serde_norway" path = "src/lib.rs" doc-scrape-examples = false [[test]] name = "test_de" path = "tests/test_de.rs" [[test]] name = "test_error" path = "tests/test_error.rs" [[test]] name = "test_serde" path = "tests/test_serde.rs" [[test]] name = "test_value" path = "tests/test_value.rs" [dependencies.indexmap] version = "2.2.1" [dependencies.itoa] version = "1.0" [dependencies.ryu] version = "1.0" [dependencies.serde] version = "1.0.203" [dependencies.unsafe-libyaml] version = "0.2.11" [dev-dependencies.anyhow] version = "1.0.79" [dev-dependencies.indoc] version = "2.0" [dev-dependencies.serde_derive] version = "1.0.203" serde_norway-0.9.38/Cargo.toml.orig000064400000000000000000000013441046102023000153170ustar 00000000000000[package] name = "serde_norway" version = "0.9.38" authors = ["Christina Sørensen ", "David Tolnay "] categories = ["encoding", "parser-implementations"] description = "YAML data format for Serde" edition = "2021" keywords = ["yaml", "serde", "serialization"] license = "MIT OR Apache-2.0" repository = "https://github.com/cafkafk/serde-yaml" rust-version = "1.64" [dependencies] indexmap = "2.2.1" itoa = "1.0" ryu = "1.0" serde = "1.0.203" unsafe-libyaml = "0.2.11" [dev-dependencies] anyhow = "1.0.79" indoc = "2.0" serde_derive = "1.0.203" [lib] doc-scrape-examples = false [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = ["--generate-link-to-definition"] serde_norway-0.9.38/LICENSE-APACHE000064400000000000000000000227731046102023000143650ustar 00000000000000 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 serde_norway-0.9.38/LICENSE-MIT000064400000000000000000000017771046102023000140760ustar 00000000000000Permission 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. serde_norway-0.9.38/README.md000064400000000000000000000074701046102023000137150ustar 00000000000000
Serde Norway, a Serde YAML fork :) ========== ![Flag_of_Norway svg](https://github.com/cafkafk/serde-norway/assets/89321978/ff00f477-7ae4-4665-ad66-cb0c3da88e47) A hard-fork of Serde YAML. I'm not committing to maintaining this long-term (yet). However, I also need it, because I'm in a platform team :) Rust library for using the [Serde] serialization framework with data in [YAML] file format. _(This project is no longer maintained.)_ [Serde]: https://github.com/serde-rs/serde [YAML]: https://yaml.org/
## Dependency ```toml [dependencies] serde = "1.0" serde_norway = "0.9" ``` Release notes are available under [GitHub releases]. [GitHub releases]: https://github.com/dtolnay/serde-yaml/releases ## Using Serde YAML [API documentation is available in rustdoc form][docs.rs] but the general idea is: [docs.rs]: https://docs.rs/serde_norway ```rust use std::collections::BTreeMap; fn main() -> Result<(), serde_norway::Error> { // You have some type. let mut map = BTreeMap::new(); map.insert("x".to_string(), 1.0); map.insert("y".to_string(), 2.0); // Serialize it to a YAML string. let yaml = serde_norway::to_string(&map)?; assert_eq!(yaml, "x: 1.0\ny: 2.0\n"); // Deserialize it back to a Rust type. let deserialized_map: BTreeMap = serde_norway::from_str(&yaml)?; assert_eq!(map, deserialized_map); Ok(()) } ``` It can also be used with Serde's derive macros to handle structs and enums defined in your program. ```toml [dependencies] serde = { version = "1.0", features = ["derive"] } serde_norway = "0.9" ``` Structs serialize in the obvious way: ```rust use serde::{Serialize, Deserialize}; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Point { x: f64, y: f64, } fn main() -> Result<(), serde_norway::Error> { let point = Point { x: 1.0, y: 2.0 }; let yaml = serde_norway::to_string(&point)?; assert_eq!(yaml, "x: 1.0\ny: 2.0\n"); let deserialized_point: Point = serde_norway::from_str(&yaml)?; assert_eq!(point, deserialized_point); Ok(()) } ``` Enums serialize using YAML's `!tag` syntax to identify the variant name. ```rust use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Enum { Unit, Newtype(usize), Tuple(usize, usize, usize), Struct { x: f64, y: f64 }, } fn main() -> Result<(), serde_norway::Error> { let yaml = " - !Newtype 1 - !Tuple [0, 0, 0] - !Struct {x: 1.0, y: 2.0} "; let values: Vec = serde_norway::from_str(yaml).unwrap(); assert_eq!(values[0], Enum::Newtype(1)); assert_eq!(values[1], Enum::Tuple(0, 0, 0)); assert_eq!(values[2], Enum::Struct { x: 1.0, y: 2.0 }); // The last two in YAML's block style instead: let yaml = " - !Tuple - 0 - 0 - 0 - !Struct x: 1.0 y: 2.0 "; let values: Vec = serde_norway::from_str(yaml).unwrap(); assert_eq!(values[0], Enum::Tuple(0, 0, 0)); assert_eq!(values[1], Enum::Struct { x: 1.0, y: 2.0 }); // Variants with no data can be written using !Tag or just the string name. let yaml = " - Unit # serialization produces this one - !Unit "; let values: Vec = serde_norway::from_str(yaml).unwrap(); assert_eq!(values[0], Enum::Unit); assert_eq!(values[1], Enum::Unit); Ok(()) } ```
#### 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 this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. serde_norway-0.9.38/cliff.toml000064400000000000000000000047331046102023000144150ustar 00000000000000# git-cliff ~ default configuration file # https://git-cliff.org/docs/configuration # # Lines starting with "#" are comments. # Configuration options are organized into tables and keys. # See documentation for more information on available options. [changelog] # changelog header header = """ # Changelog\n """ # template for the changelog body # https://tera.netlify.app/docs body = """ {% if version %}\ ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} {% else %}\ ## [unreleased] {% endif %}\ {% for group, commits in commits | group_by(attribute="group") %} ### {{ group | upper_first }} {% for commit in commits %} - {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\ {% endfor %} {% endfor %}\n """ # remove the leading and trailing whitespace from the template trim = true # changelog footer footer = """ """ [git] # parse the commits based on https://www.conventionalcommits.org conventional_commits = true # filter out the commits that are not conventional filter_unconventional = true # process each line of a commit as an individual commit split_commits = false # regex for preprocessing the commit messages commit_preprocessors = [ # { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))"}, # replace issue numbers ] # regex for parsing and grouping commits commit_parsers = [ { message = "^feat", group = "Features" }, { message = "^fix", group = "Bug Fixes" }, { message = "^doc", group = "Documentation" }, { message = "^perf", group = "Performance" }, { message = "^refactor", group = "Refactor" }, { message = "^style", group = "Styling" }, { message = "^test", group = "Testing" }, { message = "^chore\\(release\\): prepare for", skip = true }, { message = "^chore", group = "Miscellaneous Tasks" }, { body = ".*security", group = "Security" }, ] # protect breaking changes from being skipped due to matching a skipping commit_parser protect_breaking_commits = false # filter out the commits that are not matched by commit parsers filter_commits = false # glob pattern for matching git tags tag_pattern = "v[0-9]*" # regex for skipping tags skip_tags = "v0.1.0-beta.1" # regex for ignoring tags ignore_tags = "" # sort the tags topologically topo_order = false # sort the commits inside sections by oldest/newest order sort_commits = "oldest" # limit the number of commits included in the changelog. # limit_commits = 42 serde_norway-0.9.38/deny.toml000064400000000000000000000000571046102023000142640ustar 00000000000000[licenses] allow = [ "MIT", "Apache-2.0" ] serde_norway-0.9.38/flake.lock000064400000000000000000000057341046102023000143730ustar 00000000000000{ "nodes": { "advisory-db": { "flake": false, "locked": { "lastModified": 1717596017, "narHash": "sha256-LHjTqlOLgtv43GVkeM7Hb5HcZG5i/vNHnWgYaUzu+Jg=", "owner": "rustsec", "repo": "advisory-db", "rev": "af76d4423761499f954411bb3071dcc72e6b0450", "type": "github" }, "original": { "owner": "rustsec", "repo": "advisory-db", "type": "github" } }, "crane": { "inputs": { "nixpkgs": [ "nixpkgs" ] }, "locked": { "lastModified": 1717951870, "narHash": "sha256-hGLeRxSEeFz9WvmQ4s4AuMJ5InLSZvoczDdXkWSFi1A=", "owner": "ipetkov", "repo": "crane", "rev": "17d9e9dedd58dde2c562a4296934c6d6a0844534", "type": "github" }, "original": { "owner": "ipetkov", "repo": "crane", "type": "github" } }, "fenix": { "inputs": { "nixpkgs": [ "nixpkgs" ], "rust-analyzer-src": [] }, "locked": { "lastModified": 1717827974, "narHash": "sha256-ixopuTeTouxqTxfMuzs6IaRttbT8JqRW5C9Q/57WxQw=", "owner": "nix-community", "repo": "fenix", "rev": "ab655c627777ab5f9964652fe23bbb1dfbd687a8", "type": "github" }, "original": { "owner": "nix-community", "repo": "fenix", "type": "github" } }, "flake-utils": { "inputs": { "systems": "systems" }, "locked": { "lastModified": 1710146030, "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { "owner": "numtide", "repo": "flake-utils", "type": "github" } }, "nixpkgs": { "locked": { "lastModified": 1717868076, "narHash": "sha256-c83Y9t815Wa34khrux81j8K8ET94ESmCuwORSKm2bQY=", "owner": "NixOS", "repo": "nixpkgs", "rev": "cd18e2ae9ab8e2a0a8d715b60c91b54c0ac35ff9", "type": "github" }, "original": { "owner": "NixOS", "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } }, "root": { "inputs": { "advisory-db": "advisory-db", "crane": "crane", "fenix": "fenix", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } }, "systems": { "locked": { "lastModified": 1681028828, "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", "owner": "nix-systems", "repo": "default", "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", "type": "github" }, "original": { "owner": "nix-systems", "repo": "default", "type": "github" } } }, "root": "root", "version": 7 } serde_norway-0.9.38/flake.nix000064400000000000000000000101051046102023000142250ustar 00000000000000{ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; crane = { url = "github:ipetkov/crane"; inputs.nixpkgs.follows = "nixpkgs"; }; fenix = { url = "github:nix-community/fenix"; inputs.nixpkgs.follows = "nixpkgs"; inputs.rust-analyzer-src.follows = ""; }; flake-utils.url = "github:numtide/flake-utils"; advisory-db = { url = "github:rustsec/advisory-db"; flake = false; }; }; outputs = { self, nixpkgs, crane, fenix, flake-utils, advisory-db, ... }: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; inherit (pkgs) lib; craneLib = crane.mkLib pkgs; src = craneLib.cleanCargoSource (craneLib.path ./.); # Common arguments can be set here to avoid repeating them later commonArgs = { inherit src; strictDeps = true; buildInputs = [ # Add additional build inputs here ] ++ lib.optionals pkgs.stdenv.isDarwin [ # Additional darwin specific inputs can be set here pkgs.libiconv ]; # Additional environment variables can be set directly # MY_CUSTOM_VAR = "some value"; }; craneLibLLvmTools = craneLib.overrideToolchain (fenix.packages.${system}.complete.withComponents [ "cargo" "llvm-tools" "rustc" ]); # Build *just* the cargo dependencies, so we can reuse # all of that work (e.g. via cachix) when running in CI cargoArtifacts = craneLib.buildDepsOnly commonArgs; # Build the actual crate itself, reusing the dependency # artifacts from above. serde-yaml = craneLib.buildPackage (commonArgs // { inherit cargoArtifacts; }); in { checks = { # Build the crate as part of `nix flake check` for convenience inherit serde-yaml; # Run clippy (and deny all warnings) on the crate source, # again, reusing the dependency artifacts from above. # # Note that this is done as a separate derivation so that # we can block the CI if there are issues here, but not # prevent downstream consumers from building our crate by itself. serde-yaml-clippy = craneLib.cargoClippy (commonArgs // { inherit cargoArtifacts; cargoClippyExtraArgs = "--all-targets -- --deny warnings"; }); serde-yaml-doc = craneLib.cargoDoc (commonArgs // { inherit cargoArtifacts; }); # Check formatting serde-yaml-fmt = craneLib.cargoFmt { inherit src; }; # Audit dependencies serde-yaml-audit = craneLib.cargoAudit { inherit src advisory-db; }; # Audit licenses serde-yaml-deny = craneLib.cargoDeny { inherit src; }; # Run tests with cargo-nextest # Consider setting `doCheck = false` on `serde-yaml` if you do not want # the tests to run twice serde-yaml-nextest = craneLib.cargoNextest (commonArgs // { inherit cargoArtifacts; partitions = 1; partitionType = "count"; }); }; packages = { default = serde-yaml; } // lib.optionalAttrs (!pkgs.stdenv.isDarwin) { serde-yaml-llvm-coverage = craneLibLLvmTools.cargoLlvmCov (commonArgs // { inherit cargoArtifacts; }); }; apps.default = flake-utils.lib.mkApp { drv = serde-yaml; }; devShells.default = craneLib.devShell { # Inherit inputs from checks. checks = self.checks.${system}; # Additional dev-shell environment variables can be set directly # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; # Extra inputs can be added here; cargo and rustc are provided by default. packages = [ # pkgs.ripgrep ]; }; }); } serde_norway-0.9.38/src/de.rs000064400000000000000000001615531046102023000141660ustar 00000000000000use crate::error::{self, Error, ErrorImpl}; use crate::libyaml::error::Mark; use crate::libyaml::parser::{MappingStart, Scalar, ScalarStyle, SequenceStart}; use crate::libyaml::tag::Tag; use crate::loader::{Document, Loader}; use crate::path::Path; use serde::de::value::StrDeserializer; use serde::de::{ self, Deserialize, DeserializeOwned, DeserializeSeed, Expected, IgnoredAny, Unexpected, Visitor, }; use std::fmt; use std::io; use std::mem; use std::num::ParseIntError; use std::str; use std::sync::Arc; type Result = std::result::Result; /// A structure that deserializes YAML into Rust values. /// /// # Examples /// /// Deserializing a single document: /// /// ``` /// use anyhow::Result; /// use serde::Deserialize; /// use serde_norway::Value; /// /// fn main() -> Result<()> { /// let input = "k: 107\n"; /// let de = serde_norway::Deserializer::from_str(input); /// let value = Value::deserialize(de)?; /// println!("{:?}", value); /// Ok(()) /// } /// ``` /// /// Deserializing multi-doc YAML: /// /// ``` /// use anyhow::Result; /// use serde::Deserialize; /// use serde_norway::Value; /// /// fn main() -> Result<()> { /// let input = "---\nk: 107\n...\n---\nj: 106\n"; /// /// for document in serde_norway::Deserializer::from_str(input) { /// let value = Value::deserialize(document)?; /// println!("{:?}", value); /// } /// /// Ok(()) /// } /// ``` pub struct Deserializer<'de> { progress: Progress<'de>, } pub(crate) enum Progress<'de> { Str(&'de str), Slice(&'de [u8]), Read(Box), Iterable(Loader<'de>), Document(Document<'de>), Fail(Arc), } impl<'de> Deserializer<'de> { /// Creates a YAML deserializer from a `&str`. pub fn from_str(s: &'de str) -> Self { let progress = Progress::Str(s); Deserializer { progress } } /// Creates a YAML deserializer from a `&[u8]`. pub fn from_slice(v: &'de [u8]) -> Self { let progress = Progress::Slice(v); Deserializer { progress } } /// Creates a YAML deserializer from an `io::Read`. /// /// Reader-based deserializers do not support deserializing borrowed types /// like `&str`, since the `std::io::Read` trait has no non-copying methods /// -- everything it does involves copying bytes out of the data source. pub fn from_reader(rdr: R) -> Self where R: io::Read + 'de, { let progress = Progress::Read(Box::new(rdr)); Deserializer { progress } } fn de( self, f: impl for<'document> FnOnce(&mut DeserializerFromEvents<'de, 'document>) -> Result, ) -> Result { let mut pos = 0; let mut jumpcount = 0; match self.progress { Progress::Iterable(_) => return Err(error::new(ErrorImpl::MoreThanOneDocument)), Progress::Document(document) => { let t = f(&mut DeserializerFromEvents { document: &document, pos: &mut pos, jumpcount: &mut jumpcount, path: Path::Root, remaining_depth: 128, current_enum: None, })?; if let Some(parse_error) = document.error { return Err(error::shared(parse_error)); } return Ok(t); } _ => {} } let mut loader = Loader::new(self.progress)?; let document = match loader.next_document() { Some(document) => document, None => return Err(error::new(ErrorImpl::EndOfStream)), }; let t = f(&mut DeserializerFromEvents { document: &document, pos: &mut pos, jumpcount: &mut jumpcount, path: Path::Root, remaining_depth: 128, current_enum: None, })?; if let Some(parse_error) = document.error { return Err(error::shared(parse_error)); } if loader.next_document().is_none() { Ok(t) } else { Err(error::new(ErrorImpl::MoreThanOneDocument)) } } } impl<'de> Iterator for Deserializer<'de> { type Item = Self; fn next(&mut self) -> Option { match &mut self.progress { Progress::Iterable(loader) => { let document = loader.next_document()?; return Some(Deserializer { progress: Progress::Document(document), }); } Progress::Document(_) => return None, Progress::Fail(err) => { return Some(Deserializer { progress: Progress::Fail(Arc::clone(err)), }); } _ => {} } let dummy = Progress::Str(""); let input = mem::replace(&mut self.progress, dummy); match Loader::new(input) { Ok(loader) => { self.progress = Progress::Iterable(loader); self.next() } Err(err) => { let fail = err.shared(); self.progress = Progress::Fail(Arc::clone(&fail)); Some(Deserializer { progress: Progress::Fail(fail), }) } } } } impl<'de> de::Deserializer<'de> for Deserializer<'de> { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_any(visitor)) } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_bool(visitor)) } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i8(visitor)) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i16(visitor)) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i32(visitor)) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i64(visitor)) } fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_i128(visitor)) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u8(visitor)) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u16(visitor)) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u32(visitor)) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u64(visitor)) } fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_u128(visitor)) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_f32(visitor)) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_f64(visitor)) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_char(visitor)) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_str(visitor)) } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_string(visitor)) } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_bytes(visitor)) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_byte_buf(visitor)) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_option(visitor)) } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_unit(visitor)) } fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_unit_struct(name, visitor)) } fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_newtype_struct(name, visitor)) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_seq(visitor)) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_tuple(len, visitor)) } fn deserialize_tuple_struct( self, name: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_tuple_struct(name, len, visitor)) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_map(visitor)) } fn deserialize_struct( self, name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_struct(name, fields, visitor)) } fn deserialize_enum( self, name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_enum(name, variants, visitor)) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_identifier(visitor)) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.de(|state| state.deserialize_ignored_any(visitor)) } } #[derive(Debug)] pub(crate) enum Event<'de> { Alias(usize), Scalar(Scalar<'de>), SequenceStart(SequenceStart), SequenceEnd, MappingStart(MappingStart), MappingEnd, Void, } struct DeserializerFromEvents<'de, 'document> { document: &'document Document<'de>, pos: &'document mut usize, jumpcount: &'document mut usize, path: Path<'document>, remaining_depth: u8, current_enum: Option>, } #[derive(Copy, Clone)] struct CurrentEnum<'document> { name: Option<&'static str>, tag: &'document str, } impl<'de, 'document> DeserializerFromEvents<'de, 'document> { fn peek_event(&self) -> Result<&'document Event<'de>> { self.peek_event_mark().map(|(event, _mark)| event) } fn peek_event_mark(&self) -> Result<(&'document Event<'de>, Mark)> { match self.document.events.get(*self.pos) { Some((event, mark)) => Ok((event, *mark)), None => Err(match &self.document.error { Some(parse_error) => error::shared(Arc::clone(parse_error)), None => error::new(ErrorImpl::EndOfStream), }), } } fn next_event(&mut self) -> Result<&'document Event<'de>> { self.next_event_mark().map(|(event, _mark)| event) } fn next_event_mark(&mut self) -> Result<(&'document Event<'de>, Mark)> { self.peek_event_mark().map(|(event, mark)| { *self.pos += 1; self.current_enum = None; (event, mark) }) } fn jump<'anchor>( &'anchor mut self, pos: &'anchor mut usize, ) -> Result> { *self.jumpcount += 1; if *self.jumpcount > self.document.events.len() * 100 { return Err(error::new(ErrorImpl::RepetitionLimitExceeded)); } match self.document.aliases.get(pos) { Some(found) => { *pos = *found; Ok(DeserializerFromEvents { document: self.document, pos, jumpcount: self.jumpcount, path: Path::Alias { parent: &self.path }, remaining_depth: self.remaining_depth, current_enum: None, }) } None => panic!("unresolved alias: {}", *pos), } } fn ignore_any(&mut self) -> Result<()> { enum Nest { Sequence, Mapping, } let mut stack = Vec::new(); loop { match self.next_event()? { Event::Alias(_) | Event::Scalar(_) | Event::Void => {} Event::SequenceStart(_) => { stack.push(Nest::Sequence); } Event::MappingStart(_) => { stack.push(Nest::Mapping); } Event::SequenceEnd => match stack.pop() { Some(Nest::Sequence) => {} None | Some(Nest::Mapping) => { panic!("unexpected end of sequence"); } }, Event::MappingEnd => match stack.pop() { Some(Nest::Mapping) => {} None | Some(Nest::Sequence) => { panic!("unexpected end of mapping"); } }, } if stack.is_empty() { return Ok(()); } } } fn visit_sequence(&mut self, visitor: V, mark: Mark) -> Result where V: Visitor<'de>, { let (value, len) = self.recursion_check(mark, |de| { let mut seq = SeqAccess { empty: false, de, len: 0, }; let value = visitor.visit_seq(&mut seq)?; Ok((value, seq.len)) })?; self.end_sequence(len)?; Ok(value) } fn visit_mapping(&mut self, visitor: V, mark: Mark) -> Result where V: Visitor<'de>, { let (value, len) = self.recursion_check(mark, |de| { let mut map = MapAccess { empty: false, de, len: 0, key: None, }; let value = visitor.visit_map(&mut map)?; Ok((value, map.len)) })?; self.end_mapping(len)?; Ok(value) } fn end_sequence(&mut self, len: usize) -> Result<()> { let total = { let mut seq = SeqAccess { empty: false, de: self, len, }; while de::SeqAccess::next_element::(&mut seq)?.is_some() {} seq.len }; match self.next_event()? { Event::SequenceEnd | Event::Void => {} _ => panic!("expected a SequenceEnd event"), } if total == len { Ok(()) } else { struct ExpectedSeq(usize); impl Expected for ExpectedSeq { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { write!(formatter, "sequence of 1 element") } else { write!(formatter, "sequence of {} elements", self.0) } } } Err(de::Error::invalid_length(total, &ExpectedSeq(len))) } } fn end_mapping(&mut self, len: usize) -> Result<()> { let total = { let mut map = MapAccess { empty: false, de: self, len, key: None, }; while de::MapAccess::next_entry::(&mut map)?.is_some() {} map.len }; match self.next_event()? { Event::MappingEnd | Event::Void => {} _ => panic!("expected a MappingEnd event"), } if total == len { Ok(()) } else { struct ExpectedMap(usize); impl Expected for ExpectedMap { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.0 == 1 { write!(formatter, "map containing 1 entry") } else { write!(formatter, "map containing {} entries", self.0) } } } Err(de::Error::invalid_length(total, &ExpectedMap(len))) } } fn recursion_check Result, T>( &mut self, mark: Mark, f: F, ) -> Result { let previous_depth = self.remaining_depth; self.remaining_depth = match previous_depth.checked_sub(1) { Some(depth) => depth, None => return Err(error::new(ErrorImpl::RecursionLimitExceeded(mark))), }; let result = f(self); self.remaining_depth = previous_depth; result } } struct SeqAccess<'de, 'document, 'seq> { empty: bool, de: &'seq mut DeserializerFromEvents<'de, 'document>, len: usize, } impl<'de, 'document, 'seq> de::SeqAccess<'de> for SeqAccess<'de, 'document, 'seq> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result> where T: DeserializeSeed<'de>, { if self.empty { return Ok(None); } match self.de.peek_event()? { Event::SequenceEnd | Event::Void => Ok(None), _ => { let mut element_de = DeserializerFromEvents { document: self.de.document, pos: self.de.pos, jumpcount: self.de.jumpcount, path: Path::Seq { parent: &self.de.path, index: self.len, }, remaining_depth: self.de.remaining_depth, current_enum: None, }; self.len += 1; seed.deserialize(&mut element_de).map(Some) } } } } struct MapAccess<'de, 'document, 'map> { empty: bool, de: &'map mut DeserializerFromEvents<'de, 'document>, len: usize, key: Option<&'document [u8]>, } impl<'de, 'document, 'map> de::MapAccess<'de> for MapAccess<'de, 'document, 'map> { type Error = Error; fn next_key_seed(&mut self, seed: K) -> Result> where K: DeserializeSeed<'de>, { if self.empty { return Ok(None); } match self.de.peek_event()? { Event::MappingEnd | Event::Void => Ok(None), Event::Scalar(scalar) => { self.len += 1; self.key = Some(&scalar.value); seed.deserialize(&mut *self.de).map(Some) } _ => { self.len += 1; self.key = None; seed.deserialize(&mut *self.de).map(Some) } } } fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, { let mut value_de = DeserializerFromEvents { document: self.de.document, pos: self.de.pos, jumpcount: self.de.jumpcount, path: if let Some(key) = self.key.and_then(|key| str::from_utf8(key).ok()) { Path::Map { parent: &self.de.path, key, } } else { Path::Unknown { parent: &self.de.path, } }, remaining_depth: self.de.remaining_depth, current_enum: None, }; seed.deserialize(&mut value_de) } } struct EnumAccess<'de, 'document, 'variant> { de: &'variant mut DeserializerFromEvents<'de, 'document>, name: Option<&'static str>, tag: &'document str, } impl<'de, 'document, 'variant> de::EnumAccess<'de> for EnumAccess<'de, 'document, 'variant> { type Error = Error; type Variant = DeserializerFromEvents<'de, 'variant>; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>, { let str_de = StrDeserializer::::new(self.tag); let variant = seed.deserialize(str_de)?; let visitor = DeserializerFromEvents { document: self.de.document, pos: self.de.pos, jumpcount: self.de.jumpcount, path: self.de.path, remaining_depth: self.de.remaining_depth, current_enum: Some(CurrentEnum { name: self.name, tag: self.tag, }), }; Ok((variant, visitor)) } } impl<'de, 'document> de::VariantAccess<'de> for DeserializerFromEvents<'de, 'document> { type Error = Error; fn unit_variant(mut self) -> Result<()> { Deserialize::deserialize(&mut self) } fn newtype_variant_seed(mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { seed.deserialize(&mut self) } fn tuple_variant(mut self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { de::Deserializer::deserialize_seq(&mut self, visitor) } fn struct_variant(mut self, fields: &'static [&'static str], visitor: V) -> Result where V: Visitor<'de>, { de::Deserializer::deserialize_struct(&mut self, "", fields, visitor) } } struct UnitVariantAccess<'de, 'document, 'variant> { de: &'variant mut DeserializerFromEvents<'de, 'document>, } impl<'de, 'document, 'variant> de::EnumAccess<'de> for UnitVariantAccess<'de, 'document, 'variant> { type Error = Error; type Variant = Self; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> where V: DeserializeSeed<'de>, { Ok((seed.deserialize(&mut *self.de)?, self)) } } impl<'de, 'document, 'variant> de::VariantAccess<'de> for UnitVariantAccess<'de, 'document, 'variant> { type Error = Error; fn unit_variant(self) -> Result<()> { Ok(()) } fn newtype_variant_seed(self, _seed: T) -> Result where T: DeserializeSeed<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"newtype variant", )) } fn tuple_variant(self, _len: usize, _visitor: V) -> Result where V: Visitor<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"tuple variant", )) } fn struct_variant(self, _fields: &'static [&'static str], _visitor: V) -> Result where V: Visitor<'de>, { Err(de::Error::invalid_type( Unexpected::UnitVariant, &"struct variant", )) } } fn visit_scalar<'de, V>(visitor: V, scalar: &Scalar<'de>, tagged_already: bool) -> Result where V: Visitor<'de>, { let v = match str::from_utf8(&scalar.value) { Ok(v) => v, Err(_) => { return Err(de::Error::invalid_type( Unexpected::Bytes(&scalar.value), &visitor, )) } }; if let (Some(tag), false) = (&scalar.tag, tagged_already) { if tag == Tag::BOOL { return match parse_bool(v) { Some(v) => visitor.visit_bool(v), None => Err(de::Error::invalid_value(Unexpected::Str(v), &"a boolean")), }; } else if tag == Tag::INT { return match visit_int(visitor, v) { Ok(result) => result, Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"an integer")), }; } else if tag == Tag::FLOAT { return match parse_f64(v) { Some(v) => visitor.visit_f64(v), None => Err(de::Error::invalid_value(Unexpected::Str(v), &"a float")), }; } else if tag == Tag::NULL { return match parse_null(v.as_bytes()) { Some(()) => visitor.visit_unit(), None => Err(de::Error::invalid_value(Unexpected::Str(v), &"null")), }; } else if tag.starts_with("!") && scalar.style == ScalarStyle::Plain { return visit_untagged_scalar(visitor, v, scalar.repr, scalar.style); } } else if scalar.style == ScalarStyle::Plain { return visit_untagged_scalar(visitor, v, scalar.repr, scalar.style); } if let Some(borrowed) = parse_borrowed_str(v, scalar.repr, scalar.style) { visitor.visit_borrowed_str(borrowed) } else { visitor.visit_str(v) } } fn parse_borrowed_str<'de>( utf8_value: &str, repr: Option<&'de [u8]>, style: ScalarStyle, ) -> Option<&'de str> { let borrowed_repr = repr?; let expected_offset = match style { ScalarStyle::Plain => 0, ScalarStyle::SingleQuoted | ScalarStyle::DoubleQuoted => 1, ScalarStyle::Literal | ScalarStyle::Folded => return None, }; let expected_end = borrowed_repr.len().checked_sub(expected_offset)?; let expected_start = expected_end.checked_sub(utf8_value.len())?; let borrowed_bytes = borrowed_repr.get(expected_start..expected_end)?; if borrowed_bytes == utf8_value.as_bytes() { return Some(unsafe { str::from_utf8_unchecked(borrowed_bytes) }); } None } fn parse_null(scalar: &[u8]) -> Option<()> { match scalar { b"null" | b"Null" | b"NULL" | b"~" => Some(()), _ => None, } } fn parse_bool(scalar: &str) -> Option { match scalar { "true" | "True" | "TRUE" => Some(true), "false" | "False" | "FALSE" => Some(false), _ => None, } } fn parse_unsigned_int( scalar: &str, from_str_radix: fn(&str, radix: u32) -> Result, ) -> Option { let unpositive = scalar.strip_prefix('+').unwrap_or(scalar); if let Some(rest) = unpositive.strip_prefix("0x") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 16) { return Some(int); } } if let Some(rest) = unpositive.strip_prefix("0o") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 8) { return Some(int); } } if let Some(rest) = unpositive.strip_prefix("0b") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 2) { return Some(int); } } if unpositive.starts_with(['+', '-']) { return None; } if digits_but_not_number(scalar) { return None; } from_str_radix(unpositive, 10).ok() } fn parse_signed_int( scalar: &str, from_str_radix: fn(&str, radix: u32) -> Result, ) -> Option { let unpositive = if let Some(unpositive) = scalar.strip_prefix('+') { if unpositive.starts_with(['+', '-']) { return None; } unpositive } else { scalar }; if let Some(rest) = unpositive.strip_prefix("0x") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 16) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0x") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 16) { return Some(int); } } if let Some(rest) = unpositive.strip_prefix("0o") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 8) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0o") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 8) { return Some(int); } } if let Some(rest) = unpositive.strip_prefix("0b") { if rest.starts_with(['+', '-']) { return None; } if let Ok(int) = from_str_radix(rest, 2) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0b") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 2) { return Some(int); } } if digits_but_not_number(scalar) { return None; } from_str_radix(unpositive, 10).ok() } fn parse_negative_int( scalar: &str, from_str_radix: fn(&str, radix: u32) -> Result, ) -> Option { if let Some(rest) = scalar.strip_prefix("-0x") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 16) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0o") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 8) { return Some(int); } } if let Some(rest) = scalar.strip_prefix("-0b") { let negative = format!("-{}", rest); if let Ok(int) = from_str_radix(&negative, 2) { return Some(int); } } if digits_but_not_number(scalar) { return None; } from_str_radix(scalar, 10).ok() } pub(crate) fn parse_f64(scalar: &str) -> Option { let unpositive = if let Some(unpositive) = scalar.strip_prefix('+') { if unpositive.starts_with(['+', '-']) { return None; } unpositive } else { scalar }; if let ".inf" | ".Inf" | ".INF" = unpositive { return Some(f64::INFINITY); } if let "-.inf" | "-.Inf" | "-.INF" = scalar { return Some(f64::NEG_INFINITY); } if let ".nan" | ".NaN" | ".NAN" = scalar { return Some(f64::NAN.copysign(1.0)); } if let Ok(float) = unpositive.parse::() { if float.is_finite() { return Some(float); } } None } pub(crate) fn digits_but_not_number(scalar: &str) -> bool { // Leading zero(s) followed by numeric characters is a string according to // the YAML 1.2 spec. https://yaml.org/spec/1.2/spec.html#id2761292 let scalar = scalar.strip_prefix(['-', '+']).unwrap_or(scalar); scalar.len() > 1 && scalar.starts_with('0') && scalar[1..].bytes().all(|b| b.is_ascii_digit()) } pub(crate) fn visit_int<'de, V>(visitor: V, v: &str) -> Result, V> where V: Visitor<'de>, { if let Some(int) = parse_unsigned_int(v, u64::from_str_radix) { return Ok(visitor.visit_u64(int)); } if let Some(int) = parse_negative_int(v, i64::from_str_radix) { return Ok(visitor.visit_i64(int)); } if let Some(int) = parse_unsigned_int(v, u128::from_str_radix) { return Ok(visitor.visit_u128(int)); } if let Some(int) = parse_negative_int(v, i128::from_str_radix) { return Ok(visitor.visit_i128(int)); } Err(visitor) } pub(crate) fn visit_untagged_scalar<'de, V>( visitor: V, v: &str, repr: Option<&'de [u8]>, style: ScalarStyle, ) -> Result where V: Visitor<'de>, { if v.is_empty() || parse_null(v.as_bytes()) == Some(()) { return visitor.visit_unit(); } if let Some(boolean) = parse_bool(v) { return visitor.visit_bool(boolean); } let visitor = match visit_int(visitor, v) { Ok(result) => return result, Err(visitor) => visitor, }; if !digits_but_not_number(v) { if let Some(float) = parse_f64(v) { return visitor.visit_f64(float); } } if let Some(borrowed) = parse_borrowed_str(v, repr, style) { visitor.visit_borrowed_str(borrowed) } else { visitor.visit_str(v) } } fn is_plain_or_tagged_literal_scalar( expected: &str, scalar: &Scalar, tagged_already: bool, ) -> bool { match (scalar.style, &scalar.tag, tagged_already) { (ScalarStyle::Plain, _, _) => true, (ScalarStyle::Literal, Some(tag), false) => tag == expected, _ => false, } } fn invalid_type(event: &Event, exp: &dyn Expected) -> Error { enum Void {} struct InvalidType<'a> { exp: &'a dyn Expected, } impl<'de, 'a> Visitor<'de> for InvalidType<'a> { type Value = Void; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.exp.fmt(formatter) } } match event { Event::Alias(_) => unreachable!(), Event::Scalar(scalar) => { let get_type = InvalidType { exp }; // NOTE: void **should** be optimized away by the compiler #[allow(unreachable_patterns)] match visit_scalar(get_type, scalar, false) { Ok(void) => match void {}, Err(invalid_type) => invalid_type, } } Event::SequenceStart(_) => de::Error::invalid_type(Unexpected::Seq, exp), Event::MappingStart(_) => de::Error::invalid_type(Unexpected::Map, exp), Event::SequenceEnd => panic!("unexpected end of sequence"), Event::MappingEnd => panic!("unexpected end of mapping"), Event::Void => error::new(ErrorImpl::EndOfStream), } } fn parse_tag(libyaml_tag: &Option) -> Option<&str> { let mut bytes: &[u8] = libyaml_tag.as_ref()?; if let (b'!', rest) = bytes.split_first()? { if !rest.is_empty() { bytes = rest; } str::from_utf8(bytes).ok() } else { None } } impl<'de, 'document> de::Deserializer<'de> for &mut DeserializerFromEvents<'de, 'document> { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; fn enum_tag(tag: &Option, tagged_already: bool) -> Option<&str> { if tagged_already { return None; } parse_tag(tag) } loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_any(visitor), Event::Scalar(scalar) => { if let Some(tag) = enum_tag(&scalar.tag, tagged_already) { *self.pos -= 1; break visitor.visit_enum(EnumAccess { de: self, name: None, tag, }); } break visit_scalar(visitor, scalar, tagged_already); } Event::SequenceStart(sequence) => { if let Some(tag) = enum_tag(&sequence.tag, tagged_already) { *self.pos -= 1; break visitor.visit_enum(EnumAccess { de: self, name: None, tag, }); } break self.visit_sequence(visitor, mark); } Event::MappingStart(mapping) => { if let Some(tag) = enum_tag(&mapping.tag, tagged_already) { *self.pos -= 1; break visitor.visit_enum(EnumAccess { de: self, name: None, tag, }); } break self.visit_mapping(visitor, mark); } Event::SequenceEnd => panic!("unexpected end of sequence"), Event::MappingEnd => panic!("unexpected end of mapping"), Event::Void => break visitor.visit_none(), } } // The de::Error impl creates errors with unknown line and column. Fill // in the position here by looking at the current index in the input. .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_bool(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::BOOL, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(boolean) = parse_bool(value) { break visitor.visit_bool(boolean); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_i64(visitor) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_i64(visitor) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_i64(visitor) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_i64(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::INT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(int) = parse_signed_int(value, i64::from_str_radix) { break visitor.visit_i64(int); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_i128(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::INT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(int) = parse_signed_int(value, i128::from_str_radix) { break visitor.visit_i128(int); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_u64(visitor) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_u64(visitor) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_u64(visitor) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_u64(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::INT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(int) = parse_unsigned_int(value, u64::from_str_radix) { break visitor.visit_u64(int); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_u128(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::INT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(int) = parse_unsigned_int(value, u128::from_str_radix) { break visitor.visit_u128(int); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_f64(visitor) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; loop { match next { Event::Alias(mut pos) => break self.jump(&mut pos)?.deserialize_f64(visitor), Event::Scalar(scalar) if is_plain_or_tagged_literal_scalar(Tag::FLOAT, scalar, tagged_already) => { if let Ok(value) = str::from_utf8(&scalar.value) { if let Some(float) = parse_f64(value) { break visitor.visit_f64(float); } } } _ => {} } break Err(invalid_type(next, &visitor)); } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { let (next, mark) = self.next_event_mark()?; match next { Event::Scalar(scalar) => { if let Ok(v) = str::from_utf8(&scalar.value) { if let Some(borrowed) = parse_borrowed_str(v, scalar.repr, scalar.style) { visitor.visit_borrowed_str(borrowed) } else { visitor.visit_str(v) } } else { Err(invalid_type(next, &visitor)) } } Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_str(visitor), other => Err(invalid_type(other, &visitor)), } .map_err(|err: Error| error::fix_mark(err, mark, self.path)) } 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>, { Err(error::new(ErrorImpl::BytesUnsupported)) } fn deserialize_byte_buf(self, _visitor: V) -> Result where V: Visitor<'de>, { Err(error::new(ErrorImpl::BytesUnsupported)) } /// Parses `null` as None and any other values as `Some(...)`. fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { let is_some = match self.peek_event()? { Event::Alias(mut pos) => { *self.pos += 1; return self.jump(&mut pos)?.deserialize_option(visitor); } Event::Scalar(scalar) => { let tagged_already = self.current_enum.is_some(); if scalar.style != ScalarStyle::Plain { true } else if let (Some(tag), false) = (&scalar.tag, tagged_already) { if tag == Tag::NULL { if let Some(()) = parse_null(&scalar.value) { false } else if let Ok(v) = str::from_utf8(&scalar.value) { return Err(de::Error::invalid_value(Unexpected::Str(v), &"null")); } else { return Err(de::Error::invalid_value( Unexpected::Bytes(&scalar.value), &"null", )); } } else { true } } else { !scalar.value.is_empty() && parse_null(&scalar.value).is_none() } } Event::SequenceStart(_) | Event::MappingStart(_) => true, Event::SequenceEnd => panic!("unexpected end of sequence"), Event::MappingEnd => panic!("unexpected end of mapping"), Event::Void => false, }; if is_some { visitor.visit_some(self) } else { *self.pos += 1; self.current_enum = None; visitor.visit_none() } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { let tagged_already = self.current_enum.is_some(); let (next, mark) = self.next_event_mark()?; match next { Event::Scalar(scalar) => { let is_null = if scalar.style != ScalarStyle::Plain { false } else if let (Some(tag), false) = (&scalar.tag, tagged_already) { tag == Tag::NULL && parse_null(&scalar.value).is_some() } else { scalar.value.is_empty() || parse_null(&scalar.value).is_some() }; if is_null { visitor.visit_unit() } else if let Ok(v) = str::from_utf8(&scalar.value) { Err(de::Error::invalid_value(Unexpected::Str(v), &"null")) } else { Err(de::Error::invalid_value( Unexpected::Bytes(&scalar.value), &"null", )) } } Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_unit(visitor), Event::Void => visitor.visit_unit(), other => Err(invalid_type(other, &visitor)), } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_unit(visitor) } /// Parses a newtype struct as the underlying value. fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result where V: Visitor<'de>, { let (_event, mark) = self.peek_event_mark()?; self.recursion_check(mark, |de| visitor.visit_newtype_struct(de)) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { let (next, mark) = self.next_event_mark()?; match next { Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_seq(visitor), Event::SequenceStart(_) => self.visit_sequence(visitor, mark), other => { if match other { Event::Void => true, Event::Scalar(scalar) => { scalar.value.is_empty() && scalar.style == ScalarStyle::Plain } _ => false, } { visitor.visit_seq(SeqAccess { empty: true, de: self, len: 0, }) } else { Err(invalid_type(other, &visitor)) } } } .map_err(|err| error::fix_mark(err, mark, self.path)) } 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>, { let (next, mark) = self.next_event_mark()?; match next { Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_map(visitor), Event::MappingStart(_) => self.visit_mapping(visitor, mark), other => { if match other { Event::Void => true, Event::Scalar(scalar) => { scalar.value.is_empty() && scalar.style == ScalarStyle::Plain } _ => false, } { visitor.visit_map(MapAccess { empty: true, de: self, len: 0, key: None, }) } else { Err(invalid_type(other, &visitor)) } } } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_struct( self, _name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_map(visitor) } /// Parses an enum as a single key:value pair where the key identifies the /// variant and the value gives the content. A String will also parse correctly /// to a unit enum value. fn deserialize_enum( self, name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let (next, mark) = self.peek_event_mark()?; loop { if let Some(current_enum) = self.current_enum { if let Event::Scalar(scalar) = next { if !scalar.value.is_empty() { break visitor.visit_enum(UnitVariantAccess { de: self }); } } let message = if let Some(name) = current_enum.name { format!( "deserializing nested enum in {}::{} from YAML is not supported yet", name, current_enum.tag, ) } else { format!( "deserializing nested enum in !{} from YAML is not supported yet", current_enum.tag, ) }; break Err(error::new(ErrorImpl::Message(message, None))); } break match next { Event::Alias(mut pos) => { *self.pos += 1; self.jump(&mut pos)? .deserialize_enum(name, variants, visitor) } Event::Scalar(scalar) => { if let Some(tag) = parse_tag(&scalar.tag) { return visitor.visit_enum(EnumAccess { de: self, name: Some(name), tag, }); } visitor.visit_enum(UnitVariantAccess { de: self }) } Event::MappingStart(mapping) => { if let Some(tag) = parse_tag(&mapping.tag) { return visitor.visit_enum(EnumAccess { de: self, name: Some(name), tag, }); } let err = de::Error::invalid_type(Unexpected::Map, &"a YAML tag starting with '!'"); Err(error::fix_mark(err, mark, self.path)) } Event::SequenceStart(sequence) => { if let Some(tag) = parse_tag(&sequence.tag) { return visitor.visit_enum(EnumAccess { de: self, name: Some(name), tag, }); } let err = de::Error::invalid_type(Unexpected::Seq, &"a YAML tag starting with '!'"); Err(error::fix_mark(err, mark, self.path)) } Event::SequenceEnd => panic!("unexpected end of sequence"), Event::MappingEnd => panic!("unexpected end of mapping"), Event::Void => Err(error::new(ErrorImpl::EndOfStream)), }; } .map_err(|err| error::fix_mark(err, mark, self.path)) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_str(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.ignore_any()?; visitor.visit_unit() } } /// Deserialize an instance of type `T` from a string of YAML text. /// /// This conversion can fail if the structure of the Value does not match the /// structure expected by `T`, for example if `T` is a struct type but the Value /// contains something other than a YAML map. It can also fail if the structure /// is correct but `T`'s implementation of `Deserialize` decides that something /// is wrong with the data, for example required struct fields are missing from /// the YAML map or some number is too big to fit in the expected primitive /// type. pub fn from_str<'de, T>(s: &'de str) -> Result where T: Deserialize<'de>, { T::deserialize(Deserializer::from_str(s)) } /// Deserialize an instance of type `T` from an IO stream of YAML. /// /// This conversion can fail if the structure of the Value does not match the /// structure expected by `T`, for example if `T` is a struct type but the Value /// contains something other than a YAML map. It can also fail if the structure /// is correct but `T`'s implementation of `Deserialize` decides that something /// is wrong with the data, for example required struct fields are missing from /// the YAML map or some number is too big to fit in the expected primitive /// type. pub fn from_reader(rdr: R) -> Result where R: io::Read, T: DeserializeOwned, { T::deserialize(Deserializer::from_reader(rdr)) } /// Deserialize an instance of type `T` from bytes of YAML text. /// /// This conversion can fail if the structure of the Value does not match the /// structure expected by `T`, for example if `T` is a struct type but the Value /// contains something other than a YAML map. It can also fail if the structure /// is correct but `T`'s implementation of `Deserialize` decides that something /// is wrong with the data, for example required struct fields are missing from /// the YAML map or some number is too big to fit in the expected primitive /// type. pub fn from_slice<'de, T>(v: &'de [u8]) -> Result where T: Deserialize<'de>, { T::deserialize(Deserializer::from_slice(v)) } serde_norway-0.9.38/src/error.rs000064400000000000000000000212011046102023000147100ustar 00000000000000use crate::libyaml::{emitter, error as libyaml}; use crate::path::Path; use serde::{de, ser}; use std::error::Error as StdError; use std::fmt::{self, Debug, Display}; use std::io; use std::result; use std::string; use std::sync::Arc; /// An error that happened serializing or deserializing YAML data. pub struct Error(Box); /// Alias for a `Result` with the error type `serde_norway::Error`. pub type Result = result::Result; #[derive(Debug)] pub(crate) enum ErrorImpl { Message(String, Option), Libyaml(libyaml::Error), Io(io::Error), FromUtf8(string::FromUtf8Error), EndOfStream, MoreThanOneDocument, RecursionLimitExceeded(libyaml::Mark), RepetitionLimitExceeded, BytesUnsupported, UnknownAnchor(libyaml::Mark), SerializeNestedEnum, ScalarInMerge, TaggedInMerge, ScalarInMergeElement, SequenceInMergeElement, EmptyTag, FailedToParseNumber, Shared(Arc), } #[derive(Debug)] pub(crate) struct Pos { mark: libyaml::Mark, path: String, } /// The input location that an error occured. #[derive(Debug)] pub struct Location { index: usize, line: usize, column: usize, } impl Location { /// The byte index of the error pub fn index(&self) -> usize { self.index } /// The line of the error pub fn line(&self) -> usize { self.line } /// The column of the error pub fn column(&self) -> usize { self.column } // This is to keep decoupled with the yaml crate #[doc(hidden)] fn from_mark(mark: libyaml::Mark) -> Self { Location { index: mark.index() as usize, // `line` and `column` returned from libyaml are 0-indexed but all error messages add +1 to this value line: mark.line() as usize + 1, column: mark.column() as usize + 1, } } } impl Error { /// Returns the Location from the error if one exists. /// /// Not all types of errors have a location so this can return `None`. /// /// # Examples /// /// ``` /// # use serde_norway::{Value, Error}; /// # /// // The `@` character as the first character makes this invalid yaml /// let invalid_yaml: Result = serde_norway::from_str("@invalid_yaml"); /// /// let location = invalid_yaml.unwrap_err().location().unwrap(); /// /// assert_eq!(location.line(), 1); /// assert_eq!(location.column(), 1); /// ``` pub fn location(&self) -> Option { self.0.location() } } pub(crate) fn new(inner: ErrorImpl) -> Error { Error(Box::new(inner)) } pub(crate) fn shared(shared: Arc) -> Error { Error(Box::new(ErrorImpl::Shared(shared))) } pub(crate) fn fix_mark(mut error: Error, mark: libyaml::Mark, path: Path) -> Error { if let ErrorImpl::Message(_, none @ None) = error.0.as_mut() { *none = Some(Pos { mark, path: path.to_string(), }); } error } impl Error { pub(crate) fn shared(self) -> Arc { if let ErrorImpl::Shared(err) = *self.0 { err } else { Arc::from(self.0) } } } impl From for Error { fn from(err: libyaml::Error) -> Self { Error(Box::new(ErrorImpl::Libyaml(err))) } } impl From for Error { fn from(err: emitter::Error) -> Self { match err { emitter::Error::Libyaml(err) => Self::from(err), emitter::Error::Io(err) => new(ErrorImpl::Io(err)), } } } impl StdError for Error { fn source(&self) -> Option<&(dyn StdError + 'static)> { self.0.source() } } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.display(f) } } // Remove two layers of verbosity from the debug representation. Humans often // end up seeing this representation because it is what unwrap() shows. impl Debug for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.debug(f) } } impl ser::Error for Error { fn custom(msg: T) -> Self { Error(Box::new(ErrorImpl::Message(msg.to_string(), None))) } } impl de::Error for Error { fn custom(msg: T) -> Self { Error(Box::new(ErrorImpl::Message(msg.to_string(), None))) } } impl ErrorImpl { fn location(&self) -> Option { self.mark().map(Location::from_mark) } fn source(&self) -> Option<&(dyn StdError + 'static)> { match self { ErrorImpl::Io(err) => err.source(), ErrorImpl::FromUtf8(err) => err.source(), ErrorImpl::Shared(err) => err.source(), _ => None, } } fn mark(&self) -> Option { match self { ErrorImpl::Message(_, Some(Pos { mark, path: _ })) | ErrorImpl::RecursionLimitExceeded(mark) | ErrorImpl::UnknownAnchor(mark) => Some(*mark), ErrorImpl::Libyaml(err) => Some(err.mark()), ErrorImpl::Shared(err) => err.mark(), _ => None, } } fn message_no_mark(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ErrorImpl::Message(msg, None) => f.write_str(msg), ErrorImpl::Message(msg, Some(Pos { mark: _, path })) => { if path != "." { write!(f, "{}: ", path)?; } f.write_str(msg) } ErrorImpl::Libyaml(_) => unreachable!(), ErrorImpl::Io(err) => Display::fmt(err, f), ErrorImpl::FromUtf8(err) => Display::fmt(err, f), ErrorImpl::EndOfStream => f.write_str("EOF while parsing a value"), ErrorImpl::MoreThanOneDocument => f.write_str( "deserializing from YAML containing more than one document is not supported", ), ErrorImpl::RecursionLimitExceeded(_mark) => f.write_str("recursion limit exceeded"), ErrorImpl::RepetitionLimitExceeded => f.write_str("repetition limit exceeded"), ErrorImpl::BytesUnsupported => { f.write_str("serialization and deserialization of bytes in YAML is not implemented") } ErrorImpl::UnknownAnchor(_mark) => f.write_str("unknown anchor"), ErrorImpl::SerializeNestedEnum => { f.write_str("serializing nested enums in YAML is not supported yet") } ErrorImpl::ScalarInMerge => { f.write_str("expected a mapping or list of mappings for merging, but found scalar") } ErrorImpl::TaggedInMerge => f.write_str("unexpected tagged value in merge"), ErrorImpl::ScalarInMergeElement => { f.write_str("expected a mapping for merging, but found scalar") } ErrorImpl::SequenceInMergeElement => { f.write_str("expected a mapping for merging, but found sequence") } ErrorImpl::EmptyTag => f.write_str("empty YAML tag is not allowed"), ErrorImpl::FailedToParseNumber => f.write_str("failed to parse YAML number"), ErrorImpl::Shared(_) => unreachable!(), } } fn display(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ErrorImpl::Libyaml(err) => Display::fmt(err, f), ErrorImpl::Shared(err) => err.display(f), _ => { self.message_no_mark(f)?; if let Some(mark) = self.mark() { if mark.line() != 0 || mark.column() != 0 { write!(f, " at {}", mark)?; } } Ok(()) } } } fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ErrorImpl::Libyaml(err) => Debug::fmt(err, f), ErrorImpl::Shared(err) => err.debug(f), _ => { f.write_str("Error(")?; struct MessageNoMark<'a>(&'a ErrorImpl); impl<'a> Display for MessageNoMark<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.message_no_mark(f) } } let msg = MessageNoMark(self).to_string(); Debug::fmt(&msg, f)?; if let Some(mark) = self.mark() { write!( f, ", line: {}, column: {}", mark.line() + 1, mark.column() + 1, )?; } f.write_str(")") } } } } serde_norway-0.9.38/src/lib.rs000064400000000000000000000130271046102023000143340ustar 00000000000000#![doc(html_logo_url = "https://upload.wikimedia.org/wikipedia/commons/d/d9/Flag_of_Norway.svg")] //! [![github]](https://github.com/dtolnay/serde-yaml) [![crates-io]](https://crates.io/crates/serde-yaml) [![docs-rs]](https://docs.rs/serde-yaml) //! //! Rust library for using the [Serde] serialization framework with data in //! [YAML] file format. //! //! [Serde]: https://github.com/serde-rs/serde //! [YAML]: https://yaml.org/ //! //! # Examples //! //! ``` //! use std::collections::BTreeMap; //! //! fn main() -> Result<(), serde_norway::Error> { //! // You have some type. //! let mut map = BTreeMap::new(); //! map.insert("x".to_string(), 1.0); //! map.insert("y".to_string(), 2.0); //! //! // Serialize it to a YAML string. //! let yaml = serde_norway::to_string(&map)?; //! assert_eq!(yaml, "x: 1.0\ny: 2.0\n"); //! //! // Deserialize it back to a Rust type. //! let deserialized_map: BTreeMap = serde_norway::from_str(&yaml)?; //! assert_eq!(map, deserialized_map); //! Ok(()) //! } //! ``` //! //! ## Using Serde derive //! //! It can also be used with Serde's derive macros to handle structs and enums //! defined in your program. //! //! Structs serialize in the obvious way: //! //! ``` //! # use serde_derive::{Serialize, Deserialize}; //! use serde::{Serialize, Deserialize}; //! //! #[derive(Serialize, Deserialize, PartialEq, Debug)] //! struct Point { //! x: f64, //! y: f64, //! } //! //! fn main() -> Result<(), serde_norway::Error> { //! let point = Point { x: 1.0, y: 2.0 }; //! //! let yaml = serde_norway::to_string(&point)?; //! assert_eq!(yaml, "x: 1.0\ny: 2.0\n"); //! //! let deserialized_point: Point = serde_norway::from_str(&yaml)?; //! assert_eq!(point, deserialized_point); //! Ok(()) //! } //! ``` //! //! Enums serialize using YAML's `!tag` syntax to identify the variant name. //! //! ``` //! # use serde_derive::{Serialize, Deserialize}; //! use serde::{Serialize, Deserialize}; //! //! #[derive(Serialize, Deserialize, PartialEq, Debug)] //! enum Enum { //! Unit, //! Newtype(usize), //! Tuple(usize, usize, usize), //! Struct { x: f64, y: f64 }, //! } //! //! fn main() -> Result<(), serde_norway::Error> { //! let yaml = " //! - !Newtype 1 //! - !Tuple [0, 0, 0] //! - !Struct {x: 1.0, y: 2.0} //! "; //! let values: Vec = serde_norway::from_str(yaml).unwrap(); //! assert_eq!(values[0], Enum::Newtype(1)); //! assert_eq!(values[1], Enum::Tuple(0, 0, 0)); //! assert_eq!(values[2], Enum::Struct { x: 1.0, y: 2.0 }); //! //! // The last two in YAML's block style instead: //! let yaml = " //! - !Tuple //! - 0 //! - 0 //! - 0 //! - !Struct //! x: 1.0 //! y: 2.0 //! "; //! let values: Vec = serde_norway::from_str(yaml).unwrap(); //! assert_eq!(values[0], Enum::Tuple(0, 0, 0)); //! assert_eq!(values[1], Enum::Struct { x: 1.0, y: 2.0 }); //! //! // Variants with no data can be written using !Tag or just the string name. //! let yaml = " //! - Unit # serialization produces this one //! - !Unit //! "; //! let values: Vec = serde_norway::from_str(yaml).unwrap(); //! assert_eq!(values[0], Enum::Unit); //! assert_eq!(values[1], Enum::Unit); //! //! Ok(()) //! } //! ``` #![deny(missing_docs, unsafe_op_in_unsafe_fn)] // Suppressed clippy_pedantic lints #![allow( // buggy clippy::iter_not_returning_iterator, // https://github.com/rust-lang/rust-clippy/issues/8285 clippy::ptr_arg, // https://github.com/rust-lang/rust-clippy/issues/9218 clippy::question_mark, // https://github.com/rust-lang/rust-clippy/issues/7859 // private Deserializer::next clippy::should_implement_trait, // things are often more readable this way clippy::cast_lossless, clippy::checked_conversions, clippy::if_not_else, clippy::manual_assert, clippy::match_like_matches_macro, clippy::match_same_arms, clippy::module_name_repetitions, clippy::needless_pass_by_value, clippy::redundant_else, clippy::single_match_else, // code is acceptable clippy::blocks_in_conditions, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_sign_loss, clippy::derive_partial_eq_without_eq, clippy::derived_hash_with_manual_eq, clippy::doc_markdown, clippy::items_after_statements, clippy::let_underscore_untyped, clippy::manual_map, clippy::missing_panics_doc, clippy::never_loop, clippy::return_self_not_must_use, clippy::too_many_lines, clippy::uninlined_format_args, clippy::unsafe_removed_from_name, clippy::wildcard_in_or_patterns, // noisy clippy::missing_errors_doc, clippy::must_use_candidate, )] pub use crate::de::{from_reader, from_slice, from_str, Deserializer}; pub use crate::error::{Error, Location, Result}; pub use crate::ser::{to_string, to_writer, Serializer}; #[doc(inline)] pub use crate::value::{from_value, to_value, Index, Number, Sequence, Value}; #[doc(inline)] pub use crate::mapping::Mapping; mod de; mod error; mod libyaml; mod loader; pub mod mapping; mod number; mod path; mod ser; pub mod value; pub mod with; // Prevent downstream code from implementing the Index trait. mod private { pub trait Sealed {} impl Sealed for usize {} impl Sealed for str {} impl Sealed for String {} impl Sealed for crate::Value {} impl<'a, T> Sealed for &'a T where T: ?Sized + Sealed {} } serde_norway-0.9.38/src/libyaml/cstr.rs000064400000000000000000000074051046102023000161750ustar 00000000000000use std::fmt::{self, Debug, Display, Write as _}; use std::marker::PhantomData; use std::ptr::NonNull; use std::slice; use std::str; #[derive(Copy, Clone)] pub(crate) struct CStr<'a> { ptr: NonNull, marker: PhantomData<&'a [u8]>, } unsafe impl<'a> Send for CStr<'a> {} unsafe impl<'a> Sync for CStr<'a> {} impl<'a> CStr<'a> { pub fn from_bytes_with_nul(bytes: &'static [u8]) -> Self { assert_eq!(bytes.last(), Some(&b'\0')); let ptr = NonNull::from(bytes).cast(); unsafe { Self::from_ptr(ptr) } } pub unsafe fn from_ptr(ptr: NonNull) -> Self { CStr { ptr: ptr.cast(), marker: PhantomData, } } pub fn len(self) -> usize { let start = self.ptr.as_ptr(); let mut end = start; unsafe { while *end != 0 { end = end.add(1); } end.offset_from(start) as usize } } pub fn to_bytes(self) -> &'a [u8] { let len = self.len(); unsafe { slice::from_raw_parts(self.ptr.as_ptr(), len) } } } impl<'a> Display for CStr<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let ptr = self.ptr.as_ptr(); let len = self.len(); let bytes = unsafe { slice::from_raw_parts(ptr, len) }; display_lossy(bytes, formatter) } } impl<'a> Debug for CStr<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let ptr = self.ptr.as_ptr(); let len = self.len(); let bytes = unsafe { slice::from_raw_parts(ptr, len) }; debug_lossy(bytes, formatter) } } fn display_lossy(mut bytes: &[u8], formatter: &mut fmt::Formatter) -> fmt::Result { loop { match str::from_utf8(bytes) { Ok(valid) => return formatter.write_str(valid), Err(utf8_error) => { let valid_up_to = utf8_error.valid_up_to(); let valid = unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) }; formatter.write_str(valid)?; formatter.write_char(char::REPLACEMENT_CHARACTER)?; if let Some(error_len) = utf8_error.error_len() { bytes = &bytes[valid_up_to + error_len..]; } else { return Ok(()); } } } } } pub(crate) fn debug_lossy(mut bytes: &[u8], formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_char('"')?; while !bytes.is_empty() { let from_utf8_result = str::from_utf8(bytes); let valid = match from_utf8_result { Ok(valid) => valid, Err(utf8_error) => { let valid_up_to = utf8_error.valid_up_to(); unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) } } }; let mut written = 0; for (i, ch) in valid.char_indices() { let esc = ch.escape_debug(); if esc.len() != 1 && ch != '\'' { formatter.write_str(&valid[written..i])?; for ch in esc { formatter.write_char(ch)?; } written = i + ch.len_utf8(); } } formatter.write_str(&valid[written..])?; match from_utf8_result { Ok(_valid) => break, Err(utf8_error) => { let end_of_broken = if let Some(error_len) = utf8_error.error_len() { valid.len() + error_len } else { bytes.len() }; for b in &bytes[valid.len()..end_of_broken] { write!(formatter, "\\x{:02x}", b)?; } bytes = &bytes[end_of_broken..]; } } } formatter.write_char('"') } serde_norway-0.9.38/src/libyaml/emitter.rs000064400000000000000000000163221046102023000166710ustar 00000000000000use crate::libyaml; use crate::libyaml::util::Owned; use std::ffi::c_void; use std::io; use std::mem::{self, MaybeUninit}; use std::ptr::{self, addr_of_mut}; use std::slice; use unsafe_libyaml as sys; #[derive(Debug)] pub(crate) enum Error { Libyaml(libyaml::error::Error), Io(io::Error), } pub(crate) struct Emitter<'a> { pin: Owned>, } struct EmitterPinned<'a> { sys: sys::yaml_emitter_t, write: Box, write_error: Option, } #[derive(Debug)] pub(crate) enum Event<'a> { StreamStart, StreamEnd, DocumentStart, DocumentEnd, Scalar(Scalar<'a>), SequenceStart(Sequence), SequenceEnd, MappingStart(Mapping), MappingEnd, } #[derive(Debug)] pub(crate) struct Scalar<'a> { pub tag: Option, pub value: &'a str, pub style: ScalarStyle, } #[derive(Debug)] pub(crate) enum ScalarStyle { Any, Plain, SingleQuoted, Literal, } #[derive(Debug)] pub(crate) struct Sequence { pub tag: Option, } #[derive(Debug)] pub(crate) struct Mapping { pub tag: Option, } impl<'a> Emitter<'a> { pub fn new(write: Box) -> Emitter<'a> { let owned = Owned::::new_uninit(); let pin = unsafe { let emitter = addr_of_mut!((*owned.ptr).sys); if sys::yaml_emitter_initialize(emitter).fail { panic!("malloc error: {}", libyaml::Error::emit_error(emitter)); } sys::yaml_emitter_set_unicode(emitter, true); sys::yaml_emitter_set_width(emitter, -1); addr_of_mut!((*owned.ptr).write).write(write); addr_of_mut!((*owned.ptr).write_error).write(None); sys::yaml_emitter_set_output(emitter, write_handler, owned.ptr.cast()); Owned::assume_init(owned) }; Emitter { pin } } pub fn emit(&mut self, event: Event) -> Result<(), Error> { let mut sys_event = MaybeUninit::::uninit(); let sys_event = sys_event.as_mut_ptr(); unsafe { let emitter = addr_of_mut!((*self.pin.ptr).sys); let initialize_status = match event { Event::StreamStart => { sys::yaml_stream_start_event_initialize(sys_event, sys::YAML_UTF8_ENCODING) } Event::StreamEnd => sys::yaml_stream_end_event_initialize(sys_event), Event::DocumentStart => { let version_directive = ptr::null_mut(); let tag_directives_start = ptr::null_mut(); let tag_directives_end = ptr::null_mut(); let implicit = true; sys::yaml_document_start_event_initialize( sys_event, version_directive, tag_directives_start, tag_directives_end, implicit, ) } Event::DocumentEnd => { let implicit = true; sys::yaml_document_end_event_initialize(sys_event, implicit) } Event::Scalar(mut scalar) => { let anchor = ptr::null(); let tag = scalar.tag.as_mut().map_or_else(ptr::null, |tag| { tag.push('\0'); tag.as_ptr() }); let value = scalar.value.as_ptr(); let length = scalar.value.len() as i32; let plain_implicit = tag.is_null(); let quoted_implicit = tag.is_null(); let style = match scalar.style { ScalarStyle::Any => sys::YAML_ANY_SCALAR_STYLE, ScalarStyle::Plain => sys::YAML_PLAIN_SCALAR_STYLE, ScalarStyle::SingleQuoted => sys::YAML_SINGLE_QUOTED_SCALAR_STYLE, ScalarStyle::Literal => sys::YAML_LITERAL_SCALAR_STYLE, }; sys::yaml_scalar_event_initialize( sys_event, anchor, tag, value, length, plain_implicit, quoted_implicit, style, ) } Event::SequenceStart(mut sequence) => { let anchor = ptr::null(); let tag = sequence.tag.as_mut().map_or_else(ptr::null, |tag| { tag.push('\0'); tag.as_ptr() }); let implicit = tag.is_null(); let style = sys::YAML_ANY_SEQUENCE_STYLE; sys::yaml_sequence_start_event_initialize( sys_event, anchor, tag, implicit, style, ) } Event::SequenceEnd => sys::yaml_sequence_end_event_initialize(sys_event), Event::MappingStart(mut mapping) => { let anchor = ptr::null(); let tag = mapping.tag.as_mut().map_or_else(ptr::null, |tag| { tag.push('\0'); tag.as_ptr() }); let implicit = tag.is_null(); let style = sys::YAML_ANY_MAPPING_STYLE; sys::yaml_mapping_start_event_initialize( sys_event, anchor, tag, implicit, style, ) } Event::MappingEnd => sys::yaml_mapping_end_event_initialize(sys_event), }; if initialize_status.fail { return Err(Error::Libyaml(libyaml::Error::emit_error(emitter))); } if sys::yaml_emitter_emit(emitter, sys_event).fail { return Err(self.error()); } } Ok(()) } pub fn flush(&mut self) -> Result<(), Error> { unsafe { let emitter = addr_of_mut!((*self.pin.ptr).sys); if sys::yaml_emitter_flush(emitter).fail { return Err(self.error()); } } Ok(()) } pub fn into_inner(self) -> Box { let sink = Box::new(io::sink()); unsafe { mem::replace(&mut (*self.pin.ptr).write, sink) } } fn error(&mut self) -> Error { let emitter = unsafe { &mut *self.pin.ptr }; if let Some(write_error) = emitter.write_error.take() { Error::Io(write_error) } else { Error::Libyaml(unsafe { libyaml::Error::emit_error(&emitter.sys) }) } } } unsafe fn write_handler(data: *mut c_void, buffer: *mut u8, size: u64) -> i32 { let data = data.cast::(); match io::Write::write_all(unsafe { &mut *(*data).write }, unsafe { slice::from_raw_parts(buffer, size as usize) }) { Ok(()) => 1, Err(err) => { unsafe { (*data).write_error = Some(err); } 0 } } } impl<'a> Drop for EmitterPinned<'a> { fn drop(&mut self) { unsafe { sys::yaml_emitter_delete(&mut self.sys) } } } serde_norway-0.9.38/src/libyaml/error.rs000064400000000000000000000126411046102023000163510ustar 00000000000000use crate::libyaml::cstr::CStr; use std::fmt::{self, Debug, Display}; use std::mem::MaybeUninit; use std::ptr::NonNull; use unsafe_libyaml as sys; pub(crate) type Result = std::result::Result; pub(crate) struct Error { kind: sys::yaml_error_type_t, problem: CStr<'static>, problem_offset: u64, problem_mark: Mark, context: Option>, context_mark: Mark, } impl Error { pub unsafe fn parse_error(parser: *const sys::yaml_parser_t) -> Self { Error { kind: unsafe { (*parser).error }, problem: match NonNull::new(unsafe { (*parser).problem as *mut _ }) { Some(problem) => unsafe { CStr::from_ptr(problem) }, None => CStr::from_bytes_with_nul(b"libyaml parser failed but there is no error\0"), }, problem_offset: unsafe { (*parser).problem_offset }, problem_mark: Mark { sys: unsafe { (*parser).problem_mark }, }, context: match NonNull::new(unsafe { (*parser).context as *mut _ }) { Some(context) => Some(unsafe { CStr::from_ptr(context) }), None => None, }, context_mark: Mark { sys: unsafe { (*parser).context_mark }, }, } } pub unsafe fn emit_error(emitter: *const sys::yaml_emitter_t) -> Self { Error { kind: unsafe { (*emitter).error }, problem: match NonNull::new(unsafe { (*emitter).problem as *mut _ }) { Some(problem) => unsafe { CStr::from_ptr(problem) }, None => { CStr::from_bytes_with_nul(b"libyaml emitter failed but there is no error\0") } }, problem_offset: 0, problem_mark: Mark { sys: unsafe { MaybeUninit::::zeroed().assume_init() }, }, context: None, context_mark: Mark { sys: unsafe { MaybeUninit::::zeroed().assume_init() }, }, } } pub fn mark(&self) -> Mark { self.problem_mark } } impl Display for Error { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{}", self.problem)?; if self.problem_mark.sys.line != 0 || self.problem_mark.sys.column != 0 { write!(formatter, " at {}", self.problem_mark)?; } else if self.problem_offset != 0 { write!(formatter, " at position {}", self.problem_offset)?; } if let Some(context) = &self.context { write!(formatter, ", {}", context)?; if (self.context_mark.sys.line != 0 || self.context_mark.sys.column != 0) && (self.context_mark.sys.line != self.problem_mark.sys.line || self.context_mark.sys.column != self.problem_mark.sys.column) { write!(formatter, " at {}", self.context_mark)?; } } Ok(()) } } impl Debug for Error { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Error"); if let Some(kind) = match self.kind { sys::YAML_MEMORY_ERROR => Some("MEMORY"), sys::YAML_READER_ERROR => Some("READER"), sys::YAML_SCANNER_ERROR => Some("SCANNER"), sys::YAML_PARSER_ERROR => Some("PARSER"), sys::YAML_COMPOSER_ERROR => Some("COMPOSER"), sys::YAML_WRITER_ERROR => Some("WRITER"), sys::YAML_EMITTER_ERROR => Some("EMITTER"), _ => None, } { formatter.field("kind", &format_args!("{}", kind)); } formatter.field("problem", &self.problem); if self.problem_mark.sys.line != 0 || self.problem_mark.sys.column != 0 { formatter.field("problem_mark", &self.problem_mark); } else if self.problem_offset != 0 { formatter.field("problem_offset", &self.problem_offset); } if let Some(context) = &self.context { formatter.field("context", context); if self.context_mark.sys.line != 0 || self.context_mark.sys.column != 0 { formatter.field("context_mark", &self.context_mark); } } formatter.finish() } } #[derive(Copy, Clone)] pub(crate) struct Mark { pub(super) sys: sys::yaml_mark_t, } impl Mark { pub fn index(&self) -> u64 { self.sys.index } pub fn line(&self) -> u64 { self.sys.line } pub fn column(&self) -> u64 { self.sys.column } } impl Display for Mark { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.sys.line != 0 || self.sys.column != 0 { write!( formatter, "line {} column {}", self.sys.line + 1, self.sys.column + 1, ) } else { write!(formatter, "position {}", self.sys.index) } } } impl Debug for Mark { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Mark"); if self.sys.line != 0 || self.sys.column != 0 { formatter.field("line", &(self.sys.line + 1)); formatter.field("column", &(self.sys.column + 1)); } else { formatter.field("index", &self.sys.index); } formatter.finish() } } serde_norway-0.9.38/src/libyaml/mod.rs000064400000000000000000000001521046102023000157710ustar 00000000000000mod cstr; pub mod emitter; pub mod error; pub mod parser; pub mod tag; mod util; use self::error::Error; serde_norway-0.9.38/src/libyaml/parser.rs000064400000000000000000000145211046102023000165130ustar 00000000000000use crate::libyaml::cstr::{self, CStr}; use crate::libyaml::error::{Error, Mark, Result}; use crate::libyaml::tag::Tag; use crate::libyaml::util::Owned; use std::borrow::Cow; use std::fmt::{self, Debug}; use std::mem::MaybeUninit; use std::ptr::{addr_of_mut, NonNull}; use std::slice; use unsafe_libyaml as sys; pub(crate) struct Parser<'input> { pin: Owned>, } struct ParserPinned<'input> { sys: sys::yaml_parser_t, input: Cow<'input, [u8]>, } #[derive(Debug)] pub(crate) enum Event<'input> { StreamStart, StreamEnd, DocumentStart, DocumentEnd, Alias(Anchor), Scalar(Scalar<'input>), SequenceStart(SequenceStart), SequenceEnd, MappingStart(MappingStart), MappingEnd, } pub(crate) struct Scalar<'input> { pub anchor: Option, pub tag: Option, pub value: Box<[u8]>, pub style: ScalarStyle, pub repr: Option<&'input [u8]>, } #[derive(Debug)] pub(crate) struct SequenceStart { pub anchor: Option, pub tag: Option, } #[derive(Debug)] pub(crate) struct MappingStart { pub anchor: Option, pub tag: Option, } #[derive(Ord, PartialOrd, Eq, PartialEq)] pub(crate) struct Anchor(Box<[u8]>); #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub(crate) enum ScalarStyle { Plain, SingleQuoted, DoubleQuoted, Literal, Folded, } impl<'input> Parser<'input> { pub fn new(input: Cow<'input, [u8]>) -> Parser<'input> { let owned = Owned::::new_uninit(); let pin = unsafe { let parser = addr_of_mut!((*owned.ptr).sys); if sys::yaml_parser_initialize(parser).fail { panic!("malloc error: {}", Error::parse_error(parser)); } sys::yaml_parser_set_encoding(parser, sys::YAML_UTF8_ENCODING); sys::yaml_parser_set_input_string(parser, input.as_ptr(), input.len() as u64); addr_of_mut!((*owned.ptr).input).write(input); Owned::assume_init(owned) }; Parser { pin } } pub fn next(&mut self) -> Result<(Event<'input>, Mark)> { let mut event = MaybeUninit::::uninit(); unsafe { let parser = addr_of_mut!((*self.pin.ptr).sys); if (*parser).error != sys::YAML_NO_ERROR { return Err(Error::parse_error(parser)); } let event = event.as_mut_ptr(); if sys::yaml_parser_parse(parser, event).fail { return Err(Error::parse_error(parser)); } let ret = convert_event(&*event, &(*self.pin.ptr).input); let mark = Mark { sys: (*event).start_mark, }; sys::yaml_event_delete(event); Ok((ret, mark)) } } } unsafe fn convert_event<'input>( sys: &sys::yaml_event_t, input: &Cow<'input, [u8]>, ) -> Event<'input> { match sys.type_ { sys::YAML_STREAM_START_EVENT => Event::StreamStart, sys::YAML_STREAM_END_EVENT => Event::StreamEnd, sys::YAML_DOCUMENT_START_EVENT => Event::DocumentStart, sys::YAML_DOCUMENT_END_EVENT => Event::DocumentEnd, sys::YAML_ALIAS_EVENT => { Event::Alias(unsafe { optional_anchor(sys.data.alias.anchor) }.unwrap()) } sys::YAML_SCALAR_EVENT => Event::Scalar(Scalar { anchor: unsafe { optional_anchor(sys.data.scalar.anchor) }, tag: unsafe { optional_tag(sys.data.scalar.tag) }, value: Box::from(unsafe { slice::from_raw_parts(sys.data.scalar.value, sys.data.scalar.length as usize) }), style: match unsafe { sys.data.scalar.style } { sys::YAML_PLAIN_SCALAR_STYLE => ScalarStyle::Plain, sys::YAML_SINGLE_QUOTED_SCALAR_STYLE => ScalarStyle::SingleQuoted, sys::YAML_DOUBLE_QUOTED_SCALAR_STYLE => ScalarStyle::DoubleQuoted, sys::YAML_LITERAL_SCALAR_STYLE => ScalarStyle::Literal, sys::YAML_FOLDED_SCALAR_STYLE => ScalarStyle::Folded, sys::YAML_ANY_SCALAR_STYLE | _ => unreachable!(), }, repr: if let Cow::Borrowed(input) = input { Some(&input[sys.start_mark.index as usize..sys.end_mark.index as usize]) } else { None }, }), sys::YAML_SEQUENCE_START_EVENT => Event::SequenceStart(SequenceStart { anchor: unsafe { optional_anchor(sys.data.sequence_start.anchor) }, tag: unsafe { optional_tag(sys.data.sequence_start.tag) }, }), sys::YAML_SEQUENCE_END_EVENT => Event::SequenceEnd, sys::YAML_MAPPING_START_EVENT => Event::MappingStart(MappingStart { anchor: unsafe { optional_anchor(sys.data.mapping_start.anchor) }, tag: unsafe { optional_tag(sys.data.mapping_start.tag) }, }), sys::YAML_MAPPING_END_EVENT => Event::MappingEnd, sys::YAML_NO_EVENT => unreachable!(), _ => unimplemented!(), } } unsafe fn optional_anchor(anchor: *const u8) -> Option { let ptr = NonNull::new(anchor as *mut i8)?; let cstr = unsafe { CStr::from_ptr(ptr) }; Some(Anchor(Box::from(cstr.to_bytes()))) } unsafe fn optional_tag(tag: *const u8) -> Option { let ptr = NonNull::new(tag as *mut i8)?; let cstr = unsafe { CStr::from_ptr(ptr) }; Some(Tag(Box::from(cstr.to_bytes()))) } impl<'input> Debug for Scalar<'input> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let Scalar { anchor, tag, value, style, repr: _, } = self; struct LossySlice<'a>(&'a [u8]); impl<'a> Debug for LossySlice<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { cstr::debug_lossy(self.0, formatter) } } formatter .debug_struct("Scalar") .field("anchor", anchor) .field("tag", tag) .field("value", &LossySlice(value)) .field("style", style) .finish() } } impl Debug for Anchor { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { cstr::debug_lossy(&self.0, formatter) } } impl<'input> Drop for ParserPinned<'input> { fn drop(&mut self) { unsafe { sys::yaml_parser_delete(&mut self.sys) } } } serde_norway-0.9.38/src/libyaml/tag.rs000064400000000000000000000016321046102023000157710ustar 00000000000000use crate::libyaml::cstr; use std::fmt::{self, Debug}; use std::ops::Deref; #[derive(Ord, PartialOrd, Eq, PartialEq)] pub(crate) struct Tag(pub(in crate::libyaml) Box<[u8]>); impl Tag { pub const NULL: &'static str = "tag:yaml.org,2002:null"; pub const BOOL: &'static str = "tag:yaml.org,2002:bool"; pub const INT: &'static str = "tag:yaml.org,2002:int"; pub const FLOAT: &'static str = "tag:yaml.org,2002:float"; } impl Tag { pub fn starts_with(&self, prefix: &str) -> bool { self.0.starts_with(prefix.as_bytes()) } } impl PartialEq for Tag { fn eq(&self, other: &str) -> bool { *self.0 == *other.as_bytes() } } impl Deref for Tag { type Target = [u8]; fn deref(&self) -> &Self::Target { &self.0 } } impl Debug for Tag { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { cstr::debug_lossy(&self.0, formatter) } } serde_norway-0.9.38/src/libyaml/util.rs000064400000000000000000000022631046102023000161740ustar 00000000000000use std::marker::PhantomData; use std::mem::{self, MaybeUninit}; use std::ops::Deref; use std::ptr::{addr_of, NonNull}; pub(crate) struct Owned { ptr: NonNull, marker: PhantomData>, } impl Owned { pub fn new_uninit() -> Owned, T> { // FIXME: use Box::new_uninit when stable let boxed = Box::new(MaybeUninit::::uninit()); Owned { ptr: unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) }, marker: PhantomData, } } pub unsafe fn assume_init(definitely_init: Owned, T>) -> Owned { let ptr = definitely_init.ptr; mem::forget(definitely_init); Owned { ptr: ptr.cast(), marker: PhantomData, } } } #[repr(transparent)] pub(crate) struct InitPtr { pub ptr: *mut T, } impl Deref for Owned { type Target = InitPtr; fn deref(&self) -> &Self::Target { unsafe { &*addr_of!(self.ptr).cast::>() } } } impl Drop for Owned { fn drop(&mut self) { let _ = unsafe { Box::from_raw(self.ptr.as_ptr()) }; } } serde_norway-0.9.38/src/loader.rs000064400000000000000000000106131046102023000150320ustar 00000000000000use crate::de::{Event, Progress}; use crate::error::{self, Error, ErrorImpl, Result}; use crate::libyaml::error::Mark; use crate::libyaml::parser::{Event as YamlEvent, Parser}; use std::borrow::Cow; use std::collections::BTreeMap; use std::sync::Arc; pub(crate) struct Loader<'input> { parser: Option>, document_count: usize, } pub(crate) struct Document<'input> { pub events: Vec<(Event<'input>, Mark)>, pub error: Option>, /// Map from alias id to index in events. pub aliases: BTreeMap, } impl<'input> Loader<'input> { pub fn new(progress: Progress<'input>) -> Result { let input = match progress { Progress::Str(s) => Cow::Borrowed(s.as_bytes()), Progress::Slice(bytes) => Cow::Borrowed(bytes), Progress::Read(mut rdr) => { let mut buffer = Vec::new(); if let Err(io_error) = rdr.read_to_end(&mut buffer) { return Err(error::new(ErrorImpl::Io(io_error))); } Cow::Owned(buffer) } Progress::Iterable(_) | Progress::Document(_) => unreachable!(), Progress::Fail(err) => return Err(error::shared(err)), }; Ok(Loader { parser: Some(Parser::new(input)), document_count: 0, }) } pub fn next_document(&mut self) -> Option> { let parser = match &mut self.parser { Some(parser) => parser, None => return None, }; let first = self.document_count == 0; self.document_count += 1; let mut anchors = BTreeMap::new(); let mut document = Document { events: Vec::new(), error: None, aliases: BTreeMap::new(), }; loop { let (event, mark) = match parser.next() { Ok((event, mark)) => (event, mark), Err(err) => { document.error = Some(Error::from(err).shared()); return Some(document); } }; let event = match event { YamlEvent::StreamStart => continue, YamlEvent::StreamEnd => { self.parser = None; return if first { if document.events.is_empty() { document.events.push((Event::Void, mark)); } Some(document) } else { None }; } YamlEvent::DocumentStart => continue, YamlEvent::DocumentEnd => return Some(document), YamlEvent::Alias(alias) => match anchors.get(&alias) { Some(id) => Event::Alias(*id), None => { document.error = Some(error::new(ErrorImpl::UnknownAnchor(mark)).shared()); return Some(document); } }, YamlEvent::Scalar(mut scalar) => { if let Some(anchor) = scalar.anchor.take() { let id = anchors.len(); anchors.insert(anchor, id); document.aliases.insert(id, document.events.len()); } Event::Scalar(scalar) } YamlEvent::SequenceStart(mut sequence_start) => { if let Some(anchor) = sequence_start.anchor.take() { let id = anchors.len(); anchors.insert(anchor, id); document.aliases.insert(id, document.events.len()); } Event::SequenceStart(sequence_start) } YamlEvent::SequenceEnd => Event::SequenceEnd, YamlEvent::MappingStart(mut mapping_start) => { if let Some(anchor) = mapping_start.anchor.take() { let id = anchors.len(); anchors.insert(anchor, id); document.aliases.insert(id, document.events.len()); } Event::MappingStart(mapping_start) } YamlEvent::MappingEnd => Event::MappingEnd, }; document.events.push((event, mark)); } } } serde_norway-0.9.38/src/mapping.rs000064400000000000000000000632441046102023000152270ustar 00000000000000//! A YAML mapping and its iterator types. use crate::{private, Value}; use indexmap::IndexMap; use serde::{Deserialize, Deserializer, Serialize}; use std::cmp::Ordering; use std::collections::hash_map::DefaultHasher; use std::fmt::{self, Display}; use std::hash::{Hash, Hasher}; use std::mem; /// A YAML mapping in which the keys and values are both `serde_norway::Value`. #[derive(Clone, Default, Eq, PartialEq)] pub struct Mapping { map: IndexMap, } impl Mapping { /// Creates an empty YAML map. #[inline] pub fn new() -> Self { Self::default() } /// Creates an empty YAML map with the given initial capacity. #[inline] pub fn with_capacity(capacity: usize) -> Self { Mapping { map: IndexMap::with_capacity(capacity), } } /// Reserves capacity for at least `additional` more elements to be inserted /// into the map. The map may reserve more space to avoid frequent /// allocations. /// /// # Panics /// /// Panics if the new allocation size overflows `usize`. #[inline] pub fn reserve(&mut self, additional: usize) { self.map.reserve(additional); } /// Shrinks the capacity of the map as much as possible. It will drop down /// as much as possible while maintaining the internal rules and possibly /// leaving some space in accordance with the resize policy. #[inline] pub fn shrink_to_fit(&mut self) { self.map.shrink_to_fit(); } /// Inserts a key-value pair into the map. If the key already existed, the /// old value is returned. #[inline] pub fn insert(&mut self, k: Value, v: Value) -> Option { self.map.insert(k, v) } /// Checks if the map contains the given key. #[inline] pub fn contains_key(&self, index: I) -> bool { index.is_key_into(self) } /// Returns the value corresponding to the key in the map. #[inline] pub fn get(&self, index: I) -> Option<&Value> { index.index_into(self) } /// Returns the mutable reference corresponding to the key in the map. #[inline] pub fn get_mut(&mut self, index: I) -> Option<&mut Value> { index.index_into_mut(self) } /// Gets the given key's corresponding entry in the map for insertion and/or /// in-place manipulation. #[inline] pub fn entry(&mut self, k: Value) -> Entry { match self.map.entry(k) { indexmap::map::Entry::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied }), indexmap::map::Entry::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant }), } } /// Removes and returns the value corresponding to the key from the map. /// /// This is equivalent to [`.swap_remove(index)`][Self::swap_remove], /// replacing this entry's position with the last element. If you need to /// preserve the relative order of the keys in the map, use /// [`.shift_remove(key)`][Self::shift_remove] instead. #[inline] pub fn remove(&mut self, index: I) -> Option { self.swap_remove(index) } /// Remove and return the key-value pair. /// /// This is equivalent to [`.swap_remove_entry(index)`][Self::swap_remove_entry], /// replacing this entry's position with the last element. If you need to /// preserve the relative order of the keys in the map, use /// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead. #[inline] pub fn remove_entry(&mut self, index: I) -> Option<(Value, Value)> { self.swap_remove_entry(index) } /// Removes and returns the value corresponding to the key from the map. /// /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the /// last element of the map and popping it off. This perturbs the position /// of what used to be the last element! #[inline] pub fn swap_remove(&mut self, index: I) -> Option { index.swap_remove_from(self) } /// Remove and return the key-value pair. /// /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the /// last element of the map and popping it off. This perturbs the position /// of what used to be the last element! #[inline] pub fn swap_remove_entry(&mut self, index: I) -> Option<(Value, Value)> { index.swap_remove_entry_from(self) } /// Removes and returns the value corresponding to the key from the map. /// /// Like [`Vec::remove`], the entry is removed by shifting all of the /// elements that follow it, preserving their relative order. This perturbs /// the index of all of those elements! #[inline] pub fn shift_remove(&mut self, index: I) -> Option { index.shift_remove_from(self) } /// Remove and return the key-value pair. /// /// Like [`Vec::remove`], the entry is removed by shifting all of the /// elements that follow it, preserving their relative order. This perturbs /// the index of all of those elements! #[inline] pub fn shift_remove_entry(&mut self, index: I) -> Option<(Value, Value)> { index.shift_remove_entry_from(self) } /// Scan through each key-value pair in the map and keep those where the /// closure `keep` returns true. #[inline] pub fn retain(&mut self, keep: F) where F: FnMut(&Value, &mut Value) -> bool, { self.map.retain(keep); } /// Returns the maximum number of key-value pairs the map can hold without /// reallocating. #[inline] pub fn capacity(&self) -> usize { self.map.capacity() } /// Returns the number of key-value pairs in the map. #[inline] pub fn len(&self) -> usize { self.map.len() } /// Returns whether the map is currently empty. #[inline] pub fn is_empty(&self) -> bool { self.map.is_empty() } /// Clears the map of all key-value pairs. #[inline] pub fn clear(&mut self) { self.map.clear(); } /// Returns a double-ended iterator visiting all key-value pairs in order of /// insertion. Iterator element type is `(&'a Value, &'a Value)`. #[inline] pub fn iter(&self) -> Iter { Iter { iter: self.map.iter(), } } /// Returns a double-ended iterator visiting all key-value pairs in order of /// insertion. Iterator element type is `(&'a Value, &'a mut ValuE)`. #[inline] pub fn iter_mut(&mut self) -> IterMut { IterMut { iter: self.map.iter_mut(), } } /// Return an iterator over the keys of the map. pub fn keys(&self) -> Keys { Keys { iter: self.map.keys(), } } /// Return an owning iterator over the keys of the map. pub fn into_keys(self) -> IntoKeys { IntoKeys { iter: self.map.into_keys(), } } /// Return an iterator over the values of the map. pub fn values(&self) -> Values { Values { iter: self.map.values(), } } /// Return an iterator over mutable references to the values of the map. pub fn values_mut(&mut self) -> ValuesMut { ValuesMut { iter: self.map.values_mut(), } } /// Return an owning iterator over the values of the map. pub fn into_values(self) -> IntoValues { IntoValues { iter: self.map.into_values(), } } } /// A type that can be used to index into a `serde_norway::Mapping`. See the /// methods `get`, `get_mut`, `contains_key`, and `remove` of `Value`. /// /// This trait is sealed and cannot be implemented for types outside of /// `serde_norway`. pub trait Index: private::Sealed { #[doc(hidden)] fn is_key_into(&self, v: &Mapping) -> bool; #[doc(hidden)] fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value>; #[doc(hidden)] fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value>; #[doc(hidden)] fn swap_remove_from(&self, v: &mut Mapping) -> Option; #[doc(hidden)] fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>; #[doc(hidden)] fn shift_remove_from(&self, v: &mut Mapping) -> Option; #[doc(hidden)] fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>; } struct HashLikeValue<'a>(&'a str); impl<'a> indexmap::Equivalent for HashLikeValue<'a> { fn equivalent(&self, key: &Value) -> bool { match key { Value::String(string) => self.0 == string, _ => false, } } } // NOTE: This impl must be consistent with Value's Hash impl. impl<'a> Hash for HashLikeValue<'a> { fn hash(&self, state: &mut H) { const STRING: Value = Value::String(String::new()); mem::discriminant(&STRING).hash(state); self.0.hash(state); } } impl Index for Value { fn is_key_into(&self, v: &Mapping) -> bool { v.map.contains_key(self) } fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value> { v.map.get(self) } fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { v.map.get_mut(self) } fn swap_remove_from(&self, v: &mut Mapping) -> Option { v.map.swap_remove(self) } fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { v.map.swap_remove_entry(self) } fn shift_remove_from(&self, v: &mut Mapping) -> Option { v.map.shift_remove(self) } fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { v.map.shift_remove_entry(self) } } impl Index for str { fn is_key_into(&self, v: &Mapping) -> bool { v.map.contains_key(&HashLikeValue(self)) } fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value> { v.map.get(&HashLikeValue(self)) } fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { v.map.get_mut(&HashLikeValue(self)) } fn swap_remove_from(&self, v: &mut Mapping) -> Option { v.map.swap_remove(&HashLikeValue(self)) } fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { v.map.swap_remove_entry(&HashLikeValue(self)) } fn shift_remove_from(&self, v: &mut Mapping) -> Option { v.map.shift_remove(&HashLikeValue(self)) } fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { v.map.shift_remove_entry(&HashLikeValue(self)) } } impl Index for String { fn is_key_into(&self, v: &Mapping) -> bool { self.as_str().is_key_into(v) } fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value> { self.as_str().index_into(v) } fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { self.as_str().index_into_mut(v) } fn swap_remove_from(&self, v: &mut Mapping) -> Option { self.as_str().swap_remove_from(v) } fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { self.as_str().swap_remove_entry_from(v) } fn shift_remove_from(&self, v: &mut Mapping) -> Option { self.as_str().shift_remove_from(v) } fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { self.as_str().shift_remove_entry_from(v) } } impl Index for &T where T: ?Sized + Index, { fn is_key_into(&self, v: &Mapping) -> bool { (**self).is_key_into(v) } fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value> { (**self).index_into(v) } fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { (**self).index_into_mut(v) } fn swap_remove_from(&self, v: &mut Mapping) -> Option { (**self).swap_remove_from(v) } fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { (**self).swap_remove_entry_from(v) } fn shift_remove_from(&self, v: &mut Mapping) -> Option { (**self).shift_remove_from(v) } fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { (**self).shift_remove_entry_from(v) } } #[allow(clippy::derived_hash_with_manual_eq)] impl Hash for Mapping { fn hash(&self, state: &mut H) { // Hash the kv pairs in a way that is not sensitive to their order. let mut xor = 0; for (k, v) in self { let mut hasher = DefaultHasher::new(); k.hash(&mut hasher); v.hash(&mut hasher); xor ^= hasher.finish(); } xor.hash(state); } } impl PartialOrd for Mapping { fn partial_cmp(&self, other: &Self) -> Option { let mut self_entries = Vec::from_iter(self); let mut other_entries = Vec::from_iter(other); // Sort in an arbitrary order that is consistent with Value's PartialOrd // impl. fn total_cmp(a: &Value, b: &Value) -> Ordering { match (a, b) { (Value::Null, Value::Null) => Ordering::Equal, (Value::Null, _) => Ordering::Less, (_, Value::Null) => Ordering::Greater, (Value::Bool(a), Value::Bool(b)) => a.cmp(b), (Value::Bool(_), _) => Ordering::Less, (_, Value::Bool(_)) => Ordering::Greater, (Value::Number(a), Value::Number(b)) => a.total_cmp(b), (Value::Number(_), _) => Ordering::Less, (_, Value::Number(_)) => Ordering::Greater, (Value::String(a), Value::String(b)) => a.cmp(b), (Value::String(_), _) => Ordering::Less, (_, Value::String(_)) => Ordering::Greater, (Value::Sequence(a), Value::Sequence(b)) => iter_cmp_by(a, b, total_cmp), (Value::Sequence(_), _) => Ordering::Less, (_, Value::Sequence(_)) => Ordering::Greater, (Value::Mapping(a), Value::Mapping(b)) => { iter_cmp_by(a, b, |(ak, av), (bk, bv)| { total_cmp(ak, bk).then_with(|| total_cmp(av, bv)) }) } (Value::Mapping(_), _) => Ordering::Less, (_, Value::Mapping(_)) => Ordering::Greater, (Value::Tagged(a), Value::Tagged(b)) => a .tag .cmp(&b.tag) .then_with(|| total_cmp(&a.value, &b.value)), } } fn iter_cmp_by(this: I, other: I, mut cmp: F) -> Ordering where I: IntoIterator, F: FnMut(I::Item, I::Item) -> Ordering, { let mut this = this.into_iter(); let mut other = other.into_iter(); loop { let x = match this.next() { None => { if other.next().is_none() { return Ordering::Equal; } else { return Ordering::Less; } } Some(val) => val, }; let y = match other.next() { None => return Ordering::Greater, Some(val) => val, }; match cmp(x, y) { Ordering::Equal => {} non_eq => return non_eq, } } } // While sorting by map key, we get to assume that no two keys are // equal, otherwise they wouldn't both be in the map. This is not a safe // assumption outside of this situation. let total_cmp = |&(a, _): &_, &(b, _): &_| total_cmp(a, b); self_entries.sort_by(total_cmp); other_entries.sort_by(total_cmp); self_entries.partial_cmp(&other_entries) } } impl std::ops::Index for Mapping where I: Index, { type Output = Value; #[inline] #[track_caller] fn index(&self, index: I) -> &Value { index.index_into(self).unwrap() } } impl std::ops::IndexMut for Mapping where I: Index, { #[inline] #[track_caller] fn index_mut(&mut self, index: I) -> &mut Value { index.index_into_mut(self).unwrap() } } impl Extend<(Value, Value)> for Mapping { #[inline] fn extend>(&mut self, iter: I) { self.map.extend(iter); } } impl FromIterator<(Value, Value)> for Mapping { #[inline] fn from_iter>(iter: I) -> Self { Mapping { map: IndexMap::from_iter(iter), } } } macro_rules! delegate_iterator { (($name:ident $($generics:tt)*) => $item:ty) => { impl $($generics)* Iterator for $name $($generics)* { type Item = $item; #[inline] fn next(&mut self) -> Option { self.iter.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl $($generics)* ExactSizeIterator for $name $($generics)* { #[inline] fn len(&self) -> usize { self.iter.len() } } } } /// Iterator over `&serde_norway::Mapping`. pub struct Iter<'a> { iter: indexmap::map::Iter<'a, Value, Value>, } delegate_iterator!((Iter<'a>) => (&'a Value, &'a Value)); impl<'a> IntoIterator for &'a Mapping { type Item = (&'a Value, &'a Value); type IntoIter = Iter<'a>; #[inline] fn into_iter(self) -> Self::IntoIter { Iter { iter: self.map.iter(), } } } /// Iterator over `&mut serde_norway::Mapping`. pub struct IterMut<'a> { iter: indexmap::map::IterMut<'a, Value, Value>, } delegate_iterator!((IterMut<'a>) => (&'a Value, &'a mut Value)); impl<'a> IntoIterator for &'a mut Mapping { type Item = (&'a Value, &'a mut Value); type IntoIter = IterMut<'a>; #[inline] fn into_iter(self) -> Self::IntoIter { IterMut { iter: self.map.iter_mut(), } } } /// Iterator over `serde_norway::Mapping` by value. pub struct IntoIter { iter: indexmap::map::IntoIter, } delegate_iterator!((IntoIter) => (Value, Value)); impl IntoIterator for Mapping { type Item = (Value, Value); type IntoIter = IntoIter; #[inline] fn into_iter(self) -> Self::IntoIter { IntoIter { iter: self.map.into_iter(), } } } /// Iterator of the keys of a `&serde_norway::Mapping`. pub struct Keys<'a> { iter: indexmap::map::Keys<'a, Value, Value>, } delegate_iterator!((Keys<'a>) => &'a Value); /// Iterator of the keys of a `serde_norway::Mapping`. pub struct IntoKeys { iter: indexmap::map::IntoKeys, } delegate_iterator!((IntoKeys) => Value); /// Iterator of the values of a `&serde_norway::Mapping`. pub struct Values<'a> { iter: indexmap::map::Values<'a, Value, Value>, } delegate_iterator!((Values<'a>) => &'a Value); /// Iterator of the values of a `&mut serde_norway::Mapping`. pub struct ValuesMut<'a> { iter: indexmap::map::ValuesMut<'a, Value, Value>, } delegate_iterator!((ValuesMut<'a>) => &'a mut Value); /// Iterator of the values of a `serde_norway::Mapping`. pub struct IntoValues { iter: indexmap::map::IntoValues, } delegate_iterator!((IntoValues) => Value); /// Entry for an existing key-value pair or a vacant location to insert one. pub enum Entry<'a> { /// Existing slot with equivalent key. Occupied(OccupiedEntry<'a>), /// Vacant slot (no equivalent key in the map). Vacant(VacantEntry<'a>), } /// A view into an occupied entry in a [`Mapping`]. It is part of the [`Entry`] /// enum. pub struct OccupiedEntry<'a> { occupied: indexmap::map::OccupiedEntry<'a, Value, Value>, } /// A view into a vacant entry in a [`Mapping`]. It is part of the [`Entry`] /// enum. pub struct VacantEntry<'a> { vacant: indexmap::map::VacantEntry<'a, Value, Value>, } impl<'a> Entry<'a> { /// Returns a reference to this entry's key. pub fn key(&self) -> &Value { match self { Entry::Vacant(e) => e.key(), Entry::Occupied(e) => e.key(), } } /// Ensures a value is in the entry by inserting the default if empty, and /// returns a mutable reference to the value in the entry. pub fn or_insert(self, default: Value) -> &'a mut Value { match self { Entry::Vacant(entry) => entry.insert(default), Entry::Occupied(entry) => entry.into_mut(), } } /// Ensures a value is in the entry by inserting the result of the default /// function if empty, and returns a mutable reference to the value in the /// entry. pub fn or_insert_with(self, default: F) -> &'a mut Value where F: FnOnce() -> Value, { match self { Entry::Vacant(entry) => entry.insert(default()), Entry::Occupied(entry) => entry.into_mut(), } } /// Provides in-place mutable access to an occupied entry before any /// potential inserts into the map. pub fn and_modify(self, f: F) -> Self where F: FnOnce(&mut Value), { match self { Entry::Occupied(mut entry) => { f(entry.get_mut()); Entry::Occupied(entry) } Entry::Vacant(entry) => Entry::Vacant(entry), } } } impl<'a> OccupiedEntry<'a> { /// Gets a reference to the key in the entry. #[inline] pub fn key(&self) -> &Value { self.occupied.key() } /// Gets a reference to the value in the entry. #[inline] pub fn get(&self) -> &Value { self.occupied.get() } /// Gets a mutable reference to the value in the entry. #[inline] pub fn get_mut(&mut self) -> &mut Value { self.occupied.get_mut() } /// Converts the entry into a mutable reference to its value. #[inline] pub fn into_mut(self) -> &'a mut Value { self.occupied.into_mut() } /// Sets the value of the entry with the `OccupiedEntry`'s key, and returns /// the entry's old value. #[inline] pub fn insert(&mut self, value: Value) -> Value { self.occupied.insert(value) } /// Takes the value of the entry out of the map, and returns it. #[inline] pub fn remove(self) -> Value { self.occupied.swap_remove() } /// Remove and return the key, value pair stored in the map for this entry. #[inline] pub fn remove_entry(self) -> (Value, Value) { self.occupied.swap_remove_entry() } } impl<'a> VacantEntry<'a> { /// Gets a reference to the key that would be used when inserting a value /// through the VacantEntry. #[inline] pub fn key(&self) -> &Value { self.vacant.key() } /// Takes ownership of the key, leaving the entry vacant. #[inline] pub fn into_key(self) -> Value { self.vacant.into_key() } /// Sets the value of the entry with the VacantEntry's key, and returns a /// mutable reference to it. #[inline] pub fn insert(self, value: Value) -> &'a mut Value { self.vacant.insert(value) } } impl Serialize for Mapping { #[inline] fn serialize(&self, serializer: S) -> Result { use serde::ser::SerializeMap; let mut map_serializer = serializer.serialize_map(Some(self.len()))?; for (k, v) in self { map_serializer.serialize_entry(k, v)?; } map_serializer.end() } } impl<'de> Deserialize<'de> for Mapping { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Visitor; impl<'de> serde::de::Visitor<'de> for Visitor { type Value = Mapping; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a YAML mapping") } #[inline] fn visit_unit(self) -> Result where E: serde::de::Error, { Ok(Mapping::new()) } #[inline] fn visit_map(self, mut data: A) -> Result where A: serde::de::MapAccess<'de>, { let mut mapping = Mapping::new(); while let Some(key) = data.next_key()? { match mapping.entry(key) { Entry::Occupied(entry) => { return Err(serde::de::Error::custom(DuplicateKeyError { entry })); } Entry::Vacant(entry) => { let value = data.next_value()?; entry.insert(value); } } } Ok(mapping) } } deserializer.deserialize_map(Visitor) } } struct DuplicateKeyError<'a> { entry: OccupiedEntry<'a>, } impl<'a> Display for DuplicateKeyError<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("duplicate entry ")?; match self.entry.key() { Value::Null => formatter.write_str("with null key"), Value::Bool(boolean) => write!(formatter, "with key `{}`", boolean), Value::Number(number) => write!(formatter, "with key {}", number), Value::String(string) => write!(formatter, "with key {:?}", string), Value::Sequence(_) | Value::Mapping(_) | Value::Tagged(_) => { formatter.write_str("in YAML map") } } } } serde_norway-0.9.38/src/number.rs000064400000000000000000000365501046102023000150640ustar 00000000000000use crate::de; use crate::error::{self, Error, ErrorImpl}; use serde::de::{Unexpected, Visitor}; use serde::{forward_to_deserialize_any, Deserialize, Deserializer, Serialize, Serializer}; use std::cmp::Ordering; use std::fmt::{self, Display}; use std::hash::{Hash, Hasher}; use std::str::FromStr; /// Represents a YAML number, whether integer or floating point. #[derive(Clone, PartialEq, PartialOrd)] pub struct Number { n: N, } // "N" is a prefix of "NegInt"... this is a false positive. // https://github.com/Manishearth/rust-clippy/issues/1241 #[allow(clippy::enum_variant_names)] #[derive(Copy, Clone)] enum N { PosInt(u64), /// Always less than zero. NegInt(i64), /// May be infinite or NaN. Float(f64), } impl Number { /// Returns true if the `Number` is an integer between `i64::MIN` and /// `i64::MAX`. /// /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to /// return the integer value. /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// let big = i64::MAX as u64 + 10; /// let v: serde_norway::Value = serde_norway::from_str(r#" /// a: 64 /// b: 9223372036854775817 /// c: 256.0 /// "#)?; /// /// assert!(v["a"].is_i64()); /// /// // Greater than i64::MAX. /// assert!(!v["b"].is_i64()); /// /// // Numbers with a decimal point are not considered integers. /// assert!(!v["c"].is_i64()); /// # Ok(()) /// # } /// ``` #[inline] #[allow(clippy::cast_sign_loss)] pub fn is_i64(&self) -> bool { match self.n { N::PosInt(v) => v <= i64::MAX as u64, N::NegInt(_) => true, N::Float(_) => false, } } /// Returns true if the `Number` is an integer between zero and `u64::MAX`. /// /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to /// return the integer value. /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// let v: serde_norway::Value = serde_norway::from_str(r#" /// a: 64 /// b: -64 /// c: 256.0 /// "#)?; /// /// assert!(v["a"].is_u64()); /// /// // Negative integer. /// assert!(!v["b"].is_u64()); /// /// // Numbers with a decimal point are not considered integers. /// assert!(!v["c"].is_u64()); /// # Ok(()) /// # } /// ``` #[inline] pub fn is_u64(&self) -> bool { match self.n { N::PosInt(_) => true, N::NegInt(_) | N::Float(_) => false, } } /// Returns true if the `Number` can be represented by f64. /// /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to /// return the floating point value. /// /// Currently this function returns true if and only if both `is_i64` and /// `is_u64` return false but this is not a guarantee in the future. /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// let v: serde_norway::Value = serde_norway::from_str(r#" /// a: 256.0 /// b: 64 /// c: -64 /// "#)?; /// /// assert!(v["a"].is_f64()); /// /// // Integers. /// assert!(!v["b"].is_f64()); /// assert!(!v["c"].is_f64()); /// # Ok(()) /// # } /// ``` #[inline] pub fn is_f64(&self) -> bool { match self.n { N::Float(_) => true, N::PosInt(_) | N::NegInt(_) => false, } } /// If the `Number` is an integer, represent it as i64 if possible. Returns /// None otherwise. /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// let big = i64::MAX as u64 + 10; /// let v: serde_norway::Value = serde_norway::from_str(r#" /// a: 64 /// b: 9223372036854775817 /// c: 256.0 /// "#)?; /// /// assert_eq!(v["a"].as_i64(), Some(64)); /// assert_eq!(v["b"].as_i64(), None); /// assert_eq!(v["c"].as_i64(), None); /// # Ok(()) /// # } /// ``` #[inline] pub fn as_i64(&self) -> Option { match self.n { N::PosInt(n) => { if n <= i64::MAX as u64 { Some(n as i64) } else { None } } N::NegInt(n) => Some(n), N::Float(_) => None, } } /// If the `Number` is an integer, represent it as u64 if possible. Returns /// None otherwise. /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// let v: serde_norway::Value = serde_norway::from_str(r#" /// a: 64 /// b: -64 /// c: 256.0 /// "#)?; /// /// assert_eq!(v["a"].as_u64(), Some(64)); /// assert_eq!(v["b"].as_u64(), None); /// assert_eq!(v["c"].as_u64(), None); /// # Ok(()) /// # } /// ``` #[inline] pub fn as_u64(&self) -> Option { match self.n { N::PosInt(n) => Some(n), N::NegInt(_) | N::Float(_) => None, } } /// Represents the number as f64 if possible. Returns None otherwise. /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// let v: serde_norway::Value = serde_norway::from_str(r#" /// a: 256.0 /// b: 64 /// c: -64 /// "#)?; /// /// assert_eq!(v["a"].as_f64(), Some(256.0)); /// assert_eq!(v["b"].as_f64(), Some(64.0)); /// assert_eq!(v["c"].as_f64(), Some(-64.0)); /// # Ok(()) /// # } /// ``` /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// let v: serde_norway::Value = serde_norway::from_str(".inf")?; /// assert_eq!(v.as_f64(), Some(f64::INFINITY)); /// /// let v: serde_norway::Value = serde_norway::from_str("-.inf")?; /// assert_eq!(v.as_f64(), Some(f64::NEG_INFINITY)); /// /// let v: serde_norway::Value = serde_norway::from_str(".nan")?; /// assert!(v.as_f64().unwrap().is_nan()); /// # Ok(()) /// # } /// ``` #[inline] pub fn as_f64(&self) -> Option { match self.n { N::PosInt(n) => Some(n as f64), N::NegInt(n) => Some(n as f64), N::Float(n) => Some(n), } } /// Returns true if this value is NaN and false otherwise. /// /// ``` /// # use serde_norway::Number; /// # /// assert!(!Number::from(256.0).is_nan()); /// /// assert!(Number::from(f64::NAN).is_nan()); /// /// assert!(!Number::from(f64::INFINITY).is_nan()); /// /// assert!(!Number::from(f64::NEG_INFINITY).is_nan()); /// /// assert!(!Number::from(1).is_nan()); /// ``` #[inline] pub fn is_nan(&self) -> bool { match self.n { N::PosInt(_) | N::NegInt(_) => false, N::Float(f) => f.is_nan(), } } /// Returns true if this value is positive infinity or negative infinity and /// false otherwise. /// /// ``` /// # use serde_norway::Number; /// # /// assert!(!Number::from(256.0).is_infinite()); /// /// assert!(!Number::from(f64::NAN).is_infinite()); /// /// assert!(Number::from(f64::INFINITY).is_infinite()); /// /// assert!(Number::from(f64::NEG_INFINITY).is_infinite()); /// /// assert!(!Number::from(1).is_infinite()); /// ``` #[inline] pub fn is_infinite(&self) -> bool { match self.n { N::PosInt(_) | N::NegInt(_) => false, N::Float(f) => f.is_infinite(), } } /// Returns true if this number is neither infinite nor NaN. /// /// ``` /// # use serde_norway::Number; /// # /// assert!(Number::from(256.0).is_finite()); /// /// assert!(!Number::from(f64::NAN).is_finite()); /// /// assert!(!Number::from(f64::INFINITY).is_finite()); /// /// assert!(!Number::from(f64::NEG_INFINITY).is_finite()); /// /// assert!(Number::from(1).is_finite()); /// ``` #[inline] pub fn is_finite(&self) -> bool { match self.n { N::PosInt(_) | N::NegInt(_) => true, N::Float(f) => f.is_finite(), } } } impl Display for Number { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self.n { N::PosInt(i) => formatter.write_str(itoa::Buffer::new().format(i)), N::NegInt(i) => formatter.write_str(itoa::Buffer::new().format(i)), N::Float(f) if f.is_nan() => formatter.write_str(".nan"), N::Float(f) if f.is_infinite() => { if f.is_sign_negative() { formatter.write_str("-.inf") } else { formatter.write_str(".inf") } } N::Float(f) => formatter.write_str(ryu::Buffer::new().format_finite(f)), } } } impl FromStr for Number { type Err = Error; fn from_str(repr: &str) -> Result { if let Ok(result) = de::visit_int(NumberVisitor, repr) { return result; } if !de::digits_but_not_number(repr) { if let Some(float) = de::parse_f64(repr) { return Ok(float.into()); } } Err(error::new(ErrorImpl::FailedToParseNumber)) } } impl PartialEq for N { fn eq(&self, other: &N) -> bool { match (*self, *other) { (N::PosInt(a), N::PosInt(b)) => a == b, (N::NegInt(a), N::NegInt(b)) => a == b, (N::Float(a), N::Float(b)) => { if a.is_nan() && b.is_nan() { // YAML only has one NaN; // the bit representation isn't preserved true } else { a == b } } _ => false, } } } impl PartialOrd for N { fn partial_cmp(&self, other: &Self) -> Option { match (*self, *other) { (N::Float(a), N::Float(b)) => { if a.is_nan() && b.is_nan() { // YAML only has one NaN Some(Ordering::Equal) } else { a.partial_cmp(&b) } } _ => Some(self.total_cmp(other)), } } } impl N { fn total_cmp(&self, other: &Self) -> Ordering { match (*self, *other) { (N::PosInt(a), N::PosInt(b)) => a.cmp(&b), (N::NegInt(a), N::NegInt(b)) => a.cmp(&b), // negint is always less than zero (N::NegInt(_), N::PosInt(_)) => Ordering::Less, (N::PosInt(_), N::NegInt(_)) => Ordering::Greater, (N::Float(a), N::Float(b)) => a.partial_cmp(&b).unwrap_or_else(|| { // arbitrarily sort the NaN last if !a.is_nan() { Ordering::Less } else if !b.is_nan() { Ordering::Greater } else { Ordering::Equal } }), // arbitrarily sort integers below floats // FIXME: maybe something more sensible? (_, N::Float(_)) => Ordering::Less, (N::Float(_), _) => Ordering::Greater, } } } impl Number { pub(crate) fn total_cmp(&self, other: &Self) -> Ordering { self.n.total_cmp(&other.n) } } impl Serialize for Number { #[inline] fn serialize(&self, serializer: S) -> Result where S: Serializer, { match self.n { N::PosInt(i) => serializer.serialize_u64(i), N::NegInt(i) => serializer.serialize_i64(i), N::Float(f) => serializer.serialize_f64(f), } } } struct NumberVisitor; impl<'de> Visitor<'de> for NumberVisitor { type Value = Number; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a number") } #[inline] fn visit_i64(self, value: i64) -> Result { Ok(value.into()) } #[inline] fn visit_u64(self, value: u64) -> Result { Ok(value.into()) } #[inline] fn visit_f64(self, value: f64) -> Result { Ok(value.into()) } } impl<'de> Deserialize<'de> for Number { #[inline] fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_any(NumberVisitor) } } impl<'de> Deserializer<'de> for Number { type Error = Error; #[inline] fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { match self.n { N::PosInt(i) => visitor.visit_u64(i), N::NegInt(i) => visitor.visit_i64(i), N::Float(f) => visitor.visit_f64(f), } } 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> Deserializer<'de> for &'a Number { type Error = Error; #[inline] fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { match self.n { N::PosInt(i) => visitor.visit_u64(i), N::NegInt(i) => visitor.visit_i64(i), N::Float(f) => visitor.visit_f64(f), } } forward_to_deserialize_any! { bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any } } macro_rules! from_signed { ($($signed_ty:ident)*) => { $( impl From<$signed_ty> for Number { #[inline] #[allow(clippy::cast_sign_loss)] fn from(i: $signed_ty) -> Self { if i < 0 { Number { n: N::NegInt(i as i64) } } else { Number { n: N::PosInt(i as u64) } } } } )* }; } macro_rules! from_unsigned { ($($unsigned_ty:ident)*) => { $( impl From<$unsigned_ty> for Number { #[inline] fn from(u: $unsigned_ty) -> Self { Number { n: N::PosInt(u as u64) } } } )* }; } from_signed!(i8 i16 i32 i64 isize); from_unsigned!(u8 u16 u32 u64 usize); impl From for Number { fn from(f: f32) -> Self { Number::from(f as f64) } } impl From for Number { fn from(mut f: f64) -> Self { if f.is_nan() { // Destroy NaN sign, signaling, and payload. YAML only has one NaN. f = f64::NAN.copysign(1.0); } Number { n: N::Float(f) } } } // This is fine, because we don't _really_ implement hash for floats // all other hash functions should work as expected #[allow(clippy::derived_hash_with_manual_eq)] impl Hash for Number { fn hash(&self, state: &mut H) { match self.n { N::Float(_) => { // you should feel bad for using f64 as a map key 3.hash(state); } N::PosInt(u) => u.hash(state), N::NegInt(i) => i.hash(state), } } } pub(crate) fn unexpected(number: &Number) -> Unexpected { match number.n { N::PosInt(u) => Unexpected::Unsigned(u), N::NegInt(i) => Unexpected::Signed(i), N::Float(f) => Unexpected::Float(f), } } serde_norway-0.9.38/src/path.rs000064400000000000000000000022731046102023000145230ustar 00000000000000use std::fmt::{self, Display}; /// Path to the current value in the input, like `dependencies.serde.typo1`. #[derive(Copy, Clone)] pub enum Path<'a> { Root, Seq { parent: &'a Path<'a>, index: usize }, Map { parent: &'a Path<'a>, key: &'a str }, Alias { parent: &'a Path<'a> }, Unknown { parent: &'a Path<'a> }, } impl<'a> Display for Path<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { struct Parent<'a>(&'a Path<'a>); impl<'a> Display for Parent<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self.0 { Path::Root => Ok(()), path => write!(formatter, "{}.", path), } } } match self { Path::Root => formatter.write_str("."), Path::Seq { parent, index } => write!(formatter, "{}[{}]", parent, index), Path::Map { parent, key } => write!(formatter, "{}{}", Parent(parent), key), Path::Alias { parent } => write!(formatter, "{}", parent), Path::Unknown { parent } => write!(formatter, "{}?", Parent(parent)), } } } serde_norway-0.9.38/src/ser.rs000064400000000000000000000447711046102023000143710ustar 00000000000000//! YAML Serialization //! //! This module provides YAML serialization with the type `Serializer`. use crate::error::{self, Error, ErrorImpl}; use crate::libyaml; use crate::libyaml::emitter::{Emitter, Event, Mapping, Scalar, ScalarStyle, Sequence}; use crate::value::tagged::{self, MaybeTag}; use serde::de::Visitor; use serde::ser::{self, Serializer as _}; use std::fmt::{self, Display}; use std::io; use std::marker::PhantomData; use std::mem; use std::num; use std::str; type Result = std::result::Result; /// A structure for serializing Rust values into YAML. /// /// # Example /// /// ``` /// use anyhow::Result; /// use serde::Serialize; /// use std::collections::BTreeMap; /// /// fn main() -> Result<()> { /// let mut buffer = Vec::new(); /// let mut ser = serde_norway::Serializer::new(&mut buffer); /// /// let mut object = BTreeMap::new(); /// object.insert("k", 107); /// object.serialize(&mut ser)?; /// /// object.insert("J", 74); /// object.serialize(&mut ser)?; /// /// assert_eq!(buffer, b"k: 107\n---\nJ: 74\nk: 107\n"); /// Ok(()) /// } /// ``` pub struct Serializer { depth: usize, state: State, emitter: Emitter<'static>, writer: PhantomData, } enum State { NothingInParticular, CheckForTag, CheckForDuplicateTag, FoundTag(String), AlreadyTagged, } impl Serializer where W: io::Write, { /// Creates a new YAML serializer. pub fn new(writer: W) -> Self { let mut emitter = Emitter::new({ let writer = Box::new(writer); unsafe { mem::transmute::, Box>(writer) } }); emitter.emit(Event::StreamStart).unwrap(); Serializer { depth: 0, state: State::NothingInParticular, emitter, writer: PhantomData, } } /// Calls [`.flush()`](io::Write::flush) on the underlying `io::Write` /// object. pub fn flush(&mut self) -> Result<()> { self.emitter.flush()?; Ok(()) } /// Unwrap the underlying `io::Write` object from the `Serializer`. pub fn into_inner(mut self) -> Result { self.emitter.emit(Event::StreamEnd)?; self.emitter.flush()?; let writer = self.emitter.into_inner(); Ok(*unsafe { Box::from_raw(Box::into_raw(writer).cast::()) }) } fn emit_scalar(&mut self, mut scalar: Scalar) -> Result<()> { self.flush_mapping_start()?; if let Some(tag) = self.take_tag() { scalar.tag = Some(tag); } self.value_start()?; self.emitter.emit(Event::Scalar(scalar))?; self.value_end() } fn emit_sequence_start(&mut self) -> Result<()> { self.flush_mapping_start()?; self.value_start()?; let tag = self.take_tag(); self.emitter.emit(Event::SequenceStart(Sequence { tag }))?; Ok(()) } fn emit_sequence_end(&mut self) -> Result<()> { self.emitter.emit(Event::SequenceEnd)?; self.value_end() } fn emit_mapping_start(&mut self) -> Result<()> { self.flush_mapping_start()?; self.value_start()?; let tag = self.take_tag(); self.emitter.emit(Event::MappingStart(Mapping { tag }))?; Ok(()) } fn emit_mapping_end(&mut self) -> Result<()> { self.emitter.emit(Event::MappingEnd)?; self.value_end() } fn value_start(&mut self) -> Result<()> { if self.depth == 0 { self.emitter.emit(Event::DocumentStart)?; } self.depth += 1; Ok(()) } fn value_end(&mut self) -> Result<()> { self.depth -= 1; if self.depth == 0 { self.emitter.emit(Event::DocumentEnd)?; } Ok(()) } fn take_tag(&mut self) -> Option { let state = mem::replace(&mut self.state, State::NothingInParticular); if let State::FoundTag(mut tag) = state { if !tag.starts_with('!') { tag.insert(0, '!'); } Some(tag) } else { self.state = state; None } } fn flush_mapping_start(&mut self) -> Result<()> { if let State::CheckForTag = self.state { self.state = State::NothingInParticular; self.emit_mapping_start()?; } else if let State::CheckForDuplicateTag = self.state { self.state = State::NothingInParticular; } Ok(()) } } impl<'a, W> ser::Serializer for &'a mut Serializer where W: io::Write, { type Ok = (); type Error = Error; type SerializeSeq = Self; type SerializeTuple = Self; type SerializeTupleStruct = Self; type SerializeTupleVariant = Self; type SerializeMap = Self; type SerializeStruct = Self; type SerializeStructVariant = Self; fn serialize_bool(self, v: bool) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: if v { "true" } else { "false" }, style: ScalarStyle::Plain, }) } fn serialize_i8(self, v: i8) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_i16(self, v: i16) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_i32(self, v: i32) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_i64(self, v: i64) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_i128(self, v: i128) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_u8(self, v: u8) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_u16(self, v: u16) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_u32(self, v: u32) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_u64(self, v: u64) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_u128(self, v: u128) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: itoa::Buffer::new().format(v), style: ScalarStyle::Plain, }) } fn serialize_f32(self, v: f32) -> Result<()> { let mut buffer = ryu::Buffer::new(); self.emit_scalar(Scalar { tag: None, value: match v.classify() { num::FpCategory::Infinite if v.is_sign_positive() => ".inf", num::FpCategory::Infinite => "-.inf", num::FpCategory::Nan => ".nan", _ => buffer.format_finite(v), }, style: ScalarStyle::Plain, }) } fn serialize_f64(self, v: f64) -> Result<()> { let mut buffer = ryu::Buffer::new(); self.emit_scalar(Scalar { tag: None, value: match v.classify() { num::FpCategory::Infinite if v.is_sign_positive() => ".inf", num::FpCategory::Infinite => "-.inf", num::FpCategory::Nan => ".nan", _ => buffer.format_finite(v), }, style: ScalarStyle::Plain, }) } fn serialize_char(self, value: char) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: value.encode_utf8(&mut [0u8; 4]), style: ScalarStyle::SingleQuoted, }) } fn serialize_str(self, value: &str) -> Result<()> { struct InferScalarStyle; impl<'de> Visitor<'de> for InferScalarStyle { type Value = ScalarStyle; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("I wonder") } fn visit_bool(self, _v: bool) -> Result { Ok(ScalarStyle::SingleQuoted) } fn visit_i64(self, _v: i64) -> Result { Ok(ScalarStyle::SingleQuoted) } fn visit_i128(self, _v: i128) -> Result { Ok(ScalarStyle::SingleQuoted) } fn visit_u64(self, _v: u64) -> Result { Ok(ScalarStyle::SingleQuoted) } fn visit_u128(self, _v: u128) -> Result { Ok(ScalarStyle::SingleQuoted) } fn visit_f64(self, _v: f64) -> Result { Ok(ScalarStyle::SingleQuoted) } fn visit_str(self, v: &str) -> Result { Ok(if crate::de::digits_but_not_number(v) { ScalarStyle::SingleQuoted } else { ScalarStyle::Any }) } fn visit_unit(self) -> Result { Ok(ScalarStyle::SingleQuoted) } } let style = if value.contains('\n') { ScalarStyle::Literal } else { let result = crate::de::visit_untagged_scalar( InferScalarStyle, value, None, libyaml::parser::ScalarStyle::Plain, ); result.unwrap_or(ScalarStyle::Any) }; self.emit_scalar(Scalar { tag: None, value, style, }) } fn serialize_bytes(self, _value: &[u8]) -> Result<()> { Err(error::new(ErrorImpl::BytesUnsupported)) } fn serialize_unit(self) -> Result<()> { self.emit_scalar(Scalar { tag: None, value: "null", style: ScalarStyle::Plain, }) } fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { self.serialize_unit() } fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, ) -> Result<()> { self.serialize_str(variant) } fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T, ) -> Result<()> where T: ?Sized + ser::Serialize, { if let State::FoundTag(_) = self.state { return Err(error::new(ErrorImpl::SerializeNestedEnum)); } self.state = State::FoundTag(variant.to_owned()); value.serialize(&mut *self) } fn serialize_none(self) -> Result<()> { self.serialize_unit() } fn serialize_some(self, value: &V) -> Result<()> where V: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_seq(self, _len: Option) -> Result { self.emit_sequence_start()?; Ok(self) } fn serialize_tuple(self, _len: usize) -> Result { self.emit_sequence_start()?; Ok(self) } fn serialize_tuple_struct( self, _name: &'static str, _len: usize, ) -> Result { self.emit_sequence_start()?; Ok(self) } fn serialize_tuple_variant( self, _enm: &'static str, _idx: u32, variant: &'static str, _len: usize, ) -> Result { if let State::FoundTag(_) = self.state { return Err(error::new(ErrorImpl::SerializeNestedEnum)); } self.state = State::FoundTag(variant.to_owned()); self.emit_sequence_start()?; Ok(self) } fn serialize_map(self, len: Option) -> Result { if len == Some(1) { self.state = if let State::FoundTag(_) = self.state { self.emit_mapping_start()?; State::CheckForDuplicateTag } else { State::CheckForTag }; } else { self.emit_mapping_start()?; } Ok(self) } fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { self.emit_mapping_start()?; Ok(self) } fn serialize_struct_variant( self, _enm: &'static str, _idx: u32, variant: &'static str, _len: usize, ) -> Result { if let State::FoundTag(_) = self.state { return Err(error::new(ErrorImpl::SerializeNestedEnum)); } self.state = State::FoundTag(variant.to_owned()); self.emit_mapping_start()?; Ok(self) } fn collect_str(self, value: &T) -> Result where T: ?Sized + Display, { let string = if let State::CheckForTag | State::CheckForDuplicateTag = self.state { match tagged::check_for_tag(value) { MaybeTag::NotTag(string) => string, MaybeTag::Tag(string) => { return if let State::CheckForDuplicateTag = self.state { Err(error::new(ErrorImpl::SerializeNestedEnum)) } else { self.state = State::FoundTag(string); Ok(()) }; } } } else { value.to_string() }; self.serialize_str(&string) } } impl<'a, W> ser::SerializeSeq for &'a mut Serializer where W: io::Write, { type Ok = (); type Error = Error; fn serialize_element(&mut self, elem: &T) -> Result<()> where T: ?Sized + ser::Serialize, { elem.serialize(&mut **self) } fn end(self) -> Result<()> { self.emit_sequence_end() } } impl<'a, W> ser::SerializeTuple for &'a mut Serializer where W: io::Write, { type Ok = (); type Error = Error; fn serialize_element(&mut self, elem: &T) -> Result<()> where T: ?Sized + ser::Serialize, { elem.serialize(&mut **self) } fn end(self) -> Result<()> { self.emit_sequence_end() } } impl<'a, W> ser::SerializeTupleStruct for &'a mut Serializer where W: io::Write, { type Ok = (); type Error = Error; fn serialize_field(&mut self, value: &V) -> Result<()> where V: ?Sized + ser::Serialize, { value.serialize(&mut **self) } fn end(self) -> Result<()> { self.emit_sequence_end() } } impl<'a, W> ser::SerializeTupleVariant for &'a mut Serializer where W: io::Write, { type Ok = (); type Error = Error; fn serialize_field(&mut self, v: &V) -> Result<()> where V: ?Sized + ser::Serialize, { v.serialize(&mut **self) } fn end(self) -> Result<()> { self.emit_sequence_end() } } impl<'a, W> ser::SerializeMap for &'a mut Serializer where W: io::Write, { type Ok = (); type Error = Error; fn serialize_key(&mut self, key: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.flush_mapping_start()?; key.serialize(&mut **self) } fn serialize_value(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { value.serialize(&mut **self) } fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where K: ?Sized + ser::Serialize, V: ?Sized + ser::Serialize, { key.serialize(&mut **self)?; let tagged = matches!(self.state, State::FoundTag(_)); value.serialize(&mut **self)?; if tagged { self.state = State::AlreadyTagged; } Ok(()) } fn end(self) -> Result<()> { if let State::CheckForTag = self.state { self.emit_mapping_start()?; } if !matches!(self.state, State::AlreadyTagged) { self.emit_mapping_end()?; } self.state = State::NothingInParticular; Ok(()) } } impl<'a, W> ser::SerializeStruct for &'a mut Serializer where W: io::Write, { type Ok = (); type Error = Error; fn serialize_field(&mut self, key: &'static str, value: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.serialize_str(key)?; value.serialize(&mut **self) } fn end(self) -> Result<()> { self.emit_mapping_end() } } impl<'a, W> ser::SerializeStructVariant for &'a mut Serializer where W: io::Write, { type Ok = (); type Error = Error; fn serialize_field(&mut self, field: &'static str, v: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.serialize_str(field)?; v.serialize(&mut **self) } fn end(self) -> Result<()> { self.emit_mapping_end() } } /// Serialize the given data structure as YAML into the IO stream. /// /// Serialization can fail if `T`'s implementation of `Serialize` decides to /// return an error. pub fn to_writer(writer: W, value: &T) -> Result<()> where W: io::Write, T: ?Sized + ser::Serialize, { let mut serializer = Serializer::new(writer); value.serialize(&mut serializer) } /// Serialize the given data structure as a String of YAML. /// /// Serialization can fail if `T`'s implementation of `Serialize` decides to /// return an error. pub fn to_string(value: &T) -> Result where T: ?Sized + ser::Serialize, { let mut vec = Vec::with_capacity(128); to_writer(&mut vec, value)?; String::from_utf8(vec).map_err(|error| error::new(ErrorImpl::FromUtf8(error))) } serde_norway-0.9.38/src/value/de.rs000064400000000000000000000773571046102023000153120ustar 00000000000000use crate::value::tagged::{self, TagStringVisitor}; use crate::value::TaggedValue; use crate::{number, Error, Mapping, Sequence, Value}; use serde::de::value::{BorrowedStrDeserializer, StrDeserializer}; use serde::de::{ self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error as _, Expected, MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, }; use serde::forward_to_deserialize_any; use std::fmt; use std::slice; use std::vec; impl<'de> Deserialize<'de> for Value { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct ValueVisitor; impl<'de> Visitor<'de> for ValueVisitor { type Value = Value; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("any YAML value") } fn visit_bool(self, b: bool) -> Result where E: de::Error, { Ok(Value::Bool(b)) } fn visit_i64(self, i: i64) -> Result where E: de::Error, { Ok(Value::Number(i.into())) } fn visit_u64(self, u: u64) -> Result where E: de::Error, { Ok(Value::Number(u.into())) } fn visit_f64(self, f: f64) -> Result where E: de::Error, { Ok(Value::Number(f.into())) } fn visit_str(self, s: &str) -> Result where E: de::Error, { Ok(Value::String(s.to_owned())) } fn visit_string(self, s: String) -> Result where E: de::Error, { Ok(Value::String(s)) } fn visit_unit(self) -> Result where E: de::Error, { Ok(Value::Null) } fn visit_none(self) -> Result where E: de::Error, { Ok(Value::Null) } fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { Deserialize::deserialize(deserializer) } fn visit_seq(self, data: A) -> Result where A: SeqAccess<'de>, { let de = serde::de::value::SeqAccessDeserializer::new(data); let sequence = Sequence::deserialize(de)?; Ok(Value::Sequence(sequence)) } fn visit_map(self, data: A) -> Result where A: MapAccess<'de>, { let de = serde::de::value::MapAccessDeserializer::new(data); let mapping = Mapping::deserialize(de)?; Ok(Value::Mapping(mapping)) } fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { let (tag, contents) = data.variant_seed(TagStringVisitor)?; let value = contents.newtype_variant()?; Ok(Value::Tagged(Box::new(TaggedValue { tag, value }))) } } deserializer.deserialize_any(ValueVisitor) } } impl Value { fn deserialize_number<'de, V>(&self, visitor: V) -> Result where V: Visitor<'de>, { match self.untag_ref() { Value::Number(n) => n.deserialize_any(visitor), other => Err(other.invalid_type(&visitor)), } } } fn visit_sequence<'de, V>(sequence: Sequence, visitor: V) -> Result where V: Visitor<'de>, { let len = sequence.len(); let mut deserializer = SeqDeserializer::new(sequence); let seq = visitor.visit_seq(&mut deserializer)?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok(seq) } else { Err(Error::invalid_length(len, &"fewer elements in sequence")) } } fn visit_sequence_ref<'de, V>(sequence: &'de Sequence, visitor: V) -> Result where V: Visitor<'de>, { let len = sequence.len(); let mut deserializer = SeqRefDeserializer::new(sequence); let seq = visitor.visit_seq(&mut deserializer)?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok(seq) } else { Err(Error::invalid_length(len, &"fewer elements in sequence")) } } fn visit_mapping<'de, V>(mapping: Mapping, visitor: V) -> Result where V: Visitor<'de>, { let len = mapping.len(); let mut deserializer = MapDeserializer::new(mapping); let map = visitor.visit_map(&mut deserializer)?; let remaining = deserializer.iter.len(); if remaining == 0 { Ok(map) } else { Err(Error::invalid_length(len, &"fewer elements in map")) } } fn visit_mapping_ref<'de, V>(mapping: &'de Mapping, visitor: V) -> Result where V: Visitor<'de>, { let len = mapping.len(); let mut deserializer = MapRefDeserializer::new(mapping); let map = visitor.visit_map(&mut deserializer)?; let remaining = deserializer.iter.unwrap().len(); if remaining == 0 { Ok(map) } else { Err(Error::invalid_length(len, &"fewer elements in map")) } } impl<'de> Deserializer<'de> for Value { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { match self { Value::Null => visitor.visit_unit(), Value::Bool(v) => visitor.visit_bool(v), Value::Number(n) => n.deserialize_any(visitor), Value::String(v) => visitor.visit_string(v), Value::Sequence(v) => visit_sequence(v, visitor), Value::Mapping(v) => visit_mapping(v, visitor), Value::Tagged(tagged) => visitor.visit_enum(*tagged), } } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { match self.untag() { Value::Bool(v) => visitor.visit_bool(v), other => Err(other.invalid_type(&visitor)), } } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_string(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.untag() { Value::String(v) => visitor.visit_string(v), other => Err(other.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.untag() { Value::String(v) => visitor.visit_string(v), Value::Sequence(v) => visit_sequence(v, visitor), other => Err(other.invalid_type(&visitor)), } } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { match self { Value::Null => visitor.visit_none(), _ => visitor.visit_some(self), } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { match self { Value::Null => 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: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { match self.untag() { Value::Sequence(v) => visit_sequence(v, visitor), Value::Null => visit_sequence(Sequence::new(), visitor), other => Err(other.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.untag() { Value::Mapping(v) => visit_mapping(v, visitor), Value::Null => visit_mapping(Mapping::new(), visitor), other => Err(other.invalid_type(&visitor)), } } fn deserialize_struct( self, _name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_map(visitor) } fn deserialize_enum( self, _name: &str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let tag; visitor.visit_enum(match self { Value::Tagged(tagged) => EnumDeserializer { tag: { tag = tagged.tag.string; tagged::nobang(&tag) }, value: Some(tagged.value), }, Value::String(variant) => EnumDeserializer { tag: { tag = variant; &tag }, value: None, }, other => { return Err(Error::invalid_type( other.unexpected(), &"a Value::Tagged enum", )); } }) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_string(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { drop(self); visitor.visit_unit() } } struct EnumDeserializer<'a> { tag: &'a str, value: Option, } impl<'a, 'de> EnumAccess<'de> for EnumDeserializer<'a> { type Error = Error; type Variant = VariantDeserializer; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Error> where V: DeserializeSeed<'de>, { let str_de = StrDeserializer::::new(self.tag); let variant = seed.deserialize(str_de)?; let visitor = VariantDeserializer { value: self.value }; Ok((variant, visitor)) } } struct VariantDeserializer { value: Option, } impl<'de> VariantAccess<'de> for VariantDeserializer { type Error = Error; fn unit_variant(self) -> Result<(), Error> { match self.value { Some(value) => value.unit_variant(), None => Ok(()), } } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.value { Some(value) => value.newtype_variant_seed(seed), None => Err(Error::invalid_type( Unexpected::UnitVariant, &"newtype variant", )), } } fn tuple_variant(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { match self.value { Some(value) => value.tuple_variant(len, visitor), None => Err(Error::invalid_type( Unexpected::UnitVariant, &"tuple variant", )), } } fn struct_variant( self, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { match self.value { Some(value) => value.struct_variant(fields, visitor), None => Err(Error::invalid_type( Unexpected::UnitVariant, &"struct variant", )), } } } pub(crate) struct SeqDeserializer { iter: vec::IntoIter, } impl SeqDeserializer { pub(crate) fn new(vec: Vec) -> Self { SeqDeserializer { iter: vec.into_iter(), } } } impl<'de> Deserializer<'de> for SeqDeserializer { type Error = Error; #[inline] fn deserialize_any(mut self, visitor: V) -> Result where V: Visitor<'de>, { let len = self.iter.len(); if len == 0 { visitor.visit_unit() } else { let ret = visitor.visit_seq(&mut self)?; let remaining = self.iter.len(); if remaining == 0 { Ok(ret) } else { Err(Error::invalid_length(len, &"fewer elements in sequence")) } } } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { drop(self); visitor.visit_unit() } forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier } } impl<'de> SeqAccess<'de> for SeqDeserializer { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result, Error> where T: DeserializeSeed<'de>, { match self.iter.next() { Some(value) => seed.deserialize(value).map(Some), None => Ok(None), } } fn size_hint(&self) -> Option { match self.iter.size_hint() { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } } pub(crate) struct MapDeserializer { iter: ::IntoIter, value: Option, } impl MapDeserializer { pub(crate) fn new(map: Mapping) -> Self { MapDeserializer { iter: map.into_iter(), value: None, } } } impl<'de> MapAccess<'de> for MapDeserializer { type Error = Error; fn next_key_seed(&mut self, seed: T) -> Result, Error> where T: DeserializeSeed<'de>, { match self.iter.next() { Some((key, value)) => { self.value = Some(value); seed.deserialize(key).map(Some) } None => Ok(None), } } fn next_value_seed(&mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.value.take() { Some(value) => seed.deserialize(value), None => panic!("visit_value called before visit_key"), } } fn size_hint(&self) -> Option { match self.iter.size_hint() { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } } impl<'de> Deserializer<'de> for MapDeserializer { type Error = Error; #[inline] fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_map(self) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { drop(self); visitor.visit_unit() } forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier } } impl<'de> Deserializer<'de> for &'de Value { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { match self { Value::Null => visitor.visit_unit(), Value::Bool(v) => visitor.visit_bool(*v), Value::Number(n) => n.deserialize_any(visitor), Value::String(v) => visitor.visit_borrowed_str(v), Value::Sequence(v) => visit_sequence_ref(v, visitor), Value::Mapping(v) => visit_mapping_ref(v, visitor), Value::Tagged(tagged) => visitor.visit_enum(&**tagged), } } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { match self.untag_ref() { Value::Bool(v) => visitor.visit_bool(*v), other => Err(other.invalid_type(&visitor)), } } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_number(visitor) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_string(visitor) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { match self.untag_ref() { Value::String(v) => visitor.visit_borrowed_str(v), other => Err(other.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.untag_ref() { Value::String(v) => visitor.visit_borrowed_str(v), Value::Sequence(v) => visit_sequence_ref(v, visitor), other => Err(other.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>, { match self { Value::Null => visitor.visit_none(), _ => visitor.visit_some(self), } } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { match self { Value::Null => 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: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_newtype_struct(self) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { static EMPTY: Sequence = Sequence::new(); match self.untag_ref() { Value::Sequence(v) => visit_sequence_ref(v, visitor), Value::Null => visit_sequence_ref(&EMPTY, visitor), other => Err(other.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.untag_ref() { Value::Mapping(v) => visit_mapping_ref(v, visitor), Value::Null => visitor.visit_map(&mut MapRefDeserializer { iter: None, value: None, }), other => Err(other.invalid_type(&visitor)), } } fn deserialize_struct( self, _name: &'static str, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.deserialize_map(visitor) } fn deserialize_enum( self, _name: &str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { visitor.visit_enum(match self { Value::Tagged(tagged) => EnumRefDeserializer { tag: tagged::nobang(&tagged.tag.string), value: Some(&tagged.value), }, Value::String(variant) => EnumRefDeserializer { tag: variant, value: None, }, other => { return Err(Error::invalid_type( other.unexpected(), &"a Value::Tagged enum", )); } }) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.deserialize_string(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } } struct EnumRefDeserializer<'de> { tag: &'de str, value: Option<&'de Value>, } impl<'de> EnumAccess<'de> for EnumRefDeserializer<'de> { type Error = Error; type Variant = VariantRefDeserializer<'de>; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Error> where V: DeserializeSeed<'de>, { let str_de = BorrowedStrDeserializer::::new(self.tag); let variant = seed.deserialize(str_de)?; let visitor = VariantRefDeserializer { value: self.value }; Ok((variant, visitor)) } } struct VariantRefDeserializer<'de> { value: Option<&'de Value>, } impl<'de> VariantAccess<'de> for VariantRefDeserializer<'de> { type Error = Error; fn unit_variant(self) -> Result<(), Error> { match self.value { Some(value) => value.unit_variant(), None => Ok(()), } } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.value { Some(value) => value.newtype_variant_seed(seed), None => Err(Error::invalid_type( Unexpected::UnitVariant, &"newtype variant", )), } } fn tuple_variant(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { match self.value { Some(value) => value.tuple_variant(len, visitor), None => Err(Error::invalid_type( Unexpected::UnitVariant, &"tuple variant", )), } } fn struct_variant( self, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { match self.value { Some(value) => value.struct_variant(fields, visitor), None => Err(Error::invalid_type( Unexpected::UnitVariant, &"struct variant", )), } } } pub(crate) struct SeqRefDeserializer<'de> { iter: slice::Iter<'de, Value>, } impl<'de> SeqRefDeserializer<'de> { pub(crate) fn new(slice: &'de [Value]) -> Self { SeqRefDeserializer { iter: slice.iter() } } } impl<'de> Deserializer<'de> for SeqRefDeserializer<'de> { type Error = Error; #[inline] fn deserialize_any(mut self, visitor: V) -> Result where V: Visitor<'de>, { let len = self.iter.len(); if len == 0 { visitor.visit_unit() } else { let ret = visitor.visit_seq(&mut self)?; let remaining = self.iter.len(); if remaining == 0 { Ok(ret) } else { Err(Error::invalid_length(len, &"fewer elements in sequence")) } } } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier } } impl<'de> SeqAccess<'de> for SeqRefDeserializer<'de> { type Error = Error; fn next_element_seed(&mut self, seed: T) -> Result, Error> where T: DeserializeSeed<'de>, { match self.iter.next() { Some(value) => seed.deserialize(value).map(Some), None => Ok(None), } } fn size_hint(&self) -> Option { match self.iter.size_hint() { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } } pub(crate) struct MapRefDeserializer<'de> { iter: Option<<&'de Mapping as IntoIterator>::IntoIter>, value: Option<&'de Value>, } impl<'de> MapRefDeserializer<'de> { pub(crate) fn new(map: &'de Mapping) -> Self { MapRefDeserializer { iter: Some(map.iter()), value: None, } } } impl<'de> MapAccess<'de> for MapRefDeserializer<'de> { type Error = Error; fn next_key_seed(&mut self, seed: T) -> Result, Error> where T: DeserializeSeed<'de>, { match self.iter.as_mut().and_then(Iterator::next) { Some((key, value)) => { self.value = Some(value); seed.deserialize(key).map(Some) } None => Ok(None), } } fn next_value_seed(&mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { match self.value.take() { Some(value) => seed.deserialize(value), None => panic!("visit_value called before visit_key"), } } fn size_hint(&self) -> Option { match self.iter.as_ref()?.size_hint() { (lower, Some(upper)) if lower == upper => Some(upper), _ => None, } } } impl<'de> Deserializer<'de> for MapRefDeserializer<'de> { type Error = Error; #[inline] fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_map(self) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier } } impl Value { #[cold] fn invalid_type(&self, exp: &dyn Expected) -> E where E: de::Error, { de::Error::invalid_type(self.unexpected(), exp) } #[cold] pub(crate) fn unexpected(&self) -> Unexpected { match self { Value::Null => Unexpected::Unit, Value::Bool(b) => Unexpected::Bool(*b), Value::Number(n) => number::unexpected(n), Value::String(s) => Unexpected::Str(s), Value::Sequence(_) => Unexpected::Seq, Value::Mapping(_) => Unexpected::Map, Value::Tagged(_) => Unexpected::Enum, } } } serde_norway-0.9.38/src/value/debug.rs000064400000000000000000000034551046102023000157740ustar 00000000000000use crate::mapping::Mapping; use crate::value::{Number, Value}; use std::fmt::{self, Debug, Display}; impl Debug for Value { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self { Value::Null => formatter.write_str("Null"), Value::Bool(boolean) => write!(formatter, "Bool({})", boolean), Value::Number(number) => write!(formatter, "Number({})", number), Value::String(string) => write!(formatter, "String({:?})", string), Value::Sequence(sequence) => { formatter.write_str("Sequence ")?; formatter.debug_list().entries(sequence).finish() } Value::Mapping(mapping) => Debug::fmt(mapping, formatter), Value::Tagged(tagged) => Debug::fmt(tagged, formatter), } } } struct DisplayNumber<'a>(&'a Number); impl<'a> Debug for DisplayNumber<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Display::fmt(self.0, formatter) } } impl Debug for Number { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "Number({})", self) } } impl Debug for Mapping { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Mapping ")?; let mut debug = formatter.debug_map(); for (k, v) in self { let tmp; debug.entry( match k { Value::Bool(boolean) => boolean, Value::Number(number) => { tmp = DisplayNumber(number); &tmp } Value::String(string) => string, _ => k, }, v, ); } debug.finish() } } serde_norway-0.9.38/src/value/from.rs000064400000000000000000000075031046102023000156470ustar 00000000000000use crate::{Mapping, Value}; // Implement a bunch of conversion to make it easier to create YAML values // on the fly. macro_rules! from_number { ($($ty:ident)*) => { $( impl From<$ty> for Value { fn from(n: $ty) -> Self { Value::Number(n.into()) } } )* }; } from_number! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize f32 f64 } impl From for Value { /// Convert boolean to `Value` /// /// # Examples /// /// ``` /// use serde_norway::Value; /// /// let b = false; /// let x: Value = b.into(); /// ``` fn from(f: bool) -> Self { Value::Bool(f) } } impl From for Value { /// Convert `String` to `Value` /// /// # Examples /// /// ``` /// use serde_norway::Value; /// /// let s: String = "lorem".to_string(); /// let x: Value = s.into(); /// ``` fn from(f: String) -> Self { Value::String(f) } } impl<'a> From<&'a str> for Value { /// Convert string slice to `Value` /// /// # Examples /// /// ``` /// use serde_norway::Value; /// /// let s: &str = "lorem"; /// let x: Value = s.into(); /// ``` fn from(f: &str) -> Self { Value::String(f.to_string()) } } use std::borrow::Cow; impl<'a> From> for Value { /// Convert copy-on-write string to `Value` /// /// # Examples /// /// ``` /// use serde_norway::Value; /// use std::borrow::Cow; /// /// let s: Cow = Cow::Borrowed("lorem"); /// let x: Value = s.into(); /// ``` /// /// ``` /// use serde_norway::Value; /// use std::borrow::Cow; /// /// let s: Cow = Cow::Owned("lorem".to_string()); /// let x: Value = s.into(); /// ``` fn from(f: Cow<'a, str>) -> Self { Value::String(f.to_string()) } } impl From for Value { /// Convert map (with string keys) to `Value` /// /// # Examples /// /// ``` /// use serde_norway::{Mapping, Value}; /// /// let mut m = Mapping::new(); /// m.insert("Lorem".into(), "ipsum".into()); /// let x: Value = m.into(); /// ``` fn from(f: Mapping) -> Self { Value::Mapping(f) } } impl> From> for Value { /// Convert a `Vec` to `Value` /// /// # Examples /// /// ``` /// use serde_norway::Value; /// /// let v = vec!["lorem", "ipsum", "dolor"]; /// let x: Value = v.into(); /// ``` fn from(f: Vec) -> Self { Value::Sequence(f.into_iter().map(Into::into).collect()) } } impl<'a, T: Clone + Into> From<&'a [T]> for Value { /// Convert a slice to `Value` /// /// # Examples /// /// ``` /// use serde_norway::Value; /// /// let v: &[&str] = &["lorem", "ipsum", "dolor"]; /// let x: Value = v.into(); /// ``` fn from(f: &'a [T]) -> Self { Value::Sequence(f.iter().cloned().map(Into::into).collect()) } } impl> FromIterator for Value { /// Convert an iteratable type to a YAML sequence /// /// # Examples /// /// ``` /// use serde_norway::Value; /// /// let v = std::iter::repeat(42).take(5); /// let x: Value = v.collect(); /// ``` /// /// ``` /// use serde_norway::Value; /// /// let v: Vec<_> = vec!["lorem", "ipsum", "dolor"]; /// let x: Value = v.into_iter().collect(); /// ``` /// /// ``` /// use std::iter::FromIterator; /// use serde_norway::Value; /// /// let x: Value = Value::from_iter(vec!["lorem", "ipsum", "dolor"]); /// ``` fn from_iter>(iter: I) -> Self { let vec = iter.into_iter().map(T::into).collect(); Value::Sequence(vec) } } serde_norway-0.9.38/src/value/index.rs000064400000000000000000000235741046102023000160210ustar 00000000000000use crate::mapping::Entry; use crate::{mapping, private, Mapping, Value}; use std::fmt::{self, Debug}; use std::ops; /// A type that can be used to index into a `serde_norway::Value`. See the `get` /// and `get_mut` methods of `Value`. /// /// This trait is sealed and cannot be implemented for types outside of /// `serde_norway`. pub trait Index: private::Sealed { /// Return None if the key is not already in the sequence or object. #[doc(hidden)] fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>; /// Return None if the key is not already in the sequence or object. #[doc(hidden)] fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>; /// Panic if sequence index out of bounds. If key is not already in the object, /// insert it with a value of null. Panic if Value is a type that cannot be /// indexed into, except if Value is null then it can be treated as an empty /// object. #[doc(hidden)] fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value; } impl Index for usize { fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { match v.untag_ref() { Value::Sequence(vec) => vec.get(*self), Value::Mapping(vec) => vec.get(Value::Number((*self).into())), _ => None, } } fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { match v.untag_mut() { Value::Sequence(vec) => vec.get_mut(*self), Value::Mapping(vec) => vec.get_mut(Value::Number((*self).into())), _ => None, } } fn index_or_insert<'v>(&self, mut v: &'v mut Value) -> &'v mut Value { loop { match v { Value::Sequence(vec) => { let len = vec.len(); return vec.get_mut(*self).unwrap_or_else(|| { panic!( "cannot access index {} of YAML sequence of length {}", self, len ) }); } Value::Mapping(map) => { let n = Value::Number((*self).into()); return map.entry(n).or_insert(Value::Null); } Value::Tagged(tagged) => v = &mut tagged.value, _ => panic!("cannot access index {} of YAML {}", self, Type(v)), } } } } fn index_into_mapping<'v, I>(index: &I, v: &'v Value) -> Option<&'v Value> where I: ?Sized + mapping::Index, { match v.untag_ref() { Value::Mapping(map) => map.get(index), _ => None, } } fn index_into_mut_mapping<'v, I>(index: &I, v: &'v mut Value) -> Option<&'v mut Value> where I: ?Sized + mapping::Index, { match v.untag_mut() { Value::Mapping(map) => map.get_mut(index), _ => None, } } fn index_or_insert_mapping<'v, I>(index: &I, mut v: &'v mut Value) -> &'v mut Value where I: ?Sized + mapping::Index + ToOwned + Debug, Value: From, { if let Value::Null = *v { *v = Value::Mapping(Mapping::new()); return match v { Value::Mapping(map) => match map.entry(index.to_owned().into()) { Entry::Vacant(entry) => entry.insert(Value::Null), Entry::Occupied(_) => unreachable!(), }, _ => unreachable!(), }; } loop { match v { Value::Mapping(map) => { return map.entry(index.to_owned().into()).or_insert(Value::Null); } Value::Tagged(tagged) => v = &mut tagged.value, _ => panic!("cannot access key {:?} in YAML {}", index, Type(v)), } } } impl Index for Value { fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { index_into_mapping(self, v) } fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { index_into_mut_mapping(self, v) } fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { index_or_insert_mapping(self, v) } } impl Index for str { fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { index_into_mapping(self, v) } fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { index_into_mut_mapping(self, v) } fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { index_or_insert_mapping(self, v) } } impl Index for String { fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { self.as_str().index_into(v) } fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { self.as_str().index_into_mut(v) } fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { self.as_str().index_or_insert(v) } } impl<'a, T> Index for &'a T where T: ?Sized + Index, { fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { (**self).index_into(v) } fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { (**self).index_into_mut(v) } fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { (**self).index_or_insert(v) } } /// Used in panic messages. struct Type<'a>(&'a Value); impl<'a> fmt::Display for Type<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self.0 { Value::Null => formatter.write_str("null"), Value::Bool(_) => formatter.write_str("boolean"), Value::Number(_) => formatter.write_str("number"), Value::String(_) => formatter.write_str("string"), Value::Sequence(_) => formatter.write_str("sequence"), Value::Mapping(_) => formatter.write_str("mapping"), Value::Tagged(_) => unreachable!(), } } } // The usual semantics of Index is to panic on invalid indexing. // // That said, the usual semantics are for things like `Vec` and `BTreeMap` which // have different use cases than Value. If you are working with a Vec, you know // that you are working with a Vec and you can get the len of the Vec and make // sure your indices are within bounds. The Value use cases are more // loosey-goosey. You got some YAML from an endpoint and you want to pull values // out of it. Outside of this Index impl, you already have the option of using // `value.as_sequence()` and working with the Vec directly, or matching on // `Value::Sequence` and getting the Vec directly. The Index impl means you can // skip that and index directly into the thing using a concise syntax. You don't // have to check the type, you don't have to check the len, it is all about what // you expect the Value to look like. // // Basically the use cases that would be well served by panicking here are // better served by using one of the other approaches: `get` and `get_mut`, // `as_sequence`, or match. The value of this impl is that it adds a way of // working with Value that is not well served by the existing approaches: // concise and careless and sometimes that is exactly what you want. impl ops::Index for Value where I: Index, { type Output = Value; /// Index into a `serde_norway::Value` using the syntax `value[0]` or /// `value["k"]`. /// /// Returns `Value::Null` if the type of `self` does not match the type of /// the index, for example if the index is a string and `self` is a sequence /// or a number. Also returns `Value::Null` if the given key does not exist /// in the map or the given index is not within the bounds of the sequence. /// /// For retrieving deeply nested values, you should have a look at the /// `Value::pointer` method. /// /// # Examples /// /// ``` /// # use serde_norway::Value; /// # /// # fn main() -> serde_norway::Result<()> { /// let data: serde_norway::Value = serde_norway::from_str(r#"{ x: { y: [z, zz] } }"#)?; /// /// assert_eq!(data["x"]["y"], serde_norway::from_str::(r#"["z", "zz"]"#).unwrap()); /// assert_eq!(data["x"]["y"][0], serde_norway::from_str::(r#""z""#).unwrap()); /// /// assert_eq!(data["a"], serde_norway::from_str::(r#"null"#).unwrap()); // returns null for undefined values /// assert_eq!(data["a"]["b"], serde_norway::from_str::(r#"null"#).unwrap()); // does not panic /// # Ok(()) /// # } /// ``` fn index(&self, index: I) -> &Value { static NULL: Value = Value::Null; index.index_into(self).unwrap_or(&NULL) } } impl ops::IndexMut for Value where I: Index, { /// Write into a `serde_norway::Value` using the syntax `value[0] = ...` or /// `value["k"] = ...`. /// /// If the index is a number, the value must be a sequence of length bigger /// than the index. Indexing into a value that is not a sequence or a /// sequence that is too small will panic. /// /// If the index is a string, the value must be an object or null which is /// treated like an empty object. If the key is not already present in the /// object, it will be inserted with a value of null. Indexing into a value /// that is neither an object nor null will panic. /// /// # Examples /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// let mut data: serde_norway::Value = serde_norway::from_str(r#"{x: 0}"#)?; /// /// // replace an existing key /// data["x"] = serde_norway::from_str(r#"1"#)?; /// /// // insert a new key /// data["y"] = serde_norway::from_str(r#"[false, false, false]"#)?; /// /// // replace a value in a sequence /// data["y"][0] = serde_norway::from_str(r#"true"#)?; /// /// // inserted a deeply nested key /// data["a"]["b"]["c"]["d"] = serde_norway::from_str(r#"true"#)?; /// /// println!("{:?}", data); /// # Ok(()) /// # } /// ``` fn index_mut(&mut self, index: I) -> &mut Value { index.index_or_insert(self) } } serde_norway-0.9.38/src/value/mod.rs000064400000000000000000000531001046102023000154550ustar 00000000000000//! The Value enum, a loosely typed way of representing any valid YAML value. mod de; mod debug; mod from; mod index; mod partial_eq; mod ser; pub(crate) mod tagged; use crate::error::{self, Error, ErrorImpl}; use serde::de::{Deserialize, DeserializeOwned, IntoDeserializer}; use serde::Serialize; use std::hash::{Hash, Hasher}; use std::mem; pub use self::index::Index; pub use self::ser::Serializer; pub use self::tagged::{Tag, TaggedValue}; #[doc(inline)] pub use crate::mapping::Mapping; pub use crate::number::Number; /// Represents any valid YAML value. #[derive(Clone, PartialEq, PartialOrd)] pub enum Value { /// Represents a YAML null value. Null, /// Represents a YAML boolean. Bool(bool), /// Represents a YAML numerical value, whether integer or floating point. Number(Number), /// Represents a YAML string. String(String), /// Represents a YAML sequence in which the elements are /// `serde_norway::Value`. Sequence(Sequence), /// Represents a YAML mapping in which the keys and values are both /// `serde_norway::Value`. Mapping(Mapping), /// A representation of YAML's `!Tag` syntax, used for enums. Tagged(Box), } /// The default value is `Value::Null`. /// /// This is useful for handling omitted `Value` fields when deserializing. /// /// # Examples /// /// ``` /// # use serde_derive::Deserialize; /// use serde::Deserialize; /// use serde_norway::Value; /// /// #[derive(Deserialize)] /// struct Settings { /// level: i32, /// #[serde(default)] /// extras: Value, /// } /// /// # fn try_main() -> Result<(), serde_norway::Error> { /// let data = r#" { "level": 42 } "#; /// let s: Settings = serde_norway::from_str(data)?; /// /// assert_eq!(s.level, 42); /// assert_eq!(s.extras, Value::Null); /// # /// # Ok(()) /// # } /// # /// # try_main().unwrap() /// ``` impl Default for Value { fn default() -> Value { Value::Null } } /// A YAML sequence in which the elements are `serde_norway::Value`. pub type Sequence = Vec; /// Convert a `T` into `serde_norway::Value` which is an enum that can represent /// any valid YAML data. /// /// This conversion can fail if `T`'s implementation of `Serialize` decides to /// return an error. /// /// ``` /// # use serde_norway::Value; /// let val = serde_norway::to_value("s").unwrap(); /// assert_eq!(val, Value::String("s".to_owned())); /// ``` pub fn to_value(value: T) -> Result where T: Serialize, { value.serialize(Serializer) } /// Interpret a `serde_norway::Value` as an instance of type `T`. /// /// This conversion can fail if the structure of the Value does not match the /// structure expected by `T`, for example if `T` is a struct type but the Value /// contains something other than a YAML map. It can also fail if the structure /// is correct but `T`'s implementation of `Deserialize` decides that something /// is wrong with the data, for example required struct fields are missing from /// the YAML map or some number is too big to fit in the expected primitive /// type. /// /// ``` /// # use serde_norway::Value; /// let val = Value::String("foo".to_owned()); /// let s: String = serde_norway::from_value(val).unwrap(); /// assert_eq!("foo", s); /// ``` pub fn from_value(value: Value) -> Result where T: DeserializeOwned, { Deserialize::deserialize(value) } impl Value { /// Index into a YAML sequence or map. A string index can be used to access /// a value in a map, and a usize index can be used to access an element of /// an sequence. /// /// Returns `None` if the type of `self` does not match the type of the /// index, for example if the index is a string and `self` is a sequence or /// a number. Also returns `None` if the given key does not exist in the map /// or the given index is not within the bounds of the sequence. /// /// ``` /// # fn main() -> serde_norway::Result<()> { /// use serde_norway::Value; /// /// let object: Value = serde_norway::from_str(r#"{ A: 65, B: 66, C: 67 }"#)?; /// let x = object.get("A").unwrap(); /// assert_eq!(x, 65); /// /// let sequence: Value = serde_norway::from_str(r#"[ "A", "B", "C" ]"#)?; /// let x = sequence.get(2).unwrap(); /// assert_eq!(x, &Value::String("C".into())); /// /// assert_eq!(sequence.get("A"), None); /// # Ok(()) /// # } /// ``` /// /// Square brackets can also be used to index into a value in a more concise /// way. This returns `Value::Null` in cases where `get` would have returned /// `None`. /// /// ``` /// # use serde_norway::Value; /// # /// # fn main() -> serde_norway::Result<()> { /// let object: Value = serde_norway::from_str(r#" /// A: [a, á, à] /// B: [b, b́] /// C: [c, ć, ć̣, ḉ] /// 42: true /// "#)?; /// assert_eq!(object["B"][0], Value::String("b".into())); /// /// assert_eq!(object[Value::String("D".into())], Value::Null); /// assert_eq!(object["D"], Value::Null); /// assert_eq!(object[0]["x"]["y"]["z"], Value::Null); /// /// assert_eq!(object[42], Value::Bool(true)); /// # Ok(()) /// # } /// ``` pub fn get(&self, index: I) -> Option<&Value> { index.index_into(self) } /// Index into a YAML sequence or map. A string index can be used to access /// a value in a map, and a usize index can be used to access an element of /// an sequence. /// /// Returns `None` if the type of `self` does not match the type of the /// index, for example if the index is a string and `self` is a sequence or /// a number. Also returns `None` if the given key does not exist in the map /// or the given index is not within the bounds of the sequence. pub fn get_mut(&mut self, index: I) -> Option<&mut Value> { index.index_into_mut(self) } /// Returns true if the `Value` is a Null. Returns false otherwise. /// /// For any Value on which `is_null` returns true, `as_null` is guaranteed /// to return `Some(())`. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("null").unwrap(); /// assert!(v.is_null()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("false").unwrap(); /// assert!(!v.is_null()); /// ``` pub fn is_null(&self) -> bool { if let Value::Null = self.untag_ref() { true } else { false } } /// If the `Value` is a Null, returns (). Returns None otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("null").unwrap(); /// assert_eq!(v.as_null(), Some(())); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_null(), None); /// ``` pub fn as_null(&self) -> Option<()> { match self.untag_ref() { Value::Null => Some(()), _ => None, } } /// Returns true if the `Value` is a Boolean. Returns false otherwise. /// /// For any Value on which `is_boolean` returns true, `as_bool` is /// guaranteed to return the boolean value. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("true").unwrap(); /// assert!(v.is_bool()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("42").unwrap(); /// assert!(!v.is_bool()); /// ``` pub fn is_bool(&self) -> bool { self.as_bool().is_some() } /// If the `Value` is a Boolean, returns the associated bool. Returns None /// otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("true").unwrap(); /// assert_eq!(v.as_bool(), Some(true)); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("42").unwrap(); /// assert_eq!(v.as_bool(), None); /// ``` pub fn as_bool(&self) -> Option { match self.untag_ref() { Value::Bool(b) => Some(*b), _ => None, } } /// Returns true if the `Value` is a Number. Returns false otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("5").unwrap(); /// assert!(v.is_number()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("true").unwrap(); /// assert!(!v.is_number()); /// ``` pub fn is_number(&self) -> bool { match self.untag_ref() { Value::Number(_) => true, _ => false, } } /// Returns true if the `Value` is an integer between `i64::MIN` and /// `i64::MAX`. /// /// For any Value on which `is_i64` returns true, `as_i64` is guaranteed to /// return the integer value. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("1337").unwrap(); /// assert!(v.is_i64()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("null").unwrap(); /// assert!(!v.is_i64()); /// ``` pub fn is_i64(&self) -> bool { self.as_i64().is_some() } /// If the `Value` is an integer, represent it as i64 if possible. Returns /// None otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("1337").unwrap(); /// assert_eq!(v.as_i64(), Some(1337)); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_i64(), None); /// ``` pub fn as_i64(&self) -> Option { match self.untag_ref() { Value::Number(n) => n.as_i64(), _ => None, } } /// Returns true if the `Value` is an integer between `u64::MIN` and /// `u64::MAX`. /// /// For any Value on which `is_u64` returns true, `as_u64` is guaranteed to /// return the integer value. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("1337").unwrap(); /// assert!(v.is_u64()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("null").unwrap(); /// assert!(!v.is_u64()); /// ``` pub fn is_u64(&self) -> bool { self.as_u64().is_some() } /// If the `Value` is an integer, represent it as u64 if possible. Returns /// None otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("1337").unwrap(); /// assert_eq!(v.as_u64(), Some(1337)); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_u64(), None); /// ``` pub fn as_u64(&self) -> Option { match self.untag_ref() { Value::Number(n) => n.as_u64(), _ => None, } } /// Returns true if the `Value` is a number that can be represented by f64. /// /// For any Value on which `is_f64` returns true, `as_f64` is guaranteed to /// return the floating point value. /// /// Currently this function returns true if and only if both `is_i64` and /// `is_u64` return false but this is not a guarantee in the future. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("256.01").unwrap(); /// assert!(v.is_f64()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("true").unwrap(); /// assert!(!v.is_f64()); /// ``` pub fn is_f64(&self) -> bool { match self.untag_ref() { Value::Number(n) => n.is_f64(), _ => false, } } /// If the `Value` is a number, represent it as f64 if possible. Returns /// None otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("13.37").unwrap(); /// assert_eq!(v.as_f64(), Some(13.37)); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_f64(), None); /// ``` pub fn as_f64(&self) -> Option { match self.untag_ref() { Value::Number(i) => i.as_f64(), _ => None, } } /// Returns true if the `Value` is a String. Returns false otherwise. /// /// For any Value on which `is_string` returns true, `as_str` is guaranteed /// to return the string slice. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("'lorem ipsum'").unwrap(); /// assert!(v.is_string()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("42").unwrap(); /// assert!(!v.is_string()); /// ``` pub fn is_string(&self) -> bool { self.as_str().is_some() } /// If the `Value` is a String, returns the associated str. Returns None /// otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("'lorem ipsum'").unwrap(); /// assert_eq!(v.as_str(), Some("lorem ipsum")); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_str(), None); /// ``` pub fn as_str(&self) -> Option<&str> { match self.untag_ref() { Value::String(s) => Some(s), _ => None, } } /// Returns true if the `Value` is a sequence. Returns false otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("[1, 2, 3]").unwrap(); /// assert!(v.is_sequence()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("true").unwrap(); /// assert!(!v.is_sequence()); /// ``` pub fn is_sequence(&self) -> bool { self.as_sequence().is_some() } /// If the `Value` is a sequence, return a reference to it if possible. /// Returns None otherwise. /// /// ``` /// # use serde_norway::{Value, Number}; /// let v: Value = serde_norway::from_str("[1, 2]").unwrap(); /// assert_eq!(v.as_sequence(), Some(&vec![Value::Number(Number::from(1)), Value::Number(Number::from(2))])); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_sequence(), None); /// ``` pub fn as_sequence(&self) -> Option<&Sequence> { match self.untag_ref() { Value::Sequence(seq) => Some(seq), _ => None, } } /// If the `Value` is a sequence, return a mutable reference to it if /// possible. Returns None otherwise. /// /// ``` /// # use serde_norway::{Value, Number}; /// let mut v: Value = serde_norway::from_str("[1]").unwrap(); /// let s = v.as_sequence_mut().unwrap(); /// s.push(Value::Number(Number::from(2))); /// assert_eq!(s, &vec![Value::Number(Number::from(1)), Value::Number(Number::from(2))]); /// ``` /// /// ``` /// # use serde_norway::Value; /// let mut v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_sequence_mut(), None); /// ``` pub fn as_sequence_mut(&mut self) -> Option<&mut Sequence> { match self.untag_mut() { Value::Sequence(seq) => Some(seq), _ => None, } } /// Returns true if the `Value` is a mapping. Returns false otherwise. /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("a: 42").unwrap(); /// assert!(v.is_mapping()); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("true").unwrap(); /// assert!(!v.is_mapping()); /// ``` pub fn is_mapping(&self) -> bool { self.as_mapping().is_some() } /// If the `Value` is a mapping, return a reference to it if possible. /// Returns None otherwise. /// /// ``` /// # use serde_norway::{Value, Mapping, Number}; /// let v: Value = serde_norway::from_str("a: 42").unwrap(); /// /// let mut expected = Mapping::new(); /// expected.insert(Value::String("a".into()),Value::Number(Number::from(42))); /// /// assert_eq!(v.as_mapping(), Some(&expected)); /// ``` /// /// ``` /// # use serde_norway::Value; /// let v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_mapping(), None); /// ``` pub fn as_mapping(&self) -> Option<&Mapping> { match self.untag_ref() { Value::Mapping(map) => Some(map), _ => None, } } /// If the `Value` is a mapping, return a reference to it if possible. /// Returns None otherwise. /// /// ``` /// # use serde_norway::{Value, Mapping, Number}; /// let mut v: Value = serde_norway::from_str("a: 42").unwrap(); /// let m = v.as_mapping_mut().unwrap(); /// m.insert(Value::String("b".into()), Value::Number(Number::from(21))); /// /// let mut expected = Mapping::new(); /// expected.insert(Value::String("a".into()), Value::Number(Number::from(42))); /// expected.insert(Value::String("b".into()), Value::Number(Number::from(21))); /// /// assert_eq!(m, &expected); /// ``` /// /// ``` /// # use serde_norway::{Value, Mapping}; /// let mut v: Value = serde_norway::from_str("false").unwrap(); /// assert_eq!(v.as_mapping_mut(), None); /// ``` pub fn as_mapping_mut(&mut self) -> Option<&mut Mapping> { match self.untag_mut() { Value::Mapping(map) => Some(map), _ => None, } } /// Performs merging of `<<` keys into the surrounding mapping. /// /// The intended use of this in YAML is described in /// . /// /// ``` /// use serde_norway::Value; /// /// let config = "\ /// tasks: /// build: &webpack_shared /// command: webpack /// args: build /// inputs: /// - 'src/**/*' /// start: /// <<: *webpack_shared /// args: start /// "; /// /// let mut value: Value = serde_norway::from_str(config).unwrap(); /// value.apply_merge().unwrap(); /// /// assert_eq!(value["tasks"]["start"]["command"], "webpack"); /// assert_eq!(value["tasks"]["start"]["args"], "start"); /// ``` pub fn apply_merge(&mut self) -> Result<(), Error> { let mut stack = Vec::new(); stack.push(self); while let Some(node) = stack.pop() { match node { Value::Mapping(mapping) => { match mapping.remove("<<") { Some(Value::Mapping(merge)) => { for (k, v) in merge { mapping.entry(k).or_insert(v); } } Some(Value::Sequence(sequence)) => { for value in sequence { match value { Value::Mapping(merge) => { for (k, v) in merge { mapping.entry(k).or_insert(v); } } Value::Sequence(_) => { return Err(error::new(ErrorImpl::SequenceInMergeElement)); } Value::Tagged(_) => { return Err(error::new(ErrorImpl::TaggedInMerge)); } _unexpected => { return Err(error::new(ErrorImpl::ScalarInMergeElement)); } } } } None => {} Some(Value::Tagged(_)) => return Err(error::new(ErrorImpl::TaggedInMerge)), Some(_unexpected) => return Err(error::new(ErrorImpl::ScalarInMerge)), } stack.extend(mapping.values_mut()); } Value::Sequence(sequence) => stack.extend(sequence), Value::Tagged(tagged) => stack.push(&mut tagged.value), _ => {} } } Ok(()) } } impl Eq for Value {} // NOTE: This impl must be kept consistent with HashLikeValue's Hash impl in // mapping.rs in order for value[str] indexing to work. impl Hash for Value { fn hash(&self, state: &mut H) { mem::discriminant(self).hash(state); match self { Value::Null => {} Value::Bool(v) => v.hash(state), Value::Number(v) => v.hash(state), Value::String(v) => v.hash(state), Value::Sequence(v) => v.hash(state), Value::Mapping(v) => v.hash(state), Value::Tagged(v) => v.hash(state), } } } impl<'de> IntoDeserializer<'de, Error> for Value { type Deserializer = Self; fn into_deserializer(self) -> Self::Deserializer { self } } serde_norway-0.9.38/src/value/partial_eq.rs000064400000000000000000000042761046102023000170310ustar 00000000000000use crate::Value; impl PartialEq for Value { /// Compare `str` with YAML value /// /// # Examples /// /// ``` /// # use serde_norway::Value; /// assert!(Value::String("lorem".into()) == *"lorem"); /// ``` fn eq(&self, other: &str) -> bool { self.as_str().map_or(false, |s| s == other) } } impl<'a> PartialEq<&'a str> for Value { /// Compare `&str` with YAML value /// /// # Examples /// /// ``` /// # use serde_norway::Value; /// assert!(Value::String("lorem".into()) == "lorem"); /// ``` fn eq(&self, other: &&str) -> bool { self.as_str().map_or(false, |s| s == *other) } } impl PartialEq for Value { /// Compare YAML value with String /// /// # Examples /// /// ``` /// # use serde_norway::Value; /// assert!(Value::String("lorem".into()) == "lorem".to_string()); /// ``` fn eq(&self, other: &String) -> bool { self.as_str().map_or(false, |s| s == other) } } impl PartialEq for Value { /// Compare YAML value with bool /// /// # Examples /// /// ``` /// # use serde_norway::Value; /// assert!(Value::Bool(true) == true); /// ``` fn eq(&self, other: &bool) -> bool { self.as_bool().map_or(false, |b| b == *other) } } macro_rules! partialeq_numeric { ($([$($ty:ty)*], $conversion:ident, $base:ty)*) => { $($( impl PartialEq<$ty> for Value { fn eq(&self, other: &$ty) -> bool { self.$conversion().map_or(false, |i| i == (*other as $base)) } } impl<'a> PartialEq<$ty> for &'a Value { fn eq(&self, other: &$ty) -> bool { self.$conversion().map_or(false, |i| i == (*other as $base)) } } impl<'a> PartialEq<$ty> for &'a mut Value { fn eq(&self, other: &$ty) -> bool { self.$conversion().map_or(false, |i| i == (*other as $base)) } } )*)* } } partialeq_numeric! { [i8 i16 i32 i64 isize], as_i64, i64 [u8 u16 u32 u64 usize], as_u64, u64 [f32 f64], as_f64, f64 } serde_norway-0.9.38/src/value/ser.rs000064400000000000000000000607401046102023000154770ustar 00000000000000use crate::error::{self, Error, ErrorImpl}; use crate::value::tagged::{self, MaybeTag}; use crate::value::{to_value, Mapping, Number, Sequence, Tag, TaggedValue, Value}; use serde::ser::{self, Serialize}; use std::fmt::Display; use std::mem; type Result = std::result::Result; impl Serialize for Value { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { match self { Value::Null => serializer.serialize_unit(), Value::Bool(b) => serializer.serialize_bool(*b), Value::Number(n) => n.serialize(serializer), Value::String(s) => serializer.serialize_str(s), Value::Sequence(seq) => seq.serialize(serializer), Value::Mapping(mapping) => { use serde::ser::SerializeMap; let mut map = serializer.serialize_map(Some(mapping.len()))?; for (k, v) in mapping { map.serialize_entry(k, v)?; } map.end() } Value::Tagged(tagged) => tagged.serialize(serializer), } } } /// Serializer whose output is a `Value`. /// /// This is the serializer that backs [`serde_norway::to_value`][crate::to_value]. /// Unlike the main serde_norway serializer which goes from some serializable /// value of type `T` to YAML text, this one goes from `T` to /// `serde_norway::Value`. /// /// The `to_value` function is implementable as: /// /// ``` /// use serde::Serialize; /// use serde_norway::{Error, Value}; /// /// pub fn to_value(input: T) -> Result /// where /// T: Serialize, /// { /// input.serialize(serde_norway::value::Serializer) /// } /// ``` pub struct Serializer; impl ser::Serializer for Serializer { type Ok = Value; type Error = Error; type SerializeSeq = SerializeArray; type SerializeTuple = SerializeArray; type SerializeTupleStruct = SerializeArray; type SerializeTupleVariant = SerializeTupleVariant; type SerializeMap = SerializeMap; type SerializeStruct = SerializeStruct; type SerializeStructVariant = SerializeStructVariant; fn serialize_bool(self, v: bool) -> Result { Ok(Value::Bool(v)) } fn serialize_i8(self, v: i8) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_i16(self, v: i16) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_i32(self, v: i32) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_i64(self, v: i64) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_i128(self, v: i128) -> Result { if let Ok(v) = u64::try_from(v) { self.serialize_u64(v) } else if let Ok(v) = i64::try_from(v) { self.serialize_i64(v) } else { Ok(Value::String(v.to_string())) } } fn serialize_u8(self, v: u8) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_u16(self, v: u16) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_u32(self, v: u32) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_u64(self, v: u64) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_u128(self, v: u128) -> Result { if let Ok(v) = u64::try_from(v) { self.serialize_u64(v) } else { Ok(Value::String(v.to_string())) } } fn serialize_f32(self, v: f32) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_f64(self, v: f64) -> Result { Ok(Value::Number(Number::from(v))) } fn serialize_char(self, value: char) -> Result { Ok(Value::String(value.to_string())) } fn serialize_str(self, value: &str) -> Result { Ok(Value::String(value.to_owned())) } fn serialize_bytes(self, value: &[u8]) -> Result { let vec = value .iter() .map(|&b| Value::Number(Number::from(b))) .collect(); Ok(Value::Sequence(vec)) } fn serialize_unit(self) -> Result { Ok(Value::Null) } fn serialize_unit_struct(self, _name: &'static str) -> Result { self.serialize_unit() } fn serialize_unit_variant( self, _name: &str, _variant_index: u32, variant: &str, ) -> Result { Ok(Value::String(variant.to_owned())) } fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result where T: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_newtype_variant( self, _name: &str, _variant_index: u32, variant: &str, value: &T, ) -> Result where T: ?Sized + ser::Serialize, { if variant.is_empty() { return Err(error::new(ErrorImpl::EmptyTag)); } Ok(Value::Tagged(Box::new(TaggedValue { tag: Tag::new(variant), value: to_value(value)?, }))) } fn serialize_none(self) -> Result { self.serialize_unit() } fn serialize_some(self, value: &V) -> Result where V: ?Sized + ser::Serialize, { value.serialize(self) } fn serialize_seq(self, len: Option) -> Result { let sequence = match len { None => Sequence::new(), Some(len) => Sequence::with_capacity(len), }; Ok(SerializeArray { sequence }) } fn serialize_tuple(self, len: usize) -> Result { self.serialize_seq(Some(len)) } fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result { self.serialize_seq(Some(len)) } fn serialize_tuple_variant( self, _enum: &'static str, _idx: u32, variant: &'static str, len: usize, ) -> Result { if variant.is_empty() { return Err(error::new(ErrorImpl::EmptyTag)); } Ok(SerializeTupleVariant { tag: variant, sequence: Sequence::with_capacity(len), }) } fn serialize_map(self, len: Option) -> Result { if len == Some(1) { Ok(SerializeMap::CheckForTag) } else { Ok(SerializeMap::Untagged { mapping: Mapping::new(), next_key: None, }) } } fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { Ok(SerializeStruct { mapping: Mapping::new(), }) } fn serialize_struct_variant( self, _enum: &'static str, _idx: u32, variant: &'static str, _len: usize, ) -> Result { if variant.is_empty() { return Err(error::new(ErrorImpl::EmptyTag)); } Ok(SerializeStructVariant { tag: variant, mapping: Mapping::new(), }) } } pub struct SerializeArray { sequence: Sequence, } impl ser::SerializeSeq for SerializeArray { type Ok = Value; type Error = Error; fn serialize_element(&mut self, elem: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.sequence.push(to_value(elem)?); Ok(()) } fn end(self) -> Result { Ok(Value::Sequence(self.sequence)) } } impl ser::SerializeTuple for SerializeArray { type Ok = Value; type Error = Error; fn serialize_element(&mut self, elem: &T) -> Result<()> where T: ?Sized + ser::Serialize, { ser::SerializeSeq::serialize_element(self, elem) } fn end(self) -> Result { ser::SerializeSeq::end(self) } } impl ser::SerializeTupleStruct for SerializeArray { type Ok = Value; type Error = Error; fn serialize_field(&mut self, value: &V) -> Result<()> where V: ?Sized + ser::Serialize, { ser::SerializeSeq::serialize_element(self, value) } fn end(self) -> Result { ser::SerializeSeq::end(self) } } pub struct SerializeTupleVariant { tag: &'static str, sequence: Sequence, } impl ser::SerializeTupleVariant for SerializeTupleVariant { type Ok = Value; type Error = Error; fn serialize_field(&mut self, v: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.sequence.push(to_value(v)?); Ok(()) } fn end(self) -> Result { Ok(Value::Tagged(Box::new(TaggedValue { tag: Tag::new(self.tag), value: Value::Sequence(self.sequence), }))) } } pub enum SerializeMap { CheckForTag, Tagged(TaggedValue), Untagged { mapping: Mapping, next_key: Option, }, } impl ser::SerializeMap for SerializeMap { type Ok = Value; type Error = Error; fn serialize_key(&mut self, key: &T) -> Result<()> where T: ?Sized + ser::Serialize, { let key = Some(to_value(key)?); match self { SerializeMap::CheckForTag => { *self = SerializeMap::Untagged { mapping: Mapping::new(), next_key: key, }; } SerializeMap::Tagged(tagged) => { let mut mapping = Mapping::new(); mapping.insert( Value::String(tagged.tag.to_string()), mem::take(&mut tagged.value), ); *self = SerializeMap::Untagged { mapping, next_key: key, }; } SerializeMap::Untagged { next_key, .. } => *next_key = key, } Ok(()) } fn serialize_value(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { let (mapping, key) = match self { SerializeMap::CheckForTag | SerializeMap::Tagged(_) => unreachable!(), SerializeMap::Untagged { mapping, next_key } => (mapping, next_key), }; match key.take() { Some(key) => mapping.insert(key, to_value(value)?), None => panic!("serialize_value called before serialize_key"), }; Ok(()) } fn serialize_entry(&mut self, key: &K, value: &V) -> Result<()> where K: ?Sized + ser::Serialize, V: ?Sized + ser::Serialize, { struct CheckForTag; struct NotTag { delegate: T, } impl ser::Serializer for CheckForTag { type Ok = MaybeTag; type Error = Error; type SerializeSeq = NotTag; type SerializeTuple = NotTag; type SerializeTupleStruct = NotTag; type SerializeTupleVariant = NotTag; type SerializeMap = NotTag; type SerializeStruct = NotTag; type SerializeStructVariant = NotTag; fn serialize_bool(self, v: bool) -> Result { Serializer.serialize_bool(v).map(MaybeTag::NotTag) } fn serialize_i8(self, v: i8) -> Result { Serializer.serialize_i8(v).map(MaybeTag::NotTag) } fn serialize_i16(self, v: i16) -> Result { Serializer.serialize_i16(v).map(MaybeTag::NotTag) } fn serialize_i32(self, v: i32) -> Result { Serializer.serialize_i32(v).map(MaybeTag::NotTag) } fn serialize_i64(self, v: i64) -> Result { Serializer.serialize_i64(v).map(MaybeTag::NotTag) } fn serialize_i128(self, v: i128) -> Result { Serializer.serialize_i128(v).map(MaybeTag::NotTag) } fn serialize_u8(self, v: u8) -> Result { Serializer.serialize_u8(v).map(MaybeTag::NotTag) } fn serialize_u16(self, v: u16) -> Result { Serializer.serialize_u16(v).map(MaybeTag::NotTag) } fn serialize_u32(self, v: u32) -> Result { Serializer.serialize_u32(v).map(MaybeTag::NotTag) } fn serialize_u64(self, v: u64) -> Result { Serializer.serialize_u64(v).map(MaybeTag::NotTag) } fn serialize_u128(self, v: u128) -> Result { Serializer.serialize_u128(v).map(MaybeTag::NotTag) } fn serialize_f32(self, v: f32) -> Result { Serializer.serialize_f32(v).map(MaybeTag::NotTag) } fn serialize_f64(self, v: f64) -> Result { Serializer.serialize_f64(v).map(MaybeTag::NotTag) } fn serialize_char(self, value: char) -> Result { Serializer.serialize_char(value).map(MaybeTag::NotTag) } fn serialize_str(self, value: &str) -> Result { Serializer.serialize_str(value).map(MaybeTag::NotTag) } fn serialize_bytes(self, value: &[u8]) -> Result { Serializer.serialize_bytes(value).map(MaybeTag::NotTag) } fn serialize_unit(self) -> Result { Serializer.serialize_unit().map(MaybeTag::NotTag) } fn serialize_unit_struct(self, name: &'static str) -> Result { Serializer.serialize_unit_struct(name).map(MaybeTag::NotTag) } fn serialize_unit_variant( self, name: &'static str, variant_index: u32, variant: &'static str, ) -> Result { Serializer .serialize_unit_variant(name, variant_index, variant) .map(MaybeTag::NotTag) } fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result where T: ?Sized + ser::Serialize, { Serializer .serialize_newtype_struct(name, value) .map(MaybeTag::NotTag) } fn serialize_newtype_variant( self, name: &'static str, variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: ?Sized + ser::Serialize, { Serializer .serialize_newtype_variant(name, variant_index, variant, value) .map(MaybeTag::NotTag) } fn serialize_none(self) -> Result { Serializer.serialize_none().map(MaybeTag::NotTag) } fn serialize_some(self, value: &V) -> Result where V: ?Sized + ser::Serialize, { Serializer.serialize_some(value).map(MaybeTag::NotTag) } fn serialize_seq(self, len: Option) -> Result { Ok(NotTag { delegate: Serializer.serialize_seq(len)?, }) } fn serialize_tuple(self, len: usize) -> Result { Ok(NotTag { delegate: Serializer.serialize_tuple(len)?, }) } fn serialize_tuple_struct( self, name: &'static str, len: usize, ) -> Result { Ok(NotTag { delegate: Serializer.serialize_tuple_struct(name, len)?, }) } fn serialize_tuple_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(NotTag { delegate: Serializer.serialize_tuple_variant( name, variant_index, variant, len, )?, }) } fn serialize_map(self, len: Option) -> Result { Ok(NotTag { delegate: Serializer.serialize_map(len)?, }) } fn serialize_struct( self, name: &'static str, len: usize, ) -> Result { Ok(NotTag { delegate: Serializer.serialize_struct(name, len)?, }) } fn serialize_struct_variant( self, name: &'static str, variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(NotTag { delegate: Serializer.serialize_struct_variant( name, variant_index, variant, len, )?, }) } fn collect_str(self, value: &T) -> Result where T: ?Sized + Display, { Ok(match tagged::check_for_tag(value) { MaybeTag::Tag(tag) => MaybeTag::Tag(tag), MaybeTag::NotTag(string) => MaybeTag::NotTag(Value::String(string)), }) } } impl ser::SerializeSeq for NotTag { type Ok = MaybeTag; type Error = Error; fn serialize_element(&mut self, elem: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.delegate.serialize_element(elem) } fn end(self) -> Result { self.delegate.end().map(MaybeTag::NotTag) } } impl ser::SerializeTuple for NotTag { type Ok = MaybeTag; type Error = Error; fn serialize_element(&mut self, elem: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.delegate.serialize_element(elem) } fn end(self) -> Result { self.delegate.end().map(MaybeTag::NotTag) } } impl ser::SerializeTupleStruct for NotTag { type Ok = MaybeTag; type Error = Error; fn serialize_field(&mut self, value: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.delegate.serialize_field(value) } fn end(self) -> Result { self.delegate.end().map(MaybeTag::NotTag) } } impl ser::SerializeTupleVariant for NotTag { type Ok = MaybeTag; type Error = Error; fn serialize_field(&mut self, v: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.delegate.serialize_field(v) } fn end(self) -> Result { self.delegate.end().map(MaybeTag::NotTag) } } impl ser::SerializeMap for NotTag { type Ok = MaybeTag; type Error = Error; fn serialize_key(&mut self, key: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.delegate.serialize_key(key) } fn serialize_value(&mut self, value: &T) -> Result<()> where T: ?Sized + ser::Serialize, { self.delegate.serialize_value(value) } fn serialize_entry(&mut self, key: &K, value: &V) -> Result<()> where K: ?Sized + ser::Serialize, V: ?Sized + ser::Serialize, { self.delegate.serialize_entry(key, value) } fn end(self) -> Result { self.delegate.end().map(MaybeTag::NotTag) } } impl ser::SerializeStruct for NotTag { type Ok = MaybeTag; type Error = Error; fn serialize_field(&mut self, key: &'static str, value: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.delegate.serialize_field(key, value) } fn end(self) -> Result { self.delegate.end().map(MaybeTag::NotTag) } } impl ser::SerializeStructVariant for NotTag { type Ok = MaybeTag; type Error = Error; fn serialize_field(&mut self, field: &'static str, v: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.delegate.serialize_field(field, v) } fn end(self) -> Result { self.delegate.end().map(MaybeTag::NotTag) } } match self { SerializeMap::CheckForTag => { let key = key.serialize(CheckForTag)?; let mut mapping = Mapping::new(); *self = match key { MaybeTag::Tag(string) => SerializeMap::Tagged(TaggedValue { tag: Tag::new(string), value: to_value(value)?, }), MaybeTag::NotTag(key) => { mapping.insert(key, to_value(value)?); SerializeMap::Untagged { mapping, next_key: None, } } }; } SerializeMap::Tagged(tagged) => { let mut mapping = Mapping::new(); mapping.insert( Value::String(tagged.tag.to_string()), mem::take(&mut tagged.value), ); mapping.insert(to_value(key)?, to_value(value)?); *self = SerializeMap::Untagged { mapping, next_key: None, }; } SerializeMap::Untagged { mapping, .. } => { mapping.insert(to_value(key)?, to_value(value)?); } } Ok(()) } fn end(self) -> Result { Ok(match self { SerializeMap::CheckForTag => Value::Mapping(Mapping::new()), SerializeMap::Tagged(tagged) => Value::Tagged(Box::new(tagged)), SerializeMap::Untagged { mapping, .. } => Value::Mapping(mapping), }) } } pub struct SerializeStruct { mapping: Mapping, } impl ser::SerializeStruct for SerializeStruct { type Ok = Value; type Error = Error; fn serialize_field(&mut self, key: &'static str, value: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.mapping.insert(to_value(key)?, to_value(value)?); Ok(()) } fn end(self) -> Result { Ok(Value::Mapping(self.mapping)) } } pub struct SerializeStructVariant { tag: &'static str, mapping: Mapping, } impl ser::SerializeStructVariant for SerializeStructVariant { type Ok = Value; type Error = Error; fn serialize_field(&mut self, field: &'static str, v: &V) -> Result<()> where V: ?Sized + ser::Serialize, { self.mapping.insert(to_value(field)?, to_value(v)?); Ok(()) } fn end(self) -> Result { Ok(Value::Tagged(Box::new(TaggedValue { tag: Tag::new(self.tag), value: Value::Mapping(self.mapping), }))) } } serde_norway-0.9.38/src/value/tagged.rs000064400000000000000000000310451046102023000161350ustar 00000000000000use crate::value::de::{MapDeserializer, MapRefDeserializer, SeqDeserializer, SeqRefDeserializer}; use crate::value::Value; use crate::Error; use serde::de::value::{BorrowedStrDeserializer, StrDeserializer}; use serde::de::{ Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error as _, VariantAccess, Visitor, }; use serde::forward_to_deserialize_any; use serde::ser::{Serialize, SerializeMap, Serializer}; use std::cmp::Ordering; use std::fmt::{self, Debug, Display}; use std::hash::{Hash, Hasher}; use std::mem; /// A representation of YAML's `!Tag` syntax, used for enums. /// /// Refer to the example code on [`TaggedValue`] for an example of deserializing /// tagged values. #[derive(Clone)] pub struct Tag { pub(crate) string: String, } /// A `Tag` + `Value` representing a tagged YAML scalar, sequence, or mapping. /// /// ``` /// use serde_norway::value::TaggedValue; /// use std::collections::BTreeMap; /// /// let yaml = " /// scalar: !Thing x /// sequence_flow: !Thing [first] /// sequence_block: !Thing /// - first /// mapping_flow: !Thing {k: v} /// mapping_block: !Thing /// k: v /// "; /// /// let data: BTreeMap = serde_norway::from_str(yaml).unwrap(); /// assert!(data["scalar"].tag == "Thing"); /// assert!(data["sequence_flow"].tag == "Thing"); /// assert!(data["sequence_block"].tag == "Thing"); /// assert!(data["mapping_flow"].tag == "Thing"); /// assert!(data["mapping_block"].tag == "Thing"); /// /// // The leading '!' in tags are not significant. The following is also true. /// assert!(data["scalar"].tag == "!Thing"); /// ``` #[derive(Clone, PartialEq, PartialOrd, Hash, Debug)] pub struct TaggedValue { #[allow(missing_docs)] pub tag: Tag, #[allow(missing_docs)] pub value: Value, } impl Tag { /// Create tag. /// /// The leading '!' is not significant. It may be provided, but does not /// have to be. The following are equivalent: /// /// ``` /// use serde_norway::value::Tag; /// /// assert_eq!(Tag::new("!Thing"), Tag::new("Thing")); /// /// let tag = Tag::new("Thing"); /// assert!(tag == "Thing"); /// assert!(tag == "!Thing"); /// assert!(tag.to_string() == "!Thing"); /// /// let tag = Tag::new("!Thing"); /// assert!(tag == "Thing"); /// assert!(tag == "!Thing"); /// assert!(tag.to_string() == "!Thing"); /// ``` /// /// Such a tag would serialize to `!Thing` in YAML regardless of whether a /// '!' was included in the call to `Tag::new`. /// /// # Panics /// /// Panics if `string.is_empty()`. There is no syntax in YAML for an empty /// tag. pub fn new(string: impl Into) -> Self { let tag: String = string.into(); assert!(!tag.is_empty(), "empty YAML tag is not allowed"); Tag { string: tag } } } impl Value { pub(crate) fn untag(self) -> Self { let mut cur = self; while let Value::Tagged(tagged) = cur { cur = tagged.value; } cur } pub(crate) fn untag_ref(&self) -> &Self { let mut cur = self; while let Value::Tagged(tagged) = cur { cur = &tagged.value; } cur } pub(crate) fn untag_mut(&mut self) -> &mut Self { let mut cur = self; while let Value::Tagged(tagged) = cur { cur = &mut tagged.value; } cur } } pub(crate) fn nobang(maybe_banged: &str) -> &str { match maybe_banged.strip_prefix('!') { Some("") | None => maybe_banged, Some(unbanged) => unbanged, } } impl Eq for Tag {} impl PartialEq for Tag { fn eq(&self, other: &Tag) -> bool { PartialEq::eq(nobang(&self.string), nobang(&other.string)) } } impl PartialEq for Tag where T: ?Sized + AsRef, { fn eq(&self, other: &T) -> bool { PartialEq::eq(nobang(&self.string), nobang(other.as_ref())) } } impl Ord for Tag { fn cmp(&self, other: &Self) -> Ordering { Ord::cmp(nobang(&self.string), nobang(&other.string)) } } impl PartialOrd for Tag { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Hash for Tag { fn hash(&self, hasher: &mut H) { nobang(&self.string).hash(hasher); } } impl Display for Tag { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "!{}", nobang(&self.string)) } } impl Debug for Tag { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Display::fmt(self, formatter) } } impl Serialize for TaggedValue { fn serialize(&self, serializer: S) -> Result where S: Serializer, { struct SerializeTag<'a>(&'a Tag); impl<'a> Serialize for SerializeTag<'a> { fn serialize(&self, serializer: S) -> Result where S: Serializer, { serializer.collect_str(self.0) } } let mut map = serializer.serialize_map(Some(1))?; map.serialize_entry(&SerializeTag(&self.tag), &self.value)?; map.end() } } impl<'de> Deserialize<'de> for TaggedValue { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct TaggedValueVisitor; impl<'de> Visitor<'de> for TaggedValueVisitor { type Value = TaggedValue; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a YAML value with a !Tag") } fn visit_enum(self, data: A) -> Result where A: EnumAccess<'de>, { let (tag, contents) = data.variant_seed(TagStringVisitor)?; let value = contents.newtype_variant()?; Ok(TaggedValue { tag, value }) } } deserializer.deserialize_any(TaggedValueVisitor) } } impl<'de> Deserializer<'de> for TaggedValue { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_enum(self) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { drop(self); visitor.visit_unit() } forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier } } impl<'de> EnumAccess<'de> for TaggedValue { type Error = Error; type Variant = Value; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Error> where V: DeserializeSeed<'de>, { let tag = StrDeserializer::::new(nobang(&self.tag.string)); let value = seed.deserialize(tag)?; Ok((value, self.value)) } } impl<'de> VariantAccess<'de> for Value { type Error = Error; fn unit_variant(self) -> Result<(), Error> { Deserialize::deserialize(self) } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { seed.deserialize(self) } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { if let Value::Sequence(v) = self { Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) } else { Err(Error::invalid_type(self.unexpected(), &"tuple variant")) } } fn struct_variant( self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { if let Value::Mapping(v) = self { Deserializer::deserialize_any(MapDeserializer::new(v), visitor) } else { Err(Error::invalid_type(self.unexpected(), &"struct variant")) } } } impl<'de> Deserializer<'de> for &'de TaggedValue { type Error = Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_enum(self) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_unit() } forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map struct enum identifier } } impl<'de> EnumAccess<'de> for &'de TaggedValue { type Error = Error; type Variant = &'de Value; fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Error> where V: DeserializeSeed<'de>, { let tag = BorrowedStrDeserializer::::new(nobang(&self.tag.string)); let value = seed.deserialize(tag)?; Ok((value, &self.value)) } } impl<'de> VariantAccess<'de> for &'de Value { type Error = Error; fn unit_variant(self) -> Result<(), Error> { Deserialize::deserialize(self) } fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { seed.deserialize(self) } fn tuple_variant(self, _len: usize, visitor: V) -> Result where V: Visitor<'de>, { if let Value::Sequence(v) = self { Deserializer::deserialize_any(SeqRefDeserializer::new(v), visitor) } else { Err(Error::invalid_type(self.unexpected(), &"tuple variant")) } } fn struct_variant( self, _fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { if let Value::Mapping(v) = self { Deserializer::deserialize_any(MapRefDeserializer::new(v), visitor) } else { Err(Error::invalid_type(self.unexpected(), &"struct variant")) } } } pub(crate) struct TagStringVisitor; impl<'de> Visitor<'de> for TagStringVisitor { type Value = Tag; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a YAML tag string") } fn visit_str(self, string: &str) -> Result where E: serde::de::Error, { self.visit_string(string.to_owned()) } fn visit_string(self, string: String) -> Result where E: serde::de::Error, { if string.is_empty() { return Err(E::custom("empty YAML tag is not allowed")); } Ok(Tag::new(string)) } } impl<'de> DeserializeSeed<'de> for TagStringVisitor { type Value = Tag; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_string(self) } } pub(crate) enum MaybeTag { Tag(String), NotTag(T), } pub(crate) fn check_for_tag(value: &T) -> MaybeTag where T: ?Sized + Display, { enum CheckForTag { Empty, Bang, Tag(String), NotTag(String), } impl fmt::Write for CheckForTag { fn write_str(&mut self, s: &str) -> fmt::Result { if s.is_empty() { return Ok(()); } match self { CheckForTag::Empty => { if s == "!" { *self = CheckForTag::Bang; } else { *self = CheckForTag::NotTag(s.to_owned()); } } CheckForTag::Bang => { *self = CheckForTag::Tag(s.to_owned()); } CheckForTag::Tag(string) => { let mut string = mem::take(string); string.push_str(s); *self = CheckForTag::NotTag(string); } CheckForTag::NotTag(string) => { string.push_str(s); } } Ok(()) } } let mut check_for_tag = CheckForTag::Empty; fmt::write(&mut check_for_tag, format_args!("{}", value)).unwrap(); match check_for_tag { CheckForTag::Empty => MaybeTag::NotTag(String::new()), CheckForTag::Bang => MaybeTag::NotTag("!".to_owned()), CheckForTag::Tag(string) => MaybeTag::Tag(string), CheckForTag::NotTag(string) => MaybeTag::NotTag(string), } } serde_norway-0.9.38/src/with.rs000064400000000000000000001664761046102023000145620ustar 00000000000000//! Customizations to use with Serde's `#[serde(with = …)]` attribute. /// Serialize/deserialize an enum using a YAML map containing one entry in which /// the key identifies the variant name. /// /// # Example /// /// ``` /// # use serde_derive::{Deserialize, Serialize}; /// use serde::{Deserialize, Serialize}; /// /// #[derive(Serialize, Deserialize, PartialEq, Debug)] /// enum Enum { /// Unit, /// Newtype(usize), /// Tuple(usize, usize), /// Struct { value: usize }, /// } /// /// #[derive(Serialize, Deserialize, PartialEq, Debug)] /// struct Struct { /// #[serde(with = "serde_norway::with::singleton_map")] /// w: Enum, /// #[serde(with = "serde_norway::with::singleton_map")] /// x: Enum, /// #[serde(with = "serde_norway::with::singleton_map")] /// y: Enum, /// #[serde(with = "serde_norway::with::singleton_map")] /// z: Enum, /// } /// /// fn main() { /// let object = Struct { /// w: Enum::Unit, /// x: Enum::Newtype(1), /// y: Enum::Tuple(1, 1), /// z: Enum::Struct { value: 1 }, /// }; /// /// let yaml = serde_norway::to_string(&object).unwrap(); /// print!("{}", yaml); /// /// let deserialized: Struct = serde_norway::from_str(&yaml).unwrap(); /// assert_eq!(object, deserialized); /// } /// ``` /// /// The representation using `singleton_map` on all the fields is: /// /// ```yaml /// w: Unit /// x: /// Newtype: 1 /// y: /// Tuple: /// - 1 /// - 1 /// z: /// Struct: /// value: 1 /// ``` /// /// Without `singleton_map`, the default behavior would have been to serialize /// as: /// /// ```yaml /// w: Unit /// x: !Newtype 1 /// y: !Tuple /// - 1 /// - 1 /// z: !Struct /// value: 1 /// ``` pub mod singleton_map { use crate::value::{Mapping, Sequence, Value}; use serde::de::{ self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, IgnoredAny, MapAccess, Unexpected, VariantAccess, Visitor, }; use serde::ser::{ self, Serialize, SerializeMap, SerializeStructVariant, SerializeTupleVariant, Serializer, }; use std::fmt::{self, Display}; #[allow(missing_docs)] pub fn serialize(value: &T, serializer: S) -> Result where T: Serialize, S: Serializer, { value.serialize(SingletonMap { delegate: serializer, }) } #[allow(missing_docs)] pub fn deserialize<'de, T, D>(deserializer: D) -> Result where T: Deserialize<'de>, D: Deserializer<'de>, { T::deserialize(SingletonMap { delegate: deserializer, }) } struct SingletonMap { delegate: D, } impl Serialize for SingletonMap where D: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.delegate.serialize(SingletonMap { delegate: serializer, }) } } impl Serializer for SingletonMap where D: Serializer, { type Ok = D::Ok; type Error = D::Error; type SerializeSeq = D::SerializeSeq; type SerializeTuple = D::SerializeTuple; type SerializeTupleStruct = D::SerializeTupleStruct; type SerializeTupleVariant = SerializeTupleVariantAsSingletonMap; type SerializeMap = D::SerializeMap; type SerializeStruct = D::SerializeStruct; type SerializeStructVariant = SerializeStructVariantAsSingletonMap; fn serialize_bool(self, v: bool) -> Result { self.delegate.serialize_bool(v) } fn serialize_i8(self, v: i8) -> Result { self.delegate.serialize_i8(v) } fn serialize_i16(self, v: i16) -> Result { self.delegate.serialize_i16(v) } fn serialize_i32(self, v: i32) -> Result { self.delegate.serialize_i32(v) } fn serialize_i64(self, v: i64) -> Result { self.delegate.serialize_i64(v) } fn serialize_i128(self, v: i128) -> Result { self.delegate.serialize_i128(v) } fn serialize_u8(self, v: u8) -> Result { self.delegate.serialize_u8(v) } fn serialize_u16(self, v: u16) -> Result { self.delegate.serialize_u16(v) } fn serialize_u32(self, v: u32) -> Result { self.delegate.serialize_u32(v) } fn serialize_u64(self, v: u64) -> Result { self.delegate.serialize_u64(v) } fn serialize_u128(self, v: u128) -> Result { self.delegate.serialize_u128(v) } fn serialize_f32(self, v: f32) -> Result { self.delegate.serialize_f32(v) } fn serialize_f64(self, v: f64) -> Result { self.delegate.serialize_f64(v) } fn serialize_char(self, v: char) -> Result { self.delegate.serialize_char(v) } fn serialize_str(self, v: &str) -> Result { self.delegate.serialize_str(v) } fn serialize_bytes(self, v: &[u8]) -> Result { self.delegate.serialize_bytes(v) } fn serialize_unit(self) -> Result { self.delegate.serialize_unit() } fn serialize_unit_struct(self, name: &'static str) -> Result { self.delegate.serialize_unit_struct(name) } fn serialize_unit_variant( self, name: &'static str, variant_index: u32, variant: &'static str, ) -> Result { self.delegate .serialize_unit_variant(name, variant_index, variant) } fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize, { self.delegate.serialize_newtype_struct(name, value) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize, { let mut map = self.delegate.serialize_map(Some(1))?; map.serialize_entry(variant, value)?; map.end() } fn serialize_none(self) -> Result { self.delegate.serialize_none() } fn serialize_some(self, value: &V) -> Result where V: ?Sized + Serialize, { self.delegate .serialize_some(&SingletonMap { delegate: value }) } fn serialize_seq(self, len: Option) -> Result { self.delegate.serialize_seq(len) } fn serialize_tuple(self, len: usize) -> Result { self.delegate.serialize_tuple(len) } fn serialize_tuple_struct( self, name: &'static str, len: usize, ) -> Result { self.delegate.serialize_tuple_struct(name, len) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { let mut map = self.delegate.serialize_map(Some(1))?; map.serialize_key(variant)?; let sequence = Sequence::with_capacity(len); Ok(SerializeTupleVariantAsSingletonMap { map, sequence }) } fn serialize_map(self, len: Option) -> Result { self.delegate.serialize_map(len) } fn serialize_struct( self, name: &'static str, len: usize, ) -> Result { self.delegate.serialize_struct(name, len) } fn serialize_struct_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { let mut map = self.delegate.serialize_map(Some(1))?; map.serialize_key(variant)?; let mapping = Mapping::with_capacity(len); Ok(SerializeStructVariantAsSingletonMap { map, mapping }) } fn collect_str(self, value: &T) -> Result where T: ?Sized + Display, { self.delegate.collect_str(value) } fn is_human_readable(&self) -> bool { self.delegate.is_human_readable() } } struct SerializeTupleVariantAsSingletonMap { map: M, sequence: Sequence, } impl SerializeTupleVariant for SerializeTupleVariantAsSingletonMap where M: SerializeMap, { type Ok = M::Ok; type Error = M::Error; fn serialize_field(&mut self, field: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { let value = field .serialize(crate::value::Serializer) .map_err(ser::Error::custom)?; self.sequence.push(value); Ok(()) } fn end(mut self) -> Result { self.map.serialize_value(&self.sequence)?; self.map.end() } } struct SerializeStructVariantAsSingletonMap { map: M, mapping: Mapping, } impl SerializeStructVariant for SerializeStructVariantAsSingletonMap where M: SerializeMap, { type Ok = M::Ok; type Error = M::Error; fn serialize_field(&mut self, name: &'static str, field: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { let value = field .serialize(crate::value::Serializer) .map_err(ser::Error::custom)?; self.mapping.insert(Value::String(name.to_owned()), value); Ok(()) } fn end(mut self) -> Result { self.map.serialize_value(&self.mapping)?; self.map.end() } } impl<'de, D> Deserializer<'de> for SingletonMap where D: Deserializer<'de>, { type Error = D::Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_any(visitor) } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_bool(visitor) } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_i8(visitor) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_i16(visitor) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_i32(visitor) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_i64(visitor) } fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_i128(visitor) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_u8(visitor) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_u16(visitor) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_u32(visitor) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_u64(visitor) } fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_u128(visitor) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_f32(visitor) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_f64(visitor) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_char(visitor) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_str(visitor) } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_string(visitor) } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_bytes(visitor) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_byte_buf(visitor) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_option(SingletonMapAsEnum { name: "", delegate: visitor, }) } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_unit(visitor) } fn deserialize_unit_struct( self, name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate.deserialize_unit_struct(name, visitor) } fn deserialize_newtype_struct( self, name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate.deserialize_newtype_struct(name, visitor) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_seq(visitor) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_tuple(len, visitor) } fn deserialize_tuple_struct( self, name: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate.deserialize_tuple_struct(name, len, visitor) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_map(visitor) } fn deserialize_struct( self, name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate.deserialize_struct(name, fields, visitor) } fn deserialize_enum( self, name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate.deserialize_any(SingletonMapAsEnum { name, delegate: visitor, }) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_identifier(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate.deserialize_ignored_any(visitor) } fn is_human_readable(&self) -> bool { self.delegate.is_human_readable() } } struct SingletonMapAsEnum { name: &'static str, delegate: D, } impl<'de, V> Visitor<'de> for SingletonMapAsEnum where V: Visitor<'de>, { type Value = V::Value; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.delegate.expecting(formatter) } fn visit_str(self, v: &str) -> Result where E: de::Error, { self.delegate.visit_enum(de::value::StrDeserializer::new(v)) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: de::Error, { self.delegate .visit_enum(de::value::BorrowedStrDeserializer::new(v)) } fn visit_string(self, v: String) -> Result where E: de::Error, { self.delegate .visit_enum(de::value::StringDeserializer::new(v)) } fn visit_none(self) -> Result where E: de::Error, { self.delegate.visit_none() } fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { self.delegate.visit_some(SingletonMap { delegate: deserializer, }) } fn visit_unit(self) -> Result where E: de::Error, { self.delegate.visit_unit() } fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { self.delegate.visit_enum(SingletonMapAsEnum { name: self.name, delegate: map, }) } } impl<'de, D> EnumAccess<'de> for SingletonMapAsEnum where D: MapAccess<'de>, { type Error = D::Error; type Variant = Self; fn variant_seed(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: DeserializeSeed<'de>, { match self.delegate.next_key_seed(seed)? { Some(value) => Ok((value, self)), None => Err(de::Error::invalid_value( Unexpected::Map, &"map with a single key", )), } } } impl<'de, D> VariantAccess<'de> for SingletonMapAsEnum where D: MapAccess<'de>, { type Error = D::Error; fn unit_variant(self) -> Result<(), Self::Error> { Err(de::Error::invalid_type(Unexpected::Map, &"unit variant")) } fn newtype_variant_seed(mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { let value = self.delegate.next_value_seed(seed)?; match self.delegate.next_key()? { None => Ok(value), Some(IgnoredAny) => Err(de::Error::invalid_value( Unexpected::Map, &"map with a single key", )), } } fn tuple_variant(mut self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { let value = self .delegate .next_value_seed(TupleVariantSeed { len, visitor })?; match self.delegate.next_key()? { None => Ok(value), Some(IgnoredAny) => Err(de::Error::invalid_value( Unexpected::Map, &"map with a single key", )), } } fn struct_variant( mut self, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let value = self.delegate.next_value_seed(StructVariantSeed { name: self.name, fields, visitor, })?; match self.delegate.next_key()? { None => Ok(value), Some(IgnoredAny) => Err(de::Error::invalid_value( Unexpected::Map, &"map with a single key", )), } } } struct TupleVariantSeed { len: usize, visitor: V, } impl<'de, V> DeserializeSeed<'de> for TupleVariantSeed 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 StructVariantSeed { name: &'static str, fields: &'static [&'static str], visitor: V, } impl<'de, V> DeserializeSeed<'de> for StructVariantSeed where V: Visitor<'de>, { type Value = V::Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_struct(self.name, self.fields, self.visitor) } } } /// Apply [`singleton_map`] to *all* enums contained within the data structure. /// /// # Example /// /// ``` /// # use serde_derive::{Deserialize, Serialize}; /// use serde::{Deserialize, Serialize}; /// /// #[derive(Serialize, Deserialize, PartialEq, Debug)] /// enum Enum { /// Int(i32), /// } /// /// #[derive(Serialize, Deserialize, PartialEq, Debug)] /// struct Inner { /// a: Enum, /// bs: Vec, /// } /// /// #[derive(Serialize, Deserialize, PartialEq, Debug)] /// struct Outer { /// tagged_style: Inner, /// /// #[serde(with = "serde_norway::with::singleton_map_recursive")] /// singleton_map_style: Inner, /// } /// /// fn main() { /// let object = Outer { /// tagged_style: Inner { /// a: Enum::Int(0), /// bs: vec![Enum::Int(1)], /// }, /// singleton_map_style: Inner { /// a: Enum::Int(2), /// bs: vec![Enum::Int(3)], /// }, /// }; /// /// let yaml = serde_norway::to_string(&object).unwrap(); /// print!("{}", yaml); /// /// let deserialized: Outer = serde_norway::from_str(&yaml).unwrap(); /// assert_eq!(object, deserialized); /// } /// ``` /// /// The serialized output is: /// /// ```yaml /// tagged_style: /// a: !Int 0 /// bs: /// - !Int 1 /// singleton_map_style: /// a: /// Int: 2 /// bs: /// - Int: 3 /// ``` /// /// This module can also be used for the top-level serializer or deserializer /// call, without `serde(with = …)`, as follows. /// /// ``` /// # use serde_derive::{Deserialize, Serialize}; /// # use serde::{Deserialize, Serialize}; /// # /// # #[derive(Serialize, Deserialize, PartialEq, Debug)] /// # enum Enum { /// # Int(i32), /// # } /// # /// # #[derive(Serialize, Deserialize, PartialEq, Debug)] /// # struct Inner { /// # a: Enum, /// # bs: Vec, /// # } /// # /// use std::io::{self, Write}; /// /// fn main() { /// let object = Inner { /// a: Enum::Int(0), /// bs: vec![Enum::Int(1)], /// }; /// /// let mut buf = Vec::new(); /// let mut serializer = serde_norway::Serializer::new(&mut buf); /// serde_norway::with::singleton_map_recursive::serialize(&object, &mut serializer).unwrap(); /// io::stdout().write_all(&buf).unwrap(); /// /// let deserializer = serde_norway::Deserializer::from_slice(&buf); /// let deserialized: Inner = serde_norway::with::singleton_map_recursive::deserialize(deserializer).unwrap(); /// assert_eq!(object, deserialized); /// } /// ``` pub mod singleton_map_recursive { use crate::value::{Mapping, Sequence, Value}; use serde::de::{ self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, IgnoredAny, MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, }; use serde::ser::{ self, Serialize, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, Serializer, }; use std::fmt::{self, Display}; #[allow(missing_docs)] pub fn serialize(value: &T, serializer: S) -> Result where T: Serialize, S: Serializer, { value.serialize(SingletonMapRecursive { delegate: serializer, }) } #[allow(missing_docs)] pub fn deserialize<'de, T, D>(deserializer: D) -> Result where T: Deserialize<'de>, D: Deserializer<'de>, { T::deserialize(SingletonMapRecursive { delegate: deserializer, }) } struct SingletonMapRecursive { delegate: D, } impl Serialize for SingletonMapRecursive where D: Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.delegate.serialize(SingletonMapRecursive { delegate: serializer, }) } } impl Serializer for SingletonMapRecursive where D: Serializer, { type Ok = D::Ok; type Error = D::Error; type SerializeSeq = SingletonMapRecursive; type SerializeTuple = SingletonMapRecursive; type SerializeTupleStruct = SingletonMapRecursive; type SerializeTupleVariant = SerializeTupleVariantAsSingletonMapRecursive; type SerializeMap = SingletonMapRecursive; type SerializeStruct = SingletonMapRecursive; type SerializeStructVariant = SerializeStructVariantAsSingletonMapRecursive; fn serialize_bool(self, v: bool) -> Result { self.delegate.serialize_bool(v) } fn serialize_i8(self, v: i8) -> Result { self.delegate.serialize_i8(v) } fn serialize_i16(self, v: i16) -> Result { self.delegate.serialize_i16(v) } fn serialize_i32(self, v: i32) -> Result { self.delegate.serialize_i32(v) } fn serialize_i64(self, v: i64) -> Result { self.delegate.serialize_i64(v) } fn serialize_i128(self, v: i128) -> Result { self.delegate.serialize_i128(v) } fn serialize_u8(self, v: u8) -> Result { self.delegate.serialize_u8(v) } fn serialize_u16(self, v: u16) -> Result { self.delegate.serialize_u16(v) } fn serialize_u32(self, v: u32) -> Result { self.delegate.serialize_u32(v) } fn serialize_u64(self, v: u64) -> Result { self.delegate.serialize_u64(v) } fn serialize_u128(self, v: u128) -> Result { self.delegate.serialize_u128(v) } fn serialize_f32(self, v: f32) -> Result { self.delegate.serialize_f32(v) } fn serialize_f64(self, v: f64) -> Result { self.delegate.serialize_f64(v) } fn serialize_char(self, v: char) -> Result { self.delegate.serialize_char(v) } fn serialize_str(self, v: &str) -> Result { self.delegate.serialize_str(v) } fn serialize_bytes(self, v: &[u8]) -> Result { self.delegate.serialize_bytes(v) } fn serialize_unit(self) -> Result { self.delegate.serialize_unit() } fn serialize_unit_struct(self, name: &'static str) -> Result { self.delegate.serialize_unit_struct(name) } fn serialize_unit_variant( self, name: &'static str, variant_index: u32, variant: &'static str, ) -> Result { self.delegate .serialize_unit_variant(name, variant_index, variant) } fn serialize_newtype_struct( self, name: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize, { self.delegate .serialize_newtype_struct(name, &SingletonMapRecursive { delegate: value }) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: ?Sized + Serialize, { let mut map = self.delegate.serialize_map(Some(1))?; map.serialize_entry(variant, &SingletonMapRecursive { delegate: value })?; map.end() } fn serialize_none(self) -> Result { self.delegate.serialize_none() } fn serialize_some(self, value: &V) -> Result where V: ?Sized + Serialize, { self.delegate .serialize_some(&SingletonMapRecursive { delegate: value }) } fn serialize_seq(self, len: Option) -> Result { Ok(SingletonMapRecursive { delegate: self.delegate.serialize_seq(len)?, }) } fn serialize_tuple(self, len: usize) -> Result { Ok(SingletonMapRecursive { delegate: self.delegate.serialize_tuple(len)?, }) } fn serialize_tuple_struct( self, name: &'static str, len: usize, ) -> Result { Ok(SingletonMapRecursive { delegate: self.delegate.serialize_tuple_struct(name, len)?, }) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { let mut map = self.delegate.serialize_map(Some(1))?; map.serialize_key(variant)?; let sequence = Sequence::with_capacity(len); Ok(SerializeTupleVariantAsSingletonMapRecursive { map, sequence }) } fn serialize_map(self, len: Option) -> Result { Ok(SingletonMapRecursive { delegate: self.delegate.serialize_map(len)?, }) } fn serialize_struct( self, name: &'static str, len: usize, ) -> Result { Ok(SingletonMapRecursive { delegate: self.delegate.serialize_struct(name, len)?, }) } fn serialize_struct_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { let mut map = self.delegate.serialize_map(Some(1))?; map.serialize_key(variant)?; let mapping = Mapping::with_capacity(len); Ok(SerializeStructVariantAsSingletonMapRecursive { map, mapping }) } fn collect_str(self, value: &T) -> Result where T: ?Sized + Display, { self.delegate.collect_str(value) } fn is_human_readable(&self) -> bool { self.delegate.is_human_readable() } } impl SerializeSeq for SingletonMapRecursive where D: SerializeSeq, { type Ok = D::Ok; type Error = D::Error; fn serialize_element(&mut self, elem: &T) -> Result<(), Self::Error> where T: ?Sized + ser::Serialize, { self.delegate .serialize_element(&SingletonMapRecursive { delegate: elem }) } fn end(self) -> Result { self.delegate.end() } } impl SerializeTuple for SingletonMapRecursive where D: SerializeTuple, { type Ok = D::Ok; type Error = D::Error; fn serialize_element(&mut self, elem: &T) -> Result<(), Self::Error> where T: ?Sized + ser::Serialize, { self.delegate .serialize_element(&SingletonMapRecursive { delegate: elem }) } fn end(self) -> Result { self.delegate.end() } } impl SerializeTupleStruct for SingletonMapRecursive where D: SerializeTupleStruct, { type Ok = D::Ok; type Error = D::Error; fn serialize_field(&mut self, value: &V) -> Result<(), Self::Error> where V: ?Sized + ser::Serialize, { self.delegate .serialize_field(&SingletonMapRecursive { delegate: value }) } fn end(self) -> Result { self.delegate.end() } } struct SerializeTupleVariantAsSingletonMapRecursive { map: M, sequence: Sequence, } impl SerializeTupleVariant for SerializeTupleVariantAsSingletonMapRecursive where M: SerializeMap, { type Ok = M::Ok; type Error = M::Error; fn serialize_field(&mut self, field: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { let value = field .serialize(SingletonMapRecursive { delegate: crate::value::Serializer, }) .map_err(ser::Error::custom)?; self.sequence.push(value); Ok(()) } fn end(mut self) -> Result { self.map.serialize_value(&self.sequence)?; self.map.end() } } impl SerializeMap for SingletonMapRecursive where D: SerializeMap, { type Ok = D::Ok; type Error = D::Error; fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> where T: ?Sized + ser::Serialize, { self.delegate .serialize_key(&SingletonMapRecursive { delegate: key }) } fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> where T: ?Sized + ser::Serialize, { self.delegate .serialize_value(&SingletonMapRecursive { delegate: value }) } fn serialize_entry(&mut self, key: &K, value: &V) -> Result<(), Self::Error> where K: ?Sized + ser::Serialize, V: ?Sized + ser::Serialize, { self.delegate.serialize_entry( &SingletonMapRecursive { delegate: key }, &SingletonMapRecursive { delegate: value }, ) } fn end(self) -> Result { self.delegate.end() } } impl SerializeStruct for SingletonMapRecursive where D: SerializeStruct, { type Ok = D::Ok; type Error = D::Error; fn serialize_field(&mut self, key: &'static str, value: &V) -> Result<(), Self::Error> where V: ?Sized + ser::Serialize, { self.delegate .serialize_field(key, &SingletonMapRecursive { delegate: value }) } fn end(self) -> Result { self.delegate.end() } } struct SerializeStructVariantAsSingletonMapRecursive { map: M, mapping: Mapping, } impl SerializeStructVariant for SerializeStructVariantAsSingletonMapRecursive where M: SerializeMap, { type Ok = M::Ok; type Error = M::Error; fn serialize_field(&mut self, name: &'static str, field: &T) -> Result<(), Self::Error> where T: ?Sized + Serialize, { let value = field .serialize(SingletonMapRecursive { delegate: crate::value::Serializer, }) .map_err(ser::Error::custom)?; self.mapping.insert(Value::String(name.to_owned()), value); Ok(()) } fn end(mut self) -> Result { self.map.serialize_value(&self.mapping)?; self.map.end() } } impl<'de, D> Deserializer<'de> for SingletonMapRecursive where D: Deserializer<'de>, { type Error = D::Error; fn deserialize_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_any(SingletonMapRecursive { delegate: visitor }) } fn deserialize_bool(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_bool(SingletonMapRecursive { delegate: visitor }) } fn deserialize_i8(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_i8(SingletonMapRecursive { delegate: visitor }) } fn deserialize_i16(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_i16(SingletonMapRecursive { delegate: visitor }) } fn deserialize_i32(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_i32(SingletonMapRecursive { delegate: visitor }) } fn deserialize_i64(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_i64(SingletonMapRecursive { delegate: visitor }) } fn deserialize_i128(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_i128(SingletonMapRecursive { delegate: visitor }) } fn deserialize_u8(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_u8(SingletonMapRecursive { delegate: visitor }) } fn deserialize_u16(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_u16(SingletonMapRecursive { delegate: visitor }) } fn deserialize_u32(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_u32(SingletonMapRecursive { delegate: visitor }) } fn deserialize_u64(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_u64(SingletonMapRecursive { delegate: visitor }) } fn deserialize_u128(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_u128(SingletonMapRecursive { delegate: visitor }) } fn deserialize_f32(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_f32(SingletonMapRecursive { delegate: visitor }) } fn deserialize_f64(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_f64(SingletonMapRecursive { delegate: visitor }) } fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_char(SingletonMapRecursive { delegate: visitor }) } fn deserialize_str(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_str(SingletonMapRecursive { delegate: visitor }) } fn deserialize_string(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_string(SingletonMapRecursive { delegate: visitor }) } fn deserialize_bytes(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_bytes(SingletonMapRecursive { delegate: visitor }) } fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_byte_buf(SingletonMapRecursive { delegate: visitor }) } fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_option(SingletonMapRecursiveAsEnum { name: "", delegate: visitor, }) } fn deserialize_unit(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_unit(SingletonMapRecursive { delegate: visitor }) } fn deserialize_unit_struct( self, name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate .deserialize_unit_struct(name, SingletonMapRecursive { delegate: visitor }) } fn deserialize_newtype_struct( self, name: &'static str, visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate .deserialize_newtype_struct(name, SingletonMapRecursive { delegate: visitor }) } fn deserialize_seq(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_seq(SingletonMapRecursive { delegate: visitor }) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_tuple(len, SingletonMapRecursive { delegate: visitor }) } fn deserialize_tuple_struct( self, name: &'static str, len: usize, visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate.deserialize_tuple_struct( name, len, SingletonMapRecursive { delegate: visitor }, ) } fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_map(SingletonMapRecursive { delegate: visitor }) } fn deserialize_struct( self, name: &'static str, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate.deserialize_struct( name, fields, SingletonMapRecursive { delegate: visitor }, ) } fn deserialize_enum( self, name: &'static str, _variants: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { self.delegate.deserialize_any(SingletonMapRecursiveAsEnum { name, delegate: visitor, }) } fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_identifier(SingletonMapRecursive { delegate: visitor }) } fn deserialize_ignored_any(self, visitor: V) -> Result where V: Visitor<'de>, { self.delegate .deserialize_ignored_any(SingletonMapRecursive { delegate: visitor }) } fn is_human_readable(&self) -> bool { self.delegate.is_human_readable() } } impl<'de, V> Visitor<'de> for SingletonMapRecursive where V: Visitor<'de>, { type Value = V::Value; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.delegate.expecting(formatter) } fn visit_bool(self, v: bool) -> Result where E: de::Error, { self.delegate.visit_bool(v) } fn visit_i8(self, v: i8) -> Result where E: de::Error, { self.delegate.visit_i8(v) } fn visit_i16(self, v: i16) -> Result where E: de::Error, { self.delegate.visit_i16(v) } fn visit_i32(self, v: i32) -> Result where E: de::Error, { self.delegate.visit_i32(v) } fn visit_i64(self, v: i64) -> Result where E: de::Error, { self.delegate.visit_i64(v) } fn visit_i128(self, v: i128) -> Result where E: de::Error, { self.delegate.visit_i128(v) } fn visit_u8(self, v: u8) -> Result where E: de::Error, { self.delegate.visit_u8(v) } fn visit_u16(self, v: u16) -> Result where E: de::Error, { self.delegate.visit_u16(v) } fn visit_u32(self, v: u32) -> Result where E: de::Error, { self.delegate.visit_u32(v) } fn visit_u64(self, v: u64) -> Result where E: de::Error, { self.delegate.visit_u64(v) } fn visit_u128(self, v: u128) -> Result where E: de::Error, { self.delegate.visit_u128(v) } fn visit_f32(self, v: f32) -> Result where E: de::Error, { self.delegate.visit_f32(v) } fn visit_f64(self, v: f64) -> Result where E: de::Error, { self.delegate.visit_f64(v) } fn visit_char(self, v: char) -> Result where E: de::Error, { self.delegate.visit_char(v) } fn visit_str(self, v: &str) -> Result where E: de::Error, { self.delegate.visit_str(v) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: de::Error, { self.delegate.visit_borrowed_str(v) } fn visit_string(self, v: String) -> Result where E: de::Error, { self.delegate.visit_string(v) } fn visit_bytes(self, v: &[u8]) -> Result where E: de::Error, { self.delegate.visit_bytes(v) } fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result where E: de::Error, { self.delegate.visit_borrowed_bytes(v) } fn visit_byte_buf(self, v: Vec) -> Result where E: de::Error, { self.delegate.visit_byte_buf(v) } fn visit_none(self) -> Result where E: de::Error, { self.delegate.visit_none() } fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { self.delegate.visit_some(SingletonMapRecursive { delegate: deserializer, }) } fn visit_unit(self) -> Result where E: de::Error, { self.delegate.visit_unit() } fn visit_newtype_struct(self, deserializer: D) -> Result where D: Deserializer<'de>, { self.delegate.visit_newtype_struct(SingletonMapRecursive { delegate: deserializer, }) } fn visit_seq(self, seq: A) -> Result where A: SeqAccess<'de>, { self.delegate .visit_seq(SingletonMapRecursive { delegate: seq }) } fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { self.delegate .visit_map(SingletonMapRecursive { delegate: map }) } } impl<'de, T> DeserializeSeed<'de> for SingletonMapRecursive where T: DeserializeSeed<'de>, { type Value = T::Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { self.delegate.deserialize(SingletonMapRecursive { delegate: deserializer, }) } } impl<'de, S> SeqAccess<'de> for SingletonMapRecursive where S: SeqAccess<'de>, { type Error = S::Error; fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> where T: DeserializeSeed<'de>, { self.delegate .next_element_seed(SingletonMapRecursive { delegate: seed }) } } impl<'de, M> MapAccess<'de> for SingletonMapRecursive where M: MapAccess<'de>, { type Error = M::Error; fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> where K: DeserializeSeed<'de>, { self.delegate .next_key_seed(SingletonMapRecursive { delegate: seed }) } fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, { self.delegate .next_value_seed(SingletonMapRecursive { delegate: seed }) } } struct SingletonMapRecursiveAsEnum { name: &'static str, delegate: D, } impl<'de, V> Visitor<'de> for SingletonMapRecursiveAsEnum where V: Visitor<'de>, { type Value = V::Value; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.delegate.expecting(formatter) } fn visit_str(self, v: &str) -> Result where E: de::Error, { self.delegate.visit_enum(de::value::StrDeserializer::new(v)) } fn visit_borrowed_str(self, v: &'de str) -> Result where E: de::Error, { self.delegate .visit_enum(de::value::BorrowedStrDeserializer::new(v)) } fn visit_string(self, v: String) -> Result where E: de::Error, { self.delegate .visit_enum(de::value::StringDeserializer::new(v)) } fn visit_none(self) -> Result where E: de::Error, { self.delegate.visit_none() } fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { self.delegate.visit_some(SingletonMapRecursive { delegate: deserializer, }) } fn visit_unit(self) -> Result where E: de::Error, { self.delegate.visit_unit() } fn visit_map(self, map: A) -> Result where A: MapAccess<'de>, { self.delegate.visit_enum(SingletonMapRecursiveAsEnum { name: self.name, delegate: map, }) } } impl<'de, D> EnumAccess<'de> for SingletonMapRecursiveAsEnum where D: MapAccess<'de>, { type Error = D::Error; type Variant = Self; fn variant_seed(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: DeserializeSeed<'de>, { match self.delegate.next_key_seed(seed)? { Some(value) => Ok((value, self)), None => Err(de::Error::invalid_value( Unexpected::Map, &"map with a single key", )), } } } impl<'de, D> VariantAccess<'de> for SingletonMapRecursiveAsEnum where D: MapAccess<'de>, { type Error = D::Error; fn unit_variant(self) -> Result<(), Self::Error> { Err(de::Error::invalid_type(Unexpected::Map, &"unit variant")) } fn newtype_variant_seed(mut self, seed: T) -> Result where T: DeserializeSeed<'de>, { let value = self .delegate .next_value_seed(SingletonMapRecursive { delegate: seed })?; match self.delegate.next_key()? { None => Ok(value), Some(IgnoredAny) => Err(de::Error::invalid_value( Unexpected::Map, &"map with a single key", )), } } fn tuple_variant(mut self, len: usize, visitor: V) -> Result where V: Visitor<'de>, { let value = self.delegate.next_value_seed(TupleVariantSeed { len, visitor: SingletonMapRecursive { delegate: visitor }, })?; match self.delegate.next_key()? { None => Ok(value), Some(IgnoredAny) => Err(de::Error::invalid_value( Unexpected::Map, &"map with a single key", )), } } fn struct_variant( mut self, fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { let value = self.delegate.next_value_seed(StructVariantSeed { name: self.name, fields, visitor: SingletonMapRecursive { delegate: visitor }, })?; match self.delegate.next_key()? { None => Ok(value), Some(IgnoredAny) => Err(de::Error::invalid_value( Unexpected::Map, &"map with a single key", )), } } } struct TupleVariantSeed { len: usize, visitor: V, } impl<'de, V> DeserializeSeed<'de> for TupleVariantSeed 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 StructVariantSeed { name: &'static str, fields: &'static [&'static str], visitor: V, } impl<'de, V> DeserializeSeed<'de> for StructVariantSeed where V: Visitor<'de>, { type Value = V::Value; fn deserialize(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_struct(self.name, self.fields, self.visitor) } } } serde_norway-0.9.38/tests/test_de.rs000064400000000000000000000423521046102023000155730ustar 00000000000000#![allow( clippy::cast_lossless, clippy::cast_possible_wrap, clippy::derive_partial_eq_without_eq, clippy::similar_names, clippy::uninlined_format_args )] use indoc::indoc; use serde_derive::Deserialize; use serde_norway::{Deserializer, Number, Value}; use std::collections::BTreeMap; use std::fmt::Debug; fn test_de(yaml: &str, expected: &T) where T: serde::de::DeserializeOwned + PartialEq + Debug, { let deserialized: T = serde_norway::from_str(yaml).unwrap(); assert_eq!(*expected, deserialized); let value: Value = serde_norway::from_str(yaml).unwrap(); let deserialized = T::deserialize(&value).unwrap(); assert_eq!(*expected, deserialized); let deserialized: T = serde_norway::from_value(value).unwrap(); assert_eq!(*expected, deserialized); serde_norway::from_str::(yaml).unwrap(); let mut deserializer = Deserializer::from_str(yaml); let document = deserializer.next().unwrap(); let deserialized = T::deserialize(document).unwrap(); assert_eq!(*expected, deserialized); assert!(deserializer.next().is_none()); } fn test_de_no_value<'de, T>(yaml: &'de str, expected: &T) where T: serde::de::Deserialize<'de> + PartialEq + Debug, { let deserialized: T = serde_norway::from_str(yaml).unwrap(); assert_eq!(*expected, deserialized); serde_norway::from_str::(yaml).unwrap(); serde_norway::from_str::(yaml).unwrap(); } fn test_de_seed<'de, T, S>(yaml: &'de str, seed: S, expected: &T) where T: PartialEq + Debug, S: serde::de::DeserializeSeed<'de, Value = T>, { let deserialized: T = seed.deserialize(Deserializer::from_str(yaml)).unwrap(); assert_eq!(*expected, deserialized); serde_norway::from_str::(yaml).unwrap(); serde_norway::from_str::(yaml).unwrap(); } #[test] fn test_borrowed() { let yaml = indoc! {" - plain nonàscii - 'single quoted' - \"double quoted\" "}; let expected = vec!["plain nonàscii", "single quoted", "double quoted"]; test_de_no_value(yaml, &expected); } #[test] fn test_alias() { let yaml = indoc! {" first: &alias 1 second: *alias third: 3 "}; let mut expected = BTreeMap::new(); expected.insert("first".to_owned(), 1); expected.insert("second".to_owned(), 1); expected.insert("third".to_owned(), 3); test_de(yaml, &expected); } #[test] fn test_option() { #[derive(Deserialize, PartialEq, Debug)] struct Data { a: Option, b: Option, c: Option, } let yaml = indoc! {" b: c: true "}; let expected = Data { a: None, b: None, c: Some(true), }; test_de(yaml, &expected); } #[test] fn test_option_alias() { #[derive(Deserialize, PartialEq, Debug)] struct Data { a: Option, b: Option, c: Option, d: Option, e: Option, f: Option, } let yaml = indoc! {" none_f: &none_f ~ none_s: &none_s ~ none_b: &none_b ~ some_f: &some_f 1.0 some_s: &some_s x some_b: &some_b true a: *none_f b: *none_s c: *none_b d: *some_f e: *some_s f: *some_b "}; let expected = Data { a: None, b: None, c: None, d: Some(1.0), e: Some("x".to_owned()), f: Some(true), }; test_de(yaml, &expected); } #[test] fn test_enum_alias() { #[derive(Deserialize, PartialEq, Debug)] enum E { A, B(u8, u8), } #[derive(Deserialize, PartialEq, Debug)] struct Data { a: E, b: E, } let yaml = indoc! {" aref: &aref A bref: &bref !B - 1 - 2 a: *aref b: *bref "}; let expected = Data { a: E::A, b: E::B(1, 2), }; test_de(yaml, &expected); } #[test] fn test_enum_representations() { #[derive(Deserialize, PartialEq, Debug)] enum Enum { Unit, Tuple(i32, i32), Struct { x: i32, y: i32 }, String(String), Number(f64), } let yaml = indoc! {" - Unit - 'Unit' - !Unit - !Unit ~ - !Unit null - !Tuple [0, 0] - !Tuple - 0 - 0 - !Struct {x: 0, y: 0} - !Struct x: 0 y: 0 - !String '...' - !String ... - !Number 0 "}; let expected = vec![ Enum::Unit, Enum::Unit, Enum::Unit, Enum::Unit, Enum::Unit, Enum::Tuple(0, 0), Enum::Tuple(0, 0), Enum::Struct { x: 0, y: 0 }, Enum::Struct { x: 0, y: 0 }, Enum::String("...".to_owned()), Enum::String("...".to_owned()), Enum::Number(0.0), ]; test_de(yaml, &expected); let yaml = indoc! {" - !String "}; let expected = vec![Enum::String(String::new())]; test_de_no_value(yaml, &expected); } #[test] fn test_number_as_string() { #[derive(Deserialize, PartialEq, Debug)] struct Num { value: String, } let yaml = indoc! {" # Cannot be represented as u128 value: 340282366920938463463374607431768211457 "}; let expected = Num { value: "340282366920938463463374607431768211457".to_owned(), }; test_de_no_value(yaml, &expected); } #[test] fn test_empty_string() { #[derive(Deserialize, PartialEq, Debug)] struct Struct { empty: String, tilde: String, } let yaml = indoc! {" empty: tilde: ~ "}; let expected = Struct { empty: String::new(), tilde: "~".to_owned(), }; test_de_no_value(yaml, &expected); } #[test] fn test_i128_big() { let expected: i128 = i64::MIN as i128 - 1; let yaml = indoc! {" -9223372036854775809 "}; assert_eq!(expected, serde_norway::from_str::(yaml).unwrap()); let octal = indoc! {" -0o1000000000000000000001 "}; assert_eq!(expected, serde_norway::from_str::(octal).unwrap()); } #[test] fn test_u128_big() { let expected: u128 = u64::MAX as u128 + 1; let yaml = indoc! {" 18446744073709551616 "}; assert_eq!(expected, serde_norway::from_str::(yaml).unwrap()); let octal = indoc! {" 0o2000000000000000000000 "}; assert_eq!(expected, serde_norway::from_str::(octal).unwrap()); } #[test] fn test_number_alias_as_string() { #[derive(Deserialize, PartialEq, Debug)] struct Num { version: String, value: String, } let yaml = indoc! {" version: &a 1.10 value: *a "}; let expected = Num { version: "1.10".to_owned(), value: "1.10".to_owned(), }; test_de_no_value(yaml, &expected); } #[test] fn test_de_mapping() { #[derive(Debug, Deserialize, PartialEq)] struct Data { pub substructure: serde_norway::Mapping, } let yaml = indoc! {" substructure: a: 'foo' b: 'bar' "}; let mut expected = Data { substructure: serde_norway::Mapping::new(), }; expected.substructure.insert( serde_norway::Value::String("a".to_owned()), serde_norway::Value::String("foo".to_owned()), ); expected.substructure.insert( serde_norway::Value::String("b".to_owned()), serde_norway::Value::String("bar".to_owned()), ); test_de(yaml, &expected); } #[test] fn test_byte_order_mark() { let yaml = "\u{feff}- 0\n"; let expected = vec![0]; test_de(yaml, &expected); } #[test] fn test_bomb() { #[derive(Debug, Deserialize, PartialEq)] struct Data { expected: String, } // This would deserialize an astronomical number of elements if we were // vulnerable. let yaml = indoc! {" a: &a ~ b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a] c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b] d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c] e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d] f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e] g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f] h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g] i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h] j: &j [*i,*i,*i,*i,*i,*i,*i,*i,*i] k: &k [*j,*j,*j,*j,*j,*j,*j,*j,*j] l: &l [*k,*k,*k,*k,*k,*k,*k,*k,*k] m: &m [*l,*l,*l,*l,*l,*l,*l,*l,*l] n: &n [*m,*m,*m,*m,*m,*m,*m,*m,*m] o: &o [*n,*n,*n,*n,*n,*n,*n,*n,*n] p: &p [*o,*o,*o,*o,*o,*o,*o,*o,*o] q: &q [*p,*p,*p,*p,*p,*p,*p,*p,*p] r: &r [*q,*q,*q,*q,*q,*q,*q,*q,*q] s: &s [*r,*r,*r,*r,*r,*r,*r,*r,*r] t: &t [*s,*s,*s,*s,*s,*s,*s,*s,*s] u: &u [*t,*t,*t,*t,*t,*t,*t,*t,*t] v: &v [*u,*u,*u,*u,*u,*u,*u,*u,*u] w: &w [*v,*v,*v,*v,*v,*v,*v,*v,*v] x: &x [*w,*w,*w,*w,*w,*w,*w,*w,*w] y: &y [*x,*x,*x,*x,*x,*x,*x,*x,*x] z: &z [*y,*y,*y,*y,*y,*y,*y,*y,*y] expected: string "}; let expected = Data { expected: "string".to_owned(), }; assert_eq!(expected, serde_norway::from_str::(yaml).unwrap()); } #[test] fn test_numbers() { let cases = [ ("0xF0", "240"), ("+0xF0", "240"), ("-0xF0", "-240"), ("0o70", "56"), ("+0o70", "56"), ("-0o70", "-56"), ("0b10", "2"), ("+0b10", "2"), ("-0b10", "-2"), ("127", "127"), ("+127", "127"), ("-127", "-127"), (".inf", ".inf"), (".Inf", ".inf"), (".INF", ".inf"), ("-.inf", "-.inf"), ("-.Inf", "-.inf"), ("-.INF", "-.inf"), (".nan", ".nan"), (".NaN", ".nan"), (".NAN", ".nan"), ("0.1", "0.1"), ]; for &(yaml, expected) in &cases { let value = serde_norway::from_str::(yaml).unwrap(); match value { Value::Number(number) => assert_eq!(number.to_string(), expected), _ => panic!("expected number. input={:?}, result={:?}", yaml, value), } } // NOT numbers. let cases = [ "0127", "+0127", "-0127", "++.inf", "+-.inf", "++1", "+-1", "-+1", "--1", "0x+1", "0x-1", "-0x+1", "-0x-1", "++0x1", "+-0x1", "-+0x1", "--0x1", ]; for yaml in &cases { let value = serde_norway::from_str::(yaml).unwrap(); match value { Value::String(string) => assert_eq!(string, *yaml), _ => panic!("expected string. input={:?}, result={:?}", yaml, value), } } } #[test] fn test_nan() { // There is no negative NaN in YAML. assert!(serde_norway::from_str::(".nan") .unwrap() .is_sign_positive()); assert!(serde_norway::from_str::(".nan") .unwrap() .is_sign_positive()); } #[test] fn test_stateful() { struct Seed(i64); impl<'de> serde::de::DeserializeSeed<'de> for Seed { type Value = i64; fn deserialize(self, deserializer: D) -> Result where D: serde::de::Deserializer<'de>, { struct Visitor(i64); impl<'de> serde::de::Visitor<'de> for Visitor { type Value = i64; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { write!(formatter, "an integer") } fn visit_i64(self, v: i64) -> Result { Ok(v * self.0) } fn visit_u64(self, v: u64) -> Result { Ok(v as i64 * self.0) } } deserializer.deserialize_any(Visitor(self.0)) } } let cases = [("3", 5, 15), ("6", 7, 42), ("-5", 9, -45)]; for &(yaml, seed, expected) in &cases { test_de_seed(yaml, Seed(seed), &expected); } } #[test] fn test_ignore_tag() { #[derive(Deserialize, Debug, PartialEq)] struct Data { struc: Struc, tuple: Tuple, newtype: Newtype, map: BTreeMap, vec: Vec, } #[derive(Deserialize, Debug, PartialEq)] struct Struc { x: usize, } #[derive(Deserialize, Debug, PartialEq)] struct Tuple(usize, usize); #[derive(Deserialize, Debug, PartialEq)] struct Newtype(usize); let yaml = indoc! {" struc: !wat x: 0 tuple: !wat - 0 - 0 newtype: !wat 0 map: !wat x: 0 vec: !wat - 0 "}; let expected = Data { struc: Struc { x: 0 }, tuple: Tuple(0, 0), newtype: Newtype(0), map: { let mut map = BTreeMap::new(); map.insert('x', 0); map }, vec: vec![0], }; test_de(yaml, &expected); } #[test] fn test_no_required_fields() { #[derive(Deserialize, PartialEq, Debug)] pub struct NoRequiredFields { optional: Option, } for document in ["", "# comment\n"] { let expected = NoRequiredFields { optional: None }; let deserialized: NoRequiredFields = serde_norway::from_str(document).unwrap(); assert_eq!(expected, deserialized); let expected = Vec::::new(); let deserialized: Vec = serde_norway::from_str(document).unwrap(); assert_eq!(expected, deserialized); let expected = BTreeMap::new(); let deserialized: BTreeMap = serde_norway::from_str(document).unwrap(); assert_eq!(expected, deserialized); let expected = None; let deserialized: Option = serde_norway::from_str(document).unwrap(); assert_eq!(expected, deserialized); let expected = Value::Null; let deserialized: Value = serde_norway::from_str(document).unwrap(); assert_eq!(expected, deserialized); } } #[test] fn test_empty_scalar() { #[derive(Deserialize, PartialEq, Debug)] struct Struct { thing: T, } let yaml = "thing:\n"; let expected = Struct { thing: serde_norway::Sequence::new(), }; test_de(yaml, &expected); let expected = Struct { thing: serde_norway::Mapping::new(), }; test_de(yaml, &expected); } #[test] fn test_python_safe_dump() { #[derive(Deserialize, PartialEq, Debug)] struct Frob { foo: u32, } // This matches output produced by PyYAML's `yaml.safe_dump` when using the // default_style parameter. // // >>> import yaml // >>> d = {"foo": 7200} // >>> print(yaml.safe_dump(d, default_style="|")) // "foo": !!int |- // 7200 // let yaml = indoc! {r#" "foo": !!int |- 7200 "#}; let expected = Frob { foo: 7200 }; test_de(yaml, &expected); } #[test] fn test_tag_resolution() { // https://yaml.org/spec/1.2.2/#1032-tag-resolution let yaml = indoc! {" - null - Null - NULL - ~ - - true - True - TRUE - false - False - FALSE - y - Y - yes - Yes - YES - n - N - no - No - NO - on - On - ON - off - Off - OFF "}; let expected = vec![ Value::Null, Value::Null, Value::Null, Value::Null, Value::Null, Value::Bool(true), Value::Bool(true), Value::Bool(true), Value::Bool(false), Value::Bool(false), Value::Bool(false), Value::String("y".to_owned()), Value::String("Y".to_owned()), Value::String("yes".to_owned()), Value::String("Yes".to_owned()), Value::String("YES".to_owned()), Value::String("n".to_owned()), Value::String("N".to_owned()), Value::String("no".to_owned()), Value::String("No".to_owned()), Value::String("NO".to_owned()), Value::String("on".to_owned()), Value::String("On".to_owned()), Value::String("ON".to_owned()), Value::String("off".to_owned()), Value::String("Off".to_owned()), Value::String("OFF".to_owned()), ]; test_de(yaml, &expected); } #[test] fn test_parse_number() { let n = "111".parse::().unwrap(); assert_eq!(n, Number::from(111)); let n = "-111".parse::().unwrap(); assert_eq!(n, Number::from(-111)); let n = "-1.1".parse::().unwrap(); assert_eq!(n, Number::from(-1.1)); let n = ".nan".parse::().unwrap(); assert_eq!(n, Number::from(f64::NAN)); assert!(n.as_f64().unwrap().is_sign_positive()); let n = ".inf".parse::().unwrap(); assert_eq!(n, Number::from(f64::INFINITY)); let n = "-.inf".parse::().unwrap(); assert_eq!(n, Number::from(f64::NEG_INFINITY)); let err = "null".parse::().unwrap_err(); assert_eq!(err.to_string(), "failed to parse YAML number"); let err = " 1 ".parse::().unwrap_err(); assert_eq!(err.to_string(), "failed to parse YAML number"); } serde_norway-0.9.38/tests/test_error.rs000064400000000000000000000300751046102023000163330ustar 00000000000000#![allow(clippy::zero_sized_map_values)] use indoc::indoc; use serde::de::Deserialize; #[cfg(not(miri))] use serde::de::{SeqAccess, Visitor}; use serde_derive::{Deserialize, Serialize}; use serde_norway::value::{Tag, TaggedValue}; use serde_norway::{Deserializer, Value}; #[cfg(not(miri))] use std::collections::BTreeMap; #[cfg(not(miri))] use std::fmt; use std::fmt::Debug; fn test_error<'de, T>(yaml: &'de str, expected: &str) where T: Deserialize<'de> + Debug, { let result = serde_norway::from_str::(yaml); assert_eq!(expected, result.unwrap_err().to_string()); let mut deserializer = Deserializer::from_str(yaml); if let Some(first_document) = deserializer.next() { if deserializer.next().is_none() { let result = T::deserialize(first_document); assert_eq!(expected, result.unwrap_err().to_string()); } } } #[test] fn test_scan_error() { let yaml = ">\n@"; let expected = "found character that cannot start any token at line 2 column 1, while scanning for the next token"; test_error::(yaml, expected); } #[test] fn test_incorrect_type() { let yaml = indoc! {" --- str "}; let expected = "invalid type: string \"str\", expected i16 at line 2 column 1"; test_error::(yaml, expected); } #[test] fn test_incorrect_nested_type() { #[derive(Deserialize, Debug)] pub struct A { #[allow(dead_code)] pub b: Vec, } #[derive(Deserialize, Debug)] pub enum B { C(#[allow(dead_code)] C), } #[derive(Deserialize, Debug)] pub struct C { #[allow(dead_code)] pub d: bool, } let yaml = indoc! {" b: - !C d: fase "}; let expected = "b[0].d: invalid type: string \"fase\", expected a boolean at line 3 column 8"; test_error::(yaml, expected); } #[test] fn test_empty() { let expected = "EOF while parsing a value"; test_error::("", expected); } #[test] fn test_missing_field() { #[derive(Deserialize, Debug)] pub struct Basic { #[allow(dead_code)] pub v: bool, #[allow(dead_code)] pub w: bool, } let yaml = indoc! {" --- v: true "}; let expected = "missing field `w` at line 2 column 1"; test_error::(yaml, expected); } #[test] fn test_unknown_anchor() { let yaml = indoc! {" --- *some "}; let expected = "unknown anchor at line 2 column 1"; test_error::(yaml, expected); } #[test] fn test_ignored_unknown_anchor() { #[derive(Deserialize, Debug)] pub struct Wrapper { #[allow(dead_code)] pub c: (), } let yaml = indoc! {" b: [*a] c: ~ "}; let expected = "unknown anchor at line 1 column 5"; test_error::(yaml, expected); } #[test] fn test_bytes() { let expected = "serialization and deserialization of bytes in YAML is not implemented"; test_error::<&[u8]>("...", expected); } #[test] fn test_two_documents() { let yaml = indoc! {" --- 0 --- 1 "}; let expected = "deserializing from YAML containing more than one document is not supported"; test_error::(yaml, expected); } #[test] fn test_second_document_syntax_error() { let yaml = indoc! {" --- 0 --- ] "}; let mut de = Deserializer::from_str(yaml); let first_doc = de.next().unwrap(); let result = ::deserialize(first_doc); assert_eq!(0, result.unwrap()); let second_doc = de.next().unwrap(); let result = ::deserialize(second_doc); let expected = "did not find expected node content at line 4 column 1, while parsing a block node"; assert_eq!(expected, result.unwrap_err().to_string()); } #[test] fn test_missing_enum_tag() { #[derive(Deserialize, Debug)] pub enum E { V(#[allow(dead_code)] usize), } let yaml = indoc! {r#" "V": 16 "other": 32 "#}; let expected = "invalid type: map, expected a YAML tag starting with '!'"; test_error::(yaml, expected); } #[test] fn test_serialize_nested_enum() { #[derive(Serialize, Debug)] pub enum Outer { Inner(Inner), } #[derive(Serialize, Debug)] pub enum Inner { Newtype(usize), Tuple(usize, usize), Struct { x: usize }, } let expected = "serializing nested enums in YAML is not supported yet"; let e = Outer::Inner(Inner::Newtype(0)); let error = serde_norway::to_string(&e).unwrap_err(); assert_eq!(error.to_string(), expected); let e = Outer::Inner(Inner::Tuple(0, 0)); let error = serde_norway::to_string(&e).unwrap_err(); assert_eq!(error.to_string(), expected); let e = Outer::Inner(Inner::Struct { x: 0 }); let error = serde_norway::to_string(&e).unwrap_err(); assert_eq!(error.to_string(), expected); let e = Value::Tagged(Box::new(TaggedValue { tag: Tag::new("Outer"), value: Value::Tagged(Box::new(TaggedValue { tag: Tag::new("Inner"), value: Value::Null, })), })); let error = serde_norway::to_string(&e).unwrap_err(); assert_eq!(error.to_string(), expected); } #[test] fn test_deserialize_nested_enum() { #[derive(Deserialize, Debug)] pub enum Outer { Inner(#[allow(dead_code)] Inner), } #[derive(Deserialize, Debug)] pub enum Inner { Variant(#[allow(dead_code)] Vec), } let yaml = indoc! {" --- !Inner [] "}; let expected = "deserializing nested enum in Outer::Inner from YAML is not supported yet at line 2 column 1"; test_error::(yaml, expected); let yaml = indoc! {" --- !Variant [] "}; let expected = "unknown variant `Variant`, expected `Inner`"; test_error::(yaml, expected); let yaml = indoc! {" --- !Inner !Variant [] "}; let expected = "deserializing nested enum in Outer::Inner from YAML is not supported yet at line 2 column 1"; test_error::(yaml, expected); } #[test] fn test_variant_not_a_seq() { #[derive(Deserialize, Debug)] pub enum E { V(#[allow(dead_code)] usize), } let yaml = indoc! {" --- !V value: 0 "}; let expected = "invalid type: map, expected usize at line 2 column 1"; test_error::(yaml, expected); } #[test] fn test_struct_from_sequence() { #[derive(Deserialize, Debug)] pub struct Struct { #[allow(dead_code)] pub x: usize, #[allow(dead_code)] pub y: usize, } let yaml = indoc! {" [0, 0] "}; let expected = "invalid type: sequence, expected struct Struct"; test_error::(yaml, expected); } #[test] fn test_bad_bool() { let yaml = indoc! {" --- !!bool str "}; let expected = "invalid value: string \"str\", expected a boolean at line 2 column 1"; test_error::(yaml, expected); } #[test] fn test_bad_int() { let yaml = indoc! {" --- !!int str "}; let expected = "invalid value: string \"str\", expected an integer at line 2 column 1"; test_error::(yaml, expected); } #[test] fn test_bad_float() { let yaml = indoc! {" --- !!float str "}; let expected = "invalid value: string \"str\", expected a float at line 2 column 1"; test_error::(yaml, expected); } #[test] fn test_bad_null() { let yaml = indoc! {" --- !!null str "}; let expected = "invalid value: string \"str\", expected null at line 2 column 1"; test_error::<()>(yaml, expected); } #[test] fn test_short_tuple() { let yaml = indoc! {" --- [0, 0] "}; let expected = "invalid length 2, expected a tuple of size 3 at line 2 column 1"; test_error::<(u8, u8, u8)>(yaml, expected); } #[test] fn test_long_tuple() { let yaml = indoc! {" --- [0, 0, 0] "}; let expected = "invalid length 3, expected sequence of 2 elements at line 2 column 1"; test_error::<(u8, u8)>(yaml, expected); } #[test] fn test_invalid_scalar_type() { #[derive(Deserialize, Debug)] pub struct S { #[allow(dead_code)] pub x: [i32; 1], } let yaml = "x: ''\n"; let expected = "x: invalid type: string \"\", expected an array of length 1 at line 1 column 4"; test_error::(yaml, expected); } #[cfg(not(miri))] #[test] fn test_infinite_recursion_objects() { #[derive(Deserialize, Debug)] pub struct S { #[allow(dead_code)] pub x: Option>, } let yaml = "&a {'x': *a}"; let expected = "recursion limit exceeded"; test_error::(yaml, expected); } #[cfg(not(miri))] #[test] fn test_infinite_recursion_arrays() { #[derive(Deserialize, Debug)] pub struct S( #[allow(dead_code)] pub usize, #[allow(dead_code)] pub Option>, ); let yaml = "&a [0, *a]"; let expected = "recursion limit exceeded"; test_error::(yaml, expected); } #[cfg(not(miri))] #[test] fn test_infinite_recursion_newtype() { #[derive(Deserialize, Debug)] pub struct S(#[allow(dead_code)] pub Option>); let yaml = "&a [*a]"; let expected = "recursion limit exceeded"; test_error::(yaml, expected); } #[cfg(not(miri))] #[test] fn test_finite_recursion_objects() { #[derive(Deserialize, Debug)] pub struct S { #[allow(dead_code)] pub x: Option>, } let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000); let expected = "recursion limit exceeded at line 1 column 641"; test_error::(&yaml, expected); } #[cfg(not(miri))] #[test] fn test_finite_recursion_arrays() { #[derive(Deserialize, Debug)] pub struct S( #[allow(dead_code)] pub usize, #[allow(dead_code)] pub Option>, ); let yaml = "[0, ".repeat(1_000) + &"]".repeat(1_000); let expected = "recursion limit exceeded at line 1 column 513"; test_error::(&yaml, expected); } #[cfg(not(miri))] #[test] fn test_billion_laughs() { #[derive(Debug)] struct X; impl<'de> Visitor<'de> for X { type Value = X; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("exponential blowup") } fn visit_unit(self) -> Result { Ok(X) } fn visit_seq(self, mut seq: S) -> Result where S: SeqAccess<'de>, { while let Some(X) = seq.next_element()? {} Ok(X) } } impl<'de> Deserialize<'de> for X { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { deserializer.deserialize_any(X) } } let yaml = indoc! {" a: &a ~ b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a] c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b] d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c] e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d] f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e] g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f] h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g] i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h] "}; let expected = "repetition limit exceeded"; test_error::>(yaml, expected); } #[test] fn test_duplicate_keys() { let yaml = indoc! {" --- thing: true thing: false "}; let expected = "duplicate entry with key \"thing\" at line 2 column 1"; test_error::(yaml, expected); let yaml = indoc! {" --- null: true ~: false "}; let expected = "duplicate entry with null key at line 2 column 1"; test_error::(yaml, expected); let yaml = indoc! {" --- 99: true 99: false "}; let expected = "duplicate entry with key 99 at line 2 column 1"; test_error::(yaml, expected); let yaml = indoc! {" --- {}: true {}: false "}; let expected = "duplicate entry in YAML map at line 2 column 1"; test_error::(yaml, expected); } serde_norway-0.9.38/tests/test_serde.rs000064400000000000000000000273141046102023000163060ustar 00000000000000#![allow( clippy::decimal_literal_representation, clippy::derive_partial_eq_without_eq, clippy::unreadable_literal, clippy::shadow_unrelated )] use indoc::indoc; use serde::ser::SerializeMap; use serde_derive::{Deserialize, Serialize}; use serde_norway::{Mapping, Number, Value}; use std::collections::BTreeMap; use std::fmt::Debug; use std::iter; fn test_serde(thing: &T, yaml: &str) where T: serde::Serialize + serde::de::DeserializeOwned + PartialEq + Debug, { let serialized = serde_norway::to_string(&thing).unwrap(); assert_eq!(yaml, serialized); let value = serde_norway::to_value(thing).unwrap(); let serialized = serde_norway::to_string(&value).unwrap(); assert_eq!(yaml, serialized); let deserialized: T = serde_norway::from_str(yaml).unwrap(); assert_eq!(*thing, deserialized); let value: Value = serde_norway::from_str(yaml).unwrap(); let deserialized = T::deserialize(&value).unwrap(); assert_eq!(*thing, deserialized); let deserialized: T = serde_norway::from_value(value).unwrap(); assert_eq!(*thing, deserialized); serde_norway::from_str::(yaml).unwrap(); } #[test] fn test_default() { assert_eq!(Value::default(), Value::Null); } #[test] fn test_int() { let thing = 256; let yaml = indoc! {" 256 "}; test_serde(&thing, yaml); } #[test] fn test_int_max_u64() { let thing = u64::MAX; let yaml = indoc! {" 18446744073709551615 "}; test_serde(&thing, yaml); } #[test] fn test_int_min_i64() { let thing = i64::MIN; let yaml = indoc! {" -9223372036854775808 "}; test_serde(&thing, yaml); } #[test] fn test_int_max_i64() { let thing = i64::MAX; let yaml = indoc! {" 9223372036854775807 "}; test_serde(&thing, yaml); } #[test] fn test_i128_small() { let thing: i128 = -256; let yaml = indoc! {" -256 "}; test_serde(&thing, yaml); } #[test] fn test_u128_small() { let thing: u128 = 256; let yaml = indoc! {" 256 "}; test_serde(&thing, yaml); } #[test] fn test_float() { let thing = 25.6; let yaml = indoc! {" 25.6 "}; test_serde(&thing, yaml); let thing = 25.; let yaml = indoc! {" 25.0 "}; test_serde(&thing, yaml); let thing = f64::INFINITY; let yaml = indoc! {" .inf "}; test_serde(&thing, yaml); let thing = f64::NEG_INFINITY; let yaml = indoc! {" -.inf "}; test_serde(&thing, yaml); let float: f64 = serde_norway::from_str(indoc! {" .nan "}) .unwrap(); assert!(float.is_nan()); } #[test] fn test_float32() { let thing: f32 = 25.5; let yaml = indoc! {" 25.5 "}; test_serde(&thing, yaml); let thing = f32::INFINITY; let yaml = indoc! {" .inf "}; test_serde(&thing, yaml); let thing = f32::NEG_INFINITY; let yaml = indoc! {" -.inf "}; test_serde(&thing, yaml); let single_float: f32 = serde_norway::from_str(indoc! {" .nan "}) .unwrap(); assert!(single_float.is_nan()); } #[test] fn test_char() { let ch = '.'; let yaml = indoc! {" '.' "}; assert_eq!(yaml, serde_norway::to_string(&ch).unwrap()); let ch = '#'; let yaml = indoc! {" '#' "}; assert_eq!(yaml, serde_norway::to_string(&ch).unwrap()); let ch = '-'; let yaml = indoc! {" '-' "}; assert_eq!(yaml, serde_norway::to_string(&ch).unwrap()); } #[test] fn test_vec() { let thing = vec![1, 2, 3]; let yaml = indoc! {" - 1 - 2 - 3 "}; test_serde(&thing, yaml); } #[test] fn test_map() { let mut thing = BTreeMap::new(); thing.insert("x".to_owned(), 1); thing.insert("y".to_owned(), 2); let yaml = indoc! {" x: 1 y: 2 "}; test_serde(&thing, yaml); } #[test] fn test_map_key_value() { struct Map; impl serde::Serialize for Map { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { // Test maps which do not serialize using serialize_entry. let mut map = serializer.serialize_map(Some(1))?; map.serialize_key("k")?; map.serialize_value("v")?; map.end() } } let yaml = indoc! {" k: v "}; assert_eq!(yaml, serde_norway::to_string(&Map).unwrap()); } #[test] fn test_basic_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Basic { x: isize, y: String, z: bool, } let thing = Basic { x: -4, y: "hi\tquoted".to_owned(), z: true, }; let yaml = indoc! {r#" x: -4 y: "hi\tquoted" z: true "#}; test_serde(&thing, yaml); } #[test] fn test_string_escapes() { let yaml = indoc! {" ascii "}; test_serde(&"ascii".to_owned(), yaml); let yaml = indoc! {r#" "\0\a\b\t\n\v\f\r\e\"\\\N\L\P" "#}; test_serde( &"\0\u{7}\u{8}\t\n\u{b}\u{c}\r\u{1b}\"\\\u{85}\u{2028}\u{2029}".to_owned(), yaml, ); let yaml = indoc! {r#" "\x1F\uFEFF" "#}; test_serde(&"\u{1f}\u{feff}".to_owned(), yaml); let yaml = indoc! {" 🎉 "}; test_serde(&"\u{1f389}".to_owned(), yaml); } #[test] fn test_multiline_string() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Struct { trailing_newline: String, no_trailing_newline: String, } let thing = Struct { trailing_newline: "aaa\nbbb\n".to_owned(), no_trailing_newline: "aaa\nbbb".to_owned(), }; let yaml = indoc! {" trailing_newline: | aaa bbb no_trailing_newline: |- aaa bbb "}; test_serde(&thing, yaml); } #[test] fn test_strings_needing_quote() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Struct { boolean: String, integer: String, void: String, leading_zeros: String, } let thing = Struct { boolean: "true".to_owned(), integer: "1".to_owned(), void: "null".to_owned(), leading_zeros: "007".to_owned(), }; let yaml = indoc! {" boolean: 'true' integer: '1' void: 'null' leading_zeros: '007' "}; test_serde(&thing, yaml); } #[test] fn test_nested_vec() { let thing = vec![vec![1, 2, 3], vec![4, 5, 6]]; let yaml = indoc! {" - - 1 - 2 - 3 - - 4 - 5 - 6 "}; test_serde(&thing, yaml); } #[test] fn test_nested_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Outer { inner: Inner, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Inner { v: u16, } let thing = Outer { inner: Inner { v: 512 }, }; let yaml = indoc! {" inner: v: 512 "}; test_serde(&thing, yaml); } #[test] fn test_nested_enum() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Outer { Inner(Inner), } #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Inner { Unit, } let thing = Outer::Inner(Inner::Unit); let yaml = indoc! {" !Inner Unit "}; test_serde(&thing, yaml); } #[test] fn test_option() { let thing = vec![Some(1), None, Some(3)]; let yaml = indoc! {" - 1 - null - 3 "}; test_serde(&thing, yaml); } #[test] fn test_unit() { let thing = vec![(), ()]; let yaml = indoc! {" - null - null "}; test_serde(&thing, yaml); } #[test] fn test_unit_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Foo; let thing = Foo; let yaml = indoc! {" null "}; test_serde(&thing, yaml); } #[test] fn test_unit_variant() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Variant { First, Second, } let thing = Variant::First; let yaml = indoc! {" First "}; test_serde(&thing, yaml); } #[test] fn test_newtype_struct() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct OriginalType { v: u16, } #[derive(Serialize, Deserialize, PartialEq, Debug)] struct NewType(OriginalType); let thing = NewType(OriginalType { v: 1 }); let yaml = indoc! {" v: 1 "}; test_serde(&thing, yaml); } #[test] fn test_newtype_variant() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Variant { Size(usize), } let thing = Variant::Size(127); let yaml = indoc! {" !Size 127 "}; test_serde(&thing, yaml); } #[test] fn test_tuple_variant() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Variant { Rgb(u8, u8, u8), } let thing = Variant::Rgb(32, 64, 96); let yaml = indoc! {" !Rgb - 32 - 64 - 96 "}; test_serde(&thing, yaml); } #[test] fn test_struct_variant() { #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Variant { Color { r: u8, g: u8, b: u8 }, } let thing = Variant::Color { r: 32, g: 64, b: 96, }; let yaml = indoc! {" !Color r: 32 g: 64 b: 96 "}; test_serde(&thing, yaml); } #[test] fn test_tagged_map_value() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Bindings { profile: Profile, } #[derive(Serialize, Deserialize, PartialEq, Debug)] enum Profile { ClassValidator { class_name: String }, } let thing = Bindings { profile: Profile::ClassValidator { class_name: "ApplicationConfig".to_owned(), }, }; let yaml = indoc! {" profile: !ClassValidator class_name: ApplicationConfig "}; test_serde(&thing, yaml); } #[test] fn test_value() { #[derive(Serialize, Deserialize, PartialEq, Debug)] pub struct GenericInstructions { #[serde(rename = "type")] pub typ: String, pub config: Value, } let thing = GenericInstructions { typ: "primary".to_string(), config: Value::Sequence(vec![ Value::Null, Value::Bool(true), Value::Number(Number::from(65535)), Value::Number(Number::from(0.54321)), Value::String("s".into()), Value::Mapping(Mapping::new()), ]), }; let yaml = indoc! {" type: primary config: - null - true - 65535 - 0.54321 - s - {} "}; test_serde(&thing, yaml); } #[test] fn test_mapping() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Data { pub substructure: Mapping, } let mut thing = Data { substructure: Mapping::new(), }; thing.substructure.insert( Value::String("a".to_owned()), Value::String("foo".to_owned()), ); thing.substructure.insert( Value::String("b".to_owned()), Value::String("bar".to_owned()), ); let yaml = indoc! {" substructure: a: foo b: bar "}; test_serde(&thing, yaml); } #[test] fn test_long_string() { #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Data { pub string: String, } let thing = Data { string: iter::repeat(["word", " "]).flatten().take(69).collect(), }; let yaml = indoc! {" string: word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word "}; test_serde(&thing, yaml); } serde_norway-0.9.38/tests/test_value.rs000064400000000000000000000073631046102023000163220ustar 00000000000000#![allow( clippy::derive_partial_eq_without_eq, clippy::eq_op, clippy::uninlined_format_args )] use indoc::indoc; use serde::de::IntoDeserializer; use serde::Deserialize; use serde_derive::{Deserialize, Serialize}; use serde_norway::{Number, Value}; #[test] fn test_nan() { let pos_nan = serde_norway::from_str::(".nan").unwrap(); assert!(pos_nan.is_f64()); assert_eq!(pos_nan, pos_nan); let neg_fake_nan = serde_norway::from_str::("-.nan").unwrap(); assert!(neg_fake_nan.is_string()); let significand_mask = 0xF_FFFF_FFFF_FFFF; let bits = (f64::NAN.copysign(1.0).to_bits() ^ significand_mask) | 1; let different_pos_nan = Value::Number(Number::from(f64::from_bits(bits))); assert_eq!(pos_nan, different_pos_nan); } #[test] fn test_digits() { let num_string = serde_norway::from_str::("01").unwrap(); assert!(num_string.is_string()); } #[test] fn test_into_deserializer() { #[derive(Debug, Deserialize, PartialEq)] struct Test { first: String, second: u32, } let value = serde_norway::from_str::("xyz").unwrap(); let s = String::deserialize(value.into_deserializer()).unwrap(); assert_eq!(s, "xyz"); let value = serde_norway::from_str::("- first\n- second\n- third").unwrap(); let arr = Vec::::deserialize(value.into_deserializer()).unwrap(); assert_eq!(arr, &["first", "second", "third"]); let value = serde_norway::from_str::("first: abc\nsecond: 99").unwrap(); let test = Test::deserialize(value.into_deserializer()).unwrap(); assert_eq!( test, Test { first: "abc".to_string(), second: 99 } ); } #[test] fn test_merge() { // From https://yaml.org/type/merge.html. let yaml = indoc! {" --- - &CENTER { x: 1, y: 2 } - &LEFT { x: 0, y: 2 } - &BIG { r: 10 } - &SMALL { r: 1 } # All the following maps are equal: - # Explicit keys x: 1 y: 2 r: 10 label: center/big - # Merge one map << : *CENTER r: 10 label: center/big - # Merge multiple maps << : [ *CENTER, *BIG ] label: center/big - # Override << : [ *BIG, *LEFT, *SMALL ] x: 1 label: center/big "}; let mut value: Value = serde_norway::from_str(yaml).unwrap(); value.apply_merge().unwrap(); for i in 5..=7 { assert_eq!(value[4], value[i]); } } #[test] fn test_debug() { let yaml = indoc! {" 'Null': ~ Bool: true Number: 1 String: ... Sequence: - true EmptySequence: [] EmptyMapping: {} Tagged: !tag true "}; let value: Value = serde_norway::from_str(yaml).unwrap(); let debug = format!("{:#?}", value); let expected = indoc! {r#" Mapping { "Null": Null, "Bool": Bool(true), "Number": Number(1), "String": String("..."), "Sequence": Sequence [ Bool(true), ], "EmptySequence": Sequence [], "EmptyMapping": Mapping {}, "Tagged": TaggedValue { tag: !tag, value: Bool(true), }, }"# }; assert_eq!(debug, expected); } #[test] fn test_tagged() { #[derive(Serialize)] enum Enum { Variant(usize), } let value = serde_norway::to_value(Enum::Variant(0)).unwrap(); let deserialized: serde_norway::Value = serde_norway::from_value(value.clone()).unwrap(); assert_eq!(value, deserialized); let serialized = serde_norway::to_value(&value).unwrap(); assert_eq!(value, serialized); }