diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/serde_yaml | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
22 files changed, 7400 insertions, 0 deletions
diff --git a/third_party/rust/serde_yaml/.cargo-checksum.json b/third_party/rust/serde_yaml/.cargo-checksum.json new file mode 100644 index 0000000000..eb1d4afddc --- /dev/null +++ b/third_party/rust/serde_yaml/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"1e01ffba9fa6c48ceda8bd7b3b936b5909c7adbfb05b6a5f8deb3f679d7da37e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"8b6df65d390bc4f9d5e05d0a4ccc860d6e5dc2668d82cd304e6c95b472a21f35","src/de.rs":"414b82334d78cf57b7cdc2fc1ed000594791b2f675648f5286678370f460a74d","src/error.rs":"96a49b8ea102d010760b3ade9b475d0c88d4014c17625302ddc145a9fea2988c","src/lib.rs":"a3276a7da395021e34547fe2f4336a5658f07d4d606a865b707a592f7b084e10","src/mapping.rs":"6607911090c89a41ade38f1717b9c0bd6c3c253cc4711890b77b2bda18d6bac7","src/number.rs":"4edf78ad75bf66bae31c1ee4d785ba2b7a2c14c082802d54c9feb93067bcf063","src/path.rs":"44d339ce1814effd10ba131ae0393df215f09dbfb35ab4d678f49d4081f58dd4","src/ser.rs":"e32c77b3e8087ca1b68a8f093e9f1e27b93ad1aac70a9bb22054b4179973cae1","src/value/de.rs":"84b213b23a8d4bf6bd9aacd18fc1091254382c4edc479f9a9abc87c416b370f0","src/value/from.rs":"cd66c76c4ab03bed32f8c4b22ffbd96274a837d587624a62d0584c7090633862","src/value/index.rs":"16f0e4fecd4a4cd149af89a7426864f58735f7dacc90f33d92c647b044c8f112","src/value/mod.rs":"171a98133de3445ccd4cfa3991b5c3f96baa1c05542fc1927e6eccf3e4ddbe09","src/value/partial_eq.rs":"0b28c8d2f10a58581dbe2a69d25742fa0f8bf3da797f3046e38e300d1f9691bf","src/value/ser.rs":"7ddb9bfadfbfe16a79c872888ea25f8fb7df14b862fea47dd603d576e162db86","tests/test_de.rs":"c7d8d71e8b0aa966ad4003657c1024405abeca0d49aec9f66f749db81bb1f061","tests/test_error.rs":"4ef5c9001f140e1aee1e9d6238c668d26b5b264e237773741d5f65bfff036e75","tests/test_serde.rs":"56aa2623b1aca1ba00d028edc60d6f74cde6eba83529d5bcd3340c4b0487db04","tests/test_value.rs":"f360eeaa7d281d52df18a452a6f67c6095bcf50b92f1a87c5a9e3c27b7a69f33"},"package":"578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b"}
\ No newline at end of file diff --git a/third_party/rust/serde_yaml/Cargo.toml b/third_party/rust/serde_yaml/Cargo.toml new file mode 100644 index 0000000000..3fd065aa35 --- /dev/null +++ b/third_party/rust/serde_yaml/Cargo.toml @@ -0,0 +1,53 @@ +# 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.56" +name = "serde_yaml" +version = "0.8.26" +authors = ["David Tolnay <dtolnay@gmail.com>"] +description = "YAML support for Serde" +documentation = "https://docs.rs/serde_yaml/" +readme = "README.md" +keywords = [ + "yaml", + "serde", +] +categories = ["encoding"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/serde-yaml" +resolver = "2" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies.indexmap] +version = "1.5.2" +features = ["std"] + +[dependencies.ryu] +version = "1.0" + +[dependencies.serde] +version = "1.0.69" + +[dependencies.yaml-rust] +version = "0.4.5" + +[dev-dependencies.anyhow] +version = "1.0" + +[dev-dependencies.indoc] +version = "1.0" + +[dev-dependencies.serde_derive] +version = "1.0" diff --git a/third_party/rust/serde_yaml/LICENSE-APACHE b/third_party/rust/serde_yaml/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/third_party/rust/serde_yaml/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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 + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/third_party/rust/serde_yaml/LICENSE-MIT b/third_party/rust/serde_yaml/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/third_party/rust/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/third_party/rust/serde_yaml/README.md b/third_party/rust/serde_yaml/README.md new file mode 100644 index 0000000000..4500865cb0 --- /dev/null +++ b/third_party/rust/serde_yaml/README.md @@ -0,0 +1,104 @@ +Serde YAML +========== + +[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/serde--yaml-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/serde-yaml) +[<img alt="crates.io" src="https://img.shields.io/crates/v/serde_yaml.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/serde_yaml) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-serde__yaml-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/serde_yaml) +[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/serde-yaml/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/serde-yaml/actions?query=branch%3Amaster) + +This crate is a Rust library for using the [Serde] serialization framework with +data in [YAML] file format. + +[Serde]: https://github.com/serde-rs/serde +[YAML]: https://yaml.org/ + +This library does not reimplement a YAML parser; it uses [yaml-rust] which is a +pure Rust YAML 1.2 implementation. + +[yaml-rust]: https://github.com/chyh1990/yaml-rust + +## Dependency + +```toml +[dependencies] +serde = "1.0" +serde_yaml = "0.8" +``` + +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. + let s = serde_yaml::to_string(&map)?; + assert_eq!(s, "---\nx: 1.0\ny: 2.0\n"); + + // Deserialize it back to a Rust type. + let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s)?; + assert_eq!(map, deserialized_map); + Ok(()) +} +``` + +It can also be used with Serde's derive macros to handle structs and enums +defined by your program. + +```toml +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.8" +``` + +```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 s = serde_yaml::to_string(&point)?; + assert_eq!(s, "---\nx: 1.0\ny: 2.0\n"); + + let deserialized_point: Point = serde_yaml::from_str(&s)?; + assert_eq!(point, deserialized_point); + Ok(()) +} +``` + +<br> + +#### License + +<sup> +Licensed under either of <a href="LICENSE-APACHE">Apache License, Version +2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. +</sup> + +<br> + +<sub> +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. +</sub> diff --git a/third_party/rust/serde_yaml/src/de.rs b/third_party/rust/serde_yaml/src/de.rs new file mode 100644 index 0000000000..8ccf271093 --- /dev/null +++ b/third_party/rust/serde_yaml/src/de.rs @@ -0,0 +1,1525 @@ +use crate::error::{self, Error, ErrorImpl, Result}; +use crate::path::Path; +use serde::de::{ + self, Deserialize, DeserializeOwned, DeserializeSeed, Expected, IgnoredAny as Ignore, + IntoDeserializer, Unexpected, Visitor, +}; +use std::collections::BTreeMap; +use std::f64; +use std::fmt; +use std::io; +use std::marker::PhantomData; +use std::mem; +use std::str; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; +use yaml_rust::parser::{Event as YamlEvent, MarkedEventReceiver, Parser}; +use yaml_rust::scanner::{Marker, TScalarStyle, TokenType}; + +/// 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 = "---\nk: 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<'a> { + input: Input<'a>, +} + +enum Input<'a> { + Str(&'a str), + Slice(&'a [u8]), + Read(Box<dyn io::Read + 'a>), + Multidoc(Arc<Multidoc>), + Fail(Arc<ErrorImpl>), +} + +impl<'a> Deserializer<'a> { + /// Creates a YAML deserializer from a `&str`. + pub fn from_str(s: &'a str) -> Self { + let input = Input::Str(s); + Deserializer { input } + } + + /// Creates a YAML deserializer from a `&[u8]`. + pub fn from_slice(v: &'a [u8]) -> Self { + let input = Input::Slice(v); + Deserializer { input } + } + + /// 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<R>(rdr: R) -> Self + where + R: io::Read + 'a, + { + let input = Input::Read(Box::new(rdr)); + Deserializer { input } + } + + fn de<T>(self, f: impl FnOnce(&mut DeserializerFromEvents) -> Result<T>) -> Result<T> { + if let Input::Multidoc(multidoc) = &self.input { + let mut pos = multidoc.pos.load(Ordering::Relaxed); + let t = f(&mut DeserializerFromEvents { + events: &multidoc.loader.events, + aliases: &multidoc.loader.aliases, + pos: &mut pos, + path: Path::Root, + remaining_depth: 128, + })?; + multidoc.pos.store(pos, Ordering::Relaxed); + return Ok(t); + } + + let loader = loader(self.input)?; + if loader.events.is_empty() { + return Err(error::end_of_stream()); + } + let mut pos = 0; + let t = f(&mut DeserializerFromEvents { + events: &loader.events, + aliases: &loader.aliases, + pos: &mut pos, + path: Path::Root, + remaining_depth: 128, + })?; + if pos == loader.events.len() { + Ok(t) + } else { + Err(error::more_than_one_document()) + } + } +} + +fn loader(input: Input) -> Result<Loader> { + enum Input2<'a> { + Str(&'a str), + Slice(&'a [u8]), + } + + let mut buffer; + let input = match input { + Input::Str(s) => Input2::Str(s), + Input::Slice(bytes) => Input2::Slice(bytes), + Input::Read(mut rdr) => { + buffer = Vec::new(); + rdr.read_to_end(&mut buffer).map_err(error::io)?; + Input2::Slice(&buffer) + } + Input::Multidoc(_) => unreachable!(), + Input::Fail(err) => return Err(error::shared(err)), + }; + + let input = match input { + Input2::Str(s) => s, + Input2::Slice(bytes) => str::from_utf8(bytes).map_err(error::str_utf8)?, + }; + + let mut parser = Parser::new(input.chars()); + let mut loader = Loader { + events: Vec::new(), + aliases: BTreeMap::new(), + }; + parser.load(&mut loader, true).map_err(error::scanner)?; + Ok(loader) +} + +struct Multidoc { + loader: Loader, + pos: AtomicUsize, +} + +impl<'de> Iterator for Deserializer<'de> { + type Item = Self; + + fn next(&mut self) -> Option<Self> { + match &self.input { + Input::Multidoc(multidoc) => { + let pos = multidoc.pos.load(Ordering::Relaxed); + return if pos < multidoc.loader.events.len() { + Some(Deserializer { + input: Input::Multidoc(Arc::clone(multidoc)), + }) + } else { + None + }; + } + Input::Fail(err) => { + return Some(Deserializer { + input: Input::Fail(Arc::clone(err)), + }); + } + _ => {} + } + + let dummy = Input::Str(""); + let input = mem::replace(&mut self.input, dummy); + match loader(input) { + Ok(loader) => { + let multidoc = Arc::new(Multidoc { + loader, + pos: AtomicUsize::new(0), + }); + self.input = Input::Multidoc(Arc::clone(&multidoc)); + if multidoc.loader.events.is_empty() { + None + } else { + Some(Deserializer { + input: Input::Multidoc(multidoc), + }) + } + } + Err(err) => { + let fail = err.shared(); + self.input = Input::Fail(Arc::clone(&fail)); + Some(Deserializer { + input: Input::Fail(fail), + }) + } + } + } +} + +impl<'de> de::Deserializer<'de> for Deserializer<'de> { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_any(visitor)) + } + + fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_bool(visitor)) + } + + fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_i8(visitor)) + } + + fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_i16(visitor)) + } + + fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_i32(visitor)) + } + + fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_i64(visitor)) + } + + fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_i128(visitor)) + } + + fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_u8(visitor)) + } + + fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_u16(visitor)) + } + + fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_u32(visitor)) + } + + fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_u64(visitor)) + } + + fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_u128(visitor)) + } + + fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_f32(visitor)) + } + + fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_f64(visitor)) + } + + fn deserialize_char<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_char(visitor)) + } + + fn deserialize_str<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_str(visitor)) + } + + fn deserialize_string<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_string(visitor)) + } + + fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_bytes(visitor)) + } + + fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_byte_buf(visitor)) + } + + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_option(visitor)) + } + + fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_unit(visitor)) + } + + fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_unit_struct(name, visitor)) + } + + fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_newtype_struct(name, visitor)) + } + + fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_seq(visitor)) + } + + fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_tuple(len, visitor)) + } + + fn deserialize_tuple_struct<V>( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_tuple_struct(name, len, visitor)) + } + + fn deserialize_map<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_map(visitor)) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_struct(name, fields, visitor)) + } + + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_enum(name, variants, visitor)) + } + + fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_identifier(visitor)) + } + + fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.de(|state| state.deserialize_ignored_any(visitor)) + } +} + +pub struct Loader { + events: Vec<(Event, Marker)>, + /// Map from alias id to index in events. + aliases: BTreeMap<usize, usize>, +} + +impl MarkedEventReceiver for Loader { + fn on_event(&mut self, event: YamlEvent, marker: Marker) { + let event = match event { + YamlEvent::Nothing + | YamlEvent::StreamStart + | YamlEvent::StreamEnd + | YamlEvent::DocumentStart + | YamlEvent::DocumentEnd => return, + + YamlEvent::Alias(id) => Event::Alias(id), + YamlEvent::Scalar(value, style, id, tag) => { + self.aliases.insert(id, self.events.len()); + Event::Scalar(value, style, tag) + } + YamlEvent::SequenceStart(id) => { + self.aliases.insert(id, self.events.len()); + Event::SequenceStart + } + YamlEvent::SequenceEnd => Event::SequenceEnd, + YamlEvent::MappingStart(id) => { + self.aliases.insert(id, self.events.len()); + Event::MappingStart + } + YamlEvent::MappingEnd => Event::MappingEnd, + }; + self.events.push((event, marker)); + } +} + +#[derive(Debug, PartialEq)] +enum Event { + Alias(usize), + Scalar(String, TScalarStyle, Option<TokenType>), + SequenceStart, + SequenceEnd, + MappingStart, + MappingEnd, +} + +struct DeserializerFromEvents<'a> { + events: &'a [(Event, Marker)], + /// Map from alias id to index in events. + aliases: &'a BTreeMap<usize, usize>, + pos: &'a mut usize, + path: Path<'a>, + remaining_depth: u8, +} + +impl<'a> DeserializerFromEvents<'a> { + fn peek(&self) -> Result<(&'a Event, Marker)> { + match self.events.get(*self.pos) { + Some(event) => Ok((&event.0, event.1)), + None => Err(error::end_of_stream()), + } + } + + fn next(&mut self) -> Result<(&'a Event, Marker)> { + self.opt_next().ok_or_else(error::end_of_stream) + } + + fn opt_next(&mut self) -> Option<(&'a Event, Marker)> { + self.events.get(*self.pos).map(|event| { + *self.pos += 1; + (&event.0, event.1) + }) + } + + fn jump(&'a self, pos: &'a mut usize) -> Result<DeserializerFromEvents<'a>> { + match self.aliases.get(pos) { + Some(&found) => { + *pos = found; + Ok(DeserializerFromEvents { + events: self.events, + aliases: self.aliases, + pos, + path: Path::Alias { parent: &self.path }, + remaining_depth: self.remaining_depth, + }) + } + None => panic!("unresolved alias: {}", *pos), + } + } + + fn ignore_any(&mut self) { + enum Nest { + Sequence, + Mapping, + } + + let mut stack = Vec::new(); + + while let Some((event, _)) = self.opt_next() { + match event { + Event::Alias(_) | Event::Scalar(_, _, _) => {} + 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; + } + } + + if !stack.is_empty() { + panic!("missing end event"); + } + } + + fn visit_sequence<'de, V>(&mut self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (value, len) = self.recursion_check(|de| { + let mut seq = SeqAccess { de, len: 0 }; + let value = visitor.visit_seq(&mut seq)?; + Ok((value, seq.len)) + })?; + self.end_sequence(len)?; + Ok(value) + } + + fn visit_mapping<'de, V>(&mut self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (value, len) = self.recursion_check(|de| { + let mut map = MapAccess { + 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 { de: self, len }; + while de::SeqAccess::next_element::<Ignore>(&mut seq)?.is_some() {} + seq.len + }; + assert_eq!(Event::SequenceEnd, *self.next()?.0); + 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 { + de: self, + len, + key: None, + }; + while de::MapAccess::next_entry::<Ignore, Ignore>(&mut map)?.is_some() {} + map.len + }; + assert_eq!(Event::MappingEnd, *self.next()?.0); + 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<F: FnOnce(&mut Self) -> Result<T>, T>(&mut self, f: F) -> Result<T> { + let previous_depth = self.remaining_depth; + self.remaining_depth = previous_depth + .checked_sub(1) + .ok_or_else(error::recursion_limit_exceeded)?; + let result = f(self); + self.remaining_depth = previous_depth; + result + } +} + +fn visit_scalar<'de, V>( + v: &str, + style: TScalarStyle, + tag: &Option<TokenType>, + visitor: V, +) -> Result<V::Value> +where + V: Visitor<'de>, +{ + if let Some(TokenType::Tag(handle, suffix)) = tag { + if handle == "!!" { + match suffix.as_ref() { + "bool" => match v.parse::<bool>() { + Ok(v) => visitor.visit_bool(v), + Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"a boolean")), + }, + "int" => match v.parse::<i64>() { + Ok(v) => visitor.visit_i64(v), + Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"an integer")), + }, + "float" => match v.parse::<f64>() { + Ok(v) => visitor.visit_f64(v), + Err(_) => Err(de::Error::invalid_value(Unexpected::Str(v), &"a float")), + }, + "null" => match v { + "~" | "null" => visitor.visit_unit(), + _ => Err(de::Error::invalid_value(Unexpected::Str(v), &"null")), + }, + _ => visitor.visit_str(v), + } + } else { + visitor.visit_str(v) + } + } else if style == TScalarStyle::Plain { + visit_untagged_str(visitor, v) + } else { + visitor.visit_str(v) + } +} + +struct SeqAccess<'a: 'r, 'r> { + de: &'r mut DeserializerFromEvents<'a>, + len: usize, +} + +impl<'de, 'a, 'r> de::SeqAccess<'de> for SeqAccess<'a, 'r> { + type Error = Error; + + fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>> + where + T: DeserializeSeed<'de>, + { + match self.de.peek()?.0 { + Event::SequenceEnd => Ok(None), + _ => { + let mut element_de = DeserializerFromEvents { + events: self.de.events, + aliases: self.de.aliases, + pos: self.de.pos, + path: Path::Seq { + parent: &self.de.path, + index: self.len, + }, + remaining_depth: self.de.remaining_depth, + }; + self.len += 1; + seed.deserialize(&mut element_de).map(Some) + } + } + } +} + +struct MapAccess<'a: 'r, 'r> { + de: &'r mut DeserializerFromEvents<'a>, + len: usize, + key: Option<&'a str>, +} + +impl<'de, 'a, 'r> de::MapAccess<'de> for MapAccess<'a, 'r> { + type Error = Error; + + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>> + where + K: DeserializeSeed<'de>, + { + match self.de.peek()?.0 { + Event::MappingEnd => Ok(None), + Event::Scalar(key, _, _) => { + self.len += 1; + self.key = Some(key); + seed.deserialize(&mut *self.de).map(Some) + } + _ => { + self.len += 1; + self.key = None; + seed.deserialize(&mut *self.de).map(Some) + } + } + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value> + where + V: DeserializeSeed<'de>, + { + let mut value_de = DeserializerFromEvents { + events: self.de.events, + aliases: self.de.aliases, + pos: self.de.pos, + path: if let Some(key) = self.key { + Path::Map { + parent: &self.de.path, + key, + } + } else { + Path::Unknown { + parent: &self.de.path, + } + }, + remaining_depth: self.de.remaining_depth, + }; + seed.deserialize(&mut value_de) + } +} + +struct EnumAccess<'a: 'r, 'r> { + de: &'r mut DeserializerFromEvents<'a>, + name: &'static str, + tag: Option<&'static str>, +} + +impl<'de, 'a, 'r> de::EnumAccess<'de> for EnumAccess<'a, 'r> { + type Error = Error; + type Variant = DeserializerFromEvents<'r>; + + fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)> + where + V: DeserializeSeed<'de>, + { + #[derive(Debug)] + enum Nope {} + + struct BadKey { + name: &'static str, + } + + impl<'de> Visitor<'de> for BadKey { + type Value = Nope; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "variant of enum `{}`", self.name) + } + } + + let variant = if let Some(tag) = self.tag { + tag + } else { + match self.de.next()?.0 { + Event::Scalar(s, _, _) => &**s, + _ => { + *self.de.pos -= 1; + let bad = BadKey { name: self.name }; + return Err(de::Deserializer::deserialize_any(&mut *self.de, bad).unwrap_err()); + } + } + }; + + let str_de = IntoDeserializer::<Error>::into_deserializer(variant); + let ret = seed.deserialize(str_de)?; + let variant_visitor = DeserializerFromEvents { + events: self.de.events, + aliases: self.de.aliases, + pos: self.de.pos, + path: Path::Map { + parent: &self.de.path, + key: variant, + }, + remaining_depth: self.de.remaining_depth, + }; + Ok((ret, variant_visitor)) + } +} + +impl<'de, 'a> de::VariantAccess<'de> for DeserializerFromEvents<'a> { + type Error = Error; + + fn unit_variant(mut self) -> Result<()> { + Deserialize::deserialize(&mut self) + } + + fn newtype_variant_seed<T>(mut self, seed: T) -> Result<T::Value> + where + T: DeserializeSeed<'de>, + { + seed.deserialize(&mut self) + } + + fn tuple_variant<V>(mut self, _len: usize, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + de::Deserializer::deserialize_seq(&mut self, visitor) + } + + fn struct_variant<V>(mut self, fields: &'static [&'static str], visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + de::Deserializer::deserialize_struct(&mut self, "", fields, visitor) + } +} + +struct UnitVariantAccess<'a: 'r, 'r> { + de: &'r mut DeserializerFromEvents<'a>, +} + +impl<'de, 'a, 'r> de::EnumAccess<'de> for UnitVariantAccess<'a, 'r> { + type Error = Error; + type Variant = Self; + + fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)> + where + V: DeserializeSeed<'de>, + { + Ok((seed.deserialize(&mut *self.de)?, self)) + } +} + +impl<'de, 'a, 'r> de::VariantAccess<'de> for UnitVariantAccess<'a, 'r> { + type Error = Error; + + fn unit_variant(self) -> Result<()> { + Ok(()) + } + + fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value> + where + T: DeserializeSeed<'de>, + { + Err(de::Error::invalid_type( + Unexpected::UnitVariant, + &"newtype variant", + )) + } + + fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + Err(de::Error::invalid_type( + Unexpected::UnitVariant, + &"tuple variant", + )) + } + + fn struct_variant<V>(self, _fields: &'static [&'static str], _visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + Err(de::Error::invalid_type( + Unexpected::UnitVariant, + &"struct variant", + )) + } +} + +fn visit_untagged_str<'de, V>(visitor: V, v: &str) -> Result<V::Value> +where + V: Visitor<'de>, +{ + if v == "~" || v == "null" { + return visitor.visit_unit(); + } + if v == "true" { + return visitor.visit_bool(true); + } + if v == "false" { + return visitor.visit_bool(false); + } + if let Some(rest) = Option::or(v.strip_prefix("0x"), v.strip_prefix("+0x")) { + if let Ok(n) = u64::from_str_radix(rest, 16) { + return visitor.visit_u64(n); + } + } + if let Some(rest) = v.strip_prefix("-0x") { + let negative = format!("-{}", rest); + if let Ok(n) = i64::from_str_radix(&negative, 16) { + return visitor.visit_i64(n); + } + } + if let Some(rest) = Option::or(v.strip_prefix("0o"), v.strip_prefix("+0o")) { + if let Ok(n) = u64::from_str_radix(rest, 8) { + return visitor.visit_u64(n); + } + } + if let Some(rest) = v.strip_prefix("-0o") { + let negative = format!("-{}", rest); + if let Ok(n) = i64::from_str_radix(&negative, 8) { + return visitor.visit_i64(n); + } + } + if let Some(rest) = Option::or(v.strip_prefix("0b"), v.strip_prefix("+0b")) { + if let Ok(n) = u64::from_str_radix(rest, 2) { + return visitor.visit_u64(n); + } + } + if let Some(rest) = v.strip_prefix("-0b") { + let negative = format!("-{}", rest); + if let Ok(n) = i64::from_str_radix(&negative, 2) { + return visitor.visit_i64(n); + } + } + if { + let v = v.trim_start_matches(&['-', '+'][..]); + v.len() > 1 && v.starts_with('0') && v[1..].bytes().all(|b| b.is_ascii_digit()) + } { + // After handling the different number encodings above if we are left + // with leading zero(s) followed by numeric characters this is in fact a + // string according to the YAML 1.2 spec. + // https://yaml.org/spec/1.2/spec.html#id2761292 + return visitor.visit_str(v); + } + if let Ok(n) = v.parse() { + return visitor.visit_u64(n); + } + if let Ok(n) = v.parse() { + return visitor.visit_u128(n); + } + if let Ok(n) = v.parse() { + return visitor.visit_i64(n); + } + if let Ok(n) = v.parse() { + return visitor.visit_i128(n); + } + match v.trim_start_matches('+') { + ".inf" | ".Inf" | ".INF" => return visitor.visit_f64(f64::INFINITY), + _ => (), + } + if v == "-.inf" || v == "-.Inf" || v == "-.INF" { + return visitor.visit_f64(f64::NEG_INFINITY); + } + if v == ".nan" || v == ".NaN" || v == ".NAN" { + return visitor.visit_f64(f64::NAN); + } + if let Ok(n) = v.parse::<f64>() { + if n.is_finite() { + return visitor.visit_f64(n); + } + } + visitor.visit_str(v) +} + +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(v, style, tag) => { + let get_type = InvalidType { exp }; + match visit_scalar(v, *style, tag, get_type) { + 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"), + } +} + +impl<'a> DeserializerFromEvents<'a> { + fn deserialize_scalar<'de, V>(&mut self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (next, marker) = self.next()?; + match next { + Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_scalar(visitor), + Event::Scalar(v, style, tag) => visit_scalar(v, *style, tag, visitor), + other => Err(invalid_type(other, &visitor)), + } + .map_err(|err| error::fix_marker(err, marker, self.path)) + } +} + +impl<'de, 'a, 'r> de::Deserializer<'de> for &'r mut DeserializerFromEvents<'a> { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (next, marker) = self.next()?; + match next { + Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_any(visitor), + Event::Scalar(v, style, tag) => visit_scalar(v, *style, tag, visitor), + Event::SequenceStart => self.visit_sequence(visitor), + Event::MappingStart => self.visit_mapping(visitor), + Event::SequenceEnd => panic!("unexpected end of sequence"), + Event::MappingEnd => panic!("unexpected end of mapping"), + } + // 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_marker(err, marker, self.path)) + } + + fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_char<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_str<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (next, marker) = self.next()?; + match next { + Event::Scalar(v, _, _) => visitor.visit_str(v), + Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_str(visitor), + other => Err(invalid_type(other, &visitor)), + } + .map_err(|err: Error| error::fix_marker(err, marker, self.path)) + } + + fn deserialize_string<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } + + fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_bytes(visitor) + } + + /// Parses `null` as None and any other values as `Some(...)`. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + let is_some = match self.peek()?.0 { + Event::Alias(mut pos) => { + *self.pos += 1; + return self.jump(&mut pos)?.deserialize_option(visitor); + } + Event::Scalar(v, style, tag) => { + if *style != TScalarStyle::Plain { + true + } else if let Some(TokenType::Tag(handle, suffix)) = tag { + if handle == "!!" && suffix == "null" { + if v == "~" || v == "null" { + false + } else { + return Err(de::Error::invalid_value(Unexpected::Str(v), &"null")); + } + } else { + true + } + } else { + v != "~" && v != "null" + } + } + Event::SequenceStart | Event::MappingStart => true, + Event::SequenceEnd => panic!("unexpected end of sequence"), + Event::MappingEnd => panic!("unexpected end of mapping"), + }; + if is_some { + visitor.visit_some(self) + } else { + *self.pos += 1; + visitor.visit_none() + } + } + + fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_scalar(visitor) + } + + fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + /// Parses a newtype struct as the underlying value. + fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (next, marker) = self.next()?; + match next { + Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_seq(visitor), + Event::SequenceStart => self.visit_sequence(visitor), + other => Err(invalid_type(other, &visitor)), + } + .map_err(|err| error::fix_marker(err, marker, self.path)) + } + + fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct<V>( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (next, marker) = self.next()?; + match next { + Event::Alias(mut pos) => self.jump(&mut pos)?.deserialize_map(visitor), + Event::MappingStart => self.visit_mapping(visitor), + other => Err(invalid_type(other, &visitor)), + } + .map_err(|err| error::fix_marker(err, marker, self.path)) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (next, marker) = self.next()?; + match next { + Event::Alias(mut pos) => self + .jump(&mut pos)? + .deserialize_struct(name, fields, visitor), + Event::SequenceStart => self.visit_sequence(visitor), + Event::MappingStart => self.visit_mapping(visitor), + other => Err(invalid_type(other, &visitor)), + } + .map_err(|err| error::fix_marker(err, marker, self.path)) + } + + /// 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<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value> + where + V: Visitor<'de>, + { + let (next, marker) = self.peek()?; + match next { + Event::Alias(mut pos) => { + *self.pos += 1; + self.jump(&mut pos)? + .deserialize_enum(name, variants, visitor) + } + Event::Scalar(_, _, t) => { + if let Some(TokenType::Tag(handle, suffix)) = t { + if handle == "!" { + if let Some(tag) = variants.iter().find(|v| *v == suffix) { + return visitor.visit_enum(EnumAccess { + de: self, + name, + tag: Some(tag), + }); + } + } + } + visitor.visit_enum(UnitVariantAccess { de: self }) + } + Event::MappingStart => { + *self.pos += 1; + let value = visitor.visit_enum(EnumAccess { + de: self, + name, + tag: None, + })?; + self.end_mapping(1)?; + Ok(value) + } + Event::SequenceStart => { + let err = de::Error::invalid_type(Unexpected::Seq, &"string or singleton map"); + Err(error::fix_marker(err, marker, self.path)) + } + Event::SequenceEnd => panic!("unexpected end of sequence"), + Event::MappingEnd => panic!("unexpected end of mapping"), + } + } + + fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value> + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value> + 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. +/// +/// YAML currently does not support zero-copy deserialization. +pub fn from_str<T>(s: &str) -> Result<T> +where + T: DeserializeOwned, +{ + from_str_seed(s, PhantomData) +} + +/// Deserialize an instance of type `T` from a string of YAML text with a seed. +/// +/// 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. +/// +/// YAML currently does not support zero-copy deserialization. +pub fn from_str_seed<T, S>(s: &str, seed: S) -> Result<T> +where + S: for<'de> DeserializeSeed<'de, Value = T>, +{ + seed.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<R, T>(rdr: R) -> Result<T> +where + R: io::Read, + T: DeserializeOwned, +{ + from_reader_seed(rdr, PhantomData) +} + +/// Deserialize an instance of type `T` from an IO stream of YAML with a seed. +/// +/// 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_seed<R, T, S>(rdr: R, seed: S) -> Result<T> +where + R: io::Read, + S: for<'de> DeserializeSeed<'de, Value = T>, +{ + seed.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. +/// +/// YAML currently does not support zero-copy deserialization. +pub fn from_slice<T>(v: &[u8]) -> Result<T> +where + T: DeserializeOwned, +{ + from_slice_seed(v, PhantomData) +} + +/// Deserialize an instance of type `T` from bytes of YAML text with a seed. +/// +/// 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. +/// +/// YAML currently does not support zero-copy deserialization. +pub fn from_slice_seed<T, S>(v: &[u8], seed: S) -> Result<T> +where + S: for<'de> DeserializeSeed<'de, Value = T>, +{ + seed.deserialize(Deserializer::from_slice(v)) +} diff --git a/third_party/rust/serde_yaml/src/error.rs b/third_party/rust/serde_yaml/src/error.rs new file mode 100644 index 0000000000..dc8321435f --- /dev/null +++ b/third_party/rust/serde_yaml/src/error.rs @@ -0,0 +1,244 @@ +use crate::path::Path; +use serde::{de, ser}; +use std::error; +use std::fmt::{self, Debug, Display}; +use std::io; +use std::result; +use std::str; +use std::string; +use std::sync::Arc; +use yaml_rust::emitter; +use yaml_rust::scanner::{self, Marker, ScanError}; + +/// An error that happened serializing or deserializing YAML data. +pub struct Error(Box<ErrorImpl>); + +/// Alias for a `Result` with the error type `serde_yaml::Error`. +pub type Result<T> = result::Result<T, Error>; + +#[derive(Debug)] +pub enum ErrorImpl { + Message(String, Option<Pos>), + + Emit(emitter::EmitError), + Scan(scanner::ScanError), + Io(io::Error), + Utf8(str::Utf8Error), + FromUtf8(string::FromUtf8Error), + + EndOfStream, + MoreThanOneDocument, + RecursionLimitExceeded, + + Shared(Arc<ErrorImpl>), +} + +#[derive(Debug)] +pub struct Pos { + marker: Marker, + 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_marker(marker: &Marker) -> Self { + Location { + // `col` returned from the `yaml` crate is 0-indexed but all error messages add + 1 to this value + column: marker.col() + 1, + index: marker.index(), + line: marker.line(), + } + } +} + +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<Value, Error> = 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<Location> { + match self.0.as_ref() { + ErrorImpl::Message(_, Some(pos)) => Some(Location::from_marker(&pos.marker)), + ErrorImpl::Scan(scan) => Some(Location::from_marker(scan.marker())), + _ => None, + } + } +} + +pub(crate) fn end_of_stream() -> Error { + Error(Box::new(ErrorImpl::EndOfStream)) +} + +pub(crate) fn more_than_one_document() -> Error { + Error(Box::new(ErrorImpl::MoreThanOneDocument)) +} + +pub(crate) fn io(err: io::Error) -> Error { + Error(Box::new(ErrorImpl::Io(err))) +} + +pub(crate) fn emitter(err: emitter::EmitError) -> Error { + Error(Box::new(ErrorImpl::Emit(err))) +} + +pub(crate) fn scanner(err: scanner::ScanError) -> Error { + Error(Box::new(ErrorImpl::Scan(err))) +} + +pub(crate) fn str_utf8(err: str::Utf8Error) -> Error { + Error(Box::new(ErrorImpl::Utf8(err))) +} + +pub(crate) fn string_utf8(err: string::FromUtf8Error) -> Error { + Error(Box::new(ErrorImpl::FromUtf8(err))) +} + +pub(crate) fn recursion_limit_exceeded() -> Error { + Error(Box::new(ErrorImpl::RecursionLimitExceeded)) +} + +pub(crate) fn shared(shared: Arc<ErrorImpl>) -> Error { + Error(Box::new(ErrorImpl::Shared(shared))) +} + +pub(crate) fn fix_marker(mut error: Error, marker: Marker, path: Path) -> Error { + if let ErrorImpl::Message(_, none @ None) = error.0.as_mut() { + *none = Some(Pos { + marker, + path: path.to_string(), + }); + } + error +} + +impl Error { + pub(crate) fn shared(self) -> Arc<ErrorImpl> { + if let ErrorImpl::Shared(err) = *self.0 { + err + } else { + Arc::from(self.0) + } + } +} + +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + '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<T: Display>(msg: T) -> Self { + Error(Box::new(ErrorImpl::Message(msg.to_string(), None))) + } +} + +impl de::Error for Error { + fn custom<T: Display>(msg: T) -> Self { + Error(Box::new(ErrorImpl::Message(msg.to_string(), None))) + } +} + +impl ErrorImpl { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + ErrorImpl::Scan(err) => Some(err), + ErrorImpl::Io(err) => Some(err), + ErrorImpl::Utf8(err) => Some(err), + ErrorImpl::FromUtf8(err) => Some(err), + ErrorImpl::Shared(err) => err.source(), + _ => None, + } + } + + fn display(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ErrorImpl::Message(msg, None) => Display::fmt(msg, f), + ErrorImpl::Message(msg, Some(Pos { marker, path })) => { + if path == "." { + write!(f, "{}", ScanError::new(*marker, msg)) + } else { + write!(f, "{}: {}", path, ScanError::new(*marker, msg)) + } + } + ErrorImpl::Emit(emitter::EmitError::FmtError(_)) => f.write_str("yaml-rust fmt error"), + ErrorImpl::Emit(emitter::EmitError::BadHashmapKey) => f.write_str("bad hash map key"), + ErrorImpl::Scan(err) => Display::fmt(err, f), + ErrorImpl::Io(err) => Display::fmt(err, f), + ErrorImpl::Utf8(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 => f.write_str("recursion limit exceeded"), + ErrorImpl::Shared(err) => err.display(f), + } + } + + fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ErrorImpl::Message(msg, pos) => f.debug_tuple("Message").field(msg).field(pos).finish(), + ErrorImpl::Emit(emit) => f.debug_tuple("Emit").field(emit).finish(), + ErrorImpl::Scan(scan) => f.debug_tuple("Scan").field(scan).finish(), + ErrorImpl::Io(io) => f.debug_tuple("Io").field(io).finish(), + ErrorImpl::Utf8(utf8) => f.debug_tuple("Utf8").field(utf8).finish(), + ErrorImpl::FromUtf8(from_utf8) => f.debug_tuple("FromUtf8").field(from_utf8).finish(), + ErrorImpl::EndOfStream => f.debug_tuple("EndOfStream").finish(), + ErrorImpl::MoreThanOneDocument => f.debug_tuple("MoreThanOneDocument").finish(), + ErrorImpl::RecursionLimitExceeded => f.debug_tuple("RecursionLimitExceeded").finish(), + ErrorImpl::Shared(err) => err.debug(f), + } + } +} diff --git a/third_party/rust/serde_yaml/src/lib.rs b/third_party/rust/serde_yaml/src/lib.rs new file mode 100644 index 0000000000..f3fc6a9d3c --- /dev/null +++ b/third_party/rust/serde_yaml/src/lib.rs @@ -0,0 +1,125 @@ +//! [![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 +//! +//! <br> +//! +//! This crate is a Rust library for using the [Serde] serialization framework +//! with data in [YAML] file format. +//! +//! This library does not reimplement a YAML parser; it uses [yaml-rust] which +//! is a pure Rust YAML 1.2 implementation. +//! +//! [Serde]: https://github.com/serde-rs/serde +//! [YAML]: https://yaml.org/ +//! [yaml-rust]: https://github.com/chyh1990/yaml-rust +//! +//! # 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. +//! let s = serde_yaml::to_string(&map)?; +//! assert_eq!(s, "---\nx: 1.0\ny: 2.0\n"); +//! +//! // Deserialize it back to a Rust type. +//! let deserialized_map: BTreeMap<String, f64> = serde_yaml::from_str(&s)?; +//! assert_eq!(map, deserialized_map); +//! Ok(()) +//! } +//! ``` +//! +//! ## Using Serde derive +//! +//! It can also be used with Serde's serialization code generator `serde_derive` to +//! handle structs and enums defined in your own program. +//! +//! ``` +//! # use serde_derive::{Serialize, Deserialize}; +//! 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 s = serde_yaml::to_string(&point)?; +//! assert_eq!(s, "---\nx: 1.0\ny: 2.0\n"); +//! +//! let deserialized_point: Point = serde_yaml::from_str(&s)?; +//! assert_eq!(point, deserialized_point); +//! Ok(()) +//! } +//! ``` + +#![doc(html_root_url = "https://docs.rs/serde_yaml/0.8.26")] +#![deny(missing_docs)] +// Suppressed clippy_pedantic lints +#![allow( + // buggy + clippy::iter_not_returning_iterator, // https://github.com/rust-lang/rust-clippy/issues/8285 + 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::option_if_let_else, + clippy::redundant_else, + clippy::single_match_else, + // code is acceptable + clippy::blocks_in_if_conditions, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::derive_partial_eq_without_eq, + clippy::doc_markdown, + clippy::items_after_statements, + clippy::return_self_not_must_use, + // 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_vec, to_writer, Serializer}; +pub use crate::value::{from_value, to_value, Index, Number, Sequence, Value}; + +#[doc(inline)] +pub use crate::mapping::Mapping; + +/// Entry points for deserializing with pre-existing state. +/// +/// These functions are only exposed this way because we don't yet expose a +/// Deserializer type. Data formats that have a public Deserializer should not +/// copy these signatures. +pub mod seed { + pub use super::de::{from_reader_seed, from_slice_seed, from_str_seed}; +} + +mod de; +mod error; +pub mod mapping; +mod number; +mod path; +mod ser; +mod value; diff --git a/third_party/rust/serde_yaml/src/mapping.rs b/third_party/rust/serde_yaml/src/mapping.rs new file mode 100644 index 0000000000..89f6e413a0 --- /dev/null +++ b/third_party/rust/serde_yaml/src/mapping.rs @@ -0,0 +1,512 @@ +//! A YAML mapping and its iterator types. + +use crate::Value; +use indexmap::IndexMap; +use serde::{Deserialize, Deserializer, Serialize}; +use std::cmp::Ordering; +use std::collections::hash_map::DefaultHasher; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::iter::FromIterator; +use std::ops::{Index, IndexMut}; + +/// A YAML mapping in which the keys and values are both `serde_yaml::Value`. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct Mapping { + map: IndexMap<Value, Value>, +} + +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<Value> { + self.map.insert(k, v) + } + + /// Checks if the map contains the given key. + #[inline] + pub fn contains_key(&self, k: &Value) -> bool { + self.map.contains_key(k) + } + + /// Returns the value corresponding to the key in the map. + #[inline] + pub fn get(&self, k: &Value) -> Option<&Value> { + self.map.get(k) + } + + /// Returns the mutable reference corresponding to the key in the map. + #[inline] + pub fn get_mut(&mut self, k: &Value) -> Option<&mut Value> { + self.map.get_mut(k) + } + + /// 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. + #[inline] + pub fn remove(&mut self, k: &Value) -> Option<Value> { + self.map.remove(k) + } + + /// 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(), + } + } +} + +#[allow(clippy::derive_hash_xor_eq)] +impl Hash for Mapping { + fn hash<H: Hasher>(&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<Ordering> { + 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)) + }) + } + } + } + + fn iter_cmp_by<I, F>(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<'a> Index<&'a Value> for Mapping { + type Output = Value; + #[inline] + fn index(&self, index: &'a Value) -> &Value { + self.map.index(index) + } +} + +impl<'a> IndexMut<&'a Value> for Mapping { + #[inline] + fn index_mut(&mut self, index: &'a Value) -> &mut Value { + self.map.index_mut(index) + } +} + +impl Extend<(Value, Value)> for Mapping { + #[inline] + fn extend<I: IntoIterator<Item = (Value, Value)>>(&mut self, iter: I) { + self.map.extend(iter); + } +} + +impl FromIterator<(Value, Value)> for Mapping { + #[inline] + fn from_iter<I: IntoIterator<Item = (Value, Value)>>(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::Item> { + self.iter.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + 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<Value, Value>, +} + +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(), + } + } +} + +/// 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<F>(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<F>(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() + } +} + +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() + } + + /// 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<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + 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<D>(deserializer: D) -> Result<Self, D::Error> + 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<E>(self) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + Ok(Mapping::new()) + } + + #[inline] + fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> + where + V: serde::de::MapAccess<'de>, + { + let mut values = Mapping::new(); + while let Some((k, v)) = visitor.next_entry()? { + values.insert(k, v); + } + Ok(values) + } + } + + deserializer.deserialize_map(Visitor) + } +} diff --git a/third_party/rust/serde_yaml/src/number.rs b/third_party/rust/serde_yaml/src/number.rs new file mode 100644 index 0000000000..b3643ba8b1 --- /dev/null +++ b/third_party/rust/serde_yaml/src/number.rs @@ -0,0 +1,550 @@ +use crate::Error; +use serde::de::{Unexpected, Visitor}; +use serde::{forward_to_deserialize_any, Deserialize, Deserializer, Serialize, Serializer}; +use std::cmp::Ordering; +use std::fmt::{self, Debug, Display}; +use std::hash::{Hash, Hasher}; +use std::i64; + +/// 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, Debug)] +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. + /// + /// ``` + /// # use std::i64; + /// # + /// # fn yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let big = i64::MAX as u64 + 10; + /// let v = yaml(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()); + /// ``` + #[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 yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let v = yaml(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()); + /// ``` + #[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 yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let v = yaml(r#" + /// --- + /// a: 256.0 + /// b: 64 + /// c: -64 + /// "#); + /// + /// assert!(v["a"].is_f64()); + /// + /// // Integers. + /// assert!(!v["b"].is_f64()); + /// assert!(!v["c"].is_f64()); + /// ``` + #[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. + /// + /// ``` + /// # use std::i64; + /// # + /// # fn yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let big = i64::MAX as u64 + 10; + /// let v = yaml(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); + /// ``` + #[inline] + pub fn as_i64(&self) -> Option<i64> { + 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 yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let v = yaml(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); + /// ``` + #[inline] + pub fn as_u64(&self) -> Option<u64> { + match self.n { + N::PosInt(n) => Some(n), + N::NegInt(_) | N::Float(_) => None, + } + } + + /// Represents the number as f64 if possible. Returns None otherwise. + /// + /// ``` + /// # + /// # fn yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// let v = yaml(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)); + /// ``` + /// + /// ``` + /// # use std::f64; + /// # fn yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// assert_eq!(yaml(".inf").as_f64(), Some(f64::INFINITY)); + /// assert_eq!(yaml("-.inf").as_f64(), Some(f64::NEG_INFINITY)); + /// assert!(yaml(".nan").as_f64().unwrap().is_nan()); + /// ``` + #[inline] + pub fn as_f64(&self) -> Option<f64> { + 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 std::f64; + /// # + /// # 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 std::f64; + /// # + /// # 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 std::f64; + /// # + /// # 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 fmt::Display for Number { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.n { + N::PosInt(i) => Display::fmt(&i, formatter), + N::NegInt(i) => Display::fmt(&i, formatter), + 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) => Display::fmt(&f, formatter), + } + } +} + +impl Debug for Number { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.n, formatter) + } +} + +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<Ordering> { + 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<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + 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), + } + } +} + +impl<'de> Deserialize<'de> for Number { + #[inline] + fn deserialize<D>(deserializer: D) -> Result<Number, D::Error> + where + D: Deserializer<'de>, + { + 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<E>(self, value: i64) -> Result<Number, E> { + Ok(value.into()) + } + + #[inline] + fn visit_u64<E>(self, value: u64) -> Result<Number, E> { + Ok(value.into()) + } + + #[inline] + fn visit_f64<E>(self, value: f64) -> Result<Number, E> { + Ok(value.into()) + } + } + + deserializer.deserialize_any(NumberVisitor) + } +} + +impl<'de> Deserializer<'de> for Number { + type Error = Error; + + #[inline] + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error> + 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<V>(self, visitor: V) -> Result<V::Value, Error> + 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) } + } + } + )* + }; +} + +macro_rules! from_float { + ($($float_ty:ident)*) => { + $( + impl From<$float_ty> for Number { + #[inline] + fn from(f: $float_ty) -> Self { + Number { n: N::Float(f as f64) } + } + } + )* + } +} + +from_signed!(i8 i16 i32 i64 isize); +from_unsigned!(u8 u16 u32 u64 usize); +from_float!(f32 f64); + +// This is fine, because we don't _really_ implement hash for floats +// all other hash functions should work as expected +#[allow(clippy::derive_hash_xor_eq)] +impl Hash for Number { + fn hash<H: Hasher>(&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/third_party/rust/serde_yaml/src/path.rs b/third_party/rust/serde_yaml/src/path.rs new file mode 100644 index 0000000000..095add017b --- /dev/null +++ b/third_party/rust/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/third_party/rust/serde_yaml/src/ser.rs b/third_party/rust/serde_yaml/src/ser.rs new file mode 100644 index 0000000000..6ce5995dff --- /dev/null +++ b/third_party/rust/serde_yaml/src/ser.rs @@ -0,0 +1,887 @@ +//! YAML Serialization +//! +//! This module provides YAML serialization with the type `Serializer`. + +use crate::{error, Error, Result}; +use serde::ser; +use std::{fmt, io, num, str}; +use yaml_rust::{yaml, Yaml, YamlEmitter}; + +/// 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"---\nk: 107\n...\n---\nJ: 74\nk: 107\n"); +/// Ok(()) +/// } +/// ``` +pub struct Serializer<W> { + documents: usize, + writer: W, +} + +impl<W> Serializer<W> +where + W: io::Write, +{ + /// Creates a new YAML serializer. + pub fn new(writer: W) -> Self { + Serializer { + documents: 0, + writer, + } + } + + /// Calls [`.flush()`](io::Write::flush) on the underlying `io::Write` + /// object. + pub fn flush(&mut self) -> io::Result<()> { + self.writer.flush() + } + + /// Unwrap the underlying `io::Write` object from the `Serializer`. + pub fn into_inner(self) -> W { + self.writer + } + + fn write(&mut self, doc: Yaml) -> Result<()> { + if self.documents > 0 { + self.writer.write_all(b"...\n").map_err(error::io)?; + } + self.documents += 1; + let mut writer_adapter = FmtToIoWriter { + writer: &mut self.writer, + }; + YamlEmitter::new(&mut writer_adapter) + .dump(&doc) + .map_err(error::emitter)?; + writer_adapter.writer.write_all(b"\n").map_err(error::io)?; + Ok(()) + } +} + +impl<'a, W> ser::Serializer for &'a mut Serializer<W> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + type SerializeSeq = ThenWrite<'a, W, SerializeArray>; + type SerializeTuple = ThenWrite<'a, W, SerializeArray>; + type SerializeTupleStruct = ThenWrite<'a, W, SerializeArray>; + type SerializeTupleVariant = ThenWrite<'a, W, SerializeTupleVariant>; + type SerializeMap = ThenWrite<'a, W, SerializeMap>; + type SerializeStruct = ThenWrite<'a, W, SerializeStruct>; + type SerializeStructVariant = ThenWrite<'a, W, SerializeStructVariant>; + + fn serialize_bool(self, v: bool) -> Result<()> { + let doc = SerializerToYaml.serialize_bool(v)?; + self.write(doc) + } + + fn serialize_i8(self, v: i8) -> Result<()> { + let doc = SerializerToYaml.serialize_i8(v)?; + self.write(doc) + } + + fn serialize_i16(self, v: i16) -> Result<()> { + let doc = SerializerToYaml.serialize_i16(v)?; + self.write(doc) + } + + fn serialize_i32(self, v: i32) -> Result<()> { + let doc = SerializerToYaml.serialize_i32(v)?; + self.write(doc) + } + + fn serialize_i64(self, v: i64) -> Result<()> { + let doc = SerializerToYaml.serialize_i64(v)?; + self.write(doc) + } + + fn serialize_i128(self, v: i128) -> Result<()> { + let doc = SerializerToYaml.serialize_i128(v)?; + self.write(doc) + } + + fn serialize_u8(self, v: u8) -> Result<()> { + let doc = SerializerToYaml.serialize_u8(v)?; + self.write(doc) + } + + fn serialize_u16(self, v: u16) -> Result<()> { + let doc = SerializerToYaml.serialize_u16(v)?; + self.write(doc) + } + + fn serialize_u32(self, v: u32) -> Result<()> { + let doc = SerializerToYaml.serialize_u32(v)?; + self.write(doc) + } + + fn serialize_u64(self, v: u64) -> Result<()> { + let doc = SerializerToYaml.serialize_u64(v)?; + self.write(doc) + } + + fn serialize_u128(self, v: u128) -> Result<()> { + let doc = SerializerToYaml.serialize_u128(v)?; + self.write(doc) + } + + fn serialize_f32(self, v: f32) -> Result<()> { + let doc = SerializerToYaml.serialize_f32(v)?; + self.write(doc) + } + + fn serialize_f64(self, v: f64) -> Result<()> { + let doc = SerializerToYaml.serialize_f64(v)?; + self.write(doc) + } + + fn serialize_char(self, value: char) -> Result<()> { + let doc = SerializerToYaml.serialize_char(value)?; + self.write(doc) + } + + fn serialize_str(self, value: &str) -> Result<()> { + let doc = SerializerToYaml.serialize_str(value)?; + self.write(doc) + } + + fn serialize_bytes(self, value: &[u8]) -> Result<()> { + let doc = SerializerToYaml.serialize_bytes(value)?; + self.write(doc) + } + + fn serialize_unit(self) -> Result<()> { + let doc = SerializerToYaml.serialize_unit()?; + self.write(doc) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<()> { + let doc = SerializerToYaml.serialize_unit_struct(name)?; + self.write(doc) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<()> { + let doc = SerializerToYaml.serialize_unit_variant(name, variant_index, variant)?; + self.write(doc) + } + + fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + let doc = SerializerToYaml.serialize_newtype_struct(name, value)?; + self.write(doc) + } + + fn serialize_newtype_variant<T>( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + let doc = + SerializerToYaml.serialize_newtype_variant(name, variant_index, variant, value)?; + self.write(doc) + } + + fn serialize_none(self) -> Result<()> { + let doc = SerializerToYaml.serialize_none()?; + self.write(doc) + } + + fn serialize_some<V>(self, value: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + let doc = SerializerToYaml.serialize_some(value)?; + self.write(doc) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> { + let delegate = SerializerToYaml.serialize_seq(len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> { + let delegate = SerializerToYaml.serialize_tuple(len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct> { + let delegate = SerializerToYaml.serialize_tuple_struct(name, len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_tuple_variant( + self, + enm: &'static str, + idx: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant> { + let delegate = SerializerToYaml.serialize_tuple_variant(enm, idx, variant, len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> { + let delegate = SerializerToYaml.serialize_map(len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> { + let delegate = SerializerToYaml.serialize_struct(name, len)?; + Ok(ThenWrite::new(self, delegate)) + } + + fn serialize_struct_variant( + self, + enm: &'static str, + idx: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeStructVariant> { + let delegate = SerializerToYaml.serialize_struct_variant(enm, idx, variant, len)?; + Ok(ThenWrite::new(self, delegate)) + } +} + +pub struct ThenWrite<'a, W, D> { + serializer: &'a mut Serializer<W>, + delegate: D, +} + +impl<'a, W, D> ThenWrite<'a, W, D> { + fn new(serializer: &'a mut Serializer<W>, delegate: D) -> Self { + ThenWrite { + serializer, + delegate, + } + } +} + +impl<'a, W> ser::SerializeSeq for ThenWrite<'a, W, SerializeArray> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_element<T>(&mut self, elem: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + self.delegate.serialize_element(elem) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeTuple for ThenWrite<'a, W, SerializeArray> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_element<T>(&mut self, elem: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + self.delegate.serialize_element(elem) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeTupleStruct for ThenWrite<'a, W, SerializeArray> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_field<V>(&mut self, value: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + self.delegate.serialize_field(value) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeTupleVariant for ThenWrite<'a, W, SerializeTupleVariant> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_field<V>(&mut self, v: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + self.delegate.serialize_field(v) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeMap for ThenWrite<'a, W, SerializeMap> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_key<T>(&mut self, key: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + self.delegate.serialize_key(key) + } + + fn serialize_value<T>(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + self.delegate.serialize_value(value) + } + + fn serialize_entry<K, V>(&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<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeStruct for ThenWrite<'a, W, SerializeStruct> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_field<V>(&mut self, key: &'static str, value: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + self.delegate.serialize_field(key, value) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +impl<'a, W> ser::SerializeStructVariant for ThenWrite<'a, W, SerializeStructVariant> +where + W: io::Write, +{ + type Ok = (); + type Error = Error; + + fn serialize_field<V>(&mut self, field: &'static str, v: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + self.delegate.serialize_field(field, v) + } + + fn end(self) -> Result<()> { + let doc = self.delegate.end()?; + self.serializer.write(doc) + } +} + +pub struct SerializerToYaml; + +impl ser::Serializer for SerializerToYaml { + type Ok = Yaml; + 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<Yaml> { + Ok(Yaml::Boolean(v)) + } + + fn serialize_i8(self, v: i8) -> Result<Yaml> { + self.serialize_i64(v as i64) + } + + fn serialize_i16(self, v: i16) -> Result<Yaml> { + self.serialize_i64(v as i64) + } + + fn serialize_i32(self, v: i32) -> Result<Yaml> { + self.serialize_i64(v as i64) + } + + fn serialize_i64(self, v: i64) -> Result<Yaml> { + Ok(Yaml::Integer(v)) + } + + #[allow(clippy::cast_possible_truncation)] + fn serialize_i128(self, v: i128) -> Result<Yaml> { + if v <= i64::max_value() as i128 && v >= i64::min_value() as i128 { + self.serialize_i64(v as i64) + } else { + Ok(Yaml::Real(v.to_string())) + } + } + + fn serialize_u8(self, v: u8) -> Result<Yaml> { + self.serialize_i64(v as i64) + } + + fn serialize_u16(self, v: u16) -> Result<Yaml> { + self.serialize_i64(v as i64) + } + + fn serialize_u32(self, v: u32) -> Result<Yaml> { + self.serialize_i64(v as i64) + } + + fn serialize_u64(self, v: u64) -> Result<Yaml> { + if v <= i64::max_value() as u64 { + self.serialize_i64(v as i64) + } else { + Ok(Yaml::Real(v.to_string())) + } + } + + #[allow(clippy::cast_possible_truncation)] + fn serialize_u128(self, v: u128) -> Result<Yaml> { + if v <= i64::max_value() as u128 { + self.serialize_i64(v as i64) + } else { + Ok(Yaml::Real(v.to_string())) + } + } + + fn serialize_f32(self, v: f32) -> Result<Yaml> { + Ok(Yaml::Real(match v.classify() { + num::FpCategory::Infinite if v.is_sign_positive() => ".inf".into(), + num::FpCategory::Infinite => "-.inf".into(), + num::FpCategory::Nan => ".nan".into(), + _ => ryu::Buffer::new().format_finite(v).into(), + })) + } + + fn serialize_f64(self, v: f64) -> Result<Yaml> { + Ok(Yaml::Real(match v.classify() { + num::FpCategory::Infinite if v.is_sign_positive() => ".inf".into(), + num::FpCategory::Infinite => "-.inf".into(), + num::FpCategory::Nan => ".nan".into(), + _ => ryu::Buffer::new().format_finite(v).into(), + })) + } + + fn serialize_char(self, value: char) -> Result<Yaml> { + Ok(Yaml::String(value.to_string())) + } + + fn serialize_str(self, value: &str) -> Result<Yaml> { + Ok(Yaml::String(value.to_owned())) + } + + fn serialize_bytes(self, value: &[u8]) -> Result<Yaml> { + let vec = value.iter().map(|&b| Yaml::Integer(b as i64)).collect(); + Ok(Yaml::Array(vec)) + } + + fn serialize_unit(self) -> Result<Yaml> { + Ok(Yaml::Null) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<Yaml> { + self.serialize_unit() + } + + fn serialize_unit_variant( + self, + _name: &str, + _variant_index: u32, + variant: &str, + ) -> Result<Yaml> { + Ok(Yaml::String(variant.to_owned())) + } + + fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<Yaml> + where + T: ?Sized + ser::Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant<T>( + self, + _name: &str, + _variant_index: u32, + variant: &str, + value: &T, + ) -> Result<Yaml> + where + T: ?Sized + ser::Serialize, + { + Ok(singleton_hash(to_yaml(variant)?, to_yaml(value)?)) + } + + fn serialize_none(self) -> Result<Yaml> { + self.serialize_unit() + } + + fn serialize_some<V>(self, value: &V) -> Result<Yaml> + where + V: ?Sized + ser::Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<SerializeArray> { + let array = match len { + None => yaml::Array::new(), + Some(len) => yaml::Array::with_capacity(len), + }; + Ok(SerializeArray { array }) + } + + fn serialize_tuple(self, len: usize) -> Result<SerializeArray> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct(self, _name: &'static str, len: usize) -> Result<SerializeArray> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _enum: &'static str, + _idx: u32, + variant: &'static str, + len: usize, + ) -> Result<SerializeTupleVariant> { + Ok(SerializeTupleVariant { + name: variant, + array: yaml::Array::with_capacity(len), + }) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<SerializeMap> { + Ok(SerializeMap { + hash: yaml::Hash::new(), + next_key: None, + }) + } + + fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<SerializeStruct> { + Ok(SerializeStruct { + hash: yaml::Hash::new(), + }) + } + + fn serialize_struct_variant( + self, + _enum: &'static str, + _idx: u32, + variant: &'static str, + _len: usize, + ) -> Result<SerializeStructVariant> { + Ok(SerializeStructVariant { + name: variant, + hash: yaml::Hash::new(), + }) + } +} + +#[doc(hidden)] +pub struct SerializeArray { + array: yaml::Array, +} + +#[doc(hidden)] +pub struct SerializeTupleVariant { + name: &'static str, + array: yaml::Array, +} + +#[doc(hidden)] +pub struct SerializeMap { + hash: yaml::Hash, + next_key: Option<yaml::Yaml>, +} + +#[doc(hidden)] +pub struct SerializeStruct { + hash: yaml::Hash, +} + +#[doc(hidden)] +pub struct SerializeStructVariant { + name: &'static str, + hash: yaml::Hash, +} + +impl ser::SerializeSeq for SerializeArray { + type Ok = yaml::Yaml; + type Error = Error; + + fn serialize_element<T>(&mut self, elem: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + self.array.push(to_yaml(elem)?); + Ok(()) + } + + fn end(self) -> Result<Yaml> { + Ok(Yaml::Array(self.array)) + } +} + +impl ser::SerializeTuple for SerializeArray { + type Ok = yaml::Yaml; + type Error = Error; + + fn serialize_element<T>(&mut self, elem: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, elem) + } + + fn end(self) -> Result<Yaml> { + ser::SerializeSeq::end(self) + } +} + +impl ser::SerializeTupleStruct for SerializeArray { + type Ok = yaml::Yaml; + type Error = Error; + + fn serialize_field<V>(&mut self, value: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<Yaml> { + ser::SerializeSeq::end(self) + } +} + +impl ser::SerializeTupleVariant for SerializeTupleVariant { + type Ok = yaml::Yaml; + type Error = Error; + + fn serialize_field<V>(&mut self, v: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + self.array.push(to_yaml(v)?); + Ok(()) + } + + fn end(self) -> Result<Yaml> { + Ok(singleton_hash(to_yaml(self.name)?, Yaml::Array(self.array))) + } +} + +impl ser::SerializeMap for SerializeMap { + type Ok = yaml::Yaml; + type Error = Error; + + fn serialize_key<T>(&mut self, key: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + self.next_key = Some(to_yaml(key)?); + Ok(()) + } + + fn serialize_value<T>(&mut self, value: &T) -> Result<()> + where + T: ?Sized + ser::Serialize, + { + match self.next_key.take() { + Some(key) => self.hash.insert(key, to_yaml(value)?), + None => panic!("serialize_value called before serialize_key"), + }; + Ok(()) + } + + fn serialize_entry<K, V>(&mut self, key: &K, value: &V) -> Result<()> + where + K: ?Sized + ser::Serialize, + V: ?Sized + ser::Serialize, + { + self.hash.insert(to_yaml(key)?, to_yaml(value)?); + Ok(()) + } + + fn end(self) -> Result<Yaml> { + Ok(Yaml::Hash(self.hash)) + } +} + +impl ser::SerializeStruct for SerializeStruct { + type Ok = yaml::Yaml; + type Error = Error; + + fn serialize_field<V>(&mut self, key: &'static str, value: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + self.hash.insert(to_yaml(key)?, to_yaml(value)?); + Ok(()) + } + + fn end(self) -> Result<Yaml> { + Ok(Yaml::Hash(self.hash)) + } +} + +impl ser::SerializeStructVariant for SerializeStructVariant { + type Ok = yaml::Yaml; + type Error = Error; + + fn serialize_field<V>(&mut self, field: &'static str, v: &V) -> Result<()> + where + V: ?Sized + ser::Serialize, + { + self.hash.insert(to_yaml(field)?, to_yaml(v)?); + Ok(()) + } + + fn end(self) -> Result<Yaml> { + Ok(singleton_hash(to_yaml(self.name)?, Yaml::Hash(self.hash))) + } +} + +/// 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<W, T>(writer: W, value: &T) -> Result<()> +where + W: io::Write, + T: ?Sized + ser::Serialize, +{ + value.serialize(&mut Serializer::new(writer)) +} + +/// Serialize the given data structure as a YAML byte vector. +/// +/// Serialization can fail if `T`'s implementation of `Serialize` decides to +/// return an error. +pub fn to_vec<T>(value: &T) -> Result<Vec<u8>> +where + T: ?Sized + ser::Serialize, +{ + let mut vec = Vec::with_capacity(128); + to_writer(&mut vec, value)?; + Ok(vec) +} + +/// 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<T>(value: &T) -> Result<String> +where + T: ?Sized + ser::Serialize, +{ + String::from_utf8(to_vec(value)?).map_err(error::string_utf8) +} + +/// The yaml-rust library uses `fmt::Write` intead of `io::Write` so this is a +/// simple adapter. +struct FmtToIoWriter<W> { + writer: W, +} + +impl<W> fmt::Write for FmtToIoWriter<W> +where + W: io::Write, +{ + fn write_str(&mut self, s: &str) -> fmt::Result { + if self.writer.write_all(s.as_bytes()).is_err() { + return Err(fmt::Error); + } + Ok(()) + } +} + +fn to_yaml<T>(elem: T) -> Result<Yaml> +where + T: ser::Serialize, +{ + elem.serialize(SerializerToYaml) +} + +fn singleton_hash(k: Yaml, v: Yaml) -> Yaml { + let mut hash = yaml::Hash::new(); + hash.insert(k, v); + Yaml::Hash(hash) +} diff --git a/third_party/rust/serde_yaml/src/value/de.rs b/third_party/rust/serde_yaml/src/value/de.rs new file mode 100644 index 0000000000..61e0469693 --- /dev/null +++ b/third_party/rust/serde_yaml/src/value/de.rs @@ -0,0 +1,707 @@ +use crate::{number, Error, Mapping, Sequence, Value}; +use serde::de::{ + self, Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error as SError, Expected, + MapAccess, SeqAccess, Unexpected, VariantAccess, Visitor, +}; +use serde::forward_to_deserialize_any; +use std::fmt; +use std::vec; + +impl<'de> Deserialize<'de> for Value { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + 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<E>(self, b: bool) -> Result<Value, E> + where + E: SError, + { + Ok(Value::Bool(b)) + } + + fn visit_i64<E>(self, i: i64) -> Result<Value, E> + where + E: SError, + { + Ok(Value::Number(i.into())) + } + + fn visit_u64<E>(self, u: u64) -> Result<Value, E> + where + E: SError, + { + Ok(Value::Number(u.into())) + } + + fn visit_f64<E>(self, f: f64) -> Result<Value, E> + where + E: SError, + { + Ok(Value::Number(f.into())) + } + + fn visit_str<E>(self, s: &str) -> Result<Value, E> + where + E: SError, + { + Ok(Value::String(s.to_owned())) + } + + fn visit_string<E>(self, s: String) -> Result<Value, E> + where + E: SError, + { + Ok(Value::String(s)) + } + + fn visit_unit<E>(self) -> Result<Value, E> + where + E: SError, + { + Ok(Value::Null) + } + + fn visit_none<E>(self) -> Result<Value, E> + where + E: SError, + { + Ok(Value::Null) + } + + fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error> + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer) + } + + fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error> + where + V: SeqAccess<'de>, + { + let mut vec = Vec::new(); + + while let Some(element) = visitor.next_element()? { + vec.push(element); + } + + Ok(Value::Sequence(vec)) + } + + fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error> + where + V: MapAccess<'de>, + { + let mut values = Mapping::new(); + + while let Some((key, value)) = visitor.next_entry()? { + values.insert(key, value); + } + + Ok(Value::Mapping(values)) + } + } + + deserializer.deserialize_any(ValueVisitor) + } +} + +impl Value { + fn deserialize_number<'de, V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::Number(n) => n.deserialize_any(visitor), + _ => Err(self.invalid_type(&visitor)), + } + } +} + +fn visit_sequence<'de, V>(sequence: Sequence, visitor: V) -> Result<V::Value, Error> +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_mapping<'de, V>(mapping: Mapping, visitor: V) -> Result<V::Value, Error> +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")) + } +} + +impl<'de> Deserializer<'de> for Value { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error> + 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), + } + } + + fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::Bool(v) => visitor.visit_bool(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_number(visitor) + } + + fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::String(v) => visitor.visit_string(v), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_byte_buf(visitor) + } + + fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::String(v) => visitor.visit_string(v), + Value::Sequence(v) => visit_sequence(v, visitor), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::Null => visitor.visit_none(), + _ => visitor.visit_some(self), + } + } + + fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::Null => visitor.visit_unit(), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_newtype_struct<V>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::Sequence(v) => visit_sequence(v, visitor), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct<V>( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::Mapping(v) => visit_mapping(v, visitor), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_struct<V>( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self { + Value::Sequence(v) => visit_sequence(v, visitor), + Value::Mapping(v) => visit_mapping(v, visitor), + _ => Err(self.invalid_type(&visitor)), + } + } + + fn deserialize_enum<V>( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + let (variant, value) = match self { + Value::Mapping(value) => { + let mut iter = value.into_iter(); + let (variant, value) = match iter.next() { + Some(v) => v, + None => { + return Err(Error::invalid_value( + Unexpected::Map, + &"map with a single key", + )); + } + }; + // enums are encoded in json as maps with a single key:value pair + if iter.next().is_some() { + return Err(Error::invalid_value( + Unexpected::Map, + &"map with a single key", + )); + } + (variant, Some(value)) + } + Value::String(variant) => (Value::String(variant), None), + other => { + return Err(Error::invalid_type(other.unexpected(), &"string or map")); + } + }; + + visitor.visit_enum(EnumDeserializer { variant, value }) + } + + fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + drop(self); + visitor.visit_unit() + } +} + +struct EnumDeserializer { + variant: Value, + value: Option<Value>, +} + +impl<'de> EnumAccess<'de> for EnumDeserializer { + type Error = Error; + type Variant = VariantDeserializer; + + fn variant_seed<V>(self, seed: V) -> Result<(V::Value, VariantDeserializer), Error> + where + V: DeserializeSeed<'de>, + { + let visitor = VariantDeserializer { value: self.value }; + seed.deserialize(self.variant).map(|v| (v, visitor)) + } +} + +struct VariantDeserializer { + value: Option<Value>, +} + +impl<'de> VariantAccess<'de> for VariantDeserializer { + type Error = Error; + + fn unit_variant(self) -> Result<(), Error> { + match self.value { + Some(value) => Deserialize::deserialize(value), + None => Ok(()), + } + } + + fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Error> + where + T: DeserializeSeed<'de>, + { + match self.value { + Some(value) => seed.deserialize(value), + None => Err(Error::invalid_type( + Unexpected::UnitVariant, + &"newtype variant", + )), + } + } + + fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self.value { + Some(Value::Sequence(v)) => { + Deserializer::deserialize_any(SeqDeserializer::new(v), visitor) + } + Some(other) => Err(Error::invalid_type(other.unexpected(), &"tuple variant")), + None => Err(Error::invalid_type( + Unexpected::UnitVariant, + &"tuple variant", + )), + } + } + + fn struct_variant<V>( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + match self.value { + Some(Value::Mapping(v)) => { + Deserializer::deserialize_any(MapDeserializer::new(v), visitor) + } + Some(other) => Err(Error::invalid_type(other.unexpected(), &"struct variant")), + None => Err(Error::invalid_type( + Unexpected::UnitVariant, + &"struct variant", + )), + } + } +} + +struct SeqDeserializer { + iter: vec::IntoIter<Value>, +} + +impl SeqDeserializer { + fn new(vec: Vec<Value>) -> Self { + SeqDeserializer { + iter: vec.into_iter(), + } + } +} + +impl<'de> Deserializer<'de> for SeqDeserializer { + type Error = Error; + + #[inline] + fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Error> + 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<V>(self, visitor: V) -> Result<V::Value, Error> + 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<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error> + where + T: DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => seed.deserialize(value).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> Option<usize> { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +struct MapDeserializer { + iter: <Mapping as IntoIterator>::IntoIter, + value: Option<Value>, +} + +impl MapDeserializer { + 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<T>(&mut self, seed: T) -> Result<Option<T::Value>, 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<T>(&mut self, seed: T) -> Result<T::Value, Error> + 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<usize> { + 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<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: Visitor<'de>, + { + visitor.visit_map(self) + } + + fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Error> + 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 Value { + #[cold] + fn invalid_type<E>(&self, exp: &dyn Expected) -> E + where + E: de::Error, + { + de::Error::invalid_type(self.unexpected(), exp) + } + + #[cold] + 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, + } + } +} diff --git a/third_party/rust/serde_yaml/src/value/from.rs b/third_party/rust/serde_yaml/src/value/from.rs new file mode 100644 index 0000000000..c02855d3b1 --- /dev/null +++ b/third_party/rust/serde_yaml/src/value/from.rs @@ -0,0 +1,180 @@ +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<bool> 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<String> 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<Cow<'a, str>> for Value { + /// Convert copy-on-write string to `Value` + /// + /// # Examples + /// + /// ``` + /// use serde_yaml::Value; + /// use std::borrow::Cow; + /// + /// let s: Cow<str> = Cow::Borrowed("lorem"); + /// let x: Value = s.into(); + /// ``` + /// + /// ``` + /// use serde_yaml::Value; + /// use std::borrow::Cow; + /// + /// let s: Cow<str> = Cow::Owned("lorem".to_string()); + /// let x: Value = s.into(); + /// ``` + fn from(f: Cow<'a, str>) -> Self { + Value::String(f.to_string()) + } +} + +impl From<Mapping> 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<T: Into<Value>> From<Vec<T>> 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<T>) -> Self { + Value::Sequence(f.into_iter().map(Into::into).collect()) + } +} + +impl<'a, T: Clone + Into<Value>> 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()) + } +} + +use std::iter::FromIterator; + +impl<T: Into<Value>> FromIterator<T> 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<I: IntoIterator<Item = T>>(iter: I) -> Self { + let vec = iter.into_iter().map(T::into).collect(); + + Value::Sequence(vec) + } +} diff --git a/third_party/rust/serde_yaml/src/value/index.rs b/third_party/rust/serde_yaml/src/value/index.rs new file mode 100644 index 0000000000..b5f5e90160 --- /dev/null +++ b/third_party/rust/serde_yaml/src/value/index.rs @@ -0,0 +1,260 @@ +use crate::{Mapping, Value}; +use std::fmt; +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 { + 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 { + Value::Sequence(vec) => vec.get_mut(*self), + Value::Mapping(vec) => vec.get_mut(&Value::Number((*self).into())), + _ => None, + } + } + fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { + match v { + Value::Sequence(vec) => { + let len = vec.len(); + 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()); + // TODO: use entry() once LinkedHashMap supports entry() + // https://github.com/contain-rs/linked-hash-map/issues/5 + if !map.contains_key(&n) { + map.insert(n.clone(), Value::Null); + } + map.get_mut(&n).unwrap() + } + _ => panic!("cannot access index {} of YAML {}", self, Type(v)), + } + } +} + +impl Index for Value { + fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { + match v { + Value::Mapping(map) => map.get(self), + _ => None, + } + } + fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { + match v { + Value::Mapping(map) => map.get_mut(self), + _ => None, + } + } + fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { + if let Value::Null = *v { + let mut map = Mapping::new(); + map.insert(self.clone(), Value::Null); + *v = Value::Mapping(map); + } + match v { + Value::Mapping(map) => { + // TODO: use entry() once LinkedHashMap supports entry() + // https://github.com/contain-rs/linked-hash-map/issues/5 + if !map.contains_key(self) { + map.insert(self.clone(), Value::Null); + } + map.get_mut(self).unwrap() + } + _ => panic!("cannot access key {:?} in YAML {}", self, Type(v)), + } + } +} + +impl Index for str { + fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { + Value::String(self.into()).index_into(v) + } + fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { + Value::String(self.into()).index_into_mut(v) + } + fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { + Value::String(self.into()).index_or_insert(v) + } +} + +impl Index for String { + fn index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> { + Value::String(self.clone()).index_into(v) + } + fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> { + Value::String(self.clone()).index_into_mut(v) + } + fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value { + Value::String(self.clone()).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) + } +} + +// Prevent users 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 super::Value {} + impl<'a, T> Sealed for &'a T where T: ?Sized + Sealed {} +} + +/// 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"), + } + } +} + +// 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<I> ops::Index<I> 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 + /// + /// ``` + /// # fn yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let data = yaml(r#"{ x: { y: [z, zz] } }"#); + /// + /// assert_eq!(data["x"]["y"], yaml(r#"["z", "zz"]"#)); + /// assert_eq!(data["x"]["y"][0], yaml(r#""z""#)); + /// + /// assert_eq!(data["a"], yaml(r#"null"#)); // returns null for undefined values + /// assert_eq!(data["a"]["b"], yaml(r#"null"#)); // does not panic + /// ``` + fn index(&self, index: I) -> &Value { + static NULL: Value = Value::Null; + index.index_into(self).unwrap_or(&NULL) + } +} + +impl<I> ops::IndexMut<I> 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 yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let mut data = yaml(r#"{x: 0}"#); + /// + /// // replace an existing key + /// data["x"] = yaml(r#"1"#); + /// + /// // insert a new key + /// data["y"] = yaml(r#"[false, false, false]"#); + /// + /// // replace a value in a sequence + /// data["y"][0] = yaml(r#"true"#); + /// + /// // inserted a deeply nested key + /// data["a"]["b"]["c"]["d"] = yaml(r#"true"#); + /// + /// println!("{:?}", data); + /// ``` + fn index_mut(&mut self, index: I) -> &mut Value { + index.index_or_insert(self) + } +} diff --git a/third_party/rust/serde_yaml/src/value/mod.rs b/third_party/rust/serde_yaml/src/value/mod.rs new file mode 100644 index 0000000000..a71091bffb --- /dev/null +++ b/third_party/rust/serde_yaml/src/value/mod.rs @@ -0,0 +1,648 @@ +mod de; +mod from; +mod index; +mod partial_eq; +mod ser; + +use crate::ser::SerializerToYaml; +use crate::{Error, Mapping}; +use serde::de::{Deserialize, DeserializeOwned, IntoDeserializer}; +use serde::Serialize; +use std::f64; +use std::hash::{Hash, Hasher}; +use std::str::FromStr; +use yaml_rust::Yaml; + +pub use self::index::Index; +pub use crate::number::Number; + +/// Represents any valid YAML value. +#[derive(Clone, PartialOrd, Debug)] +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), +} + +/// The default value is `Value::Null`. +/// +/// This is useful for handling omitted `Value` fields when deserializing. +/// +/// # Examples +/// +/// ``` +/// # use serde_derive::Deserialize; +/// use serde::Deserialize; +/// use serde_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<Value>; + +/// 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<T>(value: T) -> Result<Value, Error> +where + T: Serialize, +{ + value.serialize(SerializerToYaml).map(yaml_to_value) +} + +/// 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<T>(value: Value) -> Result<T, Error> +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. + /// + /// ``` + /// # use serde_yaml::Value; + /// # + /// # fn yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let object: Value = yaml(r#"{ A: 65, B: 66, C: 67 }"#); + /// let x = object.get("A").unwrap(); + /// assert_eq!(x, 65); + /// + /// let sequence: Value = yaml(r#"[ "A", "B", "C" ]"#); + /// let x = sequence.get(2).unwrap(); + /// assert_eq!(x, &Value::String("C".into())); + /// + /// assert_eq!(sequence.get("A"), None); + /// ``` + /// + /// 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 yaml(i: &str) -> serde_yaml::Value { serde_yaml::from_str(i).unwrap() } + /// # + /// let object = yaml(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)); + /// ``` + pub fn get<I: Index>(&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<I: Index>(&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 { + 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 { + 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<bool> { + match self { + 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 { + 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<i64> { + match self { + 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<u64> { + match self { + 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 { + 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<f64> { + match self { + 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 { + 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 { + 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 { + 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 { + 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 { + Value::Mapping(map) => Some(map), + _ => None, + } + } +} + +fn yaml_to_value(yaml: Yaml) -> Value { + match yaml { + Yaml::Real(f) => { + if f == ".inf" { + Value::Number(f64::INFINITY.into()) + } else if f == "-.inf" { + Value::Number(f64::NEG_INFINITY.into()) + } else if f == ".nan" { + Value::Number(f64::NAN.into()) + } else if let Ok(n) = u64::from_str(&f) { + Value::Number(n.into()) + } else if let Ok(n) = i64::from_str(&f) { + Value::Number(n.into()) + } else if let Ok(n) = f64::from_str(&f) { + Value::Number(n.into()) + } else { + Value::String(f) + } + } + Yaml::Integer(i) => Value::Number(i.into()), + Yaml::String(s) => Value::String(s), + Yaml::Boolean(b) => Value::Bool(b), + Yaml::Array(sequence) => Value::Sequence(sequence.into_iter().map(yaml_to_value).collect()), + Yaml::Hash(hash) => Value::Mapping( + hash.into_iter() + .map(|(k, v)| (yaml_to_value(k), yaml_to_value(v))) + .collect(), + ), + Yaml::Alias(_) => panic!("alias unsupported"), + Yaml::Null => Value::Null, + Yaml::BadValue => panic!("bad value"), + } +} + +impl Eq for Value {} + +impl Hash for Value { + fn hash<H: Hasher>(&self, state: &mut H) { + match self { + Value::Null => 0.hash(state), + Value::Bool(b) => (1, b).hash(state), + Value::Number(i) => (2, i).hash(state), + Value::String(s) => (3, s).hash(state), + Value::Sequence(seq) => (4, seq).hash(state), + Value::Mapping(map) => (5, map).hash(state), + } + } +} + +impl<'de> IntoDeserializer<'de, Error> for Value { + type Deserializer = Self; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} diff --git a/third_party/rust/serde_yaml/src/value/partial_eq.rs b/third_party/rust/serde_yaml/src/value/partial_eq.rs new file mode 100644 index 0000000000..ff9b1f8f8a --- /dev/null +++ b/third_party/rust/serde_yaml/src/value/partial_eq.rs @@ -0,0 +1,149 @@ +use crate::Value; + +impl PartialEq for Value { + fn eq(&self, other: &Value) -> bool { + match (self, other) { + (Value::Null, Value::Null) => true, + (Value::Bool(a), Value::Bool(b)) => a == b, + (Value::Number(a), Value::Number(b)) => a == b, + (Value::String(a), Value::String(b)) => a == b, + (Value::Sequence(a), Value::Sequence(b)) => a == b, + (Value::Mapping(a), Value::Mapping(b)) => a == b, + _ => false, + } + } +} + +impl PartialEq<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<'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<Value> for str { + /// Compare YAML value with `str` + /// + /// # Examples + /// + /// ``` + /// # use serde_yaml::Value; + /// assert!(*"lorem" == Value::String("lorem".into())); + /// ``` + fn eq(&self, other: &Value) -> bool { + other.as_str().map_or(false, |s| s == self) + } +} + +impl<'a> PartialEq<Value> for &'a str { + /// Compare `&str` with YAML value + /// + /// # Examples + /// + /// ``` + /// # use serde_yaml::Value; + /// assert!("lorem" == Value::String("lorem".into())); + /// ``` + fn eq(&self, other: &Value) -> bool { + other.as_str().map_or(false, |s| s == *self) + } +} + +impl PartialEq<String> 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<Value> for String { + /// Compare `String` with YAML value + /// + /// # Examples + /// + /// ``` + /// # use serde_yaml::Value; + /// assert!("lorem".to_string() == Value::String("lorem".into())); + /// ``` + fn eq(&self, other: &Value) -> bool { + other.as_str().map_or(false, |s| s == self) + } +} + +impl PartialEq<bool> 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 PartialEq<Value> for $ty { + fn eq(&self, other: &Value) -> bool { + other.$conversion().map_or(false, |i| i == (*self 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/third_party/rust/serde_yaml/src/value/ser.rs b/third_party/rust/serde_yaml/src/value/ser.rs new file mode 100644 index 0000000000..f2c4bb438c --- /dev/null +++ b/third_party/rust/serde_yaml/src/value/ser.rs @@ -0,0 +1,25 @@ +use crate::Value; +use serde::Serialize; + +impl Serialize for Value { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + 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(hash) => { + use serde::ser::SerializeMap; + let mut map = serializer.serialize_map(Some(hash.len()))?; + for (k, v) in hash { + map.serialize_entry(k, v)?; + } + map.end() + } + } + } +} diff --git a/third_party/rust/serde_yaml/tests/test_de.rs b/third_party/rust/serde_yaml/tests/test_de.rs new file mode 100644 index 0000000000..e3a8c0da12 --- /dev/null +++ b/third_party/rust/serde_yaml/tests/test_de.rs @@ -0,0 +1,396 @@ +#![allow( + clippy::cast_lossless, + clippy::cast_possible_wrap, + clippy::derive_partial_eq_without_eq +)] + +use indoc::indoc; +use serde_derive::Deserialize; +use serde_yaml::Value; +use std::collections::BTreeMap; +use std::fmt::Debug; + +fn test_de<T>(yaml: &str, expected: &T) +where + T: serde::de::DeserializeOwned + PartialEq + Debug, +{ + let deserialized: T = serde_yaml::from_str(yaml).unwrap(); + assert_eq!(*expected, deserialized); + + serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap(); + serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap(); +} + +fn test_de_seed<T, S>(yaml: &str, seed: S, expected: &T) +where + T: PartialEq + Debug, + S: for<'de> serde::de::DeserializeSeed<'de, Value = T>, +{ + let deserialized: T = serde_yaml::seed::from_str_seed(yaml, seed).unwrap(); + assert_eq!(*expected, deserialized); + + serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap(); + serde_yaml::from_str::<serde::de::IgnoredAny>(yaml).unwrap(); +} + +#[test] +fn test_alias() { + let yaml = indoc! {" + --- + first: + &alias + 1 + second: + *alias + third: 3 + "}; + let mut expected = BTreeMap::new(); + { + expected.insert(String::from("first"), 1); + expected.insert(String::from("second"), 1); + expected.insert(String::from("third"), 3); + } + test_de(yaml, &expected); +} + +#[test] +fn test_option() { + #[derive(Deserialize, PartialEq, Debug)] + struct Data { + a: Option<f64>, + b: Option<String>, + c: Option<bool>, + } + 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<f64>, + b: Option<String>, + c: Option<bool>, + d: Option<f64>, + e: Option<String>, + f: Option<bool>, + } + 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_tag() { + #[derive(Deserialize, PartialEq, Debug)] + enum E { + A(String), + B(String), + } + #[derive(Deserialize, PartialEq, Debug)] + struct Data { + a: E, + b: E, + } + let yaml = indoc! {" + --- + a: !A foo + b: !B bar + "}; + let expected = Data { + a: E::A("foo".into()), + b: E::B("bar".into()), + }; + test_de(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(yaml, &expected); +} + +#[test] +fn test_i128_big() { + let expected: i128 = ::std::i64::MIN as i128 - 1; + let yaml = indoc! {" + --- + -9223372036854775809 + "}; + assert_eq!(expected, serde_yaml::from_str::<i128>(yaml).unwrap()); +} + +#[test] +fn test_u128_big() { + let expected: u128 = ::std::u64::MAX as u128 + 1; + let yaml = indoc! {" + --- + 18446744073709551616 + "}; + assert_eq!(expected, serde_yaml::from_str::<u128>(yaml).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(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_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::<Data>(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::<Value>(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"]; + for yaml in &cases { + let value = serde_yaml::from_str::<Value>(yaml).unwrap(); + match value { + Value::String(string) => assert_eq!(string, *yaml), + _ => panic!("expected string. input={:?}, result={:?}", yaml, value), + } + } +} + +#[test] +fn test_stateful() { + struct Seed(i64); + + impl<'de> serde::de::DeserializeSeed<'de> for Seed { + type Value = i64; + fn deserialize<D>(self, deserializer: D) -> Result<i64, D::Error> + 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<E: serde::de::Error>(self, v: i64) -> Result<i64, E> { + Ok(v * self.0) + } + + fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<i64, E> { + 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); + } +} diff --git a/third_party/rust/serde_yaml/tests/test_error.rs b/third_party/rust/serde_yaml/tests/test_error.rs new file mode 100644 index 0000000000..bd830c0fc0 --- /dev/null +++ b/third_party/rust/serde_yaml/tests/test_error.rs @@ -0,0 +1,287 @@ +use indoc::indoc; +use serde_derive::Deserialize; +use std::fmt::Debug; + +fn test_error<T>(yaml: &str, expected: &str) +where + T: serde::de::DeserializeOwned + Debug, +{ + let result = serde_yaml::from_str::<T>(yaml); + assert_eq!(expected, format!("{}", result.unwrap_err())); +} + +#[test] +fn test_incorrect_type() { + let yaml = indoc! {" + --- + str + "}; + let expected = "invalid type: string \"str\", expected i16 at line 2 column 1"; + test_error::<i16>(yaml, expected); +} + +#[test] +fn test_incorrect_nested_type() { + #[derive(Deserialize, Debug)] + struct A { + #[allow(dead_code)] + b: Vec<B>, + } + #[derive(Deserialize, Debug)] + enum B { + C(C), + } + #[derive(Deserialize, Debug)] + struct C { + #[allow(dead_code)] + d: bool, + } + let yaml = indoc! {" + --- + b: + - C: + d: fase + "}; + let expected = + "b[0].C.d: invalid type: string \"fase\", expected a boolean at line 4 column 10"; + test_error::<A>(yaml, expected); +} + +#[test] +fn test_empty() { + let expected = "EOF while parsing a value"; + test_error::<String>("", expected); +} + +#[test] +fn test_missing_field() { + #[derive(Deserialize, Debug)] + struct Basic { + #[allow(dead_code)] + v: bool, + #[allow(dead_code)] + w: bool, + } + let yaml = indoc! {" + --- + v: true + "}; + let expected = "missing field `w` at line 2 column 2"; + test_error::<Basic>(yaml, expected); +} + +#[test] +fn test_unknown_anchor() { + let yaml = indoc! {" + --- + *some + "}; + let expected = "while parsing node, found unknown anchor at line 2 column 1"; + test_error::<String>(yaml, expected); +} + +#[test] +fn test_ignored_unknown_anchor() { + #[derive(Deserialize, Debug)] + struct Wrapper { + #[allow(dead_code)] + c: (), + } + let yaml = indoc! {" + --- + b: [*a] + c: ~ + "}; + let expected = "while parsing node, found unknown anchor at line 2 column 5"; + test_error::<Wrapper>(yaml, 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::<usize>(yaml, expected); +} + +#[test] +fn test_variant_map_wrong_size() { + #[derive(Deserialize, Debug)] + enum E { + V(usize), + } + let yaml = indoc! {r#" + --- + "V": 16 + "other": 32 + "#}; + let expected = "invalid length 2, expected map containing 1 entry"; + test_error::<E>(yaml, expected); +} + +#[test] +fn test_variant_not_a_map() { + #[derive(Deserialize, Debug)] + enum E { + V(usize), + } + let yaml = indoc! {r#" + --- + - "V" + "#}; + let expected = "invalid type: sequence, expected string or singleton map at line 2 column 1"; + test_error::<E>(yaml, expected); +} + +#[test] +fn test_variant_not_string() { + #[derive(Deserialize, Debug)] + enum E { + V(bool), + } + let yaml = indoc! {r#" + --- + {}: true + "#}; + let expected = "invalid type: map, expected variant of enum `E` at line 2 column 1"; + test_error::<E>(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 8"; + test_error::<bool>(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 7"; + test_error::<i64>(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 9"; + test_error::<f64>(yaml, expected); +} + +#[test] +fn test_bad_null() { + let yaml = indoc! {" + --- + !!null str + "}; + let expected = "invalid value: string \"str\", expected null at line 2 column 8"; + 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_no_location() { + let invalid_utf8: Result<serde_yaml::Value, serde_yaml::Error> = + serde_yaml::from_slice(b"\x80\xae"); + + let utf8_location = invalid_utf8.unwrap_err().location(); + + assert!(utf8_location.is_none()); +} + +#[test] +fn test_invalid_scalar_type() { + #[derive(Deserialize, Debug)] + struct S { + #[allow(dead_code)] + x: [(); 1], + } + + let yaml = "x:\n"; + let expected = "x: invalid type: unit value, expected an array of length 1 at line 2 column 1"; + test_error::<S>(yaml, expected); +} + +#[test] +fn test_infinite_recursion_objects() { + #[derive(Deserialize, Debug)] + struct S { + #[allow(dead_code)] + x: Option<Box<S>>, + } + + let yaml = "&a {x: *a}"; + let expected = "recursion limit exceeded"; + test_error::<S>(yaml, expected); +} + +#[test] +fn test_infinite_recursion_arrays() { + #[derive(Deserialize, Debug)] + struct S { + #[allow(dead_code)] + x: Option<Box<S>>, + } + + let yaml = "&a [*a]"; + let expected = "recursion limit exceeded"; + test_error::<S>(yaml, expected); +} + +#[test] +fn test_finite_recursion_objects() { + #[derive(Deserialize, Debug)] + struct S { + #[allow(dead_code)] + x: Option<Box<S>>, + } + + let yaml = "{x:".repeat(1_000) + &"}".repeat(1_000); + let expected = "recursion limit exceeded at line 1 column 766"; + test_error::<i32>(&yaml, expected); +} + +#[test] +fn test_finite_recursion_arrays() { + #[derive(Deserialize, Debug)] + struct S { + #[allow(dead_code)] + x: Option<Box<S>>, + } + + let yaml = "[".repeat(1_000) + &"]".repeat(1_000); + let expected = "recursion limit exceeded at line 1 column 256"; + test_error::<S>(&yaml, expected); +} diff --git a/third_party/rust/serde_yaml/tests/test_serde.rs b/third_party/rust/serde_yaml/tests/test_serde.rs new file mode 100644 index 0000000000..8b3f34b3fc --- /dev/null +++ b/third_party/rust/serde_yaml/tests/test_serde.rs @@ -0,0 +1,434 @@ +#![allow( + clippy::decimal_literal_representation, + clippy::derive_partial_eq_without_eq, + clippy::unreadable_literal, + clippy::shadow_unrelated +)] + +use indoc::indoc; +use serde_derive::{Deserialize, Serialize}; +use serde_yaml::Value; +use std::collections::BTreeMap; +use std::f64; +use std::fmt::Debug; + +fn test_serde<T>(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 = serde_yaml::from_value(value).unwrap(); + assert_eq!(*thing, deserialized); + + serde_yaml::from_str::<serde::de::IgnoredAny>(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 = ::std::u64::MAX; + let yaml = indoc! {" + --- + 18446744073709551615 + "}; + test_serde(&thing, yaml); +} + +#[test] +fn test_int_min_i64() { + let thing = ::std::i64::MIN; + let yaml = indoc! {" + --- + -9223372036854775808 + "}; + test_serde(&thing, yaml); +} + +#[test] +fn test_int_max_i64() { + let thing = ::std::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.6; + let yaml = indoc! {" + --- + 25.6 + "}; + 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_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(String::from("x"), 1); + thing.insert(String::from("y"), 2); + let yaml = indoc! {" + --- + x: 1 + y: 2 + "}; + test_serde(&thing, yaml); +} + +#[test] +fn test_basic_struct() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Basic { + x: isize, + y: String, + z: bool, + } + let thing = Basic { + x: -4, + y: String::from("hi\tquoted"), + z: true, + }; + let yaml = indoc! {r#" + --- + x: -4 + y: "hi\tquoted" + z: true + "#}; + 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_option() { + let thing = vec![Some(1), None, Some(3)]; + let yaml = indoc! {" + --- + - 1 + - ~ + - 3 + "}; + test_serde(&thing, yaml); +} + +#[test] +fn test_unit() { + let thing = vec![(), ()]; + let yaml = indoc! {" + --- + - ~ + - ~ + "}; + test_serde(&thing, yaml); +} + +#[test] +fn test_unit_struct() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Foo; + let thing = Foo; + let yaml = indoc! {" + --- + ~ + "}; + 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_value() { + use serde_yaml::{Mapping, Number}; + + #[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: + - ~ + - true + - 65535 + - 0.54321 + - s + - {} + "}; + test_serde(&thing, yaml); +} + +#[test] +fn test_mapping() { + use serde_yaml::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); +} diff --git a/third_party/rust/serde_yaml/tests/test_value.rs b/third_party/rust/serde_yaml/tests/test_value.rs new file mode 100644 index 0000000000..c001b9d73d --- /dev/null +++ b/third_party/rust/serde_yaml/tests/test_value.rs @@ -0,0 +1,55 @@ +#![allow(clippy::derive_partial_eq_without_eq, clippy::eq_op)] + +use serde::de::IntoDeserializer; +use serde::Deserialize; +use serde_derive::Deserialize; +use serde_yaml::{Number, Value}; +use std::f64; + +#[test] +fn test_nan() { + let pos_nan = serde_yaml::from_str::<Value>(".nan").unwrap(); + assert!(pos_nan.is_f64()); + assert_eq!(pos_nan, pos_nan); + + let neg_fake_nan = serde_yaml::from_str::<Value>("-.nan").unwrap(); + assert!(neg_fake_nan.is_string()); + + let significand_mask = 0xF_FFFF_FFFF_FFFF; + let bits = (f64::NAN.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::<Value>("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::<Value>("xyz").unwrap(); + let s = String::deserialize(value.into_deserializer()).unwrap(); + assert_eq!(s, "xyz"); + + let value = serde_yaml::from_str::<Value>("- first\n- second\n- third").unwrap(); + let arr = Vec::<String>::deserialize(value.into_deserializer()).unwrap(); + assert_eq!(arr, &["first", "second", "third"]); + + let value = serde_yaml::from_str::<Value>("first: abc\nsecond: 99").unwrap(); + let test = Test::deserialize(value.into_deserializer()).unwrap(); + assert_eq!( + test, + Test { + first: "abc".to_string(), + second: 99 + } + ); +} |