diff --git a/kclvm/Cargo.lock b/kclvm/Cargo.lock index 05dddc028..e7ce8edc9 100644 --- a/kclvm/Cargo.lock +++ b/kclvm/Cargo.lock @@ -1262,6 +1262,12 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + [[package]] name = "inkwell" version = "0.2.0" @@ -3212,13 +3218,14 @@ dependencies = [ [[package]] name = "serde_yaml" version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ + "anyhow", "indexmap 2.2.6", + "indoc", "itoa", "ryu", "serde", + "serde_derive", "unsafe-libyaml", ] diff --git a/kclvm/api/Cargo.toml b/kclvm/api/Cargo.toml index 6f10bcd94..9c3030f13 100644 --- a/kclvm/api/Cargo.toml +++ b/kclvm/api/Cargo.toml @@ -12,7 +12,7 @@ maplit = "1.0.2" prost = "0.11.8" prost-types = "0.11.8" serde_json = "1.0" -serde_yaml = "0.9.32" +serde_yaml = {path = "../third-party/serde_yaml"} anyhow = "1.0.70" serde = { version = "1", features = ["derive"] } indexmap = "1.0" diff --git a/kclvm/config/Cargo.toml b/kclvm/config/Cargo.toml index ea78e66a5..065820dd9 100644 --- a/kclvm/config/Cargo.toml +++ b/kclvm/config/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] serde = { version = "1", features = ["derive"] } -serde_yaml = "0.9.32" +serde_yaml = {path = "../third-party/serde_yaml"} serde_json = "1.0" indexmap = "1.0" ahash = "0.7.2" diff --git a/kclvm/runtime/Cargo.toml b/kclvm/runtime/Cargo.toml index 231dc4ab5..f9d1cd235 100644 --- a/kclvm/runtime/Cargo.toml +++ b/kclvm/runtime/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" kclvm_runtime_internal_macros = { path = "./internal_macros" } serde_json = {package = "serde_json", version = "= 1.0.115"} serde = { version = "1", features = ["derive"] } -serde_yaml = "0.9.32" +serde_yaml = {path = "../third-party/serde_yaml"} generational-arena = "0.2.9" base64 = "0.13.0" diff --git a/kclvm/runtime/src/value/val_yaml.rs b/kclvm/runtime/src/value/val_yaml.rs index 2125010a0..f12e83577 100644 --- a/kclvm/runtime/src/value/val_yaml.rs +++ b/kclvm/runtime/src/value/val_yaml.rs @@ -116,6 +116,12 @@ impl ValueRef { mod test_value_yaml { use crate::*; + #[test] + fn test_serde_yaml_on_str() { + let on_str = serde_yaml::to_string("on").unwrap(); + assert_eq!(on_str, "'on'\n"); + } + #[test] fn test_value_from_yaml() { let mut ctx = Context::new(); diff --git a/kclvm/third-party/serde_yaml/.github/FUNDING.yml b/kclvm/third-party/serde_yaml/.github/FUNDING.yml new file mode 100644 index 000000000..750707701 --- /dev/null +++ b/kclvm/third-party/serde_yaml/.github/FUNDING.yml @@ -0,0 +1 @@ +github: dtolnay diff --git a/kclvm/third-party/serde_yaml/.github/workflows/ci.yml b/kclvm/third-party/serde_yaml/.github/workflows/ci.yml new file mode 100644 index 000000000..624334b8b --- /dev/null +++ b/kclvm/third-party/serde_yaml/.github/workflows/ci.yml @@ -0,0 +1,111 @@ +name: 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 diff --git a/kclvm/third-party/serde_yaml/.gitignore b/kclvm/third-party/serde_yaml/.gitignore new file mode 100644 index 000000000..a9d37c560 --- /dev/null +++ b/kclvm/third-party/serde_yaml/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/kclvm/third-party/serde_yaml/Cargo.toml b/kclvm/third-party/serde_yaml/Cargo.toml new file mode 100644 index 000000000..749e18bc2 --- /dev/null +++ b/kclvm/third-party/serde_yaml/Cargo.toml @@ -0,0 +1,62 @@ +# 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_yaml" +version = "0.9.34+deprecated" +authors = ["David Tolnay "] +description = "YAML data format for Serde" +documentation = "https://docs.rs/serde_yaml/" +readme = "README.md" +keywords = [ + "yaml", + "serde", + "serialization", +] +categories = [ + "encoding", + "parser-implementations", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/serde-yaml" + +[package.metadata.docs.rs] +rustdoc-args = ["--generate-link-to-definition"] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +doc-scrape-examples = false + +[dependencies.indexmap] +version = "2.2.1" + +[dependencies.itoa] +version = "1.0" + +[dependencies.ryu] +version = "1.0" + +[dependencies.serde] +version = "1.0.195" + +[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.195" diff --git a/kclvm/third-party/serde_yaml/LICENSE-APACHE b/kclvm/third-party/serde_yaml/LICENSE-APACHE new file mode 100644 index 000000000..1b5ec8b78 --- /dev/null +++ b/kclvm/third-party/serde_yaml/LICENSE-APACHE @@ -0,0 +1,176 @@ + 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 diff --git a/kclvm/third-party/serde_yaml/LICENSE-MIT b/kclvm/third-party/serde_yaml/LICENSE-MIT new file mode 100644 index 000000000..31aa79387 --- /dev/null +++ b/kclvm/third-party/serde_yaml/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/kclvm/third-party/serde_yaml/README.md b/kclvm/third-party/serde_yaml/README.md new file mode 100644 index 000000000..1a3416644 --- /dev/null +++ b/kclvm/third-party/serde_yaml/README.md @@ -0,0 +1,153 @@ +Serde YAML +========== + +[github](https://github.com/dtolnay/serde-yaml) +[crates.io](https://crates.io/crates/serde_yaml) +[docs.rs](https://docs.rs/serde_yaml) +[build status](https://github.com/dtolnay/serde-yaml/actions?query=branch%3Amaster) + +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_yaml = "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_yaml + +```rust +use std::collections::BTreeMap; + +fn main() -> Result<(), serde_yaml::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. + // y is quoted to avoid ambiguity in parsers that might read it as `true`. + let yaml = serde_yaml::to_string(&map)?; + assert_eq!(yaml, "x: 1.0\n'y': 2.0\n"); + + // Deserialize it back to a Rust type. + let deserialized_map: BTreeMap = serde_yaml::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_yaml = "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_yaml::Error> { + let point = Point { x: 1.0, y: 2.0 }; + + let yaml = serde_yaml::to_string(&point)?; + assert_eq!(yaml, "x: 1.0\n'y': 2.0\n"); + + let deserialized_point: Point = serde_yaml::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_yaml::Error> { + let yaml = " + - !Newtype 1 + - !Tuple [0, 0, 0] + - !Struct {x: 1.0, y: 2.0} + "; + let values: Vec = serde_yaml::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_yaml::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_yaml::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. + diff --git a/kclvm/third-party/serde_yaml/src/de.rs b/kclvm/third-party/serde_yaml/src/de.rs new file mode 100644 index 000000000..640e8795e --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/de.rs @@ -0,0 +1,1876 @@ +use 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_yaml::Value; +/// +/// fn main() -> Result<()> { +/// let input = "k: 107\n"; +/// let de = serde_yaml::Deserializer::from_str(input); +/// let value = Value::deserialize(de)?; +/// println!("{:?}", value); +/// Ok(()) +/// } +/// ``` +/// +/// Deserializing multi-doc YAML: +/// +/// ``` +/// use anyhow::Result; +/// use serde::Deserialize; +/// use serde_yaml::Value; +/// +/// fn main() -> Result<()> { +/// let input = "---\nk: 107\n...\n---\nj: 106\n"; +/// +/// for document in serde_yaml::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()) +} + +/// If a string looks like it could be parsed as some other type by some YAML +/// parser on the round trip, or could otherwise be ambiguous, then we should +/// serialize it with quotes to be safe. +/// This avoids the norway problem https://hitchdev.com/strictyaml/why/implicit-typing-removed/ +pub(crate) fn ambiguous_string(scalar: &str) -> bool { + let lower_scalar = scalar.to_lowercase(); + parse_bool(&lower_scalar).is_some() + || parse_null(&lower_scalar.as_bytes()).is_some() + || lower_scalar.len() == 0 + // Can unwrap because we just checked the length. + || lower_scalar.bytes().nth(0).unwrap().is_ascii_digit() + || lower_scalar.starts_with('-') + || lower_scalar.starts_with('.') + || lower_scalar.starts_with("+") + // Things that we don't parse as bool but could be parsed as bool by + // other YAML parsers. + || lower_scalar == "y" + || lower_scalar == "yes" + || lower_scalar == "n" + || lower_scalar == "no" + || lower_scalar == "on" + || lower_scalar == "off" + || lower_scalar == "true" + || lower_scalar == "false" + || lower_scalar == "null" + || lower_scalar == "nil" + || lower_scalar == "~" + || lower_scalar == "nan" +} + +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 }; + 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)) +} diff --git a/kclvm/third-party/serde_yaml/src/error.rs b/kclvm/third-party/serde_yaml/src/error.rs new file mode 100644 index 000000000..01f8ed126 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/error.rs @@ -0,0 +1,290 @@ +use 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_yaml::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_yaml::{Value, Error}; + /// # + /// // The `@` character as the first character makes this invalid yaml + /// let invalid_yaml: Result = serde_yaml::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(")") + } + } + } +} diff --git a/kclvm/third-party/serde_yaml/src/lib.rs b/kclvm/third-party/serde_yaml/src/lib.rs new file mode 100644 index 000000000..ad773cf85 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/lib.rs @@ -0,0 +1,194 @@ +//! [![github]](https://github.com/dtolnay/serde-yaml) [![crates-io]](https://crates.io/crates/serde-yaml) [![docs-rs]](https://docs.rs/serde-yaml) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs +//! +//!
+//! +//! 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/ +//! +//! # Examples +//! +//! ``` +//! use std::collections::BTreeMap; +//! +//! fn main() -> Result<(), serde_yaml::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. +//! // 'y' is quoted to avoid ambiguity in parsers that might read it as `true`. +//! let yaml = serde_yaml::to_string(&map)?; +//! assert_eq!(yaml, "x: 1.0\n'y': 2.0\n"); +//! +//! // Deserialize it back to a Rust type. +//! let deserialized_map: BTreeMap = serde_yaml::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::Deserialize as _; +//! # use serde::Serialize as _; +//! +//! #[derive(Serialize, Deserialize, PartialEq, Debug)] +//! struct Point { +//! x: f64, +//! y: f64, +//! } +//! +//! fn main() -> Result<(), serde_yaml::Error> { +//! let point = Point { x: 1.0, y: 2.0 }; +//! +//! let yaml = serde_yaml::to_string(&point)?; +//! assert_eq!(yaml, "x: 1.0\n'y': 2.0\n"); +//! +//! let deserialized_point: Point = serde_yaml::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::Deserialize as _; +//! # use serde::Serialize as _; +//! +//! #[derive(Serialize, Deserialize, PartialEq, Debug)] +//! enum Enum { +//! Unit, +//! Newtype(usize), +//! Tuple(usize, usize, usize), +//! Struct { x: f64, y: f64 }, +//! } +//! +//! fn main() -> Result<(), serde_yaml::Error> { +//! let yaml = " +//! - !Newtype 1 +//! - !Tuple [0, 0, 0] +//! - !Struct {x: 1.0, y: 2.0} +//! "; +//! let values: Vec = serde_yaml::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_yaml::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_yaml::from_str(yaml).unwrap(); +//! assert_eq!(values[0], Enum::Unit); +//! assert_eq!(values[1], Enum::Unit); +//! +//! Ok(()) +//! } +//! ``` + +#![doc(html_root_url = "https://docs.rs/serde_yaml/0.9.34+deprecated")] +#![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 {} +} diff --git a/kclvm/third-party/serde_yaml/src/libyaml/cstr.rs b/kclvm/third-party/serde_yaml/src/libyaml/cstr.rs new file mode 100644 index 000000000..6e82535be --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/libyaml/cstr.rs @@ -0,0 +1,127 @@ +use 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('"') +} diff --git a/kclvm/third-party/serde_yaml/src/libyaml/emitter.rs b/kclvm/third-party/serde_yaml/src/libyaml/emitter.rs new file mode 100644 index 000000000..686f06ef2 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/libyaml/emitter.rs @@ -0,0 +1,217 @@ +use 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) } + } +} diff --git a/kclvm/third-party/serde_yaml/src/libyaml/error.rs b/kclvm/third-party/serde_yaml/src/libyaml/error.rs new file mode 100644 index 000000000..8397f6e2b --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/libyaml/error.rs @@ -0,0 +1,162 @@ +use 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() + } +} diff --git a/kclvm/third-party/serde_yaml/src/libyaml/mod.rs b/kclvm/third-party/serde_yaml/src/libyaml/mod.rs new file mode 100644 index 000000000..9e160b17c --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/libyaml/mod.rs @@ -0,0 +1,8 @@ +mod cstr; +pub mod emitter; +pub mod error; +pub mod parser; +pub mod tag; +mod util; + +use self::error::Error; diff --git a/kclvm/third-party/serde_yaml/src/libyaml/parser.rs b/kclvm/third-party/serde_yaml/src/libyaml/parser.rs new file mode 100644 index 000000000..3492edd0b --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/libyaml/parser.rs @@ -0,0 +1,201 @@ +use 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) } + } +} diff --git a/kclvm/third-party/serde_yaml/src/libyaml/tag.rs b/kclvm/third-party/serde_yaml/src/libyaml/tag.rs new file mode 100644 index 000000000..1f731859a --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/libyaml/tag.rs @@ -0,0 +1,38 @@ +use 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) + } +} diff --git a/kclvm/third-party/serde_yaml/src/libyaml/util.rs b/kclvm/third-party/serde_yaml/src/libyaml/util.rs new file mode 100644 index 000000000..1f5010da0 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/libyaml/util.rs @@ -0,0 +1,48 @@ +use 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()) }; + } +} diff --git a/kclvm/third-party/serde_yaml/src/loader.rs b/kclvm/third-party/serde_yaml/src/loader.rs new file mode 100644 index 000000000..7c7c7b655 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/loader.rs @@ -0,0 +1,119 @@ +use 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)); + } + } +} diff --git a/kclvm/third-party/serde_yaml/src/mapping.rs b/kclvm/third-party/serde_yaml/src/mapping.rs new file mode 100644 index 000000000..667cd4b42 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/mapping.rs @@ -0,0 +1,851 @@ +//! 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_yaml::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_yaml::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_yaml`. +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_yaml::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_yaml::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_yaml::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_yaml::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_yaml::Mapping`. +pub struct IntoKeys { + iter: indexmap::map::IntoKeys, +} + +delegate_iterator!((IntoKeys) => Value); + +/// Iterator of the values of a `&serde_yaml::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_yaml::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_yaml::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") + } + } + } +} diff --git a/kclvm/third-party/serde_yaml/src/number.rs b/kclvm/third-party/serde_yaml/src/number.rs new file mode 100644 index 000000000..5ebe39577 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/number.rs @@ -0,0 +1,561 @@ +use 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_yaml::Result<()> { + /// let big = i64::MAX as u64 + 10; + /// let v: serde_yaml::Value = serde_yaml::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_value() 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_yaml::Result<()> { + /// let v: serde_yaml::Value = serde_yaml::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_yaml::Result<()> { + /// let v: serde_yaml::Value = serde_yaml::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_yaml::Result<()> { + /// let big = i64::MAX as u64 + 10; + /// let v: serde_yaml::Value = serde_yaml::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_value() 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_yaml::Result<()> { + /// let v: serde_yaml::Value = serde_yaml::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_yaml::Result<()> { + /// let v: serde_yaml::Value = serde_yaml::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_yaml::Result<()> { + /// let v: serde_yaml::Value = serde_yaml::from_str(".inf")?; + /// assert_eq!(v.as_f64(), Some(f64::INFINITY)); + /// + /// let v: serde_yaml::Value = serde_yaml::from_str("-.inf")?; + /// assert_eq!(v.as_f64(), Some(f64::NEG_INFINITY)); + /// + /// let v: serde_yaml::Value = serde_yaml::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_yaml::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_yaml::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_yaml::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), + } +} diff --git a/kclvm/third-party/serde_yaml/src/path.rs b/kclvm/third-party/serde_yaml/src/path.rs new file mode 100644 index 000000000..095add017 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/path.rs @@ -0,0 +1,34 @@ +use 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)), + } + } +} diff --git a/kclvm/third-party/serde_yaml/src/ser.rs b/kclvm/third-party/serde_yaml/src/ser.rs new file mode 100644 index 000000000..08b0567a3 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/ser.rs @@ -0,0 +1,714 @@ +//! 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_yaml::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 { + if crate::de::ambiguous_string(v) { + Ok(ScalarStyle::SingleQuoted) + } else { + Ok(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))) +} diff --git a/kclvm/third-party/serde_yaml/src/value/de.rs b/kclvm/third-party/serde_yaml/src/value/de.rs new file mode 100644 index 000000000..b1ff57696 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/value/de.rs @@ -0,0 +1,1242 @@ +use 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, + } + } +} diff --git a/kclvm/third-party/serde_yaml/src/value/debug.rs b/kclvm/third-party/serde_yaml/src/value/debug.rs new file mode 100644 index 000000000..060f9ecdf --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/value/debug.rs @@ -0,0 +1,57 @@ +use 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() + } +} diff --git a/kclvm/third-party/serde_yaml/src/value/from.rs b/kclvm/third-party/serde_yaml/src/value/from.rs new file mode 100644 index 000000000..82412c4f2 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/value/from.rs @@ -0,0 +1,178 @@ +use 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_yaml::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_yaml::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_yaml::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_yaml::Value; + /// use std::borrow::Cow; + /// + /// let s: Cow = Cow::Borrowed("lorem"); + /// let x: Value = s.into(); + /// ``` + /// + /// ``` + /// use serde_yaml::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_yaml::{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_yaml::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_yaml::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_yaml::Value; + /// + /// let v = std::iter::repeat(42).take(5); + /// let x: Value = v.collect(); + /// ``` + /// + /// ``` + /// use serde_yaml::Value; + /// + /// let v: Vec<_> = vec!["lorem", "ipsum", "dolor"]; + /// let x: Value = v.into_iter().collect(); + /// ``` + /// + /// ``` + /// use std::iter::FromIterator; + /// use serde_yaml::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) + } +} diff --git a/kclvm/third-party/serde_yaml/src/value/index.rs b/kclvm/third-party/serde_yaml/src/value/index.rs new file mode 100644 index 000000000..9a886d547 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/value/index.rs @@ -0,0 +1,279 @@ +use 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_yaml::Value`. See the `get` +/// and `get_mut` methods of `Value`. +/// +/// This trait is sealed and cannot be implemented for types outside of +/// `serde_yaml`. +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_yaml::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_yaml::Value; + /// # + /// # fn main() -> serde_yaml::Result<()> { + /// let data: serde_yaml::Value = serde_yaml::from_str(r#"{ x: { y: [z, zz] } }"#)?; + /// + /// assert_eq!(data["x"]["y"], serde_yaml::from_str::(r#"["z", "zz"]"#).unwrap()); + /// assert_eq!(data["x"]["y"][0], serde_yaml::from_str::(r#""z""#).unwrap()); + /// + /// assert_eq!(data["a"], serde_yaml::from_str::(r#"null"#).unwrap()); // returns null for undefined values + /// assert_eq!(data["a"]["b"], serde_yaml::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_yaml::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_yaml::Result<()> { + /// let mut data: serde_yaml::Value = serde_yaml::from_str(r#"{x: 0}"#)?; + /// + /// // replace an existing key + /// data["x"] = serde_yaml::from_str(r#"1"#)?; + /// + /// // insert a new key + /// data["y"] = serde_yaml::from_str(r#"[false, false, false]"#)?; + /// + /// // replace a value in a sequence + /// data["y"][0] = serde_yaml::from_str(r#"true"#)?; + /// + /// // inserted a deeply nested key + /// data["a"]["b"]["c"]["d"] = serde_yaml::from_str(r#"true"#)?; + /// + /// println!("{:?}", data); + /// # Ok(()) + /// # } + /// ``` + fn index_mut(&mut self, index: I) -> &mut Value { + index.index_or_insert(self) + } +} diff --git a/kclvm/third-party/serde_yaml/src/value/mod.rs b/kclvm/third-party/serde_yaml/src/value/mod.rs new file mode 100644 index 000000000..b855f5bc0 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/value/mod.rs @@ -0,0 +1,698 @@ +//! 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_yaml::Value`. + Sequence(Sequence), + /// Represents a YAML mapping in which the keys and values are both + /// `serde_yaml::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 as _; +/// use serde_yaml::Value; +/// +/// #[derive(Deserialize)] +/// struct Settings { +/// level: i32, +/// #[serde(default)] +/// extras: Value, +/// } +/// +/// # fn try_main() -> Result<(), serde_yaml::Error> { +/// let data = r#" { "level": 42 } "#; +/// let s: Settings = serde_yaml::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_yaml::Value`. +pub type Sequence = Vec; + +/// Convert a `T` into `serde_yaml::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_yaml::Value; +/// let val = serde_yaml::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_yaml::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_yaml::Value; +/// let val = Value::String("foo".to_owned()); +/// let s: String = serde_yaml::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_yaml::Result<()> { + /// use serde_yaml::Value; + /// + /// let object: Value = serde_yaml::from_str(r#"{ A: 65, B: 66, C: 67 }"#)?; + /// let x = object.get("A").unwrap(); + /// assert_eq!(x, 65); + /// + /// let sequence: Value = serde_yaml::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_yaml::Value; + /// # + /// # fn main() -> serde_yaml::Result<()> { + /// let object: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("null").unwrap(); + /// assert!(v.is_null()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("null").unwrap(); + /// assert_eq!(v.as_null(), Some(())); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("true").unwrap(); + /// assert!(v.is_bool()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("true").unwrap(); + /// assert_eq!(v.as_bool(), Some(true)); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("5").unwrap(); + /// assert!(v.is_number()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("1337").unwrap(); + /// assert!(v.is_i64()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("1337").unwrap(); + /// assert_eq!(v.as_i64(), Some(1337)); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("1337").unwrap(); + /// assert!(v.is_u64()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("1337").unwrap(); + /// assert_eq!(v.as_u64(), Some(1337)); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("256.01").unwrap(); + /// assert!(v.is_f64()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("13.37").unwrap(); + /// assert_eq!(v.as_f64(), Some(13.37)); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("'lorem ipsum'").unwrap(); + /// assert!(v.is_string()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("'lorem ipsum'").unwrap(); + /// assert_eq!(v.as_str(), Some("lorem ipsum")); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("[1, 2, 3]").unwrap(); + /// assert!(v.is_sequence()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::{Value, Number}; + /// let v: Value = serde_yaml::from_str("[1, 2]").unwrap(); + /// assert_eq!(v.as_sequence(), Some(&vec![Value::Number(Number::from(1)), Value::Number(Number::from(2))])); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::{Value, Number}; + /// let mut v: Value = serde_yaml::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_yaml::Value; + /// let mut v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::from_str("a: 42").unwrap(); + /// assert!(v.is_mapping()); + /// ``` + /// + /// ``` + /// # use serde_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::{Value, Mapping, Number}; + /// let v: Value = serde_yaml::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_yaml::Value; + /// let v: Value = serde_yaml::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_yaml::{Value, Mapping, Number}; + /// let mut v: Value = serde_yaml::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_yaml::{Value, Mapping}; + /// let mut v: Value = serde_yaml::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_yaml::Value; + /// + /// let config = "\ + /// tasks: + /// build: &webpack_shared + /// command: webpack + /// args: build + /// inputs: + /// - 'src/**/*' + /// start: + /// <<: *webpack_shared + /// args: start + /// "; + /// + /// let mut value: Value = serde_yaml::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 + } +} diff --git a/kclvm/third-party/serde_yaml/src/value/partial_eq.rs b/kclvm/third-party/serde_yaml/src/value/partial_eq.rs new file mode 100644 index 000000000..023b7dd54 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/value/partial_eq.rs @@ -0,0 +1,87 @@ +use crate::Value; + +impl PartialEq for Value { + /// Compare `str` with YAML value + /// + /// # Examples + /// + /// ``` + /// # use serde_yaml::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_yaml::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_yaml::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_yaml::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 +} diff --git a/kclvm/third-party/serde_yaml/src/value/ser.rs b/kclvm/third-party/serde_yaml/src/value/ser.rs new file mode 100644 index 000000000..50b08d6b5 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/value/ser.rs @@ -0,0 +1,840 @@ +use 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_yaml::to_value`][crate::to_value]. +/// Unlike the main serde_yaml serializer which goes from some serializable +/// value of type `T` to YAML text, this one goes from `T` to +/// `serde_yaml::Value`. +/// +/// The `to_value` function is implementable as: +/// +/// ``` +/// use serde::Serialize; +/// use serde_yaml::{Error, Value}; +/// +/// pub fn to_value(input: T) -> Result +/// where +/// T: Serialize, +/// { +/// input.serialize(serde_yaml::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), + }))) + } +} diff --git a/kclvm/third-party/serde_yaml/src/value/tagged.rs b/kclvm/third-party/serde_yaml/src/value/tagged.rs new file mode 100644 index 000000000..baf6a0aeb --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/value/tagged.rs @@ -0,0 +1,474 @@ +use 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_yaml::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_yaml::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_yaml::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), + } +} diff --git a/kclvm/third-party/serde_yaml/src/with.rs b/kclvm/third-party/serde_yaml/src/with.rs new file mode 100644 index 000000000..51d5baab4 --- /dev/null +++ b/kclvm/third-party/serde_yaml/src/with.rs @@ -0,0 +1,2127 @@ +//! 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 as _; +/// # use serde::Serialize as _; +/// +/// #[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_yaml::with::singleton_map")] +/// w: Enum, +/// #[serde(with = "serde_yaml::with::singleton_map")] +/// x: Enum, +/// #[serde(with = "serde_yaml::with::singleton_map")] +/// y: Enum, +/// #[serde(with = "serde_yaml::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_yaml::to_string(&object).unwrap(); +/// print!("{}", yaml); +/// +/// let deserialized: Struct = serde_yaml::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 as _; +/// # use serde::Serialize as _; +/// +/// #[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_yaml::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_yaml::to_string(&object).unwrap(); +/// print!("{}", yaml); +/// +/// let deserialized: Outer = serde_yaml::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 as _; +/// # use serde::Serialize as _; +/// # +/// # #[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_yaml::Serializer::new(&mut buf); +/// serde_yaml::with::singleton_map_recursive::serialize(&object, &mut serializer).unwrap(); +/// io::stdout().write_all(&buf).unwrap(); +/// +/// let deserializer = serde_yaml::Deserializer::from_slice(&buf); +/// let deserialized: Inner = serde_yaml::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) + } + } +} diff --git a/kclvm/third-party/serde_yaml/tests/test_de.rs b/kclvm/third-party/serde_yaml/tests/test_de.rs new file mode 100644 index 000000000..b9e948de0 --- /dev/null +++ b/kclvm/third-party/serde_yaml/tests/test_de.rs @@ -0,0 +1,717 @@ +#![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_yaml::{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_yaml::from_str(yaml).unwrap(); + assert_eq!(*expected, deserialized); + + let value: Value = serde_yaml::from_str(yaml).unwrap(); + let deserialized = T::deserialize(&value).unwrap(); + assert_eq!(*expected, deserialized); + + let deserialized: T = serde_yaml::from_value(value).unwrap(); + assert_eq!(*expected, deserialized); + + serde_yaml::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_yaml::from_str(yaml).unwrap(); + assert_eq!(*expected, deserialized); + + serde_yaml::from_str::(yaml).unwrap(); + serde_yaml::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_yaml::from_str::(yaml).unwrap(); + serde_yaml::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_yaml::from_str::(yaml).unwrap()); + + let octal = indoc! {" + -0o1000000000000000000001 + "}; + assert_eq!(expected, serde_yaml::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_yaml::from_str::(yaml).unwrap()); + + let octal = indoc! {" + 0o2000000000000000000000 + "}; + assert_eq!(expected, serde_yaml::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_yaml::Mapping, + } + let yaml = indoc! {" + substructure: + a: 'foo' + b: 'bar' + "}; + + let mut expected = Data { + substructure: serde_yaml::Mapping::new(), + }; + expected.substructure.insert( + serde_yaml::Value::String("a".to_owned()), + serde_yaml::Value::String("foo".to_owned()), + ); + expected.substructure.insert( + serde_yaml::Value::String("b".to_owned()), + serde_yaml::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_yaml::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_yaml::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_yaml::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_yaml::from_str::(".nan") + .unwrap() + .is_sign_positive()); + assert!(serde_yaml::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_yaml::from_str(document).unwrap(); + assert_eq!(expected, deserialized); + + let expected = Vec::::new(); + let deserialized: Vec = serde_yaml::from_str(document).unwrap(); + assert_eq!(expected, deserialized); + + let expected = BTreeMap::new(); + let deserialized: BTreeMap = serde_yaml::from_str(document).unwrap(); + assert_eq!(expected, deserialized); + + let expected = None; + let deserialized: Option = serde_yaml::from_str(document).unwrap(); + assert_eq!(expected, deserialized); + + let expected = Value::Null; + let deserialized: Value = serde_yaml::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_yaml::Sequence::new(), + }; + test_de(yaml, &expected); + + let expected = Struct { + thing: serde_yaml::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"); +} diff --git a/kclvm/third-party/serde_yaml/tests/test_error.rs b/kclvm/third-party/serde_yaml/tests/test_error.rs new file mode 100644 index 000000000..883bb6da0 --- /dev/null +++ b/kclvm/third-party/serde_yaml/tests/test_error.rs @@ -0,0 +1,500 @@ +#![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_yaml::value::{Tag, TaggedValue}; +use serde_yaml::{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_yaml::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_yaml::to_string(&e).unwrap_err(); + assert_eq!(error.to_string(), expected); + + let e = Outer::Inner(Inner::Tuple(0, 0)); + let error = serde_yaml::to_string(&e).unwrap_err(); + assert_eq!(error.to_string(), expected); + + let e = Outer::Inner(Inner::Struct { x: 0 }); + let error = serde_yaml::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_yaml::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); +} diff --git a/kclvm/third-party/serde_yaml/tests/test_serde.rs b/kclvm/third-party/serde_yaml/tests/test_serde.rs new file mode 100644 index 000000000..1a892705a --- /dev/null +++ b/kclvm/third-party/serde_yaml/tests/test_serde.rs @@ -0,0 +1,648 @@ +#![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_yaml::{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_yaml::to_string(&thing).unwrap(); + assert_eq!(yaml, serialized); + + let value = serde_yaml::to_value(thing).unwrap(); + let serialized = serde_yaml::to_string(&value).unwrap(); + assert_eq!(yaml, serialized); + + let deserialized: T = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(*thing, deserialized); + + let value: Value = serde_yaml::from_str(yaml).unwrap(); + let deserialized = T::deserialize(&value).unwrap(); + assert_eq!(*thing, deserialized); + + let deserialized: T = serde_yaml::from_value(value).unwrap(); + assert_eq!(*thing, deserialized); + + serde_yaml::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_yaml::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_yaml::from_str(indoc! {" + .nan + "}) + .unwrap(); + assert!(single_float.is_nan()); +} + +#[test] +fn test_char() { + let ch = '.'; + let yaml = indoc! {" + '.' + "}; + assert_eq!(yaml, serde_yaml::to_string(&ch).unwrap()); + + let ch = '#'; + let yaml = indoc! {" + '#' + "}; + assert_eq!(yaml, serde_yaml::to_string(&ch).unwrap()); + + let ch = '-'; + let yaml = indoc! {" + '-' + "}; + assert_eq!(yaml, serde_yaml::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_yaml::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_moar_strings_needing_quote() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Struct { + s: String, + } + + for s in &[ + // Short hex values. + "0x0", + "0x1", + // Long hex values that don't fit in a u64 need to be quoted. + "0xffaed20B7B67e498A3bEEf97386ec1849EFeE6Ac", + // "empty" strings. + "", + " ", + // The norway problem https://hitchdev.com/strictyaml/why/implicit-typing-removed/ + "NO", + "no", + "No", + "Yes", + "YES", + "yes", + "True", + "TRUE", + "true", + "False", + "FALSE", + "false", + "y", + "Y", + "n", + "N", + "on", + "On", + "ON", + "off", + "Off", + "OFF", + "0", + "1", + "null", + "Null", + "NULL", + "nil", + "Nil", + "NIL", + // https://hitchdev.com/strictyaml/why/implicit-typing-removed/#string-or-float + "9.3", + // https://github.com/dtolnay/serde-yaml/pull/398#discussion_r1432944356 + "2E234567", + // https://yaml.org/spec/1.2.2/#1022-tag-resolution + "0o7", + "0x3A", + "+12.3", + "0.", + "-0.0", + "12e3", + "-2E+05", + "0", + "-0", + "3", + "-19", + ] { + let thing = Struct { s: s.to_string() }; + let yaml = format!("s: '{}'\n", s); + 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); +} diff --git a/kclvm/third-party/serde_yaml/tests/test_value.rs b/kclvm/third-party/serde_yaml/tests/test_value.rs new file mode 100644 index 000000000..4aca75b63 --- /dev/null +++ b/kclvm/third-party/serde_yaml/tests/test_value.rs @@ -0,0 +1,152 @@ +#![allow( + clippy::derive_partial_eq_without_eq, + clippy::eq_op, + clippy::uninlined_format_args +)] + +use indoc::indoc; +use serde::{de::IntoDeserializer, Deserialize as _}; +use serde_derive::{Deserialize, Serialize}; +use serde_yaml::{Number, Value}; + +#[test] +fn test_nan() { + let pos_nan = serde_yaml::from_str::(".nan").unwrap(); + assert!(pos_nan.is_f64()); + assert_eq!(pos_nan, pos_nan); + + let neg_fake_nan = serde_yaml::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_yaml::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_yaml::from_str::("xyz").unwrap(); + let s = String::deserialize(value.into_deserializer()).unwrap(); + assert_eq!(s, "xyz"); + + let value = serde_yaml::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_yaml::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_yaml::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_yaml::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_yaml::to_value(&Enum::Variant(0)).unwrap(); + + let deserialized: serde_yaml::Value = serde_yaml::from_value(value.clone()).unwrap(); + assert_eq!(value, deserialized); + + let serialized = serde_yaml::to_value(&value).unwrap(); + assert_eq!(value, serialized); +} diff --git a/kclvm/tools/Cargo.toml b/kclvm/tools/Cargo.toml index a08a19d0f..342944d5f 100644 --- a/kclvm/tools/Cargo.toml +++ b/kclvm/tools/Cargo.toml @@ -26,7 +26,7 @@ kclvm-driver = {path = "../driver"} kclvm-utils ={ path = "../utils"} serde_json = "1.0.85" -serde_yaml = "0.9.32" +serde_yaml = {path = "../third-party/serde_yaml"} once_cell = "1.15.0" regex = "1.3" json-spanned-value = "0.2.2"