diff options
Diffstat (limited to 'third_party/rust/serde_path_to_error')
-rw-r--r-- | third_party/rust/serde_path_to_error/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/Cargo.toml | 41 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/LICENSE-APACHE | 176 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/LICENSE-MIT | 23 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/README.md | 72 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/src/de.rs | 1532 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/src/lib.rs | 193 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/src/path.rs | 158 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/src/ser.rs | 997 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/src/wrap.rs | 35 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/tests/deserialize.rs | 215 | ||||
-rw-r--r-- | third_party/rust/serde_path_to_error/tests/serialize.rs | 48 |
12 files changed, 3491 insertions, 0 deletions
diff --git a/third_party/rust/serde_path_to_error/.cargo-checksum.json b/third_party/rust/serde_path_to_error/.cargo-checksum.json new file mode 100644 index 0000000000..3b1e10f980 --- /dev/null +++ b/third_party/rust/serde_path_to_error/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"de067badf16e7bf1cf7ac11a9a80b37ac4f5919a634b4cc8081a7612a38b8a03","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"a85a795381a723c0cc19c2a75a62b309b0a01a12618da605d6166a7a5e207201","src/de.rs":"3ba337bd8602ad44e579012b93304091d46f3abeb0fe6a7dc80112c3628435a5","src/lib.rs":"2376f5ac5cb6a2eae1c2e5440b2d72c1472cb5cf1e2d99d7a39b6acdb230e5ef","src/path.rs":"1b8f0e6ec954b310213091b8bd8f3020457f020e31703e335cd09c3e2da7bccf","src/ser.rs":"093300bd35f0b499a1c28c969a7ef7f8b0ed8fb5ff09ddbfe857dcca31e213f1","src/wrap.rs":"9d88271729c6dc90d16328454f0432e18ce13df6c8dc4749785c5d3c7d260c09","tests/deserialize.rs":"785acf90b3ddc32febc7a87d0af274c59d6876a7ee7181deddf74a9d0516d93f","tests/serialize.rs":"84a16ce654ce3060a0c1cf23430ad4e5c5a9f7816c84c502716d2c991e90e358"},"package":"f7f05c1d5476066defcdfacce1f52fc3cae3af1d3089727100c02ae92e5abbe0"}
\ No newline at end of file diff --git a/third_party/rust/serde_path_to_error/Cargo.toml b/third_party/rust/serde_path_to_error/Cargo.toml new file mode 100644 index 0000000000..564864d7d2 --- /dev/null +++ b/third_party/rust/serde_path_to_error/Cargo.toml @@ -0,0 +1,41 @@ +# 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 = "2018" +rust-version = "1.31" +name = "serde_path_to_error" +version = "0.1.11" +authors = ["David Tolnay <dtolnay@gmail.com>"] +description = "Path to the element that failed to deserialize" +readme = "README.md" +keywords = [ + "serde", + "serialization", +] +categories = ["encoding"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/path-to-error" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +doc-scrape-examples = false + +[dependencies.serde] +version = "1.0" + +[dev-dependencies.serde_derive] +version = "1.0" + +[dev-dependencies.serde_json] +version = "1.0" diff --git a/third_party/rust/serde_path_to_error/LICENSE-APACHE b/third_party/rust/serde_path_to_error/LICENSE-APACHE new file mode 100644 index 0000000000..1b5ec8b78e --- /dev/null +++ b/third_party/rust/serde_path_to_error/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/third_party/rust/serde_path_to_error/LICENSE-MIT b/third_party/rust/serde_path_to_error/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/third_party/rust/serde_path_to_error/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_path_to_error/README.md b/third_party/rust/serde_path_to_error/README.md new file mode 100644 index 0000000000..c90ba4da0a --- /dev/null +++ b/third_party/rust/serde_path_to_error/README.md @@ -0,0 +1,72 @@ +# Serde path to error + +[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/path--to--error-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/path-to-error) +[<img alt="crates.io" src="https://img.shields.io/crates/v/serde_path_to_error.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/serde_path_to_error) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-serde__path__to__error-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/serde_path_to_error) +[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/path-to-error/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/path-to-error/actions?query=branch%3Amaster) + +Find out the path at which a deserialization error occurred. This crate provides +a wrapper that works with any existing Serde `Deserializer` and exposes the +chain of field names leading to the error. + +```toml +[dependencies] +serde = "1.0" +serde_path_to_error = "0.1" +``` + +```rust +use serde::Deserialize; +use std::collections::BTreeMap as Map; + +#[derive(Deserialize)] +struct Package { + name: String, + dependencies: Map<String, Dependency>, +} + +#[derive(Deserialize)] +struct Dependency { + version: String, +} + +fn main() { + let j = r#"{ + "name": "demo", + "dependencies": { + "serde": { + "version": 1 + } + } + }"#; + + // Some Deserializer. + let jd = &mut serde_json::Deserializer::from_str(j); + + let result: Result<Package, _> = serde_path_to_error::deserialize(jd); + match result { + Ok(_) => panic!("expected a type error"), + Err(err) => { + let path = err.path().to_string(); + assert_eq!(path, "dependencies.serde.version"); + } + } +} +``` + +<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_path_to_error/src/de.rs b/third_party/rust/serde_path_to_error/src/de.rs new file mode 100644 index 0000000000..b9440c3a33 --- /dev/null +++ b/third_party/rust/serde_path_to_error/src/de.rs @@ -0,0 +1,1532 @@ +use crate::wrap::{Wrap, WrapVariant}; +use crate::{Chain, Error, Track}; +use serde::de::{self, Deserialize, DeserializeSeed, Visitor}; +use serde::serde_if_integer128; +use std::fmt; + +/// Entry point. See [crate documentation][crate] for an example. +pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, Error<D::Error>> +where + D: de::Deserializer<'de>, + T: Deserialize<'de>, +{ + let mut track = Track::new(); + match T::deserialize(Deserializer::new(deserializer, &mut track)) { + Ok(t) => Ok(t), + Err(err) => Err(Error { + path: track.path(), + original: err, + }), + } +} + +/// Deserializer adapter that records path to deserialization errors. +/// +/// # Example +/// +/// ``` +/// # use serde_derive::Deserialize; +/// # +/// use serde::Deserialize; +/// use std::collections::BTreeMap as Map; +/// +/// #[derive(Deserialize)] +/// struct Package { +/// name: String, +/// dependencies: Map<String, Dependency>, +/// } +/// +/// #[derive(Deserialize)] +/// struct Dependency { +/// version: String, +/// } +/// +/// fn main() { +/// let j = r#"{ +/// "name": "demo", +/// "dependencies": { +/// "serde": { +/// "version": 1 +/// } +/// } +/// }"#; +/// +/// // Some Deserializer. +/// let jd = &mut serde_json::Deserializer::from_str(j); +/// +/// let mut track = serde_path_to_error::Track::new(); +/// let pd = serde_path_to_error::Deserializer::new(jd, &mut track); +/// +/// match Package::deserialize(pd) { +/// Ok(_) => panic!("expected a type error"), +/// Err(_) => { +/// let path = track.path().to_string(); +/// assert_eq!(path, "dependencies.serde.version"); +/// } +/// } +/// } +/// ``` +pub struct Deserializer<'a, 'b, D> { + de: D, + chain: Chain<'a>, + track: &'b Track, +} + +impl<'a, 'b, D> Deserializer<'a, 'b, D> { + pub fn new(de: D, track: &'b mut Track) -> Self { + Deserializer { + de, + chain: Chain::Root, + track, + } + } +} + +// Plain old forwarding impl. +impl<'a, 'b, 'de, D> de::Deserializer<'de> for Deserializer<'a, 'b, D> +where + D: de::Deserializer<'de>, +{ + type Error = D::Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_any(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_bool(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_u8(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_u16(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_u32(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_u64(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_i8(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_i16(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_i32(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_i64(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + serde_if_integer128! { + fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_u128(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_i128(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + } + + fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_f32(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_f64(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_char(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_str(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_string(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_bytes(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_byte_buf(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_option(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_unit(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_unit_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_unit_struct(name, Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_newtype_struct(name, Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_seq(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_tuple(len, Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_tuple_struct<V>( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_tuple_struct(name, len, Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_map(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_struct(name, fields, Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_enum(name, variants, Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_ignored_any(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, D::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.de + .deserialize_identifier(Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn is_human_readable(&self) -> bool { + self.de.is_human_readable() + } +} + +// Forwarding impl to preserve context. +impl<'a, 'b, 'de, X> Visitor<'de> for Wrap<'a, 'b, X> +where + X: Visitor<'de>, +{ + type Value = X::Value; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + self.delegate.expecting(formatter) + } + + fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_bool(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_i8(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_i16(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_i32(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_i64(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_u8(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_u16(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_u32(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_u64(v) + .map_err(|err| track.trigger(chain, err)) + } + + serde_if_integer128! { + fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_i128(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_u128(v) + .map_err(|err| track.trigger(chain, err)) + } + } + + fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_f32(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_f64(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_char<E>(self, v: char) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_char(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_str(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_borrowed_str(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_string(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_unit() + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_none<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_none() + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_some(Deserializer { + de: deserializer, + chain: Chain::Some { parent: chain }, + track, + }) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_newtype_struct(Deserializer { + de: deserializer, + chain: Chain::NewtypeStruct { parent: chain }, + track, + }) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_seq<V>(self, visitor: V) -> Result<Self::Value, V::Error> + where + V: de::SeqAccess<'de>, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_seq(SeqAccess::new(visitor, chain, track)) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_map<V>(self, visitor: V) -> Result<Self::Value, V::Error> + where + V: de::MapAccess<'de>, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_map(MapAccess::new(visitor, chain, track)) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_enum<V>(self, visitor: V) -> Result<Self::Value, V::Error> + where + V: de::EnumAccess<'de>, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_enum(Wrap::new(visitor, chain, track)) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_bytes(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_borrowed_bytes(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> + where + E: de::Error, + { + let chain = self.chain; + let track = self.track; + self.delegate + .visit_byte_buf(v) + .map_err(|err| track.trigger(chain, err)) + } +} + +// Forwarding impl to preserve context. +impl<'a, 'b, 'de, X> de::EnumAccess<'de> for Wrap<'a, 'b, X> +where + X: de::EnumAccess<'de> + 'a, +{ + type Error = X::Error; + type Variant = WrapVariant<'a, 'b, X::Variant>; + + fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), X::Error> + where + V: DeserializeSeed<'de>, + { + let chain = self.chain; + let track = self.track; + let mut variant = None; + self.delegate + .variant_seed(CaptureKey::new(seed, &mut variant)) + .map_err(|err| track.trigger(chain, err)) + .map(move |(v, vis)| { + let chain = match variant { + Some(variant) => Chain::Enum { + parent: chain, + variant, + }, + None => Chain::NonStringKey { parent: chain }, + }; + (v, WrapVariant::new(vis, chain, track)) + }) + } +} + +// Forwarding impl to preserve context. +impl<'a, 'b, 'de, X> de::VariantAccess<'de> for WrapVariant<'a, 'b, X> +where + X: de::VariantAccess<'de>, +{ + type Error = X::Error; + + fn unit_variant(self) -> Result<(), X::Error> { + let chain = self.chain; + let track = self.track; + self.delegate + .unit_variant() + .map_err(|err| track.trigger(&chain, err)) + } + + fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, X::Error> + where + T: DeserializeSeed<'de>, + { + let chain = self.chain; + let track = self.track; + let nested = Chain::NewtypeVariant { parent: &chain }; + self.delegate + .newtype_variant_seed(TrackedSeed::new(seed, nested, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.delegate + .tuple_variant(len, Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } + + fn struct_variant<V>( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + let chain = self.chain; + let track = self.track; + self.delegate + .struct_variant(fields, Wrap::new(visitor, &chain, track)) + .map_err(|err| track.trigger(&chain, err)) + } +} + +// Seed that saves the string into the given optional during `visit_str` and +// `visit_string`. +struct CaptureKey<'a, X> { + delegate: X, + key: &'a mut Option<String>, +} + +impl<'a, X> CaptureKey<'a, X> { + fn new(delegate: X, key: &'a mut Option<String>) -> Self { + CaptureKey { delegate, key } + } +} + +// Forwarding impl. +impl<'a, 'de, X> DeserializeSeed<'de> for CaptureKey<'a, X> +where + X: DeserializeSeed<'de>, +{ + type Value = X::Value; + + fn deserialize<D>(self, deserializer: D) -> Result<X::Value, D::Error> + where + D: de::Deserializer<'de>, + { + self.delegate + .deserialize(CaptureKey::new(deserializer, self.key)) + } +} + +// Forwarding impl. +impl<'a, 'de, X> de::Deserializer<'de> for CaptureKey<'a, X> +where + X: de::Deserializer<'de>, +{ + type Error = X::Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_any(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_bool(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_u8(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_u16(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_u32(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_u64(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_i8(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_i16(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_i32(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_i64(CaptureKey::new(visitor, self.key)) + } + + serde_if_integer128! { + fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_u128(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_i128(CaptureKey::new(visitor, self.key)) + } + } + + fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_f32(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_f64(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_char(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_str(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_string(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_bytes(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_byte_buf(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_option(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_unit(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_unit_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_unit_struct(name, CaptureKey::new(visitor, self.key)) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_newtype_struct(name, CaptureKey::new(visitor, self.key)) + } + + fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_seq(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_tuple(len, CaptureKey::new(visitor, self.key)) + } + + fn deserialize_tuple_struct<V>( + self, + name: &'static str, + len: usize, + visitor: V, + ) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_tuple_struct(name, len, CaptureKey::new(visitor, self.key)) + } + + fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_map(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_struct(name, fields, CaptureKey::new(visitor, self.key)) + } + + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_enum(name, variants, CaptureKey::new(visitor, self.key)) + } + + fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_ignored_any(CaptureKey::new(visitor, self.key)) + } + + fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, X::Error> + where + V: Visitor<'de>, + { + self.delegate + .deserialize_identifier(CaptureKey::new(visitor, self.key)) + } + + fn is_human_readable(&self) -> bool { + self.delegate.is_human_readable() + } +} + +// Forwarding impl except `visit_str` and `visit_string` which save the string. +impl<'a, 'de, X> Visitor<'de> for CaptureKey<'a, X> +where + X: Visitor<'de>, +{ + type Value = X::Value; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + self.delegate.expecting(formatter) + } + + fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_bool(v) + } + + fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_i8(v) + } + + fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_i16(v) + } + + fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_i32(v) + } + + fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_i64(v) + } + + fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_u8(v) + } + + fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_u16(v) + } + + fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_u32(v) + } + + fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_u64(v) + } + + serde_if_integer128! { + fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_i128(v) + } + + fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_u128(v) + } + } + + fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_f32(v) + } + + fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_f64(v) + } + + fn visit_char<E>(self, v: char) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_char(v) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: de::Error, + { + *self.key = Some(v.to_owned()); + self.delegate.visit_str(v) + } + + fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> + where + E: de::Error, + { + *self.key = Some(v.to_owned()); + self.delegate.visit_borrowed_str(v) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: de::Error, + { + *self.key = Some(v.clone()); + self.delegate.visit_string(v) + } + + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_unit() + } + + fn visit_none<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_none() + } + + fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + self.delegate.visit_some(deserializer) + } + + fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + self.delegate.visit_newtype_struct(deserializer) + } + + fn visit_seq<V>(self, visitor: V) -> Result<Self::Value, V::Error> + where + V: de::SeqAccess<'de>, + { + self.delegate.visit_seq(visitor) + } + + fn visit_map<V>(self, visitor: V) -> Result<Self::Value, V::Error> + where + V: de::MapAccess<'de>, + { + self.delegate.visit_map(visitor) + } + + fn visit_enum<V>(self, visitor: V) -> Result<Self::Value, V::Error> + where + V: de::EnumAccess<'de>, + { + self.delegate.visit_enum(visitor) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_bytes(v) + } + + fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_borrowed_bytes(v) + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> + where + E: de::Error, + { + self.delegate.visit_byte_buf(v) + } +} + +// Seed used for map values, sequence elements and newtype variants to track +// their path. +struct TrackedSeed<'a, 'b, X> { + seed: X, + chain: Chain<'a>, + track: &'b Track, +} + +impl<'a, 'b, X> TrackedSeed<'a, 'b, X> { + fn new(seed: X, chain: Chain<'a>, track: &'b Track) -> Self { + TrackedSeed { seed, chain, track } + } +} + +impl<'a, 'b, 'de, X> DeserializeSeed<'de> for TrackedSeed<'a, 'b, X> +where + X: DeserializeSeed<'de>, +{ + type Value = X::Value; + + fn deserialize<D>(self, deserializer: D) -> Result<X::Value, D::Error> + where + D: de::Deserializer<'de>, + { + let chain = self.chain; + let track = self.track; + self.seed + .deserialize(Deserializer { + de: deserializer, + chain: chain.clone(), + track, + }) + .map_err(|err| track.trigger(&chain, err)) + } +} + +// Seq visitor that tracks the index of its elements. +struct SeqAccess<'a, 'b, X> { + delegate: X, + chain: &'a Chain<'a>, + index: usize, + track: &'b Track, +} + +impl<'a, 'b, X> SeqAccess<'a, 'b, X> { + fn new(delegate: X, chain: &'a Chain<'a>, track: &'b Track) -> Self { + SeqAccess { + delegate, + chain, + index: 0, + track, + } + } +} + +// Forwarding impl to preserve context. +impl<'a, 'b, 'de, X> de::SeqAccess<'de> for SeqAccess<'a, 'b, X> +where + X: de::SeqAccess<'de>, +{ + type Error = X::Error; + + fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, X::Error> + where + T: DeserializeSeed<'de>, + { + let parent = self.chain; + let chain = Chain::Seq { + parent, + index: self.index, + }; + let track = self.track; + self.index += 1; + self.delegate + .next_element_seed(TrackedSeed::new(seed, chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn size_hint(&self) -> Option<usize> { + self.delegate.size_hint() + } +} + +// Map visitor that captures the string value of its keys and uses that to track +// the path to its values. +struct MapAccess<'a, 'b, X> { + delegate: X, + chain: &'a Chain<'a>, + key: Option<String>, + track: &'b Track, +} + +impl<'a, 'b, X> MapAccess<'a, 'b, X> { + fn new(delegate: X, chain: &'a Chain<'a>, track: &'b Track) -> Self { + MapAccess { + delegate, + chain, + key: None, + track, + } + } +} + +impl<'a, 'b, 'de, X> de::MapAccess<'de> for MapAccess<'a, 'b, X> +where + X: de::MapAccess<'de>, +{ + type Error = X::Error; + + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, X::Error> + where + K: DeserializeSeed<'de>, + { + let chain = self.chain; + let track = self.track; + let key = &mut self.key; + self.delegate + .next_key_seed(CaptureKey::new(seed, key)) + .map_err(|err| { + let chain = match key.take() { + Some(key) => Chain::Map { parent: chain, key }, + None => Chain::NonStringKey { parent: chain }, + }; + track.trigger(&chain, err) + }) + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, X::Error> + where + V: DeserializeSeed<'de>, + { + let parent = self.chain; + let chain = match self.key.take() { + Some(key) => Chain::Map { parent, key }, + None => Chain::NonStringKey { parent }, + }; + let track = self.track; + self.delegate + .next_value_seed(TrackedSeed::new(seed, chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn size_hint(&self) -> Option<usize> { + self.delegate.size_hint() + } +} diff --git a/third_party/rust/serde_path_to_error/src/lib.rs b/third_party/rust/serde_path_to_error/src/lib.rs new file mode 100644 index 0000000000..abb6a2d464 --- /dev/null +++ b/third_party/rust/serde_path_to_error/src/lib.rs @@ -0,0 +1,193 @@ +//! [![github]](https://github.com/dtolnay/path-to-error) [![crates-io]](https://crates.io/crates/serde_path_to_error) [![docs-rs]](https://docs.rs/serde_path_to_error) +//! +//! [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> +//! +//! Find out the path at which a deserialization error occurred. This crate +//! provides a wrapper that works with any existing Serde `Deserializer` and +//! exposes the chain of field names leading to the error. +//! +//! # Example +//! +//! ``` +//! # use serde_derive::Deserialize; +//! # +//! use serde::Deserialize; +//! use std::collections::BTreeMap as Map; +//! +//! #[derive(Deserialize)] +//! struct Package { +//! name: String, +//! dependencies: Map<String, Dependency>, +//! } +//! +//! #[derive(Deserialize)] +//! struct Dependency { +//! version: String, +//! } +//! +//! fn main() { +//! let j = r#"{ +//! "name": "demo", +//! "dependencies": { +//! "serde": { +//! "version": 1 +//! } +//! } +//! }"#; +//! +//! // Some Deserializer. +//! let jd = &mut serde_json::Deserializer::from_str(j); +//! +//! let result: Result<Package, _> = serde_path_to_error::deserialize(jd); +//! match result { +//! Ok(_) => panic!("expected a type error"), +//! Err(err) => { +//! let path = err.path().to_string(); +//! assert_eq!(path, "dependencies.serde.version"); +//! } +//! } +//! } +//! ``` + +#![doc(html_root_url = "https://docs.rs/serde_path_to_error/0.1.11")] +#![allow( + clippy::doc_link_with_quotes, // https://github.com/rust-lang/rust-clippy/issues/8961 + clippy::iter_not_returning_iterator, // https://github.com/rust-lang/rust-clippy/issues/8285 + clippy::missing_errors_doc, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::new_without_default +)] + +mod de; +mod path; +mod ser; +mod wrap; + +use std::cell::Cell; +use std::error::Error as StdError; +use std::fmt::{self, Display}; + +pub use crate::de::{deserialize, Deserializer}; +pub use crate::path::{Path, Segment, Segments}; +pub use crate::ser::{serialize, Serializer}; + +/// Original deserializer error together with the path at which it occurred. +#[derive(Clone, Debug)] +pub struct Error<E> { + path: Path, + original: E, +} + +impl<E> Error<E> { + pub fn new(path: Path, inner: E) -> Self { + Error { + path, + original: inner, + } + } + + /// Element path at which this deserialization error occurred. + pub fn path(&self) -> &Path { + &self.path + } + + /// The Deserializer's underlying error that occurred. + pub fn into_inner(self) -> E { + self.original + } + + /// Reference to the Deserializer's underlying error that occurred. + pub fn inner(&self) -> &E { + &self.original + } +} + +impl<E: Display> Display for Error<E> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if !self.path.is_only_unknown() { + write!(f, "{}: ", self.path)?; + } + write!(f, "{}", self.original) + } +} + +impl<E: StdError> StdError for Error<E> { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.original.source() + } +} + +/// State for bookkeeping across nested deserializer calls. +/// +/// You don't need this if you are using `serde_path_to_error::deserializer`. If +/// you are managing your own `Deserializer`, see the usage example on +/// [`Deserializer`]. +pub struct Track { + path: Cell<Option<Path>>, +} + +impl Track { + /// Empty state with no error having happened yet. + pub fn new() -> Self { + Track { + path: Cell::new(None), + } + } + + /// Gets path at which the error occurred. Only meaningful after we know + /// that an error has occurred. Returns an empty path otherwise. + pub fn path(self) -> Path { + self.path.into_inner().unwrap_or_else(Path::empty) + } + + #[inline] + fn trigger<E>(&self, chain: &Chain, err: E) -> E { + self.trigger_impl(chain); + err + } + + fn trigger_impl(&self, chain: &Chain) { + self.path.set(Some(match self.path.take() { + Some(already_set) => already_set, + None => Path::from_chain(chain), + })); + } +} + +#[derive(Clone)] +enum Chain<'a> { + Root, + Seq { + parent: &'a Chain<'a>, + index: usize, + }, + Map { + parent: &'a Chain<'a>, + key: String, + }, + Struct { + parent: &'a Chain<'a>, + key: &'static str, + }, + Enum { + parent: &'a Chain<'a>, + variant: String, + }, + Some { + parent: &'a Chain<'a>, + }, + NewtypeStruct { + parent: &'a Chain<'a>, + }, + NewtypeVariant { + parent: &'a Chain<'a>, + }, + NonStringKey { + parent: &'a Chain<'a>, + }, +} diff --git a/third_party/rust/serde_path_to_error/src/path.rs b/third_party/rust/serde_path_to_error/src/path.rs new file mode 100644 index 0000000000..5542a2527e --- /dev/null +++ b/third_party/rust/serde_path_to_error/src/path.rs @@ -0,0 +1,158 @@ +use std::fmt::{self, Display}; +use std::slice; + +use super::Chain; + +/// Path to the error value in the input, like `dependencies.serde.typo1`. +/// +/// Use `path.to_string()` to get a string representation of the path with +/// segments separated by periods, or use `path.iter()` to iterate over +/// individual segments of the path. +#[derive(Clone, Debug)] +pub struct Path { + segments: Vec<Segment>, +} + +/// Single segment of a path. +#[derive(Clone, Debug)] +pub enum Segment { + Seq { index: usize }, + Map { key: String }, + Enum { variant: String }, + Unknown, +} + +impl Path { + /// Returns an iterator with element type [`&Segment`][Segment]. + pub fn iter(&self) -> Segments { + Segments { + iter: self.segments.iter(), + } + } +} + +impl<'a> IntoIterator for &'a Path { + type Item = &'a Segment; + type IntoIter = Segments<'a>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +/// Iterator over segments of a path. +pub struct Segments<'a> { + iter: slice::Iter<'a, Segment>, +} + +impl<'a> Iterator for Segments<'a> { + type Item = &'a Segment; + + fn next(&mut self) -> Option<Self::Item> { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} + +impl<'a> DoubleEndedIterator for Segments<'a> { + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back() + } +} + +impl<'a> ExactSizeIterator for Segments<'a> { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl Display for Path { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + if self.segments.is_empty() { + return formatter.write_str("."); + } + + let mut separator = ""; + for segment in self { + match segment { + Segment::Seq { index } => { + write!(formatter, "[{}]", index)?; + } + Segment::Map { key } | Segment::Enum { variant: key } => { + write!(formatter, "{}{}", separator, key)?; + } + Segment::Unknown => { + write!(formatter, "{}?", separator)?; + } + } + separator = "."; + } + + Ok(()) + } +} + +impl Path { + pub(crate) fn empty() -> Self { + Path { + segments: Vec::new(), + } + } + + pub(crate) fn from_chain(mut chain: &Chain) -> Self { + let mut segments = Vec::new(); + loop { + match chain { + Chain::Root => break, + Chain::Seq { parent, index } => { + segments.push(Segment::Seq { index: *index }); + chain = parent; + } + Chain::Map { parent, key } => { + segments.push(Segment::Map { key: key.clone() }); + chain = parent; + } + Chain::Struct { parent, key } => { + let key = *key; + segments.push(Segment::Map { + key: key.to_owned(), + }); + chain = parent; + } + Chain::Enum { parent, variant } => { + segments.push(Segment::Enum { + variant: variant.clone(), + }); + chain = parent; + } + Chain::Some { parent } + | Chain::NewtypeStruct { parent } + | Chain::NewtypeVariant { parent } => { + chain = parent; + } + Chain::NonStringKey { parent } => { + segments.push(Segment::Unknown); + chain = parent; + } + } + } + segments.reverse(); + Path { segments } + } + + pub(crate) fn is_only_unknown(&self) -> bool { + self.segments.iter().all(Segment::is_unknown) + } +} + +impl Segment { + fn is_unknown(&self) -> bool { + match self { + Segment::Unknown => true, + _ => false, + } + } +} diff --git a/third_party/rust/serde_path_to_error/src/ser.rs b/third_party/rust/serde_path_to_error/src/ser.rs new file mode 100644 index 0000000000..ed441c0d55 --- /dev/null +++ b/third_party/rust/serde_path_to_error/src/ser.rs @@ -0,0 +1,997 @@ +use crate::wrap::Wrap; +use crate::{Chain, Error, Track}; +use serde::ser::{self, Serialize}; +use serde::serde_if_integer128; +use std::cell::Cell; +use std::fmt::Display; + +/// Entry point for tracking path to Serialize error. +/// +/// # Example +/// +/// ``` +/// # use serde_derive::Serialize; +/// # +/// use serde::Serialize; +/// use std::cell::RefCell; +/// +/// #[derive(Serialize)] +/// struct Outer<'a> { +/// k: Inner<'a>, +/// } +/// +/// #[derive(Serialize)] +/// struct Inner<'a> { +/// refcell: &'a RefCell<String>, +/// } +/// +/// let refcell = RefCell::new(String::new()); +/// let value = Outer { +/// k: Inner { refcell: &refcell }, +/// }; +/// +/// // A RefCell cannot be serialized while it is still mutably borrowed. +/// let _borrowed = refcell.borrow_mut(); +/// +/// // Some Serializer. +/// let mut out = Vec::new(); +/// let jser = &mut serde_json::Serializer::new(&mut out); +/// +/// let result = serde_path_to_error::serialize(&value, jser); +/// match result { +/// Ok(_) => panic!("expected failure to serialize RefCell"), +/// Err(err) => { +/// let path = err.path().to_string(); +/// assert_eq!(path, "k.refcell"); +/// } +/// } +/// ``` +pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, Error<S::Error>> +where + T: ?Sized + Serialize, + S: ser::Serializer, +{ + let mut track = Track::new(); + match T::serialize(value, Serializer::new(serializer, &mut track)) { + Ok(ok) => Ok(ok), + Err(err) => Err(Error { + path: track.path(), + original: err, + }), + } +} + +/// Serializer adapter that records path to serialization errors. +/// +/// # Example +/// +/// ``` +/// # use serde_derive::Serialize; +/// # +/// use serde::Serialize; +/// use std::collections::BTreeMap; +/// +/// // Maps with a non-string key are not valid in JSON. +/// let mut inner_map = BTreeMap::new(); +/// inner_map.insert(vec!['w', 'a', 't'], 0); +/// +/// let mut outer_map = BTreeMap::new(); +/// outer_map.insert("k", inner_map); +/// +/// // Some Serializer. +/// let mut out = Vec::new(); +/// let jser = &mut serde_json::Serializer::new(&mut out); +/// +/// let mut track = serde_path_to_error::Track::new(); +/// let ps = serde_path_to_error::Serializer::new(jser, &mut track); +/// +/// match outer_map.serialize(ps) { +/// Ok(_) => panic!("expected failure to serialize non-string key"), +/// Err(_) => { +/// let path = track.path().to_string(); +/// assert_eq!(path, "k"); +/// } +/// } +/// ``` +pub struct Serializer<'a, 'b, S> { + ser: S, + chain: &'a Chain<'a>, + track: &'b Track, +} + +impl<'a, 'b, S> Serializer<'a, 'b, S> { + pub fn new(ser: S, track: &'b mut Track) -> Self { + Serializer { + ser, + chain: &Chain::Root, + track, + } + } +} + +impl<'a, 'b, S> ser::Serializer for Serializer<'a, 'b, S> +where + S: ser::Serializer, +{ + type Ok = S::Ok; + type Error = S::Error; + type SerializeSeq = WrapSeq<'a, 'b, S::SerializeSeq>; + type SerializeTuple = WrapSeq<'a, 'b, S::SerializeTuple>; + type SerializeTupleStruct = WrapSeq<'a, 'b, S::SerializeTupleStruct>; + type SerializeTupleVariant = WrapSeq<'a, 'b, S::SerializeTupleVariant>; + type SerializeMap = WrapMap<'a, 'b, S::SerializeMap>; + type SerializeStruct = Wrap<'a, 'b, S::SerializeStruct>; + type SerializeStructVariant = Wrap<'a, 'b, S::SerializeStructVariant>; + + fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_bool(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_i8(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_i16(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_i32(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_i64(v) + .map_err(|err| track.trigger(chain, err)) + } + + serde_if_integer128! { + fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_i128(v) + .map_err(|err| track.trigger(chain, err)) + } + } + + fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_u8(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_u16(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_u32(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_u64(v) + .map_err(|err| track.trigger(chain, err)) + } + + serde_if_integer128! { + fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_u128(v) + .map_err(|err| track.trigger(chain, err)) + } + } + + fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_f32(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_f64(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_char(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_str(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_bytes(v) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_none() + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_some(value) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_unit() + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_unit_struct(name) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_unit_variant(name, variant_index, variant) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_newtype_struct<T>( + self, + name: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_newtype_struct(name, value) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_newtype_variant<T>( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + let chain = self.chain; + let track = self.track; + self.ser + .serialize_newtype_variant(name, variant_index, variant, value) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + let chain = self.chain; + let track = self.track; + match self.ser.serialize_seq(len) { + Ok(delegate) => Ok(WrapSeq::new(delegate, chain, track)), + Err(err) => Err(track.trigger(chain, err)), + } + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + let chain = self.chain; + let track = self.track; + match self.ser.serialize_tuple(len) { + Ok(delegate) => Ok(WrapSeq::new(delegate, chain, track)), + Err(err) => Err(track.trigger(chain, err)), + } + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + let chain = self.chain; + let track = self.track; + match self.ser.serialize_tuple_struct(name, len) { + Ok(delegate) => Ok(WrapSeq::new(delegate, chain, track)), + Err(err) => Err(track.trigger(chain, err)), + } + } + + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + let chain = self.chain; + let track = self.track; + match self + .ser + .serialize_tuple_variant(name, variant_index, variant, len) + { + Ok(delegate) => Ok(WrapSeq::new(delegate, chain, track)), + Err(err) => Err(track.trigger(chain, err)), + } + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + let chain = self.chain; + let track = self.track; + match self.ser.serialize_map(len) { + Ok(delegate) => Ok(WrapMap::new(delegate, chain, track)), + Err(err) => Err(track.trigger(chain, err)), + } + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + let chain = self.chain; + let track = self.track; + match self.ser.serialize_struct(name, len) { + Ok(delegate) => Ok(Wrap::new(delegate, chain, track)), + Err(err) => Err(track.trigger(chain, err)), + } + } + + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + let chain = self.chain; + let track = self.track; + match self + .ser + .serialize_struct_variant(name, variant_index, variant, len) + { + Ok(delegate) => Ok(Wrap::new(delegate, chain, track)), + Err(err) => Err(track.trigger(chain, err)), + } + } + + fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Display, + { + let chain = self.chain; + let track = self.track; + self.ser + .collect_str(value) + .map_err(|err| track.trigger(chain, err)) + } + + fn is_human_readable(&self) -> bool { + self.ser.is_human_readable() + } +} + +struct TrackedValue<'a, 'b, X> { + value: X, + chain: &'a Chain<'a>, + track: &'b Track, +} + +impl<'a, 'b, X> TrackedValue<'a, 'b, X> { + fn new(value: X, chain: &'a Chain<'a>, track: &'b Track) -> Self { + TrackedValue { + value, + chain, + track, + } + } +} + +impl<'a, 'b, X> Serialize for TrackedValue<'a, 'b, X> +where + X: Serialize, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + let chain = self.chain; + let track = self.track; + self.value + .serialize(Serializer { + ser: serializer, + chain, + track, + }) + .map_err(|err| track.trigger(chain, err)) + } +} + +pub struct WrapSeq<'a, 'b, S> { + delegate: S, + chain: &'a Chain<'a>, + index: usize, + track: &'b Track, +} + +impl<'a, 'b, S> WrapSeq<'a, 'b, S> { + fn new(delegate: S, chain: &'a Chain<'a>, track: &'b Track) -> Self { + WrapSeq { + delegate, + chain, + index: 0, + track, + } + } +} + +impl<'a, 'b, S> ser::SerializeSeq for WrapSeq<'a, 'b, S> +where + S: ser::SerializeSeq, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let parent = self.chain; + let chain = Chain::Seq { + parent, + index: self.index, + }; + let track = self.track; + self.index += 1; + self.delegate + .serialize_element(&TrackedValue::new(value, &chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate.end().map_err(|err| track.trigger(chain, err)) + } +} + +impl<'a, 'b, S> ser::SerializeTuple for WrapSeq<'a, 'b, S> +where + S: ser::SerializeTuple, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let parent = self.chain; + let chain = Chain::Seq { + parent, + index: self.index, + }; + let track = self.track; + self.index += 1; + self.delegate + .serialize_element(&TrackedValue::new(value, &chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate.end().map_err(|err| track.trigger(chain, err)) + } +} + +impl<'a, 'b, S> ser::SerializeTupleStruct for WrapSeq<'a, 'b, S> +where + S: ser::SerializeTupleStruct, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let parent = self.chain; + let chain = Chain::Seq { + parent, + index: self.index, + }; + let track = self.track; + self.index += 1; + self.delegate + .serialize_field(&TrackedValue::new(value, &chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate.end().map_err(|err| track.trigger(chain, err)) + } +} + +impl<'a, 'b, S> ser::SerializeTupleVariant for WrapSeq<'a, 'b, S> +where + S: ser::SerializeTupleVariant, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let parent = self.chain; + let chain = Chain::Seq { + parent, + index: self.index, + }; + let track = self.track; + self.index += 1; + self.delegate + .serialize_field(&TrackedValue::new(value, &chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate.end().map_err(|err| track.trigger(chain, err)) + } +} + +pub struct WrapMap<'a, 'b, S> { + delegate: S, + chain: &'a Chain<'a>, + key: Cell<Option<String>>, + track: &'b Track, +} + +impl<'a, 'b, S> WrapMap<'a, 'b, S> { + fn new(delegate: S, chain: &'a Chain<'a>, track: &'b Track) -> Self { + WrapMap { + delegate, + chain, + key: Cell::new(None), + track, + } + } +} + +impl<'a, 'b, S> ser::SerializeMap for WrapMap<'a, 'b, S> +where + S: ser::SerializeMap, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let chain = self.chain; + let track = self.track; + self.key.set(None); + self.delegate + .serialize_key(&CaptureKey::new(&self.key, key)) + .map_err(|err| track.trigger(chain, err)) + } + + fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let parent = self.chain; + let chain = match self.key.take() { + Some(key) => Chain::Map { parent, key }, + None => Chain::NonStringKey { parent }, + }; + let track = self.track; + self.delegate + .serialize_value(&TrackedValue::new(value, &chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate.end().map_err(|err| track.trigger(chain, err)) + } +} + +impl<'a, 'b, S> ser::SerializeStruct for Wrap<'a, 'b, S> +where + S: ser::SerializeStruct, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let parent = self.chain; + let chain = Chain::Struct { parent, key }; + let track = self.track; + self.delegate + .serialize_field(key, &TrackedValue::new(value, &chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate.end().map_err(|err| track.trigger(chain, err)) + } + + fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate + .skip_field(key) + .map_err(|err| track.trigger(chain, err)) + } +} + +impl<'a, 'b, S> ser::SerializeStructVariant for Wrap<'a, 'b, S> +where + S: ser::SerializeStructVariant, +{ + type Ok = S::Ok; + type Error = S::Error; + + fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let parent = self.chain; + let chain = Chain::Struct { parent, key }; + let track = self.track; + self.delegate + .serialize_field(key, &TrackedValue::new(value, &chain, track)) + .map_err(|err| track.trigger(parent, err)) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate.end().map_err(|err| track.trigger(chain, err)) + } + + fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { + let chain = self.chain; + let track = self.track; + self.delegate + .skip_field(key) + .map_err(|err| track.trigger(chain, err)) + } +} + +struct CaptureKey<'a, T> { + out: &'a Cell<Option<String>>, + delegate: T, +} + +impl<'a, T> CaptureKey<'a, T> { + fn new(out: &'a Cell<Option<String>>, delegate: T) -> Self { + CaptureKey { out, delegate } + } +} + +impl<'a, T> Serialize for CaptureKey<'a, T> +where + T: Serialize, +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + self.delegate + .serialize(CaptureKey::new(self.out, serializer)) + } +} + +impl<'a, S> ser::Serializer for CaptureKey<'a, S> +where + S: ser::Serializer, +{ + type Ok = S::Ok; + type Error = S::Error; + type SerializeSeq = S::SerializeSeq; + type SerializeTuple = S::SerializeTuple; + type SerializeTupleStruct = S::SerializeTupleStruct; + type SerializeTupleVariant = S::SerializeTupleVariant; + type SerializeMap = S::SerializeMap; + type SerializeStruct = S::SerializeStruct; + type SerializeStructVariant = S::SerializeStructVariant; + + fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_bool(v) + } + + fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_i8(v) + } + + fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_i16(v) + } + + fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_i32(v) + } + + fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_i64(v) + } + + serde_if_integer128! { + fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_i128(v) + } + } + + fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_u8(v) + } + + fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_u16(v) + } + + fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_u32(v) + } + + fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_u64(v) + } + + serde_if_integer128! { + fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_string())); + self.delegate.serialize_u128(v) + } + } + + fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> { + self.delegate.serialize_f32(v) + } + + fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + self.delegate.serialize_f64(v) + } + + fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> { + self.delegate.serialize_char(v) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(v.to_owned())); + self.delegate.serialize_str(v) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> { + self.delegate.serialize_bytes(v) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + self.delegate.serialize_none() + } + + fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + self.delegate + .serialize_some(&CaptureKey::new(self.out, value)) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + self.delegate.serialize_unit() + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { + self.delegate.serialize_unit_struct(name) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + self.out.set(Some(variant.to_owned())); + self.delegate + .serialize_unit_variant(name, variant_index, variant) + } + + fn serialize_newtype_struct<T>( + self, + name: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + self.delegate + .serialize_newtype_struct(name, &CaptureKey::new(self.out, value)) + } + + fn serialize_newtype_variant<T>( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Serialize, + { + self.delegate + .serialize_newtype_variant(name, variant_index, variant, value) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + self.delegate.serialize_seq(len) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + self.delegate.serialize_tuple(len) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + self.delegate.serialize_tuple_struct(name, len) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + self.delegate + .serialize_tuple_variant(name, variant_index, variant, len) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + self.delegate.serialize_map(len) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + self.delegate.serialize_struct(name, len) + } + + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + self.delegate + .serialize_struct_variant(name, variant_index, variant, len) + } + + fn collect_seq<I>(self, iter: I) -> Result<Self::Ok, Self::Error> + where + I: IntoIterator, + I::Item: Serialize, + { + self.delegate.collect_seq(iter) + } + + fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error> + where + K: Serialize, + V: Serialize, + I: IntoIterator<Item = (K, V)>, + { + self.delegate.collect_map(iter) + } + + fn collect_str<T>(self, value: &T) -> Result<Self::Ok, Self::Error> + where + T: ?Sized + Display, + { + self.out.set(Some(value.to_string())); + self.delegate.collect_str(value) + } + + fn is_human_readable(&self) -> bool { + self.delegate.is_human_readable() + } +} diff --git a/third_party/rust/serde_path_to_error/src/wrap.rs b/third_party/rust/serde_path_to_error/src/wrap.rs new file mode 100644 index 0000000000..d730995a71 --- /dev/null +++ b/third_party/rust/serde_path_to_error/src/wrap.rs @@ -0,0 +1,35 @@ +use crate::{Chain, Track}; + +// Wrapper that attaches context to a `Visitor`, `SeqAccess` or `EnumAccess`. +pub struct Wrap<'a, 'b, X> { + pub(crate) delegate: X, + pub(crate) chain: &'a Chain<'a>, + pub(crate) track: &'b Track, +} + +// Wrapper that attaches context to a `VariantAccess`. +pub struct WrapVariant<'a, 'b, X> { + pub(crate) delegate: X, + pub(crate) chain: Chain<'a>, + pub(crate) track: &'b Track, +} + +impl<'a, 'b, X> Wrap<'a, 'b, X> { + pub(crate) fn new(delegate: X, chain: &'a Chain<'a>, track: &'b Track) -> Self { + Wrap { + delegate, + chain, + track, + } + } +} + +impl<'a, 'b, X> WrapVariant<'a, 'b, X> { + pub(crate) fn new(delegate: X, chain: Chain<'a>, track: &'b Track) -> Self { + WrapVariant { + delegate, + chain, + track, + } + } +} diff --git a/third_party/rust/serde_path_to_error/tests/deserialize.rs b/third_party/rust/serde_path_to_error/tests/deserialize.rs new file mode 100644 index 0000000000..faf1219f6f --- /dev/null +++ b/third_party/rust/serde_path_to_error/tests/deserialize.rs @@ -0,0 +1,215 @@ +#![allow(clippy::unreadable_literal, dead_code)] + +use serde::{serde_if_integer128, Deserialize}; +use serde_derive::Deserialize; +use std::collections::BTreeMap as Map; +use std::fmt::Debug; + +fn test<'de, T>(json: &'de str, expected: &str) +where + T: Deserialize<'de> + Debug, +{ + let de = &mut serde_json::Deserializer::from_str(json); + let result: Result<T, _> = serde_path_to_error::deserialize(de); + let path = result.unwrap_err().path().to_string(); + assert_eq!(path, expected); +} + +#[test] +fn test_struct() { + #[derive(Deserialize, Debug)] + struct Package { + name: String, + dependencies: Map<String, Dependency>, + } + + #[derive(Deserialize, Debug)] + struct Dependency { + version: String, + } + + let j = r#"{ + "name": "demo", + "dependencies": { + "serde": { + "version": 1 + } + } + }"#; + + test::<Package>(j, "dependencies.serde.version"); +} + +#[test] +fn test_vec() { + #[derive(Deserialize, Debug)] + struct Package { + dependencies: Vec<Dependency>, + } + + #[derive(Deserialize, Debug)] + struct Dependency { + name: String, + version: String, + } + + let j = r#"{ + "dependencies": [ + { + "name": "serde", + "version": "1.0" + }, + { + "name": "serde_json", + "version": 1 + } + } + }"#; + + test::<Package>(j, "dependencies[1].version"); +} + +#[test] +fn test_option() { + #[derive(Deserialize, Debug)] + struct Package { + dependency: Option<Dependency>, + } + + #[derive(Deserialize, Debug)] + struct Dependency { + version: String, + } + + let j = r#"{ + "dependency": { + "version": 1 + } + }"#; + + test::<Package>(j, "dependency.version"); +} + +#[test] +fn test_struct_variant() { + #[derive(Deserialize, Debug)] + struct Package { + dependency: Dependency, + } + + #[derive(Deserialize, Debug)] + enum Dependency { + Struct { version: String }, + } + + let j = r#"{ + "dependency": { + "Struct": { + "version": 1 + } + } + }"#; + + test::<Package>(j, "dependency.Struct.version"); +} + +#[test] +fn test_tuple_variant() { + #[derive(Deserialize, Debug)] + struct Package { + dependency: Dependency, + } + + #[derive(Deserialize, Debug)] + enum Dependency { + Tuple(String, String), + } + + let j = r#"{ + "dependency": { + "Tuple": ["serde", 1] + } + }"#; + + test::<Package>(j, "dependency.Tuple[1]"); +} + +#[test] +fn test_unknown_field() { + #[derive(Deserialize, Debug)] + struct Package { + dependency: Dependency, + } + + #[derive(Deserialize, Debug)] + #[serde(deny_unknown_fields)] + struct Dependency { + version: String, + } + + let j = r#"{ + "dependency": { + "version": "1.0", + "name": "serde" + } + }"#; + + test::<Package>(j, "dependency.name"); +} + +#[test] +fn test_invalid_length() { + #[derive(Deserialize, Debug)] + struct Package { + dependency: Dependency, + } + + #[derive(Deserialize, Debug)] + struct Dependency(String, String); + + let j = r#"{ + "dependency": ["serde"] + }"#; + + test::<Package>(j, "dependency"); +} + +#[test] +fn test_syntax_error() { + #[derive(Deserialize, Debug)] + struct Package { + dependency: Dependency, + } + + #[derive(Deserialize, Debug)] + struct Dependency { + version: String, + } + + let j = r#"{ + "dependency": { + "error": * + }"#; + + test::<Package>(j, "dependency.error"); +} + +serde_if_integer128! { + #[test] + fn test_u128() { + #[derive(Deserialize, Debug)] + struct Container { + n: u128, + } + + let j = r#"{ + "n": 130033514578017493995102500318550798591 + }"#; + + let de = &mut serde_json::Deserializer::from_str(j); + let container: Container = + serde_path_to_error::deserialize(de).expect("failed to deserialize"); + + assert_eq!(container.n, 130033514578017493995102500318550798591u128); + } +} diff --git a/third_party/rust/serde_path_to_error/tests/serialize.rs b/third_party/rust/serde_path_to_error/tests/serialize.rs new file mode 100644 index 0000000000..26bb3cdf76 --- /dev/null +++ b/third_party/rust/serde_path_to_error/tests/serialize.rs @@ -0,0 +1,48 @@ +use serde::Serialize; +use serde_derive::Serialize; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::fmt::Debug; + +fn test<T>(value: &T, expected: &str) +where + T: ?Sized + Serialize + Debug, +{ + let mut out = Vec::new(); + let ser = &mut serde_json::Serializer::new(&mut out); + let result = serde_path_to_error::serialize(value, ser); + let path = result.unwrap_err().path().to_string(); + assert_eq!(path, expected); +} + +#[test] +fn test_refcell_already_borrowed() { + #[derive(Serialize, Debug)] + struct Outer<'a> { + k: Inner<'a>, + } + + #[derive(Serialize, Debug)] + struct Inner<'a> { + refcell: &'a RefCell<String>, + } + + let refcell = RefCell::new(String::new()); + let outer = Outer { + k: Inner { refcell: &refcell }, + }; + + let _borrowed = refcell.borrow_mut(); + test(&outer, "k.refcell"); +} + +#[test] +fn test_map_nonstring_key() { + let mut inner_map = BTreeMap::new(); + inner_map.insert(b"", 0); + + let mut outer_map = BTreeMap::new(); + outer_map.insert("k", inner_map); + + test(&outer_map, "k"); +} |