├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── src ├── de.rs ├── lib.rs ├── path.rs ├── ser.rs └── wrap.rs └── tests ├── deserialize.rs └── serialize.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: dtolnay 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | schedule: [cron: "40 1 * * *"] 8 | 9 | permissions: 10 | contents: read 11 | 12 | env: 13 | RUSTFLAGS: -Dwarnings 14 | 15 | jobs: 16 | pre_ci: 17 | uses: dtolnay/.github/.github/workflows/pre_ci.yml@master 18 | 19 | test: 20 | name: Rust ${{matrix.rust}} 21 | needs: pre_ci 22 | if: needs.pre_ci.outputs.continue 23 | runs-on: ubuntu-latest 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | rust: [nightly, beta, stable, 1.56.0] 28 | timeout-minutes: 45 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: dtolnay/rust-toolchain@master 32 | with: 33 | toolchain: ${{matrix.rust}} 34 | - name: Enable type layout randomization 35 | run: echo RUSTFLAGS=${RUSTFLAGS}\ -Zrandomize-layout >> $GITHUB_ENV 36 | if: matrix.rust == 'nightly' 37 | - run: cargo test 38 | - uses: actions/upload-artifact@v4 39 | if: matrix.rust == 'nightly' && always() 40 | with: 41 | name: Cargo.lock 42 | path: Cargo.lock 43 | continue-on-error: true 44 | 45 | minimal: 46 | name: Minimal versions 47 | needs: pre_ci 48 | if: needs.pre_ci.outputs.continue 49 | runs-on: ubuntu-latest 50 | timeout-minutes: 45 51 | steps: 52 | - uses: actions/checkout@v4 53 | - uses: dtolnay/rust-toolchain@nightly 54 | - run: cargo generate-lockfile -Z minimal-versions 55 | - run: cargo check --locked 56 | 57 | doc: 58 | name: Documentation 59 | needs: pre_ci 60 | if: needs.pre_ci.outputs.continue 61 | runs-on: ubuntu-latest 62 | timeout-minutes: 45 63 | env: 64 | RUSTDOCFLAGS: -Dwarnings 65 | steps: 66 | - uses: actions/checkout@v4 67 | - uses: dtolnay/rust-toolchain@nightly 68 | - uses: dtolnay/install@cargo-docs-rs 69 | - run: cargo docs-rs 70 | 71 | clippy: 72 | name: Clippy 73 | runs-on: ubuntu-latest 74 | if: github.event_name != 'pull_request' 75 | timeout-minutes: 45 76 | steps: 77 | - uses: actions/checkout@v4 78 | - uses: dtolnay/rust-toolchain@clippy 79 | - run: cargo clippy --tests -- -Dclippy::all -Dclippy::pedantic 80 | 81 | miri: 82 | name: Miri 83 | needs: pre_ci 84 | if: needs.pre_ci.outputs.continue 85 | runs-on: ubuntu-latest 86 | timeout-minutes: 45 87 | steps: 88 | - uses: actions/checkout@v4 89 | - uses: dtolnay/rust-toolchain@miri 90 | with: 91 | toolchain: nightly-2025-05-16 # https://github.com/rust-lang/miri/issues/4323 92 | - run: cargo miri setup 93 | - run: cargo miri test 94 | env: 95 | MIRIFLAGS: -Zmiri-strict-provenance 96 | 97 | outdated: 98 | name: Outdated 99 | runs-on: ubuntu-latest 100 | if: github.event_name != 'pull_request' 101 | timeout-minutes: 45 102 | steps: 103 | - uses: actions/checkout@v4 104 | - uses: dtolnay/rust-toolchain@stable 105 | - uses: dtolnay/install@cargo-outdated 106 | - run: cargo outdated --workspace --exit-code 1 107 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde_path_to_error" 3 | version = "0.1.17" 4 | authors = ["David Tolnay "] 5 | categories = ["encoding"] 6 | description = "Path to the element that failed to deserialize" 7 | documentation = "https://docs.rs/serde_path_to_error" 8 | edition = "2021" 9 | keywords = ["serde", "serialization"] 10 | license = "MIT OR Apache-2.0" 11 | repository = "https://github.com/dtolnay/path-to-error" 12 | rust-version = "1.56" 13 | 14 | [dependencies] 15 | itoa = "1.0" 16 | serde = "1.0.194" 17 | 18 | [dev-dependencies] 19 | serde_derive = "1.0.194" 20 | serde_json = "1.0.100" 21 | 22 | [package.metadata.docs.rs] 23 | targets = ["x86_64-unknown-linux-gnu"] 24 | rustdoc-args = [ 25 | "--generate-link-to-definition", 26 | "--extern-html-root-url=core=https://doc.rust-lang.org", 27 | "--extern-html-root-url=alloc=https://doc.rust-lang.org", 28 | "--extern-html-root-url=std=https://doc.rust-lang.org", 29 | ] 30 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Serde path to error 2 | 3 | [github](https://github.com/dtolnay/path-to-error) 4 | [crates.io](https://crates.io/crates/serde_path_to_error) 5 | [docs.rs](https://docs.rs/serde_path_to_error) 6 | [build status](https://github.com/dtolnay/path-to-error/actions?query=branch%3Amaster) 7 | 8 | Find out the path at which a deserialization error occurred. This crate provides 9 | a wrapper that works with any existing Serde `Deserializer` and exposes the 10 | chain of field names leading to the error. 11 | 12 | ```toml 13 | [dependencies] 14 | serde = "1.0" 15 | serde_path_to_error = "0.1" 16 | ``` 17 | 18 | ```rust 19 | use serde::Deserialize; 20 | use std::collections::BTreeMap as Map; 21 | 22 | #[derive(Deserialize)] 23 | struct Package { 24 | name: String, 25 | dependencies: Map, 26 | } 27 | 28 | #[derive(Deserialize)] 29 | struct Dependency { 30 | version: String, 31 | } 32 | 33 | fn main() { 34 | let j = r#"{ 35 | "name": "demo", 36 | "dependencies": { 37 | "serde": { 38 | "version": 1 39 | } 40 | } 41 | }"#; 42 | 43 | // Some Deserializer. 44 | let jd = &mut serde_json::Deserializer::from_str(j); 45 | 46 | let result: Result = serde_path_to_error::deserialize(jd); 47 | match result { 48 | Ok(_) => panic!("expected a type error"), 49 | Err(err) => { 50 | let path = err.path().to_string(); 51 | assert_eq!(path, "dependencies.serde.version"); 52 | } 53 | } 54 | } 55 | ``` 56 | 57 |
58 | 59 | #### License 60 | 61 | 62 | Licensed under either of Apache License, Version 63 | 2.0 or MIT license at your option. 64 | 65 | 66 |
67 | 68 | 69 | Unless you explicitly state otherwise, any contribution intentionally submitted 70 | for inclusion in this crate by you, as defined in the Apache-2.0 license, shall 71 | be dual licensed as above, without any additional terms or conditions. 72 | 73 | -------------------------------------------------------------------------------- /src/de.rs: -------------------------------------------------------------------------------- 1 | use crate::wrap::{Wrap, WrapVariant}; 2 | use crate::{Chain, Error, Track}; 3 | use serde::de::{self, Deserialize, DeserializeSeed, Visitor}; 4 | use std::fmt; 5 | 6 | /// Entry point. See [crate documentation][crate] for an example. 7 | pub fn deserialize<'de, D, T>(deserializer: D) -> Result> 8 | where 9 | D: de::Deserializer<'de>, 10 | T: Deserialize<'de>, 11 | { 12 | let mut track = Track::new(); 13 | match T::deserialize(Deserializer::new(deserializer, &mut track)) { 14 | Ok(t) => Ok(t), 15 | Err(err) => Err(Error { 16 | path: track.path(), 17 | original: err, 18 | }), 19 | } 20 | } 21 | 22 | /// Deserializer adapter that records path to deserialization errors. 23 | /// 24 | /// # Example 25 | /// 26 | /// ``` 27 | /// # use serde_derive::Deserialize; 28 | /// # 29 | /// use serde::Deserialize; 30 | /// use std::collections::BTreeMap as Map; 31 | /// 32 | /// #[derive(Deserialize)] 33 | /// struct Package { 34 | /// name: String, 35 | /// dependencies: Map, 36 | /// } 37 | /// 38 | /// #[derive(Deserialize)] 39 | /// struct Dependency { 40 | /// version: String, 41 | /// } 42 | /// 43 | /// fn main() { 44 | /// let j = r#"{ 45 | /// "name": "demo", 46 | /// "dependencies": { 47 | /// "serde": { 48 | /// "version": 1 49 | /// } 50 | /// } 51 | /// }"#; 52 | /// 53 | /// // Some Deserializer. 54 | /// let jd = &mut serde_json::Deserializer::from_str(j); 55 | /// 56 | /// let mut track = serde_path_to_error::Track::new(); 57 | /// let pd = serde_path_to_error::Deserializer::new(jd, &mut track); 58 | /// 59 | /// match Package::deserialize(pd) { 60 | /// Ok(_) => panic!("expected a type error"), 61 | /// Err(_) => { 62 | /// let path = track.path().to_string(); 63 | /// assert_eq!(path, "dependencies.serde.version"); 64 | /// } 65 | /// } 66 | /// } 67 | /// ``` 68 | pub struct Deserializer<'a, 'b, D> { 69 | de: D, 70 | chain: Chain<'a>, 71 | track: &'b Track, 72 | } 73 | 74 | impl<'a, 'b, D> Deserializer<'a, 'b, D> { 75 | #[allow(clippy::needless_pass_by_ref_mut)] 76 | pub fn new(de: D, track: &'b mut Track) -> Self { 77 | Deserializer { 78 | de, 79 | chain: Chain::Root, 80 | track, 81 | } 82 | } 83 | } 84 | 85 | // Plain old forwarding impl. 86 | impl<'a, 'b, 'de, D> de::Deserializer<'de> for Deserializer<'a, 'b, D> 87 | where 88 | D: de::Deserializer<'de>, 89 | { 90 | type Error = D::Error; 91 | 92 | fn deserialize_any(self, visitor: V) -> Result 93 | where 94 | V: Visitor<'de>, 95 | { 96 | let chain = self.chain; 97 | let track = self.track; 98 | self.de 99 | .deserialize_any(Wrap::new(visitor, &chain, track)) 100 | .map_err(|err| track.trigger(&chain, err)) 101 | } 102 | 103 | fn deserialize_bool(self, visitor: V) -> Result 104 | where 105 | V: Visitor<'de>, 106 | { 107 | let chain = self.chain; 108 | let track = self.track; 109 | self.de 110 | .deserialize_bool(Wrap::new(visitor, &chain, track)) 111 | .map_err(|err| track.trigger(&chain, err)) 112 | } 113 | 114 | fn deserialize_u8(self, visitor: V) -> Result 115 | where 116 | V: Visitor<'de>, 117 | { 118 | let chain = self.chain; 119 | let track = self.track; 120 | self.de 121 | .deserialize_u8(Wrap::new(visitor, &chain, track)) 122 | .map_err(|err| track.trigger(&chain, err)) 123 | } 124 | 125 | fn deserialize_u16(self, visitor: V) -> Result 126 | where 127 | V: Visitor<'de>, 128 | { 129 | let chain = self.chain; 130 | let track = self.track; 131 | self.de 132 | .deserialize_u16(Wrap::new(visitor, &chain, track)) 133 | .map_err(|err| track.trigger(&chain, err)) 134 | } 135 | 136 | fn deserialize_u32(self, visitor: V) -> Result 137 | where 138 | V: Visitor<'de>, 139 | { 140 | let chain = self.chain; 141 | let track = self.track; 142 | self.de 143 | .deserialize_u32(Wrap::new(visitor, &chain, track)) 144 | .map_err(|err| track.trigger(&chain, err)) 145 | } 146 | 147 | fn deserialize_u64(self, visitor: V) -> Result 148 | where 149 | V: Visitor<'de>, 150 | { 151 | let chain = self.chain; 152 | let track = self.track; 153 | self.de 154 | .deserialize_u64(Wrap::new(visitor, &chain, track)) 155 | .map_err(|err| track.trigger(&chain, err)) 156 | } 157 | 158 | fn deserialize_u128(self, visitor: V) -> Result 159 | where 160 | V: Visitor<'de>, 161 | { 162 | let chain = self.chain; 163 | let track = self.track; 164 | self.de 165 | .deserialize_u128(Wrap::new(visitor, &chain, track)) 166 | .map_err(|err| track.trigger(&chain, err)) 167 | } 168 | 169 | fn deserialize_i8(self, visitor: V) -> Result 170 | where 171 | V: Visitor<'de>, 172 | { 173 | let chain = self.chain; 174 | let track = self.track; 175 | self.de 176 | .deserialize_i8(Wrap::new(visitor, &chain, track)) 177 | .map_err(|err| track.trigger(&chain, err)) 178 | } 179 | 180 | fn deserialize_i16(self, visitor: V) -> Result 181 | where 182 | V: Visitor<'de>, 183 | { 184 | let chain = self.chain; 185 | let track = self.track; 186 | self.de 187 | .deserialize_i16(Wrap::new(visitor, &chain, track)) 188 | .map_err(|err| track.trigger(&chain, err)) 189 | } 190 | 191 | fn deserialize_i32(self, visitor: V) -> Result 192 | where 193 | V: Visitor<'de>, 194 | { 195 | let chain = self.chain; 196 | let track = self.track; 197 | self.de 198 | .deserialize_i32(Wrap::new(visitor, &chain, track)) 199 | .map_err(|err| track.trigger(&chain, err)) 200 | } 201 | 202 | fn deserialize_i64(self, visitor: V) -> Result 203 | where 204 | V: Visitor<'de>, 205 | { 206 | let chain = self.chain; 207 | let track = self.track; 208 | self.de 209 | .deserialize_i64(Wrap::new(visitor, &chain, track)) 210 | .map_err(|err| track.trigger(&chain, err)) 211 | } 212 | 213 | fn deserialize_i128(self, visitor: V) -> Result 214 | where 215 | V: Visitor<'de>, 216 | { 217 | let chain = self.chain; 218 | let track = self.track; 219 | self.de 220 | .deserialize_i128(Wrap::new(visitor, &chain, track)) 221 | .map_err(|err| track.trigger(&chain, err)) 222 | } 223 | 224 | fn deserialize_f32(self, visitor: V) -> Result 225 | where 226 | V: Visitor<'de>, 227 | { 228 | let chain = self.chain; 229 | let track = self.track; 230 | self.de 231 | .deserialize_f32(Wrap::new(visitor, &chain, track)) 232 | .map_err(|err| track.trigger(&chain, err)) 233 | } 234 | 235 | fn deserialize_f64(self, visitor: V) -> Result 236 | where 237 | V: Visitor<'de>, 238 | { 239 | let chain = self.chain; 240 | let track = self.track; 241 | self.de 242 | .deserialize_f64(Wrap::new(visitor, &chain, track)) 243 | .map_err(|err| track.trigger(&chain, err)) 244 | } 245 | 246 | fn deserialize_char(self, visitor: V) -> Result 247 | where 248 | V: Visitor<'de>, 249 | { 250 | let chain = self.chain; 251 | let track = self.track; 252 | self.de 253 | .deserialize_char(Wrap::new(visitor, &chain, track)) 254 | .map_err(|err| track.trigger(&chain, err)) 255 | } 256 | 257 | fn deserialize_str(self, visitor: V) -> Result 258 | where 259 | V: Visitor<'de>, 260 | { 261 | let chain = self.chain; 262 | let track = self.track; 263 | self.de 264 | .deserialize_str(Wrap::new(visitor, &chain, track)) 265 | .map_err(|err| track.trigger(&chain, err)) 266 | } 267 | 268 | fn deserialize_string(self, visitor: V) -> Result 269 | where 270 | V: Visitor<'de>, 271 | { 272 | let chain = self.chain; 273 | let track = self.track; 274 | self.de 275 | .deserialize_string(Wrap::new(visitor, &chain, track)) 276 | .map_err(|err| track.trigger(&chain, err)) 277 | } 278 | 279 | fn deserialize_bytes(self, visitor: V) -> Result 280 | where 281 | V: Visitor<'de>, 282 | { 283 | let chain = self.chain; 284 | let track = self.track; 285 | self.de 286 | .deserialize_bytes(Wrap::new(visitor, &chain, track)) 287 | .map_err(|err| track.trigger(&chain, err)) 288 | } 289 | 290 | fn deserialize_byte_buf(self, visitor: V) -> Result 291 | where 292 | V: Visitor<'de>, 293 | { 294 | let chain = self.chain; 295 | let track = self.track; 296 | self.de 297 | .deserialize_byte_buf(Wrap::new(visitor, &chain, track)) 298 | .map_err(|err| track.trigger(&chain, err)) 299 | } 300 | 301 | fn deserialize_option(self, visitor: V) -> Result 302 | where 303 | V: Visitor<'de>, 304 | { 305 | let chain = self.chain; 306 | let track = self.track; 307 | self.de 308 | .deserialize_option(Wrap::new(visitor, &chain, track)) 309 | .map_err(|err| track.trigger(&chain, err)) 310 | } 311 | 312 | fn deserialize_unit(self, visitor: V) -> Result 313 | where 314 | V: Visitor<'de>, 315 | { 316 | let chain = self.chain; 317 | let track = self.track; 318 | self.de 319 | .deserialize_unit(Wrap::new(visitor, &chain, track)) 320 | .map_err(|err| track.trigger(&chain, err)) 321 | } 322 | 323 | fn deserialize_unit_struct( 324 | self, 325 | name: &'static str, 326 | visitor: V, 327 | ) -> Result 328 | where 329 | V: Visitor<'de>, 330 | { 331 | let chain = self.chain; 332 | let track = self.track; 333 | self.de 334 | .deserialize_unit_struct(name, Wrap::new(visitor, &chain, track)) 335 | .map_err(|err| track.trigger(&chain, err)) 336 | } 337 | 338 | fn deserialize_newtype_struct( 339 | self, 340 | name: &'static str, 341 | visitor: V, 342 | ) -> Result 343 | where 344 | V: Visitor<'de>, 345 | { 346 | let chain = self.chain; 347 | let track = self.track; 348 | self.de 349 | .deserialize_newtype_struct(name, Wrap::new(visitor, &chain, track)) 350 | .map_err(|err| track.trigger(&chain, err)) 351 | } 352 | 353 | fn deserialize_seq(self, visitor: V) -> Result 354 | where 355 | V: Visitor<'de>, 356 | { 357 | let chain = self.chain; 358 | let track = self.track; 359 | self.de 360 | .deserialize_seq(Wrap::new(visitor, &chain, track)) 361 | .map_err(|err| track.trigger(&chain, err)) 362 | } 363 | 364 | fn deserialize_tuple(self, len: usize, visitor: V) -> Result 365 | where 366 | V: Visitor<'de>, 367 | { 368 | let chain = self.chain; 369 | let track = self.track; 370 | self.de 371 | .deserialize_tuple(len, Wrap::new(visitor, &chain, track)) 372 | .map_err(|err| track.trigger(&chain, err)) 373 | } 374 | 375 | fn deserialize_tuple_struct( 376 | self, 377 | name: &'static str, 378 | len: usize, 379 | visitor: V, 380 | ) -> Result 381 | where 382 | V: Visitor<'de>, 383 | { 384 | let chain = self.chain; 385 | let track = self.track; 386 | self.de 387 | .deserialize_tuple_struct(name, len, Wrap::new(visitor, &chain, track)) 388 | .map_err(|err| track.trigger(&chain, err)) 389 | } 390 | 391 | fn deserialize_map(self, visitor: V) -> Result 392 | where 393 | V: Visitor<'de>, 394 | { 395 | let chain = self.chain; 396 | let track = self.track; 397 | self.de 398 | .deserialize_map(Wrap::new(visitor, &chain, track)) 399 | .map_err(|err| track.trigger(&chain, err)) 400 | } 401 | 402 | fn deserialize_struct( 403 | self, 404 | name: &'static str, 405 | fields: &'static [&'static str], 406 | visitor: V, 407 | ) -> Result 408 | where 409 | V: Visitor<'de>, 410 | { 411 | let chain = self.chain; 412 | let track = self.track; 413 | self.de 414 | .deserialize_struct(name, fields, Wrap::new(visitor, &chain, track)) 415 | .map_err(|err| track.trigger(&chain, err)) 416 | } 417 | 418 | fn deserialize_enum( 419 | self, 420 | name: &'static str, 421 | variants: &'static [&'static str], 422 | visitor: V, 423 | ) -> Result 424 | where 425 | V: Visitor<'de>, 426 | { 427 | let chain = self.chain; 428 | let track = self.track; 429 | self.de 430 | .deserialize_enum(name, variants, Wrap::new(visitor, &chain, track)) 431 | .map_err(|err| track.trigger(&chain, err)) 432 | } 433 | 434 | fn deserialize_ignored_any(self, visitor: V) -> Result 435 | where 436 | V: Visitor<'de>, 437 | { 438 | let chain = self.chain; 439 | let track = self.track; 440 | self.de 441 | .deserialize_ignored_any(Wrap::new(visitor, &chain, track)) 442 | .map_err(|err| track.trigger(&chain, err)) 443 | } 444 | 445 | fn deserialize_identifier(self, visitor: V) -> Result 446 | where 447 | V: Visitor<'de>, 448 | { 449 | let chain = self.chain; 450 | let track = self.track; 451 | self.de 452 | .deserialize_identifier(Wrap::new(visitor, &chain, track)) 453 | .map_err(|err| track.trigger(&chain, err)) 454 | } 455 | 456 | fn is_human_readable(&self) -> bool { 457 | self.de.is_human_readable() 458 | } 459 | } 460 | 461 | // Forwarding impl to preserve context. 462 | impl<'a, 'b, 'de, X> Visitor<'de> for Wrap<'a, 'b, X> 463 | where 464 | X: Visitor<'de>, 465 | { 466 | type Value = X::Value; 467 | 468 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 469 | self.delegate.expecting(formatter) 470 | } 471 | 472 | fn visit_bool(self, v: bool) -> Result 473 | where 474 | E: de::Error, 475 | { 476 | let chain = self.chain; 477 | let track = self.track; 478 | self.delegate 479 | .visit_bool(v) 480 | .map_err(|err| track.trigger(chain, err)) 481 | } 482 | 483 | fn visit_i8(self, v: i8) -> Result 484 | where 485 | E: de::Error, 486 | { 487 | let chain = self.chain; 488 | let track = self.track; 489 | self.delegate 490 | .visit_i8(v) 491 | .map_err(|err| track.trigger(chain, err)) 492 | } 493 | 494 | fn visit_i16(self, v: i16) -> Result 495 | where 496 | E: de::Error, 497 | { 498 | let chain = self.chain; 499 | let track = self.track; 500 | self.delegate 501 | .visit_i16(v) 502 | .map_err(|err| track.trigger(chain, err)) 503 | } 504 | 505 | fn visit_i32(self, v: i32) -> Result 506 | where 507 | E: de::Error, 508 | { 509 | let chain = self.chain; 510 | let track = self.track; 511 | self.delegate 512 | .visit_i32(v) 513 | .map_err(|err| track.trigger(chain, err)) 514 | } 515 | 516 | fn visit_i64(self, v: i64) -> Result 517 | where 518 | E: de::Error, 519 | { 520 | let chain = self.chain; 521 | let track = self.track; 522 | self.delegate 523 | .visit_i64(v) 524 | .map_err(|err| track.trigger(chain, err)) 525 | } 526 | 527 | fn visit_i128(self, v: i128) -> Result 528 | where 529 | E: de::Error, 530 | { 531 | let chain = self.chain; 532 | let track = self.track; 533 | self.delegate 534 | .visit_i128(v) 535 | .map_err(|err| track.trigger(chain, err)) 536 | } 537 | 538 | fn visit_u8(self, v: u8) -> Result 539 | where 540 | E: de::Error, 541 | { 542 | let chain = self.chain; 543 | let track = self.track; 544 | self.delegate 545 | .visit_u8(v) 546 | .map_err(|err| track.trigger(chain, err)) 547 | } 548 | 549 | fn visit_u16(self, v: u16) -> Result 550 | where 551 | E: de::Error, 552 | { 553 | let chain = self.chain; 554 | let track = self.track; 555 | self.delegate 556 | .visit_u16(v) 557 | .map_err(|err| track.trigger(chain, err)) 558 | } 559 | 560 | fn visit_u32(self, v: u32) -> Result 561 | where 562 | E: de::Error, 563 | { 564 | let chain = self.chain; 565 | let track = self.track; 566 | self.delegate 567 | .visit_u32(v) 568 | .map_err(|err| track.trigger(chain, err)) 569 | } 570 | 571 | fn visit_u64(self, v: u64) -> Result 572 | where 573 | E: de::Error, 574 | { 575 | let chain = self.chain; 576 | let track = self.track; 577 | self.delegate 578 | .visit_u64(v) 579 | .map_err(|err| track.trigger(chain, err)) 580 | } 581 | 582 | fn visit_u128(self, v: u128) -> Result 583 | where 584 | E: de::Error, 585 | { 586 | let chain = self.chain; 587 | let track = self.track; 588 | self.delegate 589 | .visit_u128(v) 590 | .map_err(|err| track.trigger(chain, err)) 591 | } 592 | 593 | fn visit_f32(self, v: f32) -> Result 594 | where 595 | E: de::Error, 596 | { 597 | let chain = self.chain; 598 | let track = self.track; 599 | self.delegate 600 | .visit_f32(v) 601 | .map_err(|err| track.trigger(chain, err)) 602 | } 603 | 604 | fn visit_f64(self, v: f64) -> Result 605 | where 606 | E: de::Error, 607 | { 608 | let chain = self.chain; 609 | let track = self.track; 610 | self.delegate 611 | .visit_f64(v) 612 | .map_err(|err| track.trigger(chain, err)) 613 | } 614 | 615 | fn visit_char(self, v: char) -> Result 616 | where 617 | E: de::Error, 618 | { 619 | let chain = self.chain; 620 | let track = self.track; 621 | self.delegate 622 | .visit_char(v) 623 | .map_err(|err| track.trigger(chain, err)) 624 | } 625 | 626 | fn visit_str(self, v: &str) -> Result 627 | where 628 | E: de::Error, 629 | { 630 | let chain = self.chain; 631 | let track = self.track; 632 | self.delegate 633 | .visit_str(v) 634 | .map_err(|err| track.trigger(chain, err)) 635 | } 636 | 637 | fn visit_borrowed_str(self, v: &'de str) -> Result 638 | where 639 | E: de::Error, 640 | { 641 | let chain = self.chain; 642 | let track = self.track; 643 | self.delegate 644 | .visit_borrowed_str(v) 645 | .map_err(|err| track.trigger(chain, err)) 646 | } 647 | 648 | fn visit_string(self, v: String) -> Result 649 | where 650 | E: de::Error, 651 | { 652 | let chain = self.chain; 653 | let track = self.track; 654 | self.delegate 655 | .visit_string(v) 656 | .map_err(|err| track.trigger(chain, err)) 657 | } 658 | 659 | fn visit_unit(self) -> Result 660 | where 661 | E: de::Error, 662 | { 663 | let chain = self.chain; 664 | let track = self.track; 665 | self.delegate 666 | .visit_unit() 667 | .map_err(|err| track.trigger(chain, err)) 668 | } 669 | 670 | fn visit_none(self) -> Result 671 | where 672 | E: de::Error, 673 | { 674 | let chain = self.chain; 675 | let track = self.track; 676 | self.delegate 677 | .visit_none() 678 | .map_err(|err| track.trigger(chain, err)) 679 | } 680 | 681 | fn visit_some(self, deserializer: D) -> Result 682 | where 683 | D: de::Deserializer<'de>, 684 | { 685 | let chain = self.chain; 686 | let track = self.track; 687 | self.delegate 688 | .visit_some(Deserializer { 689 | de: deserializer, 690 | chain: Chain::Some { parent: chain }, 691 | track, 692 | }) 693 | .map_err(|err| track.trigger(chain, err)) 694 | } 695 | 696 | fn visit_newtype_struct(self, deserializer: D) -> Result 697 | where 698 | D: de::Deserializer<'de>, 699 | { 700 | let chain = self.chain; 701 | let track = self.track; 702 | self.delegate 703 | .visit_newtype_struct(Deserializer { 704 | de: deserializer, 705 | chain: Chain::NewtypeStruct { parent: chain }, 706 | track, 707 | }) 708 | .map_err(|err| track.trigger(chain, err)) 709 | } 710 | 711 | fn visit_seq(self, visitor: V) -> Result 712 | where 713 | V: de::SeqAccess<'de>, 714 | { 715 | let chain = self.chain; 716 | let track = self.track; 717 | self.delegate 718 | .visit_seq(SeqAccess::new(visitor, chain, track)) 719 | .map_err(|err| track.trigger(chain, err)) 720 | } 721 | 722 | fn visit_map(self, visitor: V) -> Result 723 | where 724 | V: de::MapAccess<'de>, 725 | { 726 | let chain = self.chain; 727 | let track = self.track; 728 | self.delegate 729 | .visit_map(MapAccess::new(visitor, chain, track)) 730 | .map_err(|err| track.trigger(chain, err)) 731 | } 732 | 733 | fn visit_enum(self, visitor: V) -> Result 734 | where 735 | V: de::EnumAccess<'de>, 736 | { 737 | let chain = self.chain; 738 | let track = self.track; 739 | self.delegate 740 | .visit_enum(Wrap::new(visitor, chain, track)) 741 | .map_err(|err| track.trigger(chain, err)) 742 | } 743 | 744 | fn visit_bytes(self, v: &[u8]) -> Result 745 | where 746 | E: de::Error, 747 | { 748 | let chain = self.chain; 749 | let track = self.track; 750 | self.delegate 751 | .visit_bytes(v) 752 | .map_err(|err| track.trigger(chain, err)) 753 | } 754 | 755 | fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result 756 | where 757 | E: de::Error, 758 | { 759 | let chain = self.chain; 760 | let track = self.track; 761 | self.delegate 762 | .visit_borrowed_bytes(v) 763 | .map_err(|err| track.trigger(chain, err)) 764 | } 765 | 766 | fn visit_byte_buf(self, v: Vec) -> Result 767 | where 768 | E: de::Error, 769 | { 770 | let chain = self.chain; 771 | let track = self.track; 772 | self.delegate 773 | .visit_byte_buf(v) 774 | .map_err(|err| track.trigger(chain, err)) 775 | } 776 | } 777 | 778 | // Forwarding impl to preserve context. 779 | impl<'a, 'b, 'de, X> de::EnumAccess<'de> for Wrap<'a, 'b, X> 780 | where 781 | X: de::EnumAccess<'de> + 'a, 782 | { 783 | type Error = X::Error; 784 | type Variant = WrapVariant<'a, 'b, X::Variant>; 785 | 786 | fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), X::Error> 787 | where 788 | V: DeserializeSeed<'de>, 789 | { 790 | let chain = self.chain; 791 | let track = self.track; 792 | let mut variant = None; 793 | self.delegate 794 | .variant_seed(CaptureKey::new(seed, &mut variant)) 795 | .map_err(|err| track.trigger(chain, err)) 796 | .map(move |(v, vis)| { 797 | let chain = match variant { 798 | Some(variant) => Chain::Enum { 799 | parent: chain, 800 | variant, 801 | }, 802 | None => Chain::NonStringKey { parent: chain }, 803 | }; 804 | (v, WrapVariant::new(vis, chain, track)) 805 | }) 806 | } 807 | } 808 | 809 | // Forwarding impl to preserve context. 810 | impl<'a, 'b, 'de, X> de::VariantAccess<'de> for WrapVariant<'a, 'b, X> 811 | where 812 | X: de::VariantAccess<'de>, 813 | { 814 | type Error = X::Error; 815 | 816 | fn unit_variant(self) -> Result<(), X::Error> { 817 | let chain = self.chain; 818 | let track = self.track; 819 | self.delegate 820 | .unit_variant() 821 | .map_err(|err| track.trigger(&chain, err)) 822 | } 823 | 824 | fn newtype_variant_seed(self, seed: T) -> Result 825 | where 826 | T: DeserializeSeed<'de>, 827 | { 828 | let chain = self.chain; 829 | let track = self.track; 830 | let nested = Chain::NewtypeVariant { parent: &chain }; 831 | self.delegate 832 | .newtype_variant_seed(TrackedSeed::new(seed, nested, track)) 833 | .map_err(|err| track.trigger(&chain, err)) 834 | } 835 | 836 | fn tuple_variant(self, len: usize, visitor: V) -> Result 837 | where 838 | V: Visitor<'de>, 839 | { 840 | let chain = self.chain; 841 | let track = self.track; 842 | self.delegate 843 | .tuple_variant(len, Wrap::new(visitor, &chain, track)) 844 | .map_err(|err| track.trigger(&chain, err)) 845 | } 846 | 847 | fn struct_variant( 848 | self, 849 | fields: &'static [&'static str], 850 | visitor: V, 851 | ) -> Result 852 | where 853 | V: Visitor<'de>, 854 | { 855 | let chain = self.chain; 856 | let track = self.track; 857 | self.delegate 858 | .struct_variant(fields, Wrap::new(visitor, &chain, track)) 859 | .map_err(|err| track.trigger(&chain, err)) 860 | } 861 | } 862 | 863 | // Seed that saves the string into the given optional during `visit_str` and 864 | // `visit_string`. 865 | struct CaptureKey<'a, X> { 866 | delegate: X, 867 | key: &'a mut Option, 868 | } 869 | 870 | impl<'a, X> CaptureKey<'a, X> { 871 | fn new(delegate: X, key: &'a mut Option) -> Self { 872 | CaptureKey { delegate, key } 873 | } 874 | } 875 | 876 | // Forwarding impl. 877 | impl<'a, 'de, X> DeserializeSeed<'de> for CaptureKey<'a, X> 878 | where 879 | X: DeserializeSeed<'de>, 880 | { 881 | type Value = X::Value; 882 | 883 | fn deserialize(self, deserializer: D) -> Result 884 | where 885 | D: de::Deserializer<'de>, 886 | { 887 | self.delegate 888 | .deserialize(CaptureKey::new(deserializer, self.key)) 889 | } 890 | } 891 | 892 | // Forwarding impl. 893 | impl<'a, 'de, X> de::Deserializer<'de> for CaptureKey<'a, X> 894 | where 895 | X: de::Deserializer<'de>, 896 | { 897 | type Error = X::Error; 898 | 899 | fn deserialize_any(self, visitor: V) -> Result 900 | where 901 | V: Visitor<'de>, 902 | { 903 | self.delegate 904 | .deserialize_any(CaptureKey::new(visitor, self.key)) 905 | } 906 | 907 | fn deserialize_bool(self, visitor: V) -> Result 908 | where 909 | V: Visitor<'de>, 910 | { 911 | self.delegate 912 | .deserialize_bool(CaptureKey::new(visitor, self.key)) 913 | } 914 | 915 | fn deserialize_u8(self, visitor: V) -> Result 916 | where 917 | V: Visitor<'de>, 918 | { 919 | self.delegate 920 | .deserialize_u8(CaptureKey::new(visitor, self.key)) 921 | } 922 | 923 | fn deserialize_u16(self, visitor: V) -> Result 924 | where 925 | V: Visitor<'de>, 926 | { 927 | self.delegate 928 | .deserialize_u16(CaptureKey::new(visitor, self.key)) 929 | } 930 | 931 | fn deserialize_u32(self, visitor: V) -> Result 932 | where 933 | V: Visitor<'de>, 934 | { 935 | self.delegate 936 | .deserialize_u32(CaptureKey::new(visitor, self.key)) 937 | } 938 | 939 | fn deserialize_u64(self, visitor: V) -> Result 940 | where 941 | V: Visitor<'de>, 942 | { 943 | self.delegate 944 | .deserialize_u64(CaptureKey::new(visitor, self.key)) 945 | } 946 | 947 | fn deserialize_u128(self, visitor: V) -> Result 948 | where 949 | V: Visitor<'de>, 950 | { 951 | self.delegate 952 | .deserialize_u128(CaptureKey::new(visitor, self.key)) 953 | } 954 | 955 | fn deserialize_i8(self, visitor: V) -> Result 956 | where 957 | V: Visitor<'de>, 958 | { 959 | self.delegate 960 | .deserialize_i8(CaptureKey::new(visitor, self.key)) 961 | } 962 | 963 | fn deserialize_i16(self, visitor: V) -> Result 964 | where 965 | V: Visitor<'de>, 966 | { 967 | self.delegate 968 | .deserialize_i16(CaptureKey::new(visitor, self.key)) 969 | } 970 | 971 | fn deserialize_i32(self, visitor: V) -> Result 972 | where 973 | V: Visitor<'de>, 974 | { 975 | self.delegate 976 | .deserialize_i32(CaptureKey::new(visitor, self.key)) 977 | } 978 | 979 | fn deserialize_i64(self, visitor: V) -> Result 980 | where 981 | V: Visitor<'de>, 982 | { 983 | self.delegate 984 | .deserialize_i64(CaptureKey::new(visitor, self.key)) 985 | } 986 | 987 | fn deserialize_i128(self, visitor: V) -> Result 988 | where 989 | V: Visitor<'de>, 990 | { 991 | self.delegate 992 | .deserialize_i128(CaptureKey::new(visitor, self.key)) 993 | } 994 | 995 | fn deserialize_f32(self, visitor: V) -> Result 996 | where 997 | V: Visitor<'de>, 998 | { 999 | self.delegate 1000 | .deserialize_f32(CaptureKey::new(visitor, self.key)) 1001 | } 1002 | 1003 | fn deserialize_f64(self, visitor: V) -> Result 1004 | where 1005 | V: Visitor<'de>, 1006 | { 1007 | self.delegate 1008 | .deserialize_f64(CaptureKey::new(visitor, self.key)) 1009 | } 1010 | 1011 | fn deserialize_char(self, visitor: V) -> Result 1012 | where 1013 | V: Visitor<'de>, 1014 | { 1015 | self.delegate 1016 | .deserialize_char(CaptureKey::new(visitor, self.key)) 1017 | } 1018 | 1019 | fn deserialize_str(self, visitor: V) -> Result 1020 | where 1021 | V: Visitor<'de>, 1022 | { 1023 | self.delegate 1024 | .deserialize_str(CaptureKey::new(visitor, self.key)) 1025 | } 1026 | 1027 | fn deserialize_string(self, visitor: V) -> Result 1028 | where 1029 | V: Visitor<'de>, 1030 | { 1031 | self.delegate 1032 | .deserialize_string(CaptureKey::new(visitor, self.key)) 1033 | } 1034 | 1035 | fn deserialize_bytes(self, visitor: V) -> Result 1036 | where 1037 | V: Visitor<'de>, 1038 | { 1039 | self.delegate 1040 | .deserialize_bytes(CaptureKey::new(visitor, self.key)) 1041 | } 1042 | 1043 | fn deserialize_byte_buf(self, visitor: V) -> Result 1044 | where 1045 | V: Visitor<'de>, 1046 | { 1047 | self.delegate 1048 | .deserialize_byte_buf(CaptureKey::new(visitor, self.key)) 1049 | } 1050 | 1051 | fn deserialize_option(self, visitor: V) -> Result 1052 | where 1053 | V: Visitor<'de>, 1054 | { 1055 | self.delegate 1056 | .deserialize_option(CaptureKey::new(visitor, self.key)) 1057 | } 1058 | 1059 | fn deserialize_unit(self, visitor: V) -> Result 1060 | where 1061 | V: Visitor<'de>, 1062 | { 1063 | self.delegate 1064 | .deserialize_unit(CaptureKey::new(visitor, self.key)) 1065 | } 1066 | 1067 | fn deserialize_unit_struct( 1068 | self, 1069 | name: &'static str, 1070 | visitor: V, 1071 | ) -> Result 1072 | where 1073 | V: Visitor<'de>, 1074 | { 1075 | self.delegate 1076 | .deserialize_unit_struct(name, CaptureKey::new(visitor, self.key)) 1077 | } 1078 | 1079 | fn deserialize_newtype_struct( 1080 | self, 1081 | name: &'static str, 1082 | visitor: V, 1083 | ) -> Result 1084 | where 1085 | V: Visitor<'de>, 1086 | { 1087 | self.delegate 1088 | .deserialize_newtype_struct(name, CaptureKey::new(visitor, self.key)) 1089 | } 1090 | 1091 | fn deserialize_seq(self, visitor: V) -> Result 1092 | where 1093 | V: Visitor<'de>, 1094 | { 1095 | self.delegate 1096 | .deserialize_seq(CaptureKey::new(visitor, self.key)) 1097 | } 1098 | 1099 | fn deserialize_tuple(self, len: usize, visitor: V) -> Result 1100 | where 1101 | V: Visitor<'de>, 1102 | { 1103 | self.delegate 1104 | .deserialize_tuple(len, CaptureKey::new(visitor, self.key)) 1105 | } 1106 | 1107 | fn deserialize_tuple_struct( 1108 | self, 1109 | name: &'static str, 1110 | len: usize, 1111 | visitor: V, 1112 | ) -> Result 1113 | where 1114 | V: Visitor<'de>, 1115 | { 1116 | self.delegate 1117 | .deserialize_tuple_struct(name, len, CaptureKey::new(visitor, self.key)) 1118 | } 1119 | 1120 | fn deserialize_map(self, visitor: V) -> Result 1121 | where 1122 | V: Visitor<'de>, 1123 | { 1124 | self.delegate 1125 | .deserialize_map(CaptureKey::new(visitor, self.key)) 1126 | } 1127 | 1128 | fn deserialize_struct( 1129 | self, 1130 | name: &'static str, 1131 | fields: &'static [&'static str], 1132 | visitor: V, 1133 | ) -> Result 1134 | where 1135 | V: Visitor<'de>, 1136 | { 1137 | self.delegate 1138 | .deserialize_struct(name, fields, CaptureKey::new(visitor, self.key)) 1139 | } 1140 | 1141 | fn deserialize_enum( 1142 | self, 1143 | name: &'static str, 1144 | variants: &'static [&'static str], 1145 | visitor: V, 1146 | ) -> Result 1147 | where 1148 | V: Visitor<'de>, 1149 | { 1150 | self.delegate 1151 | .deserialize_enum(name, variants, CaptureKey::new(visitor, self.key)) 1152 | } 1153 | 1154 | fn deserialize_ignored_any(self, visitor: V) -> Result 1155 | where 1156 | V: Visitor<'de>, 1157 | { 1158 | self.delegate 1159 | .deserialize_ignored_any(CaptureKey::new(visitor, self.key)) 1160 | } 1161 | 1162 | fn deserialize_identifier(self, visitor: V) -> Result 1163 | where 1164 | V: Visitor<'de>, 1165 | { 1166 | self.delegate 1167 | .deserialize_identifier(CaptureKey::new(visitor, self.key)) 1168 | } 1169 | 1170 | fn is_human_readable(&self) -> bool { 1171 | self.delegate.is_human_readable() 1172 | } 1173 | } 1174 | 1175 | // Forwarding impl except `visit_str` and `visit_string` which save the string. 1176 | impl<'a, 'de, X> Visitor<'de> for CaptureKey<'a, X> 1177 | where 1178 | X: Visitor<'de>, 1179 | { 1180 | type Value = X::Value; 1181 | 1182 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1183 | self.delegate.expecting(formatter) 1184 | } 1185 | 1186 | fn visit_bool(self, v: bool) -> Result 1187 | where 1188 | E: de::Error, 1189 | { 1190 | let string = if v { "true" } else { "false" }; 1191 | *self.key = Some(string.to_owned()); 1192 | self.delegate.visit_bool(v) 1193 | } 1194 | 1195 | fn visit_i8(self, v: i8) -> Result 1196 | where 1197 | E: de::Error, 1198 | { 1199 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1200 | self.delegate.visit_i8(v) 1201 | } 1202 | 1203 | fn visit_i16(self, v: i16) -> Result 1204 | where 1205 | E: de::Error, 1206 | { 1207 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1208 | self.delegate.visit_i16(v) 1209 | } 1210 | 1211 | fn visit_i32(self, v: i32) -> Result 1212 | where 1213 | E: de::Error, 1214 | { 1215 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1216 | self.delegate.visit_i32(v) 1217 | } 1218 | 1219 | fn visit_i64(self, v: i64) -> Result 1220 | where 1221 | E: de::Error, 1222 | { 1223 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1224 | self.delegate.visit_i64(v) 1225 | } 1226 | 1227 | fn visit_i128(self, v: i128) -> Result 1228 | where 1229 | E: de::Error, 1230 | { 1231 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1232 | self.delegate.visit_i128(v) 1233 | } 1234 | 1235 | fn visit_u8(self, v: u8) -> Result 1236 | where 1237 | E: de::Error, 1238 | { 1239 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1240 | self.delegate.visit_u8(v) 1241 | } 1242 | 1243 | fn visit_u16(self, v: u16) -> Result 1244 | where 1245 | E: de::Error, 1246 | { 1247 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1248 | self.delegate.visit_u16(v) 1249 | } 1250 | 1251 | fn visit_u32(self, v: u32) -> Result 1252 | where 1253 | E: de::Error, 1254 | { 1255 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1256 | self.delegate.visit_u32(v) 1257 | } 1258 | 1259 | fn visit_u64(self, v: u64) -> Result 1260 | where 1261 | E: de::Error, 1262 | { 1263 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1264 | self.delegate.visit_u64(v) 1265 | } 1266 | 1267 | fn visit_u128(self, v: u128) -> Result 1268 | where 1269 | E: de::Error, 1270 | { 1271 | *self.key = Some(itoa::Buffer::new().format(v).to_owned()); 1272 | self.delegate.visit_u128(v) 1273 | } 1274 | 1275 | fn visit_f32(self, v: f32) -> Result 1276 | where 1277 | E: de::Error, 1278 | { 1279 | self.delegate.visit_f32(v) 1280 | } 1281 | 1282 | fn visit_f64(self, v: f64) -> Result 1283 | where 1284 | E: de::Error, 1285 | { 1286 | self.delegate.visit_f64(v) 1287 | } 1288 | 1289 | fn visit_char(self, v: char) -> Result 1290 | where 1291 | E: de::Error, 1292 | { 1293 | self.delegate.visit_char(v) 1294 | } 1295 | 1296 | fn visit_str(self, v: &str) -> Result 1297 | where 1298 | E: de::Error, 1299 | { 1300 | *self.key = Some(v.to_owned()); 1301 | self.delegate.visit_str(v) 1302 | } 1303 | 1304 | fn visit_borrowed_str(self, v: &'de str) -> Result 1305 | where 1306 | E: de::Error, 1307 | { 1308 | *self.key = Some(v.to_owned()); 1309 | self.delegate.visit_borrowed_str(v) 1310 | } 1311 | 1312 | fn visit_string(self, v: String) -> Result 1313 | where 1314 | E: de::Error, 1315 | { 1316 | *self.key = Some(v.clone()); 1317 | self.delegate.visit_string(v) 1318 | } 1319 | 1320 | fn visit_unit(self) -> Result 1321 | where 1322 | E: de::Error, 1323 | { 1324 | self.delegate.visit_unit() 1325 | } 1326 | 1327 | fn visit_none(self) -> Result 1328 | where 1329 | E: de::Error, 1330 | { 1331 | self.delegate.visit_none() 1332 | } 1333 | 1334 | fn visit_some(self, deserializer: D) -> Result 1335 | where 1336 | D: de::Deserializer<'de>, 1337 | { 1338 | self.delegate.visit_some(deserializer) 1339 | } 1340 | 1341 | fn visit_newtype_struct(self, deserializer: D) -> Result 1342 | where 1343 | D: de::Deserializer<'de>, 1344 | { 1345 | self.delegate.visit_newtype_struct(deserializer) 1346 | } 1347 | 1348 | fn visit_seq(self, visitor: V) -> Result 1349 | where 1350 | V: de::SeqAccess<'de>, 1351 | { 1352 | self.delegate.visit_seq(visitor) 1353 | } 1354 | 1355 | fn visit_map(self, visitor: V) -> Result 1356 | where 1357 | V: de::MapAccess<'de>, 1358 | { 1359 | self.delegate.visit_map(visitor) 1360 | } 1361 | 1362 | fn visit_enum(self, visitor: V) -> Result 1363 | where 1364 | V: de::EnumAccess<'de>, 1365 | { 1366 | self.delegate.visit_enum(visitor) 1367 | } 1368 | 1369 | fn visit_bytes(self, v: &[u8]) -> Result 1370 | where 1371 | E: de::Error, 1372 | { 1373 | self.delegate.visit_bytes(v) 1374 | } 1375 | 1376 | fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result 1377 | where 1378 | E: de::Error, 1379 | { 1380 | self.delegate.visit_borrowed_bytes(v) 1381 | } 1382 | 1383 | fn visit_byte_buf(self, v: Vec) -> Result 1384 | where 1385 | E: de::Error, 1386 | { 1387 | self.delegate.visit_byte_buf(v) 1388 | } 1389 | } 1390 | 1391 | // Seed used for map values, sequence elements and newtype variants to track 1392 | // their path. 1393 | struct TrackedSeed<'a, 'b, X> { 1394 | seed: X, 1395 | chain: Chain<'a>, 1396 | track: &'b Track, 1397 | } 1398 | 1399 | impl<'a, 'b, X> TrackedSeed<'a, 'b, X> { 1400 | fn new(seed: X, chain: Chain<'a>, track: &'b Track) -> Self { 1401 | TrackedSeed { seed, chain, track } 1402 | } 1403 | } 1404 | 1405 | impl<'a, 'b, 'de, X> DeserializeSeed<'de> for TrackedSeed<'a, 'b, X> 1406 | where 1407 | X: DeserializeSeed<'de>, 1408 | { 1409 | type Value = X::Value; 1410 | 1411 | fn deserialize(self, deserializer: D) -> Result 1412 | where 1413 | D: de::Deserializer<'de>, 1414 | { 1415 | let chain = self.chain; 1416 | let track = self.track; 1417 | self.seed 1418 | .deserialize(Deserializer { 1419 | de: deserializer, 1420 | chain: chain.clone(), 1421 | track, 1422 | }) 1423 | .map_err(|err| track.trigger(&chain, err)) 1424 | } 1425 | } 1426 | 1427 | // Seq visitor that tracks the index of its elements. 1428 | struct SeqAccess<'a, 'b, X> { 1429 | delegate: X, 1430 | chain: &'a Chain<'a>, 1431 | index: usize, 1432 | track: &'b Track, 1433 | } 1434 | 1435 | impl<'a, 'b, X> SeqAccess<'a, 'b, X> { 1436 | fn new(delegate: X, chain: &'a Chain<'a>, track: &'b Track) -> Self { 1437 | SeqAccess { 1438 | delegate, 1439 | chain, 1440 | index: 0, 1441 | track, 1442 | } 1443 | } 1444 | } 1445 | 1446 | // Forwarding impl to preserve context. 1447 | impl<'a, 'b, 'de, X> de::SeqAccess<'de> for SeqAccess<'a, 'b, X> 1448 | where 1449 | X: de::SeqAccess<'de>, 1450 | { 1451 | type Error = X::Error; 1452 | 1453 | fn next_element_seed(&mut self, seed: T) -> Result, X::Error> 1454 | where 1455 | T: DeserializeSeed<'de>, 1456 | { 1457 | let parent = self.chain; 1458 | let chain = Chain::Seq { 1459 | parent, 1460 | index: self.index, 1461 | }; 1462 | let track = self.track; 1463 | self.index += 1; 1464 | self.delegate 1465 | .next_element_seed(TrackedSeed::new(seed, chain, track)) 1466 | .map_err(|err| track.trigger(parent, err)) 1467 | } 1468 | 1469 | fn size_hint(&self) -> Option { 1470 | self.delegate.size_hint() 1471 | } 1472 | } 1473 | 1474 | // Map visitor that captures the string value of its keys and uses that to track 1475 | // the path to its values. 1476 | struct MapAccess<'a, 'b, X> { 1477 | delegate: X, 1478 | chain: &'a Chain<'a>, 1479 | key: Option, 1480 | track: &'b Track, 1481 | } 1482 | 1483 | impl<'a, 'b, X> MapAccess<'a, 'b, X> { 1484 | fn new(delegate: X, chain: &'a Chain<'a>, track: &'b Track) -> Self { 1485 | MapAccess { 1486 | delegate, 1487 | chain, 1488 | key: None, 1489 | track, 1490 | } 1491 | } 1492 | } 1493 | 1494 | impl<'a, 'b, 'de, X> de::MapAccess<'de> for MapAccess<'a, 'b, X> 1495 | where 1496 | X: de::MapAccess<'de>, 1497 | { 1498 | type Error = X::Error; 1499 | 1500 | fn next_key_seed(&mut self, seed: K) -> Result, X::Error> 1501 | where 1502 | K: DeserializeSeed<'de>, 1503 | { 1504 | let chain = self.chain; 1505 | let track = self.track; 1506 | let key = &mut self.key; 1507 | self.delegate 1508 | .next_key_seed(CaptureKey::new(seed, key)) 1509 | .map_err(|err| { 1510 | let chain = match key.take() { 1511 | Some(key) => Chain::Map { parent: chain, key }, 1512 | None => Chain::NonStringKey { parent: chain }, 1513 | }; 1514 | track.trigger(&chain, err) 1515 | }) 1516 | } 1517 | 1518 | fn next_value_seed(&mut self, seed: V) -> Result 1519 | where 1520 | V: DeserializeSeed<'de>, 1521 | { 1522 | let parent = self.chain; 1523 | let chain = match self.key.take() { 1524 | Some(key) => Chain::Map { parent, key }, 1525 | None => Chain::NonStringKey { parent }, 1526 | }; 1527 | let track = self.track; 1528 | self.delegate 1529 | .next_value_seed(TrackedSeed::new(seed, chain, track)) 1530 | .map_err(|err| track.trigger(parent, err)) 1531 | } 1532 | 1533 | fn size_hint(&self) -> Option { 1534 | self.delegate.size_hint() 1535 | } 1536 | } 1537 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! [![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) 2 | //! 3 | //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github 4 | //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust 5 | //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs 6 | //! 7 | //!
8 | //! 9 | //! Find out the path at which a deserialization error occurred. This crate 10 | //! provides a wrapper that works with any existing Serde `Deserializer` and 11 | //! exposes the chain of field names leading to the error. 12 | //! 13 | //! # Example 14 | //! 15 | //! ``` 16 | //! # use serde_derive::Deserialize; 17 | //! # 18 | //! use serde::Deserialize; 19 | //! use std::collections::BTreeMap as Map; 20 | //! 21 | //! #[derive(Deserialize)] 22 | //! struct Package { 23 | //! name: String, 24 | //! dependencies: Map, 25 | //! } 26 | //! 27 | //! #[derive(Deserialize)] 28 | //! struct Dependency { 29 | //! version: String, 30 | //! } 31 | //! 32 | //! fn main() { 33 | //! let j = r#"{ 34 | //! "name": "demo", 35 | //! "dependencies": { 36 | //! "serde": { 37 | //! "version": 1 38 | //! } 39 | //! } 40 | //! }"#; 41 | //! 42 | //! // Some Deserializer. 43 | //! let jd = &mut serde_json::Deserializer::from_str(j); 44 | //! 45 | //! let result: Result = serde_path_to_error::deserialize(jd); 46 | //! match result { 47 | //! Ok(_) => panic!("expected a type error"), 48 | //! Err(err) => { 49 | //! let path = err.path().to_string(); 50 | //! assert_eq!(path, "dependencies.serde.version"); 51 | //! } 52 | //! } 53 | //! } 54 | //! ``` 55 | 56 | #![doc(html_root_url = "https://docs.rs/serde_path_to_error/0.1.17")] 57 | #![allow( 58 | clippy::doc_link_with_quotes, // https://github.com/rust-lang/rust-clippy/issues/8961 59 | clippy::elidable_lifetime_names, 60 | clippy::iter_not_returning_iterator, // https://github.com/rust-lang/rust-clippy/issues/8285 61 | clippy::missing_errors_doc, 62 | clippy::module_name_repetitions, 63 | clippy::must_use_candidate, 64 | clippy::needless_lifetimes, 65 | clippy::new_without_default 66 | )] 67 | 68 | mod de; 69 | mod path; 70 | mod ser; 71 | mod wrap; 72 | 73 | use std::cell::Cell; 74 | use std::error::Error as StdError; 75 | use std::fmt::{self, Display}; 76 | 77 | pub use crate::de::{deserialize, Deserializer}; 78 | pub use crate::path::{Path, Segment, Segments}; 79 | pub use crate::ser::{serialize, Serializer}; 80 | 81 | /// Original deserializer error together with the path at which it occurred. 82 | #[derive(Clone, Debug)] 83 | pub struct Error { 84 | path: Path, 85 | original: E, 86 | } 87 | 88 | impl Error { 89 | pub fn new(path: Path, inner: E) -> Self { 90 | Error { 91 | path, 92 | original: inner, 93 | } 94 | } 95 | 96 | /// Element path at which this deserialization error occurred. 97 | pub fn path(&self) -> &Path { 98 | &self.path 99 | } 100 | 101 | /// The Deserializer's underlying error that occurred. 102 | pub fn into_inner(self) -> E { 103 | self.original 104 | } 105 | 106 | /// Reference to the Deserializer's underlying error that occurred. 107 | pub fn inner(&self) -> &E { 108 | &self.original 109 | } 110 | } 111 | 112 | impl Display for Error { 113 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 114 | if !self.path.is_only_unknown() { 115 | write!(f, "{}: ", self.path)?; 116 | } 117 | write!(f, "{}", self.original) 118 | } 119 | } 120 | 121 | impl StdError for Error { 122 | fn source(&self) -> Option<&(dyn StdError + 'static)> { 123 | self.original.source() 124 | } 125 | } 126 | 127 | /// State for bookkeeping across nested deserializer calls. 128 | /// 129 | /// You don't need this if you are using `serde_path_to_error::deserializer`. If 130 | /// you are managing your own `Deserializer`, see the usage example on 131 | /// [`Deserializer`]. 132 | pub struct Track { 133 | path: Cell>, 134 | } 135 | 136 | impl Track { 137 | /// Empty state with no error having happened yet. 138 | pub const fn new() -> Self { 139 | Track { 140 | path: Cell::new(None), 141 | } 142 | } 143 | 144 | /// Gets path at which the error occurred. Only meaningful after we know 145 | /// that an error has occurred. Returns an empty path otherwise. 146 | pub fn path(self) -> Path { 147 | self.path.into_inner().unwrap_or_else(Path::empty) 148 | } 149 | 150 | #[inline] 151 | fn trigger(&self, chain: &Chain, err: E) -> E { 152 | self.trigger_impl(chain); 153 | err 154 | } 155 | 156 | fn trigger_impl(&self, chain: &Chain) { 157 | self.path.set(Some(match self.path.take() { 158 | Some(already_set) => already_set, 159 | None => Path::from_chain(chain), 160 | })); 161 | } 162 | } 163 | 164 | #[derive(Clone)] 165 | enum Chain<'a> { 166 | Root, 167 | Seq { 168 | parent: &'a Chain<'a>, 169 | index: usize, 170 | }, 171 | Map { 172 | parent: &'a Chain<'a>, 173 | key: String, 174 | }, 175 | Struct { 176 | parent: &'a Chain<'a>, 177 | key: &'static str, 178 | }, 179 | Enum { 180 | parent: &'a Chain<'a>, 181 | variant: String, 182 | }, 183 | Some { 184 | parent: &'a Chain<'a>, 185 | }, 186 | NewtypeStruct { 187 | parent: &'a Chain<'a>, 188 | }, 189 | NewtypeVariant { 190 | parent: &'a Chain<'a>, 191 | }, 192 | NonStringKey { 193 | parent: &'a Chain<'a>, 194 | }, 195 | } 196 | -------------------------------------------------------------------------------- /src/path.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::{self, Display}; 2 | use std::slice; 3 | 4 | use super::Chain; 5 | 6 | /// Path to the error value in the input, like `dependencies.serde.typo1`. 7 | /// 8 | /// Use `path.to_string()` to get a string representation of the path with 9 | /// segments separated by periods, or use `path.iter()` to iterate over 10 | /// individual segments of the path. 11 | #[derive(Clone, Debug)] 12 | pub struct Path { 13 | segments: Vec, 14 | } 15 | 16 | /// Single segment of a path. 17 | #[derive(Clone, Debug)] 18 | pub enum Segment { 19 | Seq { index: usize }, 20 | Map { key: String }, 21 | Enum { variant: String }, 22 | Unknown, 23 | } 24 | 25 | impl Path { 26 | /// Returns an iterator with element type [`&Segment`][Segment]. 27 | pub fn iter(&self) -> Segments { 28 | Segments { 29 | iter: self.segments.iter(), 30 | } 31 | } 32 | } 33 | 34 | impl<'a> IntoIterator for &'a Path { 35 | type Item = &'a Segment; 36 | type IntoIter = Segments<'a>; 37 | 38 | fn into_iter(self) -> Self::IntoIter { 39 | self.iter() 40 | } 41 | } 42 | 43 | /// Iterator over segments of a path. 44 | pub struct Segments<'a> { 45 | iter: slice::Iter<'a, Segment>, 46 | } 47 | 48 | impl<'a> Iterator for Segments<'a> { 49 | type Item = &'a Segment; 50 | 51 | fn next(&mut self) -> Option { 52 | self.iter.next() 53 | } 54 | 55 | fn size_hint(&self) -> (usize, Option) { 56 | self.iter.size_hint() 57 | } 58 | } 59 | 60 | impl<'a> DoubleEndedIterator for Segments<'a> { 61 | fn next_back(&mut self) -> Option { 62 | self.iter.next_back() 63 | } 64 | } 65 | 66 | impl<'a> ExactSizeIterator for Segments<'a> { 67 | fn len(&self) -> usize { 68 | self.iter.len() 69 | } 70 | } 71 | 72 | impl Display for Path { 73 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 74 | if self.segments.is_empty() { 75 | return formatter.write_str("."); 76 | } 77 | 78 | let mut separator = ""; 79 | for segment in self { 80 | if !matches!(segment, Segment::Seq { .. }) { 81 | formatter.write_str(separator)?; 82 | } 83 | write!(formatter, "{}", segment)?; 84 | separator = "."; 85 | } 86 | 87 | Ok(()) 88 | } 89 | } 90 | 91 | impl Path { 92 | pub(crate) fn empty() -> Self { 93 | Path { 94 | segments: Vec::new(), 95 | } 96 | } 97 | 98 | pub(crate) fn from_chain(mut chain: &Chain) -> Self { 99 | let mut segments = Vec::new(); 100 | loop { 101 | match chain { 102 | Chain::Root => break, 103 | Chain::Seq { parent, index } => { 104 | segments.push(Segment::Seq { index: *index }); 105 | chain = parent; 106 | } 107 | Chain::Map { parent, key } => { 108 | segments.push(Segment::Map { key: key.clone() }); 109 | chain = parent; 110 | } 111 | Chain::Struct { parent, key } => { 112 | let key = *key; 113 | segments.push(Segment::Map { 114 | key: key.to_owned(), 115 | }); 116 | chain = parent; 117 | } 118 | Chain::Enum { parent, variant } => { 119 | segments.push(Segment::Enum { 120 | variant: variant.clone(), 121 | }); 122 | chain = parent; 123 | } 124 | Chain::Some { parent } 125 | | Chain::NewtypeStruct { parent } 126 | | Chain::NewtypeVariant { parent } => { 127 | chain = parent; 128 | } 129 | Chain::NonStringKey { parent } => { 130 | segments.push(Segment::Unknown); 131 | chain = parent; 132 | } 133 | } 134 | } 135 | segments.reverse(); 136 | Path { segments } 137 | } 138 | 139 | pub(crate) fn is_only_unknown(&self) -> bool { 140 | self.segments.iter().all(Segment::is_unknown) 141 | } 142 | } 143 | 144 | impl Display for Segment { 145 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 146 | match self { 147 | Segment::Seq { index } => write!(formatter, "[{}]", index), 148 | Segment::Map { key } | Segment::Enum { variant: key } => { 149 | write!(formatter, "{}", key) 150 | } 151 | Segment::Unknown => formatter.write_str("?"), 152 | } 153 | } 154 | } 155 | 156 | impl Segment { 157 | fn is_unknown(&self) -> bool { 158 | matches!(self, Segment::Unknown) 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/ser.rs: -------------------------------------------------------------------------------- 1 | use crate::wrap::Wrap; 2 | use crate::{Chain, Error, Track}; 3 | use serde::ser::{self, Serialize}; 4 | use std::cell::Cell; 5 | use std::fmt::Display; 6 | 7 | /// Entry point for tracking path to Serialize error. 8 | /// 9 | /// # Example 10 | /// 11 | /// ``` 12 | /// # use serde_derive::Serialize; 13 | /// # 14 | /// use serde::Serialize; 15 | /// use std::cell::RefCell; 16 | /// 17 | /// #[derive(Serialize)] 18 | /// struct Outer<'a> { 19 | /// k: Inner<'a>, 20 | /// } 21 | /// 22 | /// #[derive(Serialize)] 23 | /// struct Inner<'a> { 24 | /// refcell: &'a RefCell, 25 | /// } 26 | /// 27 | /// let refcell = RefCell::new(String::new()); 28 | /// let value = Outer { 29 | /// k: Inner { refcell: &refcell }, 30 | /// }; 31 | /// 32 | /// // A RefCell cannot be serialized while it is still mutably borrowed. 33 | /// let _borrowed = refcell.borrow_mut(); 34 | /// 35 | /// // Some Serializer. 36 | /// let mut out = Vec::new(); 37 | /// let jser = &mut serde_json::Serializer::new(&mut out); 38 | /// 39 | /// let result = serde_path_to_error::serialize(&value, jser); 40 | /// match result { 41 | /// Ok(_) => panic!("expected failure to serialize RefCell"), 42 | /// Err(err) => { 43 | /// let path = err.path().to_string(); 44 | /// assert_eq!(path, "k.refcell"); 45 | /// } 46 | /// } 47 | /// ``` 48 | pub fn serialize(value: &T, serializer: S) -> Result> 49 | where 50 | T: ?Sized + Serialize, 51 | S: ser::Serializer, 52 | { 53 | let mut track = Track::new(); 54 | match T::serialize(value, Serializer::new(serializer, &mut track)) { 55 | Ok(ok) => Ok(ok), 56 | Err(err) => Err(Error { 57 | path: track.path(), 58 | original: err, 59 | }), 60 | } 61 | } 62 | 63 | /// Serializer adapter that records path to serialization errors. 64 | /// 65 | /// # Example 66 | /// 67 | /// ``` 68 | /// # use serde_derive::Serialize; 69 | /// # 70 | /// use serde::Serialize; 71 | /// use std::collections::BTreeMap; 72 | /// 73 | /// // Maps with a non-string key are not valid in JSON. 74 | /// let mut inner_map = BTreeMap::new(); 75 | /// inner_map.insert(vec!['w', 'a', 't'], 0); 76 | /// 77 | /// let mut outer_map = BTreeMap::new(); 78 | /// outer_map.insert("k", inner_map); 79 | /// 80 | /// // Some Serializer. 81 | /// let mut out = Vec::new(); 82 | /// let jser = &mut serde_json::Serializer::new(&mut out); 83 | /// 84 | /// let mut track = serde_path_to_error::Track::new(); 85 | /// let ps = serde_path_to_error::Serializer::new(jser, &mut track); 86 | /// 87 | /// match outer_map.serialize(ps) { 88 | /// Ok(_) => panic!("expected failure to serialize non-string key"), 89 | /// Err(_) => { 90 | /// let path = track.path().to_string(); 91 | /// assert_eq!(path, "k"); 92 | /// } 93 | /// } 94 | /// ``` 95 | pub struct Serializer<'a, 'b, S> { 96 | ser: S, 97 | chain: &'a Chain<'a>, 98 | track: &'b Track, 99 | } 100 | 101 | impl<'a, 'b, S> Serializer<'a, 'b, S> { 102 | #[allow(clippy::needless_pass_by_ref_mut)] 103 | pub fn new(ser: S, track: &'b mut Track) -> Self { 104 | Serializer { 105 | ser, 106 | chain: &Chain::Root, 107 | track, 108 | } 109 | } 110 | } 111 | 112 | impl<'a, 'b, S> ser::Serializer for Serializer<'a, 'b, S> 113 | where 114 | S: ser::Serializer, 115 | { 116 | type Ok = S::Ok; 117 | type Error = S::Error; 118 | type SerializeSeq = WrapSeq<'a, 'b, S::SerializeSeq>; 119 | type SerializeTuple = WrapSeq<'a, 'b, S::SerializeTuple>; 120 | type SerializeTupleStruct = WrapSeq<'a, 'b, S::SerializeTupleStruct>; 121 | type SerializeTupleVariant = WrapSeq<'a, 'b, S::SerializeTupleVariant>; 122 | type SerializeMap = WrapMap<'a, 'b, S::SerializeMap>; 123 | type SerializeStruct = Wrap<'a, 'b, S::SerializeStruct>; 124 | type SerializeStructVariant = Wrap<'a, 'b, S::SerializeStructVariant>; 125 | 126 | fn serialize_bool(self, v: bool) -> Result { 127 | let chain = self.chain; 128 | let track = self.track; 129 | self.ser 130 | .serialize_bool(v) 131 | .map_err(|err| track.trigger(chain, err)) 132 | } 133 | 134 | fn serialize_i8(self, v: i8) -> Result { 135 | let chain = self.chain; 136 | let track = self.track; 137 | self.ser 138 | .serialize_i8(v) 139 | .map_err(|err| track.trigger(chain, err)) 140 | } 141 | 142 | fn serialize_i16(self, v: i16) -> Result { 143 | let chain = self.chain; 144 | let track = self.track; 145 | self.ser 146 | .serialize_i16(v) 147 | .map_err(|err| track.trigger(chain, err)) 148 | } 149 | 150 | fn serialize_i32(self, v: i32) -> Result { 151 | let chain = self.chain; 152 | let track = self.track; 153 | self.ser 154 | .serialize_i32(v) 155 | .map_err(|err| track.trigger(chain, err)) 156 | } 157 | 158 | fn serialize_i64(self, v: i64) -> Result { 159 | let chain = self.chain; 160 | let track = self.track; 161 | self.ser 162 | .serialize_i64(v) 163 | .map_err(|err| track.trigger(chain, err)) 164 | } 165 | 166 | fn serialize_i128(self, v: i128) -> Result { 167 | let chain = self.chain; 168 | let track = self.track; 169 | self.ser 170 | .serialize_i128(v) 171 | .map_err(|err| track.trigger(chain, err)) 172 | } 173 | 174 | fn serialize_u8(self, v: u8) -> Result { 175 | let chain = self.chain; 176 | let track = self.track; 177 | self.ser 178 | .serialize_u8(v) 179 | .map_err(|err| track.trigger(chain, err)) 180 | } 181 | 182 | fn serialize_u16(self, v: u16) -> Result { 183 | let chain = self.chain; 184 | let track = self.track; 185 | self.ser 186 | .serialize_u16(v) 187 | .map_err(|err| track.trigger(chain, err)) 188 | } 189 | 190 | fn serialize_u32(self, v: u32) -> Result { 191 | let chain = self.chain; 192 | let track = self.track; 193 | self.ser 194 | .serialize_u32(v) 195 | .map_err(|err| track.trigger(chain, err)) 196 | } 197 | 198 | fn serialize_u64(self, v: u64) -> Result { 199 | let chain = self.chain; 200 | let track = self.track; 201 | self.ser 202 | .serialize_u64(v) 203 | .map_err(|err| track.trigger(chain, err)) 204 | } 205 | 206 | fn serialize_u128(self, v: u128) -> Result { 207 | let chain = self.chain; 208 | let track = self.track; 209 | self.ser 210 | .serialize_u128(v) 211 | .map_err(|err| track.trigger(chain, err)) 212 | } 213 | 214 | fn serialize_f32(self, v: f32) -> Result { 215 | let chain = self.chain; 216 | let track = self.track; 217 | self.ser 218 | .serialize_f32(v) 219 | .map_err(|err| track.trigger(chain, err)) 220 | } 221 | 222 | fn serialize_f64(self, v: f64) -> Result { 223 | let chain = self.chain; 224 | let track = self.track; 225 | self.ser 226 | .serialize_f64(v) 227 | .map_err(|err| track.trigger(chain, err)) 228 | } 229 | 230 | fn serialize_char(self, v: char) -> Result { 231 | let chain = self.chain; 232 | let track = self.track; 233 | self.ser 234 | .serialize_char(v) 235 | .map_err(|err| track.trigger(chain, err)) 236 | } 237 | 238 | fn serialize_str(self, v: &str) -> Result { 239 | let chain = self.chain; 240 | let track = self.track; 241 | self.ser 242 | .serialize_str(v) 243 | .map_err(|err| track.trigger(chain, err)) 244 | } 245 | 246 | fn serialize_bytes(self, v: &[u8]) -> Result { 247 | let chain = self.chain; 248 | let track = self.track; 249 | self.ser 250 | .serialize_bytes(v) 251 | .map_err(|err| track.trigger(chain, err)) 252 | } 253 | 254 | fn serialize_none(self) -> Result { 255 | let chain = self.chain; 256 | let track = self.track; 257 | self.ser 258 | .serialize_none() 259 | .map_err(|err| track.trigger(chain, err)) 260 | } 261 | 262 | fn serialize_some(self, value: &T) -> Result 263 | where 264 | T: ?Sized + Serialize, 265 | { 266 | let chain = self.chain; 267 | let track = self.track; 268 | self.ser 269 | .serialize_some(value) 270 | .map_err(|err| track.trigger(chain, err)) 271 | } 272 | 273 | fn serialize_unit(self) -> Result { 274 | let chain = self.chain; 275 | let track = self.track; 276 | self.ser 277 | .serialize_unit() 278 | .map_err(|err| track.trigger(chain, err)) 279 | } 280 | 281 | fn serialize_unit_struct(self, name: &'static str) -> Result { 282 | let chain = self.chain; 283 | let track = self.track; 284 | self.ser 285 | .serialize_unit_struct(name) 286 | .map_err(|err| track.trigger(chain, err)) 287 | } 288 | 289 | fn serialize_unit_variant( 290 | self, 291 | name: &'static str, 292 | variant_index: u32, 293 | variant: &'static str, 294 | ) -> Result { 295 | let chain = self.chain; 296 | let track = self.track; 297 | self.ser 298 | .serialize_unit_variant(name, variant_index, variant) 299 | .map_err(|err| track.trigger(chain, err)) 300 | } 301 | 302 | fn serialize_newtype_struct( 303 | self, 304 | name: &'static str, 305 | value: &T, 306 | ) -> Result 307 | where 308 | T: ?Sized + Serialize, 309 | { 310 | let chain = self.chain; 311 | let track = self.track; 312 | self.ser 313 | .serialize_newtype_struct(name, value) 314 | .map_err(|err| track.trigger(chain, err)) 315 | } 316 | 317 | fn serialize_newtype_variant( 318 | self, 319 | name: &'static str, 320 | variant_index: u32, 321 | variant: &'static str, 322 | value: &T, 323 | ) -> Result 324 | where 325 | T: ?Sized + Serialize, 326 | { 327 | let chain = self.chain; 328 | let track = self.track; 329 | self.ser 330 | .serialize_newtype_variant(name, variant_index, variant, value) 331 | .map_err(|err| track.trigger(chain, err)) 332 | } 333 | 334 | fn serialize_seq(self, len: Option) -> Result { 335 | let chain = self.chain; 336 | let track = self.track; 337 | match self.ser.serialize_seq(len) { 338 | Ok(delegate) => Ok(WrapSeq::new(delegate, chain, track)), 339 | Err(err) => Err(track.trigger(chain, err)), 340 | } 341 | } 342 | 343 | fn serialize_tuple(self, len: usize) -> Result { 344 | let chain = self.chain; 345 | let track = self.track; 346 | match self.ser.serialize_tuple(len) { 347 | Ok(delegate) => Ok(WrapSeq::new(delegate, chain, track)), 348 | Err(err) => Err(track.trigger(chain, err)), 349 | } 350 | } 351 | 352 | fn serialize_tuple_struct( 353 | self, 354 | name: &'static str, 355 | len: usize, 356 | ) -> Result { 357 | let chain = self.chain; 358 | let track = self.track; 359 | match self.ser.serialize_tuple_struct(name, len) { 360 | Ok(delegate) => Ok(WrapSeq::new(delegate, chain, track)), 361 | Err(err) => Err(track.trigger(chain, err)), 362 | } 363 | } 364 | 365 | fn serialize_tuple_variant( 366 | self, 367 | name: &'static str, 368 | variant_index: u32, 369 | variant: &'static str, 370 | len: usize, 371 | ) -> Result { 372 | let chain = self.chain; 373 | let track = self.track; 374 | match self 375 | .ser 376 | .serialize_tuple_variant(name, variant_index, variant, len) 377 | { 378 | Ok(delegate) => Ok(WrapSeq::new(delegate, chain, track)), 379 | Err(err) => Err(track.trigger(chain, err)), 380 | } 381 | } 382 | 383 | fn serialize_map(self, len: Option) -> Result { 384 | let chain = self.chain; 385 | let track = self.track; 386 | match self.ser.serialize_map(len) { 387 | Ok(delegate) => Ok(WrapMap::new(delegate, chain, track)), 388 | Err(err) => Err(track.trigger(chain, err)), 389 | } 390 | } 391 | 392 | fn serialize_struct( 393 | self, 394 | name: &'static str, 395 | len: usize, 396 | ) -> Result { 397 | let chain = self.chain; 398 | let track = self.track; 399 | match self.ser.serialize_struct(name, len) { 400 | Ok(delegate) => Ok(Wrap::new(delegate, chain, track)), 401 | Err(err) => Err(track.trigger(chain, err)), 402 | } 403 | } 404 | 405 | fn serialize_struct_variant( 406 | self, 407 | name: &'static str, 408 | variant_index: u32, 409 | variant: &'static str, 410 | len: usize, 411 | ) -> Result { 412 | let chain = self.chain; 413 | let track = self.track; 414 | match self 415 | .ser 416 | .serialize_struct_variant(name, variant_index, variant, len) 417 | { 418 | Ok(delegate) => Ok(Wrap::new(delegate, chain, track)), 419 | Err(err) => Err(track.trigger(chain, err)), 420 | } 421 | } 422 | 423 | fn collect_str(self, value: &T) -> Result 424 | where 425 | T: ?Sized + Display, 426 | { 427 | let chain = self.chain; 428 | let track = self.track; 429 | self.ser 430 | .collect_str(value) 431 | .map_err(|err| track.trigger(chain, err)) 432 | } 433 | 434 | fn is_human_readable(&self) -> bool { 435 | self.ser.is_human_readable() 436 | } 437 | } 438 | 439 | struct TrackedValue<'a, 'b, X> { 440 | value: X, 441 | chain: &'a Chain<'a>, 442 | track: &'b Track, 443 | } 444 | 445 | impl<'a, 'b, X> TrackedValue<'a, 'b, X> { 446 | fn new(value: X, chain: &'a Chain<'a>, track: &'b Track) -> Self { 447 | TrackedValue { 448 | value, 449 | chain, 450 | track, 451 | } 452 | } 453 | } 454 | 455 | impl<'a, 'b, X> Serialize for TrackedValue<'a, 'b, X> 456 | where 457 | X: Serialize, 458 | { 459 | fn serialize(&self, serializer: S) -> Result 460 | where 461 | S: ser::Serializer, 462 | { 463 | let chain = self.chain; 464 | let track = self.track; 465 | self.value 466 | .serialize(Serializer { 467 | ser: serializer, 468 | chain, 469 | track, 470 | }) 471 | .map_err(|err| track.trigger(chain, err)) 472 | } 473 | } 474 | 475 | pub struct WrapSeq<'a, 'b, S> { 476 | delegate: S, 477 | chain: &'a Chain<'a>, 478 | index: usize, 479 | track: &'b Track, 480 | } 481 | 482 | impl<'a, 'b, S> WrapSeq<'a, 'b, S> { 483 | fn new(delegate: S, chain: &'a Chain<'a>, track: &'b Track) -> Self { 484 | WrapSeq { 485 | delegate, 486 | chain, 487 | index: 0, 488 | track, 489 | } 490 | } 491 | } 492 | 493 | impl<'a, 'b, S> ser::SerializeSeq for WrapSeq<'a, 'b, S> 494 | where 495 | S: ser::SerializeSeq, 496 | { 497 | type Ok = S::Ok; 498 | type Error = S::Error; 499 | 500 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 501 | where 502 | T: ?Sized + Serialize, 503 | { 504 | let parent = self.chain; 505 | let chain = Chain::Seq { 506 | parent, 507 | index: self.index, 508 | }; 509 | let track = self.track; 510 | self.index += 1; 511 | self.delegate 512 | .serialize_element(&TrackedValue::new(value, &chain, track)) 513 | .map_err(|err| track.trigger(parent, err)) 514 | } 515 | 516 | fn end(self) -> Result { 517 | let chain = self.chain; 518 | let track = self.track; 519 | self.delegate.end().map_err(|err| track.trigger(chain, err)) 520 | } 521 | } 522 | 523 | impl<'a, 'b, S> ser::SerializeTuple for WrapSeq<'a, 'b, S> 524 | where 525 | S: ser::SerializeTuple, 526 | { 527 | type Ok = S::Ok; 528 | type Error = S::Error; 529 | 530 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 531 | where 532 | T: ?Sized + Serialize, 533 | { 534 | let parent = self.chain; 535 | let chain = Chain::Seq { 536 | parent, 537 | index: self.index, 538 | }; 539 | let track = self.track; 540 | self.index += 1; 541 | self.delegate 542 | .serialize_element(&TrackedValue::new(value, &chain, track)) 543 | .map_err(|err| track.trigger(parent, err)) 544 | } 545 | 546 | fn end(self) -> Result { 547 | let chain = self.chain; 548 | let track = self.track; 549 | self.delegate.end().map_err(|err| track.trigger(chain, err)) 550 | } 551 | } 552 | 553 | impl<'a, 'b, S> ser::SerializeTupleStruct for WrapSeq<'a, 'b, S> 554 | where 555 | S: ser::SerializeTupleStruct, 556 | { 557 | type Ok = S::Ok; 558 | type Error = S::Error; 559 | 560 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> 561 | where 562 | T: ?Sized + Serialize, 563 | { 564 | let parent = self.chain; 565 | let chain = Chain::Seq { 566 | parent, 567 | index: self.index, 568 | }; 569 | let track = self.track; 570 | self.index += 1; 571 | self.delegate 572 | .serialize_field(&TrackedValue::new(value, &chain, track)) 573 | .map_err(|err| track.trigger(parent, err)) 574 | } 575 | 576 | fn end(self) -> Result { 577 | let chain = self.chain; 578 | let track = self.track; 579 | self.delegate.end().map_err(|err| track.trigger(chain, err)) 580 | } 581 | } 582 | 583 | impl<'a, 'b, S> ser::SerializeTupleVariant for WrapSeq<'a, 'b, S> 584 | where 585 | S: ser::SerializeTupleVariant, 586 | { 587 | type Ok = S::Ok; 588 | type Error = S::Error; 589 | 590 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> 591 | where 592 | T: ?Sized + Serialize, 593 | { 594 | let parent = self.chain; 595 | let chain = Chain::Seq { 596 | parent, 597 | index: self.index, 598 | }; 599 | let track = self.track; 600 | self.index += 1; 601 | self.delegate 602 | .serialize_field(&TrackedValue::new(value, &chain, track)) 603 | .map_err(|err| track.trigger(parent, err)) 604 | } 605 | 606 | fn end(self) -> Result { 607 | let chain = self.chain; 608 | let track = self.track; 609 | self.delegate.end().map_err(|err| track.trigger(chain, err)) 610 | } 611 | } 612 | 613 | pub struct WrapMap<'a, 'b, S> { 614 | delegate: S, 615 | chain: &'a Chain<'a>, 616 | key: Cell>, 617 | track: &'b Track, 618 | } 619 | 620 | impl<'a, 'b, S> WrapMap<'a, 'b, S> { 621 | fn new(delegate: S, chain: &'a Chain<'a>, track: &'b Track) -> Self { 622 | WrapMap { 623 | delegate, 624 | chain, 625 | key: Cell::new(None), 626 | track, 627 | } 628 | } 629 | } 630 | 631 | impl<'a, 'b, S> ser::SerializeMap for WrapMap<'a, 'b, S> 632 | where 633 | S: ser::SerializeMap, 634 | { 635 | type Ok = S::Ok; 636 | type Error = S::Error; 637 | 638 | fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> 639 | where 640 | T: ?Sized + Serialize, 641 | { 642 | let chain = self.chain; 643 | let track = self.track; 644 | self.key.set(None); 645 | self.delegate 646 | .serialize_key(&CaptureKey::new(&self.key, key)) 647 | .map_err(|err| track.trigger(chain, err)) 648 | } 649 | 650 | fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> 651 | where 652 | T: ?Sized + Serialize, 653 | { 654 | let parent = self.chain; 655 | let chain = match self.key.take() { 656 | Some(key) => Chain::Map { parent, key }, 657 | None => Chain::NonStringKey { parent }, 658 | }; 659 | let track = self.track; 660 | self.delegate 661 | .serialize_value(&TrackedValue::new(value, &chain, track)) 662 | .map_err(|err| track.trigger(parent, err)) 663 | } 664 | 665 | fn end(self) -> Result { 666 | let chain = self.chain; 667 | let track = self.track; 668 | self.delegate.end().map_err(|err| track.trigger(chain, err)) 669 | } 670 | } 671 | 672 | impl<'a, 'b, S> ser::SerializeStruct for Wrap<'a, 'b, S> 673 | where 674 | S: ser::SerializeStruct, 675 | { 676 | type Ok = S::Ok; 677 | type Error = S::Error; 678 | 679 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> 680 | where 681 | T: ?Sized + Serialize, 682 | { 683 | let parent = self.chain; 684 | let chain = Chain::Struct { parent, key }; 685 | let track = self.track; 686 | self.delegate 687 | .serialize_field(key, &TrackedValue::new(value, &chain, track)) 688 | .map_err(|err| track.trigger(parent, err)) 689 | } 690 | 691 | fn end(self) -> Result { 692 | let chain = self.chain; 693 | let track = self.track; 694 | self.delegate.end().map_err(|err| track.trigger(chain, err)) 695 | } 696 | 697 | fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { 698 | let chain = self.chain; 699 | let track = self.track; 700 | self.delegate 701 | .skip_field(key) 702 | .map_err(|err| track.trigger(chain, err)) 703 | } 704 | } 705 | 706 | impl<'a, 'b, S> ser::SerializeStructVariant for Wrap<'a, 'b, S> 707 | where 708 | S: ser::SerializeStructVariant, 709 | { 710 | type Ok = S::Ok; 711 | type Error = S::Error; 712 | 713 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> 714 | where 715 | T: ?Sized + Serialize, 716 | { 717 | let parent = self.chain; 718 | let chain = Chain::Struct { parent, key }; 719 | let track = self.track; 720 | self.delegate 721 | .serialize_field(key, &TrackedValue::new(value, &chain, track)) 722 | .map_err(|err| track.trigger(parent, err)) 723 | } 724 | 725 | fn end(self) -> Result { 726 | let chain = self.chain; 727 | let track = self.track; 728 | self.delegate.end().map_err(|err| track.trigger(chain, err)) 729 | } 730 | 731 | fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { 732 | let chain = self.chain; 733 | let track = self.track; 734 | self.delegate 735 | .skip_field(key) 736 | .map_err(|err| track.trigger(chain, err)) 737 | } 738 | } 739 | 740 | struct CaptureKey<'a, T> { 741 | out: &'a Cell>, 742 | delegate: T, 743 | } 744 | 745 | impl<'a, T> CaptureKey<'a, T> { 746 | fn new(out: &'a Cell>, delegate: T) -> Self { 747 | CaptureKey { out, delegate } 748 | } 749 | } 750 | 751 | impl<'a, T> Serialize for CaptureKey<'a, T> 752 | where 753 | T: Serialize, 754 | { 755 | fn serialize(&self, serializer: S) -> Result 756 | where 757 | S: ser::Serializer, 758 | { 759 | self.delegate 760 | .serialize(CaptureKey::new(self.out, serializer)) 761 | } 762 | } 763 | 764 | impl<'a, S> ser::Serializer for CaptureKey<'a, S> 765 | where 766 | S: ser::Serializer, 767 | { 768 | type Ok = S::Ok; 769 | type Error = S::Error; 770 | type SerializeSeq = S::SerializeSeq; 771 | type SerializeTuple = S::SerializeTuple; 772 | type SerializeTupleStruct = S::SerializeTupleStruct; 773 | type SerializeTupleVariant = S::SerializeTupleVariant; 774 | type SerializeMap = S::SerializeMap; 775 | type SerializeStruct = S::SerializeStruct; 776 | type SerializeStructVariant = S::SerializeStructVariant; 777 | 778 | fn serialize_bool(self, v: bool) -> Result { 779 | let string = if v { "true" } else { "false" }; 780 | self.out.set(Some(string.to_owned())); 781 | self.delegate.serialize_bool(v) 782 | } 783 | 784 | fn serialize_i8(self, v: i8) -> Result { 785 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 786 | self.delegate.serialize_i8(v) 787 | } 788 | 789 | fn serialize_i16(self, v: i16) -> Result { 790 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 791 | self.delegate.serialize_i16(v) 792 | } 793 | 794 | fn serialize_i32(self, v: i32) -> Result { 795 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 796 | self.delegate.serialize_i32(v) 797 | } 798 | 799 | fn serialize_i64(self, v: i64) -> Result { 800 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 801 | self.delegate.serialize_i64(v) 802 | } 803 | 804 | fn serialize_i128(self, v: i128) -> Result { 805 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 806 | self.delegate.serialize_i128(v) 807 | } 808 | 809 | fn serialize_u8(self, v: u8) -> Result { 810 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 811 | self.delegate.serialize_u8(v) 812 | } 813 | 814 | fn serialize_u16(self, v: u16) -> Result { 815 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 816 | self.delegate.serialize_u16(v) 817 | } 818 | 819 | fn serialize_u32(self, v: u32) -> Result { 820 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 821 | self.delegate.serialize_u32(v) 822 | } 823 | 824 | fn serialize_u64(self, v: u64) -> Result { 825 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 826 | self.delegate.serialize_u64(v) 827 | } 828 | 829 | fn serialize_u128(self, v: u128) -> Result { 830 | self.out.set(Some(itoa::Buffer::new().format(v).to_owned())); 831 | self.delegate.serialize_u128(v) 832 | } 833 | 834 | fn serialize_f32(self, v: f32) -> Result { 835 | self.delegate.serialize_f32(v) 836 | } 837 | 838 | fn serialize_f64(self, v: f64) -> Result { 839 | self.delegate.serialize_f64(v) 840 | } 841 | 842 | fn serialize_char(self, v: char) -> Result { 843 | self.delegate.serialize_char(v) 844 | } 845 | 846 | fn serialize_str(self, v: &str) -> Result { 847 | self.out.set(Some(v.to_owned())); 848 | self.delegate.serialize_str(v) 849 | } 850 | 851 | fn serialize_bytes(self, v: &[u8]) -> Result { 852 | self.delegate.serialize_bytes(v) 853 | } 854 | 855 | fn serialize_none(self) -> Result { 856 | self.delegate.serialize_none() 857 | } 858 | 859 | fn serialize_some(self, value: &T) -> Result 860 | where 861 | T: ?Sized + Serialize, 862 | { 863 | self.delegate 864 | .serialize_some(&CaptureKey::new(self.out, value)) 865 | } 866 | 867 | fn serialize_unit(self) -> Result { 868 | self.delegate.serialize_unit() 869 | } 870 | 871 | fn serialize_unit_struct(self, name: &'static str) -> Result { 872 | self.delegate.serialize_unit_struct(name) 873 | } 874 | 875 | fn serialize_unit_variant( 876 | self, 877 | name: &'static str, 878 | variant_index: u32, 879 | variant: &'static str, 880 | ) -> Result { 881 | self.out.set(Some(variant.to_owned())); 882 | self.delegate 883 | .serialize_unit_variant(name, variant_index, variant) 884 | } 885 | 886 | fn serialize_newtype_struct( 887 | self, 888 | name: &'static str, 889 | value: &T, 890 | ) -> Result 891 | where 892 | T: ?Sized + Serialize, 893 | { 894 | self.delegate 895 | .serialize_newtype_struct(name, &CaptureKey::new(self.out, value)) 896 | } 897 | 898 | fn serialize_newtype_variant( 899 | self, 900 | name: &'static str, 901 | variant_index: u32, 902 | variant: &'static str, 903 | value: &T, 904 | ) -> Result 905 | where 906 | T: ?Sized + Serialize, 907 | { 908 | self.delegate 909 | .serialize_newtype_variant(name, variant_index, variant, value) 910 | } 911 | 912 | fn serialize_seq(self, len: Option) -> Result { 913 | self.delegate.serialize_seq(len) 914 | } 915 | 916 | fn serialize_tuple(self, len: usize) -> Result { 917 | self.delegate.serialize_tuple(len) 918 | } 919 | 920 | fn serialize_tuple_struct( 921 | self, 922 | name: &'static str, 923 | len: usize, 924 | ) -> Result { 925 | self.delegate.serialize_tuple_struct(name, len) 926 | } 927 | 928 | fn serialize_tuple_variant( 929 | self, 930 | name: &'static str, 931 | variant_index: u32, 932 | variant: &'static str, 933 | len: usize, 934 | ) -> Result { 935 | self.delegate 936 | .serialize_tuple_variant(name, variant_index, variant, len) 937 | } 938 | 939 | fn serialize_map(self, len: Option) -> Result { 940 | self.delegate.serialize_map(len) 941 | } 942 | 943 | fn serialize_struct( 944 | self, 945 | name: &'static str, 946 | len: usize, 947 | ) -> Result { 948 | self.delegate.serialize_struct(name, len) 949 | } 950 | 951 | fn serialize_struct_variant( 952 | self, 953 | name: &'static str, 954 | variant_index: u32, 955 | variant: &'static str, 956 | len: usize, 957 | ) -> Result { 958 | self.delegate 959 | .serialize_struct_variant(name, variant_index, variant, len) 960 | } 961 | 962 | fn collect_seq(self, iter: I) -> Result 963 | where 964 | I: IntoIterator, 965 | I::Item: Serialize, 966 | { 967 | self.delegate.collect_seq(iter) 968 | } 969 | 970 | fn collect_map(self, iter: I) -> Result 971 | where 972 | K: Serialize, 973 | V: Serialize, 974 | I: IntoIterator, 975 | { 976 | self.delegate.collect_map(iter) 977 | } 978 | 979 | fn collect_str(self, value: &T) -> Result 980 | where 981 | T: ?Sized + Display, 982 | { 983 | self.out.set(Some(value.to_string())); 984 | self.delegate.collect_str(value) 985 | } 986 | 987 | fn is_human_readable(&self) -> bool { 988 | self.delegate.is_human_readable() 989 | } 990 | } 991 | -------------------------------------------------------------------------------- /src/wrap.rs: -------------------------------------------------------------------------------- 1 | use crate::{Chain, Track}; 2 | 3 | // Wrapper that attaches context to a `Visitor`, `SeqAccess` or `EnumAccess`. 4 | pub struct Wrap<'a, 'b, X> { 5 | pub(crate) delegate: X, 6 | pub(crate) chain: &'a Chain<'a>, 7 | pub(crate) track: &'b Track, 8 | } 9 | 10 | // Wrapper that attaches context to a `VariantAccess`. 11 | pub struct WrapVariant<'a, 'b, X> { 12 | pub(crate) delegate: X, 13 | pub(crate) chain: Chain<'a>, 14 | pub(crate) track: &'b Track, 15 | } 16 | 17 | impl<'a, 'b, X> Wrap<'a, 'b, X> { 18 | pub(crate) fn new(delegate: X, chain: &'a Chain<'a>, track: &'b Track) -> Self { 19 | Wrap { 20 | delegate, 21 | chain, 22 | track, 23 | } 24 | } 25 | } 26 | 27 | impl<'a, 'b, X> WrapVariant<'a, 'b, X> { 28 | pub(crate) fn new(delegate: X, chain: Chain<'a>, track: &'b Track) -> Self { 29 | WrapVariant { 30 | delegate, 31 | chain, 32 | track, 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/deserialize.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::unreadable_literal, dead_code)] 2 | 3 | use serde::Deserialize; 4 | use serde_derive::Deserialize; 5 | use std::collections::BTreeMap as Map; 6 | use std::fmt::Debug; 7 | 8 | fn test<'de, T>(json: &'de str, expected: &str) 9 | where 10 | T: Deserialize<'de> + Debug, 11 | { 12 | let de = &mut serde_json::Deserializer::from_str(json); 13 | let result: Result = serde_path_to_error::deserialize(de); 14 | let path = result.unwrap_err().path().to_string(); 15 | assert_eq!(path, expected); 16 | } 17 | 18 | #[test] 19 | fn test_struct() { 20 | #[derive(Deserialize, Debug)] 21 | struct Package { 22 | name: String, 23 | dependencies: Map, 24 | } 25 | 26 | #[derive(Deserialize, Debug)] 27 | struct Dependency { 28 | version: String, 29 | } 30 | 31 | let j = r#"{ 32 | "name": "demo", 33 | "dependencies": { 34 | "serde": { 35 | "version": 1 36 | } 37 | } 38 | }"#; 39 | 40 | test::(j, "dependencies.serde.version"); 41 | } 42 | 43 | #[test] 44 | fn test_vec() { 45 | #[derive(Deserialize, Debug)] 46 | struct Package { 47 | dependencies: Vec, 48 | } 49 | 50 | #[derive(Deserialize, Debug)] 51 | struct Dependency { 52 | name: String, 53 | version: String, 54 | } 55 | 56 | let j = r#"{ 57 | "dependencies": [ 58 | { 59 | "name": "serde", 60 | "version": "1.0" 61 | }, 62 | { 63 | "name": "serde_json", 64 | "version": 1 65 | } 66 | } 67 | }"#; 68 | 69 | test::(j, "dependencies[1].version"); 70 | } 71 | 72 | #[test] 73 | fn test_option() { 74 | #[derive(Deserialize, Debug)] 75 | struct Package { 76 | dependency: Option, 77 | } 78 | 79 | #[derive(Deserialize, Debug)] 80 | struct Dependency { 81 | version: String, 82 | } 83 | 84 | let j = r#"{ 85 | "dependency": { 86 | "version": 1 87 | } 88 | }"#; 89 | 90 | test::(j, "dependency.version"); 91 | } 92 | 93 | #[test] 94 | fn test_struct_variant() { 95 | #[derive(Deserialize, Debug)] 96 | struct Package { 97 | dependency: Dependency, 98 | } 99 | 100 | #[derive(Deserialize, Debug)] 101 | enum Dependency { 102 | Struct { version: String }, 103 | } 104 | 105 | let j = r#"{ 106 | "dependency": { 107 | "Struct": { 108 | "version": 1 109 | } 110 | } 111 | }"#; 112 | 113 | test::(j, "dependency.Struct.version"); 114 | } 115 | 116 | #[test] 117 | fn test_tuple_variant() { 118 | #[derive(Deserialize, Debug)] 119 | struct Package { 120 | dependency: Dependency, 121 | } 122 | 123 | #[derive(Deserialize, Debug)] 124 | enum Dependency { 125 | Tuple(String, String), 126 | } 127 | 128 | let j = r#"{ 129 | "dependency": { 130 | "Tuple": ["serde", 1] 131 | } 132 | }"#; 133 | 134 | test::(j, "dependency.Tuple[1]"); 135 | } 136 | 137 | #[test] 138 | fn test_unknown_field() { 139 | #[derive(Deserialize, Debug)] 140 | struct Package { 141 | dependency: Dependency, 142 | } 143 | 144 | #[derive(Deserialize, Debug)] 145 | #[serde(deny_unknown_fields)] 146 | struct Dependency { 147 | version: String, 148 | } 149 | 150 | let j = r#"{ 151 | "dependency": { 152 | "version": "1.0", 153 | "name": "serde" 154 | } 155 | }"#; 156 | 157 | test::(j, "dependency.name"); 158 | } 159 | 160 | #[test] 161 | fn test_invalid_length() { 162 | #[derive(Deserialize, Debug)] 163 | struct Package { 164 | dependency: Dependency, 165 | } 166 | 167 | #[derive(Deserialize, Debug)] 168 | struct Dependency(String, String); 169 | 170 | let j = r#"{ 171 | "dependency": ["serde"] 172 | }"#; 173 | 174 | test::(j, "dependency"); 175 | } 176 | 177 | #[test] 178 | fn test_syntax_error() { 179 | #[derive(Deserialize, Debug)] 180 | struct Package { 181 | dependency: Dependency, 182 | } 183 | 184 | #[derive(Deserialize, Debug)] 185 | struct Dependency { 186 | version: String, 187 | } 188 | 189 | let j = r#"{ 190 | "dependency": { 191 | "error": * 192 | }"#; 193 | 194 | test::(j, "dependency.error"); 195 | } 196 | 197 | #[test] 198 | fn test_u128() { 199 | #[derive(Deserialize, Debug)] 200 | struct Container { 201 | n: u128, 202 | } 203 | 204 | let j = r#"{ 205 | "n": 130033514578017493995102500318550798591 206 | }"#; 207 | 208 | let de = &mut serde_json::Deserializer::from_str(j); 209 | let container: Container = serde_path_to_error::deserialize(de).expect("failed to deserialize"); 210 | 211 | assert_eq!(container.n, 130033514578017493995102500318550798591u128); 212 | } 213 | 214 | #[test] 215 | fn test_map_nonstring_key() { 216 | #[derive(Deserialize, Debug)] 217 | struct Dependency { 218 | version: String, 219 | } 220 | 221 | let j = r#"{ 222 | "100": { 223 | "version": false 224 | } 225 | }"#; 226 | 227 | test::>(j, "100.version"); 228 | } 229 | -------------------------------------------------------------------------------- /tests/serialize.rs: -------------------------------------------------------------------------------- 1 | use serde::Serialize; 2 | use serde_derive::Serialize; 3 | use std::cell::RefCell; 4 | use std::collections::BTreeMap; 5 | use std::fmt::Debug; 6 | 7 | fn test(value: &T, expected: &str) 8 | where 9 | T: ?Sized + Serialize + Debug, 10 | { 11 | let mut out = Vec::new(); 12 | let ser = &mut serde_json::Serializer::new(&mut out); 13 | let result = serde_path_to_error::serialize(value, ser); 14 | let path = result.unwrap_err().path().to_string(); 15 | assert_eq!(path, expected); 16 | } 17 | 18 | #[test] 19 | fn test_refcell_already_borrowed() { 20 | #[derive(Serialize, Debug)] 21 | struct Outer<'a> { 22 | k: Inner<'a>, 23 | } 24 | 25 | #[derive(Serialize, Debug)] 26 | struct Inner<'a> { 27 | refcell: &'a RefCell, 28 | } 29 | 30 | let refcell = RefCell::new(String::new()); 31 | let outer = Outer { 32 | k: Inner { refcell: &refcell }, 33 | }; 34 | 35 | let _borrowed = refcell.borrow_mut(); 36 | test(&outer, "k.refcell"); 37 | } 38 | 39 | #[test] 40 | fn test_map_nonstring_key() { 41 | fn singleton_map(key: K, value: V) -> BTreeMap { 42 | let mut map = BTreeMap::new(); 43 | map.insert(key, value); 44 | map 45 | } 46 | 47 | let map = singleton_map(b"", 0); 48 | let map = singleton_map("k", map); 49 | let map = singleton_map(100, map); 50 | 51 | test(&map, "100.k"); 52 | } 53 | --------------------------------------------------------------------------------