diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-02-08 01:23:32 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-02-08 01:23:32 +0000 |
commit | f07829571446860876bb98b1d5cb1f481ab8e94d (patch) | |
tree | 68c2b5426766f3a2bc770792db8644d83602b4a5 | |
parent | 999c948a546538fc6974ebec4329f194db55bbe8 (diff) | |
parent | 4fa63b698c83d34a9c686ee180b7519eedcb6b94 (diff) | |
download | toml_edit-simpleperf-release.tar.gz |
Snap for 11421525 from 4fa63b698c83d34a9c686ee180b7519eedcb6b94 to simpleperf-releasesimpleperf-release
Change-Id: I978b874e40743535e4c8c7b217459797e5f20d6a
247 files changed, 2331 insertions, 874 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index fbf4047..7288de0 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "5753e4fd8ddf78980c41aabaec78a935eaba93e1" + "sha1": "a20848d8a228605e2e4fa30b01c1a71d448de175" }, "path_in_vcs": "crates/toml_edit" }
\ No newline at end of file @@ -5,11 +5,13 @@ rust_library_host { name: "libtoml_edit", crate_name: "toml_edit", cargo_env_compat: true, - cargo_pkg_version: "0.19.14", + cargo_pkg_version: "0.22.4", srcs: ["src/lib.rs"], edition: "2021", features: [ "default", + "display", + "parse", "serde", ], rustlibs: [ @@ -184,6 +184,15 @@ dependencies = [ ] [[package]] +name = "escape8259" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4911e3666fcd7826997b4745c8224295a6f3072f1418c3067b97a67557ee" +dependencies = [ + "rustversion", +] + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -337,6 +346,18 @@ dependencies = [ ] [[package]] +name = "libtest-mimic" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f0f4c6f44ecfd52e8b443f2ad18f2b996540135771561283c2352ce56a1c70b" +dependencies = [ + "clap", + "escape8259", + "termcolor", + "threadpool", +] + +[[package]] name = "linux-raw-sys" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -430,18 +451,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -478,10 +499,16 @@ dependencies = [ ] [[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] name = "ryu" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -494,22 +521,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.160" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.41", ] [[package]] @@ -525,9 +552,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -547,7 +574,7 @@ dependencies = [ "anstream", "anstyle", "ignore", - "libtest-mimic", + "libtest-mimic 0.6.0", "normalize-line-endings", "similar", "snapbox-macros", @@ -587,9 +614,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", @@ -625,52 +652,53 @@ dependencies = [ [[package]] name = "toml-test" -version = "0.3.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37351256790aa1dbd6d60f4ff08e55e7f372e292f3e9040d6e077463d9a779c3" +checksum = "1ec3892835fb31e181a87e1758275a64b0d7c6c9e9618aeb61a647bd487314c0" dependencies = [ "chrono", + "ryu", "serde", "serde_json", ] [[package]] name = "toml-test-data" -version = "1.3.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f351b6d6005ee802b0d4a53ca1cdf05636f441df4d299e62cba57f1da52646" +checksum = "c6b5bad99e813ce8c67d1d67c9b9f37c8451933f45eae0ab2b3583975f1cc15d" dependencies = [ "include_dir", ] [[package]] name = "toml-test-harness" -version = "0.4.3" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e00fda5710922fe6b3005bf6a5050c303d6f9625249c37b7386e8818f4af675" +checksum = "1be4b8d761dee51b4694e9f1d622a1d7f9c135a8b8265459e16d09ac5b16a05d" dependencies = [ "ignore", - "libtest-mimic", + "libtest-mimic 0.6.0", "toml-test", "toml-test-data", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.22.4" dependencies = [ "indexmap", "kstring", - "libtest-mimic", + "libtest-mimic 0.7.0", "serde", "serde_json", "serde_spanned", @@ -11,9 +11,9 @@ [package] edition = "2021" -rust-version = "1.64.0" +rust-version = "1.69" name = "toml_edit" -version = "0.19.14" +version = "0.22.4" authors = [ "Andronik Ordian <write@reusable.software>", "Ed Page <eopage@gmail.com>", @@ -29,6 +29,7 @@ include = [ "examples/**/*", "tests/**/*", ] +autotests = false description = "Yet another format-preserving TOML parser." readme = "README.md" keywords = [ @@ -92,18 +93,35 @@ search = "<!-- next-url -->" [[example]] name = "visit" test = true +required-features = [ + "parse", + "display", +] + +[[test]] +name = "testsuite" +required-features = [ + "parse", + "display", +] [[test]] name = "decoder_compliance" harness = false +required-features = ["parse"] [[test]] name = "encoder_compliance" harness = false +required-features = [ + "parse", + "display", +] [[test]] name = "invalid" harness = false +required-features = ["parse"] [dependencies.indexmap] version = "2.0.0" @@ -119,18 +137,19 @@ version = "1.0.145" optional = true [dependencies.serde_spanned] -version = "0.6.3" +version = "0.6.5" features = ["serde"] optional = true [dependencies.toml_datetime] -version = "0.6.3" +version = "0.6.5" [dependencies.winnow] version = "0.5.0" +optional = true [dev-dependencies.libtest-mimic] -version = "0.6.0" +version = "0.7.0" [dev-dependencies.serde_json] version = "1.0.96" @@ -140,13 +159,18 @@ version = "0.4.11" features = ["harness"] [dev-dependencies.toml-test-data] -version = "1.3.0" +version = "1.8.0" [dev-dependencies.toml-test-harness] -version = "0.4.3" +version = "0.4.8" [features] -default = [] +default = [ + "parse", + "display", +] +display = [] +parse = ["dep:winnow"] perf = ["dep:kstring"] serde = [ "dep:serde", diff --git a/Cargo.toml.orig b/Cargo.toml.orig index cda679f..9ab60c1 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,10 +1,11 @@ [package] name = "toml_edit" -version = "0.19.14" +version = "0.22.4" keywords = ["encoding", "toml"] categories = ["encoding", "parser-implementations", "parsing", "config"] description = "Yet another format-preserving TOML parser." authors = ["Andronik Ordian <write@reusable.software>", "Ed Page <eopage@gmail.com>"] +autotests = false repository.workspace = true license.workspace = true edition.workspace = true @@ -12,8 +13,8 @@ rust-version.workspace = true include.workspace = true [package.metadata.docs.rs] -rustdoc-args = ["--cfg", "docsrs"] features = ["serde"] +rustdoc-args = ["--cfg", "docsrs"] [package.metadata.release] tag-name = "v{{version}}" @@ -26,7 +27,9 @@ pre-release-replacements = [ ] [features] -default = [] +default = ["parse", "display"] +parse = ["dep:winnow"] +display = [] perf = ["dep:kstring"] serde = ["dep:serde", "toml_datetime/serde", "dep:serde_spanned"] # Provide a method disable_recursion_limit to parse arbitrarily deep structures @@ -38,31 +41,39 @@ unbounded = [] [dependencies] indexmap = { version = "2.0.0", features = ["std"] } -winnow = "0.5.0" +winnow = { version = "0.5.0", optional = true } serde = { version = "1.0.145", optional = true } kstring = { version = "2.0.0", features = ["max_inline"], optional = true } -toml_datetime = { version = "0.6.3", path = "../toml_datetime" } -serde_spanned = { version = "0.6.3", path = "../serde_spanned", features = ["serde"], optional = true } +toml_datetime = { version = "0.6.5", path = "../toml_datetime" } +serde_spanned = { version = "0.6.5", path = "../serde_spanned", features = ["serde"], optional = true } [dev-dependencies] serde_json = "1.0.96" -toml-test-harness = "0.4.3" -toml-test-data = "1.3.0" -libtest-mimic = "0.6.0" +toml-test-harness = "0.4.8" +toml-test-data = "1.8.0" +libtest-mimic = "0.7.0" snapbox = { version = "0.4.11", features = ["harness"] } [[test]] +name = "testsuite" +required-features = ["parse", "display"] + +[[test]] name = "decoder_compliance" +required-features = ["parse"] harness = false [[test]] name = "encoder_compliance" +required-features = ["parse", "display"] harness = false [[test]] name = "invalid" +required-features = ["parse"] harness = false [[example]] name = "visit" +required-features = ["parse", "display"] test = true diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 16fe87b..8f71f43 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -1,201 +1,202 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/LICENSE-MIT b/LICENSE-MIT index b9e61a2..a2d0108 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,6 +1,4 @@ -MIT License - -Copyright (c) 2017 Andronik Ordian +Copyright (c) Individual contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1,20 +1,24 @@ +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update external/rust/crates/toml_edit +# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md + name: "toml_edit" description: "Yet another format-preserving TOML parser." third_party { + license_type: NOTICE + last_upgrade_date { + year: 2024 + month: 2 + day: 7 + } identifier { type: "crates.io" - value: "https://crates.io/crates/toml_edit" + value: "https://static.crates.io/crates/toml_edit/toml_edit-0.22.4.crate" + version: "0.19.14" } identifier { type: "Archive" value: "https://static.crates.io/crates/toml_edit/toml_edit-0.19.14.crate" - } - version: "0.19.14" - # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same. - license_type: NOTICE - last_upgrade_date { - year: 2023 - month: 8 - day: 23 + version: "0.22.4" } } @@ -1,7 +1,7 @@ # toml_edit -[![Build Status](https://github.com/ordian/toml_edit/workflows/Continuous%20integration/badge.svg)](https://github.com/ordian/toml_edit/actions) -[![codecov](https://codecov.io/gh/ordian/toml_edit/branch/master/graph/badge.svg)](https://codecov.io/gh/ordian/toml_edit) +[![Build Status](https://github.com/toml-rs/toml/workflows/Continuous%20integration/badge.svg)](https://github.com/toml-rs/toml/actions) +[![codecov](https://codecov.io/gh/toml-rs/toml/branch/master/graph/badge.svg)](https://codecov.io/gh/toml-rs/toml) [![crates.io](https://img.shields.io/crates/v/toml_edit.svg)](https://crates.io/crates/toml_edit) [![docs](https://docs.rs/toml_edit/badge.svg)](https://docs.rs/toml_edit) [![Join the chat at https://gitter.im/toml_edit/Lobby](https://badges.gitter.im/a.svg)](https://gitter.im/toml_edit/Lobby) @@ -9,7 +9,7 @@ This crate allows you to parse and modify toml documents, while preserving comments, spaces *and -relative order* or items. +relative order* of items. `toml_edit` is primarily tailored for [cargo-edit](https://github.com/killercup/cargo-edit/) needs. @@ -42,8 +42,7 @@ c = { d = "hello" } Things it does not preserve: -* Scattered array of tables (tables are reordered by default, see [test]). -* Order of dotted keys, see [issue](https://github.com/ordian/toml_edit/issues/163). +* Order of dotted keys, see [issue](https://github.com/toml-rs/toml/issues/163). ## License @@ -55,5 +54,3 @@ Licensed under either of ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. - -[test]: https://github.com/ordian/toml_edit/blob/f09bd5d075fdb7d2ef8d9bb3270a34506c276753/tests/test_valid.rs#L84 diff --git a/src/array.rs b/src/array.rs index 045b451..377f676 100644 --- a/src/array.rs +++ b/src/array.rs @@ -183,9 +183,11 @@ impl Array { /// # Examples /// /// ```rust + /// # #[cfg(feature = "parse")] { /// let formatted_value = "'literal'".parse::<toml_edit::Value>().unwrap(); /// let mut arr = toml_edit::Array::new(); /// arr.push_formatted(formatted_value); + /// # } /// ``` pub fn push_formatted(&mut self, v: Value) { self.values.push(Item::Value(v)); @@ -223,12 +225,14 @@ impl Array { /// # Examples /// /// ```rust + /// # #[cfg(feature = "parse")] { /// let mut arr = toml_edit::Array::new(); /// arr.push(1); /// arr.push("foo"); /// /// let formatted_value = "'start'".parse::<toml_edit::Value>().unwrap(); /// arr.insert_formatted(0, formatted_value); + /// # } /// ``` pub fn insert_formatted(&mut self, index: usize, v: Value) { self.values.insert(index, Item::Value(v)) @@ -269,12 +273,14 @@ impl Array { /// # Examples /// /// ```rust + /// # #[cfg(feature = "parse")] { /// let mut arr = toml_edit::Array::new(); /// arr.push(1); /// arr.push("foo"); /// /// let formatted_value = "'start'".parse::<toml_edit::Value>().unwrap(); /// arr.replace_formatted(0, formatted_value); + /// # } /// ``` pub fn replace_formatted(&mut self, index: usize, v: Value) -> Value { match mem::replace(&mut self.values[index], Item::Value(v)) { @@ -317,6 +323,56 @@ impl Array { .retain(|item| item.as_value().map(&mut keep).unwrap_or(false)); } + /// Sorts the slice with a comparator function. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*)) worst-case. + /// + /// The comparator function must define a total ordering for the elements in the slice. If + /// the ordering is not total, the order of the elements is unspecified. An order is a + /// total order if it is (for all `a`, `b` and `c`): + /// + /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and + /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. + /// + /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use + /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`. + #[inline] + pub fn sort_by<F>(&mut self, mut compare: F) + where + F: FnMut(&Value, &Value) -> std::cmp::Ordering, + { + self.values.sort_by(move |lhs, rhs| { + let lhs = lhs.as_value(); + let rhs = rhs.as_value(); + match (lhs, rhs) { + (None, None) => std::cmp::Ordering::Equal, + (Some(_), None) => std::cmp::Ordering::Greater, + (None, Some(_)) => std::cmp::Ordering::Less, + (Some(lhs), Some(rhs)) => compare(lhs, rhs), + } + }) + } + + /// Sorts the array with a key extraction function. + /// + /// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*)) + /// worst-case, where the key function is *O*(*m*). + #[inline] + pub fn sort_by_key<K, F>(&mut self, mut f: F) + where + F: FnMut(&Value) -> K, + K: Ord, + { + #[allow(clippy::manual_map)] // needed for lifetimes + self.values.sort_by_key(move |item| { + if let Some(value) = item.as_value() { + Some(f(value)) + } else { + None + } + }); + } + fn value_op<T>( &mut self, v: Value, @@ -333,9 +389,10 @@ impl Array { } } +#[cfg(feature = "display")] impl std::fmt::Display for Array { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - crate::encode::Encode::encode(self, f, None, ("", "")) + crate::encode::encode_array(self, f, None, ("", "")) } } diff --git a/src/array_of_tables.rs b/src/array_of_tables.rs index c4d7194..2e602a2 100644 --- a/src/array_of_tables.rs +++ b/src/array_of_tables.rs @@ -158,6 +158,7 @@ impl<'s> IntoIterator for &'s ArrayOfTables { } } +#[cfg(feature = "display")] impl std::fmt::Display for ArrayOfTables { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // HACK: Without the header, we don't really have a proper way of printing this diff --git a/src/de/key.rs b/src/de/key.rs index 3da41df..a3b2825 100644 --- a/src/de/key.rs +++ b/src/de/key.rs @@ -62,9 +62,20 @@ impl<'de> serde::de::Deserializer<'de> for KeyDeserializer { self.deserialize_any(visitor) } + fn deserialize_newtype_struct<V>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + serde::forward_to_deserialize_any! { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq - bytes byte_buf map option unit newtype_struct + bytes byte_buf map option unit ignored_any unit_struct tuple_struct tuple identifier } } diff --git a/src/de/mod.rs b/src/de/mod.rs index 09ea120..9b8a2c7 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -87,6 +87,7 @@ impl From<Error> for crate::TomlError { impl std::error::Error for Error {} /// Convert a value into `T`. +#[cfg(feature = "parse")] pub fn from_str<T>(s: &'_ str) -> Result<T, Error> where T: DeserializeOwned, @@ -96,6 +97,7 @@ where } /// Convert a value into `T`. +#[cfg(feature = "parse")] pub fn from_slice<T>(s: &'_ [u8]) -> Result<T, Error> where T: DeserializeOwned, @@ -125,6 +127,7 @@ impl Deserializer { } } +#[cfg(feature = "parse")] impl std::str::FromStr for Deserializer { type Err = Error; diff --git a/src/de/table.rs b/src/de/table.rs index 0b6183e..33aa397 100644 --- a/src/de/table.rs +++ b/src/de/table.rs @@ -118,7 +118,7 @@ impl crate::InlineTable { pub(crate) struct TableMapAccess { iter: indexmap::map::IntoIter<crate::InternalString, crate::table::TableKeyValue>, span: Option<std::ops::Range<usize>>, - value: Option<(crate::InternalString, crate::Item)>, + value: Option<(crate::Key, crate::Item)>, } impl TableMapAccess { @@ -149,7 +149,7 @@ impl<'de> serde::de::MapAccess<'de> for TableMapAccess { } e }); - self.value = Some((v.key.into(), v.value)); + self.value = Some((v.key, v.value)); ret } None => Ok(None), @@ -162,13 +162,13 @@ impl<'de> serde::de::MapAccess<'de> for TableMapAccess { { match self.value.take() { Some((k, v)) => { - let span = v.span(); + let span = v.span().or_else(|| k.span()); seed.deserialize(crate::de::ValueDeserializer::new(v)) .map_err(|mut e: Self::Error| { if e.span().is_none() { e.set_span(span); } - e.add_key(k.as_str().to_owned()); + e.add_key(k.get().to_owned()); e }) } diff --git a/src/de/table_enum.rs b/src/de/table_enum.rs index 197ad6e..0ceeab6 100644 --- a/src/de/table_enum.rs +++ b/src/de/table_enum.rs @@ -16,6 +16,20 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer { fn unit_variant(self) -> Result<(), Self::Error> { match self.value { + crate::Item::ArrayOfTables(values) => { + if values.is_empty() { + Ok(()) + } else { + Err(Error::custom("expected empty array", values.span())) + } + } + crate::Item::Value(crate::Value::Array(values)) => { + if values.is_empty() { + Ok(()) + } else { + Err(Error::custom("expected empty table", values.span())) + } + } crate::Item::Table(values) => { if values.is_empty() { Ok(()) @@ -49,9 +63,41 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer { V: serde::de::Visitor<'de>, { match self.value { + crate::Item::ArrayOfTables(values) => { + let values_span = values.span(); + let tuple_values = values.values.into_iter().collect::<Vec<_>>(); + + if tuple_values.len() == len { + serde::de::Deserializer::deserialize_seq( + super::ArrayDeserializer::new(tuple_values, values_span), + visitor, + ) + } else { + Err(Error::custom( + format!("expected tuple with length {}", len), + values_span, + )) + } + } + crate::Item::Value(crate::Value::Array(values)) => { + let values_span = values.span(); + let tuple_values = values.values.into_iter().collect::<Vec<_>>(); + + if tuple_values.len() == len { + serde::de::Deserializer::deserialize_seq( + super::ArrayDeserializer::new(tuple_values, values_span), + visitor, + ) + } else { + Err(Error::custom( + format!("expected tuple with length {}", len), + values_span, + )) + } + } crate::Item::Table(values) => { let values_span = values.span(); - let tuple_values = values + let tuple_values: Result<Vec<_>, _> = values .items .into_iter() .enumerate() @@ -68,17 +114,8 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer { )), }, ) - // Fold all values into a `Vec`, or return the first error. - .fold(Ok(Vec::with_capacity(len)), |result, value_result| { - result.and_then(move |mut tuple_values| match value_result { - Ok(value) => { - tuple_values.push(value); - Ok(tuple_values) - } - // `Result<de::Value, Self::Error>` to `Result<Vec<_>, Self::Error>` - Err(e) => Err(e), - }) - })?; + .collect(); + let tuple_values = tuple_values?; if tuple_values.len() == len { serde::de::Deserializer::deserialize_seq( @@ -94,7 +131,7 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer { } crate::Item::Value(crate::Value::InlineTable(values)) => { let values_span = values.span(); - let tuple_values = values + let tuple_values: Result<Vec<_>, _> = values .items .into_iter() .enumerate() @@ -111,17 +148,8 @@ impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer { )), }, ) - // Fold all values into a `Vec`, or return the first error. - .fold(Ok(Vec::with_capacity(len)), |result, value_result| { - result.and_then(move |mut tuple_values| match value_result { - Ok(value) => { - tuple_values.push(value); - Ok(tuple_values) - } - // `Result<de::Value, Self::Error>` to `Result<Vec<_>, Self::Error>` - Err(e) => Err(e), - }) - })?; + .collect(); + let tuple_values = tuple_values?; if tuple_values.len() == len { serde::de::Deserializer::deserialize_seq( diff --git a/src/de/value.rs b/src/de/value.rs index 3984287..ba6ce6d 100644 --- a/src/de/value.rs +++ b/src/de/value.rs @@ -5,7 +5,7 @@ use crate::de::Error; /// Deserialization implementation for TOML [values][crate::Value]. /// -/// Can be creater either directly from TOML strings, using [`std::str::FromStr`], +/// Can be created either directly from TOML strings, using [`std::str::FromStr`], /// or from parsed [values][crate::Value] using [`serde::de::IntoDeserializer::into_deserializer`]. /// /// # Example @@ -241,6 +241,7 @@ impl crate::Item { } } +#[cfg(feature = "parse")] impl std::str::FromStr for ValueDeserializer { type Err = Error; diff --git a/src/document.rs b/src/document.rs index 67dd293..f20e61a 100644 --- a/src/document.rs +++ b/src/document.rs @@ -1,6 +1,5 @@ use std::str::FromStr; -use crate::parser; use crate::table::Iter; use crate::{Item, RawString, Table}; @@ -78,12 +77,13 @@ impl Default for Document { } } +#[cfg(feature = "parse")] impl FromStr for Document { type Err = crate::TomlError; /// Parses a document from a &str fn from_str(s: &str) -> Result<Self, Self::Err> { - let mut d = parser::parse_document(s)?; + let mut d = crate::parser::parse_document(s)?; d.despan(); Ok(d) } diff --git a/src/encode.rs b/src/encode.rs index 9940f28..30b153a 100644 --- a/src/encode.rs +++ b/src/encode.rs @@ -13,218 +13,185 @@ use crate::value::{ }; use crate::{Array, InlineTable, Item, Table, Value}; -pub(crate) trait Encode { - fn encode( - &self, - buf: &mut dyn Write, - input: Option<&str>, - default_decor: (&str, &str), - ) -> Result; +pub(crate) fn encode_key(this: &Key, buf: &mut dyn Write, input: Option<&str>) -> Result { + if let Some(input) = input { + let repr = this + .as_repr() + .map(Cow::Borrowed) + .unwrap_or_else(|| Cow::Owned(this.default_repr())); + repr.encode(buf, input)?; + } else { + let repr = this.display_repr(); + write!(buf, "{}", repr)?; + }; + + Ok(()) } -impl Encode for Key { - fn encode( - &self, - buf: &mut dyn Write, - input: Option<&str>, - default_decor: (&str, &str), - ) -> Result { - let decor = self.decor(); - decor.prefix_encode(buf, input, default_decor.0)?; - - if let Some(input) = input { - let repr = self - .as_repr() - .map(Cow::Borrowed) - .unwrap_or_else(|| Cow::Owned(self.default_repr())); - repr.encode(buf, input)?; +fn encode_key_path( + this: &[Key], + buf: &mut dyn Write, + input: Option<&str>, + default_decor: (&str, &str), +) -> Result { + let leaf_decor = this.last().expect("always at least one key").leaf_decor(); + for (i, key) in this.iter().enumerate() { + let dotted_decor = key.dotted_decor(); + + let first = i == 0; + let last = i + 1 == this.len(); + + if first { + leaf_decor.prefix_encode(buf, input, default_decor.0)?; } else { - let repr = self.display_repr(); - write!(buf, "{}", repr)?; - }; + write!(buf, ".")?; + dotted_decor.prefix_encode(buf, input, DEFAULT_KEY_PATH_DECOR.0)?; + } + + encode_key(key, buf, input)?; - decor.suffix_encode(buf, input, default_decor.1)?; - Ok(()) + if last { + leaf_decor.suffix_encode(buf, input, default_decor.1)?; + } else { + dotted_decor.suffix_encode(buf, input, DEFAULT_KEY_PATH_DECOR.1)?; + } } + Ok(()) } -impl<'k> Encode for &'k [Key] { - fn encode( - &self, - buf: &mut dyn Write, - input: Option<&str>, - default_decor: (&str, &str), - ) -> Result { - for (i, key) in self.iter().enumerate() { - let first = i == 0; - let last = i + 1 == self.len(); - - let prefix = if first { - default_decor.0 - } else { - DEFAULT_KEY_PATH_DECOR.0 - }; - let suffix = if last { - default_decor.1 - } else { - DEFAULT_KEY_PATH_DECOR.1 - }; +pub(crate) fn encode_key_path_ref( + this: &[&Key], + buf: &mut dyn Write, + input: Option<&str>, + default_decor: (&str, &str), +) -> Result { + let leaf_decor = this.last().expect("always at least one key").leaf_decor(); + for (i, key) in this.iter().enumerate() { + let dotted_decor = key.dotted_decor(); - if !first { - write!(buf, ".")?; - } - key.encode(buf, input, (prefix, suffix))?; + let first = i == 0; + let last = i + 1 == this.len(); + + if first { + leaf_decor.prefix_encode(buf, input, default_decor.0)?; + } else { + write!(buf, ".")?; + dotted_decor.prefix_encode(buf, input, DEFAULT_KEY_PATH_DECOR.0)?; } - Ok(()) - } -} -impl<'k> Encode for &'k [&'k Key] { - fn encode( - &self, - buf: &mut dyn Write, - input: Option<&str>, - default_decor: (&str, &str), - ) -> Result { - for (i, key) in self.iter().enumerate() { - let first = i == 0; - let last = i + 1 == self.len(); - - let prefix = if first { - default_decor.0 - } else { - DEFAULT_KEY_PATH_DECOR.0 - }; - let suffix = if last { - default_decor.1 - } else { - DEFAULT_KEY_PATH_DECOR.1 - }; + encode_key(key, buf, input)?; - if !first { - write!(buf, ".")?; - } - key.encode(buf, input, (prefix, suffix))?; + if last { + leaf_decor.suffix_encode(buf, input, default_decor.1)?; + } else { + dotted_decor.suffix_encode(buf, input, DEFAULT_KEY_PATH_DECOR.1)?; } - Ok(()) } + Ok(()) } -impl<T> Encode for Formatted<T> -where - T: ValueRepr, -{ - fn encode( - &self, - buf: &mut dyn Write, - input: Option<&str>, - default_decor: (&str, &str), - ) -> Result { - let decor = self.decor(); - decor.prefix_encode(buf, input, default_decor.0)?; - - if let Some(input) = input { - let repr = self - .as_repr() - .map(Cow::Borrowed) - .unwrap_or_else(|| Cow::Owned(self.default_repr())); - repr.encode(buf, input)?; - } else { - let repr = self.display_repr(); - write!(buf, "{}", repr)?; - }; +pub(crate) fn encode_formatted<T: ValueRepr>( + this: &Formatted<T>, + buf: &mut dyn Write, + input: Option<&str>, + default_decor: (&str, &str), +) -> Result { + let decor = this.decor(); + decor.prefix_encode(buf, input, default_decor.0)?; + + if let Some(input) = input { + let repr = this + .as_repr() + .map(Cow::Borrowed) + .unwrap_or_else(|| Cow::Owned(this.default_repr())); + repr.encode(buf, input)?; + } else { + let repr = this.display_repr(); + write!(buf, "{}", repr)?; + }; - decor.suffix_encode(buf, input, default_decor.1)?; - Ok(()) - } + decor.suffix_encode(buf, input, default_decor.1)?; + Ok(()) } -impl Encode for Array { - fn encode( - &self, - buf: &mut dyn Write, - input: Option<&str>, - default_decor: (&str, &str), - ) -> Result { - let decor = self.decor(); - decor.prefix_encode(buf, input, default_decor.0)?; - write!(buf, "[")?; - - for (i, elem) in self.iter().enumerate() { - let inner_decor; - if i == 0 { - inner_decor = DEFAULT_LEADING_VALUE_DECOR; - } else { - inner_decor = DEFAULT_VALUE_DECOR; - write!(buf, ",")?; - } - elem.encode(buf, input, inner_decor)?; - } - if self.trailing_comma() && !self.is_empty() { +pub(crate) fn encode_array( + this: &Array, + buf: &mut dyn Write, + input: Option<&str>, + default_decor: (&str, &str), +) -> Result { + let decor = this.decor(); + decor.prefix_encode(buf, input, default_decor.0)?; + write!(buf, "[")?; + + for (i, elem) in this.iter().enumerate() { + let inner_decor; + if i == 0 { + inner_decor = DEFAULT_LEADING_VALUE_DECOR; + } else { + inner_decor = DEFAULT_VALUE_DECOR; write!(buf, ",")?; } + encode_value(elem, buf, input, inner_decor)?; + } + if this.trailing_comma() && !this.is_empty() { + write!(buf, ",")?; + } - self.trailing().encode_with_default(buf, input, "")?; - write!(buf, "]")?; - decor.suffix_encode(buf, input, default_decor.1)?; + this.trailing().encode_with_default(buf, input, "")?; + write!(buf, "]")?; + decor.suffix_encode(buf, input, default_decor.1)?; - Ok(()) - } + Ok(()) } -impl Encode for InlineTable { - fn encode( - &self, - buf: &mut dyn Write, - input: Option<&str>, - default_decor: (&str, &str), - ) -> Result { - let decor = self.decor(); - decor.prefix_encode(buf, input, default_decor.0)?; - write!(buf, "{{")?; - self.preamble().encode_with_default(buf, input, "")?; - - let children = self.get_values(); - let len = children.len(); - for (i, (key_path, value)) in children.into_iter().enumerate() { - if i != 0 { - write!(buf, ",")?; - } - let inner_decor = if i == len - 1 { - DEFAULT_TRAILING_VALUE_DECOR - } else { - DEFAULT_VALUE_DECOR - }; - key_path - .as_slice() - .encode(buf, input, DEFAULT_INLINE_KEY_DECOR)?; - write!(buf, "=")?; - value.encode(buf, input, inner_decor)?; +pub(crate) fn encode_table( + this: &InlineTable, + buf: &mut dyn Write, + input: Option<&str>, + default_decor: (&str, &str), +) -> Result { + let decor = this.decor(); + decor.prefix_encode(buf, input, default_decor.0)?; + write!(buf, "{{")?; + this.preamble().encode_with_default(buf, input, "")?; + + let children = this.get_values(); + let len = children.len(); + for (i, (key_path, value)) in children.into_iter().enumerate() { + if i != 0 { + write!(buf, ",")?; } + let inner_decor = if i == len - 1 { + DEFAULT_TRAILING_VALUE_DECOR + } else { + DEFAULT_VALUE_DECOR + }; + encode_key_path_ref(&key_path, buf, input, DEFAULT_INLINE_KEY_DECOR)?; + write!(buf, "=")?; + encode_value(value, buf, input, inner_decor)?; + } - write!(buf, "}}")?; - decor.suffix_encode(buf, input, default_decor.1)?; + write!(buf, "}}")?; + decor.suffix_encode(buf, input, default_decor.1)?; - Ok(()) - } + Ok(()) } -impl Encode for Value { - fn encode( - &self, - buf: &mut dyn Write, - input: Option<&str>, - default_decor: (&str, &str), - ) -> Result { - match self { - Value::String(repr) => repr.encode(buf, input, default_decor), - Value::Integer(repr) => repr.encode(buf, input, default_decor), - Value::Float(repr) => repr.encode(buf, input, default_decor), - Value::Boolean(repr) => repr.encode(buf, input, default_decor), - Value::Datetime(repr) => repr.encode(buf, input, default_decor), - Value::Array(array) => array.encode(buf, input, default_decor), - Value::InlineTable(table) => table.encode(buf, input, default_decor), - } +pub(crate) fn encode_value( + this: &Value, + buf: &mut dyn Write, + input: Option<&str>, + default_decor: (&str, &str), +) -> Result { + match this { + Value::String(repr) => encode_formatted(repr, buf, input, default_decor), + Value::Integer(repr) => encode_formatted(repr, buf, input, default_decor), + Value::Float(repr) => encode_formatted(repr, buf, input, default_decor), + Value::Boolean(repr) => encode_formatted(repr, buf, input, default_decor), + Value::Datetime(repr) => encode_formatted(repr, buf, input, default_decor), + Value::Array(array) => encode_array(array, buf, input, default_decor), + Value::InlineTable(table) => encode_table(table, buf, input, default_decor), } } @@ -275,11 +242,7 @@ where for kv in table.items.values() { match kv.value { Item::Table(ref t) => { - let mut key = kv.key.clone(); - if t.is_dotted() { - // May have newlines and generally isn't written for standard tables - key.decor_mut().clear(); - } + let key = kv.key.clone(); path.push(key); visit_nested_tables(t, path, false, callback)?; path.pop(); @@ -332,7 +295,7 @@ fn visit_table( }; table.decor.prefix_encode(buf, input, default_decor.0)?; write!(buf, "[[")?; - path.encode(buf, input, DEFAULT_KEY_PATH_DECOR)?; + encode_key_path(path, buf, input, DEFAULT_KEY_PATH_DECOR)?; write!(buf, "]]")?; table.decor.suffix_encode(buf, input, default_decor.1)?; writeln!(buf)?; @@ -345,16 +308,16 @@ fn visit_table( }; table.decor.prefix_encode(buf, input, default_decor.0)?; write!(buf, "[")?; - path.encode(buf, input, DEFAULT_KEY_PATH_DECOR)?; + encode_key_path(path, buf, input, DEFAULT_KEY_PATH_DECOR)?; write!(buf, "]")?; table.decor.suffix_encode(buf, input, default_decor.1)?; writeln!(buf)?; } // print table body for (key_path, value) in children { - key_path.as_slice().encode(buf, input, DEFAULT_KEY_DECOR)?; + encode_key_path_ref(&key_path, buf, input, DEFAULT_KEY_DECOR)?; write!(buf, "=")?; - value.encode(buf, input, DEFAULT_VALUE_DECOR)?; + encode_value(value, buf, input, DEFAULT_VALUE_DECOR)?; writeln!(buf)?; } Ok(()) @@ -390,7 +353,7 @@ pub(crate) fn to_string_repr( '\u{8}' => output.push_str("\\b"), '\u{9}' => output.push_str("\\t"), '\u{a}' => match style { - StringStyle::NewlineTripple => output.push('\n'), + StringStyle::NewlineTriple => output.push('\n'), StringStyle::OnelineSingle => output.push_str("\\n"), _ => unreachable!(), }, @@ -412,59 +375,56 @@ pub(crate) fn to_string_repr( #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub(crate) enum StringStyle { - NewlineTripple, - OnelineTripple, + NewlineTriple, + OnelineTriple, OnelineSingle, } impl StringStyle { fn literal_start(self) -> &'static str { match self { - Self::NewlineTripple => "'''\n", - Self::OnelineTripple => "'''", + Self::NewlineTriple => "'''\n", + Self::OnelineTriple => "'''", Self::OnelineSingle => "'", } } fn literal_end(self) -> &'static str { match self { - Self::NewlineTripple => "'''", - Self::OnelineTripple => "'''", + Self::NewlineTriple => "'''", + Self::OnelineTriple => "'''", Self::OnelineSingle => "'", } } fn standard_start(self) -> &'static str { match self { - Self::NewlineTripple => "\"\"\"\n", - // note: OnelineTripple can happen if do_pretty wants to do + Self::NewlineTriple => "\"\"\"\n", + // note: OnelineTriple can happen if do_pretty wants to do // '''it's one line''' // but literal == false - Self::OnelineTripple | Self::OnelineSingle => "\"", + Self::OnelineTriple | Self::OnelineSingle => "\"", } } fn standard_end(self) -> &'static str { match self { - Self::NewlineTripple => "\"\"\"", - // note: OnelineTripple can happen if do_pretty wants to do + Self::NewlineTriple => "\"\"\"", + // note: OnelineTriple can happen if do_pretty wants to do // '''it's one line''' // but literal == false - Self::OnelineTripple | Self::OnelineSingle => "\"", + Self::OnelineTriple | Self::OnelineSingle => "\"", } } } fn infer_style(value: &str) -> (StringStyle, bool) { - // For doing pretty prints we store in a new String - // because there are too many cases where pretty cannot - // work. We need to determine: + // We need to determine: // - if we are a "multi-line" pretty (if there are \n) // - if ['''] appears if multi or ['] if single // - if there are any invalid control characters // // Doing it any other way would require multiple passes // to determine if a pretty string works or not. - let mut out = String::with_capacity(value.len() * 2); let mut ty = StringStyle::OnelineSingle; // found consecutive single quotes let mut max_found_singles = 0; @@ -490,18 +450,17 @@ fn infer_style(value: &str) -> (StringStyle, bool) { '\\' => { prefer_literal = true; } - '\n' => ty = StringStyle::NewlineTripple, + '\n' => ty = StringStyle::NewlineTriple, // Escape codes are needed if any ascii control // characters are present, including \b \f \r. c if c <= '\u{1f}' || c == '\u{7f}' => can_be_pretty = false, _ => {} } - out.push(ch); } else { // the string cannot be represented as pretty, // still check if it should be multiline if ch == '\n' { - ty = StringStyle::NewlineTripple; + ty = StringStyle::NewlineTriple; } } } @@ -513,7 +472,7 @@ fn infer_style(value: &str) -> (StringStyle, bool) { can_be_pretty = false; } if !can_be_pretty { - debug_assert!(ty != StringStyle::OnelineTripple); + debug_assert!(ty != StringStyle::OnelineTriple); return (ty, false); } if found_singles > max_found_singles { @@ -522,7 +481,7 @@ fn infer_style(value: &str) -> (StringStyle, bool) { debug_assert!(max_found_singles < 3); if ty == StringStyle::OnelineSingle && max_found_singles >= 1 { // no newlines, but must use ''' because it has ' in it - ty = StringStyle::OnelineTripple; + ty = StringStyle::OnelineTriple; } (ty, true) } diff --git a/src/parser/errors.rs b/src/error.rs index 859ed53..a983019 100644 --- a/src/parser/errors.rs +++ b/src/error.rs @@ -1,12 +1,6 @@ use std::error::Error as StdError; use std::fmt::{Display, Formatter, Result}; -use crate::parser::prelude::*; -use crate::Key; - -use winnow::error::ContextError; -use winnow::error::ParseError; - /// Type representing a TOML parse error #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct TomlError { @@ -17,7 +11,14 @@ pub struct TomlError { } impl TomlError { - pub(crate) fn new(error: ParseError<Input<'_>, ContextError>, mut original: Input<'_>) -> Self { + #[cfg(feature = "parse")] + pub(crate) fn new( + error: winnow::error::ParseError< + crate::parser::prelude::Input<'_>, + winnow::error::ContextError, + >, + mut original: crate::parser::prelude::Input<'_>, + ) -> Self { use winnow::stream::Stream; let offset = error.offset(); @@ -166,7 +167,6 @@ fn translate_position(input: &[u8], index: usize) -> (usize, usize) { None => 0, }; let line = input[0..line_start].iter().filter(|b| **b == b'\n').count(); - let line = line; let column = std::str::from_utf8(&input[line_start..=index]) .map(|s| s.chars().count() - 1) @@ -244,73 +244,3 @@ mod test_translate_position { assert_eq!(position, (1, 2)); } } - -#[derive(Debug, Clone)] -pub(crate) enum CustomError { - DuplicateKey { - key: String, - table: Option<Vec<Key>>, - }, - DottedKeyExtendWrongType { - key: Vec<Key>, - actual: &'static str, - }, - OutOfRange, - #[cfg_attr(feature = "unbounded", allow(dead_code))] - RecursionLimitExceeded, -} - -impl CustomError { - pub(crate) fn duplicate_key(path: &[Key], i: usize) -> Self { - assert!(i < path.len()); - let key = &path[i]; - let repr = key.display_repr(); - Self::DuplicateKey { - key: repr.into(), - table: Some(path[..i].to_vec()), - } - } - - pub(crate) fn extend_wrong_type(path: &[Key], i: usize, actual: &'static str) -> Self { - assert!(i < path.len()); - Self::DottedKeyExtendWrongType { - key: path[..=i].to_vec(), - actual, - } - } -} - -impl StdError for CustomError { - fn description(&self) -> &'static str { - "TOML parse error" - } -} - -impl Display for CustomError { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - match self { - CustomError::DuplicateKey { key, table } => { - if let Some(table) = table { - if table.is_empty() { - write!(f, "duplicate key `{}` in document root", key) - } else { - let path = table.iter().map(|k| k.get()).collect::<Vec<_>>().join("."); - write!(f, "duplicate key `{}` in table `{}`", key, path) - } - } else { - write!(f, "duplicate key `{}`", key) - } - } - CustomError::DottedKeyExtendWrongType { key, actual } => { - let path = key.iter().map(|k| k.get()).collect::<Vec<_>>().join("."); - write!( - f, - "dotted key `{}` attempted to extend non-table type ({})", - path, actual - ) - } - CustomError::OutOfRange => write!(f, "value is out of range"), - CustomError::RecursionLimitExceeded => write!(f, "recursion limit exceded"), - } - } -} diff --git a/src/inline_table.rs b/src/inline_table.rs index 3dc6c0c..316637d 100644 --- a/src/inline_table.rs +++ b/src/inline_table.rs @@ -11,6 +11,8 @@ use crate::{InternalString, Item, KeyMut, RawString, Table, Value}; pub struct InlineTable { // `preamble` represents whitespaces in an empty table preamble: RawString, + // Whether to hide an empty table + pub(crate) implicit: bool, // prefix before `{` and suffix after `}` decor: Decor, pub(crate) span: Option<std::ops::Range<usize>>, @@ -55,10 +57,10 @@ impl InlineTable { values } - pub(crate) fn append_values<'s, 'c>( + pub(crate) fn append_values<'s>( &'s self, parent: &[&'s Key], - values: &'c mut Vec<(Vec<&'s Key>, &'s Value)>, + values: &mut Vec<(Vec<&'s Key>, &'s Value)>, ) { for value in self.items.values() { let mut path = parent.to_vec(); @@ -133,6 +135,36 @@ impl InlineTable { } } + /// If a table has no key/value pairs and implicit, it will not be displayed. + /// + /// # Examples + /// + /// ```notrust + /// [target."x86_64/windows.json".dependencies] + /// ``` + /// + /// In the document above, tables `target` and `target."x86_64/windows.json"` are implicit. + /// + /// ``` + /// # #[cfg(feature = "parse")] { + /// # #[cfg(feature = "display")] { + /// use toml_edit::Document; + /// let mut doc = "[a]\n[a.b]\n".parse::<Document>().expect("invalid toml"); + /// + /// doc["a"].as_table_mut().unwrap().set_implicit(true); + /// assert_eq!(doc.to_string(), "[a.b]\n"); + /// # } + /// # } + /// ``` + pub(crate) fn set_implicit(&mut self, implicit: bool) { + self.implicit = implicit; + } + + /// If a table has no key/value pairs and implicit, it will not be displayed. + pub(crate) fn is_implicit(&self) -> bool { + self.implicit + } + /// Change this table's dotted status pub fn set_dotted(&mut self, yes: bool) { self.dotted = yes; @@ -153,14 +185,28 @@ impl InlineTable { &self.decor } + /// Returns an accessor to a key's formatting + pub fn key(&self, key: &str) -> Option<&'_ Key> { + self.items.get(key).map(|kv| &kv.key) + } + + /// Returns an accessor to a key's formatting + pub fn key_mut(&mut self, key: &str) -> Option<KeyMut<'_>> { + self.items.get_mut(key).map(|kv| kv.key.as_mut()) + } + /// Returns the decor associated with a given key of the table. + #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { - self.items.get_mut(key).map(|kv| &mut kv.key.decor) + #![allow(deprecated)] + self.items.get_mut(key).map(|kv| kv.key.leaf_decor_mut()) } /// Returns the decor associated with a given key of the table. + #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] pub fn key_decor(&self, key: &str) -> Option<&Decor> { - self.items.get(key).map(|kv| &kv.key.decor) + #![allow(deprecated)] + self.items.get(key).map(|kv| kv.key.leaf_decor()) } /// Set whitespace after before element @@ -383,9 +429,10 @@ impl InlineTable { } } +#[cfg(feature = "display")] impl std::fmt::Display for InlineTable { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - crate::encode::Encode::encode(self, f, None, ("", "")) + crate::encode::encode_table(self, f, None, ("", "")) } } @@ -436,13 +483,14 @@ impl<'s> IntoIterator for &'s InlineTable { } fn decorate_inline_table(table: &mut InlineTable) { - for (key_decor, value) in table + for (mut key, value) in table .items .iter_mut() - .filter(|&(_, ref kv)| kv.value.is_value()) - .map(|(_, kv)| (&mut kv.key.decor, kv.value.as_value_mut().unwrap())) + .filter(|(_, kv)| kv.value.is_value()) + .map(|(_, kv)| (kv.key.as_mut(), kv.value.as_value_mut().unwrap())) { - key_decor.clear(); + key.leaf_decor_mut().clear(); + key.dotted_decor_mut().clear(); value.decor_mut().clear(); } } @@ -530,10 +578,18 @@ impl TableLike for InlineTable { self.is_dotted() } + fn key(&self, key: &str) -> Option<&'_ Key> { + self.key(key) + } + fn key_mut(&mut self, key: &str) -> Option<KeyMut<'_>> { + self.key_mut(key) + } fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { + #![allow(deprecated)] self.key_decor_mut(key) } fn key_decor(&self, key: &str) -> Option<&Decor> { + #![allow(deprecated)] self.key_decor(key) } } diff --git a/src/item.rs b/src/item.rs index 2025fd9..b58806e 100644 --- a/src/item.rs +++ b/src/item.rs @@ -7,9 +7,10 @@ use crate::table::TableLike; use crate::{Array, InlineTable, Table, Value}; /// Type representing either a value, a table, an array of tables, or none. -#[derive(Debug)] +#[derive(Debug, Default)] pub enum Item { /// Type representing none. + #[default] None, /// Type representing value. Value(Value), @@ -328,12 +329,7 @@ impl Clone for Item { } } -impl Default for Item { - fn default() -> Self { - Item::None - } -} - +#[cfg(feature = "parse")] impl FromStr for Item { type Err = crate::TomlError; @@ -344,6 +340,7 @@ impl FromStr for Item { } } +#[cfg(feature = "display")] impl std::fmt::Display for Item { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self { @@ -363,6 +360,7 @@ impl std::fmt::Display for Item { /// /// # Examples /// ```rust +/// # #[cfg(feature = "display")] { /// # use snapbox::assert_eq; /// # use toml_edit::*; /// let mut table = Table::default(); @@ -377,6 +375,7 @@ impl std::fmt::Display for Item { /// key2 = 42 /// key3 = ["hello", '\, world'] /// "#); +/// # } /// ``` pub fn value<V: Into<Value>>(v: V) -> Item { Item::Value(v.into()) @@ -1,9 +1,6 @@ use std::borrow::Cow; use std::str::FromStr; -use crate::encode::{to_string_repr, StringStyle}; -use crate::parser; -use crate::parser::key::is_unquoted_char; use crate::repr::{Decor, Repr}; use crate::InternalString; @@ -33,7 +30,8 @@ use crate::InternalString; pub struct Key { key: InternalString, pub(crate) repr: Option<Repr>, - pub(crate) decor: Decor, + pub(crate) leaf_decor: Decor, + pub(crate) dotted_decor: Decor, } impl Key { @@ -42,13 +40,15 @@ impl Key { Self { key: key.into(), repr: None, - decor: Default::default(), + leaf_decor: Default::default(), + dotted_decor: Default::default(), } } /// Parse a TOML key expression /// /// Unlike `"".parse<Key>()`, this supports dotted keys. + #[cfg(feature = "parse")] pub fn parse(repr: &str) -> Result<Vec<Self>, crate::TomlError> { Self::try_parse_path(repr) } @@ -59,8 +59,20 @@ impl Key { } /// While creating the `Key`, add `Decor` to it - pub fn with_decor(mut self, decor: Decor) -> Self { - self.decor = decor; + #[deprecated(since = "0.21.1", note = "Replaced with `with_leaf_decor`")] + pub fn with_decor(self, decor: Decor) -> Self { + self.with_leaf_decor(decor) + } + + /// While creating the `Key`, add `Decor` to it for the line entry + pub fn with_leaf_decor(mut self, decor: Decor) -> Self { + self.leaf_decor = decor; + self + } + + /// While creating the `Key`, add `Decor` to it for between dots + pub fn with_dotted_decor(mut self, decor: Decor) -> Self { + self.dotted_decor = decor; self } @@ -84,11 +96,13 @@ impl Key { } /// Returns the default raw representation. + #[cfg(feature = "display")] pub fn default_repr(&self) -> Repr { to_key_repr(&self.key) } /// Returns a raw representation. + #[cfg(feature = "display")] pub fn display_repr(&self) -> Cow<'_, str> { self.as_repr() .and_then(|r| r.as_raw().as_str()) @@ -99,13 +113,35 @@ impl Key { } /// Returns the surrounding whitespace + #[deprecated(since = "0.21.1", note = "Replaced with `decor_mut`")] pub fn decor_mut(&mut self) -> &mut Decor { - &mut self.decor + self.leaf_decor_mut() + } + + /// Returns the surrounding whitespace for the line entry + pub fn leaf_decor_mut(&mut self) -> &mut Decor { + &mut self.leaf_decor + } + + /// Returns the surrounding whitespace for between dots + pub fn dotted_decor_mut(&mut self) -> &mut Decor { + &mut self.dotted_decor } /// Returns the surrounding whitespace + #[deprecated(since = "0.21.1", note = "Replaced with `decor`")] pub fn decor(&self) -> &Decor { - &self.decor + self.leaf_decor() + } + + /// Returns the surrounding whitespace for the line entry + pub fn leaf_decor(&self) -> &Decor { + &self.leaf_decor + } + + /// Returns the surrounding whitespace for between dots + pub fn dotted_decor(&self) -> &Decor { + &self.dotted_decor } /// Returns the location within the original document @@ -115,7 +151,8 @@ impl Key { } pub(crate) fn despan(&mut self, input: &str) { - self.decor.despan(input); + self.leaf_decor.despan(input); + self.dotted_decor.despan(input); if let Some(repr) = &mut self.repr { repr.despan(input) } @@ -123,18 +160,21 @@ impl Key { /// Auto formats the key. pub fn fmt(&mut self) { - self.repr = Some(to_key_repr(&self.key)); - self.decor.clear(); + self.repr = None; + self.leaf_decor.clear(); + self.dotted_decor.clear(); } + #[cfg(feature = "parse")] fn try_parse_simple(s: &str) -> Result<Key, crate::TomlError> { - let mut key = parser::parse_key(s)?; + let mut key = crate::parser::parse_key(s)?; key.despan(s); Ok(key) } + #[cfg(feature = "parse")] fn try_parse_path(s: &str) -> Result<Vec<Key>, crate::TomlError> { - let mut keys = parser::parse_key_path(s)?; + let mut keys = crate::parser::parse_key_path(s)?; for key in &mut keys { key.despan(s); } @@ -148,7 +188,8 @@ impl Clone for Key { Self { key: self.key.clone(), repr: self.repr.clone(), - decor: self.decor.clone(), + leaf_decor: self.leaf_decor.clone(), + dotted_decor: self.dotted_decor.clone(), } } } @@ -209,12 +250,14 @@ impl PartialEq<String> for Key { } } +#[cfg(feature = "display")] impl std::fmt::Display for Key { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - crate::encode::Encode::encode(self, f, None, ("", "")) + crate::encode::encode_key(self, f, None) } } +#[cfg(feature = "parse")] impl FromStr for Key { type Err = crate::TomlError; @@ -226,11 +269,33 @@ impl FromStr for Key { } } +#[cfg(feature = "display")] fn to_key_repr(key: &str) -> Repr { - if key.as_bytes().iter().copied().all(is_unquoted_char) && !key.is_empty() { - Repr::new_unchecked(key) - } else { - to_string_repr(key, Some(StringStyle::OnelineSingle), Some(false)) + #[cfg(feature = "parse")] + { + if key + .as_bytes() + .iter() + .copied() + .all(crate::parser::key::is_unquoted_char) + && !key.is_empty() + { + Repr::new_unchecked(key) + } else { + crate::encode::to_string_repr( + key, + Some(crate::encode::StringStyle::OnelineSingle), + Some(false), + ) + } + } + #[cfg(not(feature = "parse"))] + { + crate::encode::to_string_repr( + key, + Some(crate::encode::StringStyle::OnelineSingle), + Some(false), + ) } } @@ -265,7 +330,7 @@ impl From<Key> for InternalString { } } -/// A mutable reference to a `Key` +/// A mutable reference to a `Key`'s formatting #[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct KeyMut<'k> { key: &'k mut Key, @@ -283,25 +348,51 @@ impl<'k> KeyMut<'k> { } /// Returns the default raw representation. + #[cfg(feature = "display")] pub fn default_repr(&self) -> Repr { self.key.default_repr() } /// Returns a raw representation. + #[cfg(feature = "display")] pub fn display_repr(&self) -> Cow<str> { self.key.display_repr() } /// Returns the surrounding whitespace + #[deprecated(since = "0.21.1", note = "Replaced with `decor_mut`")] pub fn decor_mut(&mut self) -> &mut Decor { + #![allow(deprecated)] self.key.decor_mut() } + /// Returns the surrounding whitespace for the line entry + pub fn leaf_decor_mut(&mut self) -> &mut Decor { + self.key.leaf_decor_mut() + } + + /// Returns the surrounding whitespace for between dots + pub fn dotted_decor_mut(&mut self) -> &mut Decor { + self.key.dotted_decor_mut() + } + /// Returns the surrounding whitespace + #[deprecated(since = "0.21.1", note = "Replaced with `decor`")] pub fn decor(&self) -> &Decor { + #![allow(deprecated)] self.key.decor() } + /// Returns the surrounding whitespace for the line entry + pub fn leaf_decor(&self) -> &Decor { + self.key.leaf_decor() + } + + /// Returns the surrounding whitespace for between dots + pub fn dotted_decor(&self) -> &Decor { + self.key.dotted_decor() + } + /// Auto formats the key. pub fn fmt(&mut self) { self.key.fmt() @@ -337,6 +428,7 @@ impl<'s> PartialEq<String> for KeyMut<'s> { } } +#[cfg(feature = "display")] impl<'k> std::fmt::Display for KeyMut<'k> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.key, f) @@ -14,6 +14,8 @@ //! # Example //! //! ```rust +//! # #[cfg(feature = "parse")] { +//! # #[cfg(feature = "display")] { //! use toml_edit::{Document, value}; //! //! let toml = r#" @@ -32,47 +34,54 @@ //! c = { d = "hello" } //! "#; //! assert_eq!(doc.to_string(), expected); +//! # } +//! # } //! ``` //! //! ## Controlling formatting //! //! By default, values are created with default formatting //! ```rust +//! # #[cfg(feature = "display")] { //! let mut doc = toml_edit::Document::new(); //! doc["foo"] = toml_edit::value("bar"); //! let expected = r#"foo = "bar" //! "#; //! assert_eq!(doc.to_string(), expected); +//! # } //! ``` //! //! You can choose a custom TOML representation by parsing the value. //! ```rust +//! # #[cfg(feature = "display")] { //! let mut doc = toml_edit::Document::new(); //! doc["foo"] = "'bar'".parse::<toml_edit::Item>().unwrap(); //! let expected = r#"foo = 'bar' //! "#; //! assert_eq!(doc.to_string(), expected); +//! # } //! ``` //! //! ## Limitations //! //! Things it does not preserve: //! -//! * Scattered array of tables (tables are reordered by default, see [test]). -//! * Order of dotted keys, see [issue](https://github.com/ordian/toml_edit/issues/163). +//! * Order of dotted keys, see [issue](https://github.com/toml-rs/toml/issues/163). //! //! [`toml`]: https://docs.rs/toml/latest/toml/ -//! [test]: https://github.com/ordian/toml_edit/blob/f09bd5d075fdb7d2ef8d9bb3270a34506c276753/tests/test_valid.rs#L84 mod array; mod array_of_tables; mod document; +#[cfg(feature = "display")] mod encode; +mod error; mod index; mod inline_table; mod internal_string; mod item; mod key; +#[cfg(feature = "parse")] mod parser; mod raw_string; mod repr; @@ -92,6 +101,7 @@ pub use crate::array_of_tables::{ ArrayOfTables, ArrayOfTablesIntoIter, ArrayOfTablesIter, ArrayOfTablesIterMut, }; pub use crate::document::Document; +pub use crate::error::TomlError; pub use crate::inline_table::{ InlineEntry, InlineOccupiedEntry, InlineTable, InlineTableIntoIter, InlineTableIter, InlineTableIterMut, InlineVacantEntry, @@ -99,7 +109,6 @@ pub use crate::inline_table::{ pub use crate::internal_string::InternalString; pub use crate::item::{array, table, value, Item}; pub use crate::key::{Key, KeyMut}; -pub use crate::parser::TomlError; pub use crate::raw_string::RawString; pub use crate::repr::{Decor, Formatted, Repr}; pub use crate::table::{ diff --git a/src/parser/array.rs b/src/parser/array.rs index e3b1f3f..0783191 100644 --- a/src/parser/array.rs +++ b/src/parser/array.rs @@ -81,6 +81,8 @@ pub(crate) fn array_value<'i>( } #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; diff --git a/src/parser/datetime.rs b/src/parser/datetime.rs index 6e89b97..945dc69 100644 --- a/src/parser/datetime.rs +++ b/src/parser/datetime.rs @@ -1,6 +1,6 @@ use std::ops::RangeInclusive; -use crate::parser::errors::CustomError; +use crate::parser::error::CustomError; use crate::parser::prelude::*; use crate::parser::trivia::from_utf8_unchecked; @@ -9,6 +9,7 @@ use winnow::combinator::alt; use winnow::combinator::cut_err; use winnow::combinator::opt; use winnow::combinator::preceded; +use winnow::stream::Stream as _; use winnow::token::one_of; use winnow::token::take_while; use winnow::trace::trace; @@ -53,12 +54,35 @@ pub(crate) fn date_time(input: &mut Input<'_>) -> PResult<Datetime> { // full-date = date-fullyear "-" date-month "-" date-mday pub(crate) fn full_date(input: &mut Input<'_>) -> PResult<Date> { - trace( - "full-date", - (date_fullyear, b'-', cut_err((date_month, b'-', date_mday))) - .map(|(year, _, (month, _, day))| Date { year, month, day }), - ) - .parse_next(input) + trace("full-date", full_date_).parse_next(input) +} + +fn full_date_(input: &mut Input<'_>) -> PResult<Date> { + let year = date_fullyear.parse_next(input)?; + let _ = b'-'.parse_next(input)?; + let month = cut_err(date_month).parse_next(input)?; + let _ = cut_err(b'-').parse_next(input)?; + let day_start = input.checkpoint(); + let day = cut_err(date_mday).parse_next(input)?; + + let is_leap_year = (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)); + let max_days_in_month = match month { + 2 if is_leap_year => 29, + 2 => 28, + 4 | 6 | 9 | 11 => 30, + _ => 31, + }; + if max_days_in_month < day { + input.reset(day_start); + return Err(winnow::error::ErrMode::from_external_error( + input, + winnow::error::ErrorKind::Verify, + CustomError::OutOfRange, + ) + .cut()); + } + + Ok(Date { year, month, day }) } // partial-time = time-hour ":" time-minute ":" time-second [time-secfrac] @@ -239,6 +263,8 @@ pub(crate) fn unsigned_digits<'i, const MIN: usize, const MAX: usize>( const DIGIT: RangeInclusive<u8> = b'0'..=b'9'; #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; diff --git a/src/parser/error.rs b/src/parser/error.rs new file mode 100644 index 0000000..22e8e66 --- /dev/null +++ b/src/parser/error.rs @@ -0,0 +1,87 @@ +use std::error::Error as StdError; +use std::fmt::{Display, Formatter, Result}; + +use crate::Key; + +#[derive(Debug, Clone)] +pub(crate) enum CustomError { + DuplicateKey { + key: String, + table: Option<Vec<Key>>, + }, + DottedKeyExtendWrongType { + key: Vec<Key>, + actual: &'static str, + }, + OutOfRange, + #[cfg_attr(feature = "unbounded", allow(dead_code))] + RecursionLimitExceeded, +} + +impl CustomError { + pub(crate) fn duplicate_key(path: &[Key], i: usize) -> Self { + assert!(i < path.len()); + let key = &path[i]; + let repr = key + .as_repr() + .and_then(|key| key.as_raw().as_str()) + .map(|s| s.to_owned()) + .unwrap_or_else(|| { + #[cfg(feature = "display")] + { + key.default_repr().as_raw().as_str().unwrap().to_owned() + } + #[cfg(not(feature = "display"))] + { + format!("{:?}", key.get()) + } + }); + Self::DuplicateKey { + key: repr, + table: Some(path[..i].to_vec()), + } + } + + pub(crate) fn extend_wrong_type(path: &[Key], i: usize, actual: &'static str) -> Self { + assert!(i < path.len()); + Self::DottedKeyExtendWrongType { + key: path[..=i].to_vec(), + actual, + } + } +} + +impl StdError for CustomError { + fn description(&self) -> &'static str { + "TOML parse error" + } +} + +impl Display for CustomError { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self { + CustomError::DuplicateKey { key, table } => { + if let Some(table) = table { + if table.is_empty() { + write!(f, "duplicate key `{}` in document root", key) + } else { + let path = table.iter().map(|k| k.get()).collect::<Vec<_>>().join("."); + write!(f, "duplicate key `{}` in table `{}`", key, path) + } + } else { + write!(f, "duplicate key `{}`", key) + } + } + CustomError::DottedKeyExtendWrongType { key, actual } => { + let path = key.iter().map(|k| k.get()).collect::<Vec<_>>().join("."); + write!( + f, + "dotted key `{}` attempted to extend non-table type ({})", + path, actual + ) + } + CustomError::OutOfRange => write!(f, "value is out of range"), + CustomError::RecursionLimitExceeded => write!(f, "recursion limit exceeded"), + } + } +} diff --git a/src/parser/inline_table.rs b/src/parser/inline_table.rs index 994e003..c2e6619 100644 --- a/src/parser/inline_table.rs +++ b/src/parser/inline_table.rs @@ -5,7 +5,7 @@ use winnow::token::one_of; use winnow::trace::trace; use crate::key::Key; -use crate::parser::errors::CustomError; +use crate::parser::error::CustomError; use crate::parser::key::key; use crate::parser::prelude::*; use crate::parser::trivia::ws; @@ -44,6 +44,16 @@ fn table_from_pairs( for (path, kv) in v { let table = descend_path(&mut root, &path)?; + + // "Likewise, using dotted keys to redefine tables already defined in [table] form is not allowed" + let mixed_table_types = table.is_dotted() == path.is_empty(); + if mixed_table_types { + return Err(CustomError::DuplicateKey { + key: kv.key.get().into(), + table: None, + }); + } + let key: InternalString = kv.key.get_internal().into(); match table.items.entry(key) { Entry::Vacant(o) => { @@ -64,15 +74,26 @@ fn descend_path<'a>( mut table: &'a mut InlineTable, path: &'a [Key], ) -> Result<&'a mut InlineTable, CustomError> { + let dotted = !path.is_empty(); for (i, key) in path.iter().enumerate() { let entry = table.entry_format(key).or_insert_with(|| { let mut new_table = InlineTable::new(); - new_table.set_dotted(true); + new_table.set_implicit(dotted); + new_table.set_dotted(dotted); Value::InlineTable(new_table) }); match *entry { Value::InlineTable(ref mut sweet_child_of_mine) => { + // Since tables cannot be defined more than once, redefining such tables using a + // [table] header is not allowed. Likewise, using dotted keys to redefine tables + // already defined in [table] form is not allowed. + if dotted && !sweet_child_of_mine.is_implicit() { + return Err(CustomError::DuplicateKey { + key: key.get().into(), + table: None, + }); + } table = sweet_child_of_mine; } ref v => { @@ -144,6 +165,8 @@ fn keyval<'i>( } #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; diff --git a/src/parser/key.rs b/src/parser/key.rs index 12715da..e72b195 100644 --- a/src/parser/key.rs +++ b/src/parser/key.rs @@ -7,7 +7,7 @@ use winnow::token::take_while; use winnow::trace::trace; use crate::key::Key; -use crate::parser::errors::CustomError; +use crate::parser::error::CustomError; use crate::parser::prelude::*; use crate::parser::strings::{basic_string, literal_string}; use crate::parser::trivia::{from_utf8_unchecked, ws}; @@ -18,13 +18,13 @@ use crate::RawString; // key = simple-key / dotted-key // dotted-key = simple-key 1*( dot-sep simple-key ) pub(crate) fn key(input: &mut Input<'_>) -> PResult<Vec<Key>> { - trace( + let mut key_path = trace( "dotted-key", separated1( (ws.span(), simple_key, ws.span()).map(|(pre, (raw, key), suffix)| { Key::new(key) .with_repr_unchecked(Repr::new_unchecked(raw)) - .with_decor(Decor::new( + .with_dotted_decor(Decor::new( RawString::with_span(pre), RawString::with_span(suffix), )) @@ -38,7 +38,31 @@ pub(crate) fn key(input: &mut Input<'_>) -> PResult<Vec<Key>> { Ok::<_, CustomError>(k) }), ) - .parse_next(input) + .parse_next(input)?; + + let mut leaf_decor = Decor::new("", ""); + { + let first_dotted_decor = key_path + .first_mut() + .expect("always at least one key") + .dotted_decor_mut(); + if let Some(prefix) = first_dotted_decor.prefix().cloned() { + leaf_decor.set_prefix(prefix); + first_dotted_decor.set_prefix(""); + } + } + let last_key = &mut key_path.last_mut().expect("always at least one key"); + { + let last_dotted_decor = last_key.dotted_decor_mut(); + if let Some(suffix) = last_dotted_decor.suffix().cloned() { + leaf_decor.set_suffix(suffix); + last_dotted_decor.set_suffix(""); + } + } + + *last_key.leaf_decor_mut() = leaf_decor; + + Ok(key_path) } // simple-key = quoted-key / unquoted-key @@ -88,6 +112,8 @@ const UNQUOTED_CHAR: ( const DOT_SEP: u8 = b'.'; #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; @@ -96,7 +122,7 @@ mod test { let cases = [ ("a", "a"), (r#""hello\n ""#, "hello\n "), - (r#"'hello\n '"#, "hello\\n "), + (r"'hello\n '", "hello\\n "), ]; for (input, expected) in cases { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 1b3cc4f..e032202 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -3,7 +3,7 @@ pub(crate) mod array; pub(crate) mod datetime; pub(crate) mod document; -pub(crate) mod errors; +pub(crate) mod error; pub(crate) mod inline_table; pub(crate) mod key; pub(crate) mod numbers; @@ -13,7 +13,7 @@ pub(crate) mod table; pub(crate) mod trivia; pub(crate) mod value; -pub use errors::TomlError; +pub use crate::error::TomlError; pub(crate) fn parse_document(raw: &str) -> Result<crate::Document, TomlError> { use prelude::*; @@ -95,11 +95,11 @@ pub(crate) mod prelude { #[cfg(not(feature = "unbounded"))] impl RecursionCheck { - pub(crate) fn check_depth(depth: usize) -> Result<(), super::errors::CustomError> { + pub(crate) fn check_depth(depth: usize) -> Result<(), super::error::CustomError> { if depth < 128 { Ok(()) } else { - Err(super::errors::CustomError::RecursionLimitExceeded) + Err(super::error::CustomError::RecursionLimitExceeded) } } @@ -114,7 +114,7 @@ pub(crate) mod prelude { Err(winnow::error::ErrMode::from_external_error( input, winnow::error::ErrorKind::Eof, - super::errors::CustomError::RecursionLimitExceeded, + super::error::CustomError::RecursionLimitExceeded, )) } } @@ -126,7 +126,7 @@ pub(crate) mod prelude { #[cfg(feature = "unbounded")] impl RecursionCheck { - pub(crate) fn check_depth(_depth: usize) -> Result<(), super::errors::CustomError> { + pub(crate) fn check_depth(_depth: usize) -> Result<(), super::error::CustomError> { Ok(()) } @@ -140,6 +140,8 @@ pub(crate) mod prelude { } #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; @@ -182,10 +184,10 @@ hosts = [ "omega" ] - 'some.wierd .stuff' = """ + 'some.weird .stuff' = """ like that - # """ # this broke my sintax highlighting + # """ # this broke my syntax highlighting " also. like " = ''' that ''' diff --git a/src/parser/numbers.rs b/src/parser/numbers.rs index 6e4757f..9681526 100644 --- a/src/parser/numbers.rs +++ b/src/parser/numbers.rs @@ -301,7 +301,7 @@ pub(crate) fn inf(input: &mut Input<'_>) -> PResult<f64> { const INF: &[u8] = b"inf"; // nan = %x6e.61.6e ; nan pub(crate) fn nan(input: &mut Input<'_>) -> PResult<f64> { - tag(NAN).value(f64::NAN).parse_next(input) + tag(NAN).value(f64::NAN.copysign(1.0)).parse_next(input) } const NAN: &[u8] = b"nan"; @@ -319,6 +319,8 @@ pub(crate) const HEXDIG: (RangeInclusive<u8>, RangeInclusive<u8>, RangeInclusive (DIGIT, b'A'..=b'F', b'a'..=b'f'); #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; @@ -353,6 +355,7 @@ mod test { fn assert_float_eq(actual: f64, expected: f64) { if expected.is_nan() { assert!(actual.is_nan()); + assert_eq!(expected.is_sign_positive(), actual.is_sign_positive()); } else if expected.is_infinite() { assert!(actual.is_infinite()); assert_eq!(expected.is_sign_positive(), actual.is_sign_positive()); @@ -376,9 +379,9 @@ mod test { ("9_224_617.445_991_228_313", 9_224_617.445_991_227), ("-1.7976931348623157e+308", std::f64::MIN), ("1.7976931348623157e+308", std::f64::MAX), - ("nan", f64::NAN), - ("+nan", f64::NAN), - ("-nan", f64::NAN), + ("nan", f64::NAN.copysign(1.0)), + ("+nan", f64::NAN.copysign(1.0)), + ("-nan", f64::NAN.copysign(-1.0)), ("inf", f64::INFINITY), ("+inf", f64::INFINITY), ("-inf", f64::NEG_INFINITY), diff --git a/src/parser/state.rs b/src/parser/state.rs index efa884d..187dd5f 100644 --- a/src/parser/state.rs +++ b/src/parser/state.rs @@ -1,5 +1,5 @@ use crate::key::Key; -use crate::parser::errors::CustomError; +use crate::parser::error::CustomError; use crate::repr::Decor; use crate::table::TableKeyValue; use crate::{ArrayOfTables, Document, InternalString, Item, RawString, Table}; @@ -39,26 +39,21 @@ impl ParseState { pub(crate) fn on_keyval( &mut self, - mut path: Vec<Key>, + path: Vec<Key>, mut kv: TableKeyValue, ) -> Result<(), CustomError> { { let mut prefix = self.trailing.take(); - let first_key = if path.is_empty() { - &mut kv.key - } else { - &mut path[0] - }; let prefix = match ( prefix.take(), - first_key.decor.prefix().and_then(|d| d.span()), + kv.key.leaf_decor.prefix().and_then(|d| d.span()), ) { (Some(p), Some(k)) => Some(p.start..k.end), (Some(p), None) | (None, Some(p)) => Some(p), (None, None) => None, }; - first_key - .decor + kv.key + .leaf_decor .set_prefix(prefix.map(RawString::with_span).unwrap_or_default()); } @@ -94,7 +89,7 @@ impl ParseState { Ok(()) } - pub(crate) fn start_aray_table( + pub(crate) fn start_array_table( &mut self, path: Vec<Key>, decor: Decor, @@ -217,9 +212,9 @@ impl ParseState { Ok(()) } - pub(crate) fn descend_path<'t, 'k>( + pub(crate) fn descend_path<'t>( mut table: &'t mut Table, - path: &'k [Key], + path: &[Key], dotted: bool, ) -> Result<&'t mut Table, CustomError> { for (i, key) in path.iter().enumerate() { @@ -297,7 +292,7 @@ impl ParseState { .take() .map(RawString::with_span) .unwrap_or_default(); - self.start_aray_table( + self.start_array_table( path, Decor::new(leading, RawString::with_span(trailing)), span, diff --git a/src/parser/strings.rs b/src/parser/strings.rs index 26f9cc2..675b5c6 100644 --- a/src/parser/strings.rs +++ b/src/parser/strings.rs @@ -21,7 +21,7 @@ use winnow::token::tag; use winnow::token::take_while; use winnow::trace::trace; -use crate::parser::errors::CustomError; +use crate::parser::error::CustomError; use crate::parser::numbers::HEXDIG; use crate::parser::prelude::*; use crate::parser::trivia::{from_utf8_unchecked, newline, ws, ws_newlines, NON_ASCII, WSCHAR}; @@ -363,6 +363,8 @@ fn mll_quotes<'i>( } #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; @@ -440,10 +442,10 @@ The quick brown \ #[test] fn literal_string() { let inputs = [ - r#"'C:\Users\nodejs\templates'"#, - r#"'\\ServerX\admin$\system32\'"#, + r"'C:\Users\nodejs\templates'", + r"'\\ServerX\admin$\system32\'", r#"'Tom "Dubs" Preston-Werner'"#, - r#"'<\i\c*\s*>'"#, + r"'<\i\c*\s*>'", ]; for input in &inputs { @@ -456,7 +458,7 @@ The quick brown \ #[test] fn ml_literal_string() { let inputs = [ - r#"'''I [dw]on't need \d{2} apples'''"#, + r"'''I [dw]on't need \d{2} apples'''", r#"''''one_quote''''"#, ]; for input in &inputs { diff --git a/src/parser/trivia.rs b/src/parser/trivia.rs index a359805..4575fb1 100644 --- a/src/parser/trivia.rs +++ b/src/parser/trivia.rs @@ -120,6 +120,8 @@ pub(crate) fn line_trailing(input: &mut Input<'_>) -> PResult<std::ops::Range<us } #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; diff --git a/src/parser/value.rs b/src/parser/value.rs index 14cd951..33300ec 100644 --- a/src/parser/value.rs +++ b/src/parser/value.rs @@ -121,6 +121,8 @@ fn apply_raw(mut val: Value, span: std::ops::Range<usize>) -> Result<Value, std: } #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod test { use super::*; @@ -131,7 +133,7 @@ mod test { "-239", "1e200", "9_224_617.445_991_228_313", - r#"'''I [dw]on't need \d{2} apples'''"#, + r"'''I [dw]on't need \d{2} apples'''", r#"''' The first newline is trimmed in raw strings. diff --git a/src/raw_string.rs b/src/raw_string.rs index c5961f1..53714a1 100644 --- a/src/raw_string.rs +++ b/src/raw_string.rs @@ -80,6 +80,7 @@ impl RawString { } } + #[cfg(feature = "display")] pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result { let raw = self.to_str(input); for part in raw.split('\r') { @@ -88,6 +89,7 @@ impl RawString { Ok(()) } + #[cfg(feature = "display")] pub(crate) fn encode_with_default( &self, buf: &mut dyn std::fmt::Write, diff --git a/src/repr.rs b/src/repr.rs index d4ab6c2..ad41bbf 100644 --- a/src/repr.rs +++ b/src/repr.rs @@ -44,11 +44,13 @@ where } /// Returns the default raw representation. + #[cfg(feature = "display")] pub fn default_repr(&self) -> Repr { self.value.to_repr() } /// Returns a raw representation. + #[cfg(feature = "display")] pub fn display_repr(&self) -> Cow<str> { self.as_repr() .and_then(|r| r.as_raw().as_str()) @@ -82,7 +84,7 @@ where /// Auto formats the value. pub fn fmt(&mut self) { - self.repr = Some(self.value.to_repr()); + self.repr = None; } } @@ -103,20 +105,33 @@ where } } +#[cfg(feature = "display")] impl<T> std::fmt::Display for Formatted<T> where T: ValueRepr, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - crate::encode::Encode::encode(self, f, None, ("", "")) + crate::encode::encode_formatted(self, f, None, ("", "")) } } pub trait ValueRepr: crate::private::Sealed { /// The TOML representation of the value + #[cfg(feature = "display")] fn to_repr(&self) -> Repr; } +#[cfg(not(feature = "display"))] +mod inner { + use super::ValueRepr; + + impl ValueRepr for String {} + impl ValueRepr for i64 {} + impl ValueRepr for f64 {} + impl ValueRepr for bool {} + impl ValueRepr for toml_datetime::Datetime {} +} + /// TOML-encoded value #[derive(Eq, PartialEq, Clone, Hash)] pub struct Repr { @@ -144,6 +159,7 @@ impl Repr { self.raw_value.despan(input) } + #[cfg(feature = "display")] pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result { self.as_raw().encode(buf, input) } @@ -185,6 +201,7 @@ impl Decor { self.prefix.as_ref() } + #[cfg(feature = "display")] pub(crate) fn prefix_encode( &self, buf: &mut dyn std::fmt::Write, @@ -208,6 +225,7 @@ impl Decor { self.suffix.as_ref() } + #[cfg(feature = "display")] pub(crate) fn suffix_encode( &self, buf: &mut dyn std::fmt::Write, diff --git a/src/ser/map.rs b/src/ser/map.rs index d743e3d..47e56ba 100644 --- a/src/ser/map.rs +++ b/src/ser/map.rs @@ -1,4 +1,4 @@ -use super::{Error, KeySerializer}; +use super::{Error, KeySerializer, SerializeValueArray, ValueSerializer}; #[doc(hidden)] pub enum SerializeMap { @@ -165,7 +165,6 @@ impl serde::ser::SerializeMap for SerializeInlineTable { where T: serde::ser::Serialize, { - self.key = None; self.key = Some(input.serialize(KeySerializer)?); Ok(()) } @@ -174,7 +173,8 @@ impl serde::ser::SerializeMap for SerializeInlineTable { where T: serde::ser::Serialize, { - let res = value.serialize(super::ValueSerializer {}); + let mut value_serializer = MapValueSerializer::new(); + let res = value.serialize(&mut value_serializer); match res { Ok(item) => { let key = self.key.take().unwrap(); @@ -185,7 +185,7 @@ impl serde::ser::SerializeMap for SerializeInlineTable { self.items.insert(key, kv); } Err(e) => { - if e != Error::UnsupportedNone { + if !(e == Error::UnsupportedNone && value_serializer.is_none) { return Err(e); } } @@ -210,7 +210,8 @@ impl serde::ser::SerializeStruct for SerializeInlineTable { where T: serde::ser::Serialize, { - let res = value.serialize(super::ValueSerializer {}); + let mut value_serializer = MapValueSerializer::new(); + let res = value.serialize(&mut value_serializer); match res { Ok(item) => { let kv = crate::table::TableKeyValue::new( @@ -220,7 +221,7 @@ impl serde::ser::SerializeStruct for SerializeInlineTable { self.items.insert(crate::InternalString::from(key), kv); } Err(e) => { - if e != Error::UnsupportedNone { + if !(e == Error::UnsupportedNone && value_serializer.is_none) { return Err(e); } } @@ -403,3 +404,261 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { Err(Error::DateInvalid) } } + +#[derive(Default)] +struct MapValueSerializer { + is_none: bool, +} + +impl MapValueSerializer { + fn new() -> Self { + Self { is_none: false } + } +} + +impl serde::ser::Serializer for &mut MapValueSerializer { + type Ok = crate::Value; + type Error = Error; + type SerializeSeq = super::SerializeValueArray; + type SerializeTuple = super::SerializeValueArray; + type SerializeTupleStruct = super::SerializeValueArray; + type SerializeTupleVariant = super::SerializeTupleVariant; + type SerializeMap = super::SerializeMap; + type SerializeStruct = super::SerializeMap; + type SerializeStructVariant = super::SerializeStructVariant; + + fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_bool(v) + } + + fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_i8(v) + } + + fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_i16(v) + } + + fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_i32(v) + } + + fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_i64(v) + } + + fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_u8(v) + } + + fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_u16(v) + } + + fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_u32(v) + } + + fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_u64(v) + } + + fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_f32(v) + } + + fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_f64(v) + } + + fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_char(v) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_str(v) + } + + fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_bytes(value) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + self.is_none = true; + Err(Error::UnsupportedNone) + } + + fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + ValueSerializer::new().serialize_some(value) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_unit() + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_unit_struct(name) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + ValueSerializer::new().serialize_unit_variant(name, variant_index, variant) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + name: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + ValueSerializer::new().serialize_newtype_struct(name, value) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + ValueSerializer::new().serialize_newtype_variant(name, variant_index, variant, value) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + ValueSerializer::new().serialize_seq(len) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + ValueSerializer::new().serialize_tuple(len) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + ValueSerializer::new().serialize_tuple_struct(name, len) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + ValueSerializer::new().serialize_tuple_variant(name, variant_index, variant, len) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + ValueSerializer::new().serialize_map(len) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + ValueSerializer::new().serialize_struct(name, len) + } + + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + ValueSerializer::new().serialize_struct_variant(name, variant_index, variant, len) + } +} + +pub type SerializeTupleVariant = SerializeVariant<SerializeValueArray>; +pub type SerializeStructVariant = SerializeVariant<SerializeMap>; + +pub struct SerializeVariant<T> { + variant: &'static str, + inner: T, +} + +impl SerializeVariant<SerializeValueArray> { + pub(crate) fn tuple(variant: &'static str, len: usize) -> Self { + Self { + variant, + inner: SerializeValueArray::with_capacity(len), + } + } +} + +impl SerializeVariant<SerializeMap> { + pub(crate) fn struct_(variant: &'static str, len: usize) -> Self { + Self { + variant, + inner: SerializeMap::table_with_capacity(len), + } + } +} + +impl serde::ser::SerializeTupleVariant for SerializeVariant<SerializeValueArray> { + type Ok = crate::Value; + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + serde::ser::SerializeSeq::serialize_element(&mut self.inner, value) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + let inner = serde::ser::SerializeSeq::end(self.inner)?; + let mut items = crate::table::KeyValuePairs::new(); + let kv = crate::table::TableKeyValue::new( + crate::Key::new(self.variant), + crate::Item::Value(inner), + ); + items.insert(crate::InternalString::from(self.variant), kv); + Ok(crate::Value::InlineTable(crate::InlineTable::with_pairs( + items, + ))) + } +} + +impl serde::ser::SerializeStructVariant for SerializeVariant<SerializeMap> { + type Ok = crate::Value; + type Error = Error; + + #[inline] + fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + serde::ser::SerializeStruct::serialize_field(&mut self.inner, key, value) + } + + #[inline] + fn end(self) -> Result<Self::Ok, Self::Error> { + let inner = serde::ser::SerializeStruct::end(self.inner)?; + let mut items = crate::table::KeyValuePairs::new(); + let kv = crate::table::TableKeyValue::new( + crate::Key::new(self.variant), + crate::Item::Value(inner), + ); + items.insert(crate::InternalString::from(self.variant), kv); + Ok(crate::Value::InlineTable(crate::InlineTable::with_pairs( + items, + ))) + } +} diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 2c31020..ba31708 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -24,7 +24,7 @@ pub enum Error { OutOfRange(Option<&'static str>), /// `None` could not be serialized to TOML UnsupportedNone, - /// Key was not convertable to `String` for serializing to TOML + /// Key was not convertible to `String` for serializing to TOML KeyNotString, /// A serialized date was invalid DateInvalid, @@ -84,6 +84,7 @@ impl std::error::Error for Error {} /// Serialization can fail if `T`'s implementation of `Serialize` decides to /// fail, if `T` contains a map with non-string keys, or if `T` attempts to /// serialize an unsupported datatype such as an enum, tuple, or tuple struct. +#[cfg(feature = "display")] pub fn to_vec<T: ?Sized>(value: &T) -> Result<Vec<u8>, Error> where T: serde::ser::Serialize, @@ -127,6 +128,7 @@ where /// let toml = toml_edit::ser::to_string(&config).unwrap(); /// println!("{}", toml) /// ``` +#[cfg(feature = "display")] pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error> where T: serde::ser::Serialize, @@ -138,6 +140,7 @@ where /// /// This is identical to `to_string` except the output string has a more /// "pretty" output. See `ValueSerializer::pretty` for more details. +#[cfg(feature = "display")] pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error> where T: serde::ser::Serialize, diff --git a/src/ser/value.rs b/src/ser/value.rs index d29390a..47a17a3 100644 --- a/src/ser/value.rs +++ b/src/ser/value.rs @@ -60,10 +60,10 @@ impl serde::ser::Serializer for ValueSerializer { type SerializeSeq = super::SerializeValueArray; type SerializeTuple = super::SerializeValueArray; type SerializeTupleStruct = super::SerializeValueArray; - type SerializeTupleVariant = super::SerializeValueArray; + type SerializeTupleVariant = super::SerializeTupleVariant; type SerializeMap = super::SerializeMap; type SerializeStruct = super::SerializeMap; - type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + type SerializeStructVariant = super::SerializeStructVariant; fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { Ok(v.into()) @@ -108,7 +108,17 @@ impl serde::ser::Serializer for ValueSerializer { self.serialize_f64(v as f64) } - fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + fn serialize_f64(self, mut v: f64) -> Result<Self::Ok, Self::Error> { + // Discard sign of NaN when serialized using Serde. + // + // In all likelihood the sign of NaNs is not meaningful in the user's + // program. Ending up with `-nan` in the TOML document would usually be + // surprising and undesirable, when the sign of the NaN was not + // intentionally controlled by the caller, or may even be + // nondeterministic if it comes from arithmetic operations or a cast. + if v.is_nan() { + v = v.copysign(1.0); + } Ok(v.into()) } @@ -205,10 +215,10 @@ impl serde::ser::Serializer for ValueSerializer { self, _name: &'static str, _variant_index: u32, - _variant: &'static str, + variant: &'static str, len: usize, ) -> Result<Self::SerializeTupleVariant, Self::Error> { - self.serialize_seq(Some(len)) + Ok(super::SerializeTupleVariant::tuple(variant, len)) } fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { @@ -233,11 +243,11 @@ impl serde::ser::Serializer for ValueSerializer { fn serialize_struct_variant( self, - name: &'static str, + _name: &'static str, _variant_index: u32, - _variant: &'static str, - _len: usize, + variant: &'static str, + len: usize, ) -> Result<Self::SerializeStructVariant, Self::Error> { - Err(Error::UnsupportedType(Some(name))) + Ok(super::SerializeStructVariant::struct_(variant, len)) } } diff --git a/src/table.rs b/src/table.rs index 45d6d61..cc0d2b2 100644 --- a/src/table.rs +++ b/src/table.rs @@ -70,10 +70,10 @@ impl Table { values } - fn append_values<'s, 'c>( + fn append_values<'s>( &'s self, parent: &[&'s Key], - values: &'c mut Vec<(Vec<&'s Key>, &'s Value)>, + values: &mut Vec<(Vec<&'s Key>, &'s Value)>, ) { for value in self.items.values() { let mut path = parent.to_vec(); @@ -165,11 +165,15 @@ impl Table { /// In the document above, tables `target` and `target."x86_64/windows.json"` are implicit. /// /// ``` + /// # #[cfg(feature = "parse")] { + /// # #[cfg(feature = "display")] { /// use toml_edit::Document; /// let mut doc = "[a]\n[a.b]\n".parse::<Document>().expect("invalid toml"); /// /// doc["a"].as_table_mut().unwrap().set_implicit(true); /// assert_eq!(doc.to_string(), "[a.b]\n"); + /// # } + /// # } /// ``` pub fn set_implicit(&mut self, implicit: bool) { self.implicit = implicit; @@ -214,14 +218,28 @@ impl Table { &self.decor } + /// Returns an accessor to a key's formatting + pub fn key(&self, key: &str) -> Option<&'_ Key> { + self.items.get(key).map(|kv| &kv.key) + } + + /// Returns an accessor to a key's formatting + pub fn key_mut(&mut self, key: &str) -> Option<KeyMut<'_>> { + self.items.get_mut(key).map(|kv| kv.key.as_mut()) + } + /// Returns the decor associated with a given key of the table. + #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { - self.items.get_mut(key).map(|kv| &mut kv.key.decor) + #![allow(deprecated)] + self.items.get_mut(key).map(|kv| kv.key.leaf_decor_mut()) } /// Returns the decor associated with a given key of the table. + #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] pub fn key_decor(&self, key: &str) -> Option<&Decor> { - self.items.get(key).map(|kv| &kv.key.decor) + #![allow(deprecated)] + self.items.get(key).map(|kv| kv.key.leaf_decor()) } /// Returns the location within the original document @@ -413,15 +431,15 @@ impl Table { } } +#[cfg(feature = "display")] impl std::fmt::Display for Table { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use crate::encode::Encode; let children = self.get_values(); // print table body for (key_path, value) in children { - key_path.as_slice().encode(f, None, DEFAULT_KEY_DECOR)?; + crate::encode::encode_key_path_ref(&key_path, f, None, DEFAULT_KEY_DECOR)?; write!(f, "=")?; - value.encode(f, None, DEFAULT_VALUE_DECOR)?; + crate::encode::encode_value(value, f, None, DEFAULT_VALUE_DECOR)?; writeln!(f)?; } Ok(()) @@ -471,13 +489,14 @@ impl<'s> IntoIterator for &'s Table { pub(crate) type KeyValuePairs = IndexMap<InternalString, TableKeyValue>; fn decorate_table(table: &mut Table) { - for (key_decor, value) in table + for (mut key, value) in table .items .iter_mut() - .filter(|&(_, ref kv)| kv.value.is_value()) - .map(|(_, kv)| (&mut kv.key.decor, kv.value.as_value_mut().unwrap())) + .filter(|(_, kv)| kv.value.is_value()) + .map(|(_, kv)| (kv.key.as_mut(), kv.value.as_value_mut().unwrap())) { - key_decor.clear(); + key.leaf_decor_mut().clear(); + key.dotted_decor_mut().clear(); value.decor_mut().clear(); } } @@ -557,9 +576,15 @@ pub trait TableLike: crate::private::Sealed { /// Check if this is a wrapper for dotted keys, rather than a standard table fn is_dotted(&self) -> bool; + /// Returns an accessor to a key's formatting + fn key(&self, key: &str) -> Option<&'_ Key>; + /// Returns an accessor to a key's formatting + fn key_mut(&mut self, key: &str) -> Option<KeyMut<'_>>; /// Returns the decor associated with a given key of the table. + #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor>; /// Returns the decor associated with a given key of the table. + #[deprecated(since = "0.21.1", note = "Replaced with `key_mut`")] fn key_decor(&self, key: &str) -> Option<&Decor>; } @@ -617,10 +642,18 @@ impl TableLike for Table { self.set_dotted(yes) } + fn key(&self, key: &str) -> Option<&'_ Key> { + self.key(key) + } + fn key_mut(&mut self, key: &str) -> Option<KeyMut<'_>> { + self.key_mut(key) + } fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { + #![allow(deprecated)] self.key_decor_mut(key) } fn key_decor(&self, key: &str) -> Option<&Decor> { + #![allow(deprecated)] self.key_decor(key) } } diff --git a/src/value.rs b/src/value.rs index f10da9a..f416434 100644 --- a/src/value.rs +++ b/src/value.rs @@ -4,7 +4,6 @@ use std::str::FromStr; use toml_datetime::*; use crate::key::Key; -use crate::parser; use crate::repr::{Decor, Formatted}; use crate::{Array, InlineTable, InternalString, RawString}; @@ -190,10 +189,12 @@ impl Value { /// Sets the prefix and the suffix for value. /// # Example /// ```rust + /// # #[cfg(feature = "display")] { /// let mut v = toml_edit::Value::from(42); /// assert_eq!(&v.to_string(), "42"); /// let d = v.decorated(" ", " "); /// assert_eq!(&d.to_string(), " 42 "); + /// # } /// ``` pub fn decorated(mut self, prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self { self.decorate(prefix, suffix); @@ -231,12 +232,13 @@ impl Value { } } +#[cfg(feature = "parse")] impl FromStr for Value { type Err = crate::TomlError; /// Parses a value from a &str fn from_str(s: &str) -> Result<Self, Self::Err> { - parser::parse_value(s) + crate::parser::parse_value(s) } } @@ -284,6 +286,7 @@ impl From<i64> for Value { impl From<f64> for Value { fn from(f: f64) -> Self { + // Preserve sign of NaN. It may get written to TOML as `-nan`. Value::Float(Formatted::new(f)) } } @@ -346,9 +349,10 @@ impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for Value { } } +#[cfg(feature = "display")] impl std::fmt::Display for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - crate::encode::Encode::encode(self, f, None, ("", "")) + crate::encode::encode_value(self, f, None, ("", "")) } } @@ -360,6 +364,8 @@ pub(crate) const DEFAULT_TRAILING_VALUE_DECOR: (&str, &str) = (" ", " "); pub(crate) const DEFAULT_LEADING_VALUE_DECOR: (&str, &str) = ("", ""); #[cfg(test)] +#[cfg(feature = "parse")] +#[cfg(feature = "display")] mod tests { use super::*; diff --git a/src/visit.rs b/src/visit.rs index 1bc640a..6d7be0b 100644 --- a/src/visit.rs +++ b/src/visit.rs @@ -43,6 +43,7 @@ //! This visitor stores every string in the document. //! //! ``` +//! # #[cfg(feature = "parse")] { //! # use toml_edit::*; //! use toml_edit::visit::*; //! @@ -67,10 +68,11 @@ //! visitor.visit_document(&document); //! //! assert_eq!(visitor.strings, vec!["sky-castle", "surrounds-you"]); +//! # } //! ``` //! //! For a more complex example where the visitor has internal state, see `examples/visit.rs` -//! [on GitHub](https://github.com/ordian/toml_edit/blob/master/examples/visit.rs). +//! [on GitHub](https://github.com/toml-rs/toml/blob/main/crates/toml_edit/examples/visit.rs). use crate::{ Array, ArrayOfTables, Datetime, Document, Formatted, InlineTable, Item, Table, TableLike, Value, diff --git a/src/visit_mut.rs b/src/visit_mut.rs index 2c2af97..c823cfb 100644 --- a/src/visit_mut.rs +++ b/src/visit_mut.rs @@ -45,6 +45,8 @@ //! 2 decimal points. //! //! ``` +//! # #[cfg(feature = "parse")] { +//! # #[cfg(feature = "display")] { //! # use toml_edit::*; //! use toml_edit::visit_mut::*; //! @@ -80,10 +82,12 @@ //! "#; //! //! assert_eq!(format!("{}", document), output); +//! # } +//! # } //! ``` //! //! For a more complex example where the visitor has internal state, see `examples/visit.rs` -//! [on GitHub](https://github.com/ordian/toml_edit/blob/master/examples/visit.rs). +//! [on GitHub](https://github.com/toml-rs/toml/blob/main/crates/toml_edit/examples/visit.rs). use crate::{ Array, ArrayOfTables, Datetime, Document, Formatted, InlineTable, Item, KeyMut, Table, diff --git a/tests/decoder_compliance.rs b/tests/decoder_compliance.rs index 0f0b350..37a9335 100644 --- a/tests/decoder_compliance.rs +++ b/tests/decoder_compliance.rs @@ -3,15 +3,7 @@ mod decoder; fn main() { let decoder = decoder::Decoder; let mut harness = toml_test_harness::DecoderHarness::new(decoder); - harness - .ignore([ - "valid/spec/float-0.toml", // Test issue; `Decoder` turns `6.626e-34` into `0.0` - // Unreleased - "valid/string/escape-esc.toml", - "valid/string/hex-escape.toml", - "valid/datetime/no-seconds.toml", - "valid/inline-table/newline.toml", - ]) - .unwrap(); + harness.version("1.0.0"); + harness.ignore([]).unwrap(); harness.test(); } diff --git a/tests/encoder_compliance.rs b/tests/encoder_compliance.rs index ad65d75..355c540 100644 --- a/tests/encoder_compliance.rs +++ b/tests/encoder_compliance.rs @@ -5,10 +5,6 @@ fn main() { let encoder = encoder::Encoder; let decoder = decoder::Decoder; let mut harness = toml_test_harness::EncoderHarness::new(encoder, decoder); - harness - .ignore([ - "valid/spec/float-0.toml", // Test issue; `Decoder` turns `6.626e-34` into `0.0` - ]) - .unwrap(); + harness.version("1.0.0"); harness.test(); } diff --git a/tests/fixtures/invalid/array/array.stderr b/tests/fixtures/invalid/array/array.stderr new file mode 100644 index 0000000..6cb810d --- /dev/null +++ b/tests/fixtures/invalid/array/array.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 21 + | +1 | double-comma-1 = [1,,2] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/double-comma-1.stderr b/tests/fixtures/invalid/array/double-comma-1.stderr index 543e1b6..6cb810d 100644 --- a/tests/fixtures/invalid/array/double-comma-1.stderr +++ b/tests/fixtures/invalid/array/double-comma-1.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 12 +TOML parse error at line 1, column 21 | -1 | array = [1,,2] - | ^ +1 | double-comma-1 = [1,,2] + | ^ invalid array expected `]` diff --git a/tests/fixtures/invalid/array/double-comma-2.stderr b/tests/fixtures/invalid/array/double-comma-2.stderr index 694d7ec..60ab5b5 100644 --- a/tests/fixtures/invalid/array/double-comma-2.stderr +++ b/tests/fixtures/invalid/array/double-comma-2.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 14 +TOML parse error at line 1, column 23 | -1 | array = [1,2,,] - | ^ +1 | double-comma-2 = [1,2,,] + | ^ invalid array expected `]` diff --git a/tests/fixtures/invalid/array/extend-defined-aot.stderr b/tests/fixtures/invalid/array/extend-defined-aot.stderr new file mode 100644 index 0000000..970e0ec --- /dev/null +++ b/tests/fixtures/invalid/array/extend-defined-aot.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 1 + | +3 | arr.val1=1 + | ^ +duplicate key `val1` diff --git a/tests/fixtures/invalid/array/missing-separator-1.stderr b/tests/fixtures/invalid/array/missing-separator-1.stderr new file mode 100644 index 0000000..1202bb1 --- /dev/null +++ b/tests/fixtures/invalid/array/missing-separator-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 14 + | +1 | arrr = [true false] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/missing-separator.stderr b/tests/fixtures/invalid/array/missing-separator-2.stderr index 8e21f51..8e21f51 100644 --- a/tests/fixtures/invalid/array/missing-separator.stderr +++ b/tests/fixtures/invalid/array/missing-separator-2.stderr diff --git a/tests/fixtures/invalid/array/no-close.stderr b/tests/fixtures/invalid/array/no-close-1.stderr index a4f0a88..6f0a3e8 100644 --- a/tests/fixtures/invalid/array/no-close.stderr +++ b/tests/fixtures/invalid/array/no-close-1.stderr @@ -1,6 +1,6 @@ TOML parse error at line 1, column 24 | -1 | long_array = [ 1, 2, 3 +1 | no-close-1 = [ 1, 2, 3 | ^ invalid array expected `]` diff --git a/tests/fixtures/invalid/array/no-close-2.stderr b/tests/fixtures/invalid/array/no-close-2.stderr index 81ae5a9..96c4d64 100644 --- a/tests/fixtures/invalid/array/no-close-2.stderr +++ b/tests/fixtures/invalid/array/no-close-2.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 11 +TOML parse error at line 1, column 18 | -1 | x = [42 # - | ^ +1 | no-close-2 = [1, + | ^ invalid array expected `]` diff --git a/tests/fixtures/invalid/array/no-close-3.stderr b/tests/fixtures/invalid/array/no-close-3.stderr new file mode 100644 index 0000000..b84e3b9 --- /dev/null +++ b/tests/fixtures/invalid/array/no-close-3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 21 + | +1 | no-close-3 = [42 #] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/no-close-4.stderr b/tests/fixtures/invalid/array/no-close-4.stderr new file mode 100644 index 0000000..ecf4224 --- /dev/null +++ b/tests/fixtures/invalid/array/no-close-4.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 25 + | +1 | no-close-4 = [{ key = 42 + | ^ +invalid inline table +expected `}` diff --git a/tests/fixtures/invalid/array/no-close-5.stderr b/tests/fixtures/invalid/array/no-close-5.stderr new file mode 100644 index 0000000..c5e9674 --- /dev/null +++ b/tests/fixtures/invalid/array/no-close-5.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 27 + | +1 | no-close-5 = [{ key = 42} + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/no-close-6.stderr b/tests/fixtures/invalid/array/no-close-6.stderr new file mode 100644 index 0000000..2512a43 --- /dev/null +++ b/tests/fixtures/invalid/array/no-close-6.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 26 + | +1 | no-close-6 = [{ key = 42 #}] + | ^ +invalid inline table +expected `}` diff --git a/tests/fixtures/invalid/array/no-close-7.stderr b/tests/fixtures/invalid/array/no-close-7.stderr new file mode 100644 index 0000000..a49e988 --- /dev/null +++ b/tests/fixtures/invalid/array/no-close-7.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 30 + | +1 | no-close-7 = [{ key = 42} #] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/no-close-8.stderr b/tests/fixtures/invalid/array/no-close-8.stderr new file mode 100644 index 0000000..0e25a0b --- /dev/null +++ b/tests/fixtures/invalid/array/no-close-8.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 16 + | +1 | no-close-8 = [ + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/no-close-table.stderr b/tests/fixtures/invalid/array/no-close-table-1.stderr index b4c3c32..b4c3c32 100644 --- a/tests/fixtures/invalid/array/no-close-table.stderr +++ b/tests/fixtures/invalid/array/no-close-table-1.stderr diff --git a/tests/fixtures/invalid/array/no-comma-1.stderr b/tests/fixtures/invalid/array/no-comma-1.stderr new file mode 100644 index 0000000..e50fb69 --- /dev/null +++ b/tests/fixtures/invalid/array/no-comma-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | no-comma-1 = [true false] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/no-comma-2.stderr b/tests/fixtures/invalid/array/no-comma-2.stderr new file mode 100644 index 0000000..b34d709 --- /dev/null +++ b/tests/fixtures/invalid/array/no-comma-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 18 + | +1 | no-comma-2 = [ 1 2 3 ] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/no-comma-3.stderr b/tests/fixtures/invalid/array/no-comma-3.stderr new file mode 100644 index 0000000..c7cbec4 --- /dev/null +++ b/tests/fixtures/invalid/array/no-comma-3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 22 + | +1 | no-comma-3 = [ 1 #,] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/only-comma-1.stderr b/tests/fixtures/invalid/array/only-comma-1.stderr new file mode 100644 index 0000000..3616ca9 --- /dev/null +++ b/tests/fixtures/invalid/array/only-comma-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 17 + | +1 | only-comma-1 = [,] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/array/only-comma-2.stderr b/tests/fixtures/invalid/array/only-comma-2.stderr new file mode 100644 index 0000000..8284be5 --- /dev/null +++ b/tests/fixtures/invalid/array/only-comma-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 17 + | +1 | only-comma-2 = [,,] + | ^ +invalid array +expected `]` diff --git a/tests/fixtures/invalid/bool/almost-false-with-extra.stderr b/tests/fixtures/invalid/bool/almost-false-with-extra.stderr index cd6c1cd..1517084 100644 --- a/tests/fixtures/invalid/bool/almost-false-with-extra.stderr +++ b/tests/fixtures/invalid/bool/almost-false-with-extra.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 5 +TOML parse error at line 1, column 27 | -1 | a = falsify - | ^ +1 | almost-false-with-extra = falsify + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/almost-false.stderr b/tests/fixtures/invalid/bool/almost-false.stderr index 550020b..ba22196 100644 --- a/tests/fixtures/invalid/bool/almost-false.stderr +++ b/tests/fixtures/invalid/bool/almost-false.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 5 +TOML parse error at line 1, column 27 | -1 | a = fals - | ^ +1 | almost-false = fals + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/almost-true-with-extra.stderr b/tests/fixtures/invalid/bool/almost-true-with-extra.stderr index c75c553..23e230e 100644 --- a/tests/fixtures/invalid/bool/almost-true-with-extra.stderr +++ b/tests/fixtures/invalid/bool/almost-true-with-extra.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 5 +TOML parse error at line 1, column 27 | -1 | a = truthy - | ^ +1 | almost-true-with-extra = truthy + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/almost-true.stderr b/tests/fixtures/invalid/bool/almost-true.stderr index 0c97e00..21bdf37 100644 --- a/tests/fixtures/invalid/bool/almost-true.stderr +++ b/tests/fixtures/invalid/bool/almost-true.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 5 +TOML parse error at line 1, column 27 | -1 | a = tru - | ^ +1 | almost-true = tru + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/bool.stderr b/tests/fixtures/invalid/bool/bool.stderr new file mode 100644 index 0000000..1517084 --- /dev/null +++ b/tests/fixtures/invalid/bool/bool.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 27 + | +1 | almost-false-with-extra = falsify + | ^ +invalid string +expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/capitalized-false.stderr b/tests/fixtures/invalid/bool/capitalized-false.stderr new file mode 100644 index 0000000..fd318ca --- /dev/null +++ b/tests/fixtures/invalid/bool/capitalized-false.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 28 + | +1 | capitalized-false = False + | ^ +invalid string +expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/capitalized-true.stderr b/tests/fixtures/invalid/bool/capitalized-true.stderr new file mode 100644 index 0000000..cb32d8e --- /dev/null +++ b/tests/fixtures/invalid/bool/capitalized-true.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 28 + | +1 | capitalized-true = True + | ^ +invalid string +expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/just-f.stderr b/tests/fixtures/invalid/bool/just-f.stderr index ed2b9f0..cc4fb78 100644 --- a/tests/fixtures/invalid/bool/just-f.stderr +++ b/tests/fixtures/invalid/bool/just-f.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 5 +TOML parse error at line 1, column 27 | -1 | a = f - | ^ +1 | just-f = f + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/just-t.stderr b/tests/fixtures/invalid/bool/just-t.stderr index 2c8b6a5..f2d889b 100644 --- a/tests/fixtures/invalid/bool/just-t.stderr +++ b/tests/fixtures/invalid/bool/just-t.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 5 +TOML parse error at line 1, column 27 | -1 | a = t - | ^ +1 | just-t = t + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/mixed-case-false.stderr b/tests/fixtures/invalid/bool/mixed-case-false.stderr new file mode 100644 index 0000000..d96dc60 --- /dev/null +++ b/tests/fixtures/invalid/bool/mixed-case-false.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 27 + | +1 | mixed-case-false = falsE + | ^ +invalid string +expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/mixed-case-true.stderr b/tests/fixtures/invalid/bool/mixed-case-true.stderr new file mode 100644 index 0000000..e7f8289 --- /dev/null +++ b/tests/fixtures/invalid/bool/mixed-case-true.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 27 + | +1 | mixed-case-true = trUe + | ^ +invalid string +expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/mixed-case.stderr b/tests/fixtures/invalid/bool/mixed-case.stderr index b7c6192..994020e 100644 --- a/tests/fixtures/invalid/bool/mixed-case.stderr +++ b/tests/fixtures/invalid/bool/mixed-case.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 9 +TOML parse error at line 1, column 27 | -1 | valid = False - | ^ +1 | mixed-case = valid = False + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/starting-same-false.stderr b/tests/fixtures/invalid/bool/starting-same-false.stderr index b332089..1cc00d5 100644 --- a/tests/fixtures/invalid/bool/starting-same-false.stderr +++ b/tests/fixtures/invalid/bool/starting-same-false.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 10 +TOML parse error at line 1, column 32 | -1 | a = falsey - | ^ +1 | starting-same-false = falsey + | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/bool/starting-same-true.stderr b/tests/fixtures/invalid/bool/starting-same-true.stderr index 6053103..a7cc00b 100644 --- a/tests/fixtures/invalid/bool/starting-same-true.stderr +++ b/tests/fixtures/invalid/bool/starting-same-true.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 9 +TOML parse error at line 1, column 31 | -1 | a = truer - | ^ +1 | starting-same-true = truer + | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/bool/wrong-case-false.stderr b/tests/fixtures/invalid/bool/wrong-case-false.stderr index f67444c..fd15caa 100644 --- a/tests/fixtures/invalid/bool/wrong-case-false.stderr +++ b/tests/fixtures/invalid/bool/wrong-case-false.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 5 +TOML parse error at line 1, column 27 | -1 | b = FALSE - | ^ +1 | wrong-case-false = FALSE + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/bool/wrong-case-true.stderr b/tests/fixtures/invalid/bool/wrong-case-true.stderr index 82bb619..bc60a4c 100644 --- a/tests/fixtures/invalid/bool/wrong-case-true.stderr +++ b/tests/fixtures/invalid/bool/wrong-case-true.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 5 +TOML parse error at line 1, column 27 | -1 | a = TRUE - | ^ +1 | wrong-case-true = TRUE + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/control/bare-formfeed.stderr b/tests/fixtures/invalid/control/bare-formfeed.stderr index 313274a..449ec87 100644 --- a/tests/fixtures/invalid/control/bare-formfeed.stderr +++ b/tests/fixtures/invalid/control/bare-formfeed.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 17 +TOML parse error at line 1, column 21 | -1 | bare-formfeed = - | ^ +1 | bare-formfeed = + | ^ invalid string expected `"`, `'` diff --git a/tests/fixtures/invalid/control/bare-null.stderr b/tests/fixtures/invalid/control/bare-null.stderr Binary files differindex cd5e936..9c8231d 100644 --- a/tests/fixtures/invalid/control/bare-null.stderr +++ b/tests/fixtures/invalid/control/bare-null.stderr diff --git a/tests/fixtures/invalid/control/comment-cr.stderr b/tests/fixtures/invalid/control/comment-cr.stderr index fb262e5..54e42df 100644 --- a/tests/fixtures/invalid/control/comment-cr.stderr +++ b/tests/fixtures/invalid/control/comment-cr.stderr @@ -1,6 +1,6 @@ -TOML parse error at line 1, column 45 +TOML parse error at line 1, column 47 | -1 | comment-cr = "Carriage return in comment" # +1 | comment-cr = "Carriage return in comment" # a=1 - | ^ + | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/control/comment-del.stderr b/tests/fixtures/invalid/control/comment-del.stderr index 3d25d68..5eae7a4 100644 --- a/tests/fixtures/invalid/control/comment-del.stderr +++ b/tests/fixtures/invalid/control/comment-del.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 24 +TOML parse error at line 1, column 27 | -1 | comment-del = "0x7f" # - | ^ +1 | comment-del = "0x7f" # + | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/control/comment-ff.stderr b/tests/fixtures/invalid/control/comment-ff.stderr new file mode 100644 index 0000000..6f54974 --- /dev/null +++ b/tests/fixtures/invalid/control/comment-ff.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 27 + | +1 | comment-ff = "0x7f" # + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/control/comment-lf.stderr b/tests/fixtures/invalid/control/comment-lf.stderr index 1613710..3eacd62 100644 --- a/tests/fixtures/invalid/control/comment-lf.stderr +++ b/tests/fixtures/invalid/control/comment-lf.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 25 +TOML parse error at line 1, column 27 | -1 | comment-lf = "ctrl-P" # - | ^ +1 | comment-lf = "ctrl-P" # + | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/control/comment-null.stderr b/tests/fixtures/invalid/control/comment-null.stderr Binary files differindex 4955b9d..ba5bc80 100644 --- a/tests/fixtures/invalid/control/comment-null.stderr +++ b/tests/fixtures/invalid/control/comment-null.stderr diff --git a/tests/fixtures/invalid/control/comment-us.stderr b/tests/fixtures/invalid/control/comment-us.stderr index b48d4f3..f34076e 100644 --- a/tests/fixtures/invalid/control/comment-us.stderr +++ b/tests/fixtures/invalid/control/comment-us.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 25 +TOML parse error at line 1, column 27 | -1 | comment-us = "ctrl-_" # - | ^ +1 | comment-us = "ctrl-_" # + | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/control/control.stderr b/tests/fixtures/invalid/control/control.stderr index 486aacf..f214b54 100644 --- a/tests/fixtures/invalid/control/control.stderr +++ b/tests/fixtures/invalid/control/control.stderr @@ -1,6 +1,5 @@ -TOML parse error at line 9, column 22 +TOML parse error at line 9, column 1 | -9 | string-null = "null\x00" - | ^ -invalid escape sequence -expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` +9 | comment-cr = "Carriage return in comment" # \x0da=1 + | ^ +duplicate key `comment-cr` in document root diff --git a/tests/fixtures/invalid/control/multi-cr.stderr b/tests/fixtures/invalid/control/multi-cr.stderr new file mode 100644 index 0000000..d5c749c --- /dev/null +++ b/tests/fixtures/invalid/control/multi-cr.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 21 + | +1 | multi-cr = """null +""" + | ^ +invalid multiline basic string diff --git a/tests/fixtures/invalid/control/multi-del.stderr b/tests/fixtures/invalid/control/multi-del.stderr index 62702da..a1b54b7 100644 --- a/tests/fixtures/invalid/control/multi-del.stderr +++ b/tests/fixtures/invalid/control/multi-del.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 20 +TOML parse error at line 1, column 21 | -1 | multi-del = """null""" - | ^ +1 | multi-del = """null""" + | ^ invalid multiline basic string diff --git a/tests/fixtures/invalid/control/multi-lf.stderr b/tests/fixtures/invalid/control/multi-lf.stderr index 7b7a138..a0a8f7b 100644 --- a/tests/fixtures/invalid/control/multi-lf.stderr +++ b/tests/fixtures/invalid/control/multi-lf.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 19 +TOML parse error at line 1, column 21 | -1 | multi-lf = """null""" - | ^ +1 | multi-lf = """null""" + | ^ invalid multiline basic string diff --git a/tests/fixtures/invalid/control/multi-us.stderr b/tests/fixtures/invalid/control/multi-us.stderr index cf8e732..ac556b2 100644 --- a/tests/fixtures/invalid/control/multi-us.stderr +++ b/tests/fixtures/invalid/control/multi-us.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 19 +TOML parse error at line 1, column 21 | -1 | multi-us = """null""" - | ^ +1 | multi-us = """null""" + | ^ invalid multiline basic string diff --git a/tests/fixtures/invalid/control/rawmulti-cd.stderr b/tests/fixtures/invalid/control/rawmulti-cd.stderr new file mode 100644 index 0000000..1027009 --- /dev/null +++ b/tests/fixtures/invalid/control/rawmulti-cd.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 24 + | +1 | rawmulti-cd = '''null +''' + | ^ +invalid multiline literal string diff --git a/tests/fixtures/invalid/control/rawmulti-del.stderr b/tests/fixtures/invalid/control/rawmulti-del.stderr index 3beeae0..7972a2b 100644 --- a/tests/fixtures/invalid/control/rawmulti-del.stderr +++ b/tests/fixtures/invalid/control/rawmulti-del.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 23 +TOML parse error at line 1, column 24 | -1 | rawmulti-del = '''null''' - | ^ +1 | rawmulti-del = '''null''' + | ^ invalid multiline literal string diff --git a/tests/fixtures/invalid/control/rawmulti-lf.stderr b/tests/fixtures/invalid/control/rawmulti-lf.stderr index 40782a2..1898ec8 100644 --- a/tests/fixtures/invalid/control/rawmulti-lf.stderr +++ b/tests/fixtures/invalid/control/rawmulti-lf.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 22 +TOML parse error at line 1, column 24 | -1 | rawmulti-lf = '''null''' - | ^ +1 | rawmulti-lf = '''null''' + | ^ invalid multiline literal string diff --git a/tests/fixtures/invalid/control/rawmulti-us.stderr b/tests/fixtures/invalid/control/rawmulti-us.stderr index d413d54..4c412f7 100644 --- a/tests/fixtures/invalid/control/rawmulti-us.stderr +++ b/tests/fixtures/invalid/control/rawmulti-us.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 22 +TOML parse error at line 1, column 24 | -1 | rawmulti-us = '''null''' - | ^ +1 | rawmulti-us = '''null''' + | ^ invalid multiline literal string diff --git a/tests/fixtures/invalid/control/rawstring-cr.stderr b/tests/fixtures/invalid/control/rawstring-cr.stderr new file mode 100644 index 0000000..bc8a1a2 --- /dev/null +++ b/tests/fixtures/invalid/control/rawstring-cr.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 23 + | +1 | rawstring-cr = 'null +' + | ^ +invalid literal string diff --git a/tests/fixtures/invalid/control/rawstring-del.stderr b/tests/fixtures/invalid/control/rawstring-del.stderr index 640ba46..e80e322 100644 --- a/tests/fixtures/invalid/control/rawstring-del.stderr +++ b/tests/fixtures/invalid/control/rawstring-del.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 22 +TOML parse error at line 1, column 23 | -1 | rawstring-del = 'null' - | ^ +1 | rawstring-del = 'null' + | ^ invalid literal string diff --git a/tests/fixtures/invalid/control/rawstring-lf.stderr b/tests/fixtures/invalid/control/rawstring-lf.stderr index e6499b6..b8874c6 100644 --- a/tests/fixtures/invalid/control/rawstring-lf.stderr +++ b/tests/fixtures/invalid/control/rawstring-lf.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 21 +TOML parse error at line 1, column 23 | -1 | rawstring-lf = 'null' - | ^ +1 | rawstring-lf = 'null' + | ^ invalid literal string diff --git a/tests/fixtures/invalid/control/rawstring-us.stderr b/tests/fixtures/invalid/control/rawstring-us.stderr index 492cdf7..9cf3fae 100644 --- a/tests/fixtures/invalid/control/rawstring-us.stderr +++ b/tests/fixtures/invalid/control/rawstring-us.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 21 +TOML parse error at line 1, column 23 | -1 | rawstring-us = 'null' - | ^ +1 | rawstring-us = 'null' + | ^ invalid literal string diff --git a/tests/fixtures/invalid/control/string-bs.stderr b/tests/fixtures/invalid/control/string-bs.stderr index 556ba1d..3f7b5ee 100644 --- a/tests/fixtures/invalid/control/string-bs.stderr +++ b/tests/fixtures/invalid/control/string-bs.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 23 +TOML parse error at line 1, column 25 | -1 | string-bs = "backspace" - | ^ +1 | string-bs = "backspace" + | ^ invalid basic string diff --git a/tests/fixtures/invalid/control/string-cr.stderr b/tests/fixtures/invalid/control/string-cr.stderr new file mode 100644 index 0000000..0eff4c2 --- /dev/null +++ b/tests/fixtures/invalid/control/string-cr.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | string-cr = "null +" + | ^ +invalid basic string diff --git a/tests/fixtures/invalid/control/string-del.stderr b/tests/fixtures/invalid/control/string-del.stderr index 85d7af3..b6ace6b 100644 --- a/tests/fixtures/invalid/control/string-del.stderr +++ b/tests/fixtures/invalid/control/string-del.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 19 +TOML parse error at line 1, column 20 | -1 | string-del = "null" - | ^ +1 | string-del = "null" + | ^ invalid basic string diff --git a/tests/fixtures/invalid/control/string-lf.stderr b/tests/fixtures/invalid/control/string-lf.stderr index fbf0d1a..c3b141e 100644 --- a/tests/fixtures/invalid/control/string-lf.stderr +++ b/tests/fixtures/invalid/control/string-lf.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 18 +TOML parse error at line 1, column 20 | -1 | string-lf = "null" - | ^ +1 | string-lf = "null" + | ^ invalid basic string diff --git a/tests/fixtures/invalid/control/string-us.stderr b/tests/fixtures/invalid/control/string-us.stderr index 8278e57..26f2f6a 100644 --- a/tests/fixtures/invalid/control/string-us.stderr +++ b/tests/fixtures/invalid/control/string-us.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 18 +TOML parse error at line 1, column 20 | -1 | string-us = "null" - | ^ +1 | string-us = "null" + | ^ invalid basic string diff --git a/tests/fixtures/invalid/datetime/feb-29.stderr b/tests/fixtures/invalid/datetime/feb-29.stderr new file mode 100644 index 0000000..63fac67 --- /dev/null +++ b/tests/fixtures/invalid/datetime/feb-29.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 29 + | +1 | "not a leap year" = 2100-02-29T15:15:15Z + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/datetime/feb-30.stderr b/tests/fixtures/invalid/datetime/feb-30.stderr new file mode 100644 index 0000000..2b5212a --- /dev/null +++ b/tests/fixtures/invalid/datetime/feb-30.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 44 + | +1 | "only 28 or 29 days in february" = 1988-02-30T15:15:15Z + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/datetime/no-leads-month.stderr b/tests/fixtures/invalid/datetime/no-leads-month.stderr new file mode 100644 index 0000000..3e0ccf7 --- /dev/null +++ b/tests/fixtures/invalid/datetime/no-leads-month.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 17 + | +2 | no-leads = 1987-7-05T17:45:00Z + | ^ +invalid date-time diff --git a/tests/fixtures/invalid/datetime/time-no-leads.stderr b/tests/fixtures/invalid/datetime/time-no-leads.stderr index 7a98902..012f62f 100644 --- a/tests/fixtures/invalid/datetime/time-no-leads.stderr +++ b/tests/fixtures/invalid/datetime/time-no-leads.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 2, column 6 +TOML parse error at line 2, column 15 | -2 | d = 1:32:00 - | ^ +2 | d = 2023-10-01T1:32:00Z + | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/datetime/y10k.stderr b/tests/fixtures/invalid/datetime/y10k.stderr new file mode 100644 index 0000000..dc5cfc5 --- /dev/null +++ b/tests/fixtures/invalid/datetime/y10k.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 10 + | +2 | d = 10000-01-01 00:00:00z + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/encoding/bad-codepoint.stderr b/tests/fixtures/invalid/encoding/bad-codepoint.stderr new file mode 100644 index 0000000..89ef2c7 --- /dev/null +++ b/tests/fixtures/invalid/encoding/bad-codepoint.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 29
\ No newline at end of file diff --git a/tests/fixtures/invalid/encoding/utf16.stderr b/tests/fixtures/invalid/encoding/utf16-comment.stderr Binary files differindex 6886165..6886165 100644 --- a/tests/fixtures/invalid/encoding/utf16.stderr +++ b/tests/fixtures/invalid/encoding/utf16-comment.stderr diff --git a/tests/fixtures/invalid/encoding/utf16-key.stderr b/tests/fixtures/invalid/encoding/utf16-key.stderr Binary files differnew file mode 100644 index 0000000..16bedc0 --- /dev/null +++ b/tests/fixtures/invalid/encoding/utf16-key.stderr diff --git a/tests/fixtures/invalid/float/exp-point-3.stderr b/tests/fixtures/invalid/float/exp-point-3.stderr new file mode 100644 index 0000000..873791c --- /dev/null +++ b/tests/fixtures/invalid/float/exp-point-3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 17 + | +1 | exp-point-3 = 3.e+20 + | ^ +invalid floating-point number +expected digit diff --git a/tests/fixtures/invalid/float/exp-trailing-us-1.stderr b/tests/fixtures/invalid/float/exp-trailing-us-1.stderr new file mode 100644 index 0000000..254bdf2 --- /dev/null +++ b/tests/fixtures/invalid/float/exp-trailing-us-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 23 + | +1 | exp-trailing-us-1 = 1_e2 + | ^ +invalid integer +expected digit diff --git a/tests/fixtures/invalid/float/exp-trailing-us-2.stderr b/tests/fixtures/invalid/float/exp-trailing-us-2.stderr new file mode 100644 index 0000000..b2986ad --- /dev/null +++ b/tests/fixtures/invalid/float/exp-trailing-us-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 25 + | +1 | exp-trailing-us-2 = 1.2_e2 + | ^ +invalid floating-point number +expected digit, digit diff --git a/tests/fixtures/invalid/float/exp-trailing-us.stderr b/tests/fixtures/invalid/float/exp-trailing-us.stderr index 9a28184..b7e2ad9 100644 --- a/tests/fixtures/invalid/float/exp-trailing-us.stderr +++ b/tests/fixtures/invalid/float/exp-trailing-us.stderr @@ -1,5 +1,6 @@ -TOML parse error at line 1, column 21 +TOML parse error at line 1, column 24 | -1 | exp-trailing-us = 1e_23_ - | ^ +1 | exp-trailing-us = 1e23_ + | ^ invalid floating-point number +expected digit diff --git a/tests/fixtures/invalid/float/inf-capital.stderr b/tests/fixtures/invalid/float/inf-capital.stderr new file mode 100644 index 0000000..ca7a1b1 --- /dev/null +++ b/tests/fixtures/invalid/float/inf-capital.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | v = Inf + | ^ +invalid string +expected `"`, `'` diff --git a/tests/fixtures/invalid/float/nan-capital.stderr b/tests/fixtures/invalid/float/nan-capital.stderr new file mode 100644 index 0000000..ae3b4d9 --- /dev/null +++ b/tests/fixtures/invalid/float/nan-capital.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | v = NaN + | ^ +invalid string +expected `"`, `'` diff --git a/tests/fixtures/invalid/float/trailing-us-exp-1.stderr b/tests/fixtures/invalid/float/trailing-us-exp-1.stderr new file mode 100644 index 0000000..cf0fabc --- /dev/null +++ b/tests/fixtures/invalid/float/trailing-us-exp-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 23 + | +1 | trailing-us-exp-1 = 1_e2 + | ^ +invalid integer +expected digit diff --git a/tests/fixtures/invalid/float/trailing-us-exp-2.stderr b/tests/fixtures/invalid/float/trailing-us-exp-2.stderr new file mode 100644 index 0000000..83ff120 --- /dev/null +++ b/tests/fixtures/invalid/float/trailing-us-exp-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 25 + | +1 | trailing-us-exp-2 = 1.2_e2 + | ^ +invalid floating-point number +expected digit, digit diff --git a/tests/fixtures/invalid/float/trailing-us-exp.stderr b/tests/fixtures/invalid/float/trailing-us-exp.stderr deleted file mode 100644 index 811f951..0000000 --- a/tests/fixtures/invalid/float/trailing-us-exp.stderr +++ /dev/null @@ -1,6 +0,0 @@ -TOML parse error at line 2, column 21 - | -2 | trailing-us-exp = 1_e2 - | ^ -invalid integer -expected digit diff --git a/tests/fixtures/invalid/inline-table/bad-key-syntax.stderr b/tests/fixtures/invalid/inline-table/bad-key-syntax.stderr new file mode 100644 index 0000000..c8ce45a --- /dev/null +++ b/tests/fixtures/invalid/inline-table/bad-key-syntax.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 14 + | +1 | tbl = { a = 1, [b] } + | ^ +invalid inline table +expected `}` diff --git a/tests/fixtures/invalid/inline-table/duplicate-key.stderr b/tests/fixtures/invalid/inline-table/duplicate-key-1.stderr index acee967..acee967 100644 --- a/tests/fixtures/invalid/inline-table/duplicate-key.stderr +++ b/tests/fixtures/invalid/inline-table/duplicate-key-1.stderr diff --git a/tests/fixtures/invalid/inline-table/duplicate-key-2.stderr b/tests/fixtures/invalid/inline-table/duplicate-key-2.stderr new file mode 100644 index 0000000..91b41fd --- /dev/null +++ b/tests/fixtures/invalid/inline-table/duplicate-key-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 11 + | +1 | table1 = { table2.dupe = 1, table2.dupe = 2 } + | ^ +duplicate key `dupe` diff --git a/tests/fixtures/invalid/inline-table/duplicate-key-3.stderr b/tests/fixtures/invalid/inline-table/duplicate-key-3.stderr new file mode 100644 index 0000000..79a8041 --- /dev/null +++ b/tests/fixtures/invalid/inline-table/duplicate-key-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 8 + | +1 | tbl = { fruit = { apple.color = "red" }, fruit.apple.texture = { smooth = true } } + | ^ +duplicate key `fruit` diff --git a/tests/fixtures/invalid/inline-table/duplicate-key-4.stderr b/tests/fixtures/invalid/inline-table/duplicate-key-4.stderr new file mode 100644 index 0000000..7b86044 --- /dev/null +++ b/tests/fixtures/invalid/inline-table/duplicate-key-4.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 8 + | +1 | tbl = { a.b = "a_b", a.b.c = "a_b_c" } + | ^ +dotted key `a.b` attempted to extend non-table type (string) diff --git a/tests/fixtures/invalid/inline-table/empty.stderr b/tests/fixtures/invalid/inline-table/empty-1.stderr index 0fcfd34..0fcfd34 100644 --- a/tests/fixtures/invalid/inline-table/empty.stderr +++ b/tests/fixtures/invalid/inline-table/empty-1.stderr diff --git a/tests/fixtures/invalid/inline-table/empty-2.stderr b/tests/fixtures/invalid/inline-table/empty-2.stderr new file mode 100644 index 0000000..ea51c18 --- /dev/null +++ b/tests/fixtures/invalid/inline-table/empty-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 6 + | +1 | t = {, + | ^ +invalid inline table +expected `}` diff --git a/tests/fixtures/invalid/inline-table/empty-3.stderr b/tests/fixtures/invalid/inline-table/empty-3.stderr new file mode 100644 index 0000000..ca4a29a --- /dev/null +++ b/tests/fixtures/invalid/inline-table/empty-3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 6 + | +1 | t = { + | ^ +invalid inline table +expected `}` diff --git a/tests/fixtures/invalid/inline-table/no-close-1.stderr b/tests/fixtures/invalid/inline-table/no-close-1.stderr new file mode 100644 index 0000000..d371b65 --- /dev/null +++ b/tests/fixtures/invalid/inline-table/no-close-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 4 + | +1 | a={ + | ^ +invalid inline table +expected `}` diff --git a/tests/fixtures/invalid/inline-table/no-close-2.stderr b/tests/fixtures/invalid/inline-table/no-close-2.stderr new file mode 100644 index 0000000..3b42d78 --- /dev/null +++ b/tests/fixtures/invalid/inline-table/no-close-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 7 + | +1 | a={b=1 + | ^ +invalid inline table +expected `}` diff --git a/tests/fixtures/invalid/inline-table/no-comma.stderr b/tests/fixtures/invalid/inline-table/no-comma-1.stderr index 8955218..8955218 100644 --- a/tests/fixtures/invalid/inline-table/no-comma.stderr +++ b/tests/fixtures/invalid/inline-table/no-comma-1.stderr diff --git a/tests/fixtures/invalid/inline-table/no-comma-2.stderr b/tests/fixtures/invalid/inline-table/no-comma-2.stderr new file mode 100644 index 0000000..128ac53 --- /dev/null +++ b/tests/fixtures/invalid/inline-table/no-comma-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 31 + | +1 | arrr = { comma-missing = true valid-toml = false } + | ^ +invalid inline table +expected `}` diff --git a/tests/fixtures/invalid/inline-table/overwrite.stderr b/tests/fixtures/invalid/inline-table/overwrite-01.stderr index 5c48ee2..5c48ee2 100644 --- a/tests/fixtures/invalid/inline-table/overwrite.stderr +++ b/tests/fixtures/invalid/inline-table/overwrite-01.stderr diff --git a/tests/fixtures/invalid/inline-table/add.stderr b/tests/fixtures/invalid/inline-table/overwrite-02.stderr index 4108142..4108142 100644 --- a/tests/fixtures/invalid/inline-table/add.stderr +++ b/tests/fixtures/invalid/inline-table/overwrite-02.stderr diff --git a/tests/fixtures/invalid/inline-table/overwrite-03.stderr b/tests/fixtures/invalid/inline-table/overwrite-03.stderr new file mode 100644 index 0000000..c1ab1d7 --- /dev/null +++ b/tests/fixtures/invalid/inline-table/overwrite-03.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 1 + | +2 | a.b = 2 + | ^ +dotted key `a` attempted to extend non-table type (inline table) diff --git a/tests/fixtures/invalid/inline-table/overwrite-04.stderr b/tests/fixtures/invalid/inline-table/overwrite-04.stderr new file mode 100644 index 0000000..993e04e --- /dev/null +++ b/tests/fixtures/invalid/inline-table/overwrite-04.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 1 + | +3 | [[inline-t.nest]] + | ^ +invalid table header +dotted key `inline-t` attempted to extend non-table type (inline table) diff --git a/tests/fixtures/invalid/inline-table/overwrite-05.stderr b/tests/fixtures/invalid/inline-table/overwrite-05.stderr new file mode 100644 index 0000000..bf1953d --- /dev/null +++ b/tests/fixtures/invalid/inline-table/overwrite-05.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 1 + | +3 | [inline-t.nest] + | ^ +invalid table header +dotted key `inline-t` attempted to extend non-table type (inline table) diff --git a/tests/fixtures/invalid/inline-table/overwrite-06.stderr b/tests/fixtures/invalid/inline-table/overwrite-06.stderr new file mode 100644 index 0000000..1e5d4cd --- /dev/null +++ b/tests/fixtures/invalid/inline-table/overwrite-06.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 6 + | +1 | a = { b = 1, b.c = 2 } + | ^ +dotted key `b` attempted to extend non-table type (integer) diff --git a/tests/fixtures/invalid/inline-table/overwrite-07.stderr b/tests/fixtures/invalid/inline-table/overwrite-07.stderr new file mode 100644 index 0000000..9e5efba --- /dev/null +++ b/tests/fixtures/invalid/inline-table/overwrite-07.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 8 + | +1 | tab = { inner.table = [{}], inner.table.val = "bad" } + | ^ +dotted key `inner.table` attempted to extend non-table type (array) diff --git a/tests/fixtures/invalid/inline-table/overwrite-08.stderr b/tests/fixtures/invalid/inline-table/overwrite-08.stderr new file mode 100644 index 0000000..8322330 --- /dev/null +++ b/tests/fixtures/invalid/inline-table/overwrite-08.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 8 + | +1 | tab = { inner = { dog = "best" }, inner.cat = "worst" } + | ^ +duplicate key `inner` diff --git a/tests/fixtures/invalid/inline-table/overwrite-09.stderr b/tests/fixtures/invalid/inline-table/overwrite-09.stderr new file mode 100644 index 0000000..9d68dbb --- /dev/null +++ b/tests/fixtures/invalid/inline-table/overwrite-09.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 5, column 1 + | +5 | nested.inline-t.nest = 2 + | ^ +duplicate key `nested` diff --git a/tests/fixtures/invalid/inline-table/overwrite-10.stderr b/tests/fixtures/invalid/inline-table/overwrite-10.stderr new file mode 100644 index 0000000..18af75a --- /dev/null +++ b/tests/fixtures/invalid/inline-table/overwrite-10.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 4, column 6 + | +4 | a = {b.a = 1, b = 2, b.c = 3} + | ^ +duplicate key `b` diff --git a/tests/fixtures/invalid/integer/invalid-hex-1.stderr b/tests/fixtures/invalid/integer/invalid-hex-1.stderr new file mode 100644 index 0000000..b899e6a --- /dev/null +++ b/tests/fixtures/invalid/integer/invalid-hex-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 22 + | +1 | invalid-hex-1 = 0xaafz + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/integer/invalid-hex-2.stderr b/tests/fixtures/invalid/integer/invalid-hex-2.stderr new file mode 100644 index 0000000..4df3e2f --- /dev/null +++ b/tests/fixtures/invalid/integer/invalid-hex-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | invalid-hex-2 = 0xgabba00f1 + | ^ +invalid hexadecimal integer diff --git a/tests/fixtures/invalid/integer/leading-us-bin.stderr b/tests/fixtures/invalid/integer/leading-us-bin.stderr index c893e75..c979c19 100644 --- a/tests/fixtures/invalid/integer/leading-us-bin.stderr +++ b/tests/fixtures/invalid/integer/leading-us-bin.stderr @@ -1,6 +1,6 @@ TOML parse error at line 1, column 18 | -1 | leading-us-bin = _0o1 +1 | leading-us-bin = _0b1 | ^ invalid integer expected leading digit diff --git a/tests/fixtures/invalid/integer/leading-us-hex.stderr b/tests/fixtures/invalid/integer/leading-us-hex.stderr index 12eb8e6..1824a8b 100644 --- a/tests/fixtures/invalid/integer/leading-us-hex.stderr +++ b/tests/fixtures/invalid/integer/leading-us-hex.stderr @@ -1,6 +1,6 @@ TOML parse error at line 1, column 18 | -1 | leading-us-hex = _0o1 +1 | leading-us-hex = _0x1 | ^ invalid integer expected leading digit diff --git a/tests/fixtures/invalid/integer/negative-oct.stderr b/tests/fixtures/invalid/integer/negative-oct.stderr index fcf3140..9e922c6 100644 --- a/tests/fixtures/invalid/integer/negative-oct.stderr +++ b/tests/fixtures/invalid/integer/negative-oct.stderr @@ -1,5 +1,5 @@ TOML parse error at line 1, column 18 | -1 | negative-oct = -0o99 +1 | negative-oct = -0o755 | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/integer/positive-oct.stderr b/tests/fixtures/invalid/integer/positive-oct.stderr index cc09466..30d2ab3 100644 --- a/tests/fixtures/invalid/integer/positive-oct.stderr +++ b/tests/fixtures/invalid/integer/positive-oct.stderr @@ -1,5 +1,5 @@ TOML parse error at line 1, column 18 | -1 | positive-oct = +0o99 +1 | positive-oct = +0o755 | ^ expected newline, `#` diff --git a/tests/fixtures/invalid/key/dotted-redefine-table-1.stderr b/tests/fixtures/invalid/key/dotted-redefine-table-1.stderr new file mode 100644 index 0000000..f51a108 --- /dev/null +++ b/tests/fixtures/invalid/key/dotted-redefine-table-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 1 + | +2 | a.b = true + | ^ +dotted key `a` attempted to extend non-table type (boolean) diff --git a/tests/fixtures/invalid/key/dotted-redefine-table.stderr b/tests/fixtures/invalid/key/dotted-redefine-table-2.stderr index 3a2b8d5..3a2b8d5 100644 --- a/tests/fixtures/invalid/key/dotted-redefine-table.stderr +++ b/tests/fixtures/invalid/key/dotted-redefine-table-2.stderr diff --git a/tests/fixtures/invalid/key/duplicate-keys-1.stderr b/tests/fixtures/invalid/key/duplicate-keys-1.stderr new file mode 100644 index 0000000..c58dd3c --- /dev/null +++ b/tests/fixtures/invalid/key/duplicate-keys-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 1 + | +2 | name = "Pradyun" + | ^ +duplicate key `name` in document root diff --git a/tests/fixtures/invalid/key/duplicate-keys.stderr b/tests/fixtures/invalid/key/duplicate-keys-2.stderr index 74149f8..74149f8 100644 --- a/tests/fixtures/invalid/key/duplicate-keys.stderr +++ b/tests/fixtures/invalid/key/duplicate-keys-2.stderr diff --git a/tests/fixtures/invalid/key/duplicate-keys-3.stderr b/tests/fixtures/invalid/key/duplicate-keys-3.stderr new file mode 100644 index 0000000..94a019f --- /dev/null +++ b/tests/fixtures/invalid/key/duplicate-keys-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 1 + | +2 | "spelling" = "favourite" + | ^ +duplicate key `spelling` in document root diff --git a/tests/fixtures/invalid/key/duplicate-keys-4.stderr b/tests/fixtures/invalid/key/duplicate-keys-4.stderr new file mode 100644 index 0000000..2bd02ab --- /dev/null +++ b/tests/fixtures/invalid/key/duplicate-keys-4.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 1 + | +2 | 'spelling' = "favourite" + | ^ +duplicate key `spelling` in document root diff --git a/tests/fixtures/invalid/key/duplicate.stderr b/tests/fixtures/invalid/key/duplicate.stderr deleted file mode 100644 index 8c7d7b7..0000000 --- a/tests/fixtures/invalid/key/duplicate.stderr +++ /dev/null @@ -1,5 +0,0 @@ -TOML parse error at line 3, column 1 - | -3 | name = "Pradyun" - | ^ -duplicate key `name` in document root diff --git a/tests/fixtures/invalid/key/end-in-escape.stderr b/tests/fixtures/invalid/key/end-in-escape.stderr new file mode 100644 index 0000000..5916980 --- /dev/null +++ b/tests/fixtures/invalid/key/end-in-escape.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 30 + | +1 | "backslash is the last char\ + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/tests/fixtures/invalid/key/newline.stderr b/tests/fixtures/invalid/key/newline-1.stderr index 141932e..141932e 100644 --- a/tests/fixtures/invalid/key/newline.stderr +++ b/tests/fixtures/invalid/key/newline-1.stderr diff --git a/tests/fixtures/invalid/key/newline-2.stderr b/tests/fixtures/invalid/key/newline-2.stderr new file mode 100644 index 0000000..ac205e1 --- /dev/null +++ b/tests/fixtures/invalid/key/newline-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 8 + | +1 | "quoted + | ^ +invalid basic string diff --git a/tests/fixtures/invalid/key/newline-3.stderr b/tests/fixtures/invalid/key/newline-3.stderr new file mode 100644 index 0000000..ee7c519 --- /dev/null +++ b/tests/fixtures/invalid/key/newline-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 8 + | +1 | 'quoted + | ^ +invalid literal string diff --git a/tests/fixtures/invalid/key/multiline.stderr b/tests/fixtures/invalid/key/newline-4.stderr index b4241ee..b4241ee 100644 --- a/tests/fixtures/invalid/key/multiline.stderr +++ b/tests/fixtures/invalid/key/newline-4.stderr diff --git a/tests/fixtures/invalid/key/newline-5.stderr b/tests/fixtures/invalid/key/newline-5.stderr new file mode 100644 index 0000000..18e3ab3 --- /dev/null +++ b/tests/fixtures/invalid/key/newline-5.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 3 + | +1 | '''long + | ^ +expected `.`, `=` diff --git a/tests/fixtures/invalid/key/two-equals.stderr b/tests/fixtures/invalid/key/two-equals-1.stderr index 2f92886..2f92886 100644 --- a/tests/fixtures/invalid/key/two-equals.stderr +++ b/tests/fixtures/invalid/key/two-equals-1.stderr diff --git a/tests/fixtures/invalid/key/two-equals2.stderr b/tests/fixtures/invalid/key/two-equals-2.stderr index f2adb1f..f2adb1f 100644 --- a/tests/fixtures/invalid/key/two-equals2.stderr +++ b/tests/fixtures/invalid/key/two-equals-2.stderr diff --git a/tests/fixtures/invalid/key/two-equals3.stderr b/tests/fixtures/invalid/key/two-equals-3.stderr index dbee169..dbee169 100644 --- a/tests/fixtures/invalid/key/two-equals3.stderr +++ b/tests/fixtures/invalid/key/two-equals-3.stderr diff --git a/tests/fixtures/invalid/key/without-value-5.stderr b/tests/fixtures/invalid/key/without-value-5.stderr new file mode 100644 index 0000000..711eab1 --- /dev/null +++ b/tests/fixtures/invalid/key/without-value-5.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 6 + | +1 | fs.fw + | ^ +expected `.`, `=` diff --git a/tests/fixtures/invalid/key/without-value-6.stderr b/tests/fixtures/invalid/key/without-value-6.stderr new file mode 100644 index 0000000..c380d70 --- /dev/null +++ b/tests/fixtures/invalid/key/without-value-6.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 8 + | +1 | fs.fw = + | ^ +invalid string +expected `"`, `'` diff --git a/tests/fixtures/invalid/key/without-value-7.stderr b/tests/fixtures/invalid/key/without-value-7.stderr new file mode 100644 index 0000000..8565837 --- /dev/null +++ b/tests/fixtures/invalid/key/without-value-7.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 3 + | +1 | fs. + | ^ +expected `.`, `=` diff --git a/tests/fixtures/invalid/local-date/feb-29.stderr b/tests/fixtures/invalid/local-date/feb-29.stderr new file mode 100644 index 0000000..b0ae76d --- /dev/null +++ b/tests/fixtures/invalid/local-date/feb-29.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 29 + | +1 | "not a leap year" = 2100-02-29 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-date/feb-30.stderr b/tests/fixtures/invalid/local-date/feb-30.stderr new file mode 100644 index 0000000..7f64348 --- /dev/null +++ b/tests/fixtures/invalid/local-date/feb-30.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 44 + | +1 | "only 28 or 29 days in february" = 1988-02-30 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-date/mday-over.stderr b/tests/fixtures/invalid/local-date/mday-over.stderr new file mode 100644 index 0000000..f2d1876 --- /dev/null +++ b/tests/fixtures/invalid/local-date/mday-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 13 + | +3 | d = 2006-01-32 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-date/mday-under.stderr b/tests/fixtures/invalid/local-date/mday-under.stderr new file mode 100644 index 0000000..fab958d --- /dev/null +++ b/tests/fixtures/invalid/local-date/mday-under.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 13 + | +3 | d = 2006-01-00 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-date/month-over.stderr b/tests/fixtures/invalid/local-date/month-over.stderr new file mode 100644 index 0000000..ec6d090 --- /dev/null +++ b/tests/fixtures/invalid/local-date/month-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 10 + | +2 | d = 2006-13-01 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-date/month-under.stderr b/tests/fixtures/invalid/local-date/month-under.stderr new file mode 100644 index 0000000..3e8324a --- /dev/null +++ b/tests/fixtures/invalid/local-date/month-under.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 10 + | +2 | d = 2007-00-01 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-date/no-leads-with-milli.stderr b/tests/fixtures/invalid/local-date/no-leads-with-milli.stderr new file mode 100644 index 0000000..e0e3046 --- /dev/null +++ b/tests/fixtures/invalid/local-date/no-leads-with-milli.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 22 + | +2 | with-milli = 1987-07-5 + | ^ +invalid date-time diff --git a/tests/fixtures/invalid/local-date/no-leads.stderr b/tests/fixtures/invalid/local-date/no-leads.stderr new file mode 100644 index 0000000..e7b5d69 --- /dev/null +++ b/tests/fixtures/invalid/local-date/no-leads.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 17 + | +2 | no-leads = 1987-7-05 + | ^ +invalid date-time diff --git a/tests/fixtures/invalid/datetime/trailing-t.stderr b/tests/fixtures/invalid/local-date/trailing-t.stderr index 061ec26..061ec26 100644 --- a/tests/fixtures/invalid/datetime/trailing-t.stderr +++ b/tests/fixtures/invalid/local-date/trailing-t.stderr diff --git a/tests/fixtures/invalid/local-date/y10k.stderr b/tests/fixtures/invalid/local-date/y10k.stderr new file mode 100644 index 0000000..244266e --- /dev/null +++ b/tests/fixtures/invalid/local-date/y10k.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 10 + | +2 | d = 10000-01-01 + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/local-datetime/feb-29.stderr b/tests/fixtures/invalid/local-datetime/feb-29.stderr new file mode 100644 index 0000000..8aac712 --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/feb-29.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 29 + | +1 | "not a leap year" = 2100-02-29T15:15:15 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-datetime/feb-30.stderr b/tests/fixtures/invalid/local-datetime/feb-30.stderr new file mode 100644 index 0000000..6175c5e --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/feb-30.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 44 + | +1 | "only 28 or 29 days in february" = 1988-02-30T15:15:15 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-datetime/hour-over.stderr b/tests/fixtures/invalid/local-datetime/hour-over.stderr new file mode 100644 index 0000000..bc255ed --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/hour-over.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 15 + | +2 | d = 2006-01-01T24:00:00 + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/local-datetime/mday-over.stderr b/tests/fixtures/invalid/local-datetime/mday-over.stderr new file mode 100644 index 0000000..0556e3a --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/mday-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 13 + | +3 | d = 2006-01-32T00:00:00 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-datetime/mday-under.stderr b/tests/fixtures/invalid/local-datetime/mday-under.stderr new file mode 100644 index 0000000..036e963 --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/mday-under.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 13 + | +3 | d = 2006-01-00T00:00:00 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-datetime/minute-over.stderr b/tests/fixtures/invalid/local-datetime/minute-over.stderr new file mode 100644 index 0000000..039fc6e --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/minute-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 19 + | +2 | d = 2006-01-01T00:60:00 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-datetime/month-over.stderr b/tests/fixtures/invalid/local-datetime/month-over.stderr new file mode 100644 index 0000000..0d2dca2 --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/month-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 10 + | +2 | d = 2006-13-01T00:00:00 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-datetime/month-under.stderr b/tests/fixtures/invalid/local-datetime/month-under.stderr new file mode 100644 index 0000000..6ce30cb --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/month-under.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 10 + | +2 | d = 2007-00-01T00:00:00 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-datetime/no-leads-with-milli.stderr b/tests/fixtures/invalid/local-datetime/no-leads-with-milli.stderr new file mode 100644 index 0000000..5ec75e9 --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/no-leads-with-milli.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 22 + | +2 | with-milli = 1987-07-5T17:45:00.12 + | ^ +invalid date-time diff --git a/tests/fixtures/invalid/local-datetime/no-leads.stderr b/tests/fixtures/invalid/local-datetime/no-leads.stderr new file mode 100644 index 0000000..7d2c879 --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/no-leads.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 17 + | +2 | no-leads = 1987-7-05T17:45:00 + | ^ +invalid date-time diff --git a/tests/fixtures/invalid/local-datetime/no-secs.stderr b/tests/fixtures/invalid/local-datetime/no-secs.stderr new file mode 100644 index 0000000..7585e1b --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/no-secs.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 27 + | +2 | no-secs = 1987-07-05T17:45 + | ^ +invalid date-time diff --git a/tests/fixtures/invalid/local-datetime/no-t.stderr b/tests/fixtures/invalid/local-datetime/no-t.stderr new file mode 100644 index 0000000..0f520a2 --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/no-t.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 18 + | +2 | no-t = 1987-07-0517:45:00 + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/local-datetime/second-over.stderr b/tests/fixtures/invalid/local-datetime/second-over.stderr new file mode 100644 index 0000000..63d0007 --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/second-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 22 + | +3 | d = 2006-01-01T00:00:61 + | ^ +invalid date-time +value is out of range diff --git a/tests/fixtures/invalid/local-datetime/time-no-leads.stderr b/tests/fixtures/invalid/local-datetime/time-no-leads.stderr new file mode 100644 index 0000000..012f62f --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/time-no-leads.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 15 + | +2 | d = 2023-10-01T1:32:00Z + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/local-datetime/y10k.stderr b/tests/fixtures/invalid/local-datetime/y10k.stderr new file mode 100644 index 0000000..2d4015d --- /dev/null +++ b/tests/fixtures/invalid/local-datetime/y10k.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 10 + | +2 | d = 10000-01-01 00:00:00 + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/local-time/hour-over.stderr b/tests/fixtures/invalid/local-time/hour-over.stderr new file mode 100644 index 0000000..1f669e3 --- /dev/null +++ b/tests/fixtures/invalid/local-time/hour-over.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 7 + | +2 | d = 24:00:00 + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/local-time/minute-over.stderr b/tests/fixtures/invalid/local-time/minute-over.stderr new file mode 100644 index 0000000..efb676f --- /dev/null +++ b/tests/fixtures/invalid/local-time/minute-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 8 + | +2 | d = 00:60:00 + | ^ +invalid time +value is out of range diff --git a/tests/fixtures/invalid/local-time/no-secs.stderr b/tests/fixtures/invalid/local-time/no-secs.stderr new file mode 100644 index 0000000..2fa8ba3 --- /dev/null +++ b/tests/fixtures/invalid/local-time/no-secs.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 16 + | +2 | no-secs = 17:45 + | ^ +invalid time diff --git a/tests/fixtures/invalid/local-time/second-over.stderr b/tests/fixtures/invalid/local-time/second-over.stderr new file mode 100644 index 0000000..a608f89 --- /dev/null +++ b/tests/fixtures/invalid/local-time/second-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 11 + | +3 | d = 00:00:61 + | ^ +invalid time +value is out of range diff --git a/tests/fixtures/invalid/datetime/time-no-leads-2.stderr b/tests/fixtures/invalid/local-time/time-no-leads-2.stderr index fd77fb2..fd77fb2 100644 --- a/tests/fixtures/invalid/datetime/time-no-leads-2.stderr +++ b/tests/fixtures/invalid/local-time/time-no-leads-2.stderr diff --git a/tests/fixtures/invalid/local-time/time-no-leads.stderr b/tests/fixtures/invalid/local-time/time-no-leads.stderr new file mode 100644 index 0000000..7a98902 --- /dev/null +++ b/tests/fixtures/invalid/local-time/time-no-leads.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 6 + | +2 | d = 1:32:00 + | ^ +expected newline, `#` diff --git a/tests/fixtures/invalid/string/bad-codepoint.stderr b/tests/fixtures/invalid/string/bad-codepoint.stderr deleted file mode 100644 index 4061c79..0000000 --- a/tests/fixtures/invalid/string/bad-codepoint.stderr +++ /dev/null @@ -1,6 +0,0 @@ -TOML parse error at line 1, column 76 - | -1 | invalid-codepoint = "This string contains a non scalar unicode codepoint \uD801" - | ^ -invalid unicode 4-digit hex code -value is out of range diff --git a/tests/fixtures/invalid/string/bad-escape-3.stderr b/tests/fixtures/invalid/string/bad-escape-3.stderr new file mode 100644 index 0000000..ea10886 --- /dev/null +++ b/tests/fixtures/invalid/string/bad-escape-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 16 + | +1 | backslash = "\" + | ^ +invalid basic string diff --git a/tests/fixtures/invalid/string/bad-uni-esc-1.stderr b/tests/fixtures/invalid/string/bad-uni-esc-1.stderr index a9e439b..71d8ed3 100644 --- a/tests/fixtures/invalid/string/bad-uni-esc-1.stderr +++ b/tests/fixtures/invalid/string/bad-uni-esc-1.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 13 +TOML parse error at line 1, column 23 | -1 | str = "val\ue" - | ^ +1 | bad-uni-esc-1 = "val\ue" + | ^ invalid unicode 4-digit hex code diff --git a/tests/fixtures/invalid/string/bad-uni-esc-2.stderr b/tests/fixtures/invalid/string/bad-uni-esc-2.stderr index 87c8681..06138c1 100644 --- a/tests/fixtures/invalid/string/bad-uni-esc-2.stderr +++ b/tests/fixtures/invalid/string/bad-uni-esc-2.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 13 +TOML parse error at line 1, column 23 | -1 | str = "val\Ux" - | ^ +1 | bad-uni-esc-2 = "val\Ux" + | ^ invalid unicode 8-digit hex code diff --git a/tests/fixtures/invalid/string/bad-uni-esc-3.stderr b/tests/fixtures/invalid/string/bad-uni-esc-3.stderr index 61f8ded..c82355c 100644 --- a/tests/fixtures/invalid/string/bad-uni-esc-3.stderr +++ b/tests/fixtures/invalid/string/bad-uni-esc-3.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 13 +TOML parse error at line 1, column 23 | -1 | str = "val\U0000000" - | ^ +1 | bad-uni-esc-3 = "val\U0000000" + | ^ invalid unicode 8-digit hex code diff --git a/tests/fixtures/invalid/string/bad-uni-esc-4.stderr b/tests/fixtures/invalid/string/bad-uni-esc-4.stderr index 1a781d9..71fb48c 100644 --- a/tests/fixtures/invalid/string/bad-uni-esc-4.stderr +++ b/tests/fixtures/invalid/string/bad-uni-esc-4.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 13 +TOML parse error at line 1, column 23 | -1 | str = "val\U0000" - | ^ +1 | bad-uni-esc-4 = "val\U0000" + | ^ invalid unicode 8-digit hex code diff --git a/tests/fixtures/invalid/string/bad-uni-esc-5.stderr b/tests/fixtures/invalid/string/bad-uni-esc-5.stderr index 88773ca..d79798f 100644 --- a/tests/fixtures/invalid/string/bad-uni-esc-5.stderr +++ b/tests/fixtures/invalid/string/bad-uni-esc-5.stderr @@ -1,5 +1,5 @@ -TOML parse error at line 1, column 13 +TOML parse error at line 1, column 23 | -1 | str = "val\Ugggggggg" - | ^ +1 | bad-uni-esc-5 = "val\Ugggggggg" + | ^ invalid unicode 8-digit hex code diff --git a/tests/fixtures/invalid/string/bad-uni-esc-6.stderr b/tests/fixtures/invalid/string/bad-uni-esc-6.stderr new file mode 100644 index 0000000..7eb5ff0 --- /dev/null +++ b/tests/fixtures/invalid/string/bad-uni-esc-6.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 72 + | +1 | bad-uni-esc-6 = "This string contains a non scalar unicode codepoint \uD801" + | ^ +invalid unicode 4-digit hex code +value is out of range diff --git a/tests/fixtures/invalid/string/bad-uni-esc-7.stderr b/tests/fixtures/invalid/string/bad-uni-esc-7.stderr new file mode 100644 index 0000000..c53ef12 --- /dev/null +++ b/tests/fixtures/invalid/string/bad-uni-esc-7.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | bad-uni-esc-7 = "\uabag" + | ^ +invalid unicode 4-digit hex code diff --git a/tests/fixtures/invalid/string/multiline-bad-escape-4.stderr b/tests/fixtures/invalid/string/multiline-bad-escape-4.stderr new file mode 100644 index 0000000..d662a4d --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-bad-escape-4.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | backslash = """\""" + | ^ +invalid multiline basic string diff --git a/tests/fixtures/invalid/string/multiline-escape-space.stderr b/tests/fixtures/invalid/string/multiline-escape-space-1.stderr index 4b3c32b..4b3c32b 100644 --- a/tests/fixtures/invalid/string/multiline-escape-space.stderr +++ b/tests/fixtures/invalid/string/multiline-escape-space-1.stderr diff --git a/tests/fixtures/invalid/string/multiline-escape-space-2.stderr b/tests/fixtures/invalid/string/multiline-escape-space-2.stderr new file mode 100644 index 0000000..b5ed276 --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-escape-space-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 4, column 7 + | +4 | gee \ """ + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/tests/fixtures/invalid/string/multiline-lit-no-close-1.stderr b/tests/fixtures/invalid/string/multiline-lit-no-close-1.stderr new file mode 100644 index 0000000..1731932 --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-lit-no-close-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 20 + | +2 | this will fail + | ^ +invalid multiline literal string diff --git a/tests/fixtures/invalid/string/multiline-lit-no-close-2.stderr b/tests/fixtures/invalid/string/multiline-lit-no-close-2.stderr new file mode 100644 index 0000000..347c6de --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-lit-no-close-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 7 + | +1 | x=''' + | ^ +invalid multiline literal string diff --git a/tests/fixtures/invalid/string/multiline-lit-no-close-3.stderr b/tests/fixtures/invalid/string/multiline-lit-no-close-3.stderr new file mode 100644 index 0000000..b6d5ec5 --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-lit-no-close-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 4, column 7 + | +4 | eteta + | ^ +invalid multiline literal string diff --git a/tests/fixtures/invalid/string/multiline-lit-no-close-4.stderr b/tests/fixtures/invalid/string/multiline-lit-no-close-4.stderr new file mode 100644 index 0000000..5dea96d --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-lit-no-close-4.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 8 + | +3 | gee '' + | ^ +invalid multiline literal string diff --git a/tests/fixtures/invalid/string/multiline-no-close.stderr b/tests/fixtures/invalid/string/multiline-no-close-1.stderr index 99e967a..99e967a 100644 --- a/tests/fixtures/invalid/string/multiline-no-close.stderr +++ b/tests/fixtures/invalid/string/multiline-no-close-1.stderr diff --git a/tests/fixtures/invalid/string/multiline-no-close-3.stderr b/tests/fixtures/invalid/string/multiline-no-close-3.stderr new file mode 100644 index 0000000..eff9fe4 --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-no-close-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 4, column 7 + | +4 | eteta + | ^ +invalid multiline basic string diff --git a/tests/fixtures/invalid/string/multiline-no-close-4.stderr b/tests/fixtures/invalid/string/multiline-no-close-4.stderr new file mode 100644 index 0000000..e19582f --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-no-close-4.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 8 + | +3 | gee "" + | ^ +invalid multiline basic string diff --git a/tests/fixtures/invalid/string/multiline-no-close-5.stderr b/tests/fixtures/invalid/string/multiline-no-close-5.stderr new file mode 100644 index 0000000..00c1735 --- /dev/null +++ b/tests/fixtures/invalid/string/multiline-no-close-5.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 8 + | +3 | gee\ + | ^ +invalid multiline basic string diff --git a/tests/fixtures/invalid/string/no-close.stderr b/tests/fixtures/invalid/string/no-close-1.stderr index f23223d..f23223d 100644 --- a/tests/fixtures/invalid/string/no-close.stderr +++ b/tests/fixtures/invalid/string/no-close-1.stderr diff --git a/tests/fixtures/invalid/string/no-close-2.stderr b/tests/fixtures/invalid/string/no-close-2.stderr new file mode 100644 index 0000000..a80fe60 --- /dev/null +++ b/tests/fixtures/invalid/string/no-close-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 29 + | +1 | "a-string".must-be = "closed + | ^ +invalid basic string diff --git a/tests/fixtures/invalid/string/no-close-3.stderr b/tests/fixtures/invalid/string/no-close-3.stderr new file mode 100644 index 0000000..029b40a --- /dev/null +++ b/tests/fixtures/invalid/string/no-close-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 42 + | +1 | no-ending-quote = 'One time, at band camp + | ^ +invalid literal string diff --git a/tests/fixtures/invalid/string/no-close-4.stderr b/tests/fixtures/invalid/string/no-close-4.stderr new file mode 100644 index 0000000..9e47ef7 --- /dev/null +++ b/tests/fixtures/invalid/string/no-close-4.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 29 + | +1 | 'a-string'.must-be = 'closed + | ^ +invalid literal string diff --git a/tests/fixtures/invalid/string/bad-hex-esc.stderr b/tests/fixtures/invalid/string/string.stderr index 5d5577f..5d5577f 100644 --- a/tests/fixtures/invalid/string/bad-hex-esc.stderr +++ b/tests/fixtures/invalid/string/string.stderr diff --git a/tests/fixtures/invalid/table/append-to-array-with-dotted-keys.stderr b/tests/fixtures/invalid/table/append-to-array-with-dotted-keys.stderr new file mode 100644 index 0000000..0fb4b2e --- /dev/null +++ b/tests/fixtures/invalid/table/append-to-array-with-dotted-keys.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 4, column 1 + | +4 | b.y = 2 + | ^ +duplicate key `y` diff --git a/tests/fixtures/invalid/table/array-missing-bracket.stderr b/tests/fixtures/invalid/table/array-no-close-1.stderr index ed370ef..ed370ef 100644 --- a/tests/fixtures/invalid/table/array-missing-bracket.stderr +++ b/tests/fixtures/invalid/table/array-no-close-1.stderr diff --git a/tests/fixtures/invalid/table/array-no-close-2.stderr b/tests/fixtures/invalid/table/array-no-close-2.stderr new file mode 100644 index 0000000..a723c14 --- /dev/null +++ b/tests/fixtures/invalid/table/array-no-close-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 26 + | +1 | [[closing-bracket.missing] + | ^ +invalid table header +expected `.`, `]]` diff --git a/tests/fixtures/invalid/table/duplicate-key-dotted-array.stderr b/tests/fixtures/invalid/table/duplicate-key-dotted-array.stderr new file mode 100644 index 0000000..0cf32ab --- /dev/null +++ b/tests/fixtures/invalid/table/duplicate-key-dotted-array.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 4, column 1 + | +4 | [[fruit.apple]] + | ^ +invalid table header +duplicate key `apple` in table `fruit` diff --git a/tests/fixtures/invalid/table/no-close-1.stderr b/tests/fixtures/invalid/table/no-close-1.stderr new file mode 100644 index 0000000..2e184fa --- /dev/null +++ b/tests/fixtures/invalid/table/no-close-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 8 + | +1 | [where will it end + | ^ +invalid table header +expected `.`, `]` diff --git a/tests/fixtures/invalid/table/no-close-2.stderr b/tests/fixtures/invalid/table/no-close-2.stderr new file mode 100644 index 0000000..a7adf38 --- /dev/null +++ b/tests/fixtures/invalid/table/no-close-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 25 + | +1 | [closing-bracket.missingö + | ^ +invalid table header +expected `.`, `]` diff --git a/tests/fixtures/invalid/table/quoted-no-close.stderr b/tests/fixtures/invalid/table/no-close-3.stderr index 2b05e95..2b05e95 100644 --- a/tests/fixtures/invalid/table/quoted-no-close.stderr +++ b/tests/fixtures/invalid/table/no-close-3.stderr diff --git a/tests/fixtures/invalid/table/no-close-4.stderr b/tests/fixtures/invalid/table/no-close-4.stderr new file mode 100644 index 0000000..022f1fa --- /dev/null +++ b/tests/fixtures/invalid/table/no-close-4.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 2 + | +1 | [ + | ^ +invalid key diff --git a/tests/fixtures/invalid/table/no-close-5.stderr b/tests/fixtures/invalid/table/no-close-5.stderr new file mode 100644 index 0000000..38c7bee --- /dev/null +++ b/tests/fixtures/invalid/table/no-close-5.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 11 + | +1 | [fwfw.wafw + | ^ +invalid table header +expected `.`, `]` diff --git a/tests/fixtures/invalid/table/overwrite-array-in-parent.stderr b/tests/fixtures/invalid/table/overwrite-array-in-parent.stderr new file mode 100644 index 0000000..8a774ff --- /dev/null +++ b/tests/fixtures/invalid/table/overwrite-array-in-parent.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 4, column 1 + | +4 | arr = 2 + | ^ +duplicate key `arr` in table `parent-table` diff --git a/tests/fixtures/invalid/table/overwrite-bool-with-array.stderr b/tests/fixtures/invalid/table/overwrite-bool-with-array.stderr new file mode 100644 index 0000000..f52c773 --- /dev/null +++ b/tests/fixtures/invalid/table/overwrite-bool-with-array.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 1 + | +2 | [[a]] + | ^ +invalid table header +duplicate key `a` in document root diff --git a/tests/fixtures/invalid/table/overwrite-with-deep-table.stderr b/tests/fixtures/invalid/table/overwrite-with-deep-table.stderr new file mode 100644 index 0000000..48773b6 --- /dev/null +++ b/tests/fixtures/invalid/table/overwrite-with-deep-table.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 1 + | +2 | [a.b.c.d] + | ^ +invalid table header +dotted key `a` attempted to extend non-table type (integer) diff --git a/tests/fixtures/invalid/table/redefine.stderr b/tests/fixtures/invalid/table/redefine-1.stderr index 99c1f98..99c1f98 100644 --- a/tests/fixtures/invalid/table/redefine.stderr +++ b/tests/fixtures/invalid/table/redefine-1.stderr diff --git a/tests/fixtures/invalid/table/redefine-2.stderr b/tests/fixtures/invalid/table/redefine-2.stderr new file mode 100644 index 0000000..43bbb56 --- /dev/null +++ b/tests/fixtures/invalid/table/redefine-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 1 + | +3 | [t1.t2] + | ^ +invalid table header +duplicate key `t2` in table `t1` diff --git a/tests/fixtures/invalid/table/redefine-3.stderr b/tests/fixtures/invalid/table/redefine-3.stderr new file mode 100644 index 0000000..63bfc24 --- /dev/null +++ b/tests/fixtures/invalid/table/redefine-3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 1 + | +3 | [t1.t2.t3] + | ^ +invalid table header +duplicate key `t3` in table `t1.t2` diff --git a/tests/fixtures/invalid/table/super-twice.stderr b/tests/fixtures/invalid/table/super-twice.stderr new file mode 100644 index 0000000..b36517a --- /dev/null +++ b/tests/fixtures/invalid/table/super-twice.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 1 + | +3 | [a] + | ^ +invalid table header +duplicate key `a` in document root diff --git a/tests/testsuite/edit.rs b/tests/testsuite/edit.rs index 28f73c1..94c20d4 100644 --- a/tests/testsuite/edit.rs +++ b/tests/testsuite/edit.rs @@ -853,3 +853,10 @@ src.git = "https://github.com/nixos/nixpkgs" "#, ); } + +#[test] +fn sorting_with_references() { + let values = vec!["foo", "qux", "bar"]; + let mut array = toml_edit::Array::from_iter(values); + array.sort_by(|lhs, rhs| lhs.as_str().cmp(&rhs.as_str())); +} diff --git a/tests/testsuite/float.rs b/tests/testsuite/float.rs new file mode 100644 index 0000000..34e792e --- /dev/null +++ b/tests/testsuite/float.rs @@ -0,0 +1,60 @@ +use toml_edit::Document; + +macro_rules! float_inf_tests { + ($ty:ty) => {{ + let document = r" + # infinity + sf1 = inf # positive infinity + sf2 = +inf # positive infinity + sf3 = -inf # negative infinity + + # not a number + sf4 = nan # actual sNaN/qNaN encoding is implementation specific + sf5 = +nan # same as `nan` + sf6 = -nan # valid, actual encoding is implementation specific + + # zero + sf7 = +0.0 + sf8 = -0.0 + "; + + let document = document.parse::<Document>().unwrap(); + let float = |k| document[k].as_float().unwrap(); + + assert!(float("sf1").is_infinite()); + assert!(float("sf1").is_sign_positive()); + assert!(float("sf2").is_infinite()); + assert!(float("sf2").is_sign_positive()); + assert!(float("sf3").is_infinite()); + assert!(float("sf3").is_sign_negative()); + + assert!(float("sf4").is_nan()); + assert!(float("sf4").is_sign_positive()); + assert!(float("sf5").is_nan()); + assert!(float("sf5").is_sign_positive()); + assert!(float("sf6").is_nan()); + assert!(float("sf6").is_sign_negative()); + + assert_eq!(float("sf7"), 0.0); + assert!(float("sf7").is_sign_positive()); + assert_eq!(float("sf8"), 0.0); + assert!(float("sf8").is_sign_negative()); + + let mut document = Document::new(); + document["sf4"] = toml_edit::value(f64::NAN.copysign(1.0)); + document["sf6"] = toml_edit::value(f64::NAN.copysign(-1.0)); + assert_eq!( + document.to_string(), + "\ +sf4 = nan +sf6 = -nan +" + ); + }}; +} + +#[test] +fn test_float() { + float_inf_tests!(f32); + float_inf_tests!(f64); +} diff --git a/tests/testsuite/main.rs b/tests/testsuite/main.rs index 1476c5d..0592f3c 100644 --- a/tests/testsuite/main.rs +++ b/tests/testsuite/main.rs @@ -3,6 +3,7 @@ mod convert; mod datetime; mod edit; +mod float; mod invalid; mod parse; mod stackoverflow; diff --git a/tests/testsuite/parse.rs b/tests/testsuite/parse.rs index f1c3c27..f22b61d 100644 --- a/tests/testsuite/parse.rs +++ b/tests/testsuite/parse.rs @@ -56,11 +56,11 @@ multiline basic string """"# ) .is_str()); - assert!(parse_value!(r#"'literal string\ \'"#).is_str()); + assert!(parse_value!(r"'literal string\ \'").is_str()); assert!(parse_value!( - r#"'''multiline + r"'''multiline literal \ \ -string'''"# +string'''" ) .is_str()); assert!(parse_value!(r#"{ hello = "world", a = 1}"#).is_inline_table()); @@ -1488,3 +1488,23 @@ fn despan_keys() { assert_eq!(doc.to_string(), "aaaaaa = 1\nbbb = 2\n"); } + +#[test] +fn dotted_key_comment_roundtrip() { + let input = r###" +rust.unsafe_op_in_unsafe_fn = "deny" + +rust.explicit_outlives_requirements = "warn" +# rust.unused_crate_dependencies = "warn" + +clippy.cast_lossless = "warn" +clippy.doc_markdown = "warn" +clippy.exhaustive_enums = "warn" +"###; + let expected = input; + + let manifest: toml_edit::Document = input.parse().unwrap(); + let actual = manifest.to_string(); + + assert_eq(expected, actual); +} |