diff options
Diffstat (limited to '')
364 files changed, 27509 insertions, 0 deletions
diff --git a/vendor/toml/.cargo-checksum.json b/vendor/toml/.cargo-checksum.json new file mode 100644 index 0000000..4e825d0 --- /dev/null +++ b/vendor/toml/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{},"package":"dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"}
\ No newline at end of file diff --git a/vendor/toml/Cargo.lock b/vendor/toml/Cargo.lock new file mode 100644 index 0000000..cb6f911 --- /dev/null +++ b/vendor/toml/Cargo.lock @@ -0,0 +1,891 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "memchr", +] + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "clap" +version = "4.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.105", +] + +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "crossbeam-utils" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "equivalent" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "globset" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "ignore" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "include_dir" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +dependencies = [ + "libc", + "windows-sys 0.42.0", +] + +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" + +[[package]] +name = "libtest-mimic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7b603516767d1ab23d0de09d023e62966c3322f7148297c35cf3d97aa8b37fa" +dependencies = [ + "clap", + "termcolor", + "threadpool", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi 0.1.19", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" + +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.105", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "rustix" +version = "0.37.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.160" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.160" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "serde_json" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + +[[package]] +name = "similar" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803" + +[[package]] +name = "snapbox" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6bccd62078347f89a914e3004d94582e13824d4e3d8a816317862884c423835" +dependencies = [ + "anstream", + "anstyle", + "normalize-line-endings", + "similar", + "snapbox-macros", +] + +[[package]] +name = "snapbox-macros" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaaf09df9f0eeae82be96290918520214530e738a7fe5a351b0f24cf77c0ca31" +dependencies = [ + "anstream", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "toml" +version = "0.7.8" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "serde_spanned", + "snapbox", + "toml-test-harness", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml-test" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37351256790aa1dbd6d60f4ff08e55e7f372e292f3e9040d6e077463d9a779c3" +dependencies = [ + "chrono", + "serde", + "serde_json", +] + +[[package]] +name = "toml-test-data" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f351b6d6005ee802b0d4a53ca1cdf05636f441df4d299e62cba57f1da52646" +dependencies = [ + "include_dir", +] + +[[package]] +name = "toml-test-harness" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e00fda5710922fe6b3005bf6a5050c303d6f9625249c37b7386e8818f4af675" +dependencies = [ + "ignore", + "libtest-mimic", + "toml-test", + "toml-test-data", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +dependencies = [ + "memchr", +] diff --git a/vendor/toml/Cargo.toml b/vendor/toml/Cargo.toml new file mode 100644 index 0000000..b073553 --- /dev/null +++ b/vendor/toml/Cargo.toml @@ -0,0 +1,150 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.66.0" +name = "toml" +version = "0.7.8" +authors = ["Alex Crichton <alex@alexcrichton.com>"] +include = [ + "build.rs", + "src/**/*", + "Cargo.toml", + "Cargo.lock", + "LICENSE*", + "README.md", + "benches/**/*", + "examples/**/*", + "tests/**/*", +] +description = """ +A native Rust encoder and decoder of TOML-formatted files and streams. Provides +implementations of the standard Serialize/Deserialize traits for TOML data to +facilitate deserializing and serializing Rust structures. +""" +homepage = "https://github.com/toml-rs/toml" +readme = "README.md" +keywords = [ + "encoding", + "toml", +] +categories = [ + "encoding", + "parser-implementations", + "parsing", + "config", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/toml-rs/toml" +autotests = false + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +min = 1 +replace = "{{version}}" +search = "Unreleased" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = "...{{tag_name}}" +search = '\.\.\.HEAD' + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +min = 1 +replace = "{{date}}" +search = "ReleaseDate" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = """ +<!-- next-header --> +## [Unreleased] - ReleaseDate +""" +search = "<!-- next-header -->" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = """ +<!-- next-url --> +[Unreleased]: https://github.com/toml-rs/toml/compare/{{tag_name}}...HEAD""" +search = "<!-- next-url -->" + +[[example]] +name = "decode" +required-features = [ + "parse", + "display", +] + +[[example]] +name = "enum_external" +required-features = [ + "parse", + "display", +] + +[[example]] +name = "toml2json" +required-features = [ + "parse", + "display", +] + +[dependencies.indexmap] +version = ">= 1.9.1" +optional = true + +[dependencies.serde] +version = "1.0.145" + +[dependencies.serde_spanned] +version = "0.6.3" +features = ["serde"] + +[dependencies.toml_datetime] +version = "0.6.3" +features = ["serde"] + +[dependencies.toml_edit] +version = "0.19.15" +features = ["serde"] +optional = true + +[dev-dependencies.serde] +version = "1.0.160" +features = ["derive"] + +[dev-dependencies.serde_json] +version = "1.0.96" + +[dev-dependencies.snapbox] +version = "0.4.8" + +[features] +default = [ + "parse", + "display", +] +display = ["dep:toml_edit"] +parse = ["dep:toml_edit"] +preserve_order = ["indexmap"] diff --git a/vendor/toml/LICENSE-APACHE b/vendor/toml/LICENSE-APACHE new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/vendor/toml/LICENSE-APACHE @@ -0,0 +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. + diff --git a/vendor/toml/LICENSE-MIT b/vendor/toml/LICENSE-MIT new file mode 100644 index 0000000..a2d0108 --- /dev/null +++ b/vendor/toml/LICENSE-MIT @@ -0,0 +1,19 @@ +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 +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/toml/README.md b/vendor/toml/README.md new file mode 100644 index 0000000..82960dd --- /dev/null +++ b/vendor/toml/README.md @@ -0,0 +1,29 @@ +# toml + +[![Latest Version](https://img.shields.io/crates/v/toml.svg)](https://crates.io/crates/toml) +[![Documentation](https://docs.rs/toml/badge.svg)](https://docs.rs/toml) + +A [serde]-compatible [TOML][toml] decoder and encoder for Rust. + +For format-preserving edits or finer control over output, see [toml_edit] + +[serde]: https://serde.rs/ +[toml]: https://github.com/toml-lang/toml +[toml_edit]: https://docs.rs/toml_edit + +# License + +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in toml-rs by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/vendor/toml/debian/patches/relax-dep.diff b/vendor/toml/debian/patches/relax-dep.diff new file mode 100644 index 0000000..5043cc3 --- /dev/null +++ b/vendor/toml/debian/patches/relax-dep.diff @@ -0,0 +1,22 @@ +Index: toml/Cargo.toml +=================================================================== +--- toml.orig/Cargo.toml ++++ toml/Cargo.toml +@@ -117,7 +117,7 @@ name = "encoder_compliance" + harness = false + + [dependencies.indexmap] +-version = "2.0.0" ++version = ">= 1.9.1" + optional = true + + [dependencies.serde] +@@ -144,7 +144,7 @@ features = ["derive"] + version = "1.0.96" + + [dev-dependencies.snapbox] +-version = "0.4.11" ++version = "0.4.8" + + [dev-dependencies.toml-test-harness] + version = "0.4.3" diff --git a/vendor/toml/debian/patches/remove-toml-test-harness.diff b/vendor/toml/debian/patches/remove-toml-test-harness.diff new file mode 100644 index 0000000..1b5131f --- /dev/null +++ b/vendor/toml/debian/patches/remove-toml-test-harness.diff @@ -0,0 +1,37 @@ +Index: toml/Cargo.toml +=================================================================== +--- toml.orig/Cargo.toml ++++ toml/Cargo.toml +@@ -45,6 +45,7 @@ categories = [ + ] + license = "MIT OR Apache-2.0" + repository = "https://github.com/toml-rs/toml" ++autotests = false + + [package.metadata.docs.rs] + rustdoc-args = [ +@@ -108,14 +109,6 @@ required-features = [ + "display", + ] + +-[[test]] +-name = "decoder_compliance" +-harness = false +- +-[[test]] +-name = "encoder_compliance" +-harness = false +- + [dependencies.indexmap] + version = ">= 1.9.1" + optional = true +@@ -146,9 +139,6 @@ version = "1.0.96" + [dev-dependencies.snapbox] + version = "0.4.8" + +-[dev-dependencies.toml-test-harness] +-version = "0.4.3" +- + [features] + default = [ + "parse", diff --git a/vendor/toml/debian/patches/series b/vendor/toml/debian/patches/series new file mode 100644 index 0000000..d2cabf2 --- /dev/null +++ b/vendor/toml/debian/patches/series @@ -0,0 +1,2 @@ +relax-dep.diff +remove-toml-test-harness.diff diff --git a/vendor/toml/examples/decode.rs b/vendor/toml/examples/decode.rs new file mode 100644 index 0000000..348e911 --- /dev/null +++ b/vendor/toml/examples/decode.rs @@ -0,0 +1,54 @@ +//! An example showing off the usage of `Deserialize` to automatically decode +//! TOML into a Rust `struct` + +#![deny(warnings)] +#![allow(dead_code)] + +use serde::Deserialize; + +/// This is what we're going to decode into. Each field is optional, meaning +/// that it doesn't have to be present in TOML. +#[derive(Debug, Deserialize)] +struct Config { + global_string: Option<String>, + global_integer: Option<u64>, + server: Option<ServerConfig>, + peers: Option<Vec<PeerConfig>>, +} + +/// Sub-structs are decoded from tables, so this will decode from the `[server]` +/// table. +/// +/// Again, each field is optional, meaning they don't have to be present. +#[derive(Debug, Deserialize)] +struct ServerConfig { + ip: Option<String>, + port: Option<u64>, +} + +#[derive(Debug, Deserialize)] +struct PeerConfig { + ip: Option<String>, + port: Option<u64>, +} + +fn main() { + let toml_str = r#" + global_string = "test" + global_integer = 5 + + [server] + ip = "127.0.0.1" + port = 80 + + [[peers]] + ip = "127.0.0.1" + port = 8080 + + [[peers]] + ip = "127.0.0.1" + "#; + + let decoded: Config = toml::from_str(toml_str).unwrap(); + println!("{:#?}", decoded); +} diff --git a/vendor/toml/examples/enum_external.rs b/vendor/toml/examples/enum_external.rs new file mode 100644 index 0000000..edac7d6 --- /dev/null +++ b/vendor/toml/examples/enum_external.rs @@ -0,0 +1,45 @@ +//! An example showing off the usage of `Deserialize` to automatically decode +//! TOML into a Rust `struct`, with enums. + +#![deny(warnings)] +#![allow(dead_code)] + +use serde::Deserialize; + +/// This is what we're going to decode into. +#[derive(Debug, Deserialize)] +struct Config { + plain: MyEnum, + plain_table: MyEnum, + tuple: MyEnum, + #[serde(rename = "struct")] + structv: MyEnum, + newtype: MyEnum, + my_enum: Vec<MyEnum>, +} + +#[derive(Debug, Deserialize)] +enum MyEnum { + Plain, + Tuple(i64, bool), + NewType(String), + Struct { value: i64 }, +} + +fn main() { + let toml_str = r#" + plain = "Plain" + plain_table = { Plain = {} } + tuple = { Tuple = { 0 = 123, 1 = true } } + struct = { Struct = { value = 123 } } + newtype = { NewType = "value" } + my_enum = [ + { Plain = {} }, + { Tuple = { 0 = 123, 1 = true } }, + { NewType = "value" }, + { Struct = { value = 123 } } + ]"#; + + let decoded: Config = toml::from_str(toml_str).unwrap(); + println!("{:#?}", decoded); +} diff --git a/vendor/toml/examples/toml2json.rs b/vendor/toml/examples/toml2json.rs new file mode 100644 index 0000000..3660611 --- /dev/null +++ b/vendor/toml/examples/toml2json.rs @@ -0,0 +1,47 @@ +#![deny(warnings)] + +use std::env; +use std::fs::File; +use std::io; +use std::io::prelude::*; + +use serde_json::Value as Json; +use toml::Value as Toml; + +fn main() { + let mut args = env::args(); + let mut input = String::new(); + if args.len() > 1 { + let name = args.nth(1).unwrap(); + File::open(name) + .and_then(|mut f| f.read_to_string(&mut input)) + .unwrap(); + } else { + io::stdin().read_to_string(&mut input).unwrap(); + } + + match input.parse() { + Ok(toml) => { + let json = convert(toml); + println!("{}", serde_json::to_string_pretty(&json).unwrap()); + } + Err(error) => println!("failed to parse TOML: {}", error), + } +} + +fn convert(toml: Toml) -> Json { + match toml { + Toml::String(s) => Json::String(s), + Toml::Integer(i) => Json::Number(i.into()), + Toml::Float(f) => { + let n = serde_json::Number::from_f64(f).expect("float infinite and nan not allowed"); + Json::Number(n) + } + Toml::Boolean(b) => Json::Bool(b), + Toml::Array(arr) => Json::Array(arr.into_iter().map(convert).collect()), + Toml::Table(table) => { + Json::Object(table.into_iter().map(|(k, v)| (k, convert(v))).collect()) + } + Toml::Datetime(dt) => Json::String(dt.to_string()), + } +} diff --git a/vendor/toml/src/de.rs b/vendor/toml/src/de.rs new file mode 100644 index 0000000..9eb4c41 --- /dev/null +++ b/vendor/toml/src/de.rs @@ -0,0 +1,322 @@ +//! Deserializing TOML into Rust structures. +//! +//! This module contains all the Serde support for deserializing TOML documents +//! into Rust structures. Note that some top-level functions here are also +//! provided at the top of the crate. + +/// Deserializes a string into a type. +/// +/// This function will attempt to interpret `s` as a TOML document and +/// deserialize `T` from the document. +/// +/// To deserializes TOML values, instead of documents, see [`ValueDeserializer`]. +/// +/// # Examples +/// +/// ``` +/// use serde::Deserialize; +/// +/// #[derive(Deserialize)] +/// struct Config { +/// title: String, +/// owner: Owner, +/// } +/// +/// #[derive(Deserialize)] +/// struct Owner { +/// name: String, +/// } +/// +/// let config: Config = toml::from_str(r#" +/// title = 'TOML Example' +/// +/// [owner] +/// name = 'Lisa' +/// "#).unwrap(); +/// +/// assert_eq!(config.title, "TOML Example"); +/// assert_eq!(config.owner.name, "Lisa"); +/// ``` +#[cfg(feature = "parse")] +pub fn from_str<T>(s: &'_ str) -> Result<T, Error> +where + T: serde::de::DeserializeOwned, +{ + T::deserialize(Deserializer::new(s)) +} + +/// Errors that can occur when deserializing a type. +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Error { + inner: crate::edit::de::Error, +} + +impl Error { + fn new(inner: crate::edit::de::Error) -> Self { + Self { inner } + } + + pub(crate) fn add_key(&mut self, key: String) { + self.inner.add_key(key) + } + + /// What went wrong + pub fn message(&self) -> &str { + self.inner.message() + } + + /// The start/end index into the original document where the error occurred + #[cfg(feature = "parse")] + pub fn span(&self) -> Option<std::ops::Range<usize>> { + self.inner.span() + } +} + +impl serde::de::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::new(crate::edit::de::Error::custom(msg)) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.inner.fmt(f) + } +} + +impl std::error::Error for Error {} + +/// Deserialization TOML document +/// +/// To deserializes TOML values, instead of documents, see [`ValueDeserializer`]. +#[cfg(feature = "parse")] +pub struct Deserializer<'a> { + input: &'a str, +} + +#[cfg(feature = "parse")] +impl<'a> Deserializer<'a> { + /// Deserialization implementation for TOML. + pub fn new(input: &'a str) -> Self { + Self { input } + } +} + +#[cfg(feature = "parse")] +impl<'de, 'a> serde::Deserializer<'de> for Deserializer<'a> { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner.deserialize_any(visitor).map_err(Error::new) + } + + // `None` is interpreted as a missing field so be sure to implement `Some` + // as a present field. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner.deserialize_option(visitor).map_err(Error::new) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner + .deserialize_newtype_struct(name, visitor) + .map_err(Error::new) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner + .deserialize_struct(name, fields, visitor) + .map_err(Error::new) + } + + // Called when the type to deserialize is an enum, as opposed to a field in the type. + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::Deserializer>() + .map_err(Error::new)?; + inner + .deserialize_enum(name, variants, visitor) + .map_err(Error::new) + } + + serde::forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq + bytes byte_buf map unit + ignored_any unit_struct tuple_struct tuple identifier + } +} + +/// Deserialization TOML [value][crate::Value] +/// +/// # Example +/// +/// ``` +/// use serde::Deserialize; +/// +/// #[derive(Deserialize)] +/// struct Config { +/// title: String, +/// owner: Owner, +/// } +/// +/// #[derive(Deserialize)] +/// struct Owner { +/// name: String, +/// } +/// +/// let config = Config::deserialize(toml::de::ValueDeserializer::new( +/// r#"{ title = 'TOML Example', owner = { name = 'Lisa' } }"# +/// )).unwrap(); +/// +/// assert_eq!(config.title, "TOML Example"); +/// assert_eq!(config.owner.name, "Lisa"); +/// ``` +#[cfg(feature = "parse")] +pub struct ValueDeserializer<'a> { + input: &'a str, +} + +#[cfg(feature = "parse")] +impl<'a> ValueDeserializer<'a> { + /// Deserialization implementation for TOML. + pub fn new(input: &'a str) -> Self { + Self { input } + } +} + +#[cfg(feature = "parse")] +impl<'de, 'a> serde::Deserializer<'de> for ValueDeserializer<'a> { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner.deserialize_any(visitor).map_err(Error::new) + } + + // `None` is interpreted as a missing field so be sure to implement `Some` + // as a present field. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner.deserialize_option(visitor).map_err(Error::new) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner + .deserialize_newtype_struct(name, visitor) + .map_err(Error::new) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner + .deserialize_struct(name, fields, visitor) + .map_err(Error::new) + } + + // Called when the type to deserialize is an enum, as opposed to a field in the type. + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let inner = self + .input + .parse::<toml_edit::de::ValueDeserializer>() + .map_err(Error::new)?; + inner + .deserialize_enum(name, variants, visitor) + .map_err(Error::new) + } + + serde::forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq + bytes byte_buf map unit + ignored_any unit_struct tuple_struct tuple identifier + } +} diff --git a/vendor/toml/src/edit.rs b/vendor/toml/src/edit.rs new file mode 100644 index 0000000..90fb284 --- /dev/null +++ b/vendor/toml/src/edit.rs @@ -0,0 +1,91 @@ +#[cfg(feature = "parse")] +pub(crate) mod de { + pub(crate) use toml_edit::de::Error; +} + +#[cfg(not(feature = "parse"))] +pub(crate) mod de { + /// Errors that can occur when deserializing a type. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct Error { + inner: String, + } + + impl Error { + /// Add key while unwinding + pub fn add_key(&mut self, _key: String) {} + + /// What went wrong + pub fn message(&self) -> &str { + self.inner.as_str() + } + } + + impl serde::de::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error { + inner: msg.to_string(), + } + } + } + + impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.inner.fmt(f) + } + } + + impl std::error::Error for Error {} +} + +#[cfg(feature = "display")] +pub(crate) mod ser { + pub(crate) use toml_edit::ser::Error; +} + +#[cfg(not(feature = "display"))] +pub(crate) mod ser { + #[derive(Debug, Clone, PartialEq, Eq)] + #[non_exhaustive] + pub(crate) enum Error { + UnsupportedType(Option<&'static str>), + UnsupportedNone, + KeyNotString, + Custom(String), + } + + impl Error { + pub(crate) fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::Custom(msg.to_string()) + } + } + + impl serde::ser::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Self::custom(msg) + } + } + + impl std::fmt::Display for Error { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::UnsupportedType(Some(t)) => write!(formatter, "unsupported {t} type"), + Self::UnsupportedType(None) => write!(formatter, "unsupported rust type"), + Self::UnsupportedNone => "unsupported None value".fmt(formatter), + Self::KeyNotString => "map key was not a string".fmt(formatter), + Self::Custom(s) => s.fmt(formatter), + } + } + } + + impl std::error::Error for Error {} +} diff --git a/vendor/toml/src/fmt.rs b/vendor/toml/src/fmt.rs new file mode 100644 index 0000000..281cb59 --- /dev/null +++ b/vendor/toml/src/fmt.rs @@ -0,0 +1,66 @@ +#[derive(Copy, Clone, Default)] +pub(crate) struct DocumentFormatter { + pub(crate) multiline_array: bool, + is_value: bool, +} + +impl toml_edit::visit_mut::VisitMut for DocumentFormatter { + fn visit_document_mut(&mut self, node: &mut toml_edit::Document) { + toml_edit::visit_mut::visit_document_mut(self, node); + } + + fn visit_item_mut(&mut self, node: &mut toml_edit::Item) { + let is_parent_value = self.is_value; + if !is_parent_value { + let other = std::mem::take(node); + let other = match other.into_table().map(toml_edit::Item::Table) { + Ok(i) => i, + Err(i) => i, + }; + let other = match other + .into_array_of_tables() + .map(toml_edit::Item::ArrayOfTables) + { + Ok(i) => i, + Err(i) => i, + }; + self.is_value = other.is_value(); + *node = other; + } + + toml_edit::visit_mut::visit_item_mut(self, node); + self.is_value = is_parent_value; + } + + fn visit_table_mut(&mut self, node: &mut toml_edit::Table) { + node.decor_mut().clear(); + + // Empty tables could be semantically meaningful, so make sure they are not implicit + if !node.is_empty() { + node.set_implicit(true); + } + + toml_edit::visit_mut::visit_table_mut(self, node); + } + + fn visit_value_mut(&mut self, node: &mut toml_edit::Value) { + node.decor_mut().clear(); + + toml_edit::visit_mut::visit_value_mut(self, node); + } + + fn visit_array_mut(&mut self, node: &mut toml_edit::Array) { + toml_edit::visit_mut::visit_array_mut(self, node); + + if !self.multiline_array || (0..=1).contains(&node.len()) { + node.set_trailing(""); + node.set_trailing_comma(false); + } else { + for item in node.iter_mut() { + item.decor_mut().set_prefix("\n "); + } + node.set_trailing("\n"); + node.set_trailing_comma(true); + } + } +} diff --git a/vendor/toml/src/lib.rs b/vendor/toml/src/lib.rs new file mode 100644 index 0000000..61e6a4c --- /dev/null +++ b/vendor/toml/src/lib.rs @@ -0,0 +1,182 @@ +//! A [serde]-compatible [TOML]-parsing library +//! +//! TOML itself is a simple, ergonomic, and readable configuration format: +//! +//! ```toml +//! [package] +//! name = "toml" +//! version = "0.4.2" +//! authors = ["Alex Crichton <alex@alexcrichton.com>"] +//! +//! [dependencies] +//! serde = "1.0" +//! ``` +//! +//! The TOML format tends to be relatively common throughout the Rust community +//! for configuration, notably being used by [Cargo], Rust's package manager. +//! +//! ## TOML values +//! +//! A TOML document is represented with the [`Table`] type which maps `String` to the [`Value`] enum: +//! +//! ```rust +//! # use toml::value::{Datetime, Array, Table}; +//! pub enum Value { +//! String(String), +//! Integer(i64), +//! Float(f64), +//! Boolean(bool), +//! Datetime(Datetime), +//! Array(Array), +//! Table(Table), +//! } +//! ``` +//! +//! ## Parsing TOML +//! +//! The easiest way to parse a TOML document is via the [`Table`] type: +//! +#![cfg_attr(not(feature = "parse"), doc = " ```ignore")] +#![cfg_attr(feature = "parse", doc = " ```")] +//! use toml::Table; +//! +//! let value = "foo = 'bar'".parse::<Table>().unwrap(); +//! +//! assert_eq!(value["foo"].as_str(), Some("bar")); +//! ``` +//! +//! The [`Table`] type implements a number of convenience methods and +//! traits; the example above uses [`FromStr`] to parse a [`str`] into a +//! [`Table`]. +//! +//! ## Deserialization and Serialization +//! +//! This crate supports [`serde`] 1.0 with a number of +//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and +//! `Serializer` traits. Namely, you'll find: +//! +//! * `Deserialize for Table` +//! * `Serialize for Table` +//! * `Deserialize for Value` +//! * `Serialize for Value` +//! * `Deserialize for Datetime` +//! * `Serialize for Datetime` +//! * `Deserializer for de::Deserializer` +//! * `Serializer for ser::Serializer` +//! * `Deserializer for Table` +//! * `Deserializer for Value` +//! +//! This means that you can use Serde to deserialize/serialize the +//! [`Table`] type as well as [`Value`] and [`Datetime`] type in this crate. You can also +//! use the [`Deserializer`], [`Serializer`], or [`Table`] type itself to act as +//! a deserializer/serializer for arbitrary types. +//! +//! An example of deserializing with TOML is: +//! +#![cfg_attr(not(feature = "parse"), doc = " ```ignore")] +#![cfg_attr(feature = "parse", doc = " ```")] +//! use serde::Deserialize; +//! +//! #[derive(Deserialize)] +//! struct Config { +//! ip: String, +//! port: Option<u16>, +//! keys: Keys, +//! } +//! +//! #[derive(Deserialize)] +//! struct Keys { +//! github: String, +//! travis: Option<String>, +//! } +//! +//! let config: Config = toml::from_str(r#" +//! ip = '127.0.0.1' +//! +//! [keys] +//! github = 'xxxxxxxxxxxxxxxxx' +//! travis = 'yyyyyyyyyyyyyyyyy' +//! "#).unwrap(); +//! +//! assert_eq!(config.ip, "127.0.0.1"); +//! assert_eq!(config.port, None); +//! assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx"); +//! assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy"); +//! ``` +//! +//! You can serialize types in a similar fashion: +//! +#![cfg_attr(not(feature = "display"), doc = " ```ignore")] +#![cfg_attr(feature = "display", doc = " ```")] +//! use serde::Serialize; +//! +//! #[derive(Serialize)] +//! struct Config { +//! ip: String, +//! port: Option<u16>, +//! keys: Keys, +//! } +//! +//! #[derive(Serialize)] +//! struct Keys { +//! github: String, +//! travis: Option<String>, +//! } +//! +//! let config = Config { +//! ip: "127.0.0.1".to_string(), +//! port: None, +//! keys: Keys { +//! github: "xxxxxxxxxxxxxxxxx".to_string(), +//! travis: Some("yyyyyyyyyyyyyyyyy".to_string()), +//! }, +//! }; +//! +//! let toml = toml::to_string(&config).unwrap(); +//! ``` +//! +//! [TOML]: https://github.com/toml-lang/toml +//! [Cargo]: https://crates.io/ +//! [`serde`]: https://serde.rs/ +//! [serde]: https://serde.rs/ + +#![deny(missing_docs)] +#![warn(rust_2018_idioms)] +// Makes rustc abort compilation if there are any unsafe blocks in the crate. +// Presence of this annotation is picked up by tools such as cargo-geiger +// and lets them ensure that there is indeed no unsafe code as opposed to +// something they couldn't detect (e.g. unsafe added via macro expansion, etc). +#![forbid(unsafe_code)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +pub mod map; +pub mod value; + +pub mod de; +pub mod ser; + +#[doc(hidden)] +pub mod macros; + +mod edit; +#[cfg(feature = "display")] +mod fmt; +mod table; + +#[cfg(feature = "parse")] +#[doc(inline)] +pub use crate::de::{from_str, Deserializer}; +#[cfg(feature = "display")] +#[doc(inline)] +pub use crate::ser::{to_string, to_string_pretty, Serializer}; +#[doc(inline)] +pub use crate::value::Value; + +pub use serde_spanned::Spanned; +pub use table::Table; + +// Shortcuts for the module doc-comment +#[allow(unused_imports)] +use core::str::FromStr; +#[allow(unused_imports)] +use toml_datetime::Datetime; diff --git a/vendor/toml/src/macros.rs b/vendor/toml/src/macros.rs new file mode 100644 index 0000000..d86cc52 --- /dev/null +++ b/vendor/toml/src/macros.rs @@ -0,0 +1,460 @@ +pub use serde::de::{Deserialize, IntoDeserializer}; + +use crate::value::{Array, Table, Value}; + +/// Construct a [`Table`] from TOML syntax. +/// +/// ```rust +/// let cargo_toml = toml::toml! { +/// [package] +/// name = "toml" +/// version = "0.4.5" +/// authors = ["Alex Crichton <alex@alexcrichton.com>"] +/// +/// [badges] +/// travis-ci = { repository = "alexcrichton/toml-rs" } +/// +/// [dependencies] +/// serde = "1.0" +/// +/// [dev-dependencies] +/// serde_derive = "1.0" +/// serde_json = "1.0" +/// }; +/// +/// println!("{:#?}", cargo_toml); +/// ``` +#[macro_export] +macro_rules! toml { + ($($toml:tt)+) => {{ + let table = $crate::value::Table::new(); + let mut root = $crate::Value::Table(table); + $crate::toml_internal!(@toplevel root [] $($toml)+); + match root { + $crate::Value::Table(table) => table, + _ => unreachable!(), + } + }}; +} + +// TT-muncher to parse TOML syntax into a toml::Value. +// +// @toplevel -- Parse tokens outside of an inline table or inline array. In +// this state, `[table headers]` and `[[array headers]]` are +// allowed and `key = value` pairs are not separated by commas. +// +// @topleveldatetime -- Helper to parse a Datetime from string and insert it +// into a table, continuing in the @toplevel state. +// +// @path -- Turn a path segment into a string. Segments that look like idents +// are stringified, while quoted segments like `"cfg(windows)"` +// are not. +// +// @value -- Parse the value part of a `key = value` pair, which may be a +// primitive or inline table or inline array. +// +// @table -- Parse the contents of an inline table, returning them as a +// toml::Value::Table. +// +// @tabledatetime -- Helper to parse a Datetime from string and insert it +// into a table, continuing in the @table state. +// +// @array -- Parse the contents of an inline array, returning them as a +// toml::Value::Array. +// +// @arraydatetime -- Helper to parse a Datetime from string and push it into +// an array, continuing in the @array state. +// +// @trailingcomma -- Helper to append a comma to a sequence of tokens if the +// sequence is non-empty and does not already end in a trailing +// comma. +// +#[macro_export] +#[doc(hidden)] +macro_rules! toml_internal { + // Base case, no elements remaining. + (@toplevel $root:ident [$($path:tt)*]) => {}; + + // Parse negative number `key = -value`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = - $v:tt $($rest:tt)*) => { + $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = (-$v) $($rest)*); + }; + + // Parse positive number `key = +value`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = + $v:tt $($rest:tt)*) => { + $crate::toml_internal!(@toplevel $root [$($path)*] $($($k)-+).+ = ($v) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T00:32:00.999999-07:00`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T00:32:00-07:00`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + + // Parse local datetime `key = 1979-05-27T00:32:00.999999`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); + }; + // Space instead of T. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T07:32:00Z` and local datetime `key = 1979-05-27T07:32:00`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*); + }; + // Space instead of T. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); + }; + + // Parse local date `key = 1979-05-27`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($yr - $mo - $day) $($rest)*); + }; + + // Parse local time `key = 00:32:00.999999`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse local time `key = 07:32:00`. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt $($rest:tt)*) => { + $crate::toml_internal!(@topleveldatetime $root [$($path)*] $($($k)-+).+ = ($hr : $min : $sec) $($rest)*); + }; + + // Parse any other `key = value` including string, inline array, inline + // table, number, and boolean. + (@toplevel $root:ident [$($path:tt)*] $($($k:tt)-+).+ = $v:tt $($rest:tt)*) => {{ + $crate::macros::insert_toml( + &mut $root, + &[$($path)* $(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+], + $crate::toml_internal!(@value $v)); + $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*); + }}; + + // Parse array header `[[bin]]`. + (@toplevel $root:ident $oldpath:tt [[$($($path:tt)-+).+]] $($rest:tt)*) => { + $crate::macros::push_toml( + &mut $root, + &[$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+]); + $crate::toml_internal!(@toplevel $root [$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*); + }; + + // Parse table header `[patch.crates-io]`. + (@toplevel $root:ident $oldpath:tt [$($($path:tt)-+).+] $($rest:tt)*) => { + $crate::macros::insert_toml( + &mut $root, + &[$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+], + $crate::Value::Table($crate::value::Table::new())); + $crate::toml_internal!(@toplevel $root [$(&concat!($("-", $crate::toml_internal!(@path $path),)+)[1..],)+] $($rest)*); + }; + + // Parse datetime from string and insert into table. + (@topleveldatetime $root:ident [$($path:tt)*] $($($k:tt)-+).+ = ($($datetime:tt)+) $($rest:tt)*) => { + $crate::macros::insert_toml( + &mut $root, + &[$($path)* $(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+], + $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); + $crate::toml_internal!(@toplevel $root [$($path)*] $($rest)*); + }; + + // Turn a path segment into a string. + (@path $ident:ident) => { + stringify!($ident) + }; + + // For a path segment that is not an ident, expect that it is already a + // quoted string, like in `[target."cfg(windows)".dependencies]`. + (@path $quoted:tt) => { + $quoted + }; + + // Construct a Value from an inline table. + (@value { $($inline:tt)* }) => {{ + let mut table = $crate::Value::Table($crate::value::Table::new()); + $crate::toml_internal!(@trailingcomma (@table table) $($inline)*); + table + }}; + + // Construct a Value from an inline array. + (@value [ $($inline:tt)* ]) => {{ + let mut array = $crate::value::Array::new(); + $crate::toml_internal!(@trailingcomma (@array array) $($inline)*); + $crate::Value::Array(array) + }}; + + (@value (-nan)) => { + $crate::Value::Float(-::std::f64::NAN) + }; + + (@value (nan)) => { + $crate::Value::Float(::std::f64::NAN) + }; + + (@value nan) => { + $crate::Value::Float(::std::f64::NAN) + }; + + (@value (-inf)) => { + $crate::Value::Float(::std::f64::NEG_INFINITY) + }; + + (@value (inf)) => { + $crate::Value::Float(::std::f64::INFINITY) + }; + + (@value inf) => { + $crate::Value::Float(::std::f64::INFINITY) + }; + + // Construct a Value from any other type, probably string or boolean or number. + (@value $v:tt) => {{ + // TODO: Implement this with something like serde_json::to_value instead. + let de = $crate::macros::IntoDeserializer::<$crate::de::Error>::into_deserializer($v); + <$crate::Value as $crate::macros::Deserialize>::deserialize(de).unwrap() + }}; + + // Base case of inline table. + (@table $root:ident) => {}; + + // Parse negative number `key = -value`. + (@table $root:ident $($($k:tt)-+).+ = - $v:tt , $($rest:tt)*) => { + $crate::toml_internal!(@table $root $($($k)-+).+ = (-$v) , $($rest)*); + }; + + // Parse positive number `key = +value`. + (@table $root:ident $($($k:tt)-+).+ = + $v:tt , $($rest:tt)*) => { + $crate::toml_internal!(@table $root $($($k)-+).+ = ($v) , $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T00:32:00.999999-07:00`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T00:32:00-07:00`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + + // Parse local datetime `key = 1979-05-27T00:32:00.999999`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); + }; + // Space instead of T. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse offset datetime `key = 1979-05-27T07:32:00Z` and local datetime `key = 1979-05-27T07:32:00`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $dhr : $min : $sec) $($rest)*); + }; + // Space instead of T. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); + }; + + // Parse local date `key = 1979-05-27`. + (@table $root:ident $($($k:tt)-+).+ = $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($yr - $mo - $day) $($rest)*); + }; + + // Parse local time `key = 00:32:00.999999`. + (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse local time `key = 07:32:00`. + (@table $root:ident $($($k:tt)-+).+ = $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@tabledatetime $root $($($k)-+).+ = ($hr : $min : $sec) $($rest)*); + }; + + // Parse any other type, probably string or boolean or number. + (@table $root:ident $($($k:tt)-+).+ = $v:tt , $($rest:tt)*) => { + $crate::macros::insert_toml( + &mut $root, + &[$(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+], + $crate::toml_internal!(@value $v)); + $crate::toml_internal!(@table $root $($rest)*); + }; + + // Parse a Datetime from string and continue in @table state. + (@tabledatetime $root:ident $($($k:tt)-+).+ = ($($datetime:tt)*) $($rest:tt)*) => { + $crate::macros::insert_toml( + &mut $root, + &[$(&concat!($("-", $crate::toml_internal!(@path $k),)+)[1..], )+], + $crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); + $crate::toml_internal!(@table $root $($rest)*); + }; + + // Base case of inline array. + (@array $root:ident) => {}; + + // Parse negative number `-value`. + (@array $root:ident - $v:tt , $($rest:tt)*) => { + $crate::toml_internal!(@array $root (-$v) , $($rest)*); + }; + + // Parse positive number `+value`. + (@array $root:ident + $v:tt , $($rest:tt)*) => { + $crate::toml_internal!(@array $root ($v) , $($rest)*); + }; + + // Parse offset datetime `1979-05-27T00:32:00.999999-07:00`. + (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac - $tzh : $tzm) $($rest)*); + }; + + // Parse offset datetime `1979-05-27T00:32:00-07:00`. + (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + // Space instead of T. + (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt - $tzh:tt : $tzm:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec - $tzh : $tzm) $($rest)*); + }; + + // Parse local datetime `1979-05-27T00:32:00.999999`. + (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec . $frac) $($rest)*); + }; + // Space instead of T. + (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse offset datetime `1979-05-27T07:32:00Z` and local datetime `1979-05-27T07:32:00`. + (@array $root:ident $yr:tt - $mo:tt - $dhr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $dhr : $min : $sec) $($rest)*); + }; + // Space instead of T. + (@array $root:ident $yr:tt - $mo:tt - $day:tt $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day T $hr : $min : $sec) $($rest)*); + }; + + // Parse local date `1979-05-27`. + (@array $root:ident $yr:tt - $mo:tt - $day:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($yr - $mo - $day) $($rest)*); + }; + + // Parse local time `00:32:00.999999`. + (@array $root:ident $hr:tt : $min:tt : $sec:tt . $frac:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec . $frac) $($rest)*); + }; + + // Parse local time `07:32:00`. + (@array $root:ident $hr:tt : $min:tt : $sec:tt , $($rest:tt)*) => { + $crate::toml_internal!(@arraydatetime $root ($hr : $min : $sec) $($rest)*); + }; + + // Parse any other type, probably string or boolean or number. + (@array $root:ident $v:tt , $($rest:tt)*) => { + $root.push($crate::toml_internal!(@value $v)); + $crate::toml_internal!(@array $root $($rest)*); + }; + + // Parse a Datetime from string and continue in @array state. + (@arraydatetime $root:ident ($($datetime:tt)*) $($rest:tt)*) => { + $root.push($crate::Value::Datetime(concat!($(stringify!($datetime)),+).parse().unwrap())); + $crate::toml_internal!(@array $root $($rest)*); + }; + + // No trailing comma required if the tokens are empty. + (@trailingcomma ($($args:tt)*)) => { + $crate::toml_internal!($($args)*); + }; + + // Tokens end with a trailing comma, do not append another one. + (@trailingcomma ($($args:tt)*) ,) => { + $crate::toml_internal!($($args)* ,); + }; + + // Tokens end with something other than comma, append a trailing comma. + (@trailingcomma ($($args:tt)*) $last:tt) => { + $crate::toml_internal!($($args)* $last ,); + }; + + // Not yet at the last token. + (@trailingcomma ($($args:tt)*) $first:tt $($rest:tt)+) => { + $crate::toml_internal!(@trailingcomma ($($args)* $first) $($rest)+); + }; +} + +// Called when parsing a `key = value` pair. +// Inserts an entry into the table at the given path. +pub fn insert_toml(root: &mut Value, path: &[&str], value: Value) { + *traverse(root, path) = value; +} + +// Called when parsing an `[[array header]]`. +// Pushes an empty table onto the array at the given path. +pub fn push_toml(root: &mut Value, path: &[&str]) { + let target = traverse(root, path); + if !target.is_array() { + *target = Value::Array(Array::new()); + } + target + .as_array_mut() + .unwrap() + .push(Value::Table(Table::new())); +} + +fn traverse<'a>(root: &'a mut Value, path: &[&str]) -> &'a mut Value { + let mut cur = root; + for &key in path { + // Lexical lifetimes :D + let cur1 = cur; + + // From the TOML spec: + // + // > Each double-bracketed sub-table will belong to the most recently + // > defined table element above it. + let cur2 = if cur1.is_array() { + cur1.as_array_mut().unwrap().last_mut().unwrap() + } else { + cur1 + }; + + // We are about to index into this value, so it better be a table. + if !cur2.is_table() { + *cur2 = Value::Table(Table::new()); + } + + if !cur2.as_table().unwrap().contains_key(key) { + // Insert an empty table for the next loop iteration to point to. + let empty = Value::Table(Table::new()); + cur2.as_table_mut().unwrap().insert(key.to_owned(), empty); + } + + // Step into the current table. + cur = cur2.as_table_mut().unwrap().get_mut(key).unwrap(); + } + cur +} diff --git a/vendor/toml/src/map.rs b/vendor/toml/src/map.rs new file mode 100644 index 0000000..bd720a7 --- /dev/null +++ b/vendor/toml/src/map.rs @@ -0,0 +1,609 @@ +// Copyright 2017 Serde Developers +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A map of `String` to [Value]. +//! +//! By default the map is backed by a [`BTreeMap`]. Enable the `preserve_order` +//! feature of toml-rs to use [`IndexMap`] instead. +//! +//! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html +//! [`IndexMap`]: https://docs.rs/indexmap + +use crate::value::Value; +use serde::{de, ser}; +use std::borrow::Borrow; +use std::fmt::{self, Debug}; +use std::hash::Hash; +use std::iter::FromIterator; +use std::ops; + +#[cfg(not(feature = "preserve_order"))] +use std::collections::{btree_map, BTreeMap}; + +#[cfg(feature = "preserve_order")] +use indexmap::{self, IndexMap}; + +/// Represents a TOML key/value type. +pub struct Map<K, V> { + map: MapImpl<K, V>, +} + +#[cfg(not(feature = "preserve_order"))] +type MapImpl<K, V> = BTreeMap<K, V>; +#[cfg(feature = "preserve_order")] +type MapImpl<K, V> = IndexMap<K, V>; + +impl Map<String, Value> { + /// Makes a new empty Map. + #[inline] + pub fn new() -> Self { + Map { + map: MapImpl::new(), + } + } + + #[cfg(not(feature = "preserve_order"))] + /// Makes a new empty Map with the given initial capacity. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + // does not support with_capacity + let _ = capacity; + Map { + map: BTreeMap::new(), + } + } + + #[cfg(feature = "preserve_order")] + /// Makes a new empty Map with the given initial capacity. + #[inline] + pub fn with_capacity(capacity: usize) -> Self { + Map { + map: IndexMap::with_capacity(capacity), + } + } + + /// Clears the map, removing all values. + #[inline] + pub fn clear(&mut self) { + self.map.clear() + } + + /// Returns a reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + #[inline] + pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&Value> + where + String: Borrow<Q>, + Q: Ord + Eq + Hash, + { + self.map.get(key) + } + + /// Returns true if the map contains a value for the specified key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + #[inline] + pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool + where + String: Borrow<Q>, + Q: Ord + Eq + Hash, + { + self.map.contains_key(key) + } + + /// Returns a mutable reference to the value corresponding to the key. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + #[inline] + pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut Value> + where + String: Borrow<Q>, + Q: Ord + Eq + Hash, + { + self.map.get_mut(key) + } + + /// Inserts a key-value pair into the map. + /// + /// If the map did not have this key present, `None` is returned. + /// + /// If the map did have this key present, the value is updated, and the old + /// value is returned. The key is not updated, though; this matters for + /// types that can be `==` without being identical. + #[inline] + pub fn insert(&mut self, k: String, v: Value) -> Option<Value> { + self.map.insert(k, v) + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + /// + /// The key may be any borrowed form of the map's key type, but the ordering + /// on the borrowed form *must* match the ordering on the key type. + #[inline] + pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<Value> + where + String: Borrow<Q>, + Q: Ord + Eq + Hash, + { + self.map.remove(key) + } + + /// Retains only the elements specified by the `keep` predicate. + /// + /// In other words, remove all pairs `(k, v)` for which `keep(&k, &mut v)` + /// returns `false`. + /// + /// The elements are visited in iteration order. + #[inline] + pub fn retain<F>(&mut self, mut keep: F) + where + F: FnMut(&str, &mut Value) -> bool, + { + self.map.retain(|key, value| keep(key.as_str(), value)); + } + + /// Gets the given key's corresponding entry in the map for in-place + /// manipulation. + pub fn entry<S>(&mut self, key: S) -> Entry<'_> + where + S: Into<String>, + { + #[cfg(feature = "preserve_order")] + use indexmap::map::Entry as EntryImpl; + #[cfg(not(feature = "preserve_order"))] + use std::collections::btree_map::Entry as EntryImpl; + + match self.map.entry(key.into()) { + EntryImpl::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant }), + EntryImpl::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied }), + } + } + + /// Returns the number of elements in the map. + #[inline] + pub fn len(&self) -> usize { + self.map.len() + } + + /// Returns true if the map contains no elements. + #[inline] + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + + /// Gets an iterator over the entries of the map. + #[inline] + pub fn iter(&self) -> Iter<'_> { + Iter { + iter: self.map.iter(), + } + } + + /// Gets a mutable iterator over the entries of the map. + #[inline] + pub fn iter_mut(&mut self) -> IterMut<'_> { + IterMut { + iter: self.map.iter_mut(), + } + } + + /// Gets an iterator over the keys of the map. + #[inline] + pub fn keys(&self) -> Keys<'_> { + Keys { + iter: self.map.keys(), + } + } + + /// Gets an iterator over the values of the map. + #[inline] + pub fn values(&self) -> Values<'_> { + Values { + iter: self.map.values(), + } + } +} + +impl Default for Map<String, Value> { + #[inline] + fn default() -> Self { + Map { + map: MapImpl::new(), + } + } +} + +impl Clone for Map<String, Value> { + #[inline] + fn clone(&self) -> Self { + Map { + map: self.map.clone(), + } + } +} + +impl PartialEq for Map<String, Value> { + #[inline] + fn eq(&self, other: &Self) -> bool { + self.map.eq(&other.map) + } +} + +/// Access an element of this map. Panics if the given key is not present in the +/// map. +impl<'a, Q: ?Sized> ops::Index<&'a Q> for Map<String, Value> +where + String: Borrow<Q>, + Q: Ord + Eq + Hash, +{ + type Output = Value; + + fn index(&self, index: &Q) -> &Value { + self.map.index(index) + } +} + +/// Mutably access an element of this map. Panics if the given key is not +/// present in the map. +impl<'a, Q: ?Sized> ops::IndexMut<&'a Q> for Map<String, Value> +where + String: Borrow<Q>, + Q: Ord + Eq + Hash, +{ + fn index_mut(&mut self, index: &Q) -> &mut Value { + self.map.get_mut(index).expect("no entry found for key") + } +} + +impl Debug for Map<String, Value> { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + self.map.fmt(formatter) + } +} + +impl ser::Serialize for Map<String, Value> { + #[inline] + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + use serde::ser::SerializeMap; + let mut map = serializer.serialize_map(Some(self.len()))?; + for (k, v) in self { + map.serialize_key(k)?; + map.serialize_value(v)?; + } + map.end() + } +} + +impl<'de> de::Deserialize<'de> for Map<String, Value> { + #[inline] + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + struct Visitor; + + impl<'de> de::Visitor<'de> for Visitor { + type Value = Map<String, Value>; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a map") + } + + #[inline] + fn visit_unit<E>(self) -> Result<Self::Value, E> + where + E: de::Error, + { + Ok(Map::new()) + } + + #[inline] + fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> + where + V: de::MapAccess<'de>, + { + let mut values = Map::new(); + + while let Some((key, value)) = visitor.next_entry()? { + values.insert(key, value); + } + + Ok(values) + } + } + + deserializer.deserialize_map(Visitor) + } +} + +impl FromIterator<(String, Value)> for Map<String, Value> { + fn from_iter<T>(iter: T) -> Self + where + T: IntoIterator<Item = (String, Value)>, + { + Map { + map: FromIterator::from_iter(iter), + } + } +} + +impl Extend<(String, Value)> for Map<String, Value> { + fn extend<T>(&mut self, iter: T) + where + T: IntoIterator<Item = (String, Value)>, + { + self.map.extend(iter); + } +} + +macro_rules! delegate_iterator { + (($name:ident $($generics:tt)*) => $item:ty) => { + impl $($generics)* Iterator for $name $($generics)* { + type Item = $item; + #[inline] + fn next(&mut self) -> Option<Self::Item> { + self.iter.next() + } + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } + } + + impl $($generics)* DoubleEndedIterator for $name $($generics)* { + #[inline] + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back() + } + } + + impl $($generics)* ExactSizeIterator for $name $($generics)* { + #[inline] + fn len(&self) -> usize { + self.iter.len() + } + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +/// A view into a single entry in a map, which may either be vacant or occupied. +/// This enum is constructed from the [`entry`] method on [`Map`]. +/// +/// [`entry`]: struct.Map.html#method.entry +/// [`Map`]: struct.Map.html +pub enum Entry<'a> { + /// A vacant Entry. + Vacant(VacantEntry<'a>), + /// An occupied Entry. + Occupied(OccupiedEntry<'a>), +} + +/// A vacant Entry. It is part of the [`Entry`] enum. +/// +/// [`Entry`]: enum.Entry.html +pub struct VacantEntry<'a> { + vacant: VacantEntryImpl<'a>, +} + +/// An occupied Entry. It is part of the [`Entry`] enum. +/// +/// [`Entry`]: enum.Entry.html +pub struct OccupiedEntry<'a> { + occupied: OccupiedEntryImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type VacantEntryImpl<'a> = btree_map::VacantEntry<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type VacantEntryImpl<'a> = indexmap::map::VacantEntry<'a, String, Value>; + +#[cfg(not(feature = "preserve_order"))] +type OccupiedEntryImpl<'a> = btree_map::OccupiedEntry<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type OccupiedEntryImpl<'a> = indexmap::map::OccupiedEntry<'a, String, Value>; + +impl<'a> Entry<'a> { + /// Returns a reference to this entry's key. + pub fn key(&self) -> &String { + match *self { + Entry::Vacant(ref e) => e.key(), + Entry::Occupied(ref e) => e.key(), + } + } + + /// Ensures a value is in the entry by inserting the default if empty, and + /// returns a mutable reference to the value in the entry. + pub fn or_insert(self, default: Value) -> &'a mut Value { + match self { + Entry::Vacant(entry) => entry.insert(default), + Entry::Occupied(entry) => entry.into_mut(), + } + } + + /// Ensures a value is in the entry by inserting the result of the default + /// function if empty, and returns a mutable reference to the value in the + /// entry. + pub fn or_insert_with<F>(self, default: F) -> &'a mut Value + where + F: FnOnce() -> Value, + { + match self { + Entry::Vacant(entry) => entry.insert(default()), + Entry::Occupied(entry) => entry.into_mut(), + } + } +} + +impl<'a> VacantEntry<'a> { + /// Gets a reference to the key that would be used when inserting a value + /// through the VacantEntry. + #[inline] + pub fn key(&self) -> &String { + self.vacant.key() + } + + /// Sets the value of the entry with the VacantEntry's key, and returns a + /// mutable reference to it. + #[inline] + pub fn insert(self, value: Value) -> &'a mut Value { + self.vacant.insert(value) + } +} + +impl<'a> OccupiedEntry<'a> { + /// Gets a reference to the key in the entry. + #[inline] + pub fn key(&self) -> &String { + self.occupied.key() + } + + /// Gets a reference to the value in the entry. + #[inline] + pub fn get(&self) -> &Value { + self.occupied.get() + } + + /// Gets a mutable reference to the value in the entry. + #[inline] + pub fn get_mut(&mut self) -> &mut Value { + self.occupied.get_mut() + } + + /// Converts the entry into a mutable reference to its value. + #[inline] + pub fn into_mut(self) -> &'a mut Value { + self.occupied.into_mut() + } + + /// Sets the value of the entry with the `OccupiedEntry`'s key, and returns + /// the entry's old value. + #[inline] + pub fn insert(&mut self, value: Value) -> Value { + self.occupied.insert(value) + } + + /// Takes the value of the entry out of the map, and returns it. + #[inline] + pub fn remove(self) -> Value { + self.occupied.remove() + } +} + +////////////////////////////////////////////////////////////////////////////// + +impl<'a> IntoIterator for &'a Map<String, Value> { + type Item = (&'a String, &'a Value); + type IntoIter = Iter<'a>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + Iter { + iter: self.map.iter(), + } + } +} + +/// An iterator over a toml::Map's entries. +pub struct Iter<'a> { + iter: IterImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type IterImpl<'a> = btree_map::Iter<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type IterImpl<'a> = indexmap::map::Iter<'a, String, Value>; + +delegate_iterator!((Iter<'a>) => (&'a String, &'a Value)); + +////////////////////////////////////////////////////////////////////////////// + +impl<'a> IntoIterator for &'a mut Map<String, Value> { + type Item = (&'a String, &'a mut Value); + type IntoIter = IterMut<'a>; + #[inline] + fn into_iter(self) -> Self::IntoIter { + IterMut { + iter: self.map.iter_mut(), + } + } +} + +/// A mutable iterator over a toml::Map's entries. +pub struct IterMut<'a> { + iter: IterMutImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type IterMutImpl<'a> = btree_map::IterMut<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type IterMutImpl<'a> = indexmap::map::IterMut<'a, String, Value>; + +delegate_iterator!((IterMut<'a>) => (&'a String, &'a mut Value)); + +////////////////////////////////////////////////////////////////////////////// + +impl IntoIterator for Map<String, Value> { + type Item = (String, Value); + type IntoIter = IntoIter; + #[inline] + fn into_iter(self) -> Self::IntoIter { + IntoIter { + iter: self.map.into_iter(), + } + } +} + +/// An owning iterator over a toml::Map's entries. +pub struct IntoIter { + iter: IntoIterImpl, +} + +#[cfg(not(feature = "preserve_order"))] +type IntoIterImpl = btree_map::IntoIter<String, Value>; +#[cfg(feature = "preserve_order")] +type IntoIterImpl = indexmap::map::IntoIter<String, Value>; + +delegate_iterator!((IntoIter) => (String, Value)); + +////////////////////////////////////////////////////////////////////////////// + +/// An iterator over a toml::Map's keys. +pub struct Keys<'a> { + iter: KeysImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type KeysImpl<'a> = btree_map::Keys<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type KeysImpl<'a> = indexmap::map::Keys<'a, String, Value>; + +delegate_iterator!((Keys<'a>) => &'a String); + +////////////////////////////////////////////////////////////////////////////// + +/// An iterator over a toml::Map's values. +pub struct Values<'a> { + iter: ValuesImpl<'a>, +} + +#[cfg(not(feature = "preserve_order"))] +type ValuesImpl<'a> = btree_map::Values<'a, String, Value>; +#[cfg(feature = "preserve_order")] +type ValuesImpl<'a> = indexmap::map::Values<'a, String, Value>; + +delegate_iterator!((Values<'a>) => &'a Value); diff --git a/vendor/toml/src/ser.rs b/vendor/toml/src/ser.rs new file mode 100644 index 0000000..f1ab24b --- /dev/null +++ b/vendor/toml/src/ser.rs @@ -0,0 +1,1087 @@ +//! Serializing Rust structures into TOML. +//! +//! This module contains all the Serde support for serializing Rust structures +//! into TOML documents (as strings). Note that some top-level functions here +//! are also provided at the top of the crate. + +/// Serialize the given data structure as a String of TOML. +/// +/// 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. +/// +/// To serialize TOML values, instead of documents, see [`ValueSerializer`]. +/// +/// # Examples +/// +/// ``` +/// use serde::Serialize; +/// +/// #[derive(Serialize)] +/// struct Config { +/// database: Database, +/// } +/// +/// #[derive(Serialize)] +/// struct Database { +/// ip: String, +/// port: Vec<u16>, +/// connection_max: u32, +/// enabled: bool, +/// } +/// +/// let config = Config { +/// database: Database { +/// ip: "192.168.1.1".to_string(), +/// port: vec![8001, 8002, 8003], +/// connection_max: 5000, +/// enabled: false, +/// }, +/// }; +/// +/// let toml = toml::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, +{ + let mut output = String::new(); + let serializer = Serializer::new(&mut output); + value.serialize(serializer)?; + Ok(output) +} + +/// Serialize the given data structure as a "pretty" String of TOML. +/// +/// This is identical to `to_string` except the output string has a more +/// "pretty" output. See `Serializer::pretty` for more details. +/// +/// To serialize TOML values, instead of documents, see [`ValueSerializer`]. +/// +/// For greater customization, instead serialize to a +/// [`toml_edit::Document`](https://docs.rs/toml_edit/latest/toml_edit/struct.Document.html). +#[cfg(feature = "display")] +pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error> +where + T: serde::ser::Serialize, +{ + let mut output = String::new(); + let serializer = Serializer::pretty(&mut output); + value.serialize(serializer)?; + Ok(output) +} + +/// Errors that can occur when serializing a type. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Error { + pub(crate) inner: crate::edit::ser::Error, +} + +impl Error { + pub(crate) fn new(inner: impl std::fmt::Display) -> Self { + Self { + inner: crate::edit::ser::Error::Custom(inner.to_string()), + } + } + + #[cfg(feature = "display")] + pub(crate) fn wrap(inner: crate::edit::ser::Error) -> Self { + Self { inner } + } + + pub(crate) fn unsupported_type(t: Option<&'static str>) -> Self { + Self { + inner: crate::edit::ser::Error::UnsupportedType(t), + } + } + + pub(crate) fn unsupported_none() -> Self { + Self { + inner: crate::edit::ser::Error::UnsupportedNone, + } + } + + pub(crate) fn key_not_string() -> Self { + Self { + inner: crate::edit::ser::Error::KeyNotString, + } + } +} + +impl serde::ser::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::new(msg) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.inner.fmt(f) + } +} + +impl std::error::Error for Error {} + +/// Serialization for TOML documents. +/// +/// This structure implements serialization support for TOML to serialize an +/// arbitrary type to TOML. Note that the TOML format does not support all +/// datatypes in Rust, such as enums, tuples, and tuple structs. These types +/// will generate an error when serialized. +/// +/// Currently a serializer always writes its output to an in-memory `String`, +/// which is passed in when creating the serializer itself. +/// +/// To serialize TOML values, instead of documents, see [`ValueSerializer`]. +#[non_exhaustive] +#[cfg(feature = "display")] +pub struct Serializer<'d> { + dst: &'d mut String, + settings: crate::fmt::DocumentFormatter, +} + +#[cfg(feature = "display")] +impl<'d> Serializer<'d> { + /// Creates a new serializer which will emit TOML into the buffer provided. + /// + /// The serializer can then be used to serialize a type after which the data + /// will be present in `dst`. + pub fn new(dst: &'d mut String) -> Self { + Self { + dst, + settings: Default::default(), + } + } + + /// Apply a default "pretty" policy to the document + /// + /// For greater customization, instead serialize to a + /// [`toml_edit::Document`](https://docs.rs/toml_edit/latest/toml_edit/struct.Document.html). + pub fn pretty(dst: &'d mut String) -> Self { + let mut ser = Serializer::new(dst); + ser.settings.multiline_array = true; + ser + } +} + +#[cfg(feature = "display")] +impl<'d> serde::ser::Serializer for Serializer<'d> { + type Ok = (); + type Error = Error; + type SerializeSeq = SerializeDocumentArray<'d>; + type SerializeTuple = SerializeDocumentArray<'d>; + type SerializeTupleStruct = SerializeDocumentArray<'d>; + type SerializeTupleVariant = SerializeDocumentArray<'d>; + type SerializeMap = SerializeDocumentTable<'d>; + type SerializeStruct = SerializeDocumentTable<'d>; + type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + + fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_bool(v), + ) + } + + fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_i8(v), + ) + } + + fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_i16(v), + ) + } + + fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_i32(v), + ) + } + + fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_i64(v), + ) + } + + fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_u8(v), + ) + } + + fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_u16(v), + ) + } + + fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_u32(v), + ) + } + + fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_u64(v), + ) + } + + fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_f32(v), + ) + } + + fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_f64(v), + ) + } + + fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_char(v), + ) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_str(v), + ) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_bytes(v), + ) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_none(), + ) + } + + fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_some(v), + ) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_unit(), + ) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { + write_document( + self.dst, + self.settings, + toml_edit::ser::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> { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_unit_variant( + name, + variant_index, + variant, + ), + ) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + name: &'static str, + v: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v), + ) + } + + 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, + { + write_document( + self.dst, + self.settings, + toml_edit::ser::ValueSerializer::new().serialize_newtype_variant( + name, + variant_index, + variant, + value, + ), + ) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + let ser = toml_edit::ser::ValueSerializer::new() + .serialize_seq(len) + .map_err(Error::wrap)?; + let ser = SerializeDocumentArray::new(self, ser); + Ok(ser) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + let ser = toml_edit::ser::ValueSerializer::new() + .serialize_map(len) + .map_err(Error::wrap)?; + let ser = SerializeDocumentTable::new(self, ser); + Ok(ser) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error::unsupported_type(Some(name))) + } +} + +/// Serialization for TOML [values][crate::Value]. +/// +/// This structure implements serialization support for TOML to serialize an +/// arbitrary type to TOML. Note that the TOML format does not support all +/// datatypes in Rust, such as enums, tuples, and tuple structs. These types +/// will generate an error when serialized. +/// +/// Currently a serializer always writes its output to an in-memory `String`, +/// which is passed in when creating the serializer itself. +/// +/// # Examples +/// +/// ``` +/// use serde::Serialize; +/// +/// #[derive(Serialize)] +/// struct Config { +/// database: Database, +/// } +/// +/// #[derive(Serialize)] +/// struct Database { +/// ip: String, +/// port: Vec<u16>, +/// connection_max: u32, +/// enabled: bool, +/// } +/// +/// let config = Config { +/// database: Database { +/// ip: "192.168.1.1".to_string(), +/// port: vec![8001, 8002, 8003], +/// connection_max: 5000, +/// enabled: false, +/// }, +/// }; +/// +/// let mut value = String::new(); +/// serde::Serialize::serialize( +/// &config, +/// toml::ser::ValueSerializer::new(&mut value) +/// ).unwrap(); +/// println!("{}", value) +/// ``` +#[non_exhaustive] +#[cfg(feature = "display")] +pub struct ValueSerializer<'d> { + dst: &'d mut String, +} + +#[cfg(feature = "display")] +impl<'d> ValueSerializer<'d> { + /// Creates a new serializer which will emit TOML into the buffer provided. + /// + /// The serializer can then be used to serialize a type after which the data + /// will be present in `dst`. + pub fn new(dst: &'d mut String) -> Self { + Self { dst } + } +} + +#[cfg(feature = "display")] +impl<'d> serde::ser::Serializer for ValueSerializer<'d> { + type Ok = (); + type Error = Error; + type SerializeSeq = SerializeValueArray<'d>; + type SerializeTuple = SerializeValueArray<'d>; + type SerializeTupleStruct = SerializeValueArray<'d>; + type SerializeTupleVariant = SerializeValueArray<'d>; + type SerializeMap = SerializeValueTable<'d>; + type SerializeStruct = SerializeValueTable<'d>; + type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + + fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_bool(v), + ) + } + + fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_i8(v), + ) + } + + fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_i16(v), + ) + } + + fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_i32(v), + ) + } + + fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_i64(v), + ) + } + + fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_u8(v), + ) + } + + fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_u16(v), + ) + } + + fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_u32(v), + ) + } + + fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_u64(v), + ) + } + + fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_f32(v), + ) + } + + fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_f64(v), + ) + } + + fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_char(v), + ) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_str(v), + ) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_bytes(v), + ) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_none(), + ) + } + + fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_some(v), + ) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_unit(), + ) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { + write_value( + self.dst, + toml_edit::ser::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> { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_unit_variant( + name, + variant_index, + variant, + ), + ) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + name: &'static str, + v: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v), + ) + } + + 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, + { + write_value( + self.dst, + toml_edit::ser::ValueSerializer::new().serialize_newtype_variant( + name, + variant_index, + variant, + value, + ), + ) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + let ser = toml_edit::ser::ValueSerializer::new() + .serialize_seq(len) + .map_err(Error::wrap)?; + let ser = SerializeValueArray::new(self, ser); + Ok(ser) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + let ser = toml_edit::ser::ValueSerializer::new() + .serialize_map(len) + .map_err(Error::wrap)?; + let ser = SerializeValueTable::new(self, ser); + Ok(ser) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error::unsupported_type(Some(name))) + } +} + +#[cfg(feature = "display")] +use internal::*; + +#[cfg(feature = "display")] +mod internal { + use super::*; + + use crate::fmt::DocumentFormatter; + + type InnerSerializeDocumentSeq = + <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeSeq; + + #[doc(hidden)] + pub struct SerializeDocumentArray<'d> { + inner: InnerSerializeDocumentSeq, + dst: &'d mut String, + settings: DocumentFormatter, + } + + impl<'d> SerializeDocumentArray<'d> { + pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentSeq) -> Self { + Self { + inner, + dst: ser.dst, + settings: ser.settings, + } + } + } + + impl<'d> serde::ser::SerializeSeq for SerializeDocumentArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTuple for SerializeDocumentArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTupleVariant for SerializeDocumentArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTupleStruct for SerializeDocumentArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + type InnerSerializeDocumentTable = + <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeMap; + + #[doc(hidden)] + pub struct SerializeDocumentTable<'d> { + inner: InnerSerializeDocumentTable, + dst: &'d mut String, + settings: DocumentFormatter, + } + + impl<'d> SerializeDocumentTable<'d> { + pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentTable) -> Self { + Self { + inner, + dst: ser.dst, + settings: ser.settings, + } + } + } + + impl<'d> serde::ser::SerializeMap for SerializeDocumentTable<'d> { + type Ok = (); + type Error = Error; + + fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_key(input).map_err(Error::wrap) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_value(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeStruct for SerializeDocumentTable<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(key, value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_document(self.dst, self.settings, self.inner.end()) + } + } + + pub(crate) fn write_document( + dst: &mut String, + mut settings: DocumentFormatter, + value: Result<toml_edit::Value, crate::edit::ser::Error>, + ) -> Result<(), Error> { + use std::fmt::Write; + + let value = value.map_err(Error::wrap)?; + let mut table = match toml_edit::Item::Value(value).into_table() { + Ok(i) => i, + Err(_) => { + return Err(Error::unsupported_type(None)); + } + }; + + use toml_edit::visit_mut::VisitMut as _; + settings.visit_table_mut(&mut table); + + let doc: toml_edit::Document = table.into(); + write!(dst, "{}", doc).unwrap(); + + Ok(()) + } + + type InnerSerializeValueSeq = + <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeSeq; + + #[doc(hidden)] + pub struct SerializeValueArray<'d> { + inner: InnerSerializeValueSeq, + dst: &'d mut String, + } + + impl<'d> SerializeValueArray<'d> { + pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueSeq) -> Self { + Self { + inner, + dst: ser.dst, + } + } + } + + impl<'d> serde::ser::SerializeSeq for SerializeValueArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTuple for SerializeValueArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTupleVariant for SerializeValueArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeTupleStruct for SerializeValueArray<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + type InnerSerializeValueTable = + <toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeMap; + + #[doc(hidden)] + pub struct SerializeValueTable<'d> { + inner: InnerSerializeValueTable, + dst: &'d mut String, + } + + impl<'d> SerializeValueTable<'d> { + pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueTable) -> Self { + Self { + inner, + dst: ser.dst, + } + } + } + + impl<'d> serde::ser::SerializeMap for SerializeValueTable<'d> { + type Ok = (); + type Error = Error; + + fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_key(input).map_err(Error::wrap) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_value(value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + impl<'d> serde::ser::SerializeStruct for SerializeValueTable<'d> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.inner.serialize_field(key, value).map_err(Error::wrap) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + write_value(self.dst, self.inner.end()) + } + } + + pub(crate) fn write_value( + dst: &mut String, + value: Result<toml_edit::Value, crate::edit::ser::Error>, + ) -> Result<(), Error> { + use std::fmt::Write; + + let value = value.map_err(Error::wrap)?; + + write!(dst, "{}", value).unwrap(); + + Ok(()) + } +} diff --git a/vendor/toml/src/table.rs b/vendor/toml/src/table.rs new file mode 100644 index 0000000..a2d392b --- /dev/null +++ b/vendor/toml/src/table.rs @@ -0,0 +1,114 @@ +use std::fmt; + +use serde::de; +use serde::ser; + +use crate::map::Map; +use crate::Value; + +/// Type representing a TOML table, payload of the `Value::Table` variant. +/// By default it is backed by a BTreeMap, enable the `preserve_order` feature +/// to use a LinkedHashMap instead. +pub type Table = Map<String, Value>; + +impl Table { + /// Convert a `T` into `toml::Table`. + /// + /// This conversion can fail if `T`'s implementation of `Serialize` decides to + /// fail, or if `T` contains a map with non-string keys. + pub fn try_from<T>(value: T) -> Result<Self, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(crate::value::TableSerializer) + } + + /// Interpret a `toml::Table` as an instance of type `T`. + /// + /// This conversion can fail if the structure of the `Table` does not match the structure + /// expected by `T`, for example if `T` is a bool which can't be mapped to a `Table`. It can + /// also fail if the structure is correct but `T`'s implementation of `Deserialize` decides + /// that something is wrong with the data, for example required struct fields are missing from + /// the TOML map or some number is too big to fit in the expected primitive type. + pub fn try_into<'de, T>(self) -> Result<T, crate::de::Error> + where + T: de::Deserialize<'de>, + { + de::Deserialize::deserialize(self) + } +} + +#[cfg(feature = "display")] +impl fmt::Display for Table { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + crate::ser::to_string(self) + .expect("Unable to represent value as string") + .fmt(f) + } +} + +#[cfg(feature = "parse")] +impl std::str::FromStr for Table { + type Err = crate::de::Error; + fn from_str(s: &str) -> Result<Self, Self::Err> { + crate::from_str(s) + } +} + +impl<'de> de::Deserializer<'de> for Table { + type Error = crate::de::Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + Value::Table(self).deserialize_any(visitor) + } + + #[inline] + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + Value::Table(self).deserialize_enum(name, variants, visitor) + } + + // `None` is interpreted as a missing field so be sure to implement `Some` + // as a present field. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + Value::Table(self).deserialize_option(visitor) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + Value::Table(self).deserialize_newtype_struct(name, visitor) + } + + serde::forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit seq + bytes byte_buf map unit_struct tuple_struct struct + tuple ignored_any identifier + } +} + +impl<'de> de::IntoDeserializer<'de, crate::de::Error> for Table { + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} diff --git a/vendor/toml/src/value.rs b/vendor/toml/src/value.rs new file mode 100644 index 0000000..2785d9d --- /dev/null +++ b/vendor/toml/src/value.rs @@ -0,0 +1,1455 @@ +//! Definition of a TOML [value][Value] + +use std::collections::{BTreeMap, HashMap}; +use std::fmt; +use std::hash::Hash; +use std::mem::discriminant; +use std::ops; +use std::vec; + +use serde::de; +use serde::de::IntoDeserializer; +use serde::ser; + +use toml_datetime::__unstable as datetime; +pub use toml_datetime::{Date, Datetime, DatetimeParseError, Offset, Time}; + +/// Type representing a TOML array, payload of the `Value::Array` variant +pub type Array = Vec<Value>; + +#[doc(no_inline)] +pub use crate::Table; + +/// Representation of a TOML value. +#[derive(PartialEq, Clone, Debug)] +pub enum Value { + /// Represents a TOML string + String(String), + /// Represents a TOML integer + Integer(i64), + /// Represents a TOML float + Float(f64), + /// Represents a TOML boolean + Boolean(bool), + /// Represents a TOML datetime + Datetime(Datetime), + /// Represents a TOML array + Array(Array), + /// Represents a TOML table + Table(Table), +} + +impl Value { + /// Convert a `T` into `toml::Value` which is an enum that can represent + /// any valid TOML data. + /// + /// This conversion can fail if `T`'s implementation of `Serialize` decides to + /// fail, or if `T` contains a map with non-string keys. + pub fn try_from<T>(value: T) -> Result<Value, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(ValueSerializer) + } + + /// Interpret a `toml::Value` as an instance of type `T`. + /// + /// This conversion can fail if the structure of the `Value` does not match the + /// structure expected by `T`, for example if `T` is a struct type but the + /// `Value` contains something other than a TOML table. It can also fail if the + /// structure is correct but `T`'s implementation of `Deserialize` decides that + /// something is wrong with the data, for example required struct fields are + /// missing from the TOML map or some number is too big to fit in the expected + /// primitive type. + pub fn try_into<'de, T>(self) -> Result<T, crate::de::Error> + where + T: de::Deserialize<'de>, + { + de::Deserialize::deserialize(self) + } + + /// Index into a TOML array or map. A string index can be used to access a + /// value in a map, and a usize index can be used to access an element of an + /// array. + /// + /// Returns `None` if the type of `self` does not match the type of the + /// index, for example if the index is a string and `self` is an array or a + /// number. Also returns `None` if the given key does not exist in the map + /// or the given index is not within the bounds of the array. + pub fn get<I: Index>(&self, index: I) -> Option<&Value> { + index.index(self) + } + + /// Mutably index into a TOML array or map. A string index can be used to + /// access a value in a map, and a usize index can be used to access an + /// element of an array. + /// + /// Returns `None` if the type of `self` does not match the type of the + /// index, for example if the index is a string and `self` is an array or a + /// number. Also returns `None` if the given key does not exist in the map + /// or the given index is not within the bounds of the array. + pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Value> { + index.index_mut(self) + } + + /// Extracts the integer value if it is an integer. + pub fn as_integer(&self) -> Option<i64> { + match *self { + Value::Integer(i) => Some(i), + _ => None, + } + } + + /// Tests whether this value is an integer. + pub fn is_integer(&self) -> bool { + self.as_integer().is_some() + } + + /// Extracts the float value if it is a float. + pub fn as_float(&self) -> Option<f64> { + match *self { + Value::Float(f) => Some(f), + _ => None, + } + } + + /// Tests whether this value is a float. + pub fn is_float(&self) -> bool { + self.as_float().is_some() + } + + /// Extracts the boolean value if it is a boolean. + pub fn as_bool(&self) -> Option<bool> { + match *self { + Value::Boolean(b) => Some(b), + _ => None, + } + } + + /// Tests whether this value is a boolean. + pub fn is_bool(&self) -> bool { + self.as_bool().is_some() + } + + /// Extracts the string of this value if it is a string. + pub fn as_str(&self) -> Option<&str> { + match *self { + Value::String(ref s) => Some(&**s), + _ => None, + } + } + + /// Tests if this value is a string. + pub fn is_str(&self) -> bool { + self.as_str().is_some() + } + + /// Extracts the datetime value if it is a datetime. + /// + /// Note that a parsed TOML value will only contain ISO 8601 dates. An + /// example date is: + /// + /// ```notrust + /// 1979-05-27T07:32:00Z + /// ``` + pub fn as_datetime(&self) -> Option<&Datetime> { + match *self { + Value::Datetime(ref s) => Some(s), + _ => None, + } + } + + /// Tests whether this value is a datetime. + pub fn is_datetime(&self) -> bool { + self.as_datetime().is_some() + } + + /// Extracts the array value if it is an array. + pub fn as_array(&self) -> Option<&Vec<Value>> { + match *self { + Value::Array(ref s) => Some(s), + _ => None, + } + } + + /// Extracts the array value if it is an array. + pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> { + match *self { + Value::Array(ref mut s) => Some(s), + _ => None, + } + } + + /// Tests whether this value is an array. + pub fn is_array(&self) -> bool { + self.as_array().is_some() + } + + /// Extracts the table value if it is a table. + pub fn as_table(&self) -> Option<&Table> { + match *self { + Value::Table(ref s) => Some(s), + _ => None, + } + } + + /// Extracts the table value if it is a table. + pub fn as_table_mut(&mut self) -> Option<&mut Table> { + match *self { + Value::Table(ref mut s) => Some(s), + _ => None, + } + } + + /// Tests whether this value is a table. + pub fn is_table(&self) -> bool { + self.as_table().is_some() + } + + /// Tests whether this and another value have the same type. + pub fn same_type(&self, other: &Value) -> bool { + discriminant(self) == discriminant(other) + } + + /// Returns a human-readable representation of the type of this value. + pub fn type_str(&self) -> &'static str { + match *self { + Value::String(..) => "string", + Value::Integer(..) => "integer", + Value::Float(..) => "float", + Value::Boolean(..) => "boolean", + Value::Datetime(..) => "datetime", + Value::Array(..) => "array", + Value::Table(..) => "table", + } + } +} + +impl<I> ops::Index<I> for Value +where + I: Index, +{ + type Output = Value; + + fn index(&self, index: I) -> &Value { + self.get(index).expect("index not found") + } +} + +impl<I> ops::IndexMut<I> for Value +where + I: Index, +{ + fn index_mut(&mut self, index: I) -> &mut Value { + self.get_mut(index).expect("index not found") + } +} + +impl<'a> From<&'a str> for Value { + #[inline] + fn from(val: &'a str) -> Value { + Value::String(val.to_string()) + } +} + +impl<V: Into<Value>> From<Vec<V>> for Value { + fn from(val: Vec<V>) -> Value { + Value::Array(val.into_iter().map(|v| v.into()).collect()) + } +} + +impl<S: Into<String>, V: Into<Value>> From<BTreeMap<S, V>> for Value { + fn from(val: BTreeMap<S, V>) -> Value { + let table = val.into_iter().map(|(s, v)| (s.into(), v.into())).collect(); + + Value::Table(table) + } +} + +impl<S: Into<String> + Hash + Eq, V: Into<Value>> From<HashMap<S, V>> for Value { + fn from(val: HashMap<S, V>) -> Value { + let table = val.into_iter().map(|(s, v)| (s.into(), v.into())).collect(); + + Value::Table(table) + } +} + +macro_rules! impl_into_value { + ($variant:ident : $T:ty) => { + impl From<$T> for Value { + #[inline] + fn from(val: $T) -> Value { + Value::$variant(val.into()) + } + } + }; +} + +impl_into_value!(String: String); +impl_into_value!(Integer: i64); +impl_into_value!(Integer: i32); +impl_into_value!(Integer: i8); +impl_into_value!(Integer: u8); +impl_into_value!(Integer: u32); +impl_into_value!(Float: f64); +impl_into_value!(Float: f32); +impl_into_value!(Boolean: bool); +impl_into_value!(Datetime: Datetime); +impl_into_value!(Table: Table); + +/// Types that can be used to index a `toml::Value` +/// +/// Currently this is implemented for `usize` to index arrays and `str` to index +/// tables. +/// +/// This trait is sealed and not intended for implementation outside of the +/// `toml` crate. +pub trait Index: Sealed { + #[doc(hidden)] + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value>; + #[doc(hidden)] + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value>; +} + +/// An implementation detail that should not be implemented, this will change in +/// the future and break code otherwise. +#[doc(hidden)] +pub trait Sealed {} +impl Sealed for usize {} +impl Sealed for str {} +impl Sealed for String {} +impl<'a, T: Sealed + ?Sized> Sealed for &'a T {} + +impl Index for usize { + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { + match *val { + Value::Array(ref a) => a.get(*self), + _ => None, + } + } + + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { + match *val { + Value::Array(ref mut a) => a.get_mut(*self), + _ => None, + } + } +} + +impl Index for str { + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { + match *val { + Value::Table(ref a) => a.get(self), + _ => None, + } + } + + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { + match *val { + Value::Table(ref mut a) => a.get_mut(self), + _ => None, + } + } +} + +impl Index for String { + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { + self[..].index(val) + } + + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { + self[..].index_mut(val) + } +} + +impl<'s, T: ?Sized> Index for &'s T +where + T: Index, +{ + fn index<'a>(&self, val: &'a Value) -> Option<&'a Value> { + (**self).index(val) + } + + fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut Value> { + (**self).index_mut(val) + } +} + +#[cfg(feature = "display")] +impl fmt::Display for Value { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use serde::Serialize as _; + + let mut output = String::new(); + let serializer = crate::ser::ValueSerializer::new(&mut output); + self.serialize(serializer).unwrap(); + output.fmt(f) + } +} + +#[cfg(feature = "parse")] +impl std::str::FromStr for Value { + type Err = crate::de::Error; + fn from_str(s: &str) -> Result<Value, Self::Err> { + crate::from_str(s) + } +} + +impl ser::Serialize for Value { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + use serde::ser::SerializeMap; + + match *self { + Value::String(ref s) => serializer.serialize_str(s), + Value::Integer(i) => serializer.serialize_i64(i), + Value::Float(f) => serializer.serialize_f64(f), + Value::Boolean(b) => serializer.serialize_bool(b), + Value::Datetime(ref s) => s.serialize(serializer), + Value::Array(ref a) => a.serialize(serializer), + Value::Table(ref t) => { + let mut map = serializer.serialize_map(Some(t.len()))?; + // Be sure to visit non-tables first (and also non + // array-of-tables) as all keys must be emitted first. + for (k, v) in t { + if !v.is_table() && !v.is_array() + || (v + .as_array() + .map(|a| !a.iter().any(|v| v.is_table())) + .unwrap_or(false)) + { + map.serialize_entry(k, v)?; + } + } + for (k, v) in t { + if v.as_array() + .map(|a| a.iter().any(|v| v.is_table())) + .unwrap_or(false) + { + map.serialize_entry(k, v)?; + } + } + for (k, v) in t { + if v.is_table() { + map.serialize_entry(k, v)?; + } + } + map.end() + } + } + } +} + +impl<'de> de::Deserialize<'de> for Value { + fn deserialize<D>(deserializer: D) -> Result<Value, D::Error> + where + D: de::Deserializer<'de>, + { + struct ValueVisitor; + + impl<'de> de::Visitor<'de> for ValueVisitor { + type Value = Value; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("any valid TOML value") + } + + fn visit_bool<E>(self, value: bool) -> Result<Value, E> { + Ok(Value::Boolean(value)) + } + + fn visit_i64<E>(self, value: i64) -> Result<Value, E> { + Ok(Value::Integer(value)) + } + + fn visit_u64<E: de::Error>(self, value: u64) -> Result<Value, E> { + if value <= i64::max_value() as u64 { + Ok(Value::Integer(value as i64)) + } else { + Err(de::Error::custom("u64 value was too large")) + } + } + + fn visit_u32<E>(self, value: u32) -> Result<Value, E> { + Ok(Value::Integer(value.into())) + } + + fn visit_i32<E>(self, value: i32) -> Result<Value, E> { + Ok(Value::Integer(value.into())) + } + + fn visit_f64<E>(self, value: f64) -> Result<Value, E> { + Ok(Value::Float(value)) + } + + fn visit_str<E>(self, value: &str) -> Result<Value, E> { + Ok(Value::String(value.into())) + } + + fn visit_string<E>(self, value: String) -> Result<Value, E> { + Ok(Value::String(value)) + } + + fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error> + where + D: de::Deserializer<'de>, + { + de::Deserialize::deserialize(deserializer) + } + + fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error> + where + V: de::SeqAccess<'de>, + { + let mut vec = Vec::new(); + while let Some(elem) = visitor.next_element()? { + vec.push(elem); + } + Ok(Value::Array(vec)) + } + + fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error> + where + V: de::MapAccess<'de>, + { + let mut key = String::new(); + let datetime = visitor.next_key_seed(DatetimeOrTable { key: &mut key })?; + match datetime { + Some(true) => { + let date: datetime::DatetimeFromString = visitor.next_value()?; + return Ok(Value::Datetime(date.value)); + } + None => return Ok(Value::Table(Table::new())), + Some(false) => {} + } + let mut map = Table::new(); + map.insert(key, visitor.next_value()?); + while let Some(key) = visitor.next_key::<String>()? { + if let crate::map::Entry::Vacant(vacant) = map.entry(&key) { + vacant.insert(visitor.next_value()?); + } else { + let msg = format!("duplicate key: `{}`", key); + return Err(de::Error::custom(msg)); + } + } + Ok(Value::Table(map)) + } + } + + deserializer.deserialize_any(ValueVisitor) + } +} + +// This is wrapped by `Table` and any trait methods implemented here need to be wrapped there. +impl<'de> de::Deserializer<'de> for Value { + type Error = crate::de::Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + match self { + Value::Boolean(v) => visitor.visit_bool(v), + Value::Integer(n) => visitor.visit_i64(n), + Value::Float(n) => visitor.visit_f64(n), + Value::String(v) => visitor.visit_string(v), + Value::Datetime(v) => visitor.visit_string(v.to_string()), + Value::Array(v) => { + let len = v.len(); + let mut deserializer = SeqDeserializer::new(v); + let seq = visitor.visit_seq(&mut deserializer)?; + let remaining = deserializer.iter.len(); + if remaining == 0 { + Ok(seq) + } else { + Err(de::Error::invalid_length(len, &"fewer elements in array")) + } + } + Value::Table(v) => { + let len = v.len(); + let mut deserializer = MapDeserializer::new(v); + let map = visitor.visit_map(&mut deserializer)?; + let remaining = deserializer.iter.len(); + if remaining == 0 { + Ok(map) + } else { + Err(de::Error::invalid_length(len, &"fewer elements in map")) + } + } + } + } + + #[inline] + fn deserialize_enum<V>( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + match self { + Value::String(variant) => visitor.visit_enum(variant.into_deserializer()), + Value::Table(variant) => { + use de::Error; + if variant.is_empty() { + Err(crate::de::Error::custom( + "wanted exactly 1 element, found 0 elements", + )) + } else if variant.len() != 1 { + Err(crate::de::Error::custom( + "wanted exactly 1 element, more than 1 element", + )) + } else { + let deserializer = MapDeserializer::new(variant); + visitor.visit_enum(deserializer) + } + } + _ => Err(de::Error::invalid_type( + de::Unexpected::UnitVariant, + &"string only", + )), + } + } + + // `None` is interpreted as a missing field so be sure to implement `Some` + // as a present field. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, crate::de::Error> + where + V: de::Visitor<'de>, + { + visitor.visit_some(self) + } + + fn deserialize_newtype_struct<V>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, crate::de::Error> + where + V: 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 unit seq + bytes byte_buf map unit_struct tuple_struct struct + tuple ignored_any identifier + } +} + +struct SeqDeserializer { + iter: vec::IntoIter<Value>, +} + +impl SeqDeserializer { + fn new(vec: Vec<Value>) -> Self { + SeqDeserializer { + iter: vec.into_iter(), + } + } +} + +impl<'de> de::SeqAccess<'de> for SeqDeserializer { + type Error = crate::de::Error; + + fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, crate::de::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => seed.deserialize(value).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> Option<usize> { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +struct MapDeserializer { + iter: <Table as IntoIterator>::IntoIter, + value: Option<(String, Value)>, +} + +impl MapDeserializer { + fn new(map: Table) -> Self { + MapDeserializer { + iter: map.into_iter(), + value: None, + } + } +} + +impl<'de> de::MapAccess<'de> for MapDeserializer { + type Error = crate::de::Error; + + fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, crate::de::Error> + where + T: de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some((key, value)) => { + self.value = Some((key.clone(), value)); + seed.deserialize(Value::String(key)).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, crate::de::Error> + where + T: de::DeserializeSeed<'de>, + { + let (key, res) = match self.value.take() { + Some((key, value)) => (key, seed.deserialize(value)), + None => return Err(de::Error::custom("value is missing")), + }; + res.map_err(|mut error| { + error.add_key(key); + error + }) + } + + fn size_hint(&self) -> Option<usize> { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +impl<'de> de::EnumAccess<'de> for MapDeserializer { + type Error = crate::de::Error; + type Variant = MapEnumDeserializer; + + fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: serde::de::DeserializeSeed<'de>, + { + use de::Error; + let (key, value) = match self.iter.next() { + Some(pair) => pair, + None => { + return Err(Error::custom( + "expected table with exactly 1 entry, found empty table", + )); + } + }; + + let val = seed.deserialize(key.into_deserializer())?; + + let variant = MapEnumDeserializer::new(value); + + Ok((val, variant)) + } +} + +/// Deserializes table values into enum variants. +pub(crate) struct MapEnumDeserializer { + value: Value, +} + +impl MapEnumDeserializer { + pub(crate) fn new(value: Value) -> Self { + MapEnumDeserializer { value } + } +} + +impl<'de> serde::de::VariantAccess<'de> for MapEnumDeserializer { + type Error = crate::de::Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + use de::Error; + match self.value { + Value::Table(values) => { + if values.is_empty() { + Ok(()) + } else { + Err(Error::custom("expected empty table")) + } + } + e => Err(Error::custom(format!( + "expected table, found {}", + e.type_str() + ))), + } + } + + fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + seed.deserialize(self.value.into_deserializer()) + } + + fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + use de::Error; + match self.value { + Value::Table(values) => { + let tuple_values = values + .into_iter() + .enumerate() + .map(|(index, (key, value))| match key.parse::<usize>() { + Ok(key_index) if key_index == index => Ok(value), + Ok(_) | Err(_) => Err(Error::custom(format!( + "expected table key `{}`, but was `{}`", + index, key + ))), + }) + // 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), + }) + })?; + + if tuple_values.len() == len { + serde::de::Deserializer::deserialize_seq( + tuple_values.into_deserializer(), + visitor, + ) + } else { + Err(Error::custom(format!("expected tuple with length {}", len))) + } + } + e => Err(Error::custom(format!( + "expected table, found {}", + e.type_str() + ))), + } + } + + fn struct_variant<V>( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + serde::de::Deserializer::deserialize_struct( + self.value.into_deserializer(), + "", // TODO: this should be the variant name + fields, + visitor, + ) + } +} + +impl<'de> de::IntoDeserializer<'de, crate::de::Error> for Value { + type Deserializer = Self; + + fn into_deserializer(self) -> Self { + self + } +} + +struct ValueSerializer; + +impl ser::Serializer for ValueSerializer { + type Ok = Value; + type Error = crate::ser::Error; + + type SerializeSeq = ValueSerializeVec; + type SerializeTuple = ValueSerializeVec; + type SerializeTupleStruct = ValueSerializeVec; + type SerializeTupleVariant = ValueSerializeVec; + type SerializeMap = ValueSerializeMap; + type SerializeStruct = ValueSerializeMap; + type SerializeStructVariant = ser::Impossible<Value, crate::ser::Error>; + + fn serialize_bool(self, value: bool) -> Result<Value, crate::ser::Error> { + Ok(Value::Boolean(value)) + } + + fn serialize_i8(self, value: i8) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_i16(self, value: i16) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_i32(self, value: i32) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_i64(self, value: i64) -> Result<Value, crate::ser::Error> { + Ok(Value::Integer(value)) + } + + fn serialize_u8(self, value: u8) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_u16(self, value: u16) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_u32(self, value: u32) -> Result<Value, crate::ser::Error> { + self.serialize_i64(value.into()) + } + + fn serialize_u64(self, value: u64) -> Result<Value, crate::ser::Error> { + if value <= i64::max_value() as u64 { + self.serialize_i64(value as i64) + } else { + Err(ser::Error::custom("u64 value was too large")) + } + } + + fn serialize_f32(self, value: f32) -> Result<Value, crate::ser::Error> { + self.serialize_f64(value.into()) + } + + fn serialize_f64(self, value: f64) -> Result<Value, crate::ser::Error> { + Ok(Value::Float(value)) + } + + fn serialize_char(self, value: char) -> Result<Value, crate::ser::Error> { + let mut s = String::new(); + s.push(value); + self.serialize_str(&s) + } + + fn serialize_str(self, value: &str) -> Result<Value, crate::ser::Error> { + Ok(Value::String(value.to_owned())) + } + + fn serialize_bytes(self, value: &[u8]) -> Result<Value, crate::ser::Error> { + let vec = value.iter().map(|&b| Value::Integer(b.into())).collect(); + Ok(Value::Array(vec)) + } + + fn serialize_unit(self) -> Result<Value, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some("unit"))) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Value, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result<Value, crate::ser::Error> { + self.serialize_str(_variant) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + value: &T, + ) -> Result<Value, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<Value, crate::ser::Error> + where + T: ser::Serialize, + { + let value = value.serialize(ValueSerializer)?; + let mut table = Table::new(); + table.insert(variant.to_owned(), value); + Ok(table.into()) + } + + fn serialize_none(self) -> Result<Value, crate::ser::Error> { + Err(crate::ser::Error::unsupported_none()) + } + + fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Value, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, crate::ser::Error> { + Ok(ValueSerializeVec { + vec: Vec::with_capacity(len.unwrap_or(0)), + }) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, crate::ser::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, crate::ser::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, crate::ser::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, crate::ser::Error> { + Ok(ValueSerializeMap { + ser: SerializeMap { + map: Table::new(), + next_key: None, + }, + }) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, crate::ser::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } +} + +pub(crate) struct TableSerializer; + +impl ser::Serializer for TableSerializer { + type Ok = Table; + type Error = crate::ser::Error; + + type SerializeSeq = ser::Impossible<Table, crate::ser::Error>; + type SerializeTuple = ser::Impossible<Table, crate::ser::Error>; + type SerializeTupleStruct = ser::Impossible<Table, crate::ser::Error>; + type SerializeTupleVariant = ser::Impossible<Table, crate::ser::Error>; + type SerializeMap = SerializeMap; + type SerializeStruct = SerializeMap; + type SerializeStructVariant = ser::Impossible<Table, crate::ser::Error>; + + fn serialize_bool(self, _value: bool) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_i8(self, _value: i8) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_i16(self, _value: i16) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_i32(self, _value: i32) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_i64(self, _value: i64) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_u8(self, _value: u8) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_u16(self, _value: u16) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_u32(self, _value: u32) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_u64(self, _value: u64) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_f32(self, _value: f32) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_f64(self, _value: f64) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_char(self, _value: char) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_str(self, _value: &str) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_unit(self) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_unit_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + value: &T, + ) -> Result<Table, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<Table, crate::ser::Error> + where + T: ser::Serialize, + { + let value = value.serialize(ValueSerializer)?; + let mut table = Table::new(); + table.insert(variant.to_owned(), value); + Ok(table) + } + + fn serialize_none(self) -> Result<Table, crate::ser::Error> { + Err(crate::ser::Error::unsupported_none()) + } + + fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Table, crate::ser::Error> + where + T: ser::Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(None)) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleStruct, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, crate::ser::Error> { + Ok(SerializeMap { + map: Table::new(), + next_key: None, + }) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, crate::ser::Error> { + self.serialize_map(Some(len)) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, crate::ser::Error> { + Err(crate::ser::Error::unsupported_type(Some(name))) + } +} + +struct ValueSerializeVec { + vec: Vec<Value>, +} + +impl ser::SerializeSeq for ValueSerializeVec { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + self.vec.push(Value::try_from(value)?); + Ok(()) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + Ok(Value::Array(self.vec)) + } +} + +impl ser::SerializeTuple for ValueSerializeVec { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + ser::SerializeSeq::end(self) + } +} + +impl ser::SerializeTupleStruct for ValueSerializeVec { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + ser::SerializeSeq::end(self) + } +} + +impl ser::SerializeTupleVariant for ValueSerializeVec { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + ser::SerializeSeq::end(self) + } +} + +pub(crate) struct SerializeMap { + map: Table, + next_key: Option<String>, +} + +impl ser::SerializeMap for SerializeMap { + type Ok = Table; + type Error = crate::ser::Error; + + fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + match Value::try_from(key)? { + Value::String(s) => self.next_key = Some(s), + _ => return Err(crate::ser::Error::key_not_string()), + }; + Ok(()) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + let key = self.next_key.take(); + let key = key.expect("serialize_value called before serialize_key"); + match Value::try_from(value) { + Ok(value) => { + self.map.insert(key, value); + } + Err(crate::ser::Error { + inner: crate::edit::ser::Error::UnsupportedNone, + }) => {} + Err(e) => return Err(e), + } + Ok(()) + } + + fn end(self) -> Result<Table, crate::ser::Error> { + Ok(self.map) + } +} + +impl ser::SerializeStruct for SerializeMap { + type Ok = Table; + type Error = crate::ser::Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeMap::serialize_key(self, key)?; + ser::SerializeMap::serialize_value(self, value) + } + + fn end(self) -> Result<Table, crate::ser::Error> { + ser::SerializeMap::end(self) + } +} + +struct ValueSerializeMap { + ser: SerializeMap, +} + +impl ser::SerializeMap for ValueSerializeMap { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + self.ser.serialize_key(key) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + self.ser.serialize_value(value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + self.ser.end().map(Value::Table) + } +} + +impl ser::SerializeStruct for ValueSerializeMap { + type Ok = Value; + type Error = crate::ser::Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), crate::ser::Error> + where + T: ser::Serialize, + { + ser::SerializeMap::serialize_key(self, key)?; + ser::SerializeMap::serialize_value(self, value) + } + + fn end(self) -> Result<Value, crate::ser::Error> { + ser::SerializeMap::end(self) + } +} + +struct DatetimeOrTable<'a> { + key: &'a mut String, +} + +impl<'a, 'de> de::DeserializeSeed<'de> for DatetimeOrTable<'a> { + type Value = bool; + + fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> + where + D: de::Deserializer<'de>, + { + deserializer.deserialize_any(self) + } +} + +impl<'a, 'de> de::Visitor<'de> for DatetimeOrTable<'a> { + type Value = bool; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a string key") + } + + fn visit_str<E>(self, s: &str) -> Result<bool, E> + where + E: de::Error, + { + if s == datetime::FIELD { + Ok(true) + } else { + self.key.push_str(s); + Ok(false) + } + } + + fn visit_string<E>(self, s: String) -> Result<bool, E> + where + E: de::Error, + { + if s == datetime::FIELD { + Ok(true) + } else { + *self.key = s; + Ok(false) + } + } +} diff --git a/vendor/toml/tests/decoder.rs b/vendor/toml/tests/decoder.rs new file mode 100644 index 0000000..fe6db3f --- /dev/null +++ b/vendor/toml/tests/decoder.rs @@ -0,0 +1,67 @@ +#![cfg(all(feature = "parse", feature = "display"))] + +#[derive(Copy, Clone)] +pub struct Decoder; + +impl toml_test_harness::Decoder for Decoder { + fn name(&self) -> &str { + "toml" + } + + fn decode(&self, data: &[u8]) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + let data = std::str::from_utf8(data).map_err(toml_test_harness::Error::new)?; + let document = data + .parse::<toml::Value>() + .map_err(toml_test_harness::Error::new)?; + value_to_decoded(&document) + } +} + +fn value_to_decoded( + value: &toml::Value, +) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + match value { + toml::Value::Integer(v) => Ok(toml_test_harness::Decoded::Value( + toml_test_harness::DecodedValue::from(*v), + )), + toml::Value::String(v) => Ok(toml_test_harness::Decoded::Value( + toml_test_harness::DecodedValue::from(v), + )), + toml::Value::Float(v) => Ok(toml_test_harness::Decoded::Value( + toml_test_harness::DecodedValue::from(*v), + )), + toml::Value::Datetime(v) => { + let value = v.to_string(); + let value = match (v.date.is_some(), v.time.is_some(), v.offset.is_some()) { + (true, true, true) => toml_test_harness::DecodedValue::Datetime(value), + (true, true, false) => toml_test_harness::DecodedValue::DatetimeLocal(value), + (true, false, false) => toml_test_harness::DecodedValue::DateLocal(value), + (false, true, false) => toml_test_harness::DecodedValue::TimeLocal(value), + _ => unreachable!("Unsupported case"), + }; + Ok(toml_test_harness::Decoded::Value(value)) + } + toml::Value::Boolean(v) => Ok(toml_test_harness::Decoded::Value( + toml_test_harness::DecodedValue::from(*v), + )), + toml::Value::Array(v) => { + let v: Result<_, toml_test_harness::Error> = v.iter().map(value_to_decoded).collect(); + Ok(toml_test_harness::Decoded::Array(v?)) + } + toml::Value::Table(v) => table_to_decoded(v), + } +} + +fn table_to_decoded( + value: &toml::value::Table, +) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + let table: Result<_, toml_test_harness::Error> = value + .iter() + .map(|(k, v)| { + let k = k.to_owned(); + let v = value_to_decoded(v)?; + Ok((k, v)) + }) + .collect(); + Ok(toml_test_harness::Decoded::Table(table?)) +} diff --git a/vendor/toml/tests/decoder_compliance.rs b/vendor/toml/tests/decoder_compliance.rs new file mode 100644 index 0000000..5d4fc2a --- /dev/null +++ b/vendor/toml/tests/decoder_compliance.rs @@ -0,0 +1,21 @@ +mod decoder; + +#[cfg(all(feature = "parse", feature = "display"))] +fn main() { + let decoder = decoder::Decoder; + let mut harness = toml_test_harness::DecoderHarness::new(decoder); + harness + .ignore([ + "valid/spec/float-0.toml", + // Unreleased + "valid/string/escape-esc.toml", + "valid/string/hex-escape.toml", + "valid/datetime/no-seconds.toml", + "valid/inline-table/newline.toml", + ]) + .unwrap(); + harness.test(); +} + +#[cfg(not(all(feature = "parse", feature = "display")))] +fn main() {} diff --git a/vendor/toml/tests/encoder.rs b/vendor/toml/tests/encoder.rs new file mode 100644 index 0000000..eda6296 --- /dev/null +++ b/vendor/toml/tests/encoder.rs @@ -0,0 +1,81 @@ +#![cfg(all(feature = "parse", feature = "display"))] + +#[derive(Copy, Clone)] +pub struct Encoder; + +impl toml_test_harness::Encoder for Encoder { + fn name(&self) -> &str { + "toml" + } + + fn encode(&self, data: toml_test_harness::Decoded) -> Result<String, toml_test_harness::Error> { + let value = from_decoded(&data)?; + let s = toml::to_string(&value).map_err(toml_test_harness::Error::new)?; + Ok(s) + } +} + +fn from_decoded( + decoded: &toml_test_harness::Decoded, +) -> Result<toml::Value, toml_test_harness::Error> { + let value = match decoded { + toml_test_harness::Decoded::Value(value) => from_decoded_value(value)?, + toml_test_harness::Decoded::Table(value) => toml::Value::Table(from_table(value)?), + toml_test_harness::Decoded::Array(value) => toml::Value::Array(from_array(value)?), + }; + Ok(value) +} + +fn from_decoded_value( + decoded: &toml_test_harness::DecodedValue, +) -> Result<toml::Value, toml_test_harness::Error> { + match decoded { + toml_test_harness::DecodedValue::String(value) => Ok(toml::Value::String(value.clone())), + toml_test_harness::DecodedValue::Integer(value) => value + .parse::<i64>() + .map_err(toml_test_harness::Error::new) + .map(toml::Value::Integer), + toml_test_harness::DecodedValue::Float(value) => value + .parse::<f64>() + .map_err(toml_test_harness::Error::new) + .map(toml::Value::Float), + toml_test_harness::DecodedValue::Bool(value) => value + .parse::<bool>() + .map_err(toml_test_harness::Error::new) + .map(toml::Value::Boolean), + toml_test_harness::DecodedValue::Datetime(value) => value + .parse::<toml::value::Datetime>() + .map_err(toml_test_harness::Error::new) + .map(toml::Value::Datetime), + toml_test_harness::DecodedValue::DatetimeLocal(value) => value + .parse::<toml::value::Datetime>() + .map_err(toml_test_harness::Error::new) + .map(toml::Value::Datetime), + toml_test_harness::DecodedValue::DateLocal(value) => value + .parse::<toml::value::Datetime>() + .map_err(toml_test_harness::Error::new) + .map(toml::Value::Datetime), + toml_test_harness::DecodedValue::TimeLocal(value) => value + .parse::<toml::value::Datetime>() + .map_err(toml_test_harness::Error::new) + .map(toml::Value::Datetime), + } +} + +fn from_table( + decoded: &std::collections::HashMap<String, toml_test_harness::Decoded>, +) -> Result<toml::value::Table, toml_test_harness::Error> { + decoded + .iter() + .map(|(k, v)| { + let v = from_decoded(v)?; + Ok((k.to_owned(), v)) + }) + .collect() +} + +fn from_array( + decoded: &[toml_test_harness::Decoded], +) -> Result<toml::value::Array, toml_test_harness::Error> { + decoded.iter().map(from_decoded).collect() +} diff --git a/vendor/toml/tests/encoder_compliance.rs b/vendor/toml/tests/encoder_compliance.rs new file mode 100644 index 0000000..3807248 --- /dev/null +++ b/vendor/toml/tests/encoder_compliance.rs @@ -0,0 +1,14 @@ +mod decoder; +mod encoder; + +#[cfg(all(feature = "parse", feature = "display"))] +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"]).unwrap(); + harness.test(); +} + +#[cfg(not(all(feature = "parse", feature = "display")))] +fn main() {} diff --git a/vendor/toml/tests/testsuite/de_errors.rs b/vendor/toml/tests/testsuite/de_errors.rs new file mode 100644 index 0000000..b3630bd --- /dev/null +++ b/vendor/toml/tests/testsuite/de_errors.rs @@ -0,0 +1,460 @@ +use serde::{de, Deserialize}; +use std::fmt; + +macro_rules! bad { + ($toml:expr, $ty:ty, $msg:expr) => { + match toml::from_str::<$ty>($toml) { + Ok(s) => panic!("parsed to: {:#?}", s), + Err(e) => snapbox::assert_eq($msg, e.to_string()), + } + }; +} + +#[derive(Debug, Deserialize, PartialEq)] +struct Parent<T> { + p_a: T, + p_b: Vec<Child<T>>, +} + +#[derive(Debug, Deserialize, PartialEq)] +#[serde(deny_unknown_fields)] +struct Child<T> { + c_a: T, + c_b: T, +} + +#[derive(Debug, PartialEq)] +enum CasedString { + Lowercase(String), + Uppercase(String), +} + +impl<'de> de::Deserialize<'de> for CasedString { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: de::Deserializer<'de>, + { + struct CasedStringVisitor; + + impl<'de> de::Visitor<'de> for CasedStringVisitor { + type Value = CasedString; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string") + } + + fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> + where + E: de::Error, + { + if s.is_empty() { + Err(de::Error::invalid_length(0, &"a non-empty string")) + } else if s.chars().all(|x| x.is_ascii_lowercase()) { + Ok(CasedString::Lowercase(s.to_string())) + } else if s.chars().all(|x| x.is_ascii_uppercase()) { + Ok(CasedString::Uppercase(s.to_string())) + } else { + Err(de::Error::invalid_value( + de::Unexpected::Str(s), + &"all lowercase or all uppercase", + )) + } + } + } + + deserializer.deserialize_any(CasedStringVisitor) + } +} + +#[test] +fn custom_errors() { + toml::from_str::<Parent<CasedString>>( + " + p_a = 'a' + p_b = [{c_a = 'a', c_b = 'c'}] + ", + ) + .unwrap(); + + // Custom error at p_b value. + bad!( + " + p_a = '' + # ^ + ", + Parent<CasedString>, + "\ +TOML parse error at line 2, column 19 + | +2 | p_a = '' + | ^^ +invalid length 0, expected a non-empty string +" + ); + + // Missing field in table. + bad!( + " + p_a = 'a' + # ^ + ", + Parent<CasedString>, + "\ +TOML parse error at line 1, column 1 + | +1 | + | ^ +missing field `p_b` +" + ); + + // Invalid type in p_b. + bad!( + " + p_a = 'a' + p_b = 1 + # ^ + ", + Parent<CasedString>, + "\ +TOML parse error at line 3, column 19 + | +3 | p_b = 1 + | ^ +invalid type: integer `1`, expected a sequence +" + ); + + // Sub-table in Vec is missing a field. + bad!( + " + p_a = 'a' + p_b = [ + {c_a = 'a'} + # ^ + ] + ", + Parent<CasedString>, + "\ +TOML parse error at line 4, column 17 + | +4 | {c_a = 'a'} + | ^^^^^^^^^^^ +missing field `c_b` +" + ); + + // Sub-table in Vec has a field with a bad value. + bad!( + " + p_a = 'a' + p_b = [ + {c_a = 'a', c_b = '*'} + # ^ + ] + ", + Parent<CasedString>, + "\ +TOML parse error at line 4, column 35 + | +4 | {c_a = 'a', c_b = '*'} + | ^^^ +invalid value: string \"*\", expected all lowercase or all uppercase +" + ); + + // Sub-table in Vec is missing a field. + bad!( + " + p_a = 'a' + p_b = [ + {c_a = 'a', c_b = 'b'}, + {c_a = 'aa'} + # ^ + ] + ", + Parent<CasedString>, + "\ +TOML parse error at line 5, column 17 + | +5 | {c_a = 'aa'} + | ^^^^^^^^^^^^ +missing field `c_b` +" + ); + + // Sub-table in the middle of a Vec is missing a field. + bad!( + " + p_a = 'a' + p_b = [ + {c_a = 'a', c_b = 'b'}, + {c_a = 'aa'}, + # ^ + {c_a = 'aaa', c_b = 'bbb'}, + ] + ", + Parent<CasedString>, + "\ +TOML parse error at line 5, column 17 + | +5 | {c_a = 'aa'}, + | ^^^^^^^^^^^^ +missing field `c_b` +" + ); + + // Sub-table in the middle of a Vec has a field with a bad value. + bad!( + " + p_a = 'a' + p_b = [ + {c_a = 'a', c_b = 'b'}, + {c_a = 'aa', c_b = 1}, + # ^ + {c_a = 'aaa', c_b = 'bbb'}, + ] + ", + Parent<CasedString>, + "\ +TOML parse error at line 5, column 36 + | +5 | {c_a = 'aa', c_b = 1}, + | ^ +invalid type: integer `1`, expected a string +" + ); + + // Sub-table in the middle of a Vec has an extra field. + bad!( + " + p_a = 'a' + p_b = [ + {c_a = 'a', c_b = 'b'}, + {c_a = 'aa', c_b = 'bb', c_d = 'd'}, + # ^ + {c_a = 'aaa', c_b = 'bbb'}, + {c_a = 'aaaa', c_b = 'bbbb'}, + ] + ", + Parent<CasedString>, + "\ +TOML parse error at line 5, column 42 + | +5 | {c_a = 'aa', c_b = 'bb', c_d = 'd'}, + | ^^^ +unknown field `c_d`, expected `c_a` or `c_b` +" + ); + + // Sub-table in the middle of a Vec is missing a field. + // FIXME: This location is pretty off. + bad!( + " + p_a = 'a' + [[p_b]] + c_a = 'a' + c_b = 'b' + [[p_b]] + c_a = 'aa' + # c_b = 'bb' # <- missing field + [[p_b]] + c_a = 'aaa' + c_b = 'bbb' + [[p_b]] + # ^ + c_a = 'aaaa' + c_b = 'bbbb' + ", + Parent<CasedString>, + "\ +TOML parse error at line 6, column 13 + | +6 | [[p_b]] + | ^^^^^^^^^^^^^^^^^^^ +missing field `c_b` +" + ); + + // Sub-table in the middle of a Vec has a field with a bad value. + bad!( + " + p_a = 'a' + [[p_b]] + c_a = 'a' + c_b = 'b' + [[p_b]] + c_a = 'aa' + c_b = '*' + # ^ + [[p_b]] + c_a = 'aaa' + c_b = 'bbb' + ", + Parent<CasedString>, + "\ +TOML parse error at line 8, column 19 + | +8 | c_b = '*' + | ^^^ +invalid value: string \"*\", expected all lowercase or all uppercase +" + ); + + // Sub-table in the middle of a Vec has an extra field. + bad!( + " + p_a = 'a' + [[p_b]] + c_a = 'a' + c_b = 'b' + [[p_b]] + c_a = 'aa' + c_d = 'dd' # unknown field + # ^ + [[p_b]] + c_a = 'aaa' + c_b = 'bbb' + [[p_b]] + c_a = 'aaaa' + c_b = 'bbbb' + ", + Parent<CasedString>, + "\ +TOML parse error at line 8, column 13 + | +8 | c_d = 'dd' # unknown field + | ^^^ +unknown field `c_d`, expected `c_a` or `c_b` +" + ); +} + +#[test] +fn serde_derive_deserialize_errors() { + bad!( + " + p_a = '' + # ^ + ", + Parent<String>, + "\ +TOML parse error at line 1, column 1 + | +1 | + | ^ +missing field `p_b` +" + ); + + bad!( + " + p_a = '' + p_b = [ + {c_a = ''} + # ^ + ] + ", + Parent<String>, + "\ +TOML parse error at line 4, column 17 + | +4 | {c_a = ''} + | ^^^^^^^^^^ +missing field `c_b` +" + ); + + bad!( + " + p_a = '' + p_b = [ + {c_a = '', c_b = 1} + # ^ + ] + ", + Parent<String>, + "\ +TOML parse error at line 4, column 34 + | +4 | {c_a = '', c_b = 1} + | ^ +invalid type: integer `1`, expected a string +" + ); + + // FIXME: This location could be better. + bad!( + " + p_a = '' + p_b = [ + {c_a = '', c_b = '', c_d = ''}, + # ^ + ] + ", + Parent<String>, + "\ +TOML parse error at line 4, column 38 + | +4 | {c_a = '', c_b = '', c_d = ''}, + | ^^^ +unknown field `c_d`, expected `c_a` or `c_b` +" + ); + + bad!( + " + p_a = 'a' + p_b = [ + {c_a = '', c_b = 1, c_d = ''}, + # ^ + ] + ", + Parent<String>, + "\ +TOML parse error at line 4, column 34 + | +4 | {c_a = '', c_b = 1, c_d = ''}, + | ^ +invalid type: integer `1`, expected a string +" + ); +} + +#[test] +fn error_handles_crlf() { + bad!( + "\r\n\ + [t1]\r\n\ + [t2]\r\n\ + a = 1\r\n\ + a = 2\r\n\ + ", + toml::Value, + "\ +TOML parse error at line 5, column 1 + | +5 | a = 2 + | ^ +duplicate key `a` in table `t2` +" + ); + + // Should be the same as above. + bad!( + "\n\ + [t1]\n\ + [t2]\n\ + a = 1\n\ + a = 2\n\ + ", + toml::Value, + "\ +TOML parse error at line 5, column 1 + | +5 | a = 2 + | ^ +duplicate key `a` in table `t2` +" + ); +} diff --git a/vendor/toml/tests/testsuite/display.rs b/vendor/toml/tests/testsuite/display.rs new file mode 100644 index 0000000..7430fac --- /dev/null +++ b/vendor/toml/tests/testsuite/display.rs @@ -0,0 +1,116 @@ +use toml::map::Map; +use toml::Value::{Array, Boolean, Float, Integer, String, Table}; + +macro_rules! map( ($($k:expr => $v:expr),*) => ({ + let mut _m = Map::new(); + $(_m.insert($k.to_string(), $v);)* + _m +}) ); + +#[test] +fn simple_show() { + assert_eq!(String("foo".to_string()).to_string(), "\"foo\""); + assert_eq!(Integer(10).to_string(), "10"); + assert_eq!(Float(10.0).to_string(), "10.0"); + assert_eq!(Float(2.4).to_string(), "2.4"); + assert_eq!(Boolean(true).to_string(), "true"); + assert_eq!(Array(vec![]).to_string(), "[]"); + assert_eq!(Array(vec![Integer(1), Integer(2)]).to_string(), "[1, 2]"); +} + +#[test] +fn table() { + assert_eq!(map! {}.to_string(), ""); + assert_eq!( + map! { + "test" => Integer(2), + "test2" => Integer(3) } + .to_string(), + "test = 2\ntest2 = 3\n" + ); + assert_eq!( + map! { + "test" => Integer(2), + "test2" => Table(map! { + "test" => String("wut".to_string()) + }) + } + .to_string(), + "test = 2\n\ + \n\ + [test2]\n\ + test = \"wut\"\n" + ); + assert_eq!( + map! { + "test" => Integer(2), + "test2" => Table(map! { + "test" => String("wut".to_string()) + }) + } + .to_string(), + "test = 2\n\ + \n\ + [test2]\n\ + test = \"wut\"\n" + ); + assert_eq!( + map! { + "test" => Integer(2), + "test2" => Array(vec![Table(map! { + "test" => String("wut".to_string()) + })]) + } + .to_string(), + "test = 2\n\ + \n\ + [[test2]]\n\ + test = \"wut\"\n" + ); + #[cfg(feature = "preserve_order")] + assert_eq!( + map! { + "foo.bar" => Integer(2), + "foo\"bar" => Integer(2) + } + .to_string(), + "\"foo.bar\" = 2\n\ + \"foo\\\"bar\" = 2\n" + ); + assert_eq!( + map! { + "test" => Integer(2), + "test2" => Array(vec![Table(map! { + "test" => Array(vec![Integer(2)]) + })]) + } + .to_string(), + "test = 2\n\ + \n\ + [[test2]]\n\ + test = [2]\n" + ); + let table = map! { + "test" => Integer(2), + "test2" => Array(vec![Table(map! { + "test" => Array(vec![Array(vec![Integer(2), Integer(3)]), + Array(vec![String("foo".to_string()), String("bar".to_string())])]) + })]) + }; + assert_eq!( + table.to_string(), + "test = 2\n\ + \n\ + [[test2]]\n\ + test = [[2, 3], [\"foo\", \"bar\"]]\n" + ); + assert_eq!( + map! { + "test" => Array(vec![Integer(2)]), + "test2" => Integer(2) + } + .to_string(), + "test = [2]\n\ + test2 = 2\n" + ); +} diff --git a/vendor/toml/tests/testsuite/display_tricky.rs b/vendor/toml/tests/testsuite/display_tricky.rs new file mode 100644 index 0000000..379ae91 --- /dev/null +++ b/vendor/toml/tests/testsuite/display_tricky.rs @@ -0,0 +1,55 @@ +use serde::Deserialize; +use serde::Serialize; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Recipe { + pub name: String, + pub description: Option<String>, + #[serde(default)] + pub modules: Vec<Modules>, + #[serde(default)] + pub packages: Vec<Packages>, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Modules { + pub name: String, + pub version: Option<String>, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Packages { + pub name: String, + pub version: Option<String>, +} + +#[test] +fn both_ends() { + let recipe_works = toml::from_str::<Recipe>( + r#" + name = "testing" + description = "example" + modules = [] + + [[packages]] + name = "base" + "#, + ) + .unwrap(); + toml::to_string(&recipe_works).unwrap(); + + let recipe_fails = toml::from_str::<Recipe>( + r#" + name = "testing" + description = "example" + packages = [] + + [[modules]] + name = "base" + "#, + ) + .unwrap(); + + let recipe_toml = toml::Table::try_from(recipe_fails).unwrap(); + recipe_toml.to_string(); +} diff --git a/vendor/toml/tests/testsuite/enum_external_deserialize.rs b/vendor/toml/tests/testsuite/enum_external_deserialize.rs new file mode 100644 index 0000000..6e0c2f7 --- /dev/null +++ b/vendor/toml/tests/testsuite/enum_external_deserialize.rs @@ -0,0 +1,320 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize, PartialEq)] +struct OuterStruct { + inner: TheEnum, +} + +#[derive(Debug, Deserialize, PartialEq)] +enum TheEnum { + Plain, + Tuple(i64, bool), + NewType(String), + Struct { value: i64 }, +} + +#[derive(Debug, Deserialize, PartialEq)] +struct Val { + val: TheEnum, +} + +#[derive(Debug, Deserialize, PartialEq)] +struct Multi { + enums: Vec<TheEnum>, +} + +fn value_from_str<T>(s: &'_ str) -> Result<T, toml::de::Error> +where + T: serde::de::DeserializeOwned, +{ + T::deserialize(toml::de::ValueDeserializer::new(s)) +} + +#[test] +fn invalid_variant_returns_error_with_good_message_string() { + let error = value_from_str::<TheEnum>("\"NonExistent\"").unwrap_err(); + snapbox::assert_eq( + r#"unknown variant `NonExistent`, expected one of `Plain`, `Tuple`, `NewType`, `Struct` +"#, + error.to_string(), + ); + + let error = toml::from_str::<Val>("val = \"NonExistent\"").unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 1, column 7 + | +1 | val = "NonExistent" + | ^^^^^^^^^^^^^ +unknown variant `NonExistent`, expected one of `Plain`, `Tuple`, `NewType`, `Struct` +"#, + error.to_string(), + ); +} + +#[test] +fn invalid_variant_returns_error_with_good_message_inline_table() { + let error = value_from_str::<TheEnum>("{ NonExistent = {} }").unwrap_err(); + snapbox::assert_eq( + r#"unknown variant `NonExistent`, expected one of `Plain`, `Tuple`, `NewType`, `Struct` +"#, + error.to_string(), + ); + + let error = toml::from_str::<Val>("val = { NonExistent = {} }").unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 1, column 9 + | +1 | val = { NonExistent = {} } + | ^^^^^^^^^^^ +unknown variant `NonExistent`, expected one of `Plain`, `Tuple`, `NewType`, `Struct` +"#, + error.to_string(), + ); +} + +#[test] +fn extra_field_returns_expected_empty_table_error() { + let error = value_from_str::<TheEnum>("{ Plain = { extra_field = 404 } }").unwrap_err(); + snapbox::assert_eq( + r#"expected empty table +"#, + error.to_string(), + ); + + let error = toml::from_str::<Val>("val = { Plain = { extra_field = 404 } }").unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 1, column 17 + | +1 | val = { Plain = { extra_field = 404 } } + | ^^^^^^^^^^^^^^^^^^^^^ +expected empty table +"#, + error.to_string(), + ); +} + +#[test] +fn extra_field_returns_expected_empty_table_error_struct_variant() { + let error = value_from_str::<TheEnum>("{ Struct = { value = 123, extra_0 = 0, extra_1 = 1 } }") + .unwrap_err(); + + snapbox::assert_eq( + r#"unexpected keys in table: extra_0, extra_1, available keys: value +"#, + error.to_string(), + ); + + let error = + toml::from_str::<Val>("val = { Struct = { value = 123, extra_0 = 0, extra_1 = 1 } }") + .unwrap_err(); + + snapbox::assert_eq( + r#"TOML parse error at line 1, column 33 + | +1 | val = { Struct = { value = 123, extra_0 = 0, extra_1 = 1 } } + | ^^^^^^^ +unexpected keys in table: extra_0, extra_1, available keys: value +"#, + error.to_string(), + ); +} + +mod enum_unit { + use super::*; + + #[test] + fn from_str() { + assert_eq!(TheEnum::Plain, value_from_str("\"Plain\"").unwrap()); + + assert_eq!( + Val { + val: TheEnum::Plain + }, + toml::from_str("val = \"Plain\"").unwrap() + ); + } + + #[test] + fn from_inline_table() { + assert_eq!(TheEnum::Plain, value_from_str("{ Plain = {} }").unwrap()); + assert_eq!( + Val { + val: TheEnum::Plain + }, + toml::from_str("val = { Plain = {} }").unwrap() + ); + } + + #[test] + fn from_std_table() { + assert_eq!(TheEnum::Plain, toml::from_str("[Plain]\n").unwrap()); + } +} + +mod enum_tuple { + use super::*; + + #[test] + fn from_inline_table() { + assert_eq!( + TheEnum::Tuple(-123, true), + value_from_str("{ Tuple = { 0 = -123, 1 = true } }").unwrap() + ); + assert_eq!( + Val { + val: TheEnum::Tuple(-123, true) + }, + toml::from_str("val = { Tuple = { 0 = -123, 1 = true } }").unwrap() + ); + } + + #[test] + fn from_std_table() { + assert_eq!( + TheEnum::Tuple(-123, true), + toml::from_str( + r#"[Tuple] + 0 = -123 + 1 = true + "# + ) + .unwrap() + ); + } +} + +mod enum_newtype { + use super::*; + + #[test] + fn from_inline_table() { + assert_eq!( + TheEnum::NewType("value".to_string()), + value_from_str(r#"{ NewType = "value" }"#).unwrap() + ); + assert_eq!( + Val { + val: TheEnum::NewType("value".to_string()), + }, + toml::from_str(r#"val = { NewType = "value" }"#).unwrap() + ); + } + + #[test] + fn from_std_table() { + assert_eq!( + TheEnum::NewType("value".to_string()), + toml::from_str(r#"NewType = "value""#).unwrap() + ); + assert_eq!( + Val { + val: TheEnum::NewType("value".to_string()), + }, + toml::from_str( + r#"[val] + NewType = "value" + "# + ) + .unwrap() + ); + } +} + +mod enum_struct { + use super::*; + + #[test] + fn from_inline_table() { + assert_eq!( + TheEnum::Struct { value: -123 }, + value_from_str("{ Struct = { value = -123 } }").unwrap() + ); + assert_eq!( + Val { + val: TheEnum::Struct { value: -123 } + }, + toml::from_str("val = { Struct = { value = -123 } }").unwrap() + ); + } + + #[test] + fn from_std_table() { + assert_eq!( + TheEnum::Struct { value: -123 }, + toml::from_str( + r#"[Struct] + value = -123 + "# + ) + .unwrap() + ); + } + + #[test] + fn from_nested_std_table() { + assert_eq!( + OuterStruct { + inner: TheEnum::Struct { value: -123 } + }, + toml::from_str( + r#"[inner.Struct] + value = -123 + "# + ) + .unwrap() + ); + } +} + +mod enum_array { + use super::*; + + #[test] + fn from_inline_tables() { + let toml_str = r#" + enums = [ + { Plain = {} }, + { Tuple = { 0 = -123, 1 = true } }, + { NewType = "value" }, + { Struct = { value = -123 } } + ]"#; + assert_eq!( + Multi { + enums: vec![ + TheEnum::Plain, + TheEnum::Tuple(-123, true), + TheEnum::NewType("value".to_string()), + TheEnum::Struct { value: -123 }, + ] + }, + toml::from_str(toml_str).unwrap() + ); + } + + #[test] + fn from_std_table() { + let toml_str = r#"[[enums]] + Plain = {} + + [[enums]] + Tuple = { 0 = -123, 1 = true } + + [[enums]] + NewType = "value" + + [[enums]] + Struct = { value = -123 } + "#; + assert_eq!( + Multi { + enums: vec![ + TheEnum::Plain, + TheEnum::Tuple(-123, true), + TheEnum::NewType("value".to_string()), + TheEnum::Struct { value: -123 }, + ] + }, + toml::from_str(toml_str).unwrap() + ); + } +} diff --git a/vendor/toml/tests/testsuite/float.rs b/vendor/toml/tests/testsuite/float.rs new file mode 100644 index 0000000..d008134 --- /dev/null +++ b/vendor/toml/tests/testsuite/float.rs @@ -0,0 +1,80 @@ +use serde::Deserialize; +use serde::Serialize; +use toml::Value; + +#[rustfmt::skip] // appears to be a bug in rustfmt to make this converge... +macro_rules! float_inf_tests { + ($ty:ty) => {{ + #[derive(Serialize, Deserialize)] + struct S { + sf1: $ty, + sf2: $ty, + sf3: $ty, + sf4: $ty, + sf5: $ty, + sf6: $ty, + sf7: $ty, + sf8: $ty, + } + let inf: S = toml::from_str( + 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 + ", + ) + .expect("Parse infinities."); + + assert!(inf.sf1.is_infinite()); + assert!(inf.sf1.is_sign_positive()); + assert!(inf.sf2.is_infinite()); + assert!(inf.sf2.is_sign_positive()); + assert!(inf.sf3.is_infinite()); + assert!(inf.sf3.is_sign_negative()); + + assert!(inf.sf4.is_nan()); + assert!(inf.sf4.is_sign_positive()); + assert!(inf.sf5.is_nan()); + assert!(inf.sf5.is_sign_positive()); + assert!(inf.sf6.is_nan()); + assert!(inf.sf6.is_sign_negative()); + + assert_eq!(inf.sf7, 0.0); + assert!(inf.sf7.is_sign_positive()); + assert_eq!(inf.sf8, 0.0); + assert!(inf.sf8.is_sign_negative()); + + let s = toml::to_string(&inf).unwrap(); + assert_eq!( + s, + "\ +sf1 = inf +sf2 = inf +sf3 = -inf +sf4 = nan +sf5 = nan +sf6 = -nan +sf7 = 0.0 +sf8 = -0.0 +" + ); + + toml::from_str::<Value>(&s).expect("roundtrip"); + }}; +} + +#[test] +fn float_inf() { + float_inf_tests!(f32); + float_inf_tests!(f64); +} diff --git a/vendor/toml/tests/testsuite/formatting.rs b/vendor/toml/tests/testsuite/formatting.rs new file mode 100644 index 0000000..8240d1d --- /dev/null +++ b/vendor/toml/tests/testsuite/formatting.rs @@ -0,0 +1,54 @@ +use serde::Deserialize; +use serde::Serialize; +use toml::to_string; + +#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +struct User { + pub name: String, + pub surname: String, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +struct Users { + pub user: Vec<User>, +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] +struct TwoUsers { + pub user0: User, + pub user1: User, +} + +#[test] +fn no_unnecessary_newlines_array() { + assert!(!to_string(&Users { + user: vec![ + User { + name: "John".to_string(), + surname: "Doe".to_string(), + }, + User { + name: "Jane".to_string(), + surname: "Dough".to_string(), + }, + ], + }) + .unwrap() + .starts_with('\n')); +} + +#[test] +fn no_unnecessary_newlines_table() { + assert!(!to_string(&TwoUsers { + user0: User { + name: "John".to_string(), + surname: "Doe".to_string(), + }, + user1: User { + name: "Jane".to_string(), + surname: "Dough".to_string(), + }, + }) + .unwrap() + .starts_with('\n')); +} diff --git a/vendor/toml/tests/testsuite/macros.rs b/vendor/toml/tests/testsuite/macros.rs new file mode 100644 index 0000000..5100705 --- /dev/null +++ b/vendor/toml/tests/testsuite/macros.rs @@ -0,0 +1,368 @@ +use std::f64; + +use toml::toml; + +macro_rules! table { + ($($key:expr => $value:expr,)*) => {{ + // https://github.com/rust-lang/rust/issues/60643 + #[allow(unused_mut)] + let mut table = toml::value::Table::new(); + $( + table.insert($key.to_string(), $value.into()); + )* + toml::Value::Table(table) + }}; +} + +macro_rules! array { + ($($element:expr,)*) => {{ + // https://github.com/rust-lang/rust/issues/60643 + #![allow(clippy::vec_init_then_push)] + #[allow(unused_mut)] + let mut array = toml::value::Array::new(); + $( + array.push($element.into()); + )* + toml::Value::Array(array) + }}; +} + +macro_rules! datetime { + ($s:tt) => { + $s.parse::<toml::value::Datetime>().unwrap() + }; +} + +#[test] +fn test_cargo_toml() { + // Simple sanity check of: + // + // - Ordinary tables + // - Inline tables + // - Inline arrays + // - String values + // - Table keys containing hyphen + // - Table headers containing hyphen + let actual = toml! { + [package] + name = "toml" + version = "0.4.5" + authors = ["Alex Crichton <alex@alexcrichton.com>"] + + [badges] + travis-ci = { repository = "alexcrichton/toml-rs" } + + [dependencies] + serde = "1.0" + + [dev-dependencies] + serde_derive = "1.0" + serde_json = "1.0" + }; + + let expected = table! { + "package" => table! { + "name" => "toml".to_owned(), + "version" => "0.4.5".to_owned(), + "authors" => array! { + "Alex Crichton <alex@alexcrichton.com>".to_owned(), + }, + }, + "badges" => table! { + "travis-ci" => table! { + "repository" => "alexcrichton/toml-rs".to_owned(), + }, + }, + "dependencies" => table! { + "serde" => "1.0".to_owned(), + }, + "dev-dependencies" => table! { + "serde_derive" => "1.0".to_owned(), + "serde_json" => "1.0".to_owned(), + }, + }; + + assert_eq!(toml::Value::Table(actual), expected); +} + +#[test] +fn test_array() { + // Copied from the TOML spec. + let actual = toml! { + [[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + + [[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" + }; + + let expected = table! { + "fruit" => array! { + table! { + "name" => "apple", + "physical" => table! { + "color" => "red", + "shape" => "round", + }, + "variety" => array! { + table! { + "name" => "red delicious", + }, + table! { + "name" => "granny smith", + }, + }, + }, + table! { + "name" => "banana", + "variety" => array! { + table! { + "name" => "plantain", + }, + }, + }, + }, + }; + + assert_eq!(toml::Value::Table(actual), expected); +} + +#[test] +fn test_number() { + #![allow(clippy::unusual_byte_groupings)] // Verify the macro with odd formatting + + let actual = toml! { + positive = 1 + negative = -1 + table = { positive = 1, negative = -1 } + array = [ 1, -1 ] + neg_zero = -0 + pos_zero = +0 + float = 1.618 + + sf1 = inf + sf2 = +inf + sf3 = -inf + sf7 = +0.0 + sf8 = -0.0 + + hex = 0xa_b_c + oct = 0o755 + bin = 0b11010110 + }; + + let expected = table! { + "positive" => 1, + "negative" => -1, + "table" => table! { + "positive" => 1, + "negative" => -1, + }, + "array" => array! { + 1, + -1, + }, + "neg_zero" => -0, + "pos_zero" => 0, + "float" => 1.618, + "sf1" => f64::INFINITY, + "sf2" => f64::INFINITY, + "sf3" => f64::NEG_INFINITY, + "sf7" => 0.0, + "sf8" => -0.0, + "hex" => 2748, + "oct" => 493, + "bin" => 214, + }; + + assert_eq!(toml::Value::Table(actual), expected); +} + +#[test] +fn test_nan() { + let actual = toml! { + sf4 = nan + sf5 = +nan + sf6 = -nan + }; + assert!(actual["sf4"].as_float().unwrap().is_nan()); + assert!(actual["sf5"].as_float().unwrap().is_nan()); + assert!(actual["sf6"].as_float().unwrap().is_nan()); +} + +#[test] +fn test_datetime() { + let actual = toml! { + // Copied from the TOML spec. + odt1 = 1979-05-27T07:32:00Z + odt2 = 1979-05-27T00:32:00-07:00 + odt3 = 1979-05-27T00:32:00.999999-07:00 + odt4 = 1979-05-27 07:32:00Z + ldt1 = 1979-05-27T07:32:00 + ldt2 = 1979-05-27T00:32:00.999999 + ld1 = 1979-05-27 + lt1 = 07:32:00 + lt2 = 00:32:00.999999 + + table = { + odt1 = 1979-05-27T07:32:00Z, + odt2 = 1979-05-27T00:32:00-07:00, + odt3 = 1979-05-27T00:32:00.999999-07:00, + odt4 = 1979-05-27 07:32:00Z, + ldt1 = 1979-05-27T07:32:00, + ldt2 = 1979-05-27T00:32:00.999999, + ld1 = 1979-05-27, + lt1 = 07:32:00, + lt2 = 00:32:00.999999, + } + + array = [ + 1979-05-27T07:32:00Z, + 1979-05-27T00:32:00-07:00, + 1979-05-27T00:32:00.999999-07:00, + 1979-05-27 07:32:00Z, + 1979-05-27T07:32:00, + 1979-05-27T00:32:00.999999, + 1979-05-27, + 07:32:00, + 00:32:00.999999, + ] + }; + + let expected = table! { + "odt1" => datetime!("1979-05-27T07:32:00Z"), + "odt2" => datetime!("1979-05-27T00:32:00-07:00"), + "odt3" => datetime!("1979-05-27T00:32:00.999999-07:00"), + "odt4" => datetime!("1979-05-27 07:32:00Z"), + "ldt1" => datetime!("1979-05-27T07:32:00"), + "ldt2" => datetime!("1979-05-27T00:32:00.999999"), + "ld1" => datetime!("1979-05-27"), + "lt1" => datetime!("07:32:00"), + "lt2" => datetime!("00:32:00.999999"), + + "table" => table! { + "odt1" => datetime!("1979-05-27T07:32:00Z"), + "odt2" => datetime!("1979-05-27T00:32:00-07:00"), + "odt3" => datetime!("1979-05-27T00:32:00.999999-07:00"), + "odt4" => datetime!("1979-05-27 07:32:00Z"), + "ldt1" => datetime!("1979-05-27T07:32:00"), + "ldt2" => datetime!("1979-05-27T00:32:00.999999"), + "ld1" => datetime!("1979-05-27"), + "lt1" => datetime!("07:32:00"), + "lt2" => datetime!("00:32:00.999999"), + }, + + "array" => array! { + datetime!("1979-05-27T07:32:00Z"), + datetime!("1979-05-27T00:32:00-07:00"), + datetime!("1979-05-27T00:32:00.999999-07:00"), + datetime!("1979-05-27 07:32:00Z"), + datetime!("1979-05-27T07:32:00"), + datetime!("1979-05-27T00:32:00.999999"), + datetime!("1979-05-27"), + datetime!("07:32:00"), + datetime!("00:32:00.999999"), + }, + }; + + assert_eq!(toml::Value::Table(actual), expected); +} + +// This test requires rustc >= 1.20. +#[test] +fn test_quoted_key() { + let actual = toml! { + "quoted" = true + table = { "quoted" = true } + + [target."cfg(windows)".dependencies] + winapi = "0.2.8" + }; + + let expected = table! { + "quoted" => true, + "table" => table! { + "quoted" => true, + }, + "target" => table! { + "cfg(windows)" => table! { + "dependencies" => table! { + "winapi" => "0.2.8", + }, + }, + }, + }; + + assert_eq!(toml::Value::Table(actual), expected); +} + +#[test] +fn test_empty() { + let actual = toml! { + empty_inline_table = {} + empty_inline_array = [] + + [empty_table] + + [[empty_array]] + }; + + let expected = table! { + "empty_inline_table" => table! {}, + "empty_inline_array" => array! {}, + "empty_table" => table! {}, + "empty_array" => array! { + table! {}, + }, + }; + + assert_eq!(toml::Value::Table(actual), expected); +} + +#[test] +fn test_dotted_keys() { + let actual = toml! { + a.b = 123 + a.c = 1979-05-27T07:32:00Z + [table] + a.b.c = 1 + a . b . d = 2 + in = { type.name = "cat", type.color = "blue" } + }; + + let expected = table! { + "a" => table! { + "b" => 123, + "c" => datetime!("1979-05-27T07:32:00Z"), + }, + "table" => table! { + "a" => table! { + "b" => table! { + "c" => 1, + "d" => 2, + }, + }, + "in" => table! { + "type" => table! { + "name" => "cat", + "color" => "blue", + }, + }, + }, + }; + + assert_eq!(toml::Value::Table(actual), expected); +} diff --git a/vendor/toml/tests/testsuite/main.rs b/vendor/toml/tests/testsuite/main.rs new file mode 100644 index 0000000..1473787 --- /dev/null +++ b/vendor/toml/tests/testsuite/main.rs @@ -0,0 +1,15 @@ +#![recursion_limit = "256"] +#![cfg(all(feature = "parse", feature = "display"))] + +mod de_errors; +mod display; +mod display_tricky; +mod enum_external_deserialize; +mod float; +mod formatting; +mod macros; +mod pretty; +mod serde; +mod spanned; +mod spanned_impls; +mod tables_last; diff --git a/vendor/toml/tests/testsuite/pretty.rs b/vendor/toml/tests/testsuite/pretty.rs new file mode 100644 index 0000000..3ae772b --- /dev/null +++ b/vendor/toml/tests/testsuite/pretty.rs @@ -0,0 +1,184 @@ +use serde::ser::Serialize; +use snapbox::assert_eq; + +const NO_PRETTY: &str = "\ +[example] +array = [\"item 1\", \"item 2\"] +empty = [] +oneline = \"this has no newlines.\" +text = ''' + +this is the first line\\nthis is the second line +''' +"; + +#[test] +fn no_pretty() { + let toml = NO_PRETTY; + let value: toml::Value = toml::from_str(toml).unwrap(); + let mut result = String::with_capacity(128); + value.serialize(toml::Serializer::new(&mut result)).unwrap(); + assert_eq(toml, &result); +} + +const PRETTY_STD: &str = "\ +[example] +array = [ + \"item 1\", + \"item 2\", +] +empty = [] +one = [\"one\"] +oneline = \"this has no newlines.\" +text = \"\"\" +this is the first line +this is the second line +\"\"\" +"; + +#[test] +fn pretty_std() { + let toml = PRETTY_STD; + let value: toml::Value = toml::from_str(toml).unwrap(); + let mut result = String::with_capacity(128); + value + .serialize(toml::Serializer::pretty(&mut result)) + .unwrap(); + assert_eq(toml, &result); +} + +const PRETTY_TRICKY: &str = r##"[example] +f = "\f" +glass = """ +Nothing too unusual, except that I can eat glass in: +- Greek: Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα. +- Polish: Mogę jeść szkło, i mi nie szkodzi. +- Hindi: मैं काँच खा सकता हूँ, मुझे उस से कोई पीडा नहीं होती. +- Japanese: 私はガラスを食べられます。それは私を傷つけません。 +""" +r = "\r" +r_newline = """ +\r +""" +single = "this is a single line but has '' cuz it's tricky" +single_tricky = "single line with ''' in it" +tabs = """ +this is pretty standard +\texcept for some \ttabs right here +""" +text = """ +this is the first line. +This has a ''' in it and \"\"\" cuz it's tricky yo +Also ' and \" because why not +this is the fourth line +""" +"##; + +#[test] +fn pretty_tricky() { + let toml = PRETTY_TRICKY; + let value: toml::Value = toml::from_str(toml).unwrap(); + let mut result = String::with_capacity(128); + value + .serialize(toml::Serializer::pretty(&mut result)) + .unwrap(); + assert_eq(toml, &result); +} + +const PRETTY_TABLE_ARRAY: &str = r##"[[array]] +key = "foo" + +[[array]] +key = "bar" + +[abc] +doc = "this is a table" + +[example] +single = "this is a single line string" +"##; + +#[test] +fn pretty_table_array() { + let toml = PRETTY_TABLE_ARRAY; + let value: toml::Value = toml::from_str(toml).unwrap(); + let mut result = String::with_capacity(128); + value + .serialize(toml::Serializer::pretty(&mut result)) + .unwrap(); + assert_eq(toml, &result); +} + +const TABLE_ARRAY: &str = r##"[[array]] +key = "foo" + +[[array]] +key = "bar" + +[abc] +doc = "this is a table" + +[example] +single = "this is a single line string" +"##; + +#[test] +fn table_array() { + let toml = TABLE_ARRAY; + let value: toml::Value = toml::from_str(toml).unwrap(); + let mut result = String::with_capacity(128); + value.serialize(toml::Serializer::new(&mut result)).unwrap(); + assert_eq(toml, &result); +} + +const PRETTY_EMPTY_TABLE: &str = r#"[example] +"#; + +#[test] +fn pretty_empty_table() { + let toml = PRETTY_EMPTY_TABLE; + let value: toml::Value = toml::from_str(toml).unwrap(); + let mut result = String::with_capacity(128); + value.serialize(toml::Serializer::new(&mut result)).unwrap(); + assert_eq(toml, &result); +} + +#[test] +fn error_includes_key() { + #[derive(Debug, serde::Serialize, serde::Deserialize)] + struct Package { + name: String, + version: String, + authors: Vec<String>, + profile: Profile, + } + + #[derive(Debug, serde::Serialize, serde::Deserialize)] + struct Profile { + dev: Dev, + } + + #[derive(Debug, serde::Serialize, serde::Deserialize)] + struct Dev { + debug: U32OrBool, + } + + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, Eq, PartialEq)] + #[serde(untagged, expecting = "expected a boolean or an integer")] + pub enum U32OrBool { + U32(u32), + Bool(bool), + } + + let raw = r#"name = "foo" +version = "0.0.0" +authors = [] + +[profile.dev] +debug = true +"#; + + let pkg: Package = toml::from_str(raw).unwrap(); + let pretty = toml::to_string_pretty(&pkg).unwrap(); + assert_eq(raw, pretty); +} diff --git a/vendor/toml/tests/testsuite/serde.rs b/vendor/toml/tests/testsuite/serde.rs new file mode 100644 index 0000000..13af51d --- /dev/null +++ b/vendor/toml/tests/testsuite/serde.rs @@ -0,0 +1,1222 @@ +use serde::Deserialize; +use serde::Deserializer; +use serde::Serialize; +use std::collections::BTreeMap; + +use toml::map::Map; +use toml::Table; +use toml::Value; + +macro_rules! t { + ($e:expr) => { + match $e { + Ok(t) => t, + Err(e) => panic!("{} failed with {}", stringify!($e), e), + } + }; +} + +macro_rules! equivalent { + ($literal:expr, $toml:expr,) => {{ + let toml = $toml; + let literal = $literal; + + // In/out of Value is equivalent + println!("try_from"); + assert_eq!(t!(Table::try_from(literal.clone())), toml); + println!("try_into"); + assert_eq!(literal, t!(toml.clone().try_into())); + + // Through a string equivalent + println!("to_string"); + snapbox::assert_eq(t!(toml::to_string(&toml)), t!(toml::to_string(&literal))); + println!("literal, from_str(toml)"); + assert_eq!(literal, t!(toml::from_str(&t!(toml::to_string(&toml))))); + println!("toml, from_str(toml)"); + assert_eq!(toml, t!(toml::from_str(&t!(toml::to_string(&toml))))); + }}; +} + +macro_rules! error { + ($ty:ty, $toml:expr, $msg_parse:expr, $msg_decode:expr) => {{ + println!("attempting parsing"); + match toml::from_str::<$ty>(&$toml.to_string()) { + Ok(_) => panic!("successful"), + Err(e) => snapbox::assert_eq($msg_parse, e.to_string()), + } + + println!("attempting toml decoding"); + match $toml.try_into::<$ty>() { + Ok(_) => panic!("successful"), + Err(e) => snapbox::assert_eq($msg_decode, e.to_string()), + } + }}; +} + +macro_rules! map( ($($k:ident: $v:expr),*) => ({ + let mut _m = Map::new(); + $(_m.insert(stringify!($k).to_string(), t!(Value::try_from($v)));)* + _m +}) ); + +#[test] +fn smoke() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: isize, + } + + equivalent!(Foo { a: 2 }, map! { a: Value::Integer(2) },); +} + +#[test] +fn smoke_hyphen() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a_b: isize, + } + + equivalent! { + Foo { a_b: 2 }, + map! { a_b: Value::Integer(2)}, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo2 { + #[serde(rename = "a-b")] + a_b: isize, + } + + let mut m = Map::new(); + m.insert("a-b".to_string(), Value::Integer(2)); + equivalent! { + Foo2 { a_b: 2 }, + m, + } +} + +#[test] +fn nested() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: isize, + b: Bar, + } + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Bar { + a: String, + } + + equivalent! { + Foo { a: 2, b: Bar { a: "test".to_string() } }, + map! { + a: Value::Integer(2), + b: map! { + a: Value::String("test".to_string()) + } + }, + } +} + +#[test] +fn application_decode_error() { + #[derive(PartialEq, Debug)] + struct Range10(usize); + impl<'de> serde::Deserialize<'de> for Range10 { + fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Range10, D::Error> { + let x: usize = serde::Deserialize::deserialize(d)?; + if x > 10 { + Err(serde::de::Error::custom("more than 10")) + } else { + Ok(Range10(x)) + } + } + } + let d_good = Value::Integer(5); + let d_bad1 = Value::String("not an isize".to_string()); + let d_bad2 = Value::Integer(11); + + assert_eq!(Range10(5), d_good.try_into().unwrap()); + + let err1: Result<Range10, _> = d_bad1.try_into(); + assert!(err1.is_err()); + let err2: Result<Range10, _> = d_bad2.try_into(); + assert!(err2.is_err()); +} + +#[test] +fn array() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: Vec<isize>, + } + + equivalent! { + Foo { a: vec![1, 2, 3, 4] }, + map! { + a: Value::Array(vec![ + Value::Integer(1), + Value::Integer(2), + Value::Integer(3), + Value::Integer(4) + ]) + }, + }; +} + +#[test] +fn inner_structs_with_options() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: Option<Box<Foo>>, + b: Bar, + } + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Bar { + a: String, + b: f64, + } + + equivalent! { + Foo { + a: Some(Box::new(Foo { + a: None, + b: Bar { a: "foo".to_string(), b: 4.5 }, + })), + b: Bar { a: "bar".to_string(), b: 1.0 }, + }, + map! { + a: map! { + b: map! { + a: Value::String("foo".to_string()), + b: Value::Float(4.5) + } + }, + b: map! { + a: Value::String("bar".to_string()), + b: Value::Float(1.0) + } + }, + } +} + +#[test] +#[cfg(feature = "preserve_order")] +fn hashmap() { + use std::collections::HashSet; + + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + set: HashSet<char>, + map: BTreeMap<String, isize>, + } + + equivalent! { + Foo { + set: { + let mut s = HashSet::new(); + s.insert('a'); + s + }, + map: { + let mut m = BTreeMap::new(); + m.insert("bar".to_string(), 4); + m.insert("foo".to_string(), 10); + m + } + }, + map! { + set: Value::Array(vec![Value::String("a".to_string())]), + map: map! { + bar: Value::Integer(4), + foo: Value::Integer(10) + } + }, + } +} + +#[test] +fn table_array() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: Vec<Bar>, + } + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Bar { + a: isize, + } + + equivalent! { + Foo { a: vec![Bar { a: 1 }, Bar { a: 2 }] }, + map! { + a: Value::Array(vec![ + Value::Table(map!{ a: Value::Integer(1) }), + Value::Table(map!{ a: Value::Integer(2) }), + ]) + }, + } +} + +#[test] +fn type_errors() { + #[derive(Deserialize)] + #[allow(dead_code)] + struct Foo { + bar: isize, + } + + error! { + Foo, + map! { + bar: Value::String("a".to_string()) + }, + r#"TOML parse error at line 1, column 7 + | +1 | bar = "a" + | ^^^ +invalid type: string "a", expected isize +"#, + "invalid type: string \"a\", expected isize\nin `bar`\n" + } + + #[derive(Deserialize)] + #[allow(dead_code)] + struct Bar { + foo: Foo, + } + + error! { + Bar, + map! { + foo: map! { + bar: Value::String("a".to_string()) + } + }, + r#"TOML parse error at line 2, column 7 + | +2 | bar = "a" + | ^^^ +invalid type: string "a", expected isize +"#, + "invalid type: string \"a\", expected isize\nin `foo.bar`\n" + } +} + +#[test] +fn missing_errors() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Foo { + bar: isize, + } + + error! { + Foo, + map! { }, + r#"TOML parse error at line 1, column 1 + | +1 | + | ^ +missing field `bar` +"#, + "missing field `bar`\n" + } +} + +#[test] +fn parse_enum() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: E, + } + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + #[serde(untagged)] + enum E { + Bar(isize), + Baz(String), + Last(Foo2), + } + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo2 { + test: String, + } + + equivalent! { + Foo { a: E::Bar(10) }, + map! { a: Value::Integer(10) }, + } + + equivalent! { + Foo { a: E::Baz("foo".to_string()) }, + map! { a: Value::String("foo".to_string()) }, + } + + equivalent! { + Foo { a: E::Last(Foo2 { test: "test".to_string() }) }, + map! { a: map! { test: Value::String("test".to_string()) } }, + } +} + +#[test] +fn parse_enum_string() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: Sort, + } + + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + #[serde(rename_all = "lowercase")] + enum Sort { + Asc, + Desc, + } + + equivalent! { + Foo { a: Sort::Desc }, + map! { a: Value::String("desc".to_string()) }, + } +} + +#[test] +#[cfg(feature = "preserve_order")] +fn map_key_unit_variants() { + #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, PartialOrd, Ord)] + enum Sort { + #[serde(rename = "ascending")] + Asc, + Desc, + } + + let mut map = BTreeMap::new(); + map.insert(Sort::Asc, 1); + map.insert(Sort::Desc, 2); + + equivalent! { + map, + map! { ascending: Value::Integer(1), Desc: Value::Integer(2) }, + } +} + +// #[test] +// fn unused_fields() { +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Foo { a: isize } +// +// let v = Foo { a: 2 }; +// let mut d = Decoder::new(Table(map! { +// a, Integer(2), +// b, Integer(5) +// })); +// assert_eq!(v, t!(Deserialize::deserialize(&mut d))); +// +// assert_eq!(d.toml, Some(Table(map! { +// b, Integer(5) +// }))); +// } +// +// #[test] +// fn unused_fields2() { +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Foo { a: Bar } +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Bar { a: isize } +// +// let v = Foo { a: Bar { a: 2 } }; +// let mut d = Decoder::new(Table(map! { +// a, Table(map! { +// a, Integer(2), +// b, Integer(5) +// }) +// })); +// assert_eq!(v, t!(Deserialize::deserialize(&mut d))); +// +// assert_eq!(d.toml, Some(Table(map! { +// a, Table(map! { +// b, Integer(5) +// }) +// }))); +// } +// +// #[test] +// fn unused_fields3() { +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Foo { a: Bar } +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Bar { a: isize } +// +// let v = Foo { a: Bar { a: 2 } }; +// let mut d = Decoder::new(Table(map! { +// a, Table(map! { +// a, Integer(2) +// }) +// })); +// assert_eq!(v, t!(Deserialize::deserialize(&mut d))); +// +// assert_eq!(d.toml, None); +// } +// +// #[test] +// fn unused_fields4() { +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Foo { a: BTreeMap<String, String> } +// +// let v = Foo { a: map! { a, "foo".to_string() } }; +// let mut d = Decoder::new(Table(map! { +// a, Table(map! { +// a, Value::String("foo".to_string()) +// }) +// })); +// assert_eq!(v, t!(Deserialize::deserialize(&mut d))); +// +// assert_eq!(d.toml, None); +// } +// +// #[test] +// fn unused_fields5() { +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Foo { a: Vec<String> } +// +// let v = Foo { a: vec!["a".to_string()] }; +// let mut d = Decoder::new(Table(map! { +// a, Array(vec![Value::String("a".to_string())]) +// })); +// assert_eq!(v, t!(Deserialize::deserialize(&mut d))); +// +// assert_eq!(d.toml, None); +// } +// +// #[test] +// fn unused_fields6() { +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Foo { a: Option<Vec<String>> } +// +// let v = Foo { a: Some(vec![]) }; +// let mut d = Decoder::new(Table(map! { +// a, Array(vec![]) +// })); +// assert_eq!(v, t!(Deserialize::deserialize(&mut d))); +// +// assert_eq!(d.toml, None); +// } +// +// #[test] +// fn unused_fields7() { +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Foo { a: Vec<Bar> } +// #[derive(Serialize, Deserialize, PartialEq, Debug)] +// struct Bar { a: isize } +// +// let v = Foo { a: vec![Bar { a: 1 }] }; +// let mut d = Decoder::new(Table(map! { +// a, Array(vec![Table(map! { +// a, Integer(1), +// b, Integer(2) +// })]) +// })); +// assert_eq!(v, t!(Deserialize::deserialize(&mut d))); +// +// assert_eq!(d.toml, Some(Table(map! { +// a, Array(vec![Table(map! { +// b, Integer(2) +// })]) +// }))); +// } + +#[test] +fn empty_arrays() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: Vec<Bar>, + } + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Bar; + + equivalent! { + Foo { a: vec![] }, + map! {a: Value::Array(Vec::new())}, + } +} + +#[test] +fn empty_arrays2() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a: Option<Vec<Bar>>, + } + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Bar; + + equivalent! { + Foo { a: None }, + map! {}, + } + + equivalent! { + Foo { a: Some(vec![]) }, + map! { a: Value::Array(vec![]) }, + } +} + +#[test] +fn extra_keys() { + #[derive(Serialize, Deserialize)] + struct Foo { + a: isize, + } + + let toml = map! { a: Value::Integer(2), b: Value::Integer(2) }; + assert!(toml.clone().try_into::<Foo>().is_ok()); + assert!(toml::from_str::<Foo>(&toml.to_string()).is_ok()); +} + +#[test] +fn newtypes() { + #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)] + struct A { + b: B, + } + + #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)] + struct B(u32); + + equivalent! { + A { b: B(2) }, + map! { b: Value::Integer(2) }, + } +} + +#[test] +fn newtypes2() { + #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)] + struct A { + b: B, + } + + #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)] + struct B(Option<C>); + + #[derive(Deserialize, Serialize, PartialEq, Debug, Clone)] + struct C { + x: u32, + y: u32, + z: u32, + } + + equivalent! { + A { b: B(Some(C { x: 0, y: 1, z: 2 })) }, + map! { + b: map! { + x: Value::Integer(0), + y: Value::Integer(1), + z: Value::Integer(2) + } + }, + } +} + +#[test] +fn newtype_variant() { + #[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] + struct Struct { + field: Enum, + } + + #[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] + enum Enum { + Variant(u8), + } + + equivalent! { + Struct { field: Enum::Variant(21) }, + map! { + field: map! { + Variant: Value::Integer(21) + } + }, + } +} + +#[derive(Debug, Default, PartialEq, Serialize, Deserialize)] +struct CanBeEmpty { + a: Option<String>, + b: Option<String>, +} + +#[test] +fn table_structs_empty() { + let text = "[bar]\n\n[baz]\n\n[bazv]\na = \"foo\"\n\n[foo]\n"; + let value: BTreeMap<String, CanBeEmpty> = toml::from_str(text).unwrap(); + let mut expected: BTreeMap<String, CanBeEmpty> = BTreeMap::new(); + expected.insert("bar".to_string(), CanBeEmpty::default()); + expected.insert("baz".to_string(), CanBeEmpty::default()); + expected.insert( + "bazv".to_string(), + CanBeEmpty { + a: Some("foo".to_string()), + b: None, + }, + ); + expected.insert("foo".to_string(), CanBeEmpty::default()); + assert_eq!(value, expected); + snapbox::assert_eq(text, toml::to_string(&value).unwrap()); +} + +#[test] +fn fixed_size_array() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Entity { + pos: [i32; 2], + } + + equivalent! { + Entity { pos: [1, 2] }, + map! { + pos: Value::Array(vec![ + Value::Integer(1), + Value::Integer(2), + ]) + }, + } +} + +#[test] +fn homogeneous_tuple() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Collection { + elems: (i64, i64, i64), + } + + equivalent! { + Collection { elems: (0, 1, 2) }, + map! { + elems: Value::Array(vec![ + Value::Integer(0), + Value::Integer(1), + Value::Integer(2), + ]) + }, + } +} + +#[test] +fn homogeneous_tuple_struct() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Object(Vec<String>, Vec<String>, Vec<String>); + + equivalent! { + map! { + obj: Object(vec!["foo".to_string()], vec![], vec!["bar".to_string(), "baz".to_string()]) + }, + map! { + obj: Value::Array(vec![ + Value::Array(vec![ + Value::String("foo".to_string()), + ]), + Value::Array(vec![]), + Value::Array(vec![ + Value::String("bar".to_string()), + Value::String("baz".to_string()), + ]), + ]) + }, + } +} + +#[test] +fn json_interoperability() { + #[derive(Serialize, Deserialize)] + struct Foo { + any: toml::Value, + } + + let _foo: Foo = serde_json::from_str( + r#" + {"any":1} + "#, + ) + .unwrap(); +} + +#[test] +fn error_includes_key() { + #[derive(Debug, Serialize, Deserialize)] + struct Package { + name: String, + version: String, + authors: Vec<String>, + profile: Profile, + } + + #[derive(Debug, Serialize, Deserialize)] + struct Profile { + dev: Dev, + } + + #[derive(Debug, Serialize, Deserialize)] + struct Dev { + debug: U32OrBool, + } + + #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] + #[serde(untagged, expecting = "expected a boolean or an integer")] + pub enum U32OrBool { + U32(u32), + Bool(bool), + } + + let res: Result<Package, _> = toml::from_str( + r#" +[package] +name = "foo" +version = "0.0.0" +authors = [] + +[profile.dev] +debug = 'a' +"#, + ); + let err = res.unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 8, column 9 + | +8 | debug = 'a' + | ^^^ +expected a boolean or an integer +"#, + err.to_string(), + ); + + let res: Result<Package, _> = toml::from_str( + r#" +[package] +name = "foo" +version = "0.0.0" +authors = [] + +[profile] +dev = { debug = 'a' } +"#, + ); + let err = res.unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 8, column 17 + | +8 | dev = { debug = 'a' } + | ^^^ +expected a boolean or an integer +"#, + err.to_string(), + ); +} + +#[test] +fn newline_key_value() { + #[derive(Debug, Serialize, Deserialize)] + struct Package { + name: String, + } + + let package = Package { + name: "foo".to_owned(), + }; + let raw = toml::to_string_pretty(&package).unwrap(); + snapbox::assert_eq( + r#"name = "foo" +"#, + raw, + ); +} + +#[test] +fn newline_table() { + #[derive(Debug, Serialize, Deserialize)] + struct Manifest { + package: Package, + } + + #[derive(Debug, Serialize, Deserialize)] + struct Package { + name: String, + } + + let package = Manifest { + package: Package { + name: "foo".to_owned(), + }, + }; + let raw = toml::to_string_pretty(&package).unwrap(); + snapbox::assert_eq( + r#"[package] +name = "foo" +"#, + raw, + ); +} + +#[test] +fn newline_dotted_table() { + #[derive(Debug, Serialize, Deserialize)] + struct Manifest { + profile: Profile, + } + + #[derive(Debug, Serialize, Deserialize)] + struct Profile { + dev: Dev, + } + + #[derive(Debug, Serialize, Deserialize)] + struct Dev { + debug: U32OrBool, + } + + #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] + #[serde(untagged, expecting = "expected a boolean or an integer")] + pub enum U32OrBool { + U32(u32), + Bool(bool), + } + + let package = Manifest { + profile: Profile { + dev: Dev { + debug: U32OrBool::Bool(true), + }, + }, + }; + let raw = toml::to_string_pretty(&package).unwrap(); + snapbox::assert_eq( + r#"[profile.dev] +debug = true +"#, + raw, + ); +} + +#[test] +fn newline_mixed_tables() { + #[derive(Debug, Serialize, Deserialize)] + struct Manifest { + cargo_features: Vec<String>, + package: Package, + profile: Profile, + } + + #[derive(Debug, Serialize, Deserialize)] + struct Package { + name: String, + version: String, + authors: Vec<String>, + } + + #[derive(Debug, Serialize, Deserialize)] + struct Profile { + dev: Dev, + } + + #[derive(Debug, Serialize, Deserialize)] + struct Dev { + debug: U32OrBool, + } + + #[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] + #[serde(untagged, expecting = "expected a boolean or an integer")] + pub enum U32OrBool { + U32(u32), + Bool(bool), + } + + let package = Manifest { + cargo_features: vec![], + package: Package { + name: "foo".to_owned(), + version: "1.0.0".to_owned(), + authors: vec![], + }, + profile: Profile { + dev: Dev { + debug: U32OrBool::Bool(true), + }, + }, + }; + let raw = toml::to_string_pretty(&package).unwrap(); + snapbox::assert_eq( + r#"cargo_features = [] + +[package] +name = "foo" +version = "1.0.0" +authors = [] + +[profile.dev] +debug = true +"#, + raw, + ); +} + +#[test] +fn integer_min() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a_b: i64, + } + + equivalent! { + Foo { a_b: i64::MIN }, + map! { a_b: Value::Integer(i64::MIN) }, + } +} + +#[test] +fn integer_too_big() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a_b: u64, + } + + let native = Foo { a_b: u64::MAX }; + let err = Table::try_from(native.clone()).unwrap_err(); + snapbox::assert_eq("u64 value was too large", err.to_string()); + let err = toml::to_string(&native).unwrap_err(); + snapbox::assert_eq("out-of-range value for u64 type", err.to_string()); +} + +#[test] +fn integer_max() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a_b: i64, + } + + equivalent! { + Foo { a_b: i64::MAX }, + map! { a_b: Value::Integer(i64::MAX) }, + } +} + +#[test] +fn float_min() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a_b: f64, + } + + equivalent! { + Foo { a_b: f64::MIN }, + map! { a_b: Value::Float(f64::MIN) }, + } +} + +#[test] +fn float_max() { + #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] + struct Foo { + a_b: f64, + } + + equivalent! { + Foo { a_b: f64::MAX }, + map! { a_b: Value::Float(f64::MAX) }, + } +} + +#[test] +fn unsupported_root_type() { + let native = "value"; + let err = toml::to_string_pretty(&native).unwrap_err(); + snapbox::assert_eq("unsupported rust type", err.to_string()); +} + +#[test] +fn unsupported_nested_type() { + #[derive(Debug, Serialize, Deserialize)] + struct Foo { + unused: (), + } + + let native = Foo { unused: () }; + let err = toml::to_string_pretty(&native).unwrap_err(); + snapbox::assert_eq("unsupported unit type", err.to_string()); +} + +#[test] +fn table_type_enum_regression_issue_388() { + #[derive(Deserialize)] + struct DataFile { + #[allow(dead_code)] + data: Compare, + } + + #[derive(Deserialize)] + enum Compare { + Gt(u32), + } + + let dotted_table = r#" + data.Gt = 5 + "#; + assert!(toml::from_str::<DataFile>(dotted_table).is_ok()); + + let inline_table = r#" + data = { Gt = 5 } + "#; + assert!(toml::from_str::<DataFile>(inline_table).is_ok()); +} + +#[test] +fn serialize_datetime_issue_333() { + use toml::{to_string, value::Date, value::Datetime}; + + #[derive(Serialize)] + struct Struct { + date: Datetime, + } + + let toml = to_string(&Struct { + date: Datetime { + date: Some(Date { + year: 2022, + month: 1, + day: 1, + }), + time: None, + offset: None, + }, + }) + .unwrap(); + assert_eq!(toml, "date = 2022-01-01\n"); +} + +#[test] +fn datetime_offset_issue_496() { + let original = "value = 1911-01-01T10:11:12-00:36\n"; + let toml = original.parse::<toml::Table>().unwrap(); + let output = toml.to_string(); + snapbox::assert_eq(original, output); +} + +#[test] +fn serialize_array_with_none_value() { + #[derive(Serialize)] + struct Document { + values: Vec<Option<usize>>, + } + + let input = Document { + values: vec![Some(1), Some(2), Some(3)], + }; + let expected = "values = [1, 2, 3]\n"; + let raw = toml::to_string(&input).unwrap(); + snapbox::assert_eq(expected, raw); + + let input = Document { + values: vec![Some(1), None, Some(3)], + }; + let err = toml::to_string(&input).unwrap_err(); + snapbox::assert_eq("unsupported None value", err.to_string()); +} + +#[test] +fn serialize_array_with_optional_struct_field() { + #[derive(Debug, Deserialize, Serialize)] + struct Document { + values: Vec<OptionalField>, + } + + #[derive(Debug, Deserialize, Serialize)] + struct OptionalField { + x: u8, + y: Option<u8>, + } + + let input = Document { + values: vec![ + OptionalField { x: 0, y: Some(4) }, + OptionalField { x: 2, y: Some(5) }, + OptionalField { x: 3, y: Some(7) }, + ], + }; + let expected = "\ +[[values]] +x = 0 +y = 4 + +[[values]] +x = 2 +y = 5 + +[[values]] +x = 3 +y = 7 +"; + let raw = toml::to_string(&input).unwrap(); + snapbox::assert_eq(expected, raw); + + let input = Document { + values: vec![ + OptionalField { x: 0, y: Some(4) }, + OptionalField { x: 2, y: None }, + OptionalField { x: 3, y: Some(7) }, + ], + }; + let expected = "\ +[[values]] +x = 0 +y = 4 + +[[values]] +x = 2 + +[[values]] +x = 3 +y = 7 +"; + let raw = toml::to_string(&input).unwrap(); + snapbox::assert_eq(expected, raw); +} + +#[test] +fn serialize_array_with_enum_of_optional_struct_field() { + #[derive(Debug, Deserialize, Serialize)] + struct Document { + values: Vec<Choice>, + } + + #[derive(Debug, Deserialize, Serialize)] + enum Choice { + Optional(OptionalField), + Empty, + } + + #[derive(Debug, Deserialize, Serialize)] + struct OptionalField { + x: u8, + y: Option<u8>, + } + + let input = Document { + values: vec![ + Choice::Optional(OptionalField { x: 0, y: Some(4) }), + Choice::Empty, + Choice::Optional(OptionalField { x: 2, y: Some(5) }), + Choice::Optional(OptionalField { x: 3, y: Some(7) }), + ], + }; + let expected = "values = [{ Optional = { x = 0, y = 4 } }, \"Empty\", { Optional = { x = 2, y = 5 } }, { Optional = { x = 3, y = 7 } }] +"; + let raw = toml::to_string(&input).unwrap(); + snapbox::assert_eq(expected, raw); + + let input = Document { + values: vec![ + Choice::Optional(OptionalField { x: 0, y: Some(4) }), + Choice::Empty, + Choice::Optional(OptionalField { x: 2, y: None }), + Choice::Optional(OptionalField { x: 3, y: Some(7) }), + ], + }; + let expected = "values = [{ Optional = { x = 0, y = 4 } }, \"Empty\", { Optional = { x = 2 } }, { Optional = { x = 3, y = 7 } }] +"; + let raw = toml::to_string(&input).unwrap(); + snapbox::assert_eq(expected, raw); +} diff --git a/vendor/toml/tests/testsuite/spanned.rs b/vendor/toml/tests/testsuite/spanned.rs new file mode 100644 index 0000000..760c73a --- /dev/null +++ b/vendor/toml/tests/testsuite/spanned.rs @@ -0,0 +1,261 @@ +#![allow(renamed_and_removed_lints)] +#![allow(clippy::blacklisted_name)] + +use std::collections::HashMap; +use std::fmt::Debug; + +use serde::Deserialize; +use toml::value::Datetime; +use toml::Spanned; + +/// A set of good datetimes. +pub fn good_datetimes() -> Vec<&'static str> { + vec![ + "1997-09-09T09:09:09Z", + "1997-09-09T09:09:09+09:09", + "1997-09-09T09:09:09-09:09", + "1997-09-09T09:09:09", + "1997-09-09", + "09:09:09", + "1997-09-09T09:09:09.09Z", + "1997-09-09T09:09:09.09+09:09", + "1997-09-09T09:09:09.09-09:09", + "1997-09-09T09:09:09.09", + "09:09:09.09", + ] +} + +#[test] +fn test_spanned_field() { + #[derive(Deserialize)] + struct Foo<T> { + foo: Spanned<T>, + } + + #[derive(Deserialize)] + struct BareFoo<T> { + foo: T, + } + + fn good<T>(s: &str, expected: &str, end: Option<usize>) + where + T: serde::de::DeserializeOwned + Debug + PartialEq, + { + let foo: Foo<T> = toml::from_str(s).unwrap(); + + assert_eq!(6, foo.foo.span().start); + if let Some(end) = end { + assert_eq!(end, foo.foo.span().end); + } else { + assert_eq!(s.len(), foo.foo.span().end); + } + assert_eq!(expected, &s[foo.foo.span()]); + + // Test for Spanned<> at the top level + let foo_outer: Spanned<BareFoo<T>> = toml::from_str(s).unwrap(); + + assert_eq!(0, foo_outer.span().start); + assert_eq!(s.len(), foo_outer.span().end); + assert_eq!(foo.foo.into_inner(), foo_outer.into_inner().foo); + } + + good::<String>("foo = \"foo\"", "\"foo\"", None); + good::<u32>("foo = 42", "42", None); + // leading plus + good::<u32>("foo = +42", "+42", None); + // table + good::<HashMap<String, u32>>( + "foo = {\"foo\" = 42, \"bar\" = 42}", + "{\"foo\" = 42, \"bar\" = 42}", + None, + ); + // array + good::<Vec<u32>>("foo = [0, 1, 2, 3, 4]", "[0, 1, 2, 3, 4]", None); + // datetime + good::<String>( + "foo = \"1997-09-09T09:09:09Z\"", + "\"1997-09-09T09:09:09Z\"", + None, + ); + + for expected in good_datetimes() { + let s = format!("foo = {}", expected); + good::<Datetime>(&s, expected, None); + } + // ending at something other than the absolute end + good::<u32>("foo = 42\nnoise = true", "42", Some(8)); +} + +#[test] +fn test_inner_spanned_table() { + #[derive(Deserialize)] + struct Foo { + foo: Spanned<HashMap<Spanned<String>, Spanned<String>>>, + } + + fn good(s: &str, zero: bool) { + let foo: Foo = toml::from_str(s).unwrap(); + + if zero { + assert_eq!(foo.foo.span().start, 0); + assert_eq!(foo.foo.span().end, 73); + } else { + assert_eq!(foo.foo.span().start, s.find('{').unwrap()); + assert_eq!(foo.foo.span().end, s.find('}').unwrap() + 1); + } + for (k, v) in foo.foo.as_ref().iter() { + assert_eq!(&s[k.span().start..k.span().end], k.as_ref()); + assert_eq!(&s[(v.span().start + 1)..(v.span().end - 1)], v.as_ref()); + } + } + + good( + "\ + [foo] + a = 'b' + bar = 'baz' + c = 'd' + e = \"f\" + ", + true, + ); + + good( + " + foo = { a = 'b', bar = 'baz', c = 'd', e = \"f\" }", + false, + ); +} + +#[test] +fn test_outer_spanned_table() { + #[derive(Deserialize)] + struct Foo { + foo: HashMap<Spanned<String>, Spanned<String>>, + } + + fn good(s: &str) { + let foo: Foo = toml::from_str(s).unwrap(); + + for (k, v) in foo.foo.iter() { + assert_eq!(&s[k.span().start..k.span().end], k.as_ref()); + assert_eq!(&s[(v.span().start + 1)..(v.span().end - 1)], v.as_ref()); + } + } + + good( + " + [foo] + a = 'b' + bar = 'baz' + c = 'd' + e = \"f\" + ", + ); + + good( + " + foo = { a = 'b', bar = 'baz', c = 'd', e = \"f\" } + ", + ); +} + +#[test] +fn test_spanned_nested() { + #[derive(Deserialize)] + struct Foo { + foo: HashMap<Spanned<String>, HashMap<Spanned<String>, Spanned<String>>>, + } + + fn good(s: &str) { + let foo: Foo = toml::from_str(s).unwrap(); + + for (k, v) in foo.foo.iter() { + assert_eq!(&s[k.span().start..k.span().end], k.as_ref()); + for (n_k, n_v) in v.iter() { + assert_eq!(&s[n_k.span().start..n_k.span().end], n_k.as_ref()); + assert_eq!( + &s[(n_v.span().start + 1)..(n_v.span().end - 1)], + n_v.as_ref() + ); + } + } + } + + good( + " + [foo.a] + a = 'b' + c = 'd' + e = \"f\" + [foo.bar] + baz = 'true' + ", + ); + + good( + " + [foo] + foo = { a = 'b', bar = 'baz', c = 'd', e = \"f\" } + bazz = {} + g = { h = 'i' } + ", + ); +} + +#[test] +fn test_spanned_array() { + #[derive(Deserialize)] + struct Foo { + foo: Vec<Spanned<HashMap<Spanned<String>, Spanned<String>>>>, + } + + let toml = "\ + [[foo]] + a = 'b' + bar = 'baz' + c = 'd' + e = \"f\" + [[foo]] + a = 'c' + bar = 'baz' + c = 'g' + e = \"h\" + "; + let foo_list: Foo = toml::from_str(toml).unwrap(); + + for (foo, expected) in foo_list.foo.iter().zip([0..75, 84..159]) { + assert_eq!(foo.span(), expected); + for (k, v) in foo.as_ref().iter() { + assert_eq!(&toml[k.span().start..k.span().end], k.as_ref()); + assert_eq!(&toml[(v.span().start + 1)..(v.span().end - 1)], v.as_ref()); + } + } +} + +#[test] +fn deny_unknown_fields() { + #[derive(Debug, serde::Deserialize)] + #[serde(deny_unknown_fields)] + struct Example { + #[allow(dead_code)] + real: u32, + } + + let error = toml::from_str::<Example>( + r#"# my comment +# bla bla bla +fake = 1"#, + ) + .unwrap_err(); + snapbox::assert_eq( + "\ +TOML parse error at line 3, column 1 + | +3 | fake = 1 + | ^^^^ +unknown field `fake`, expected `real` +", + error.to_string(), + ); +} diff --git a/vendor/toml/tests/testsuite/spanned_impls.rs b/vendor/toml/tests/testsuite/spanned_impls.rs new file mode 100644 index 0000000..5e866f9 --- /dev/null +++ b/vendor/toml/tests/testsuite/spanned_impls.rs @@ -0,0 +1,41 @@ +use std::cmp::{Ord, Ordering, PartialOrd}; + +use serde::Deserialize; +use toml::{from_str, Spanned}; + +#[test] +fn test_spans_impls() { + #[derive(Deserialize)] + struct Foo { + bar: Spanned<bool>, + baz: Spanned<String>, + } + let f: Foo = from_str( + " + bar = true + baz = \"yes\" + ", + ) + .unwrap(); + let g: Foo = from_str( + " + baz = \"yes\" + bar = true + ", + ) + .unwrap(); + assert!(f.bar.span() != g.bar.span()); + assert!(f.baz.span() != g.baz.span()); + + // test that eq still holds + assert_eq!(f.bar, g.bar); + assert_eq!(f.baz, g.baz); + + // test that Ord returns equal order + assert_eq!(f.bar.cmp(&g.bar), Ordering::Equal); + assert_eq!(f.baz.cmp(&g.baz), Ordering::Equal); + + // test that PartialOrd returns equal order + assert_eq!(f.bar.partial_cmp(&g.bar), Some(Ordering::Equal)); + assert_eq!(f.baz.partial_cmp(&g.baz), Some(Ordering::Equal)); +} diff --git a/vendor/toml/tests/testsuite/tables_last.rs b/vendor/toml/tests/testsuite/tables_last.rs new file mode 100644 index 0000000..b003557 --- /dev/null +++ b/vendor/toml/tests/testsuite/tables_last.rs @@ -0,0 +1,162 @@ +use std::collections::HashMap; + +use serde::Deserialize; +use serde::Serialize; + +#[test] +fn always_works() { + // Ensure this works without the removed "toml::ser::tables_last" + #[derive(Serialize)] + struct A { + vals: HashMap<&'static str, Value>, + } + + #[derive(Serialize)] + #[serde(untagged)] + enum Value { + Map(HashMap<&'static str, &'static str>), + Int(i32), + } + + let mut a = A { + vals: HashMap::new(), + }; + a.vals.insert("foo", Value::Int(0)); + + let mut sub = HashMap::new(); + sub.insert("foo", "bar"); + a.vals.insert("bar", Value::Map(sub)); + + toml::to_string(&a).unwrap(); +} + +#[test] +fn vec_of_vec_issue_387() { + #[derive(Deserialize, Serialize, Debug)] + struct Glyph { + components: Vec<Component>, + contours: Vec<Contour>, + } + + #[derive(Deserialize, Serialize, Debug)] + struct Point { + x: f64, + y: f64, + pt_type: String, + } + + type Contour = Vec<Point>; + + #[derive(Deserialize, Serialize, Debug)] + struct Component { + base: String, + transform: (f64, f64, f64, f64, f64, f64), + } + + let comp1 = Component { + base: "b".to_string(), + transform: (1.0, 0.0, 0.0, 1.0, 0.0, 0.0), + }; + let comp2 = Component { + base: "c".to_string(), + transform: (1.0, 0.0, 0.0, 1.0, 0.0, 0.0), + }; + let components = vec![comp1, comp2]; + + let contours = vec![ + vec![ + Point { + x: 3.0, + y: 4.0, + pt_type: "line".to_string(), + }, + Point { + x: 5.0, + y: 6.0, + pt_type: "line".to_string(), + }, + ], + vec![ + Point { + x: 0.0, + y: 0.0, + pt_type: "move".to_string(), + }, + Point { + x: 7.0, + y: 9.0, + pt_type: "offcurve".to_string(), + }, + Point { + x: 8.0, + y: 10.0, + pt_type: "offcurve".to_string(), + }, + Point { + x: 11.0, + y: 12.0, + pt_type: "curve".to_string(), + }, + ], + ]; + let g1 = Glyph { + contours, + components, + }; + + let s = toml::to_string_pretty(&g1).unwrap(); + let _g2: Glyph = toml::from_str(&s).unwrap(); +} + +#[test] +fn vec_order_issue_356() { + #[derive(Serialize, Deserialize)] + struct Outer { + v1: Vec<Inner>, + v2: Vec<Inner>, + } + + #[derive(Serialize, Deserialize)] + struct Inner {} + + let outer = Outer { + v1: vec![Inner {}], + v2: vec![], + }; + let s = toml::to_string_pretty(&outer).unwrap(); + let _o: Outer = toml::from_str(&s).unwrap(); +} + +#[test] +fn values_before_tables_issue_403() { + #[derive(Serialize, Deserialize)] + struct A { + a: String, + b: String, + } + + #[derive(Serialize, Deserialize)] + struct B { + a: String, + b: Vec<String>, + } + + #[derive(Serialize, Deserialize)] + struct C { + a: A, + b: Vec<String>, + c: Vec<B>, + } + toml::to_string(&C { + a: A { + a: "aa".to_string(), + b: "ab".to_string(), + }, + b: vec!["b".to_string()], + c: vec![B { + a: "cba".to_string(), + b: vec!["cbb".to_string()], + }], + }) + .unwrap(); +} diff --git a/vendor/toml_datetime/.cargo-checksum.json b/vendor/toml_datetime/.cargo-checksum.json new file mode 100644 index 0000000..28b4f4c --- /dev/null +++ b/vendor/toml_datetime/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{},"package":"7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"}
\ No newline at end of file diff --git a/vendor/toml_datetime/Cargo.toml b/vendor/toml_datetime/Cargo.toml new file mode 100644 index 0000000..da89eba --- /dev/null +++ b/vendor/toml_datetime/Cargo.toml @@ -0,0 +1,89 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.64.0" +name = "toml_datetime" +version = "0.6.3" +authors = ["Alex Crichton <alex@alexcrichton.com>"] +include = [ + "build.rs", + "src/**/*", + "Cargo.toml", + "Cargo.lock", + "LICENSE*", + "README.md", + "benches/**/*", + "examples/**/*", + "tests/**/*", +] +description = "A TOML-compatible datetime type" +homepage = "https://github.com/toml-rs/toml" +readme = "README.md" +keywords = [ + "encoding", + "toml", +] +categories = [ + "encoding", + "parser-implementations", + "parsing", + "config", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/toml-rs/toml" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +min = 1 +replace = "{{version}}" +search = "Unreleased" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = "...{{tag_name}}" +search = '\.\.\.HEAD' + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +min = 1 +replace = "{{date}}" +search = "ReleaseDate" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = """ +<!-- next-header --> +## [Unreleased] - ReleaseDate +""" +search = "<!-- next-header -->" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = """ +<!-- next-url --> +[Unreleased]: https://github.com/toml-rs/toml/compare/{{tag_name}}...HEAD""" +search = "<!-- next-url -->" + +[dependencies.serde] +version = "1.0.145" +optional = true diff --git a/vendor/toml_datetime/LICENSE-APACHE b/vendor/toml_datetime/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/vendor/toml_datetime/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/toml_datetime/LICENSE-MIT b/vendor/toml_datetime/LICENSE-MIT new file mode 100644 index 0000000..39e0ed6 --- /dev/null +++ b/vendor/toml_datetime/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 Alex Crichton + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/toml_datetime/README.md b/vendor/toml_datetime/README.md new file mode 100644 index 0000000..67d1da4 --- /dev/null +++ b/vendor/toml_datetime/README.md @@ -0,0 +1,21 @@ +# toml_datetime + +[![Latest Version](https://img.shields.io/crates/v/toml_datetime.svg)](https://crates.io/crates/toml_datetime) +[![Documentation](https://docs.rs/toml_datetime/badge.svg)](https://docs.rs/toml_datetime) + +# License + +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in toml-rs by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/vendor/toml_datetime/src/datetime.rs b/vendor/toml_datetime/src/datetime.rs new file mode 100644 index 0000000..15781b9 --- /dev/null +++ b/vendor/toml_datetime/src/datetime.rs @@ -0,0 +1,583 @@ +use std::error; +use std::fmt; +use std::str::{self, FromStr}; + +#[cfg(feature = "serde")] +use serde::{de, ser}; + +/// A parsed TOML datetime value +/// +/// This structure is intended to represent the datetime primitive type that can +/// be encoded into TOML documents. This type is a parsed version that contains +/// all metadata internally. +/// +/// Currently this type is intentionally conservative and only supports +/// `to_string` as an accessor. Over time though it's intended that it'll grow +/// more support! +/// +/// Note that if you're using `Deserialize` to deserialize a TOML document, you +/// can use this as a placeholder for where you're expecting a datetime to be +/// specified. +/// +/// Also note though that while this type implements `Serialize` and +/// `Deserialize` it's only recommended to use this type with the TOML format, +/// otherwise encoded in other formats it may look a little odd. +/// +/// Depending on how the option values are used, this struct will correspond +/// with one of the following four datetimes from the [TOML v1.0.0 spec]: +/// +/// | `date` | `time` | `offset` | TOML type | +/// | --------- | --------- | --------- | ------------------ | +/// | `Some(_)` | `Some(_)` | `Some(_)` | [Offset Date-Time] | +/// | `Some(_)` | `Some(_)` | `None` | [Local Date-Time] | +/// | `Some(_)` | `None` | `None` | [Local Date] | +/// | `None` | `Some(_)` | `None` | [Local Time] | +/// +/// **1. Offset Date-Time**: If all the optional values are used, `Datetime` +/// corresponds to an [Offset Date-Time]. From the TOML v1.0.0 spec: +/// +/// > To unambiguously represent a specific instant in time, you may use an +/// > RFC 3339 formatted date-time with offset. +/// > +/// > ```toml +/// > odt1 = 1979-05-27T07:32:00Z +/// > odt2 = 1979-05-27T00:32:00-07:00 +/// > odt3 = 1979-05-27T00:32:00.999999-07:00 +/// > ``` +/// > +/// > For the sake of readability, you may replace the T delimiter between date +/// > and time with a space character (as permitted by RFC 3339 section 5.6). +/// > +/// > ```toml +/// > odt4 = 1979-05-27 07:32:00Z +/// > ``` +/// +/// **2. Local Date-Time**: If `date` and `time` are given but `offset` is +/// `None`, `Datetime` corresponds to a [Local Date-Time]. From the spec: +/// +/// > If you omit the offset from an RFC 3339 formatted date-time, it will +/// > represent the given date-time without any relation to an offset or +/// > timezone. It cannot be converted to an instant in time without additional +/// > information. Conversion to an instant, if required, is implementation- +/// > specific. +/// > +/// > ```toml +/// > ldt1 = 1979-05-27T07:32:00 +/// > ldt2 = 1979-05-27T00:32:00.999999 +/// > ``` +/// +/// **3. Local Date**: If only `date` is given, `Datetime` corresponds to a +/// [Local Date]; see the docs for [`Date`]. +/// +/// **4. Local Time**: If only `time` is given, `Datetime` corresponds to a +/// [Local Time]; see the docs for [`Time`]. +/// +/// [TOML v1.0.0 spec]: https://toml.io/en/v1.0.0 +/// [Offset Date-Time]: https://toml.io/en/v1.0.0#offset-date-time +/// [Local Date-Time]: https://toml.io/en/v1.0.0#local-date-time +/// [Local Date]: https://toml.io/en/v1.0.0#local-date +/// [Local Time]: https://toml.io/en/v1.0.0#local-time +#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] +pub struct Datetime { + /// Optional date. + /// Required for: *Offset Date-Time*, *Local Date-Time*, *Local Date*. + pub date: Option<Date>, + + /// Optional time. + /// Required for: *Offset Date-Time*, *Local Date-Time*, *Local Time*. + pub time: Option<Time>, + + /// Optional offset. + /// Required for: *Offset Date-Time*. + pub offset: Option<Offset>, +} + +/// Error returned from parsing a `Datetime` in the `FromStr` implementation. +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct DatetimeParseError {} + +// Currently serde itself doesn't have a datetime type, so we map our `Datetime` +// to a special value in the serde data model. Namely one with these special +// fields/struct names. +// +// In general the TOML encoder/decoder will catch this and not literally emit +// these strings but rather emit datetimes as they're intended. +#[doc(hidden)] +#[cfg(feature = "serde")] +pub const FIELD: &str = "$__toml_private_datetime"; +#[doc(hidden)] +#[cfg(feature = "serde")] +pub const NAME: &str = "$__toml_private_Datetime"; + +/// A parsed TOML date value +/// +/// May be part of a [`Datetime`]. Alone, `Date` corresponds to a [Local Date]. +/// From the TOML v1.0.0 spec: +/// +/// > If you include only the date portion of an RFC 3339 formatted date-time, +/// > it will represent that entire day without any relation to an offset or +/// > timezone. +/// > +/// > ```toml +/// > ld1 = 1979-05-27 +/// > ``` +/// +/// [Local Date]: https://toml.io/en/v1.0.0#local-date +#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] +pub struct Date { + /// Year: four digits + pub year: u16, + /// Month: 1 to 12 + pub month: u8, + /// Day: 1 to {28, 29, 30, 31} (based on month/year) + pub day: u8, +} + +/// A parsed TOML time value +/// +/// May be part of a [`Datetime`]. Alone, `Time` corresponds to a [Local Time]. +/// From the TOML v1.0.0 spec: +/// +/// > If you include only the time portion of an RFC 3339 formatted date-time, +/// > it will represent that time of day without any relation to a specific +/// > day or any offset or timezone. +/// > +/// > ```toml +/// > lt1 = 07:32:00 +/// > lt2 = 00:32:00.999999 +/// > ``` +/// > +/// > Millisecond precision is required. Further precision of fractional +/// > seconds is implementation-specific. If the value contains greater +/// > precision than the implementation can support, the additional precision +/// > must be truncated, not rounded. +/// +/// [Local Time]: https://toml.io/en/v1.0.0#local-time +#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] +pub struct Time { + /// Hour: 0 to 23 + pub hour: u8, + /// Minute: 0 to 59 + pub minute: u8, + /// Second: 0 to {58, 59, 60} (based on leap second rules) + pub second: u8, + /// Nanosecond: 0 to 999_999_999 + pub nanosecond: u32, +} + +/// A parsed TOML time offset +/// +#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] +pub enum Offset { + /// > A suffix which, when applied to a time, denotes a UTC offset of 00:00; + /// > often spoken "Zulu" from the ICAO phonetic alphabet representation of + /// > the letter "Z". --- [RFC 3339 section 2] + /// + /// [RFC 3339 section 2]: https://datatracker.ietf.org/doc/html/rfc3339#section-2 + Z, + + /// Offset between local time and UTC + Custom { + /// Minutes: -1_440..1_440 + minutes: i16, + }, +} + +impl From<Date> for Datetime { + fn from(other: Date) -> Self { + Datetime { + date: Some(other), + time: None, + offset: None, + } + } +} + +impl From<Time> for Datetime { + fn from(other: Time) -> Self { + Datetime { + date: None, + time: Some(other), + offset: None, + } + } +} + +impl fmt::Display for Datetime { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(ref date) = self.date { + write!(f, "{}", date)?; + } + if let Some(ref time) = self.time { + if self.date.is_some() { + write!(f, "T")?; + } + write!(f, "{}", time)?; + } + if let Some(ref offset) = self.offset { + write!(f, "{}", offset)?; + } + Ok(()) + } +} + +impl fmt::Display for Date { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:04}-{:02}-{:02}", self.year, self.month, self.day) + } +} + +impl fmt::Display for Time { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:02}:{:02}:{:02}", self.hour, self.minute, self.second)?; + if self.nanosecond != 0 { + let s = format!("{:09}", self.nanosecond); + write!(f, ".{}", s.trim_end_matches('0'))?; + } + Ok(()) + } +} + +impl fmt::Display for Offset { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Offset::Z => write!(f, "Z"), + Offset::Custom { mut minutes } => { + let mut sign = '+'; + if minutes < 0 { + minutes *= -1; + sign = '-'; + } + let hours = minutes / 60; + let minutes = minutes % 60; + write!(f, "{}{:02}:{:02}", sign, hours, minutes) + } + } + } +} + +impl FromStr for Datetime { + type Err = DatetimeParseError; + + fn from_str(date: &str) -> Result<Datetime, DatetimeParseError> { + // Accepted formats: + // + // 0000-00-00T00:00:00.00Z + // 0000-00-00T00:00:00.00 + // 0000-00-00 + // 00:00:00.00 + if date.len() < 3 { + return Err(DatetimeParseError {}); + } + let mut offset_allowed = true; + let mut chars = date.chars(); + + // First up, parse the full date if we can + let full_date = if chars.clone().nth(2) == Some(':') { + offset_allowed = false; + None + } else { + let y1 = u16::from(digit(&mut chars)?); + let y2 = u16::from(digit(&mut chars)?); + let y3 = u16::from(digit(&mut chars)?); + let y4 = u16::from(digit(&mut chars)?); + + match chars.next() { + Some('-') => {} + _ => return Err(DatetimeParseError {}), + } + + let m1 = digit(&mut chars)?; + let m2 = digit(&mut chars)?; + + match chars.next() { + Some('-') => {} + _ => return Err(DatetimeParseError {}), + } + + let d1 = digit(&mut chars)?; + let d2 = digit(&mut chars)?; + + let date = Date { + year: y1 * 1000 + y2 * 100 + y3 * 10 + y4, + month: m1 * 10 + m2, + day: d1 * 10 + d2, + }; + + if date.month < 1 || date.month > 12 { + return Err(DatetimeParseError {}); + } + if date.day < 1 || date.day > 31 { + return Err(DatetimeParseError {}); + } + + Some(date) + }; + + // Next parse the "partial-time" if available + let next = chars.clone().next(); + let partial_time = if full_date.is_some() + && (next == Some('T') || next == Some('t') || next == Some(' ')) + { + chars.next(); + true + } else { + full_date.is_none() + }; + + let time = if partial_time { + let h1 = digit(&mut chars)?; + let h2 = digit(&mut chars)?; + match chars.next() { + Some(':') => {} + _ => return Err(DatetimeParseError {}), + } + let m1 = digit(&mut chars)?; + let m2 = digit(&mut chars)?; + match chars.next() { + Some(':') => {} + _ => return Err(DatetimeParseError {}), + } + let s1 = digit(&mut chars)?; + let s2 = digit(&mut chars)?; + + let mut nanosecond = 0; + if chars.clone().next() == Some('.') { + chars.next(); + let whole = chars.as_str(); + + let mut end = whole.len(); + for (i, byte) in whole.bytes().enumerate() { + match byte { + b'0'..=b'9' => { + if i < 9 { + let p = 10_u32.pow(8 - i as u32); + nanosecond += p * u32::from(byte - b'0'); + } + } + _ => { + end = i; + break; + } + } + } + if end == 0 { + return Err(DatetimeParseError {}); + } + chars = whole[end..].chars(); + } + + let time = Time { + hour: h1 * 10 + h2, + minute: m1 * 10 + m2, + second: s1 * 10 + s2, + nanosecond, + }; + + if time.hour > 24 { + return Err(DatetimeParseError {}); + } + if time.minute > 59 { + return Err(DatetimeParseError {}); + } + if time.second > 59 { + return Err(DatetimeParseError {}); + } + if time.nanosecond > 999_999_999 { + return Err(DatetimeParseError {}); + } + + Some(time) + } else { + offset_allowed = false; + None + }; + + // And finally, parse the offset + let offset = if offset_allowed { + let next = chars.clone().next(); + if next == Some('Z') || next == Some('z') { + chars.next(); + Some(Offset::Z) + } else if next.is_none() { + None + } else { + let sign = match next { + Some('+') => 1, + Some('-') => -1, + _ => return Err(DatetimeParseError {}), + }; + chars.next(); + let h1 = digit(&mut chars)? as i16; + let h2 = digit(&mut chars)? as i16; + match chars.next() { + Some(':') => {} + _ => return Err(DatetimeParseError {}), + } + let m1 = digit(&mut chars)? as i16; + let m2 = digit(&mut chars)? as i16; + + let hours = h1 * 10 + h2; + let minutes = m1 * 10 + m2; + + let total_minutes = sign * (hours * 60 + minutes); + + if !((-24 * 60)..=(24 * 60)).contains(&total_minutes) { + return Err(DatetimeParseError {}); + } + + Some(Offset::Custom { + minutes: total_minutes, + }) + } + } else { + None + }; + + // Return an error if we didn't hit eof, otherwise return our parsed + // date + if chars.next().is_some() { + return Err(DatetimeParseError {}); + } + + Ok(Datetime { + date: full_date, + time, + offset, + }) + } +} + +fn digit(chars: &mut str::Chars<'_>) -> Result<u8, DatetimeParseError> { + match chars.next() { + Some(c) if ('0'..='9').contains(&c) => Ok(c as u8 - b'0'), + _ => Err(DatetimeParseError {}), + } +} + +#[cfg(feature = "serde")] +impl ser::Serialize for Datetime { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + use serde::ser::SerializeStruct; + + let mut s = serializer.serialize_struct(NAME, 1)?; + s.serialize_field(FIELD, &self.to_string())?; + s.end() + } +} + +#[cfg(feature = "serde")] +impl<'de> de::Deserialize<'de> for Datetime { + fn deserialize<D>(deserializer: D) -> Result<Datetime, D::Error> + where + D: de::Deserializer<'de>, + { + struct DatetimeVisitor; + + impl<'de> de::Visitor<'de> for DatetimeVisitor { + type Value = Datetime; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a TOML datetime") + } + + fn visit_map<V>(self, mut visitor: V) -> Result<Datetime, V::Error> + where + V: de::MapAccess<'de>, + { + let value = visitor.next_key::<DatetimeKey>()?; + if value.is_none() { + return Err(de::Error::custom("datetime key not found")); + } + let v: DatetimeFromString = visitor.next_value()?; + Ok(v.value) + } + } + + static FIELDS: [&str; 1] = [FIELD]; + deserializer.deserialize_struct(NAME, &FIELDS, DatetimeVisitor) + } +} + +#[cfg(feature = "serde")] +struct DatetimeKey; + +#[cfg(feature = "serde")] +impl<'de> de::Deserialize<'de> for DatetimeKey { + fn deserialize<D>(deserializer: D) -> Result<DatetimeKey, D::Error> + where + D: de::Deserializer<'de>, + { + struct FieldVisitor; + + impl<'de> de::Visitor<'de> for FieldVisitor { + type Value = (); + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a valid datetime field") + } + + fn visit_str<E>(self, s: &str) -> Result<(), E> + where + E: de::Error, + { + if s == FIELD { + Ok(()) + } else { + Err(de::Error::custom("expected field with custom name")) + } + } + } + + deserializer.deserialize_identifier(FieldVisitor)?; + Ok(DatetimeKey) + } +} + +#[doc(hidden)] +#[cfg(feature = "serde")] +pub struct DatetimeFromString { + pub value: Datetime, +} + +#[cfg(feature = "serde")] +impl<'de> de::Deserialize<'de> for DatetimeFromString { + fn deserialize<D>(deserializer: D) -> Result<DatetimeFromString, D::Error> + where + D: de::Deserializer<'de>, + { + struct Visitor; + + impl<'de> de::Visitor<'de> for Visitor { + type Value = DatetimeFromString; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("string containing a datetime") + } + + fn visit_str<E>(self, s: &str) -> Result<DatetimeFromString, E> + where + E: de::Error, + { + match s.parse() { + Ok(date) => Ok(DatetimeFromString { value: date }), + Err(e) => Err(de::Error::custom(e)), + } + } + } + + deserializer.deserialize_str(Visitor) + } +} + +impl fmt::Display for DatetimeParseError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + "failed to parse datetime".fmt(f) + } +} + +impl error::Error for DatetimeParseError {} diff --git a/vendor/toml_datetime/src/lib.rs b/vendor/toml_datetime/src/lib.rs new file mode 100644 index 0000000..4df40dc --- /dev/null +++ b/vendor/toml_datetime/src/lib.rs @@ -0,0 +1,28 @@ +//! A [TOML]-compatible datetime type +//! +//! [TOML]: https://github.com/toml-lang/toml + +#![deny(missing_docs)] +#![warn(rust_2018_idioms)] +// Makes rustc abort compilation if there are any unsafe blocks in the crate. +// Presence of this annotation is picked up by tools such as cargo-geiger +// and lets them ensure that there is indeed no unsafe code as opposed to +// something they couldn't detect (e.g. unsafe added via macro expansion, etc). +#![forbid(unsafe_code)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +mod datetime; + +pub use crate::datetime::Date; +pub use crate::datetime::Datetime; +pub use crate::datetime::DatetimeParseError; +pub use crate::datetime::Offset; +pub use crate::datetime::Time; + +#[doc(hidden)] +#[cfg(feature = "serde")] +pub mod __unstable { + pub use crate::datetime::DatetimeFromString; + pub use crate::datetime::FIELD; + pub use crate::datetime::NAME; +} diff --git a/vendor/toml_edit/.cargo-checksum.json b/vendor/toml_edit/.cargo-checksum.json new file mode 100644 index 0000000..a62db67 --- /dev/null +++ b/vendor/toml_edit/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{},"package":"1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"}
\ No newline at end of file diff --git a/vendor/toml_edit/Cargo.lock b/vendor/toml_edit/Cargo.lock new file mode 100644 index 0000000..65bda25 --- /dev/null +++ b/vendor/toml_edit/Cargo.lock @@ -0,0 +1,898 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "memchr", +] + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "clap" +version = "4.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.105", +] + +[[package]] +name = "clap_lex" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "crossbeam-utils" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "equivalent" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "globset" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "ignore" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +dependencies = [ + "crossbeam-utils", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + +[[package]] +name = "include_dir" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +dependencies = [ + "libc", + "windows-sys 0.42.0", +] + +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "itoa" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "kstring" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" + +[[package]] +name = "libtest-mimic" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7b603516767d1ab23d0de09d023e62966c3322f7148297c35cf3d97aa8b37fa" +dependencies = [ + "clap", + "termcolor", + "threadpool", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi 0.1.19", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" + +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.105", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "rustix" +version = "0.37.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.160" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.160" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.15", +] + +[[package]] +name = "serde_json" +version = "1.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + +[[package]] +name = "similar" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803" + +[[package]] +name = "snapbox" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6bccd62078347f89a914e3004d94582e13824d4e3d8a816317862884c423835" +dependencies = [ + "anstream", + "anstyle", + "ignore", + "libtest-mimic", + "normalize-line-endings", + "similar", + "snapbox-macros", +] + +[[package]] +name = "snapbox-macros" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaaf09df9f0eeae82be96290918520214530e738a7fe5a351b0f24cf77c0ca31" +dependencies = [ + "anstream", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "toml-test" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37351256790aa1dbd6d60f4ff08e55e7f372e292f3e9040d6e077463d9a779c3" +dependencies = [ + "chrono", + "serde", + "serde_json", +] + +[[package]] +name = "toml-test-data" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f351b6d6005ee802b0d4a53ca1cdf05636f441df4d299e62cba57f1da52646" +dependencies = [ + "include_dir", +] + +[[package]] +name = "toml-test-harness" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e00fda5710922fe6b3005bf6a5050c303d6f9625249c37b7386e8818f4af675" +dependencies = [ + "ignore", + "libtest-mimic", + "toml-test", + "toml-test-data", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +dependencies = [ + "indexmap", + "kstring", + "libtest-mimic", + "serde", + "serde_json", + "serde_spanned", + "snapbox", + "toml-test-data", + "toml-test-harness", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.1", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm 0.42.1", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +dependencies = [ + "memchr", +] diff --git a/vendor/toml_edit/Cargo.toml b/vendor/toml_edit/Cargo.toml new file mode 100644 index 0000000..f2ed7a1 --- /dev/null +++ b/vendor/toml_edit/Cargo.toml @@ -0,0 +1,139 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.66.0" +name = "toml_edit" +version = "0.19.15" +authors = [ + "Andronik Ordian <write@reusable.software>", + "Ed Page <eopage@gmail.com>", +] +include = [ + "build.rs", + "src/**/*", + "Cargo.toml", + "Cargo.lock", + "LICENSE*", + "README.md", + "benches/**/*", + "examples/**/*", + "tests/**/*", +] +description = "Yet another format-preserving TOML parser." +readme = "README.md" +keywords = [ + "encoding", + "toml", +] +categories = [ + "encoding", + "parser-implementations", + "parsing", + "config", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/toml-rs/toml" +autotests = false + +[package.metadata.docs.rs] +features = ["serde"] +rustdoc-args = [ + "--cfg", + "docsrs", +] + +[package.metadata.release] +tag-name = "v{{version}}" + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +min = 1 +replace = "{{version}}" +search = "Unreleased" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = "...{{tag_name}}" +search = '\.\.\.HEAD' + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +min = 1 +replace = "{{date}}" +search = "ReleaseDate" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = """ +<!-- next-header --> +## [Unreleased] - ReleaseDate +""" +search = "<!-- next-header -->" + +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "CHANGELOG.md" +replace = """ +<!-- next-url --> +[Unreleased]: https://github.com/toml-rs/toml/compare/{{tag_name}}...HEAD""" +search = "<!-- next-url -->" + +[[example]] +name = "visit" +test = true + +[dependencies.indexmap] +version = ">= 1.9.1" +features = ["std"] + +[dependencies.kstring] +version = "2.0.0" +features = ["max_inline"] +optional = true + +[dependencies.serde] +version = "1.0.145" +optional = true + +[dependencies.serde_spanned] +version = "0.6.3" +features = ["serde"] +optional = true + +[dependencies.toml_datetime] +version = "0.6.3" + +[dependencies.winnow] +version = "0.5.0" + +[dev-dependencies.libtest-mimic] +version = "0.6.0" + +[dev-dependencies.serde_json] +version = "1.0.96" + +[dev-dependencies.snapbox] +version = "0.4.8" +features = ["harness"] + +[features] +default = [] +perf = ["dep:kstring"] +serde = [ + "dep:serde", + "toml_datetime/serde", + "dep:serde_spanned", +] +unbounded = [] diff --git a/vendor/toml_edit/LICENSE-APACHE b/vendor/toml_edit/LICENSE-APACHE new file mode 100644 index 0000000..8f71f43 --- /dev/null +++ b/vendor/toml_edit/LICENSE-APACHE @@ -0,0 +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. + diff --git a/vendor/toml_edit/LICENSE-MIT b/vendor/toml_edit/LICENSE-MIT new file mode 100644 index 0000000..a2d0108 --- /dev/null +++ b/vendor/toml_edit/LICENSE-MIT @@ -0,0 +1,19 @@ +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 +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/toml_edit/README.md b/vendor/toml_edit/README.md new file mode 100644 index 0000000..f1c74ee --- /dev/null +++ b/vendor/toml_edit/README.md @@ -0,0 +1,59 @@ +# 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) +[![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) + + +This crate allows you to parse and modify toml +documents, while preserving comments, spaces *and +relative order* or items. + +`toml_edit` is primarily tailored for [cargo-edit](https://github.com/killercup/cargo-edit/) needs. + +## Example + +```rust +use toml_edit::{Document, value}; + +fn main() { + let toml = r#" +"hello" = 'toml!' # comment +['a'.b] + "#; + let mut doc = toml.parse::<Document>().expect("invalid doc"); + assert_eq!(doc.to_string(), toml); + // let's add a new key/value pair inside a.b: c = {d = "hello"} + doc["a"]["b"]["c"]["d"] = value("hello"); + // autoformat inline table a.b.c: { d = "hello" } + doc["a"]["b"]["c"].as_inline_table_mut().map(|t| t.fmt()); + let expected = r#" +"hello" = 'toml!' # comment +['a'.b] +c = { d = "hello" } + "#; + 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). + +## License + +Licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +### 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/vendor/toml_edit/debian/patches/drop-toml-test.patch b/vendor/toml_edit/debian/patches/drop-toml-test.patch new file mode 100644 index 0000000..67d8b60 --- /dev/null +++ b/vendor/toml_edit/debian/patches/drop-toml-test.patch @@ -0,0 +1,44 @@ +Index: toml-edit/Cargo.toml +=================================================================== +--- toml-edit.orig/Cargo.toml ++++ toml-edit/Cargo.toml +@@ -43,6 +43,7 @@ categories = [ + ] + license = "MIT OR Apache-2.0" + repository = "https://github.com/toml-rs/toml" ++autotests = false + + [package.metadata.docs.rs] + features = ["serde"] +@@ -93,18 +94,6 @@ search = "<!-- next-url -->" + name = "visit" + test = true + +-[[test]] +-name = "decoder_compliance" +-harness = false +- +-[[test]] +-name = "encoder_compliance" +-harness = false +- +-[[test]] +-name = "invalid" +-harness = false +- + [dependencies.indexmap] + version = "2.0.0" + features = ["std"] +@@ -139,12 +128,6 @@ version = "1.0.96" + version = "0.4.11" + features = ["harness"] + +-[dev-dependencies.toml-test-data] +-version = "1.3.0" +- +-[dev-dependencies.toml-test-harness] +-version = "0.4.3" +- + [features] + default = [] + perf = ["dep:kstring"] diff --git a/vendor/toml_edit/debian/patches/relax-dep.diff b/vendor/toml_edit/debian/patches/relax-dep.diff new file mode 100644 index 0000000..73d47df --- /dev/null +++ b/vendor/toml_edit/debian/patches/relax-dep.diff @@ -0,0 +1,22 @@ +Index: toml-edit/Cargo.toml +=================================================================== +--- toml-edit.orig/Cargo.toml ++++ toml-edit/Cargo.toml +@@ -95,7 +95,7 @@ name = "visit" + test = true + + [dependencies.indexmap] +-version = "2.0.0" ++version = ">= 1.9.1" + features = ["std"] + + [dependencies.kstring] +@@ -125,7 +125,7 @@ version = "0.6.0" + version = "1.0.96" + + [dev-dependencies.snapbox] +-version = "0.4.11" ++version = "0.4.8" + features = ["harness"] + + [features] diff --git a/vendor/toml_edit/debian/patches/series b/vendor/toml_edit/debian/patches/series new file mode 100644 index 0000000..b946974 --- /dev/null +++ b/vendor/toml_edit/debian/patches/series @@ -0,0 +1,2 @@ +drop-toml-test.patch +relax-dep.diff diff --git a/vendor/toml_edit/examples/visit.rs b/vendor/toml_edit/examples/visit.rs new file mode 100644 index 0000000..cd7f851 --- /dev/null +++ b/vendor/toml_edit/examples/visit.rs @@ -0,0 +1,284 @@ +//! Example for how to use `VisitMut` to iterate over a table. + +use std::collections::BTreeSet; +use toml_edit::visit::*; +use toml_edit::visit_mut::*; +use toml_edit::{Array, Document, InlineTable, Item, KeyMut, Table, Value}; + +/// This models the visit state for dependency keys in a `Cargo.toml`. +/// +/// Dependencies can be specified as: +/// +/// ```toml +/// [dependencies] +/// dep1 = "0.2" +/// +/// [build-dependencies] +/// dep2 = "0.3" +/// +/// [dev-dependencies] +/// dep3 = "0.4" +/// +/// [target.'cfg(windows)'.dependencies] +/// dep4 = "0.5" +/// +/// # and target build- and dev-dependencies +/// ``` +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +enum VisitState { + /// Represents the root of the table. + Root, + /// Represents "dependencies", "build-dependencies" or "dev-dependencies", or the target + /// forms of these. + Dependencies, + /// A table within dependencies. + SubDependencies, + /// Represents "target". + Target, + /// "target.[TARGET]". + TargetWithSpec, + /// Represents some other state. + Other, +} + +impl VisitState { + /// Figures out the next visit state, given the current state and the given key. + fn descend(self, key: &str) -> Self { + match (self, key) { + ( + VisitState::Root | VisitState::TargetWithSpec, + "dependencies" | "build-dependencies" | "dev-dependencies", + ) => VisitState::Dependencies, + (VisitState::Root, "target") => VisitState::Target, + (VisitState::Root | VisitState::TargetWithSpec, _) => VisitState::Other, + (VisitState::Target, _) => VisitState::TargetWithSpec, + (VisitState::Dependencies, _) => VisitState::SubDependencies, + (VisitState::SubDependencies, _) => VisitState::SubDependencies, + (VisitState::Other, _) => VisitState::Other, + } + } +} + +/// Collect the names of every dependency key. +#[derive(Debug)] +struct DependencyNameVisitor<'doc> { + state: VisitState, + names: BTreeSet<&'doc str>, +} + +impl<'doc> Visit<'doc> for DependencyNameVisitor<'doc> { + fn visit_table_like_kv(&mut self, key: &'doc str, node: &'doc Item) { + if self.state == VisitState::Dependencies { + self.names.insert(key); + } else { + // Since we're only interested in collecting the top-level keys right under + // [dependencies], don't recurse unconditionally. + + let old_state = self.state; + + // Figure out the next state given the key. + self.state = self.state.descend(key); + + // Recurse further into the document tree. + visit_table_like_kv(self, key, node); + + // Restore the old state after it's done. + self.state = old_state; + } + } +} + +/// Normalize all dependency tables into the format: +/// +/// ```toml +/// [dependencies] +/// dep = { version = "1.0", features = ["foo", "bar"], ... } +/// ``` +/// +/// leaving other tables untouched. +#[derive(Debug)] +struct NormalizeDependencyTablesVisitor { + state: VisitState, +} + +impl VisitMut for NormalizeDependencyTablesVisitor { + fn visit_table_mut(&mut self, node: &mut Table) { + visit_table_mut(self, node); + + // The conversion from regular tables into inline ones might leave some explicit parent + // tables hanging, so convert them to implicit. + if matches!(self.state, VisitState::Target | VisitState::TargetWithSpec) { + node.set_implicit(true); + } + } + + fn visit_table_like_kv_mut(&mut self, mut key: KeyMut<'_>, node: &mut Item) { + let old_state = self.state; + + // Figure out the next state given the key. + self.state = self.state.descend(key.get()); + + match self.state { + VisitState::Target | VisitState::TargetWithSpec | VisitState::Dependencies => { + // Top-level dependency row, or above: turn inline tables into regular ones. + if let Item::Value(Value::InlineTable(inline_table)) = node { + let inline_table = std::mem::replace(inline_table, InlineTable::new()); + let table = inline_table.into_table(); + key.fmt(); + *node = Item::Table(table); + } + } + VisitState::SubDependencies => { + // Individual dependency: turn regular tables into inline ones. + if let Item::Table(table) = node { + // Turn the table into an inline table. + let table = std::mem::replace(table, Table::new()); + let inline_table = table.into_inline_table(); + key.fmt(); + *node = Item::Value(Value::InlineTable(inline_table)); + } + } + _ => {} + } + + // Recurse further into the document tree. + visit_table_like_kv_mut(self, key, node); + + // Restore the old state after it's done. + self.state = old_state; + } + + fn visit_array_mut(&mut self, node: &mut Array) { + // Format any arrays within dependencies to be on the same line. + if matches!( + self.state, + VisitState::Dependencies | VisitState::SubDependencies + ) { + node.fmt(); + } + } +} + +/// This is the input provided to visit_mut_example. +static INPUT: &str = r#" +[package] +name = "my-package" + +[package.metadata.foo] +bar = 42 + +[dependencies] +atty = "0.2" +cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" } + +[dependencies.pretty_env_logger] +version = "0.4" +optional = true + +[target.'cfg(windows)'.dependencies] +fwdansi = "1.1.0" + +[target.'cfg(windows)'.dependencies.winapi] +version = "0.3" +features = [ +"handleapi", +"jobapi", +] + +[target.'cfg(unix)'] +dev-dependencies = { miniz_oxide = "0.5" } + +[dev-dependencies.cargo-test-macro] +path = "crates/cargo-test-macro" + +[build-dependencies.flate2] +version = "0.4" +"#; + +/// This is the output produced by visit_mut_example. +#[cfg(test)] +static VISIT_MUT_OUTPUT: &str = r#" +[package] +name = "my-package" + +[package.metadata.foo] +bar = 42 + +[dependencies] +atty = "0.2" +cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" } +pretty_env_logger = { version = "0.4", optional = true } + +[target.'cfg(windows)'.dependencies] +fwdansi = "1.1.0" +winapi = { version = "0.3", features = ["handleapi", "jobapi"] } + +[target.'cfg(unix)'.dev-dependencies] +miniz_oxide = "0.5" + +[dev-dependencies] +cargo-test-macro = { path = "crates/cargo-test-macro" } + +[build-dependencies] +flate2 = { version = "0.4" } +"#; + +fn visit_example(document: &Document) -> BTreeSet<&str> { + let mut visitor = DependencyNameVisitor { + state: VisitState::Root, + names: BTreeSet::new(), + }; + + visitor.visit_document(document); + + visitor.names +} + +fn visit_mut_example(document: &mut Document) { + let mut visitor = NormalizeDependencyTablesVisitor { + state: VisitState::Root, + }; + + visitor.visit_document_mut(document); +} + +fn main() { + let mut document: Document = INPUT.parse().expect("input is valid TOML"); + + println!("** visit example"); + println!("{:?}", visit_example(&document)); + + println!("** visit_mut example"); + visit_mut_example(&mut document); + println!("{}", document); +} + +#[cfg(test)] +#[test] +fn visit_correct() { + let document: Document = INPUT.parse().expect("input is valid TOML"); + + let names = visit_example(&document); + let expected = vec![ + "atty", + "cargo-platform", + "pretty_env_logger", + "fwdansi", + "winapi", + "miniz_oxide", + "cargo-test-macro", + "flate2", + ] + .into_iter() + .collect(); + assert_eq!(names, expected); +} + +#[cfg(test)] +#[test] +fn visit_mut_correct() { + let mut document: Document = INPUT.parse().expect("input is valid TOML"); + + visit_mut_example(&mut document); + assert_eq!(format!("{}", document), VISIT_MUT_OUTPUT); +} diff --git a/vendor/toml_edit/src/array.rs b/vendor/toml_edit/src/array.rs new file mode 100644 index 0000000..045b451 --- /dev/null +++ b/vendor/toml_edit/src/array.rs @@ -0,0 +1,403 @@ +use std::iter::FromIterator; +use std::mem; + +use crate::repr::Decor; +use crate::value::{DEFAULT_LEADING_VALUE_DECOR, DEFAULT_VALUE_DECOR}; +use crate::{Item, RawString, Value}; + +/// Type representing a TOML array, +/// payload of the `Value::Array` variant's value +#[derive(Debug, Default, Clone)] +pub struct Array { + // `trailing` represents whitespaces, newlines + // and comments in an empty array or after the trailing comma + trailing: RawString, + trailing_comma: bool, + // prefix before `[` and suffix after `]` + decor: Decor, + pub(crate) span: Option<std::ops::Range<usize>>, + // always Vec<Item::Value> + pub(crate) values: Vec<Item>, +} + +/// An owned iterator type over `Table`'s key/value pairs. +pub type ArrayIntoIter = Box<dyn Iterator<Item = Value>>; +/// An iterator type over `Array`'s values. +pub type ArrayIter<'a> = Box<dyn Iterator<Item = &'a Value> + 'a>; +/// An iterator type over `Array`'s values. +pub type ArrayIterMut<'a> = Box<dyn Iterator<Item = &'a mut Value> + 'a>; + +/// Constructors +/// +/// See also `FromIterator` +impl Array { + /// Create an empty `Array` + /// + /// # Examples + /// + /// ```rust + /// let mut arr = toml_edit::Array::new(); + /// ``` + pub fn new() -> Self { + Default::default() + } + + pub(crate) fn with_vec(values: Vec<Item>) -> Self { + Self { + values, + ..Default::default() + } + } +} + +/// Formatting +impl Array { + /// Auto formats the array. + pub fn fmt(&mut self) { + decorate_array(self); + } + + /// Set whether the array will use a trailing comma + pub fn set_trailing_comma(&mut self, yes: bool) { + self.trailing_comma = yes; + } + + /// Whether the array will use a trailing comma + pub fn trailing_comma(&self) -> bool { + self.trailing_comma + } + + /// Set whitespace after last element + pub fn set_trailing(&mut self, trailing: impl Into<RawString>) { + self.trailing = trailing.into(); + } + + /// Whitespace after last element + pub fn trailing(&self) -> &RawString { + &self.trailing + } + + /// Returns the surrounding whitespace + pub fn decor_mut(&mut self) -> &mut Decor { + &mut self.decor + } + + /// Returns the surrounding whitespace + pub fn decor(&self) -> &Decor { + &self.decor + } + + /// Returns the location within the original document + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + self.span.clone() + } + + pub(crate) fn despan(&mut self, input: &str) { + self.span = None; + self.decor.despan(input); + self.trailing.despan(input); + for value in &mut self.values { + value.despan(input); + } + } +} + +impl Array { + /// Returns an iterator over all values. + pub fn iter(&self) -> ArrayIter<'_> { + Box::new(self.values.iter().filter_map(Item::as_value)) + } + + /// Returns an iterator over all values. + pub fn iter_mut(&mut self) -> ArrayIterMut<'_> { + Box::new(self.values.iter_mut().filter_map(Item::as_value_mut)) + } + + /// Returns the length of the underlying Vec. + /// + /// In some rare cases, placeholder elements will exist. For a more accurate count, call + /// `a.iter().count()` + /// + /// # Examples + /// + /// ```rust + /// let mut arr = toml_edit::Array::new(); + /// arr.push(1); + /// arr.push("foo"); + /// assert_eq!(arr.len(), 2); + /// ``` + pub fn len(&self) -> usize { + self.values.len() + } + + /// Return true iff `self.len() == 0`. + /// + /// # Examples + /// + /// ```rust + /// let mut arr = toml_edit::Array::new(); + /// assert!(arr.is_empty()); + /// + /// arr.push(1); + /// arr.push("foo"); + /// assert!(! arr.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Clears the array, removing all values. Keeps the allocated memory for reuse. + pub fn clear(&mut self) { + self.values.clear() + } + + /// Returns a reference to the value at the given index, or `None` if the index is out of + /// bounds. + pub fn get(&self, index: usize) -> Option<&Value> { + self.values.get(index).and_then(Item::as_value) + } + + /// Returns a reference to the value at the given index, or `None` if the index is out of + /// bounds. + pub fn get_mut(&mut self, index: usize) -> Option<&mut Value> { + self.values.get_mut(index).and_then(Item::as_value_mut) + } + + /// Appends a new value to the end of the array, applying default formatting to it. + /// + /// # Examples + /// + /// ```rust + /// let mut arr = toml_edit::Array::new(); + /// arr.push(1); + /// arr.push("foo"); + /// ``` + pub fn push<V: Into<Value>>(&mut self, v: V) { + self.value_op(v.into(), true, |items, value| { + items.push(Item::Value(value)) + }) + } + + /// Appends a new, already formatted value to the end of the array. + /// + /// # Examples + /// + /// ```rust + /// 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)); + } + + /// Inserts an element at the given position within the array, applying default formatting to + /// it and shifting all values after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + /// + /// # Examples + /// + /// ```rust + /// let mut arr = toml_edit::Array::new(); + /// arr.push(1); + /// arr.push("foo"); + /// + /// arr.insert(0, "start"); + /// ``` + pub fn insert<V: Into<Value>>(&mut self, index: usize, v: V) { + self.value_op(v.into(), true, |items, value| { + items.insert(index, Item::Value(value)) + }) + } + + /// Inserts an already formatted value at the given position within the array, shifting all + /// values after it to the right. + /// + /// # Panics + /// + /// Panics if `index > len`. + /// + /// # Examples + /// + /// ```rust + /// 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)) + } + + /// Replaces the element at the given position within the array, preserving existing formatting. + /// + /// # Panics + /// + /// Panics if `index >= len`. + /// + /// # Examples + /// + /// ```rust + /// let mut arr = toml_edit::Array::new(); + /// arr.push(1); + /// arr.push("foo"); + /// + /// arr.replace(0, "start"); + /// ``` + pub fn replace<V: Into<Value>>(&mut self, index: usize, v: V) -> Value { + // Read the existing value's decor and preserve it. + let existing_decor = self + .get(index) + .unwrap_or_else(|| panic!("index {} out of bounds (len = {})", index, self.len())) + .decor(); + let mut value = v.into(); + *value.decor_mut() = existing_decor.clone(); + self.replace_formatted(index, value) + } + + /// Replaces the element at the given position within the array with an already formatted value. + /// + /// # Panics + /// + /// Panics if `index >= len`. + /// + /// # Examples + /// + /// ```rust + /// 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)) { + Item::Value(old_value) => old_value, + x => panic!("non-value item {:?} in an array", x), + } + } + + /// Removes the value at the given index. + /// + /// # Examples + /// + /// ```rust + /// let mut arr = toml_edit::Array::new(); + /// arr.push(1); + /// arr.push("foo"); + /// + /// arr.remove(0); + /// assert_eq!(arr.len(), 1); + /// ``` + pub fn remove(&mut self, index: usize) -> Value { + let removed = self.values.remove(index); + match removed { + Item::Value(v) => v, + x => panic!("non-value item {:?} in an array", x), + } + } + + /// Retains only the values specified by the `keep` predicate. + /// + /// In other words, remove all values for which `keep(&value)` returns `false`. + /// + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + pub fn retain<F>(&mut self, mut keep: F) + where + F: FnMut(&Value) -> bool, + { + self.values + .retain(|item| item.as_value().map(&mut keep).unwrap_or(false)); + } + + fn value_op<T>( + &mut self, + v: Value, + decorate: bool, + op: impl FnOnce(&mut Vec<Item>, Value) -> T, + ) -> T { + let mut value = v; + if !self.is_empty() && decorate { + value.decorate(" ", ""); + } else if decorate { + value.decorate("", ""); + } + op(&mut self.values, value) + } +} + +impl std::fmt::Display for Array { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + crate::encode::Encode::encode(self, f, None, ("", "")) + } +} + +impl<V: Into<Value>> Extend<V> for Array { + fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) { + for value in iter { + self.push_formatted(value.into()); + } + } +} + +impl<V: Into<Value>> FromIterator<V> for Array { + fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator<Item = V>, + { + let v = iter.into_iter().map(|a| Item::Value(a.into())); + Array { + values: v.collect(), + ..Default::default() + } + } +} + +impl IntoIterator for Array { + type Item = Value; + type IntoIter = ArrayIntoIter; + + fn into_iter(self) -> Self::IntoIter { + Box::new( + self.values + .into_iter() + .filter(|v| v.is_value()) + .map(|v| v.into_value().unwrap()), + ) + } +} + +impl<'s> IntoIterator for &'s Array { + type Item = &'s Value; + type IntoIter = ArrayIter<'s>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +fn decorate_array(array: &mut Array) { + for (i, value) in array + .values + .iter_mut() + .filter_map(Item::as_value_mut) + .enumerate() + { + // [value1, value2, value3] + if i == 0 { + value.decorate(DEFAULT_LEADING_VALUE_DECOR.0, DEFAULT_LEADING_VALUE_DECOR.1); + } else { + value.decorate(DEFAULT_VALUE_DECOR.0, DEFAULT_VALUE_DECOR.1); + } + } + // Since everything is now on the same line, remove trailing commas and whitespace. + array.set_trailing_comma(false); + array.set_trailing(""); +} diff --git a/vendor/toml_edit/src/array_of_tables.rs b/vendor/toml_edit/src/array_of_tables.rs new file mode 100644 index 0000000..c4d7194 --- /dev/null +++ b/vendor/toml_edit/src/array_of_tables.rs @@ -0,0 +1,166 @@ +use std::iter::FromIterator; + +use crate::{Array, Item, Table}; + +/// Type representing a TOML array of tables +#[derive(Clone, Debug, Default)] +pub struct ArrayOfTables { + // Always Vec<Item::Table>, just `Item` to make `Index` work + pub(crate) span: Option<std::ops::Range<usize>>, + pub(crate) values: Vec<Item>, +} + +/// Constructors +/// +/// See also `FromIterator` +impl ArrayOfTables { + /// Creates an empty array of tables. + pub fn new() -> Self { + Default::default() + } +} + +/// Formatting +impl ArrayOfTables { + /// Convert to an inline array + pub fn into_array(mut self) -> Array { + for value in self.values.iter_mut() { + value.make_value(); + } + let mut a = Array::with_vec(self.values); + a.fmt(); + a + } + + /// Returns the location within the original document + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + self.span.clone() + } + + pub(crate) fn despan(&mut self, input: &str) { + self.span = None; + for value in &mut self.values { + value.despan(input); + } + } +} + +impl ArrayOfTables { + /// Returns an iterator over tables. + pub fn iter(&self) -> ArrayOfTablesIter<'_> { + Box::new(self.values.iter().filter_map(Item::as_table)) + } + + /// Returns an iterator over tables. + pub fn iter_mut(&mut self) -> ArrayOfTablesIterMut<'_> { + Box::new(self.values.iter_mut().filter_map(Item::as_table_mut)) + } + + /// Returns the length of the underlying Vec. + /// To get the actual number of items use `a.iter().count()`. + pub fn len(&self) -> usize { + self.values.len() + } + + /// Returns true iff `self.len() == 0`. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Removes all the tables. + pub fn clear(&mut self) { + self.values.clear() + } + + /// Returns an optional reference to the table. + pub fn get(&self, index: usize) -> Option<&Table> { + self.values.get(index).and_then(Item::as_table) + } + + /// Returns an optional mutable reference to the table. + pub fn get_mut(&mut self, index: usize) -> Option<&mut Table> { + self.values.get_mut(index).and_then(Item::as_table_mut) + } + + /// Appends a table to the array. + pub fn push(&mut self, table: Table) { + self.values.push(Item::Table(table)); + } + + /// Removes a table with the given index. + pub fn remove(&mut self, index: usize) { + self.values.remove(index); + } + + /// Retains only the elements specified by the `keep` predicate. + /// + /// In other words, remove all tables for which `keep(&table)` returns `false`. + /// + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + pub fn retain<F>(&mut self, mut keep: F) + where + F: FnMut(&Table) -> bool, + { + self.values + .retain(|item| item.as_table().map(&mut keep).unwrap_or(false)); + } +} + +/// An iterator type over `ArrayOfTables`'s values. +pub type ArrayOfTablesIter<'a> = Box<dyn Iterator<Item = &'a Table> + 'a>; +/// An iterator type over `ArrayOfTables`'s values. +pub type ArrayOfTablesIterMut<'a> = Box<dyn Iterator<Item = &'a mut Table> + 'a>; +/// An iterator type over `ArrayOfTables`'s values. +pub type ArrayOfTablesIntoIter = Box<dyn Iterator<Item = Table>>; + +impl Extend<Table> for ArrayOfTables { + fn extend<T: IntoIterator<Item = Table>>(&mut self, iter: T) { + for value in iter { + self.push(value); + } + } +} + +impl FromIterator<Table> for ArrayOfTables { + fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator<Item = Table>, + { + let v = iter.into_iter().map(Item::Table); + ArrayOfTables { + values: v.collect(), + span: None, + } + } +} + +impl IntoIterator for ArrayOfTables { + type Item = Table; + type IntoIter = ArrayOfTablesIntoIter; + + fn into_iter(self) -> Self::IntoIter { + Box::new( + self.values + .into_iter() + .filter(|v| v.is_table()) + .map(|v| v.into_table().unwrap()), + ) + } +} + +impl<'s> IntoIterator for &'s ArrayOfTables { + type Item = &'s Table; + type IntoIter = ArrayOfTablesIter<'s>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +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 + self.clone().into_array().fmt(f) + } +} diff --git a/vendor/toml_edit/src/de/array.rs b/vendor/toml_edit/src/de/array.rs new file mode 100644 index 0000000..adc5401 --- /dev/null +++ b/vendor/toml_edit/src/de/array.rs @@ -0,0 +1,97 @@ +use crate::de::Error; + +pub(crate) struct ArrayDeserializer { + input: Vec<crate::Item>, + span: Option<std::ops::Range<usize>>, +} + +impl ArrayDeserializer { + pub(crate) fn new(input: Vec<crate::Item>, span: Option<std::ops::Range<usize>>) -> Self { + Self { input, span } + } +} + +// Note: this is wrapped by `ValueDeserializer` and any trait methods +// implemented here need to be wrapped there +impl<'de> serde::Deserializer<'de> for ArrayDeserializer { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + visitor.visit_seq(ArraySeqAccess::new(self.input)) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + if serde_spanned::__unstable::is_spanned(name, fields) { + if let Some(span) = self.span.clone() { + return visitor.visit_map(super::SpannedDeserializer::new(self, span)); + } + } + + self.deserialize_any(visitor) + } + + 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 + ignored_any unit_struct tuple_struct tuple enum identifier + } +} + +impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for ArrayDeserializer { + type Deserializer = Self; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +impl crate::Array { + pub(crate) fn into_deserializer(self) -> ArrayDeserializer { + ArrayDeserializer::new(self.values, self.span) + } +} + +impl crate::ArrayOfTables { + pub(crate) fn into_deserializer(self) -> ArrayDeserializer { + ArrayDeserializer::new(self.values, self.span) + } +} + +pub(crate) struct ArraySeqAccess { + iter: std::vec::IntoIter<crate::Item>, +} + +impl ArraySeqAccess { + pub(crate) fn new(input: Vec<crate::Item>) -> Self { + Self { + iter: input.into_iter(), + } + } +} + +impl<'de> serde::de::SeqAccess<'de> for ArraySeqAccess { + type Error = Error; + + fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(v) => seed + .deserialize(crate::de::ValueDeserializer::new(v)) + .map(Some), + None => Ok(None), + } + } +} diff --git a/vendor/toml_edit/src/de/datetime.rs b/vendor/toml_edit/src/de/datetime.rs new file mode 100644 index 0000000..14de28b --- /dev/null +++ b/vendor/toml_edit/src/de/datetime.rs @@ -0,0 +1,43 @@ +use serde::de::value::BorrowedStrDeserializer; +use serde::de::IntoDeserializer; + +use crate::de::Error; + +pub(crate) struct DatetimeDeserializer { + date: Option<crate::Datetime>, +} + +impl DatetimeDeserializer { + pub(crate) fn new(date: crate::Datetime) -> Self { + Self { date: Some(date) } + } +} + +impl<'de> serde::de::MapAccess<'de> for DatetimeDeserializer { + type Error = Error; + + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error> + where + K: serde::de::DeserializeSeed<'de>, + { + if self.date.is_some() { + seed.deserialize(BorrowedStrDeserializer::new( + toml_datetime::__unstable::FIELD, + )) + .map(Some) + } else { + Ok(None) + } + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error> + where + V: serde::de::DeserializeSeed<'de>, + { + if let Some(date) = self.date.take() { + seed.deserialize(date.to_string().into_deserializer()) + } else { + panic!("next_value_seed called before next_key_seed") + } + } +} diff --git a/vendor/toml_edit/src/de/key.rs b/vendor/toml_edit/src/de/key.rs new file mode 100644 index 0000000..3da41df --- /dev/null +++ b/vendor/toml_edit/src/de/key.rs @@ -0,0 +1,140 @@ +use serde::de::IntoDeserializer; + +use super::Error; + +pub(crate) struct KeyDeserializer { + span: Option<std::ops::Range<usize>>, + key: crate::InternalString, +} + +impl KeyDeserializer { + pub(crate) fn new(key: crate::InternalString, span: Option<std::ops::Range<usize>>) -> Self { + KeyDeserializer { span, key } + } +} + +impl<'de> serde::de::IntoDeserializer<'de, Error> for KeyDeserializer { + type Deserializer = Self; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +impl<'de> serde::de::Deserializer<'de> for KeyDeserializer { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + self.key.into_deserializer().deserialize_any(visitor) + } + + fn deserialize_enum<V>( + self, + name: &str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + let _ = name; + let _ = variants; + visitor.visit_enum(self) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + if serde_spanned::__unstable::is_spanned(name, fields) { + if let Some(span) = self.span.clone() { + return visitor.visit_map(super::SpannedDeserializer::new(self.key.as_str(), span)); + } + } + self.deserialize_any(visitor) + } + + 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 + ignored_any unit_struct tuple_struct tuple identifier + } +} + +impl<'de> serde::de::EnumAccess<'de> for KeyDeserializer { + type Error = super::Error; + type Variant = UnitOnly<Self::Error>; + + fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + seed.deserialize(self).map(unit_only) + } +} + +pub(crate) struct UnitOnly<E> { + marker: std::marker::PhantomData<E>, +} + +fn unit_only<T, E>(t: T) -> (T, UnitOnly<E>) { + ( + t, + UnitOnly { + marker: std::marker::PhantomData, + }, + ) +} + +impl<'de, E> serde::de::VariantAccess<'de> for UnitOnly<E> +where + E: serde::de::Error, +{ + type Error = E; + + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + Err(serde::de::Error::invalid_type( + serde::de::Unexpected::UnitVariant, + &"newtype variant", + )) + } + + fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + Err(serde::de::Error::invalid_type( + serde::de::Unexpected::UnitVariant, + &"tuple variant", + )) + } + + fn struct_variant<V>( + self, + _fields: &'static [&'static str], + _visitor: V, + ) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + Err(serde::de::Error::invalid_type( + serde::de::Unexpected::UnitVariant, + &"struct variant", + )) + } +} diff --git a/vendor/toml_edit/src/de/mod.rs b/vendor/toml_edit/src/de/mod.rs new file mode 100644 index 0000000..09ea120 --- /dev/null +++ b/vendor/toml_edit/src/de/mod.rs @@ -0,0 +1,289 @@ +//! Deserializing TOML into Rust structures. +//! +//! This module contains all the Serde support for deserializing TOML documents into Rust structures. + +use serde::de::DeserializeOwned; + +mod array; +mod datetime; +mod key; +mod spanned; +mod table; +mod table_enum; +mod value; + +use array::ArrayDeserializer; +use datetime::DatetimeDeserializer; +use key::KeyDeserializer; +use spanned::SpannedDeserializer; +use table::TableMapAccess; +use table_enum::TableEnumDeserializer; + +pub use value::ValueDeserializer; + +/// Errors that can occur when deserializing a type. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Error { + inner: crate::TomlError, +} + +impl Error { + pub(crate) fn custom<T>(msg: T, span: Option<std::ops::Range<usize>>) -> Self + where + T: std::fmt::Display, + { + Error { + inner: crate::TomlError::custom(msg.to_string(), span), + } + } + + /// Add key while unwinding + pub fn add_key(&mut self, key: String) { + self.inner.add_key(key) + } + + /// What went wrong + pub fn message(&self) -> &str { + self.inner.message() + } + + /// The start/end index into the original document where the error occurred + pub fn span(&self) -> Option<std::ops::Range<usize>> { + self.inner.span() + } + + pub(crate) fn set_span(&mut self, span: Option<std::ops::Range<usize>>) { + self.inner.set_span(span); + } +} + +impl serde::de::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::custom(msg, None) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.inner.fmt(f) + } +} + +impl From<crate::TomlError> for Error { + fn from(e: crate::TomlError) -> Error { + Self { inner: e } + } +} + +impl From<Error> for crate::TomlError { + fn from(e: Error) -> crate::TomlError { + e.inner + } +} + +impl std::error::Error for Error {} + +/// Convert a value into `T`. +pub fn from_str<T>(s: &'_ str) -> Result<T, Error> +where + T: DeserializeOwned, +{ + let de = s.parse::<Deserializer>()?; + T::deserialize(de) +} + +/// Convert a value into `T`. +pub fn from_slice<T>(s: &'_ [u8]) -> Result<T, Error> +where + T: DeserializeOwned, +{ + let s = std::str::from_utf8(s).map_err(|e| Error::custom(e, None))?; + from_str(s) +} + +/// Convert a document into `T`. +pub fn from_document<T>(d: crate::Document) -> Result<T, Error> +where + T: DeserializeOwned, +{ + let deserializer = Deserializer::new(d); + T::deserialize(deserializer) +} + +/// Deserialization for TOML [documents][crate::Document]. +pub struct Deserializer { + input: crate::Document, +} + +impl Deserializer { + /// Deserialization implementation for TOML. + pub fn new(input: crate::Document) -> Self { + Self { input } + } +} + +impl std::str::FromStr for Deserializer { + type Err = Error; + + /// Parses a document from a &str + fn from_str(s: &str) -> Result<Self, Self::Err> { + let d = crate::parser::parse_document(s).map_err(Error::from)?; + Ok(Self::new(d)) + } +} + +// Note: this is wrapped by `toml::de::Deserializer` and any trait methods +// implemented here need to be wrapped there +impl<'de> serde::Deserializer<'de> for Deserializer { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_any(visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + // `None` is interpreted as a missing field so be sure to implement `Some` + // as a present field. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_option(visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + fn deserialize_newtype_struct<V>( + self, + name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_newtype_struct(name, visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_struct(name, fields, visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + // Called when the type to deserialize is an enum, as opposed to a field in the type. + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let original = self.input.original; + self.input + .root + .into_deserializer() + .deserialize_enum(name, variants, visitor) + .map_err(|mut e: Self::Error| { + e.inner.set_original(original); + e + }) + } + + serde::forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq + bytes byte_buf map unit + ignored_any unit_struct tuple_struct tuple identifier + } +} + +impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for Deserializer { + type Deserializer = Deserializer; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for crate::Document { + type Deserializer = Deserializer; + + fn into_deserializer(self) -> Self::Deserializer { + Deserializer::new(self) + } +} + +pub(crate) fn validate_struct_keys( + table: &crate::table::KeyValuePairs, + fields: &'static [&'static str], +) -> Result<(), Error> { + let extra_fields = table + .iter() + .filter_map(|(key, val)| { + if !fields.contains(&key.as_str()) { + Some(val.clone()) + } else { + None + } + }) + .collect::<Vec<_>>(); + + if extra_fields.is_empty() { + Ok(()) + } else { + Err(Error::custom( + format!( + "unexpected keys in table: {}, available keys: {}", + extra_fields + .iter() + .map(|k| k.key.get()) + .collect::<Vec<_>>() + .join(", "), + fields.join(", "), + ), + extra_fields[0].key.span(), + )) + } +} diff --git a/vendor/toml_edit/src/de/spanned.rs b/vendor/toml_edit/src/de/spanned.rs new file mode 100644 index 0000000..7ce5864 --- /dev/null +++ b/vendor/toml_edit/src/de/spanned.rs @@ -0,0 +1,70 @@ +use serde::de::value::BorrowedStrDeserializer; +use serde::de::IntoDeserializer as _; + +use super::Error; + +pub(crate) struct SpannedDeserializer<'de, T: serde::de::IntoDeserializer<'de, Error>> { + phantom_data: std::marker::PhantomData<&'de ()>, + start: Option<usize>, + end: Option<usize>, + value: Option<T>, +} + +impl<'de, T> SpannedDeserializer<'de, T> +where + T: serde::de::IntoDeserializer<'de, Error>, +{ + pub(crate) fn new(value: T, span: std::ops::Range<usize>) -> Self { + Self { + phantom_data: Default::default(), + start: Some(span.start), + end: Some(span.end), + value: Some(value), + } + } +} + +impl<'de, T> serde::de::MapAccess<'de> for SpannedDeserializer<'de, T> +where + T: serde::de::IntoDeserializer<'de, Error>, +{ + type Error = Error; + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error> + where + K: serde::de::DeserializeSeed<'de>, + { + if self.start.is_some() { + seed.deserialize(BorrowedStrDeserializer::new( + serde_spanned::__unstable::START_FIELD, + )) + .map(Some) + } else if self.end.is_some() { + seed.deserialize(BorrowedStrDeserializer::new( + serde_spanned::__unstable::END_FIELD, + )) + .map(Some) + } else if self.value.is_some() { + seed.deserialize(BorrowedStrDeserializer::new( + serde_spanned::__unstable::VALUE_FIELD, + )) + .map(Some) + } else { + Ok(None) + } + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error> + where + V: serde::de::DeserializeSeed<'de>, + { + if let Some(start) = self.start.take() { + seed.deserialize(start.into_deserializer()) + } else if let Some(end) = self.end.take() { + seed.deserialize(end.into_deserializer()) + } else if let Some(value) = self.value.take() { + seed.deserialize(value.into_deserializer()) + } else { + panic!("next_value_seed called before next_key_seed") + } + } +} diff --git a/vendor/toml_edit/src/de/table.rs b/vendor/toml_edit/src/de/table.rs new file mode 100644 index 0000000..0b6183e --- /dev/null +++ b/vendor/toml_edit/src/de/table.rs @@ -0,0 +1,213 @@ +use serde::de::IntoDeserializer; + +use crate::de::Error; + +pub(crate) struct TableDeserializer { + span: Option<std::ops::Range<usize>>, + items: crate::table::KeyValuePairs, +} + +// Note: this is wrapped by `Deserializer` and `ValueDeserializer` and any trait methods +// implemented here need to be wrapped there +impl<'de> serde::Deserializer<'de> for TableDeserializer { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + visitor.visit_map(crate::de::TableMapAccess::new(self)) + } + + // `None` is interpreted as a missing field so be sure to implement `Some` + // as a present field. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + visitor.visit_some(self) + } + + 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) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + if serde_spanned::__unstable::is_spanned(name, fields) { + if let Some(span) = self.span.clone() { + return visitor.visit_map(super::SpannedDeserializer::new(self, span)); + } + } + + self.deserialize_any(visitor) + } + + // Called when the type to deserialize is an enum, as opposed to a field in the type. + fn deserialize_enum<V>( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + if self.items.is_empty() { + Err(crate::de::Error::custom( + "wanted exactly 1 element, found 0 elements", + self.span, + )) + } else if self.items.len() != 1 { + Err(crate::de::Error::custom( + "wanted exactly 1 element, more than 1 element", + self.span, + )) + } else { + visitor.visit_enum(crate::de::TableMapAccess::new(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 unit + ignored_any unit_struct tuple_struct tuple identifier + } +} + +impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for TableDeserializer { + type Deserializer = TableDeserializer; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +impl crate::Table { + pub(crate) fn into_deserializer(self) -> TableDeserializer { + TableDeserializer { + span: self.span(), + items: self.items, + } + } +} + +impl crate::InlineTable { + pub(crate) fn into_deserializer(self) -> TableDeserializer { + TableDeserializer { + span: self.span(), + items: self.items, + } + } +} + +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)>, +} + +impl TableMapAccess { + pub(crate) fn new(input: TableDeserializer) -> Self { + Self { + iter: input.items.into_iter(), + span: input.span, + value: None, + } + } +} + +impl<'de> serde::de::MapAccess<'de> for TableMapAccess { + type Error = Error; + + fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> + where + K: serde::de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some((k, v)) => { + let ret = seed + .deserialize(super::KeyDeserializer::new(k, v.key.span())) + .map(Some) + .map_err(|mut e: Self::Error| { + if e.span().is_none() { + e.set_span(v.key.span()); + } + e + }); + self.value = Some((v.key.into(), v.value)); + ret + } + None => Ok(None), + } + } + + fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> + where + V: serde::de::DeserializeSeed<'de>, + { + match self.value.take() { + Some((k, v)) => { + let span = v.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 + }) + } + None => { + panic!("no more values in next_value_seed, internal error in ValueDeserializer") + } + } + } +} + +impl<'de> serde::de::EnumAccess<'de> for TableMapAccess { + type Error = Error; + type Variant = super::TableEnumDeserializer; + + fn variant_seed<V>(mut self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: serde::de::DeserializeSeed<'de>, + { + let (key, value) = match self.iter.next() { + Some(pair) => pair, + None => { + return Err(Error::custom( + "expected table with exactly 1 entry, found empty table", + self.span, + )); + } + }; + + let val = seed + .deserialize(key.into_deserializer()) + .map_err(|mut e: Self::Error| { + if e.span().is_none() { + e.set_span(value.key.span()); + } + e + })?; + + let variant = super::TableEnumDeserializer::new(value.value); + + Ok((val, variant)) + } +} diff --git a/vendor/toml_edit/src/de/table_enum.rs b/vendor/toml_edit/src/de/table_enum.rs new file mode 100644 index 0000000..197ad6e --- /dev/null +++ b/vendor/toml_edit/src/de/table_enum.rs @@ -0,0 +1,160 @@ +use crate::de::Error; + +/// Deserializes table values into enum variants. +pub(crate) struct TableEnumDeserializer { + value: crate::Item, +} + +impl TableEnumDeserializer { + pub(crate) fn new(value: crate::Item) -> Self { + TableEnumDeserializer { value } + } +} + +impl<'de> serde::de::VariantAccess<'de> for TableEnumDeserializer { + type Error = Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + match self.value { + crate::Item::Table(values) => { + if values.is_empty() { + Ok(()) + } else { + Err(Error::custom("expected empty table", values.span())) + } + } + crate::Item::Value(crate::Value::InlineTable(values)) => { + if values.is_empty() { + Ok(()) + } else { + Err(Error::custom("expected empty table", values.span())) + } + } + e => Err(Error::custom( + format!("expected table, found {}", e.type_name()), + e.span(), + )), + } + } + + fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + seed.deserialize(super::ValueDeserializer::new(self.value)) + } + + fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + match self.value { + crate::Item::Table(values) => { + let values_span = values.span(); + let tuple_values = values + .items + .into_iter() + .enumerate() + .map( + |(index, (_, value))| match value.key.get().parse::<usize>() { + Ok(key_index) if key_index == index => Ok(value.value), + Ok(_) | Err(_) => Err(Error::custom( + format!( + "expected table key `{}`, but was `{}`", + index, + value.key.get() + ), + value.key.span(), + )), + }, + ) + // 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), + }) + })?; + + 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::InlineTable(values)) => { + let values_span = values.span(); + let tuple_values = values + .items + .into_iter() + .enumerate() + .map( + |(index, (_, value))| match value.key.get().parse::<usize>() { + Ok(key_index) if key_index == index => Ok(value.value), + Ok(_) | Err(_) => Err(Error::custom( + format!( + "expected table key `{}`, but was `{}`", + index, + value.key.get() + ), + value.key.span(), + )), + }, + ) + // 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), + }) + })?; + + 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, + )) + } + } + e => Err(Error::custom( + format!("expected table, found {}", e.type_name()), + e.span(), + )), + } + } + + fn struct_variant<V>( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + serde::de::Deserializer::deserialize_struct( + super::ValueDeserializer::new(self.value).with_struct_key_validation(), + "", // TODO: this should be the variant name + fields, + visitor, + ) + } +} diff --git a/vendor/toml_edit/src/de/value.rs b/vendor/toml_edit/src/de/value.rs new file mode 100644 index 0000000..d3cf87f --- /dev/null +++ b/vendor/toml_edit/src/de/value.rs @@ -0,0 +1,252 @@ +use serde::de::IntoDeserializer as _; + +use crate::de::DatetimeDeserializer; +use crate::de::Error; + +/// Deserialization implementation for TOML [values][crate::Value]. +/// +/// 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 +/// +/// ``` +/// use serde::Deserialize; +/// +/// #[derive(Deserialize)] +/// struct Config { +/// title: String, +/// owner: Owner, +/// } +/// +/// #[derive(Deserialize)] +/// struct Owner { +/// name: String, +/// } +/// +/// let value = r#"{ title = 'TOML Example', owner = { name = 'Lisa' } }"#; +/// let deserializer = value.parse::<toml_edit::de::ValueDeserializer>().unwrap(); +/// let config = Config::deserialize(deserializer).unwrap(); +/// assert_eq!(config.title, "TOML Example"); +/// assert_eq!(config.owner.name, "Lisa"); +/// ``` +pub struct ValueDeserializer { + input: crate::Item, + validate_struct_keys: bool, +} + +impl ValueDeserializer { + pub(crate) fn new(input: crate::Item) -> Self { + Self { + input, + validate_struct_keys: false, + } + } + + pub(crate) fn with_struct_key_validation(mut self) -> Self { + self.validate_struct_keys = true; + self + } +} + +// Note: this is wrapped by `toml::de::ValueDeserializer` and any trait methods +// implemented here need to be wrapped there +impl<'de> serde::Deserializer<'de> for ValueDeserializer { + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where + V: serde::de::Visitor<'de>, + { + let span = self.input.span(); + match self.input { + crate::Item::None => visitor.visit_none(), + crate::Item::Value(crate::Value::String(v)) => visitor.visit_string(v.into_value()), + crate::Item::Value(crate::Value::Integer(v)) => visitor.visit_i64(v.into_value()), + crate::Item::Value(crate::Value::Float(v)) => visitor.visit_f64(v.into_value()), + crate::Item::Value(crate::Value::Boolean(v)) => visitor.visit_bool(v.into_value()), + crate::Item::Value(crate::Value::Datetime(v)) => { + visitor.visit_map(DatetimeDeserializer::new(v.into_value())) + } + crate::Item::Value(crate::Value::Array(v)) => { + v.into_deserializer().deserialize_any(visitor) + } + crate::Item::Value(crate::Value::InlineTable(v)) => { + v.into_deserializer().deserialize_any(visitor) + } + crate::Item::Table(v) => v.into_deserializer().deserialize_any(visitor), + crate::Item::ArrayOfTables(v) => v.into_deserializer().deserialize_any(visitor), + } + .map_err(|mut e: Self::Error| { + if e.span().is_none() { + e.set_span(span); + } + e + }) + } + + // `None` is interpreted as a missing field so be sure to implement `Some` + // as a present field. + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let span = self.input.span(); + visitor.visit_some(self).map_err(|mut e: Self::Error| { + if e.span().is_none() { + e.set_span(span); + } + e + }) + } + + fn deserialize_newtype_struct<V>( + self, + _name: &'static str, + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let span = self.input.span(); + visitor + .visit_newtype_struct(self) + .map_err(|mut e: Self::Error| { + if e.span().is_none() { + e.set_span(span); + } + e + }) + } + + fn deserialize_struct<V>( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + if serde_spanned::__unstable::is_spanned(name, fields) { + if let Some(span) = self.input.span() { + return visitor.visit_map(super::SpannedDeserializer::new(self, span)); + } + } + + if name == toml_datetime::__unstable::NAME && fields == [toml_datetime::__unstable::FIELD] { + let span = self.input.span(); + if let crate::Item::Value(crate::Value::Datetime(d)) = self.input { + return visitor + .visit_map(DatetimeDeserializer::new(d.into_value())) + .map_err(|mut e: Self::Error| { + if e.span().is_none() { + e.set_span(span); + } + e + }); + } + } + + if self.validate_struct_keys { + let span = self.input.span(); + match &self.input { + crate::Item::Table(values) => super::validate_struct_keys(&values.items, fields), + crate::Item::Value(crate::Value::InlineTable(values)) => { + super::validate_struct_keys(&values.items, fields) + } + _ => Ok(()), + } + .map_err(|mut e: Self::Error| { + if e.span().is_none() { + e.set_span(span); + } + e + })? + } + + self.deserialize_any(visitor) + } + + // Called when the type to deserialize is an enum, as opposed to a field in the type. + fn deserialize_enum<V>( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result<V::Value, Error> + where + V: serde::de::Visitor<'de>, + { + let span = self.input.span(); + match self.input { + crate::Item::Value(crate::Value::String(v)) => { + visitor.visit_enum(v.into_value().into_deserializer()) + } + crate::Item::Value(crate::Value::InlineTable(v)) => { + if v.is_empty() { + Err(crate::de::Error::custom( + "wanted exactly 1 element, found 0 elements", + v.span(), + )) + } else if v.len() != 1 { + Err(crate::de::Error::custom( + "wanted exactly 1 element, more than 1 element", + v.span(), + )) + } else { + v.into_deserializer() + .deserialize_enum(name, variants, visitor) + } + } + crate::Item::Table(v) => v + .into_deserializer() + .deserialize_enum(name, variants, visitor), + e => Err(crate::de::Error::custom("wanted string or table", e.span())), + } + .map_err(|mut e: Self::Error| { + if e.span().is_none() { + e.set_span(span); + } + e + }) + } + + serde::forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq + bytes byte_buf map unit + ignored_any unit_struct tuple_struct tuple identifier + } +} + +impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for ValueDeserializer { + type Deserializer = Self; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +impl<'de> serde::de::IntoDeserializer<'de, crate::de::Error> for crate::Value { + type Deserializer = ValueDeserializer; + + fn into_deserializer(self) -> Self::Deserializer { + ValueDeserializer::new(crate::Item::Value(self)) + } +} + +impl crate::Item { + pub(crate) fn into_deserializer(self) -> ValueDeserializer { + ValueDeserializer::new(self) + } +} + +impl std::str::FromStr for ValueDeserializer { + type Err = Error; + + /// Parses a value from a &str + fn from_str(s: &str) -> Result<Self, Self::Err> { + let v = crate::parser::parse_value(s).map_err(Error::from)?; + Ok(v.into_deserializer()) + } +} diff --git a/vendor/toml_edit/src/document.rs b/vendor/toml_edit/src/document.rs new file mode 100644 index 0000000..67dd293 --- /dev/null +++ b/vendor/toml_edit/src/document.rs @@ -0,0 +1,113 @@ +use std::str::FromStr; + +use crate::parser; +use crate::table::Iter; +use crate::{Item, RawString, Table}; + +/// Type representing a TOML document +#[derive(Debug, Clone)] +pub struct Document { + pub(crate) root: Item, + // Trailing comments and whitespaces + pub(crate) trailing: RawString, + pub(crate) original: Option<String>, + pub(crate) span: Option<std::ops::Range<usize>>, +} + +impl Document { + /// Creates an empty document + pub fn new() -> Self { + Default::default() + } + + /// Returns a reference to the root item. + pub fn as_item(&self) -> &Item { + &self.root + } + + /// Returns a mutable reference to the root item. + pub fn as_item_mut(&mut self) -> &mut Item { + &mut self.root + } + + /// Returns a reference to the root table. + pub fn as_table(&self) -> &Table { + self.root.as_table().expect("root should always be a table") + } + + /// Returns a mutable reference to the root table. + pub fn as_table_mut(&mut self) -> &mut Table { + self.root + .as_table_mut() + .expect("root should always be a table") + } + + /// Returns an iterator over the root table. + pub fn iter(&self) -> Iter<'_> { + self.as_table().iter() + } + + /// Set whitespace after last element + pub fn set_trailing(&mut self, trailing: impl Into<RawString>) { + self.trailing = trailing.into(); + } + + /// Whitespace after last element + pub fn trailing(&self) -> &RawString { + &self.trailing + } + + /// # Panics + /// + /// If run on on a `Document` not generated by the parser + pub(crate) fn despan(&mut self) { + self.span = None; + self.root.despan(self.original.as_deref().unwrap()); + self.trailing.despan(self.original.as_deref().unwrap()); + } +} + +impl Default for Document { + fn default() -> Self { + Self { + root: Item::Table(Table::with_pos(Some(0))), + trailing: Default::default(), + original: Default::default(), + span: Default::default(), + } + } +} + +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)?; + d.despan(); + Ok(d) + } +} + +impl std::ops::Deref for Document { + type Target = Table; + + fn deref(&self) -> &Self::Target { + self.as_table() + } +} + +impl std::ops::DerefMut for Document { + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_table_mut() + } +} + +impl From<Table> for Document { + fn from(root: Table) -> Self { + Self { + root: Item::Table(root), + ..Default::default() + } + } +} diff --git a/vendor/toml_edit/src/encode.rs b/vendor/toml_edit/src/encode.rs new file mode 100644 index 0000000..3e98448 --- /dev/null +++ b/vendor/toml_edit/src/encode.rs @@ -0,0 +1,569 @@ +use std::borrow::Cow; +use std::fmt::{Display, Formatter, Result, Write}; + +use toml_datetime::*; + +use crate::document::Document; +use crate::inline_table::DEFAULT_INLINE_KEY_DECOR; +use crate::key::Key; +use crate::repr::{Formatted, Repr, ValueRepr}; +use crate::table::{DEFAULT_KEY_DECOR, DEFAULT_KEY_PATH_DECOR, DEFAULT_TABLE_DECOR}; +use crate::value::{ + DEFAULT_LEADING_VALUE_DECOR, DEFAULT_TRAILING_VALUE_DECOR, DEFAULT_VALUE_DECOR, +}; +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; +} + +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)?; + } else { + let repr = self.display_repr(); + write!(buf, "{}", repr)?; + }; + + decor.suffix_encode(buf, input, default_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 + }; + + if !first { + write!(buf, ".")?; + } + key.encode(buf, input, (prefix, suffix))?; + } + 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 + }; + + if !first { + write!(buf, ".")?; + } + key.encode(buf, input, (prefix, suffix))?; + } + 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)?; + }; + + 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() { + write!(buf, ",")?; + } + + self.trailing().encode_with_default(buf, input, "")?; + write!(buf, "]")?; + decor.suffix_encode(buf, input, default_decor.1)?; + + 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)?; + } + + write!(buf, "}}")?; + decor.suffix_encode(buf, input, default_decor.1)?; + + 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), + } + } +} + +impl Display for Document { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let mut path = Vec::new(); + let mut last_position = 0; + let mut tables = Vec::new(); + visit_nested_tables(self.as_table(), &mut path, false, &mut |t, p, is_array| { + if let Some(pos) = t.position() { + last_position = pos; + } + tables.push((last_position, t, p.clone(), is_array)); + Ok(()) + }) + .unwrap(); + + tables.sort_by_key(|&(id, _, _, _)| id); + let mut first_table = true; + for (_, table, path, is_array) in tables { + visit_table( + f, + self.original.as_deref(), + table, + &path, + is_array, + &mut first_table, + )?; + } + self.trailing() + .encode_with_default(f, self.original.as_deref(), "") + } +} + +fn visit_nested_tables<'t, F>( + table: &'t Table, + path: &mut Vec<Key>, + is_array_of_tables: bool, + callback: &mut F, +) -> Result +where + F: FnMut(&'t Table, &Vec<Key>, bool) -> Result, +{ + if !table.is_dotted() { + callback(table, path, is_array_of_tables)?; + } + + 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(); + } + path.push(key); + visit_nested_tables(t, path, false, callback)?; + path.pop(); + } + Item::ArrayOfTables(ref a) => { + for t in a.iter() { + let key = kv.key.clone(); + path.push(key); + visit_nested_tables(t, path, true, callback)?; + path.pop(); + } + } + _ => {} + } + } + Ok(()) +} + +fn visit_table( + buf: &mut dyn Write, + input: Option<&str>, + table: &Table, + path: &[Key], + is_array_of_tables: bool, + first_table: &mut bool, +) -> Result { + let children = table.get_values(); + // We are intentionally hiding implicit tables without any tables nested under them (ie + // `table.is_empty()` which is in contrast to `table.get_values().is_empty()`). We are + // trusting the user that an empty implicit table is not semantically meaningful + // + // This allows a user to delete all tables under this implicit table and the implicit table + // will disappear. + // + // However, this means that users need to take care in deciding what tables get marked as + // implicit. + let is_visible_std_table = !(table.implicit && children.is_empty()); + + if path.is_empty() { + // don't print header for the root node + if !children.is_empty() { + *first_table = false; + } + } else if is_array_of_tables { + let default_decor = if *first_table { + *first_table = false; + ("", DEFAULT_TABLE_DECOR.1) + } else { + DEFAULT_TABLE_DECOR + }; + table.decor.prefix_encode(buf, input, default_decor.0)?; + write!(buf, "[[")?; + path.encode(buf, input, DEFAULT_KEY_PATH_DECOR)?; + write!(buf, "]]")?; + table.decor.suffix_encode(buf, input, default_decor.1)?; + writeln!(buf)?; + } else if is_visible_std_table { + let default_decor = if *first_table { + *first_table = false; + ("", DEFAULT_TABLE_DECOR.1) + } else { + DEFAULT_TABLE_DECOR + }; + table.decor.prefix_encode(buf, input, default_decor.0)?; + write!(buf, "[")?; + path.encode(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)?; + write!(buf, "=")?; + value.encode(buf, input, DEFAULT_VALUE_DECOR)?; + writeln!(buf)?; + } + Ok(()) +} + +impl ValueRepr for String { + fn to_repr(&self) -> Repr { + to_string_repr(self, None, None) + } +} + +pub(crate) fn to_string_repr( + value: &str, + style: Option<StringStyle>, + literal: Option<bool>, +) -> Repr { + let (style, literal) = match (style, literal) { + (Some(style), Some(literal)) => (style, literal), + (_, Some(literal)) => (infer_style(value).0, literal), + (Some(style), _) => (style, infer_style(value).1), + (_, _) => infer_style(value), + }; + + let mut output = String::with_capacity(value.len() * 2); + if literal { + output.push_str(style.literal_start()); + output.push_str(value); + output.push_str(style.literal_end()); + } else { + output.push_str(style.standard_start()); + for ch in value.chars() { + match ch { + '\u{8}' => output.push_str("\\b"), + '\u{9}' => output.push_str("\\t"), + '\u{a}' => match style { + StringStyle::NewlineTriple => output.push('\n'), + StringStyle::OnelineSingle => output.push_str("\\n"), + _ => unreachable!(), + }, + '\u{c}' => output.push_str("\\f"), + '\u{d}' => output.push_str("\\r"), + '\u{22}' => output.push_str("\\\""), + '\u{5c}' => output.push_str("\\\\"), + c if c <= '\u{1f}' || c == '\u{7f}' => { + write!(output, "\\u{:04X}", ch as u32).unwrap(); + } + ch => output.push(ch), + } + } + output.push_str(style.standard_end()); + } + + Repr::new_unchecked(output) +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) enum StringStyle { + NewlineTriple, + OnelineTriple, + OnelineSingle, +} + +impl StringStyle { + fn literal_start(self) -> &'static str { + match self { + Self::NewlineTriple => "'''\n", + Self::OnelineTriple => "'''", + Self::OnelineSingle => "'", + } + } + fn literal_end(self) -> &'static str { + match self { + Self::NewlineTriple => "'''", + Self::OnelineTriple => "'''", + Self::OnelineSingle => "'", + } + } + + fn standard_start(self) -> &'static str { + match self { + Self::NewlineTriple => "\"\"\"\n", + // note: OnelineTriple can happen if do_pretty wants to do + // '''it's one line''' + // but literal == false + Self::OnelineTriple | Self::OnelineSingle => "\"", + } + } + + fn standard_end(self) -> &'static str { + match self { + Self::NewlineTriple => "\"\"\"", + // note: OnelineTriple can happen if do_pretty wants to do + // '''it's one line''' + // but literal == false + 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: + // - 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; + let mut found_singles = 0; + let mut prefer_literal = false; + let mut can_be_pretty = true; + + for ch in value.chars() { + if can_be_pretty { + if ch == '\'' { + found_singles += 1; + if found_singles >= 3 { + can_be_pretty = false; + } + } else { + if found_singles > max_found_singles { + max_found_singles = found_singles; + } + found_singles = 0 + } + match ch { + '\t' => {} + '\\' => { + prefer_literal = true; + } + '\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::NewlineTriple; + } + } + } + if found_singles > 0 && value.ends_with('\'') { + // We cannot escape the ending quote so we must use """ + can_be_pretty = false; + } + if !prefer_literal { + can_be_pretty = false; + } + if !can_be_pretty { + debug_assert!(ty != StringStyle::OnelineTriple); + return (ty, false); + } + if found_singles > max_found_singles { + max_found_singles = found_singles; + } + 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::OnelineTriple; + } + (ty, true) +} + +impl ValueRepr for i64 { + fn to_repr(&self) -> Repr { + Repr::new_unchecked(self.to_string()) + } +} + +impl ValueRepr for f64 { + fn to_repr(&self) -> Repr { + to_f64_repr(*self) + } +} + +fn to_f64_repr(f: f64) -> Repr { + let repr = match (f.is_sign_negative(), f.is_nan(), f == 0.0) { + (true, true, _) => "-nan".to_owned(), + (false, true, _) => "nan".to_owned(), + (true, false, true) => "-0.0".to_owned(), + (false, false, true) => "0.0".to_owned(), + (_, false, false) => { + if f % 1.0 == 0.0 { + format!("{}.0", f) + } else { + format!("{}", f) + } + } + }; + Repr::new_unchecked(repr) +} + +impl ValueRepr for bool { + fn to_repr(&self) -> Repr { + Repr::new_unchecked(self.to_string()) + } +} + +impl ValueRepr for Datetime { + fn to_repr(&self) -> Repr { + Repr::new_unchecked(self.to_string()) + } +} diff --git a/vendor/toml_edit/src/index.rs b/vendor/toml_edit/src/index.rs new file mode 100644 index 0000000..276db79 --- /dev/null +++ b/vendor/toml_edit/src/index.rs @@ -0,0 +1,156 @@ +use std::ops; + +use crate::document::Document; +use crate::key::Key; +use crate::table::TableKeyValue; +use crate::{value, InlineTable, InternalString, Item, Table, Value}; + +// copied from +// https://github.com/serde-rs/json/blob/master/src/value/index.rs + +pub trait Index: crate::private::Sealed { + #[doc(hidden)] + fn index<'v>(&self, val: &'v Item) -> Option<&'v Item>; + #[doc(hidden)] + fn index_mut<'v>(&self, val: &'v mut Item) -> Option<&'v mut Item>; +} + +impl Index for usize { + fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> { + match *v { + Item::ArrayOfTables(ref aot) => aot.values.get(*self), + Item::Value(ref a) if a.is_array() => a.as_array().and_then(|a| a.values.get(*self)), + _ => None, + } + } + fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> { + match *v { + Item::ArrayOfTables(ref mut vec) => vec.values.get_mut(*self), + Item::Value(ref mut a) => a.as_array_mut().and_then(|a| a.values.get_mut(*self)), + _ => None, + } + } +} + +impl Index for str { + fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> { + match *v { + Item::Table(ref t) => t.get(self), + Item::Value(ref v) => v + .as_inline_table() + .and_then(|t| t.items.get(self)) + .and_then(|kv| { + if !kv.value.is_none() { + Some(&kv.value) + } else { + None + } + }), + _ => None, + } + } + fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> { + if let Item::None = *v { + let mut t = InlineTable::default(); + t.items.insert( + InternalString::from(self), + TableKeyValue::new(Key::new(self), Item::None), + ); + *v = value(Value::InlineTable(t)); + } + match *v { + Item::Table(ref mut t) => Some(t.entry(self).or_insert(Item::None)), + Item::Value(ref mut v) => v.as_inline_table_mut().map(|t| { + &mut t + .items + .entry(InternalString::from(self)) + .or_insert_with(|| TableKeyValue::new(Key::new(self), Item::None)) + .value + }), + _ => None, + } + } +} + +impl Index for String { + fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> { + self[..].index(v) + } + fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> { + self[..].index_mut(v) + } +} + +impl<'a, T: ?Sized> Index for &'a T +where + T: Index, +{ + fn index<'v>(&self, v: &'v Item) -> Option<&'v Item> { + (**self).index(v) + } + fn index_mut<'v>(&self, v: &'v mut Item) -> Option<&'v mut Item> { + (**self).index_mut(v) + } +} + +impl<I> ops::Index<I> for Item +where + I: Index, +{ + type Output = Item; + + fn index(&self, index: I) -> &Item { + index.index(self).expect("index not found") + } +} + +impl<I> ops::IndexMut<I> for Item +where + I: Index, +{ + fn index_mut(&mut self, index: I) -> &mut Item { + index.index_mut(self).expect("index not found") + } +} + +impl<'s> ops::Index<&'s str> for Table { + type Output = Item; + + fn index(&self, key: &'s str) -> &Item { + self.get(key).expect("index not found") + } +} + +impl<'s> ops::IndexMut<&'s str> for Table { + fn index_mut(&mut self, key: &'s str) -> &mut Item { + self.entry(key).or_insert(Item::None) + } +} + +impl<'s> ops::Index<&'s str> for InlineTable { + type Output = Value; + + fn index(&self, key: &'s str) -> &Value { + self.get(key).expect("index not found") + } +} + +impl<'s> ops::IndexMut<&'s str> for InlineTable { + fn index_mut(&mut self, key: &'s str) -> &mut Value { + self.get_mut(key).expect("index not found") + } +} + +impl<'s> ops::Index<&'s str> for Document { + type Output = Item; + + fn index(&self, key: &'s str) -> &Item { + self.root.index(key) + } +} + +impl<'s> ops::IndexMut<&'s str> for Document { + fn index_mut(&mut self, key: &'s str) -> &mut Item { + self.root.index_mut(key) + } +} diff --git a/vendor/toml_edit/src/inline_table.rs b/vendor/toml_edit/src/inline_table.rs new file mode 100644 index 0000000..3dc6c0c --- /dev/null +++ b/vendor/toml_edit/src/inline_table.rs @@ -0,0 +1,679 @@ +use std::iter::FromIterator; + +use crate::key::Key; +use crate::repr::Decor; +use crate::table::{Iter, IterMut, KeyValuePairs, TableKeyValue, TableLike}; +use crate::{InternalString, Item, KeyMut, RawString, Table, Value}; + +/// Type representing a TOML inline table, +/// payload of the `Value::InlineTable` variant +#[derive(Debug, Default, Clone)] +pub struct InlineTable { + // `preamble` represents whitespaces in an empty table + preamble: RawString, + // prefix before `{` and suffix after `}` + decor: Decor, + pub(crate) span: Option<std::ops::Range<usize>>, + // whether this is a proxy for dotted keys + dotted: bool, + pub(crate) items: KeyValuePairs, +} + +/// Constructors +/// +/// See also `FromIterator` +impl InlineTable { + /// Creates an empty table. + pub fn new() -> Self { + Default::default() + } + + pub(crate) fn with_pairs(items: KeyValuePairs) -> Self { + Self { + items, + ..Default::default() + } + } + + /// Convert to a table + pub fn into_table(self) -> Table { + let mut t = Table::with_pairs(self.items); + t.fmt(); + t + } +} + +/// Formatting +impl InlineTable { + /// Get key/values for values that are visually children of this table + /// + /// For example, this will return dotted keys + pub fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> { + let mut values = Vec::new(); + let root = Vec::new(); + self.append_values(&root, &mut values); + values + } + + pub(crate) fn append_values<'s, 'c>( + &'s self, + parent: &[&'s Key], + values: &'c mut Vec<(Vec<&'s Key>, &'s Value)>, + ) { + for value in self.items.values() { + let mut path = parent.to_vec(); + path.push(&value.key); + match &value.value { + Item::Value(Value::InlineTable(table)) if table.is_dotted() => { + table.append_values(&path, values); + } + Item::Value(value) => { + values.push((path, value)); + } + _ => {} + } + } + } + + /// Auto formats the table. + pub fn fmt(&mut self) { + decorate_inline_table(self); + } + + /// Sorts the key/value pairs by key. + pub fn sort_values(&mut self) { + // Assuming standard tables have their position set and this won't negatively impact them + self.items.sort_keys(); + for kv in self.items.values_mut() { + match &mut kv.value { + Item::Value(Value::InlineTable(table)) if table.is_dotted() => { + table.sort_values(); + } + _ => {} + } + } + } + + /// Sort Key/Value Pairs of the table using the using the comparison function `compare`. + /// + /// The comparison function receives two key and value pairs to compare (you can sort by keys or + /// values or their combination as needed). + pub fn sort_values_by<F>(&mut self, mut compare: F) + where + F: FnMut(&Key, &Value, &Key, &Value) -> std::cmp::Ordering, + { + self.sort_values_by_internal(&mut compare); + } + + fn sort_values_by_internal<F>(&mut self, compare: &mut F) + where + F: FnMut(&Key, &Value, &Key, &Value) -> std::cmp::Ordering, + { + let modified_cmp = |_: &InternalString, + val1: &TableKeyValue, + _: &InternalString, + val2: &TableKeyValue| + -> std::cmp::Ordering { + match (val1.value.as_value(), val2.value.as_value()) { + (Some(v1), Some(v2)) => compare(&val1.key, v1, &val2.key, v2), + (Some(_), None) => std::cmp::Ordering::Greater, + (None, Some(_)) => std::cmp::Ordering::Less, + (None, None) => std::cmp::Ordering::Equal, + } + }; + + self.items.sort_by(modified_cmp); + for kv in self.items.values_mut() { + match &mut kv.value { + Item::Value(Value::InlineTable(table)) if table.is_dotted() => { + table.sort_values_by_internal(compare); + } + _ => {} + } + } + } + + /// Change this table's dotted status + pub fn set_dotted(&mut self, yes: bool) { + self.dotted = yes; + } + + /// Check if this is a wrapper for dotted keys, rather than a standard table + pub fn is_dotted(&self) -> bool { + self.dotted + } + + /// Returns the surrounding whitespace + pub fn decor_mut(&mut self) -> &mut Decor { + &mut self.decor + } + + /// Returns the surrounding whitespace + pub fn decor(&self) -> &Decor { + &self.decor + } + + /// Returns the decor associated with a given key of the table. + pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { + self.items.get_mut(key).map(|kv| &mut kv.key.decor) + } + + /// Returns the decor associated with a given key of the table. + pub fn key_decor(&self, key: &str) -> Option<&Decor> { + self.items.get(key).map(|kv| &kv.key.decor) + } + + /// Set whitespace after before element + pub fn set_preamble(&mut self, preamble: impl Into<RawString>) { + self.preamble = preamble.into(); + } + + /// Whitespace after before element + pub fn preamble(&self) -> &RawString { + &self.preamble + } + + /// Returns the location within the original document + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + self.span.clone() + } + + pub(crate) fn despan(&mut self, input: &str) { + self.span = None; + self.decor.despan(input); + self.preamble.despan(input); + for kv in self.items.values_mut() { + kv.key.despan(input); + kv.value.despan(input); + } + } +} + +impl InlineTable { + /// Returns an iterator over key/value pairs. + pub fn iter(&self) -> InlineTableIter<'_> { + Box::new( + self.items + .iter() + .filter(|&(_, kv)| kv.value.is_value()) + .map(|(k, kv)| (&k[..], kv.value.as_value().unwrap())), + ) + } + + /// Returns an iterator over key/value pairs. + pub fn iter_mut(&mut self) -> InlineTableIterMut<'_> { + Box::new( + self.items + .iter_mut() + .filter(|(_, kv)| kv.value.is_value()) + .map(|(_, kv)| (kv.key.as_mut(), kv.value.as_value_mut().unwrap())), + ) + } + + /// Returns the number of key/value pairs. + pub fn len(&self) -> usize { + self.iter().count() + } + + /// Returns true iff the table is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Clears the table, removing all key-value pairs. Keeps the allocated memory for reuse. + pub fn clear(&mut self) { + self.items.clear() + } + + /// Gets the given key's corresponding entry in the Table for in-place manipulation. + pub fn entry(&'_ mut self, key: impl Into<InternalString>) -> InlineEntry<'_> { + match self.items.entry(key.into()) { + indexmap::map::Entry::Occupied(mut entry) => { + // Ensure it is a `Value` to simplify `InlineOccupiedEntry`'s code. + let scratch = std::mem::take(&mut entry.get_mut().value); + let scratch = Item::Value( + scratch + .into_value() + // HACK: `Item::None` is a corner case of a corner case, let's just pick a + // "safe" value + .unwrap_or_else(|_| Value::InlineTable(Default::default())), + ); + entry.get_mut().value = scratch; + + InlineEntry::Occupied(InlineOccupiedEntry { entry }) + } + indexmap::map::Entry::Vacant(entry) => { + InlineEntry::Vacant(InlineVacantEntry { entry, key: None }) + } + } + } + + /// Gets the given key's corresponding entry in the Table for in-place manipulation. + pub fn entry_format<'a>(&'a mut self, key: &Key) -> InlineEntry<'a> { + // Accept a `&Key` to be consistent with `entry` + match self.items.entry(key.get().into()) { + indexmap::map::Entry::Occupied(mut entry) => { + // Ensure it is a `Value` to simplify `InlineOccupiedEntry`'s code. + let scratch = std::mem::take(&mut entry.get_mut().value); + let scratch = Item::Value( + scratch + .into_value() + // HACK: `Item::None` is a corner case of a corner case, let's just pick a + // "safe" value + .unwrap_or_else(|_| Value::InlineTable(Default::default())), + ); + entry.get_mut().value = scratch; + + InlineEntry::Occupied(InlineOccupiedEntry { entry }) + } + indexmap::map::Entry::Vacant(entry) => InlineEntry::Vacant(InlineVacantEntry { + entry, + key: Some(key.clone()), + }), + } + } + /// Return an optional reference to the value at the given the key. + pub fn get(&self, key: &str) -> Option<&Value> { + self.items.get(key).and_then(|kv| kv.value.as_value()) + } + + /// Return an optional mutable reference to the value at the given the key. + pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> { + self.items + .get_mut(key) + .and_then(|kv| kv.value.as_value_mut()) + } + + /// Return references to the key-value pair stored for key, if it is present, else None. + pub fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { + self.items.get(key).and_then(|kv| { + if !kv.value.is_none() { + Some((&kv.key, &kv.value)) + } else { + None + } + }) + } + + /// Return mutable references to the key-value pair stored for key, if it is present, else None. + pub fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> { + self.items.get_mut(key).and_then(|kv| { + if !kv.value.is_none() { + Some((kv.key.as_mut(), &mut kv.value)) + } else { + None + } + }) + } + + /// Returns true iff the table contains given key. + pub fn contains_key(&self, key: &str) -> bool { + if let Some(kv) = self.items.get(key) { + kv.value.is_value() + } else { + false + } + } + + /// Inserts a key/value pair if the table does not contain the key. + /// Returns a mutable reference to the corresponding value. + pub fn get_or_insert<V: Into<Value>>( + &mut self, + key: impl Into<InternalString>, + value: V, + ) -> &mut Value { + let key = key.into(); + self.items + .entry(key.clone()) + .or_insert(TableKeyValue::new(Key::new(key), Item::Value(value.into()))) + .value + .as_value_mut() + .expect("non-value type in inline table") + } + + /// Inserts a key-value pair into the map. + pub fn insert(&mut self, key: impl Into<InternalString>, value: Value) -> Option<Value> { + let key = key.into(); + let kv = TableKeyValue::new(Key::new(key.clone()), Item::Value(value)); + self.items + .insert(key, kv) + .and_then(|kv| kv.value.into_value().ok()) + } + + /// Inserts a key-value pair into the map. + pub fn insert_formatted(&mut self, key: &Key, value: Value) -> Option<Value> { + let kv = TableKeyValue::new(key.to_owned(), Item::Value(value)); + self.items + .insert(InternalString::from(key.get()), kv) + .filter(|kv| kv.value.is_value()) + .map(|kv| kv.value.into_value().unwrap()) + } + + /// Removes an item given the key. + pub fn remove(&mut self, key: &str) -> Option<Value> { + self.items + .shift_remove(key) + .and_then(|kv| kv.value.into_value().ok()) + } + + /// Removes a key from the map, returning the stored key and value if the key was previously in the map. + pub fn remove_entry(&mut self, key: &str) -> Option<(Key, Value)> { + self.items.shift_remove(key).and_then(|kv| { + let key = kv.key; + kv.value.into_value().ok().map(|value| (key, value)) + }) + } + + /// Retains only the elements specified by the `keep` predicate. + /// + /// In other words, remove all pairs `(key, value)` for which + /// `keep(&key, &mut value)` returns `false`. + /// + /// The elements are visited in iteration order. + pub fn retain<F>(&mut self, mut keep: F) + where + F: FnMut(&str, &mut Value) -> bool, + { + self.items.retain(|key, item| { + item.value + .as_value_mut() + .map(|value| keep(key, value)) + .unwrap_or(false) + }); + } +} + +impl std::fmt::Display for InlineTable { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + crate::encode::Encode::encode(self, f, None, ("", "")) + } +} + +impl<K: Into<Key>, V: Into<Value>> Extend<(K, V)> for InlineTable { + fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) { + for (key, value) in iter { + let key = key.into(); + let value = Item::Value(value.into()); + let value = TableKeyValue::new(key, value); + self.items + .insert(InternalString::from(value.key.get()), value); + } + } +} + +impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for InlineTable { + fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator<Item = (K, V)>, + { + let mut table = InlineTable::new(); + table.extend(iter); + table + } +} + +impl IntoIterator for InlineTable { + type Item = (InternalString, Value); + type IntoIter = InlineTableIntoIter; + + fn into_iter(self) -> Self::IntoIter { + Box::new( + self.items + .into_iter() + .filter(|(_, kv)| kv.value.is_value()) + .map(|(k, kv)| (k, kv.value.into_value().unwrap())), + ) + } +} + +impl<'s> IntoIterator for &'s InlineTable { + type Item = (&'s str, &'s Value); + type IntoIter = InlineTableIter<'s>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +fn decorate_inline_table(table: &mut InlineTable) { + for (key_decor, 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())) + { + key_decor.clear(); + value.decor_mut().clear(); + } +} + +/// An owned iterator type over key/value pairs of an inline table. +pub type InlineTableIntoIter = Box<dyn Iterator<Item = (InternalString, Value)>>; +/// An iterator type over key/value pairs of an inline table. +pub type InlineTableIter<'a> = Box<dyn Iterator<Item = (&'a str, &'a Value)> + 'a>; +/// A mutable iterator type over key/value pairs of an inline table. +pub type InlineTableIterMut<'a> = Box<dyn Iterator<Item = (KeyMut<'a>, &'a mut Value)> + 'a>; + +impl TableLike for InlineTable { + fn iter(&self) -> Iter<'_> { + Box::new(self.items.iter().map(|(key, kv)| (&key[..], &kv.value))) + } + fn iter_mut(&mut self) -> IterMut<'_> { + Box::new( + self.items + .iter_mut() + .map(|(_, kv)| (kv.key.as_mut(), &mut kv.value)), + ) + } + fn clear(&mut self) { + self.clear(); + } + fn entry<'a>(&'a mut self, key: &str) -> crate::Entry<'a> { + // Accept a `&str` rather than an owned type to keep `InternalString`, well, internal + match self.items.entry(key.into()) { + indexmap::map::Entry::Occupied(entry) => { + crate::Entry::Occupied(crate::OccupiedEntry { entry }) + } + indexmap::map::Entry::Vacant(entry) => { + crate::Entry::Vacant(crate::VacantEntry { entry, key: None }) + } + } + } + fn entry_format<'a>(&'a mut self, key: &Key) -> crate::Entry<'a> { + // Accept a `&Key` to be consistent with `entry` + match self.items.entry(key.get().into()) { + indexmap::map::Entry::Occupied(entry) => { + crate::Entry::Occupied(crate::OccupiedEntry { entry }) + } + indexmap::map::Entry::Vacant(entry) => crate::Entry::Vacant(crate::VacantEntry { + entry, + key: Some(key.to_owned()), + }), + } + } + fn get<'s>(&'s self, key: &str) -> Option<&'s Item> { + self.items.get(key).map(|kv| &kv.value) + } + fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> { + self.items.get_mut(key).map(|kv| &mut kv.value) + } + fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { + self.get_key_value(key) + } + fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> { + self.get_key_value_mut(key) + } + fn contains_key(&self, key: &str) -> bool { + self.contains_key(key) + } + fn insert(&mut self, key: &str, value: Item) -> Option<Item> { + self.insert(key, value.into_value().unwrap()) + .map(Item::Value) + } + fn remove(&mut self, key: &str) -> Option<Item> { + self.remove(key).map(Item::Value) + } + + fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> { + self.get_values() + } + fn fmt(&mut self) { + self.fmt() + } + fn sort_values(&mut self) { + self.sort_values() + } + fn set_dotted(&mut self, yes: bool) { + self.set_dotted(yes) + } + fn is_dotted(&self) -> bool { + self.is_dotted() + } + + fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { + self.key_decor_mut(key) + } + fn key_decor(&self, key: &str) -> Option<&Decor> { + self.key_decor(key) + } +} + +// `{ key1 = value1, ... }` +pub(crate) const DEFAULT_INLINE_KEY_DECOR: (&str, &str) = (" ", " "); + +/// A view into a single location in a map, which may be vacant or occupied. +pub enum InlineEntry<'a> { + /// An occupied Entry. + Occupied(InlineOccupiedEntry<'a>), + /// A vacant Entry. + Vacant(InlineVacantEntry<'a>), +} + +impl<'a> InlineEntry<'a> { + /// Returns the entry key + /// + /// # Examples + /// + /// ``` + /// use toml_edit::Table; + /// + /// let mut map = Table::new(); + /// + /// assert_eq!("hello", map.entry("hello").key()); + /// ``` + pub fn key(&self) -> &str { + match self { + InlineEntry::Occupied(e) => e.key(), + InlineEntry::Vacant(e) => e.key(), + } + } + + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + pub fn or_insert(self, default: Value) -> &'a mut Value { + match self { + InlineEntry::Occupied(entry) => entry.into_mut(), + InlineEntry::Vacant(entry) => entry.insert(default), + } + } + + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with<F: FnOnce() -> Value>(self, default: F) -> &'a mut Value { + match self { + InlineEntry::Occupied(entry) => entry.into_mut(), + InlineEntry::Vacant(entry) => entry.insert(default()), + } + } +} + +/// A view into a single occupied location in a `IndexMap`. +pub struct InlineOccupiedEntry<'a> { + entry: indexmap::map::OccupiedEntry<'a, InternalString, TableKeyValue>, +} + +impl<'a> InlineOccupiedEntry<'a> { + /// Gets a reference to the entry key + /// + /// # Examples + /// + /// ``` + /// use toml_edit::Table; + /// + /// let mut map = Table::new(); + /// + /// assert_eq!("foo", map.entry("foo").key()); + /// ``` + pub fn key(&self) -> &str { + self.entry.key().as_str() + } + + /// Gets a mutable reference to the entry key + pub fn key_mut(&mut self) -> KeyMut<'_> { + self.entry.get_mut().key.as_mut() + } + + /// Gets a reference to the value in the entry. + pub fn get(&self) -> &Value { + self.entry.get().value.as_value().unwrap() + } + + /// Gets a mutable reference to the value in the entry. + pub fn get_mut(&mut self) -> &mut Value { + self.entry.get_mut().value.as_value_mut().unwrap() + } + + /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// with a lifetime bound to the map itself + pub fn into_mut(self) -> &'a mut Value { + self.entry.into_mut().value.as_value_mut().unwrap() + } + + /// Sets the value of the entry, and returns the entry's old value + pub fn insert(&mut self, value: Value) -> Value { + let mut value = Item::Value(value); + std::mem::swap(&mut value, &mut self.entry.get_mut().value); + value.into_value().unwrap() + } + + /// Takes the value out of the entry, and returns it + pub fn remove(self) -> Value { + self.entry.shift_remove().value.into_value().unwrap() + } +} + +/// A view into a single empty location in a `IndexMap`. +pub struct InlineVacantEntry<'a> { + entry: indexmap::map::VacantEntry<'a, InternalString, TableKeyValue>, + key: Option<Key>, +} + +impl<'a> InlineVacantEntry<'a> { + /// Gets a reference to the entry key + /// + /// # Examples + /// + /// ``` + /// use toml_edit::Table; + /// + /// let mut map = Table::new(); + /// + /// assert_eq!("foo", map.entry("foo").key()); + /// ``` + pub fn key(&self) -> &str { + self.entry.key().as_str() + } + + /// Sets the value of the entry with the VacantEntry's key, + /// and returns a mutable reference to it + pub fn insert(self, value: Value) -> &'a mut Value { + let entry = self.entry; + let key = self.key.unwrap_or_else(|| Key::new(entry.key().as_str())); + let value = Item::Value(value); + entry + .insert(TableKeyValue::new(key, value)) + .value + .as_value_mut() + .unwrap() + } +} diff --git a/vendor/toml_edit/src/internal_string.rs b/vendor/toml_edit/src/internal_string.rs new file mode 100644 index 0000000..d4347d2 --- /dev/null +++ b/vendor/toml_edit/src/internal_string.rs @@ -0,0 +1,183 @@ +use std::borrow::Borrow; +use std::str::FromStr; + +/// Opaque string storage internal to `toml_edit` +#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct InternalString(Inner); + +#[cfg(feature = "kstring")] +type Inner = kstring::KString; +#[cfg(not(feature = "kstring"))] +type Inner = String; + +impl InternalString { + /// Create an empty string + pub fn new() -> Self { + InternalString(Inner::new()) + } + + /// Access the underlying string + #[inline] + pub fn as_str(&self) -> &str { + self.0.as_str() + } +} + +impl std::fmt::Debug for InternalString { + #[inline] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + self.0.fmt(formatter) + } +} + +impl std::ops::Deref for InternalString { + type Target = str; + + #[inline] + fn deref(&self) -> &str { + self.as_str() + } +} + +impl Borrow<str> for InternalString { + #[inline] + fn borrow(&self) -> &str { + self.as_str() + } +} + +impl AsRef<str> for InternalString { + #[inline] + fn as_ref(&self) -> &str { + self.as_str() + } +} + +impl From<&str> for InternalString { + #[inline] + fn from(s: &str) -> Self { + #[cfg(feature = "kstring")] + let inner = kstring::KString::from_ref(s); + #[cfg(not(feature = "kstring"))] + let inner = String::from(s); + + InternalString(inner) + } +} + +impl From<String> for InternalString { + #[inline] + fn from(s: String) -> Self { + #[allow(clippy::useless_conversion)] // handle any string type + InternalString(s.into()) + } +} + +impl From<&String> for InternalString { + #[inline] + fn from(s: &String) -> Self { + InternalString(s.into()) + } +} + +impl From<&InternalString> for InternalString { + #[inline] + fn from(s: &InternalString) -> Self { + s.clone() + } +} + +impl From<Box<str>> for InternalString { + #[inline] + fn from(s: Box<str>) -> Self { + InternalString(s.into()) + } +} + +impl FromStr for InternalString { + type Err = core::convert::Infallible; + #[inline] + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(Self::from(s)) + } +} + +impl std::fmt::Display for InternalString { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.as_str().fmt(f) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for InternalString { + #[inline] + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: serde::Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for InternalString { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_string(StringVisitor) + } +} + +#[cfg(feature = "serde")] +struct StringVisitor; + +#[cfg(feature = "serde")] +impl<'de> serde::de::Visitor<'de> for StringVisitor { + type Value = InternalString; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("a string") + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + Ok(InternalString::from(v)) + } + + fn visit_string<E>(self, v: String) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + Ok(InternalString::from(v)) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + match std::str::from_utf8(v) { + Ok(s) => Ok(InternalString::from(s)), + Err(_) => Err(serde::de::Error::invalid_value( + serde::de::Unexpected::Bytes(v), + &self, + )), + } + } + + fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E> + where + E: serde::de::Error, + { + match String::from_utf8(v) { + Ok(s) => Ok(InternalString::from(s)), + Err(e) => Err(serde::de::Error::invalid_value( + serde::de::Unexpected::Bytes(&e.into_bytes()), + &self, + )), + } + } +} diff --git a/vendor/toml_edit/src/item.rs b/vendor/toml_edit/src/item.rs new file mode 100644 index 0000000..2025fd9 --- /dev/null +++ b/vendor/toml_edit/src/item.rs @@ -0,0 +1,393 @@ +use std::str::FromStr; + +use toml_datetime::*; + +use crate::array_of_tables::ArrayOfTables; +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)] +pub enum Item { + /// Type representing none. + None, + /// Type representing value. + Value(Value), + /// Type representing table. + Table(Table), + /// Type representing array of tables. + ArrayOfTables(ArrayOfTables), +} + +impl Item { + /// Sets `self` to the given item iff `self` is none and + /// returns a mutable reference to `self`. + pub fn or_insert(&mut self, item: Item) -> &mut Item { + if self.is_none() { + *self = item + } + self + } +} + +// TODO: This should be generated by macro or derive +/// Downcasting +impl Item { + /// Text description of value type + pub fn type_name(&self) -> &'static str { + match self { + Item::None => "none", + Item::Value(v) => v.type_name(), + Item::Table(..) => "table", + Item::ArrayOfTables(..) => "array of tables", + } + } + + /// Index into a TOML array or map. A string index can be used to access a + /// value in a map, and a usize index can be used to access an element of an + /// array. + /// + /// Returns `None` if: + /// - The type of `self` does not match the type of the + /// index, for example if the index is a string and `self` is an array or a + /// number. + /// - The given key does not exist in the map + /// or the given index is not within the bounds of the array. + pub fn get<I: crate::index::Index>(&self, index: I) -> Option<&Item> { + index.index(self) + } + + /// Mutably index into a TOML array or map. A string index can be used to + /// access a value in a map, and a usize index can be used to access an + /// element of an array. + /// + /// Returns `None` if: + /// - The type of `self` does not match the type of the + /// index, for example if the index is a string and `self` is an array or a + /// number. + /// - The given key does not exist in the map + /// or the given index is not within the bounds of the array. + pub fn get_mut<I: crate::index::Index>(&mut self, index: I) -> Option<&mut Item> { + index.index_mut(self) + } + + /// Casts `self` to value. + pub fn as_value(&self) -> Option<&Value> { + match *self { + Item::Value(ref v) => Some(v), + _ => None, + } + } + /// Casts `self` to table. + pub fn as_table(&self) -> Option<&Table> { + match *self { + Item::Table(ref t) => Some(t), + _ => None, + } + } + /// Casts `self` to array of tables. + pub fn as_array_of_tables(&self) -> Option<&ArrayOfTables> { + match *self { + Item::ArrayOfTables(ref a) => Some(a), + _ => None, + } + } + /// Casts `self` to mutable value. + pub fn as_value_mut(&mut self) -> Option<&mut Value> { + match *self { + Item::Value(ref mut v) => Some(v), + _ => None, + } + } + /// Casts `self` to mutable table. + pub fn as_table_mut(&mut self) -> Option<&mut Table> { + match *self { + Item::Table(ref mut t) => Some(t), + _ => None, + } + } + /// Casts `self` to mutable array of tables. + pub fn as_array_of_tables_mut(&mut self) -> Option<&mut ArrayOfTables> { + match *self { + Item::ArrayOfTables(ref mut a) => Some(a), + _ => None, + } + } + /// Casts `self` to value. + pub fn into_value(self) -> Result<Value, Self> { + match self { + Item::None => Err(self), + Item::Value(v) => Ok(v), + Item::Table(v) => { + let v = v.into_inline_table(); + Ok(Value::InlineTable(v)) + } + Item::ArrayOfTables(v) => { + let v = v.into_array(); + Ok(Value::Array(v)) + } + } + } + /// In-place convert to a value + pub fn make_value(&mut self) { + let other = std::mem::take(self); + let other = other.into_value().map(Item::Value).unwrap_or(Item::None); + *self = other; + } + /// Casts `self` to table. + pub fn into_table(self) -> Result<Table, Self> { + match self { + Item::Table(t) => Ok(t), + Item::Value(Value::InlineTable(t)) => Ok(t.into_table()), + _ => Err(self), + } + } + /// Casts `self` to array of tables. + pub fn into_array_of_tables(self) -> Result<ArrayOfTables, Self> { + match self { + Item::ArrayOfTables(a) => Ok(a), + Item::Value(Value::Array(a)) => { + if a.is_empty() { + Err(Item::Value(Value::Array(a))) + } else if a.iter().all(|v| v.is_inline_table()) { + let mut aot = ArrayOfTables::new(); + aot.values = a.values; + for value in aot.values.iter_mut() { + value.make_item(); + } + Ok(aot) + } else { + Err(Item::Value(Value::Array(a))) + } + } + _ => Err(self), + } + } + // Starting private because the name is unclear + pub(crate) fn make_item(&mut self) { + let other = std::mem::take(self); + let other = match other.into_table().map(crate::Item::Table) { + Ok(i) => i, + Err(i) => i, + }; + let other = match other.into_array_of_tables().map(crate::Item::ArrayOfTables) { + Ok(i) => i, + Err(i) => i, + }; + *self = other; + } + /// Returns true iff `self` is a value. + pub fn is_value(&self) -> bool { + self.as_value().is_some() + } + /// Returns true iff `self` is a table. + pub fn is_table(&self) -> bool { + self.as_table().is_some() + } + /// Returns true iff `self` is an array of tables. + pub fn is_array_of_tables(&self) -> bool { + self.as_array_of_tables().is_some() + } + /// Returns true iff `self` is `None`. + pub fn is_none(&self) -> bool { + matches!(*self, Item::None) + } + + // Duplicate Value downcasting API + + /// Casts `self` to integer. + pub fn as_integer(&self) -> Option<i64> { + self.as_value().and_then(Value::as_integer) + } + + /// Returns true iff `self` is an integer. + pub fn is_integer(&self) -> bool { + self.as_integer().is_some() + } + + /// Casts `self` to float. + pub fn as_float(&self) -> Option<f64> { + self.as_value().and_then(Value::as_float) + } + + /// Returns true iff `self` is a float. + pub fn is_float(&self) -> bool { + self.as_float().is_some() + } + + /// Casts `self` to boolean. + pub fn as_bool(&self) -> Option<bool> { + self.as_value().and_then(Value::as_bool) + } + + /// Returns true iff `self` is a boolean. + pub fn is_bool(&self) -> bool { + self.as_bool().is_some() + } + + /// Casts `self` to str. + pub fn as_str(&self) -> Option<&str> { + self.as_value().and_then(Value::as_str) + } + + /// Returns true iff `self` is a string. + pub fn is_str(&self) -> bool { + self.as_str().is_some() + } + + /// Casts `self` to date-time. + pub fn as_datetime(&self) -> Option<&Datetime> { + self.as_value().and_then(Value::as_datetime) + } + + /// Returns true iff `self` is a date-time. + pub fn is_datetime(&self) -> bool { + self.as_datetime().is_some() + } + + /// Casts `self` to array. + pub fn as_array(&self) -> Option<&Array> { + self.as_value().and_then(Value::as_array) + } + + /// Casts `self` to mutable array. + pub fn as_array_mut(&mut self) -> Option<&mut Array> { + self.as_value_mut().and_then(Value::as_array_mut) + } + + /// Returns true iff `self` is an array. + pub fn is_array(&self) -> bool { + self.as_array().is_some() + } + + /// Casts `self` to inline table. + pub fn as_inline_table(&self) -> Option<&InlineTable> { + self.as_value().and_then(Value::as_inline_table) + } + + /// Casts `self` to mutable inline table. + pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> { + self.as_value_mut().and_then(Value::as_inline_table_mut) + } + + /// Returns true iff `self` is an inline table. + pub fn is_inline_table(&self) -> bool { + self.as_inline_table().is_some() + } + + /// Casts `self` to either a table or an inline table. + pub fn as_table_like(&self) -> Option<&dyn TableLike> { + self.as_table() + .map(|t| t as &dyn TableLike) + .or_else(|| self.as_inline_table().map(|t| t as &dyn TableLike)) + } + + /// Casts `self` to either a table or an inline table. + pub fn as_table_like_mut(&mut self) -> Option<&mut dyn TableLike> { + match self { + Item::Table(t) => Some(t as &mut dyn TableLike), + Item::Value(Value::InlineTable(t)) => Some(t as &mut dyn TableLike), + _ => None, + } + } + + /// Returns true iff `self` is either a table, or an inline table. + pub fn is_table_like(&self) -> bool { + self.as_table_like().is_some() + } + + /// Returns the location within the original document + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + match self { + Item::None => None, + Item::Value(v) => v.span(), + Item::Table(v) => v.span(), + Item::ArrayOfTables(v) => v.span(), + } + } + + pub(crate) fn despan(&mut self, input: &str) { + match self { + Item::None => {} + Item::Value(v) => v.despan(input), + Item::Table(v) => v.despan(input), + Item::ArrayOfTables(v) => v.despan(input), + } + } +} + +impl Clone for Item { + #[inline(never)] + fn clone(&self) -> Self { + match self { + Item::None => Item::None, + Item::Value(v) => Item::Value(v.clone()), + Item::Table(v) => Item::Table(v.clone()), + Item::ArrayOfTables(v) => Item::ArrayOfTables(v.clone()), + } + } +} + +impl Default for Item { + fn default() -> Self { + Item::None + } +} + +impl FromStr for Item { + type Err = crate::TomlError; + + /// Parses a value from a &str + fn from_str(s: &str) -> Result<Self, Self::Err> { + let value = s.parse::<Value>()?; + Ok(Item::Value(value)) + } +} + +impl std::fmt::Display for Item { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + Item::None => Ok(()), + Item::Value(v) => v.fmt(f), + Item::Table(v) => v.fmt(f), + Item::ArrayOfTables(v) => v.fmt(f), + } + } +} + +/// Returns a formatted value. +/// +/// Since formatting is part of a `Value`, the right hand side of the +/// assignment needs to be decorated with a space before the value. +/// The `value` function does just that. +/// +/// # Examples +/// ```rust +/// # use snapbox::assert_eq; +/// # use toml_edit::*; +/// let mut table = Table::default(); +/// let mut array = Array::default(); +/// array.push("hello"); +/// array.push("\\, world"); // \ is only allowed in a literal string +/// table["key1"] = value("value1"); +/// table["key2"] = value(42); +/// table["key3"] = value(array); +/// assert_eq(table.to_string(), +/// r#"key1 = "value1" +/// key2 = 42 +/// key3 = ["hello", '\, world'] +/// "#); +/// ``` +pub fn value<V: Into<Value>>(v: V) -> Item { + Item::Value(v.into()) +} + +/// Returns an empty table. +pub fn table() -> Item { + Item::Table(Table::new()) +} + +/// Returns an empty array of tables. +pub fn array() -> Item { + Item::ArrayOfTables(ArrayOfTables::new()) +} diff --git a/vendor/toml_edit/src/key.rs b/vendor/toml_edit/src/key.rs new file mode 100644 index 0000000..c1ee165 --- /dev/null +++ b/vendor/toml_edit/src/key.rs @@ -0,0 +1,344 @@ +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; + +/// Key as part of a Key/Value Pair or a table header. +/// +/// # Examples +/// +/// ```notrust +/// [dependencies."nom"] +/// version = "5.0" +/// 'literal key' = "nonsense" +/// "basic string key" = 42 +/// ``` +/// +/// There are 3 types of keys: +/// +/// 1. Bare keys (`version` and `dependencies`) +/// +/// 2. Basic quoted keys (`"basic string key"` and `"nom"`) +/// +/// 3. Literal quoted keys (`'literal key'`) +/// +/// For details see [toml spec](https://github.com/toml-lang/toml/#keyvalue-pair). +/// +/// To parse a key use `FromStr` trait implementation: `"string".parse::<Key>()`. +#[derive(Debug)] +pub struct Key { + key: InternalString, + pub(crate) repr: Option<Repr>, + pub(crate) decor: Decor, +} + +impl Key { + /// Create a new table key + pub fn new(key: impl Into<InternalString>) -> Self { + Self { + key: key.into(), + repr: None, + decor: Default::default(), + } + } + + /// Parse a TOML key expression + /// + /// Unlike `"".parse<Key>()`, this supports dotted keys. + pub fn parse(repr: &str) -> Result<Vec<Self>, crate::TomlError> { + Self::try_parse_path(repr) + } + + pub(crate) fn with_repr_unchecked(mut self, repr: Repr) -> Self { + self.repr = Some(repr); + self + } + + /// While creating the `Key`, add `Decor` to it + pub fn with_decor(mut self, decor: Decor) -> Self { + self.decor = decor; + self + } + + /// Access a mutable proxy for the `Key`. + pub fn as_mut(&mut self) -> KeyMut<'_> { + KeyMut { key: self } + } + + /// Returns the parsed key value. + pub fn get(&self) -> &str { + &self.key + } + + pub(crate) fn get_internal(&self) -> &InternalString { + &self.key + } + + /// Returns key raw representation, if available. + pub fn as_repr(&self) -> Option<&Repr> { + self.repr.as_ref() + } + + /// Returns the default raw representation. + pub fn default_repr(&self) -> Repr { + to_key_repr(&self.key) + } + + /// Returns a raw representation. + pub fn display_repr(&self) -> Cow<'_, str> { + self.as_repr() + .and_then(|r| r.as_raw().as_str()) + .map(Cow::Borrowed) + .unwrap_or_else(|| { + Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned()) + }) + } + + /// Returns the surrounding whitespace + pub fn decor_mut(&mut self) -> &mut Decor { + &mut self.decor + } + + /// Returns the surrounding whitespace + pub fn decor(&self) -> &Decor { + &self.decor + } + + /// Returns the location within the original document + #[cfg(feature = "serde")] + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + self.repr.as_ref().and_then(|r| r.span()) + } + + pub(crate) fn despan(&mut self, input: &str) { + self.decor.despan(input); + if let Some(repr) = &mut self.repr { + repr.despan(input) + } + } + + /// Auto formats the key. + pub fn fmt(&mut self) { + self.repr = Some(to_key_repr(&self.key)); + self.decor.clear(); + } + + fn try_parse_simple(s: &str) -> Result<Key, crate::TomlError> { + let mut key = parser::parse_key(s)?; + key.despan(s); + Ok(key) + } + + fn try_parse_path(s: &str) -> Result<Vec<Key>, crate::TomlError> { + let mut keys = parser::parse_key_path(s)?; + for key in &mut keys { + key.despan(s); + } + Ok(keys) + } +} + +impl Clone for Key { + #[inline(never)] + fn clone(&self) -> Self { + Self { + key: self.key.clone(), + repr: self.repr.clone(), + decor: self.decor.clone(), + } + } +} + +impl std::ops::Deref for Key { + type Target = str; + + fn deref(&self) -> &Self::Target { + self.get() + } +} + +impl std::hash::Hash for Key { + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + self.get().hash(state); + } +} + +impl Ord for Key { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.get().cmp(other.get()) + } +} + +impl PartialOrd for Key { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + Some(self.cmp(other)) + } +} + +impl Eq for Key {} + +impl PartialEq for Key { + #[inline] + fn eq(&self, other: &Key) -> bool { + PartialEq::eq(self.get(), other.get()) + } +} + +impl PartialEq<str> for Key { + #[inline] + fn eq(&self, other: &str) -> bool { + PartialEq::eq(self.get(), other) + } +} + +impl<'s> PartialEq<&'s str> for Key { + #[inline] + fn eq(&self, other: &&str) -> bool { + PartialEq::eq(self.get(), *other) + } +} + +impl PartialEq<String> for Key { + #[inline] + fn eq(&self, other: &String) -> bool { + PartialEq::eq(self.get(), other.as_str()) + } +} + +impl std::fmt::Display for Key { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + crate::encode::Encode::encode(self, f, None, ("", "")) + } +} + +impl FromStr for Key { + type Err = crate::TomlError; + + /// Tries to parse a key from a &str, + /// if fails, tries as basic quoted key (surrounds with "") + /// and then literal quoted key (surrounds with '') + fn from_str(s: &str) -> Result<Self, Self::Err> { + Key::try_parse_simple(s) + } +} + +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)) + } +} + +impl<'b> From<&'b str> for Key { + fn from(s: &'b str) -> Self { + Key::new(s) + } +} + +impl<'b> From<&'b String> for Key { + fn from(s: &'b String) -> Self { + Key::new(s) + } +} + +impl From<String> for Key { + fn from(s: String) -> Self { + Key::new(s) + } +} + +impl From<InternalString> for Key { + fn from(s: InternalString) -> Self { + Key::new(s) + } +} + +#[doc(hidden)] +impl From<Key> for InternalString { + fn from(key: Key) -> InternalString { + key.key + } +} + +/// A mutable reference to a `Key` +#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub struct KeyMut<'k> { + key: &'k mut Key, +} + +impl<'k> KeyMut<'k> { + /// Returns the parsed key value. + pub fn get(&self) -> &str { + self.key.get() + } + + /// Returns the raw representation, if available. + pub fn as_repr(&self) -> Option<&Repr> { + self.key.as_repr() + } + + /// Returns the default raw representation. + pub fn default_repr(&self) -> Repr { + self.key.default_repr() + } + + /// Returns a raw representation. + pub fn display_repr(&self) -> Cow<str> { + self.key.display_repr() + } + + /// Returns the surrounding whitespace + pub fn decor_mut(&mut self) -> &mut Decor { + self.key.decor_mut() + } + + /// Returns the surrounding whitespace + pub fn decor(&self) -> &Decor { + self.key.decor() + } + + /// Auto formats the key. + pub fn fmt(&mut self) { + self.key.fmt() + } +} + +impl<'k> std::ops::Deref for KeyMut<'k> { + type Target = str; + + fn deref(&self) -> &Self::Target { + self.get() + } +} + +impl<'s> PartialEq<str> for KeyMut<'s> { + #[inline] + fn eq(&self, other: &str) -> bool { + PartialEq::eq(self.get(), other) + } +} + +impl<'s> PartialEq<&'s str> for KeyMut<'s> { + #[inline] + fn eq(&self, other: &&str) -> bool { + PartialEq::eq(self.get(), *other) + } +} + +impl<'s> PartialEq<String> for KeyMut<'s> { + #[inline] + fn eq(&self, other: &String) -> bool { + PartialEq::eq(self.get(), other.as_str()) + } +} + +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) + } +} diff --git a/vendor/toml_edit/src/lib.rs b/vendor/toml_edit/src/lib.rs new file mode 100644 index 0000000..80c0ddd --- /dev/null +++ b/vendor/toml_edit/src/lib.rs @@ -0,0 +1,124 @@ +#![deny(missing_docs)] +// https://github.com/Marwes/combine/issues/172 +#![recursion_limit = "256"] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +//! # `toml_edit` +//! +//! This crate allows you to parse and modify toml +//! documents, while preserving comments, spaces *and +//! relative order* or items. +//! +//! If you also need the ease of a more traditional API, see the [`toml`] crate. +//! +//! # Example +//! +//! ```rust +//! use toml_edit::{Document, value}; +//! +//! let toml = r#" +//! "hello" = 'toml!' # comment +//! ['a'.b] +//! "#; +//! let mut doc = toml.parse::<Document>().expect("invalid doc"); +//! assert_eq!(doc.to_string(), toml); +//! // let's add a new key/value pair inside a.b: c = {d = "hello"} +//! doc["a"]["b"]["c"]["d"] = value("hello"); +//! // autoformat inline table a.b.c: { d = "hello" } +//! doc["a"]["b"]["c"].as_inline_table_mut().map(|t| t.fmt()); +//! let expected = r#" +//! "hello" = 'toml!' # comment +//! ['a'.b] +//! c = { d = "hello" } +//! "#; +//! assert_eq!(doc.to_string(), expected); +//! ``` +//! +//! ## Controlling formatting +//! +//! By default, values are created with default formatting +//! ```rust +//! 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 +//! 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). +//! +//! [`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; +mod encode; +mod index; +mod inline_table; +mod internal_string; +mod item; +mod key; +mod parser; +mod raw_string; +mod repr; +mod table; +mod value; + +#[cfg(feature = "serde")] +pub mod de; +#[cfg(feature = "serde")] +pub mod ser; + +pub mod visit; +pub mod visit_mut; + +pub use crate::array::{Array, ArrayIntoIter, ArrayIter, ArrayIterMut}; +pub use crate::array_of_tables::{ + ArrayOfTables, ArrayOfTablesIntoIter, ArrayOfTablesIter, ArrayOfTablesIterMut, +}; +pub use crate::document::Document; +pub use crate::inline_table::{ + InlineEntry, InlineOccupiedEntry, InlineTable, InlineTableIntoIter, InlineTableIter, + InlineTableIterMut, InlineVacantEntry, +}; +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::{ + Entry, IntoIter, Iter, IterMut, OccupiedEntry, Table, TableLike, VacantEntry, +}; +pub use crate::value::Value; +pub use toml_datetime::*; + +// Prevent users from some traits. +pub(crate) mod private { + pub trait Sealed {} + impl Sealed for usize {} + impl Sealed for str {} + impl Sealed for String {} + impl Sealed for i64 {} + impl Sealed for f64 {} + impl Sealed for bool {} + impl Sealed for crate::Datetime {} + impl<'a, T: ?Sized> Sealed for &'a T where T: Sealed {} + impl Sealed for crate::Table {} + impl Sealed for crate::InlineTable {} +} diff --git a/vendor/toml_edit/src/parser/array.rs b/vendor/toml_edit/src/parser/array.rs new file mode 100644 index 0000000..e3b1f3f --- /dev/null +++ b/vendor/toml_edit/src/parser/array.rs @@ -0,0 +1,146 @@ +use winnow::combinator::cut_err; +use winnow::combinator::delimited; +use winnow::combinator::opt; +use winnow::combinator::separated1; +use winnow::trace::trace; + +use crate::parser::trivia::ws_comment_newline; +use crate::parser::value::value; +use crate::{Array, Item, RawString, Value}; + +use crate::parser::prelude::*; + +// ;; Array + +// array = array-open array-values array-close +pub(crate) fn array<'i>(check: RecursionCheck) -> impl Parser<Input<'i>, Array, ContextError> { + trace("array", move |input: &mut Input<'i>| { + delimited( + ARRAY_OPEN, + cut_err(array_values(check)), + cut_err(ARRAY_CLOSE) + .context(StrContext::Label("array")) + .context(StrContext::Expected(StrContextValue::CharLiteral(']'))), + ) + .parse_next(input) + }) +} + +// note: we're omitting ws and newlines here, because +// they should be part of the formatted values +// array-open = %x5B ws-newline ; [ +pub(crate) const ARRAY_OPEN: u8 = b'['; +// array-close = ws-newline %x5D ; ] +const ARRAY_CLOSE: u8 = b']'; +// array-sep = ws %x2C ws ; , Comma +const ARRAY_SEP: u8 = b','; + +// note: this rule is modified +// array-values = [ ( array-value array-sep array-values ) / +// array-value / ws-comment-newline ] +pub(crate) fn array_values<'i>( + check: RecursionCheck, +) -> impl Parser<Input<'i>, Array, ContextError> { + move |input: &mut Input<'i>| { + let check = check.recursing(input)?; + ( + opt( + (separated1(array_value(check), ARRAY_SEP), opt(ARRAY_SEP)).map( + |(v, trailing): (Vec<Value>, Option<u8>)| { + ( + Array::with_vec(v.into_iter().map(Item::Value).collect()), + trailing.is_some(), + ) + }, + ), + ), + ws_comment_newline.span(), + ) + .try_map::<_, _, std::str::Utf8Error>(|(array, trailing)| { + let (mut array, comma) = array.unwrap_or_default(); + array.set_trailing_comma(comma); + array.set_trailing(RawString::with_span(trailing)); + Ok(array) + }) + .parse_next(input) + } +} + +pub(crate) fn array_value<'i>( + check: RecursionCheck, +) -> impl Parser<Input<'i>, Value, ContextError> { + move |input: &mut Input<'i>| { + ( + ws_comment_newline.span(), + value(check), + ws_comment_newline.span(), + ) + .map(|(ws1, v, ws2)| v.decorated(RawString::with_span(ws1), RawString::with_span(ws2))) + .parse_next(input) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn arrays() { + let inputs = [ + r#"[]"#, + r#"[ ]"#, + r#"[ + 1, 2, 3 +]"#, + r#"[ + 1, + 2, # this is ok +]"#, + r#"[# comment +# comment2 + + + ]"#, + r#"[# comment +# comment2 + 1 + +#sd +, +# comment3 + + ]"#, + r#"[1]"#, + r#"[1,]"#, + r#"[ "all", 'strings', """are the same""", '''type''']"#, + r#"[ 100, -2,]"#, + r#"[1, 2, 3]"#, + r#"[1.1, 2.1, 3.1]"#, + r#"["a", "b", "c"]"#, + r#"[ [ 1, 2 ], [3, 4, 5] ]"#, + r#"[ [ 1, 2 ], ["a", "b", "c"] ]"#, + r#"[ { x = 1, a = "2" }, {a = "a",b = "b", c = "c"} ]"#, + ]; + for input in inputs { + dbg!(input); + let mut parsed = array(Default::default()).parse(new_input(input)); + if let Ok(parsed) = &mut parsed { + parsed.despan(input); + } + assert_eq!(parsed.map(|a| a.to_string()), Ok(input.to_owned())); + } + } + + #[test] + fn invalid_arrays() { + let invalid_inputs = [r#"["#, r#"[,]"#, r#"[,2]"#, r#"[1e165,,]"#]; + for input in invalid_inputs { + dbg!(input); + let mut parsed = array(Default::default()).parse(new_input(input)); + if let Ok(parsed) = &mut parsed { + parsed.despan(input); + } + assert!(parsed.is_err()); + } + } +} diff --git a/vendor/toml_edit/src/parser/datetime.rs b/vendor/toml_edit/src/parser/datetime.rs new file mode 100644 index 0000000..6e89b97 --- /dev/null +++ b/vendor/toml_edit/src/parser/datetime.rs @@ -0,0 +1,446 @@ +use std::ops::RangeInclusive; + +use crate::parser::errors::CustomError; +use crate::parser::prelude::*; +use crate::parser::trivia::from_utf8_unchecked; + +use toml_datetime::*; +use winnow::combinator::alt; +use winnow::combinator::cut_err; +use winnow::combinator::opt; +use winnow::combinator::preceded; +use winnow::token::one_of; +use winnow::token::take_while; +use winnow::trace::trace; + +// ;; Date and Time (as defined in RFC 3339) + +// date-time = offset-date-time / local-date-time / local-date / local-time +// offset-date-time = full-date time-delim full-time +// local-date-time = full-date time-delim partial-time +// local-date = full-date +// local-time = partial-time +// full-time = partial-time time-offset +pub(crate) fn date_time(input: &mut Input<'_>) -> PResult<Datetime> { + trace( + "date-time", + alt(( + (full_date, opt((time_delim, partial_time, opt(time_offset)))) + .map(|(date, opt)| { + match opt { + // Offset Date-Time + Some((_, time, offset)) => Datetime { + date: Some(date), + time: Some(time), + offset, + }, + // Local Date + None => Datetime { + date: Some(date), + time: None, + offset: None, + }, + } + }) + .context(StrContext::Label("date-time")), + partial_time + .map(|t| t.into()) + .context(StrContext::Label("time")), + )), + ) + .parse_next(input) +} + +// 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) +} + +// partial-time = time-hour ":" time-minute ":" time-second [time-secfrac] +pub(crate) fn partial_time(input: &mut Input<'_>) -> PResult<Time> { + trace( + "partial-time", + ( + time_hour, + b':', + cut_err((time_minute, b':', time_second, opt(time_secfrac))), + ) + .map(|(hour, _, (minute, _, second, nanosecond))| Time { + hour, + minute, + second, + nanosecond: nanosecond.unwrap_or_default(), + }), + ) + .parse_next(input) +} + +// time-offset = "Z" / time-numoffset +// time-numoffset = ( "+" / "-" ) time-hour ":" time-minute +pub(crate) fn time_offset(input: &mut Input<'_>) -> PResult<Offset> { + trace( + "time-offset", + alt(( + one_of((b'Z', b'z')).value(Offset::Z), + ( + one_of((b'+', b'-')), + cut_err((time_hour, b':', time_minute)), + ) + .map(|(sign, (hours, _, minutes))| { + let sign = match sign { + b'+' => 1, + b'-' => -1, + _ => unreachable!("Parser prevents this"), + }; + sign * (hours as i16 * 60 + minutes as i16) + }) + .verify(|minutes| ((-24 * 60)..=(24 * 60)).contains(minutes)) + .map(|minutes| Offset::Custom { minutes }), + )) + .context(StrContext::Label("time offset")), + ) + .parse_next(input) +} + +// date-fullyear = 4DIGIT +pub(crate) fn date_fullyear(input: &mut Input<'_>) -> PResult<u16> { + unsigned_digits::<4, 4> + .map(|s: &str| s.parse::<u16>().expect("4DIGIT should match u8")) + .parse_next(input) +} + +// date-month = 2DIGIT ; 01-12 +pub(crate) fn date_month(input: &mut Input<'_>) -> PResult<u8> { + unsigned_digits::<2, 2> + .try_map(|s: &str| { + let d = s.parse::<u8>().expect("2DIGIT should match u8"); + if (1..=12).contains(&d) { + Ok(d) + } else { + Err(CustomError::OutOfRange) + } + }) + .parse_next(input) +} + +// date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year +pub(crate) fn date_mday(input: &mut Input<'_>) -> PResult<u8> { + unsigned_digits::<2, 2> + .try_map(|s: &str| { + let d = s.parse::<u8>().expect("2DIGIT should match u8"); + if (1..=31).contains(&d) { + Ok(d) + } else { + Err(CustomError::OutOfRange) + } + }) + .parse_next(input) +} + +// time-delim = "T" / %x20 ; T, t, or space +pub(crate) fn time_delim(input: &mut Input<'_>) -> PResult<u8> { + one_of(TIME_DELIM).parse_next(input) +} + +const TIME_DELIM: (u8, u8, u8) = (b'T', b't', b' '); + +// time-hour = 2DIGIT ; 00-23 +pub(crate) fn time_hour(input: &mut Input<'_>) -> PResult<u8> { + unsigned_digits::<2, 2> + .try_map(|s: &str| { + let d = s.parse::<u8>().expect("2DIGIT should match u8"); + if (0..=23).contains(&d) { + Ok(d) + } else { + Err(CustomError::OutOfRange) + } + }) + .parse_next(input) +} + +// time-minute = 2DIGIT ; 00-59 +pub(crate) fn time_minute(input: &mut Input<'_>) -> PResult<u8> { + unsigned_digits::<2, 2> + .try_map(|s: &str| { + let d = s.parse::<u8>().expect("2DIGIT should match u8"); + if (0..=59).contains(&d) { + Ok(d) + } else { + Err(CustomError::OutOfRange) + } + }) + .parse_next(input) +} + +// time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules +pub(crate) fn time_second(input: &mut Input<'_>) -> PResult<u8> { + unsigned_digits::<2, 2> + .try_map(|s: &str| { + let d = s.parse::<u8>().expect("2DIGIT should match u8"); + if (0..=60).contains(&d) { + Ok(d) + } else { + Err(CustomError::OutOfRange) + } + }) + .parse_next(input) +} + +// time-secfrac = "." 1*DIGIT +pub(crate) fn time_secfrac(input: &mut Input<'_>) -> PResult<u32> { + static SCALE: [u32; 10] = [ + 0, + 100_000_000, + 10_000_000, + 1_000_000, + 100_000, + 10_000, + 1_000, + 100, + 10, + 1, + ]; + const INF: usize = usize::MAX; + preceded(b'.', unsigned_digits::<1, INF>) + .try_map(|mut repr: &str| -> Result<u32, CustomError> { + let max_digits = SCALE.len() - 1; + if max_digits < repr.len() { + // Millisecond precision is required. Further precision of fractional seconds is + // implementation-specific. If the value contains greater precision than the + // implementation can support, the additional precision must be truncated, not rounded. + repr = &repr[0..max_digits]; + } + + let v = repr.parse::<u32>().map_err(|_| CustomError::OutOfRange)?; + let num_digits = repr.len(); + + // scale the number accordingly. + let scale = SCALE.get(num_digits).ok_or(CustomError::OutOfRange)?; + let v = v.checked_mul(*scale).ok_or(CustomError::OutOfRange)?; + Ok(v) + }) + .parse_next(input) +} + +pub(crate) fn unsigned_digits<'i, const MIN: usize, const MAX: usize>( + input: &mut Input<'i>, +) -> PResult<&'i str> { + take_while(MIN..=MAX, DIGIT) + .map(|b: &[u8]| unsafe { from_utf8_unchecked(b, "`is_ascii_digit` filters out on-ASCII") }) + .parse_next(input) +} + +// DIGIT = %x30-39 ; 0-9 +const DIGIT: RangeInclusive<u8> = b'0'..=b'9'; + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn offset_date_time() { + let inputs = [ + ( + "1979-05-27T07:32:00Z", + Datetime { + date: Some(Date { + year: 1979, + month: 5, + day: 27, + }), + time: Some(Time { + hour: 7, + minute: 32, + second: 0, + nanosecond: 0, + }), + offset: Some(Offset::Z), + }, + ), + ( + "1979-05-27T00:32:00-07:00", + Datetime { + date: Some(Date { + year: 1979, + month: 5, + day: 27, + }), + time: Some(Time { + hour: 0, + minute: 32, + second: 0, + nanosecond: 0, + }), + offset: Some(Offset::Custom { minutes: -7 * 60 }), + }, + ), + ( + "1979-05-27T00:32:00-00:36", + Datetime { + date: Some(Date { + year: 1979, + month: 5, + day: 27, + }), + time: Some(Time { + hour: 0, + minute: 32, + second: 0, + nanosecond: 0, + }), + offset: Some(Offset::Custom { minutes: -36 }), + }, + ), + ( + "1979-05-27T00:32:00.999999", + Datetime { + date: Some(Date { + year: 1979, + month: 5, + day: 27, + }), + time: Some(Time { + hour: 0, + minute: 32, + second: 0, + nanosecond: 999999000, + }), + offset: None, + }, + ), + ]; + for (input, expected) in inputs { + dbg!(input); + let actual = date_time.parse(new_input(input)).unwrap(); + assert_eq!(expected, actual); + } + } + + #[test] + fn local_date_time() { + let inputs = [ + ( + "1979-05-27T07:32:00", + Datetime { + date: Some(Date { + year: 1979, + month: 5, + day: 27, + }), + time: Some(Time { + hour: 7, + minute: 32, + second: 0, + nanosecond: 0, + }), + offset: None, + }, + ), + ( + "1979-05-27T00:32:00.999999", + Datetime { + date: Some(Date { + year: 1979, + month: 5, + day: 27, + }), + time: Some(Time { + hour: 0, + minute: 32, + second: 0, + nanosecond: 999999000, + }), + offset: None, + }, + ), + ]; + for (input, expected) in inputs { + dbg!(input); + let actual = date_time.parse(new_input(input)).unwrap(); + assert_eq!(expected, actual); + } + } + + #[test] + fn local_date() { + let inputs = [ + ( + "1979-05-27", + Datetime { + date: Some(Date { + year: 1979, + month: 5, + day: 27, + }), + time: None, + offset: None, + }, + ), + ( + "2017-07-20", + Datetime { + date: Some(Date { + year: 2017, + month: 7, + day: 20, + }), + time: None, + offset: None, + }, + ), + ]; + for (input, expected) in inputs { + dbg!(input); + let actual = date_time.parse(new_input(input)).unwrap(); + assert_eq!(expected, actual); + } + } + + #[test] + fn local_time() { + let inputs = [ + ( + "07:32:00", + Datetime { + date: None, + time: Some(Time { + hour: 7, + minute: 32, + second: 0, + nanosecond: 0, + }), + offset: None, + }, + ), + ( + "00:32:00.999999", + Datetime { + date: None, + time: Some(Time { + hour: 0, + minute: 32, + second: 0, + nanosecond: 999999000, + }), + offset: None, + }, + ), + ]; + for (input, expected) in inputs { + dbg!(input); + let actual = date_time.parse(new_input(input)).unwrap(); + assert_eq!(expected, actual); + } + } + + #[test] + fn time_fraction_truncated() { + let input = "1987-07-05T17:45:00.123456789012345Z"; + date_time.parse(new_input(input)).unwrap(); + } +} diff --git a/vendor/toml_edit/src/parser/document.rs b/vendor/toml_edit/src/parser/document.rs new file mode 100644 index 0000000..aa8fb11 --- /dev/null +++ b/vendor/toml_edit/src/parser/document.rs @@ -0,0 +1,141 @@ +use std::cell::RefCell; + +use winnow::combinator::cut_err; +use winnow::combinator::eof; +use winnow::combinator::opt; +use winnow::combinator::peek; +use winnow::combinator::repeat; +use winnow::token::any; +use winnow::token::one_of; +use winnow::trace::trace; + +use crate::document::Document; +use crate::key::Key; +use crate::parser::inline_table::KEYVAL_SEP; +use crate::parser::key::key; +use crate::parser::prelude::*; +use crate::parser::state::ParseState; +use crate::parser::table::table; +use crate::parser::trivia::{comment, line_ending, line_trailing, newline, ws}; +use crate::parser::value::value; +use crate::table::TableKeyValue; +use crate::Item; +use crate::RawString; + +// ;; TOML + +// toml = expression *( newline expression ) + +// expression = ( ( ws comment ) / +// ( ws keyval ws [ comment ] ) / +// ( ws table ws [ comment ] ) / +// ws ) +pub(crate) fn document(input: &mut Input<'_>) -> PResult<Document> { + let state = RefCell::new(ParseState::default()); + let state_ref = &state; + + let _o = ( + // Remove BOM if present + opt(b"\xEF\xBB\xBF"), + parse_ws(state_ref), + repeat(0.., ( + dispatch! {peek(any); + crate::parser::trivia::COMMENT_START_SYMBOL => cut_err(parse_comment(state_ref)), + crate::parser::table::STD_TABLE_OPEN => cut_err(table(state_ref)), + crate::parser::trivia::LF | + crate::parser::trivia::CR => parse_newline(state_ref), + _ => cut_err(keyval(state_ref)), + }, + parse_ws(state_ref), + )) + .map(|()| ()), + eof, + ) + .parse_next(input)?; + state.into_inner().into_document().map_err(|err| { + winnow::error::ErrMode::from_external_error(input, winnow::error::ErrorKind::Verify, err) + }) +} + +pub(crate) fn parse_comment<'s, 'i>( + state: &'s RefCell<ParseState>, +) -> impl Parser<Input<'i>, (), ContextError> + 's { + move |i: &mut Input<'i>| { + (comment, line_ending) + .span() + .map(|span| { + state.borrow_mut().on_comment(span); + }) + .parse_next(i) + } +} + +pub(crate) fn parse_ws<'s, 'i>( + state: &'s RefCell<ParseState>, +) -> impl Parser<Input<'i>, (), ContextError> + 's { + move |i: &mut Input<'i>| { + ws.span() + .map(|span| state.borrow_mut().on_ws(span)) + .parse_next(i) + } +} + +pub(crate) fn parse_newline<'s, 'i>( + state: &'s RefCell<ParseState>, +) -> impl Parser<Input<'i>, (), ContextError> + 's { + move |i: &mut Input<'i>| { + newline + .span() + .map(|span| state.borrow_mut().on_ws(span)) + .parse_next(i) + } +} + +pub(crate) fn keyval<'s, 'i>( + state: &'s RefCell<ParseState>, +) -> impl Parser<Input<'i>, (), ContextError> + 's { + move |i: &mut Input<'i>| { + parse_keyval + .try_map(|(p, kv)| state.borrow_mut().on_keyval(p, kv)) + .parse_next(i) + } +} + +// keyval = key keyval-sep val +pub(crate) fn parse_keyval(input: &mut Input<'_>) -> PResult<(Vec<Key>, TableKeyValue)> { + trace( + "keyval", + ( + key, + cut_err(( + one_of(KEYVAL_SEP) + .context(StrContext::Expected(StrContextValue::CharLiteral('.'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('='))), + ( + ws.span(), + value(RecursionCheck::default()), + line_trailing + .context(StrContext::Expected(StrContextValue::CharLiteral('\n'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('#'))), + ), + )), + ) + .try_map::<_, _, std::str::Utf8Error>(|(key, (_, v))| { + let mut path = key; + let key = path.pop().expect("grammar ensures at least 1"); + + let (pre, v, suf) = v; + let pre = RawString::with_span(pre); + let suf = RawString::with_span(suf); + let v = v.decorated(pre, suf); + Ok(( + path, + TableKeyValue { + key, + value: Item::Value(v), + }, + )) + }), + ) + .parse_next(input) +} diff --git a/vendor/toml_edit/src/parser/errors.rs b/vendor/toml_edit/src/parser/errors.rs new file mode 100644 index 0000000..96ad886 --- /dev/null +++ b/vendor/toml_edit/src/parser/errors.rs @@ -0,0 +1,316 @@ +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 { + message: String, + original: Option<String>, + keys: Vec<String>, + span: Option<std::ops::Range<usize>>, +} + +impl TomlError { + pub(crate) fn new(error: ParseError<Input<'_>, ContextError>, mut original: Input<'_>) -> Self { + use winnow::stream::Stream; + + let offset = error.offset(); + let span = if offset == original.len() { + offset..offset + } else { + offset..(offset + 1) + }; + + let message = error.inner().to_string(); + let original = original.finish(); + + Self { + message, + original: Some( + String::from_utf8(original.to_owned()).expect("original document was utf8"), + ), + keys: Vec::new(), + span: Some(span), + } + } + + #[cfg(feature = "serde")] + pub(crate) fn custom(message: String, span: Option<std::ops::Range<usize>>) -> Self { + Self { + message, + original: None, + keys: Vec::new(), + span, + } + } + + #[cfg(feature = "serde")] + pub(crate) fn add_key(&mut self, key: String) { + self.keys.insert(0, key); + } + + /// What went wrong + pub fn message(&self) -> &str { + &self.message + } + + /// The start/end index into the original document where the error occurred + pub fn span(&self) -> Option<std::ops::Range<usize>> { + self.span.clone() + } + + #[cfg(feature = "serde")] + pub(crate) fn set_span(&mut self, span: Option<std::ops::Range<usize>>) { + self.span = span; + } + + #[cfg(feature = "serde")] + pub(crate) fn set_original(&mut self, original: Option<String>) { + self.original = original; + } +} + +/// Displays a TOML parse error +/// +/// # Example +/// +/// TOML parse error at line 1, column 10 +/// | +/// 1 | 00:32:00.a999999 +/// | ^ +/// Unexpected `a` +/// Expected `digit` +/// While parsing a Time +/// While parsing a Date-Time +impl Display for TomlError { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let mut context = false; + if let (Some(original), Some(span)) = (&self.original, self.span()) { + context = true; + + let (line, column) = translate_position(original.as_bytes(), span.start); + let line_num = line + 1; + let col_num = column + 1; + let gutter = line_num.to_string().len(); + let content = original.split('\n').nth(line).expect("valid line number"); + + writeln!( + f, + "TOML parse error at line {}, column {}", + line_num, col_num + )?; + // | + for _ in 0..=gutter { + write!(f, " ")?; + } + writeln!(f, "|")?; + + // 1 | 00:32:00.a999999 + write!(f, "{} | ", line_num)?; + writeln!(f, "{}", content)?; + + // | ^ + for _ in 0..=gutter { + write!(f, " ")?; + } + write!(f, "|")?; + for _ in 0..=column { + write!(f, " ")?; + } + // The span will be empty at eof, so we need to make sure we always print at least + // one `^` + write!(f, "^")?; + for _ in (span.start + 1)..(span.end.min(span.start + content.len())) { + write!(f, "^")?; + } + writeln!(f)?; + } + writeln!(f, "{}", self.message)?; + if !context && !self.keys.is_empty() { + writeln!(f, "in `{}`", self.keys.join("."))?; + } + + Ok(()) + } +} + +impl StdError for TomlError { + fn description(&self) -> &'static str { + "TOML parse error" + } +} + +fn translate_position(input: &[u8], index: usize) -> (usize, usize) { + if input.is_empty() { + return (0, index); + } + + let safe_index = index.min(input.len() - 1); + let column_offset = index - safe_index; + let index = safe_index; + + let nl = input[0..index] + .iter() + .rev() + .enumerate() + .find(|(_, b)| **b == b'\n') + .map(|(nl, _)| index - nl - 1); + let line_start = match nl { + Some(nl) => nl + 1, + 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) + .unwrap_or_else(|_| index - line_start); + let column = column + column_offset; + + (line, column) +} + +#[cfg(test)] +mod test_translate_position { + use super::*; + + #[test] + fn empty() { + let input = b""; + let index = 0; + let position = translate_position(&input[..], index); + assert_eq!(position, (0, 0)); + } + + #[test] + fn start() { + let input = b"Hello"; + let index = 0; + let position = translate_position(&input[..], index); + assert_eq!(position, (0, 0)); + } + + #[test] + fn end() { + let input = b"Hello"; + let index = input.len() - 1; + let position = translate_position(&input[..], index); + assert_eq!(position, (0, input.len() - 1)); + } + + #[test] + fn after() { + let input = b"Hello"; + let index = input.len(); + let position = translate_position(&input[..], index); + assert_eq!(position, (0, input.len())); + } + + #[test] + fn first_line() { + let input = b"Hello\nWorld\n"; + let index = 2; + let position = translate_position(&input[..], index); + assert_eq!(position, (0, 2)); + } + + #[test] + fn end_of_line() { + let input = b"Hello\nWorld\n"; + let index = 5; + let position = translate_position(&input[..], index); + assert_eq!(position, (0, 5)); + } + + #[test] + fn start_of_second_line() { + let input = b"Hello\nWorld\n"; + let index = 6; + let position = translate_position(&input[..], index); + assert_eq!(position, (1, 0)); + } + + #[test] + fn second_line() { + let input = b"Hello\nWorld\n"; + let index = 8; + let position = translate_position(&input[..], index); + 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 exceeded"), + } + } +} diff --git a/vendor/toml_edit/src/parser/inline_table.rs b/vendor/toml_edit/src/parser/inline_table.rs new file mode 100644 index 0000000..994e003 --- /dev/null +++ b/vendor/toml_edit/src/parser/inline_table.rs @@ -0,0 +1,181 @@ +use winnow::combinator::cut_err; +use winnow::combinator::delimited; +use winnow::combinator::separated0; +use winnow::token::one_of; +use winnow::trace::trace; + +use crate::key::Key; +use crate::parser::errors::CustomError; +use crate::parser::key::key; +use crate::parser::prelude::*; +use crate::parser::trivia::ws; +use crate::parser::value::value; +use crate::table::TableKeyValue; +use crate::{InlineTable, InternalString, Item, RawString, Value}; + +use indexmap::map::Entry; + +// ;; Inline Table + +// inline-table = inline-table-open inline-table-keyvals inline-table-close +pub(crate) fn inline_table<'i>( + check: RecursionCheck, +) -> impl Parser<Input<'i>, InlineTable, ContextError> { + trace("inline-table", move |input: &mut Input<'i>| { + delimited( + INLINE_TABLE_OPEN, + cut_err(inline_table_keyvals(check).try_map(|(kv, p)| table_from_pairs(kv, p))), + cut_err(INLINE_TABLE_CLOSE) + .context(StrContext::Label("inline table")) + .context(StrContext::Expected(StrContextValue::CharLiteral('}'))), + ) + .parse_next(input) + }) +} + +fn table_from_pairs( + v: Vec<(Vec<Key>, TableKeyValue)>, + preamble: RawString, +) -> Result<InlineTable, CustomError> { + let mut root = InlineTable::new(); + root.set_preamble(preamble); + // Assuming almost all pairs will be directly in `root` + root.items.reserve(v.len()); + + for (path, kv) in v { + let table = descend_path(&mut root, &path)?; + let key: InternalString = kv.key.get_internal().into(); + match table.items.entry(key) { + Entry::Vacant(o) => { + o.insert(kv); + } + Entry::Occupied(o) => { + return Err(CustomError::DuplicateKey { + key: o.key().as_str().into(), + table: None, + }); + } + } + } + Ok(root) +} + +fn descend_path<'a>( + mut table: &'a mut InlineTable, + path: &'a [Key], +) -> Result<&'a mut InlineTable, CustomError> { + 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); + + Value::InlineTable(new_table) + }); + match *entry { + Value::InlineTable(ref mut sweet_child_of_mine) => { + table = sweet_child_of_mine; + } + ref v => { + return Err(CustomError::extend_wrong_type(path, i, v.type_name())); + } + } + } + Ok(table) +} + +// inline-table-open = %x7B ws ; { +pub(crate) const INLINE_TABLE_OPEN: u8 = b'{'; +// inline-table-close = ws %x7D ; } +const INLINE_TABLE_CLOSE: u8 = b'}'; +// inline-table-sep = ws %x2C ws ; , Comma +const INLINE_TABLE_SEP: u8 = b','; +// keyval-sep = ws %x3D ws ; = +pub(crate) const KEYVAL_SEP: u8 = b'='; + +// inline-table-keyvals = [ inline-table-keyvals-non-empty ] +// inline-table-keyvals-non-empty = +// ( key keyval-sep val inline-table-sep inline-table-keyvals-non-empty ) / +// ( key keyval-sep val ) + +fn inline_table_keyvals<'i>( + check: RecursionCheck, +) -> impl Parser<Input<'i>, (Vec<(Vec<Key>, TableKeyValue)>, RawString), ContextError> { + move |input: &mut Input<'i>| { + let check = check.recursing(input)?; + ( + separated0(keyval(check), INLINE_TABLE_SEP), + ws.span().map(RawString::with_span), + ) + .parse_next(input) + } +} + +fn keyval<'i>( + check: RecursionCheck, +) -> impl Parser<Input<'i>, (Vec<Key>, TableKeyValue), ContextError> { + move |input: &mut Input<'i>| { + ( + key, + cut_err(( + one_of(KEYVAL_SEP) + .context(StrContext::Expected(StrContextValue::CharLiteral('.'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('='))), + (ws.span(), value(check), ws.span()), + )), + ) + .map(|(key, (_, v))| { + let mut path = key; + let key = path.pop().expect("grammar ensures at least 1"); + + let (pre, v, suf) = v; + let pre = RawString::with_span(pre); + let suf = RawString::with_span(suf); + let v = v.decorated(pre, suf); + ( + path, + TableKeyValue { + key, + value: Item::Value(v), + }, + ) + }) + .parse_next(input) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn inline_tables() { + let inputs = [ + r#"{}"#, + r#"{ }"#, + r#"{a = 1e165}"#, + r#"{ hello = "world", a = 1}"#, + r#"{ hello.world = "a" }"#, + ]; + for input in inputs { + dbg!(input); + let mut parsed = inline_table(Default::default()).parse(new_input(input)); + if let Ok(parsed) = &mut parsed { + parsed.despan(input); + } + assert_eq!(parsed.map(|a| a.to_string()), Ok(input.to_owned())); + } + } + + #[test] + fn invalid_inline_tables() { + let invalid_inputs = [r#"{a = 1e165"#, r#"{ hello = "world", a = 2, hello = 1}"#]; + for input in invalid_inputs { + dbg!(input); + let mut parsed = inline_table(Default::default()).parse(new_input(input)); + if let Ok(parsed) = &mut parsed { + parsed.despan(input); + } + assert!(parsed.is_err()); + } + } +} diff --git a/vendor/toml_edit/src/parser/key.rs b/vendor/toml_edit/src/parser/key.rs new file mode 100644 index 0000000..12715da --- /dev/null +++ b/vendor/toml_edit/src/parser/key.rs @@ -0,0 +1,112 @@ +use std::ops::RangeInclusive; + +use winnow::combinator::peek; +use winnow::combinator::separated1; +use winnow::token::any; +use winnow::token::take_while; +use winnow::trace::trace; + +use crate::key::Key; +use crate::parser::errors::CustomError; +use crate::parser::prelude::*; +use crate::parser::strings::{basic_string, literal_string}; +use crate::parser::trivia::{from_utf8_unchecked, ws}; +use crate::repr::{Decor, Repr}; +use crate::InternalString; +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( + "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( + RawString::with_span(pre), + RawString::with_span(suffix), + )) + }), + DOT_SEP, + ) + .context(StrContext::Label("key")) + .try_map(|k: Vec<_>| { + // Inserting the key will require recursion down the line + RecursionCheck::check_depth(k.len())?; + Ok::<_, CustomError>(k) + }), + ) + .parse_next(input) +} + +// simple-key = quoted-key / unquoted-key +// quoted-key = basic-string / literal-string +pub(crate) fn simple_key(input: &mut Input<'_>) -> PResult<(RawString, InternalString)> { + trace( + "simple-key", + dispatch! {peek(any); + crate::parser::strings::QUOTATION_MARK => basic_string + .map(|s: std::borrow::Cow<'_, str>| s.as_ref().into()), + crate::parser::strings::APOSTROPHE => literal_string.map(|s: &str| s.into()), + _ => unquoted_key.map(|s: &str| s.into()), + } + .with_span() + .map(|(k, span)| { + let raw = RawString::with_span(span); + (raw, k) + }), + ) + .parse_next(input) +} + +// unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _ +fn unquoted_key<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + trace( + "unquoted-key", + take_while(1.., UNQUOTED_CHAR) + .map(|b| unsafe { from_utf8_unchecked(b, "`is_unquoted_char` filters out on-ASCII") }), + ) + .parse_next(input) +} + +pub(crate) fn is_unquoted_char(c: u8) -> bool { + use winnow::stream::ContainsToken; + UNQUOTED_CHAR.contains_token(c) +} + +const UNQUOTED_CHAR: ( + RangeInclusive<u8>, + RangeInclusive<u8>, + RangeInclusive<u8>, + u8, + u8, +) = (b'A'..=b'Z', b'a'..=b'z', b'0'..=b'9', b'-', b'_'); + +// dot-sep = ws %x2E ws ; . Period +const DOT_SEP: u8 = b'.'; + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn keys() { + let cases = [ + ("a", "a"), + (r#""hello\n ""#, "hello\n "), + (r#"'hello\n '"#, "hello\\n "), + ]; + + for (input, expected) in cases { + dbg!(input); + let parsed = simple_key.parse(new_input(input)); + assert_eq!( + parsed, + Ok((RawString::with_span(0..(input.len())), expected.into())), + "Parsing {input:?}" + ); + } + } +} diff --git a/vendor/toml_edit/src/parser/mod.rs b/vendor/toml_edit/src/parser/mod.rs new file mode 100644 index 0000000..eb47550 --- /dev/null +++ b/vendor/toml_edit/src/parser/mod.rs @@ -0,0 +1,265 @@ +#![allow(clippy::type_complexity)] + +pub(crate) mod array; +pub(crate) mod datetime; +pub(crate) mod document; +pub(crate) mod errors; +pub(crate) mod inline_table; +pub(crate) mod key; +pub(crate) mod numbers; +pub(crate) mod state; +pub(crate) mod strings; +pub(crate) mod table; +pub(crate) mod trivia; +pub(crate) mod value; + +pub use errors::TomlError; + +pub(crate) fn parse_document(raw: &str) -> Result<crate::Document, TomlError> { + use prelude::*; + + let b = new_input(raw); + let mut doc = document::document + .parse(b) + .map_err(|e| TomlError::new(e, b))?; + doc.span = Some(0..(raw.len())); + doc.original = Some(raw.to_owned()); + Ok(doc) +} + +pub(crate) fn parse_key(raw: &str) -> Result<crate::Key, TomlError> { + use prelude::*; + + let b = new_input(raw); + let result = key::simple_key.parse(b); + match result { + Ok((raw, key)) => { + Ok(crate::Key::new(key).with_repr_unchecked(crate::Repr::new_unchecked(raw))) + } + Err(e) => Err(TomlError::new(e, b)), + } +} + +pub(crate) fn parse_key_path(raw: &str) -> Result<Vec<crate::Key>, TomlError> { + use prelude::*; + + let b = new_input(raw); + let result = key::key.parse(b); + match result { + Ok(mut keys) => { + for key in &mut keys { + key.despan(raw); + } + Ok(keys) + } + Err(e) => Err(TomlError::new(e, b)), + } +} + +pub(crate) fn parse_value(raw: &str) -> Result<crate::Value, TomlError> { + use prelude::*; + + let b = new_input(raw); + let parsed = value::value(RecursionCheck::default()).parse(b); + match parsed { + Ok(mut value) => { + // Only take the repr and not decor, as its probably not intended + value.decor_mut().clear(); + value.despan(raw); + Ok(value) + } + Err(e) => Err(TomlError::new(e, b)), + } +} + +pub(crate) mod prelude { + pub(crate) use winnow::combinator::dispatch; + pub(crate) use winnow::error::ContextError; + pub(crate) use winnow::error::FromExternalError; + pub(crate) use winnow::error::StrContext; + pub(crate) use winnow::error::StrContextValue; + pub(crate) use winnow::PResult; + pub(crate) use winnow::Parser; + + pub(crate) type Input<'b> = winnow::Located<&'b winnow::BStr>; + + pub(crate) fn new_input(s: &str) -> Input<'_> { + winnow::Located::new(winnow::BStr::new(s)) + } + + #[cfg(not(feature = "unbounded"))] + #[derive(Copy, Clone, Debug, Default)] + pub(crate) struct RecursionCheck { + current: usize, + } + + #[cfg(not(feature = "unbounded"))] + impl RecursionCheck { + pub(crate) fn check_depth(depth: usize) -> Result<(), super::errors::CustomError> { + if depth < 128 { + Ok(()) + } else { + Err(super::errors::CustomError::RecursionLimitExceeded) + } + } + + pub(crate) fn recursing( + mut self, + input: &mut Input<'_>, + ) -> Result<Self, winnow::error::ErrMode<ContextError>> { + self.current += 1; + if self.current < 128 { + Ok(self) + } else { + Err(winnow::error::ErrMode::from_external_error( + input, + winnow::error::ErrorKind::Eof, + super::errors::CustomError::RecursionLimitExceeded, + )) + } + } + } + + #[cfg(feature = "unbounded")] + #[derive(Copy, Clone, Debug, Default)] + pub(crate) struct RecursionCheck {} + + #[cfg(feature = "unbounded")] + impl RecursionCheck { + pub(crate) fn check_depth(_depth: usize) -> Result<(), super::errors::CustomError> { + Ok(()) + } + + pub(crate) fn recursing( + self, + _input: &mut Input<'_>, + ) -> Result<Self, winnow::error::ErrMode<ContextError>> { + Ok(self) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn documents() { + let documents = [ + "", + r#" +# This is a TOML document. + +title = "TOML Example" + + [owner] + name = "Tom Preston-Werner" + dob = 1979-05-27T07:32:00-08:00 # First class dates + + [database] + server = "192.168.1.1" + ports = [ 8001, 8001, 8002 ] + connection_max = 5000 + enabled = true + + [servers] + + # Indentation (tabs and/or spaces) is allowed but not required +[servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + + [clients] + data = [ ["gamma", "delta"], [1, 2] ] + + # Line breaks are OK when inside arrays +hosts = [ + "alpha", + "omega" +] + + 'some.weird .stuff' = """ + like + that + # """ # this broke my syntax highlighting + " also. like " = ''' +that +''' + double = 2e39 # this number looks familiar +# trailing comment"#, + r#""#, + r#" "#, + r#" hello = 'darkness' # my old friend +"#, + r#"[parent . child] +key = "value" +"#, + r#"hello.world = "a" +"#, + r#"foo = 1979-05-27 # Comment +"#, + ]; + for input in documents { + dbg!(input); + let mut parsed = parse_document(input); + if let Ok(parsed) = &mut parsed { + parsed.despan(); + } + let doc = match parsed { + Ok(doc) => doc, + Err(err) => { + panic!( + "Parse error: {:?}\nFailed to parse:\n```\n{}\n```", + err, input + ) + } + }; + + snapbox::assert_eq(input, doc.to_string()); + } + } + + #[test] + fn documents_parse_only() { + let parse_only = ["\u{FEFF} +[package] +name = \"foo\" +version = \"0.0.1\" +authors = [] +"]; + for input in parse_only { + dbg!(input); + let mut parsed = parse_document(input); + if let Ok(parsed) = &mut parsed { + parsed.despan(); + } + match parsed { + Ok(_) => (), + Err(err) => { + panic!( + "Parse error: {:?}\nFailed to parse:\n```\n{}\n```", + err, input + ) + } + } + } + } + + #[test] + fn invalid_documents() { + let invalid_inputs = [r#" hello = 'darkness' # my old friend +$"#]; + for input in invalid_inputs { + dbg!(input); + let mut parsed = parse_document(input); + if let Ok(parsed) = &mut parsed { + parsed.despan(); + } + assert!(parsed.is_err(), "Input: {:?}", input); + } + } +} diff --git a/vendor/toml_edit/src/parser/numbers.rs b/vendor/toml_edit/src/parser/numbers.rs new file mode 100644 index 0000000..6e4757f --- /dev/null +++ b/vendor/toml_edit/src/parser/numbers.rs @@ -0,0 +1,397 @@ +use std::ops::RangeInclusive; + +use winnow::combinator::alt; +use winnow::combinator::cut_err; +use winnow::combinator::opt; +use winnow::combinator::peek; +use winnow::combinator::preceded; +use winnow::combinator::repeat; +use winnow::combinator::rest; +use winnow::token::one_of; +use winnow::token::tag; +use winnow::token::take; +use winnow::trace::trace; + +use crate::parser::prelude::*; +use crate::parser::trivia::from_utf8_unchecked; + +// ;; Boolean + +// boolean = true / false +#[allow(dead_code)] // directly define in `fn value` +pub(crate) fn boolean(input: &mut Input<'_>) -> PResult<bool> { + trace("boolean", alt((true_, false_))).parse_next(input) +} + +pub(crate) fn true_(input: &mut Input<'_>) -> PResult<bool> { + (peek(TRUE[0]), cut_err(TRUE)).value(true).parse_next(input) +} +const TRUE: &[u8] = b"true"; + +pub(crate) fn false_(input: &mut Input<'_>) -> PResult<bool> { + (peek(FALSE[0]), cut_err(FALSE)) + .value(false) + .parse_next(input) +} +const FALSE: &[u8] = b"false"; + +// ;; Integer + +// integer = dec-int / hex-int / oct-int / bin-int +pub(crate) fn integer(input: &mut Input<'_>) -> PResult<i64> { + trace("integer", + dispatch! {peek(opt::<_, &[u8], _, _>(take(2usize))); + Some(b"0x") => cut_err(hex_int.try_map(|s| i64::from_str_radix(&s.replace('_', ""), 16))), + Some(b"0o") => cut_err(oct_int.try_map(|s| i64::from_str_radix(&s.replace('_', ""), 8))), + Some(b"0b") => cut_err(bin_int.try_map(|s| i64::from_str_radix(&s.replace('_', ""), 2))), + _ => dec_int.and_then(cut_err(rest + .try_map(|s: &str| s.replace('_', "").parse()))) + }) + .parse_next(input) +} + +// dec-int = [ minus / plus ] unsigned-dec-int +// unsigned-dec-int = DIGIT / digit1-9 1*( DIGIT / underscore DIGIT ) +pub(crate) fn dec_int<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + trace( + "dec-int", + ( + opt(one_of((b'+', b'-'))), + alt(( + ( + one_of(DIGIT1_9), + repeat( + 0.., + alt(( + digit.value(()), + ( + one_of(b'_'), + cut_err(digit).context(StrContext::Expected( + StrContextValue::Description("digit"), + )), + ) + .value(()), + )), + ) + .map(|()| ()), + ) + .value(()), + digit.value(()), + )), + ) + .recognize() + .map(|b: &[u8]| unsafe { + from_utf8_unchecked(b, "`digit` and `_` filter out non-ASCII") + }) + .context(StrContext::Label("integer")), + ) + .parse_next(input) +} +const DIGIT1_9: RangeInclusive<u8> = b'1'..=b'9'; + +// hex-prefix = %x30.78 ; 0x +// hex-int = hex-prefix HEXDIG *( HEXDIG / underscore HEXDIG ) +pub(crate) fn hex_int<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + trace( + "hex-int", + preceded( + HEX_PREFIX, + cut_err(( + hexdig, + repeat( + 0.., + alt(( + hexdig.value(()), + ( + one_of(b'_'), + cut_err(hexdig).context(StrContext::Expected( + StrContextValue::Description("digit"), + )), + ) + .value(()), + )), + ) + .map(|()| ()), + )) + .recognize(), + ) + .map(|b| unsafe { from_utf8_unchecked(b, "`hexdig` and `_` filter out non-ASCII") }) + .context(StrContext::Label("hexadecimal integer")), + ) + .parse_next(input) +} +const HEX_PREFIX: &[u8] = b"0x"; + +// oct-prefix = %x30.6F ; 0o +// oct-int = oct-prefix digit0-7 *( digit0-7 / underscore digit0-7 ) +pub(crate) fn oct_int<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + trace( + "oct-int", + preceded( + OCT_PREFIX, + cut_err(( + one_of(DIGIT0_7), + repeat( + 0.., + alt(( + one_of(DIGIT0_7).value(()), + ( + one_of(b'_'), + cut_err(one_of(DIGIT0_7)).context(StrContext::Expected( + StrContextValue::Description("digit"), + )), + ) + .value(()), + )), + ) + .map(|()| ()), + )) + .recognize(), + ) + .map(|b| unsafe { from_utf8_unchecked(b, "`DIGIT0_7` and `_` filter out non-ASCII") }) + .context(StrContext::Label("octal integer")), + ) + .parse_next(input) +} +const OCT_PREFIX: &[u8] = b"0o"; +const DIGIT0_7: RangeInclusive<u8> = b'0'..=b'7'; + +// bin-prefix = %x30.62 ; 0b +// bin-int = bin-prefix digit0-1 *( digit0-1 / underscore digit0-1 ) +pub(crate) fn bin_int<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + trace( + "bin-int", + preceded( + BIN_PREFIX, + cut_err(( + one_of(DIGIT0_1), + repeat( + 0.., + alt(( + one_of(DIGIT0_1).value(()), + ( + one_of(b'_'), + cut_err(one_of(DIGIT0_1)).context(StrContext::Expected( + StrContextValue::Description("digit"), + )), + ) + .value(()), + )), + ) + .map(|()| ()), + )) + .recognize(), + ) + .map(|b| unsafe { from_utf8_unchecked(b, "`DIGIT0_1` and `_` filter out non-ASCII") }) + .context(StrContext::Label("binary integer")), + ) + .parse_next(input) +} +const BIN_PREFIX: &[u8] = b"0b"; +const DIGIT0_1: RangeInclusive<u8> = b'0'..=b'1'; + +// ;; Float + +// float = float-int-part ( exp / frac [ exp ] ) +// float =/ special-float +// float-int-part = dec-int +pub(crate) fn float(input: &mut Input<'_>) -> PResult<f64> { + trace( + "float", + alt(( + float_.and_then(cut_err( + rest.try_map(|s: &str| s.replace('_', "").parse()) + .verify(|f: &f64| *f != f64::INFINITY), + )), + special_float, + )) + .context(StrContext::Label("floating-point number")), + ) + .parse_next(input) +} + +pub(crate) fn float_<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + ( + dec_int, + alt((exp.void(), (frac.void(), opt(exp.void())).void())), + ) + .recognize() + .map(|b: &[u8]| unsafe { + from_utf8_unchecked( + b, + "`dec_int`, `one_of`, `exp`, and `frac` filter out non-ASCII", + ) + }) + .parse_next(input) +} + +// frac = decimal-point zero-prefixable-int +// decimal-point = %x2E ; . +pub(crate) fn frac<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + ( + b'.', + cut_err(zero_prefixable_int) + .context(StrContext::Expected(StrContextValue::Description("digit"))), + ) + .recognize() + .map(|b: &[u8]| unsafe { + from_utf8_unchecked( + b, + "`.` and `parse_zero_prefixable_int` filter out non-ASCII", + ) + }) + .parse_next(input) +} + +// zero-prefixable-int = DIGIT *( DIGIT / underscore DIGIT ) +pub(crate) fn zero_prefixable_int<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + ( + digit, + repeat( + 0.., + alt(( + digit.value(()), + ( + one_of(b'_'), + cut_err(digit) + .context(StrContext::Expected(StrContextValue::Description("digit"))), + ) + .value(()), + )), + ) + .map(|()| ()), + ) + .recognize() + .map(|b: &[u8]| unsafe { from_utf8_unchecked(b, "`digit` and `_` filter out non-ASCII") }) + .parse_next(input) +} + +// exp = "e" float-exp-part +// float-exp-part = [ minus / plus ] zero-prefixable-int +pub(crate) fn exp<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + ( + one_of((b'e', b'E')), + opt(one_of([b'+', b'-'])), + cut_err(zero_prefixable_int), + ) + .recognize() + .map(|b: &[u8]| unsafe { + from_utf8_unchecked( + b, + "`one_of` and `parse_zero_prefixable_int` filter out non-ASCII", + ) + }) + .parse_next(input) +} + +// special-float = [ minus / plus ] ( inf / nan ) +pub(crate) fn special_float(input: &mut Input<'_>) -> PResult<f64> { + (opt(one_of((b'+', b'-'))), alt((inf, nan))) + .map(|(s, f)| match s { + Some(b'+') | None => f, + Some(b'-') => -f, + _ => unreachable!("one_of should prevent this"), + }) + .parse_next(input) +} +// inf = %x69.6e.66 ; inf +pub(crate) fn inf(input: &mut Input<'_>) -> PResult<f64> { + tag(INF).value(f64::INFINITY).parse_next(input) +} +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) +} +const NAN: &[u8] = b"nan"; + +// DIGIT = %x30-39 ; 0-9 +pub(crate) fn digit(input: &mut Input<'_>) -> PResult<u8> { + one_of(DIGIT).parse_next(input) +} +const DIGIT: RangeInclusive<u8> = b'0'..=b'9'; + +// HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" +pub(crate) fn hexdig(input: &mut Input<'_>) -> PResult<u8> { + one_of(HEXDIG).parse_next(input) +} +pub(crate) const HEXDIG: (RangeInclusive<u8>, RangeInclusive<u8>, RangeInclusive<u8>) = + (DIGIT, b'A'..=b'F', b'a'..=b'f'); + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn integers() { + let cases = [ + ("+99", 99), + ("42", 42), + ("0", 0), + ("-17", -17), + ("1_000", 1_000), + ("5_349_221", 5_349_221), + ("1_2_3_4_5", 1_2_3_4_5), + ("0xF", 15), + ("0o0_755", 493), + ("0b1_0_1", 5), + (&std::i64::MIN.to_string()[..], std::i64::MIN), + (&std::i64::MAX.to_string()[..], std::i64::MAX), + ]; + for &(input, expected) in &cases { + dbg!(input); + let parsed = integer.parse(new_input(input)); + assert_eq!(parsed, Ok(expected), "Parsing {input:?}"); + } + + let overflow = "1000000000000000000000000000000000"; + let parsed = integer.parse(new_input(overflow)); + assert!(parsed.is_err()); + } + + #[track_caller] + fn assert_float_eq(actual: f64, expected: f64) { + if expected.is_nan() { + assert!(actual.is_nan()); + } else if expected.is_infinite() { + assert!(actual.is_infinite()); + assert_eq!(expected.is_sign_positive(), actual.is_sign_positive()); + } else { + dbg!(expected); + dbg!(actual); + assert!((expected - actual).abs() < std::f64::EPSILON); + } + } + + #[test] + fn floats() { + let cases = [ + ("+1.0", 1.0), + ("3.1419", 3.1419), + ("-0.01", -0.01), + ("5e+22", 5e+22), + ("1e6", 1e6), + ("-2E-2", -2E-2), + ("6.626e-34", 6.626e-34), + ("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), + ("inf", f64::INFINITY), + ("+inf", f64::INFINITY), + ("-inf", f64::NEG_INFINITY), + // ("1e+400", std::f64::INFINITY), + ]; + for &(input, expected) in &cases { + dbg!(input); + let parsed = float.parse(new_input(input)).unwrap(); + assert_float_eq(parsed, expected); + + let overflow = "9e99999"; + let parsed = float.parse(new_input(overflow)); + assert!(parsed.is_err(), "{:?}", parsed); + } + } +} diff --git a/vendor/toml_edit/src/parser/state.rs b/vendor/toml_edit/src/parser/state.rs new file mode 100644 index 0000000..b30ee3f --- /dev/null +++ b/vendor/toml_edit/src/parser/state.rs @@ -0,0 +1,323 @@ +use crate::key::Key; +use crate::parser::errors::CustomError; +use crate::repr::Decor; +use crate::table::TableKeyValue; +use crate::{ArrayOfTables, Document, InternalString, Item, RawString, Table}; + +pub(crate) struct ParseState { + document: Document, + trailing: Option<std::ops::Range<usize>>, + current_table_position: usize, + current_table: Table, + current_is_array: bool, + current_table_path: Vec<Key>, +} + +impl ParseState { + pub(crate) fn into_document(mut self) -> Result<Document, CustomError> { + self.finalize_table()?; + let trailing = self.trailing.map(RawString::with_span); + self.document.trailing = trailing.unwrap_or_default(); + Ok(self.document) + } + + pub(crate) fn on_ws(&mut self, span: std::ops::Range<usize>) { + if let Some(old) = self.trailing.take() { + self.trailing = Some(old.start..span.end); + } else { + self.trailing = Some(span); + } + } + + pub(crate) fn on_comment(&mut self, span: std::ops::Range<usize>) { + if let Some(old) = self.trailing.take() { + self.trailing = Some(old.start..span.end); + } else { + self.trailing = Some(span); + } + } + + pub(crate) fn on_keyval( + &mut self, + mut 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()), + ) { + (Some(p), Some(k)) => Some(p.start..k.end), + (Some(p), None) | (None, Some(p)) => Some(p), + (None, None) => None, + }; + first_key + .decor + .set_prefix(prefix.map(RawString::with_span).unwrap_or_default()); + } + + if let (Some(existing), Some(value)) = (self.current_table.span(), kv.value.span()) { + self.current_table.span = Some((existing.start)..(value.end)); + } + let table = &mut self.current_table; + let table = Self::descend_path(table, &path, true)?; + + // "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) { + indexmap::map::Entry::Vacant(o) => { + o.insert(kv); + } + indexmap::map::Entry::Occupied(o) => { + // "Since tables cannot be defined more than once, redefining such tables using a [table] header is not allowed" + return Err(CustomError::DuplicateKey { + key: o.key().as_str().into(), + table: Some(self.current_table_path.clone()), + }); + } + } + + Ok(()) + } + + pub(crate) fn start_array_table( + &mut self, + path: Vec<Key>, + decor: Decor, + span: std::ops::Range<usize>, + ) -> Result<(), CustomError> { + debug_assert!(!path.is_empty()); + debug_assert!(self.current_table.is_empty()); + debug_assert!(self.current_table_path.is_empty()); + + // Look up the table on start to ensure the duplicate_key error points to the right line + let root = self.document.as_table_mut(); + let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?; + let key = &path[path.len() - 1]; + let entry = parent_table + .entry_format(key) + .or_insert(Item::ArrayOfTables(ArrayOfTables::new())); + entry + .as_array_of_tables() + .ok_or_else(|| CustomError::duplicate_key(&path, path.len() - 1))?; + + self.current_table_position += 1; + self.current_table.decor = decor; + self.current_table.set_implicit(false); + self.current_table.set_dotted(false); + self.current_table.set_position(self.current_table_position); + self.current_table.span = Some(span); + self.current_is_array = true; + self.current_table_path = path; + + Ok(()) + } + + pub(crate) fn start_table( + &mut self, + path: Vec<Key>, + decor: Decor, + span: std::ops::Range<usize>, + ) -> Result<(), CustomError> { + debug_assert!(!path.is_empty()); + debug_assert!(self.current_table.is_empty()); + debug_assert!(self.current_table_path.is_empty()); + + // 1. Look up the table on start to ensure the duplicate_key error points to the right line + // 2. Ensure any child tables from an implicit table are preserved + let root = self.document.as_table_mut(); + let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?; + let key = &path[path.len() - 1]; + if let Some(entry) = parent_table.remove(key.get()) { + match entry { + Item::Table(t) if t.implicit && !t.is_dotted() => { + self.current_table = t; + } + // 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. + _ => return Err(CustomError::duplicate_key(&path, path.len() - 1)), + } + } + + self.current_table_position += 1; + self.current_table.decor = decor; + self.current_table.set_implicit(false); + self.current_table.set_dotted(false); + self.current_table.set_position(self.current_table_position); + self.current_table.span = Some(span); + self.current_is_array = false; + self.current_table_path = path; + + Ok(()) + } + + pub(crate) fn finalize_table(&mut self) -> Result<(), CustomError> { + let mut table = std::mem::take(&mut self.current_table); + let path = std::mem::take(&mut self.current_table_path); + + let root = self.document.as_table_mut(); + if path.is_empty() { + assert!(root.is_empty()); + std::mem::swap(&mut table, root); + } else if self.current_is_array { + let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?; + let key = &path[path.len() - 1]; + + let entry = parent_table + .entry_format(key) + .or_insert(Item::ArrayOfTables(ArrayOfTables::new())); + let array = entry + .as_array_of_tables_mut() + .ok_or_else(|| CustomError::duplicate_key(&path, path.len() - 1))?; + array.push(table); + let span = if let (Some(first), Some(last)) = ( + array.values.first().and_then(|t| t.span()), + array.values.last().and_then(|t| t.span()), + ) { + Some((first.start)..(last.end)) + } else { + None + }; + array.span = span; + } else { + let parent_table = Self::descend_path(root, &path[..path.len() - 1], false)?; + let key = &path[path.len() - 1]; + + let entry = parent_table.entry_format(key); + match entry { + crate::Entry::Occupied(entry) => { + match entry.into_mut() { + // if [a.b.c] header preceded [a.b] + Item::Table(ref mut t) if t.implicit => { + std::mem::swap(t, &mut table); + } + _ => return Err(CustomError::duplicate_key(&path, path.len() - 1)), + } + } + crate::Entry::Vacant(entry) => { + let item = Item::Table(table); + entry.insert(item); + } + } + } + + Ok(()) + } + + pub(crate) fn descend_path<'t, 'k>( + mut table: &'t mut Table, + path: &'k [Key], + dotted: bool, + ) -> Result<&'t mut Table, CustomError> { + for (i, key) in path.iter().enumerate() { + let entry = table.entry_format(key).or_insert_with(|| { + let mut new_table = Table::new(); + new_table.set_implicit(true); + new_table.set_dotted(dotted); + + Item::Table(new_table) + }); + match *entry { + Item::Value(ref v) => { + return Err(CustomError::extend_wrong_type(path, i, v.type_name())); + } + Item::ArrayOfTables(ref mut array) => { + debug_assert!(!array.is_empty()); + + let index = array.len() - 1; + let last_child = array.get_mut(index).unwrap(); + + table = last_child; + } + Item::Table(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; + } + _ => unreachable!(), + } + } + Ok(table) + } + + pub(crate) fn on_std_header( + &mut self, + path: Vec<Key>, + trailing: std::ops::Range<usize>, + span: std::ops::Range<usize>, + ) -> Result<(), CustomError> { + debug_assert!(!path.is_empty()); + + self.finalize_table()?; + let leading = self + .trailing + .take() + .map(RawString::with_span) + .unwrap_or_default(); + self.start_table( + path, + Decor::new(leading, RawString::with_span(trailing)), + span, + )?; + + Ok(()) + } + + pub(crate) fn on_array_header( + &mut self, + path: Vec<Key>, + trailing: std::ops::Range<usize>, + span: std::ops::Range<usize>, + ) -> Result<(), CustomError> { + debug_assert!(!path.is_empty()); + + self.finalize_table()?; + let leading = self + .trailing + .take() + .map(RawString::with_span) + .unwrap_or_default(); + self.start_array_table( + path, + Decor::new(leading, RawString::with_span(trailing)), + span, + )?; + + Ok(()) + } +} + +impl Default for ParseState { + fn default() -> Self { + let mut root = Table::new(); + root.span = Some(0..0); + Self { + document: Document::new(), + trailing: None, + current_table_position: 0, + current_table: root, + current_is_array: false, + current_table_path: Vec::new(), + } + } +} diff --git a/vendor/toml_edit/src/parser/strings.rs b/vendor/toml_edit/src/parser/strings.rs new file mode 100644 index 0000000..26f9cc2 --- /dev/null +++ b/vendor/toml_edit/src/parser/strings.rs @@ -0,0 +1,478 @@ +use std::borrow::Cow; +use std::char; +use std::ops::RangeInclusive; + +use winnow::combinator::alt; +use winnow::combinator::cut_err; +use winnow::combinator::delimited; +use winnow::combinator::fail; +use winnow::combinator::opt; +use winnow::combinator::peek; +use winnow::combinator::preceded; +use winnow::combinator::repeat; +use winnow::combinator::success; +use winnow::combinator::terminated; +use winnow::prelude::*; +use winnow::stream::Stream; +use winnow::token::any; +use winnow::token::none_of; +use winnow::token::one_of; +use winnow::token::tag; +use winnow::token::take_while; +use winnow::trace::trace; + +use crate::parser::errors::CustomError; +use crate::parser::numbers::HEXDIG; +use crate::parser::prelude::*; +use crate::parser::trivia::{from_utf8_unchecked, newline, ws, ws_newlines, NON_ASCII, WSCHAR}; + +// ;; String + +// string = ml-basic-string / basic-string / ml-literal-string / literal-string +pub(crate) fn string<'i>(input: &mut Input<'i>) -> PResult<Cow<'i, str>> { + trace( + "string", + alt(( + ml_basic_string, + basic_string, + ml_literal_string, + literal_string.map(Cow::Borrowed), + )), + ) + .parse_next(input) +} + +// ;; Basic String + +// basic-string = quotation-mark *basic-char quotation-mark +pub(crate) fn basic_string<'i>(input: &mut Input<'i>) -> PResult<Cow<'i, str>> { + trace("basic-string", |input: &mut Input<'i>| { + let _ = one_of(QUOTATION_MARK).parse_next(input)?; + + let mut c = Cow::Borrowed(""); + if let Some(ci) = opt(basic_chars).parse_next(input)? { + c = ci; + } + while let Some(ci) = opt(basic_chars).parse_next(input)? { + c.to_mut().push_str(&ci); + } + + let _ = cut_err(one_of(QUOTATION_MARK)) + .context(StrContext::Label("basic string")) + .parse_next(input)?; + + Ok(c) + }) + .parse_next(input) +} + +// quotation-mark = %x22 ; " +pub(crate) const QUOTATION_MARK: u8 = b'"'; + +// basic-char = basic-unescaped / escaped +fn basic_chars<'i>(input: &mut Input<'i>) -> PResult<Cow<'i, str>> { + alt(( + // Deviate from the official grammar by batching the unescaped chars so we build a string a + // chunk at a time, rather than a `char` at a time. + take_while(1.., BASIC_UNESCAPED) + .try_map(std::str::from_utf8) + .map(Cow::Borrowed), + escaped.map(|c| Cow::Owned(String::from(c))), + )) + .parse_next(input) +} + +// basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii +pub(crate) const BASIC_UNESCAPED: ( + (u8, u8), + u8, + RangeInclusive<u8>, + RangeInclusive<u8>, + RangeInclusive<u8>, +) = (WSCHAR, 0x21, 0x23..=0x5B, 0x5D..=0x7E, NON_ASCII); + +// escaped = escape escape-seq-char +fn escaped(input: &mut Input<'_>) -> PResult<char> { + preceded(ESCAPE, escape_seq_char).parse_next(input) +} + +// escape = %x5C ; \ +pub(crate) const ESCAPE: u8 = b'\\'; + +// escape-seq-char = %x22 ; " quotation mark U+0022 +// escape-seq-char =/ %x5C ; \ reverse solidus U+005C +// escape-seq-char =/ %x62 ; b backspace U+0008 +// escape-seq-char =/ %x66 ; f form feed U+000C +// escape-seq-char =/ %x6E ; n line feed U+000A +// escape-seq-char =/ %x72 ; r carriage return U+000D +// escape-seq-char =/ %x74 ; t tab U+0009 +// escape-seq-char =/ %x75 4HEXDIG ; uXXXX U+XXXX +// escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX U+XXXXXXXX +fn escape_seq_char(input: &mut Input<'_>) -> PResult<char> { + dispatch! {any; + b'b' => success('\u{8}'), + b'f' => success('\u{c}'), + b'n' => success('\n'), + b'r' => success('\r'), + b't' => success('\t'), + b'u' => cut_err(hexescape::<4>).context(StrContext::Label("unicode 4-digit hex code")), + b'U' => cut_err(hexescape::<8>).context(StrContext::Label("unicode 8-digit hex code")), + b'\\' => success('\\'), + b'"' => success('"'), + _ => { + cut_err(fail::<_, char, _>) + .context(StrContext::Label("escape sequence")) + .context(StrContext::Expected(StrContextValue::CharLiteral('b'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('f'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('n'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('r'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('t'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('u'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('U'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('\\'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('"'))) + } + } + .parse_next(input) +} + +pub(crate) fn hexescape<const N: usize>(input: &mut Input<'_>) -> PResult<char> { + take_while(0..=N, HEXDIG) + .verify(|b: &[u8]| b.len() == N) + .map(|b: &[u8]| unsafe { from_utf8_unchecked(b, "`is_ascii_digit` filters out on-ASCII") }) + .verify_map(|s| u32::from_str_radix(s, 16).ok()) + .try_map(|h| char::from_u32(h).ok_or(CustomError::OutOfRange)) + .parse_next(input) +} + +// ;; Multiline Basic String + +// ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body +// ml-basic-string-delim +fn ml_basic_string<'i>(input: &mut Input<'i>) -> PResult<Cow<'i, str>> { + trace( + "ml-basic-string", + delimited( + ML_BASIC_STRING_DELIM, + preceded(opt(newline), cut_err(ml_basic_body)), + cut_err(ML_BASIC_STRING_DELIM), + ) + .context(StrContext::Label("multiline basic string")), + ) + .parse_next(input) +} + +// ml-basic-string-delim = 3quotation-mark +pub(crate) const ML_BASIC_STRING_DELIM: &[u8] = b"\"\"\""; + +// ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ] +fn ml_basic_body<'i>(input: &mut Input<'i>) -> PResult<Cow<'i, str>> { + let mut c = Cow::Borrowed(""); + if let Some(ci) = opt(mlb_content).parse_next(input)? { + c = ci; + } + while let Some(ci) = opt(mlb_content).parse_next(input)? { + c.to_mut().push_str(&ci); + } + + while let Some(qi) = opt(mlb_quotes(none_of(b'\"').value(()))).parse_next(input)? { + if let Some(ci) = opt(mlb_content).parse_next(input)? { + c.to_mut().push_str(qi); + c.to_mut().push_str(&ci); + while let Some(ci) = opt(mlb_content).parse_next(input)? { + c.to_mut().push_str(&ci); + } + } else { + break; + } + } + + if let Some(qi) = opt(mlb_quotes(tag(ML_BASIC_STRING_DELIM).value(()))).parse_next(input)? { + c.to_mut().push_str(qi); + } + + Ok(c) +} + +// mlb-content = mlb-char / newline / mlb-escaped-nl +// mlb-char = mlb-unescaped / escaped +fn mlb_content<'i>(input: &mut Input<'i>) -> PResult<Cow<'i, str>> { + alt(( + // Deviate from the official grammar by batching the unescaped chars so we build a string a + // chunk at a time, rather than a `char` at a time. + take_while(1.., MLB_UNESCAPED) + .try_map(std::str::from_utf8) + .map(Cow::Borrowed), + // Order changed fromg grammar so `escaped` can more easily `cut_err` on bad escape sequences + mlb_escaped_nl.map(|_| Cow::Borrowed("")), + escaped.map(|c| Cow::Owned(String::from(c))), + newline.map(|_| Cow::Borrowed("\n")), + )) + .parse_next(input) +} + +// mlb-quotes = 1*2quotation-mark +fn mlb_quotes<'i>( + mut term: impl winnow::Parser<Input<'i>, (), ContextError>, +) -> impl Parser<Input<'i>, &'i str, ContextError> { + move |input: &mut Input<'i>| { + let start = input.checkpoint(); + let res = terminated(b"\"\"", peek(term.by_ref())) + .map(|b| unsafe { from_utf8_unchecked(b, "`bytes` out non-ASCII") }) + .parse_next(input); + + match res { + Err(winnow::error::ErrMode::Backtrack(_)) => { + input.reset(start); + terminated(b"\"", peek(term.by_ref())) + .map(|b| unsafe { from_utf8_unchecked(b, "`bytes` out non-ASCII") }) + .parse_next(input) + } + res => res, + } + } +} + +// mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii +pub(crate) const MLB_UNESCAPED: ( + (u8, u8), + u8, + RangeInclusive<u8>, + RangeInclusive<u8>, + RangeInclusive<u8>, +) = (WSCHAR, 0x21, 0x23..=0x5B, 0x5D..=0x7E, NON_ASCII); + +// mlb-escaped-nl = escape ws newline *( wschar / newline +// When the last non-whitespace character on a line is a \, +// it will be trimmed along with all whitespace +// (including newlines) up to the next non-whitespace +// character or closing delimiter. +fn mlb_escaped_nl(input: &mut Input<'_>) -> PResult<()> { + repeat(1.., (ESCAPE, ws, ws_newlines)) + .map(|()| ()) + .value(()) + .parse_next(input) +} + +// ;; Literal String + +// literal-string = apostrophe *literal-char apostrophe +pub(crate) fn literal_string<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + trace( + "literal-string", + delimited( + APOSTROPHE, + cut_err(take_while(0.., LITERAL_CHAR)), + cut_err(APOSTROPHE), + ) + .try_map(std::str::from_utf8) + .context(StrContext::Label("literal string")), + ) + .parse_next(input) +} + +// apostrophe = %x27 ; ' apostrophe +pub(crate) const APOSTROPHE: u8 = b'\''; + +// literal-char = %x09 / %x20-26 / %x28-7E / non-ascii +pub(crate) const LITERAL_CHAR: ( + u8, + RangeInclusive<u8>, + RangeInclusive<u8>, + RangeInclusive<u8>, +) = (0x9, 0x20..=0x26, 0x28..=0x7E, NON_ASCII); + +// ;; Multiline Literal String + +// ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body +// ml-literal-string-delim +fn ml_literal_string<'i>(input: &mut Input<'i>) -> PResult<Cow<'i, str>> { + trace( + "ml-literal-string", + delimited( + (ML_LITERAL_STRING_DELIM, opt(newline)), + cut_err(ml_literal_body.map(|t| { + if t.contains("\r\n") { + Cow::Owned(t.replace("\r\n", "\n")) + } else { + Cow::Borrowed(t) + } + })), + cut_err(ML_LITERAL_STRING_DELIM), + ) + .context(StrContext::Label("multiline literal string")), + ) + .parse_next(input) +} + +// ml-literal-string-delim = 3apostrophe +pub(crate) const ML_LITERAL_STRING_DELIM: &[u8] = b"'''"; + +// ml-literal-body = *mll-content *( mll-quotes 1*mll-content ) [ mll-quotes ] +fn ml_literal_body<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + ( + repeat(0.., mll_content).map(|()| ()), + repeat( + 0.., + ( + mll_quotes(none_of(APOSTROPHE).value(())), + repeat(1.., mll_content).map(|()| ()), + ), + ) + .map(|()| ()), + opt(mll_quotes(tag(ML_LITERAL_STRING_DELIM).value(()))), + ) + .recognize() + .try_map(std::str::from_utf8) + .parse_next(input) +} + +// mll-content = mll-char / newline +fn mll_content(input: &mut Input<'_>) -> PResult<u8> { + alt((one_of(MLL_CHAR), newline)).parse_next(input) +} + +// mll-char = %x09 / %x20-26 / %x28-7E / non-ascii +const MLL_CHAR: ( + u8, + RangeInclusive<u8>, + RangeInclusive<u8>, + RangeInclusive<u8>, +) = (0x9, 0x20..=0x26, 0x28..=0x7E, NON_ASCII); + +// mll-quotes = 1*2apostrophe +fn mll_quotes<'i>( + mut term: impl winnow::Parser<Input<'i>, (), ContextError>, +) -> impl Parser<Input<'i>, &'i str, ContextError> { + move |input: &mut Input<'i>| { + let start = input.checkpoint(); + let res = terminated(b"''", peek(term.by_ref())) + .map(|b| unsafe { from_utf8_unchecked(b, "`bytes` out non-ASCII") }) + .parse_next(input); + + match res { + Err(winnow::error::ErrMode::Backtrack(_)) => { + input.reset(start); + terminated(b"'", peek(term.by_ref())) + .map(|b| unsafe { from_utf8_unchecked(b, "`bytes` out non-ASCII") }) + .parse_next(input) + } + res => res, + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn basic_string() { + let input = + r#""I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF. \U0002070E""#; + let expected = "I\'m a string. \"You can quote me\". Name\tJosé\nLocation\tSF. \u{2070E}"; + let parsed = string.parse(new_input(input)); + assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}"); + } + + #[test] + fn ml_basic_string() { + let cases = [ + ( + r#"""" +Roses are red +Violets are blue""""#, + r#"Roses are red +Violets are blue"#, + ), + (r#"""" \""" """"#, " \"\"\" "), + (r#"""" \\""""#, " \\"), + ]; + + for &(input, expected) in &cases { + let parsed = string.parse(new_input(input)); + assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}"); + } + + let invalid_cases = [r#"""" """#, r#"""" \""""#]; + + for input in &invalid_cases { + let parsed = string.parse(new_input(input)); + assert!(parsed.is_err()); + } + } + + #[test] + fn ml_basic_string_escape_ws() { + let inputs = [ + r#"""" +The quick brown \ + + + fox jumps over \ + the lazy dog.""""#, + r#""""\ + The quick brown \ + fox jumps over \ + the lazy dog.\ + """"#, + ]; + for input in &inputs { + let expected = "The quick brown fox jumps over the lazy dog."; + let parsed = string.parse(new_input(input)); + assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}"); + } + let empties = [ + r#""""\ + """"#, + r#"""" +\ + \ +""""#, + ]; + for input in &empties { + let expected = ""; + let parsed = string.parse(new_input(input)); + assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}"); + } + } + + #[test] + fn literal_string() { + let inputs = [ + r#"'C:\Users\nodejs\templates'"#, + r#"'\\ServerX\admin$\system32\'"#, + r#"'Tom "Dubs" Preston-Werner'"#, + r#"'<\i\c*\s*>'"#, + ]; + + for input in &inputs { + let expected = &input[1..input.len() - 1]; + let parsed = string.parse(new_input(input)); + assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}"); + } + } + + #[test] + fn ml_literal_string() { + let inputs = [ + r#"'''I [dw]on't need \d{2} apples'''"#, + r#"''''one_quote''''"#, + ]; + for input in &inputs { + let expected = &input[3..input.len() - 3]; + let parsed = string.parse(new_input(input)); + assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}"); + } + + let input = r#"''' +The first newline is +trimmed in raw strings. + All other whitespace + is preserved. +'''"#; + let expected = &input[4..input.len() - 3]; + let parsed = string.parse(new_input(input)); + assert_eq!(parsed.as_deref(), Ok(expected), "Parsing {input:?}"); + } +} diff --git a/vendor/toml_edit/src/parser/table.rs b/vendor/toml_edit/src/parser/table.rs new file mode 100644 index 0000000..0ace0c7 --- /dev/null +++ b/vendor/toml_edit/src/parser/table.rs @@ -0,0 +1,89 @@ +use std::cell::RefCell; +#[allow(unused_imports)] +use std::ops::DerefMut; + +use winnow::combinator::cut_err; +use winnow::combinator::delimited; +use winnow::combinator::peek; +use winnow::token::take; + +// https://github.com/rust-lang/rust/issues/41358 +use crate::parser::key::key; +use crate::parser::prelude::*; +use crate::parser::state::ParseState; +use crate::parser::trivia::line_trailing; + +// std-table-open = %x5B ws ; [ Left square bracket +pub(crate) const STD_TABLE_OPEN: u8 = b'['; +// std-table-close = ws %x5D ; ] Right square bracket +const STD_TABLE_CLOSE: u8 = b']'; +// array-table-open = %x5B.5B ws ; [[ Double left square bracket +const ARRAY_TABLE_OPEN: &[u8] = b"[["; +// array-table-close = ws %x5D.5D ; ]] Double right quare bracket +const ARRAY_TABLE_CLOSE: &[u8] = b"]]"; + +// ;; Standard Table + +// std-table = std-table-open key *( table-key-sep key) std-table-close +pub(crate) fn std_table<'s, 'i>( + state: &'s RefCell<ParseState>, +) -> impl Parser<Input<'i>, (), ContextError> + 's { + move |i: &mut Input<'i>| { + ( + delimited( + STD_TABLE_OPEN, + cut_err(key), + cut_err(STD_TABLE_CLOSE) + .context(StrContext::Expected(StrContextValue::CharLiteral('.'))) + .context(StrContext::Expected(StrContextValue::StringLiteral("]"))), + ) + .with_span(), + cut_err(line_trailing) + .context(StrContext::Expected(StrContextValue::CharLiteral('\n'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('#'))), + ) + .try_map(|((h, span), t)| state.borrow_mut().deref_mut().on_std_header(h, t, span)) + .parse_next(i) + } +} + +// ;; Array Table + +// array-table = array-table-open key *( table-key-sep key) array-table-close +pub(crate) fn array_table<'s, 'i>( + state: &'s RefCell<ParseState>, +) -> impl Parser<Input<'i>, (), ContextError> + 's { + move |i: &mut Input<'i>| { + ( + delimited( + ARRAY_TABLE_OPEN, + cut_err(key), + cut_err(ARRAY_TABLE_CLOSE) + .context(StrContext::Expected(StrContextValue::CharLiteral('.'))) + .context(StrContext::Expected(StrContextValue::StringLiteral("]]"))), + ) + .with_span(), + cut_err(line_trailing) + .context(StrContext::Expected(StrContextValue::CharLiteral('\n'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('#'))), + ) + .try_map(|((h, span), t)| state.borrow_mut().deref_mut().on_array_header(h, t, span)) + .parse_next(i) + } +} + +// ;; Table + +// table = std-table / array-table +pub(crate) fn table<'s, 'i>( + state: &'s RefCell<ParseState>, +) -> impl Parser<Input<'i>, (), ContextError> + 's { + move |i: &mut Input<'i>| { + dispatch!(peek::<_, &[u8],_,_>(take(2usize)); + b"[[" => array_table(state), + _ => std_table(state), + ) + .context(StrContext::Label("table header")) + .parse_next(i) + } +} diff --git a/vendor/toml_edit/src/parser/trivia.rs b/vendor/toml_edit/src/parser/trivia.rs new file mode 100644 index 0000000..a359805 --- /dev/null +++ b/vendor/toml_edit/src/parser/trivia.rs @@ -0,0 +1,156 @@ +use std::ops::RangeInclusive; + +use winnow::combinator::alt; +use winnow::combinator::eof; +use winnow::combinator::opt; +use winnow::combinator::repeat; +use winnow::combinator::terminated; +use winnow::prelude::*; +use winnow::token::one_of; +use winnow::token::take_while; + +use crate::parser::prelude::*; + +pub(crate) unsafe fn from_utf8_unchecked<'b>( + bytes: &'b [u8], + safety_justification: &'static str, +) -> &'b str { + if cfg!(debug_assertions) { + // Catch problems more quickly when testing + std::str::from_utf8(bytes).expect(safety_justification) + } else { + std::str::from_utf8_unchecked(bytes) + } +} + +// wschar = ( %x20 / ; Space +// %x09 ) ; Horizontal tab +pub(crate) const WSCHAR: (u8, u8) = (b' ', b'\t'); + +// ws = *wschar +pub(crate) fn ws<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + take_while(0.., WSCHAR) + .map(|b| unsafe { from_utf8_unchecked(b, "`is_wschar` filters out on-ASCII") }) + .parse_next(input) +} + +// non-ascii = %x80-D7FF / %xE000-10FFFF +// - ASCII is 0xxxxxxx +// - First byte for UTF-8 is 11xxxxxx +// - Subsequent UTF-8 bytes are 10xxxxxx +pub(crate) const NON_ASCII: RangeInclusive<u8> = 0x80..=0xff; + +// non-eol = %x09 / %x20-7E / non-ascii +pub(crate) const NON_EOL: (u8, RangeInclusive<u8>, RangeInclusive<u8>) = + (0x09, 0x20..=0x7E, NON_ASCII); + +// comment-start-symbol = %x23 ; # +pub(crate) const COMMENT_START_SYMBOL: u8 = b'#'; + +// comment = comment-start-symbol *non-eol +pub(crate) fn comment<'i>(input: &mut Input<'i>) -> PResult<&'i [u8]> { + (COMMENT_START_SYMBOL, take_while(0.., NON_EOL)) + .recognize() + .parse_next(input) +} + +// newline = ( %x0A / ; LF +// %x0D.0A ) ; CRLF +pub(crate) fn newline(input: &mut Input<'_>) -> PResult<u8> { + alt(( + one_of(LF).value(b'\n'), + (one_of(CR), one_of(LF)).value(b'\n'), + )) + .parse_next(input) +} +pub(crate) const LF: u8 = b'\n'; +pub(crate) const CR: u8 = b'\r'; + +// ws-newline = *( wschar / newline ) +pub(crate) fn ws_newline<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + repeat( + 0.., + alt((newline.value(&b"\n"[..]), take_while(1.., WSCHAR))), + ) + .map(|()| ()) + .recognize() + .map(|b| unsafe { from_utf8_unchecked(b, "`is_wschar` and `newline` filters out on-ASCII") }) + .parse_next(input) +} + +// ws-newlines = newline *( wschar / newline ) +pub(crate) fn ws_newlines<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + (newline, ws_newline) + .recognize() + .map(|b| unsafe { + from_utf8_unchecked(b, "`is_wschar` and `newline` filters out on-ASCII") + }) + .parse_next(input) +} + +// note: this rule is not present in the original grammar +// ws-comment-newline = *( ws-newline-nonempty / comment ) +pub(crate) fn ws_comment_newline<'i>(input: &mut Input<'i>) -> PResult<&'i [u8]> { + repeat( + 0.., + alt(( + repeat( + 1.., + alt((take_while(1.., WSCHAR), newline.value(&b"\n"[..]))), + ) + .map(|()| ()), + comment.value(()), + )), + ) + .map(|()| ()) + .recognize() + .parse_next(input) +} + +// note: this rule is not present in the original grammar +// line-ending = newline / eof +pub(crate) fn line_ending<'i>(input: &mut Input<'i>) -> PResult<&'i str> { + alt((newline.value("\n"), eof.value(""))).parse_next(input) +} + +// note: this rule is not present in the original grammar +// line-trailing = ws [comment] skip-line-ending +pub(crate) fn line_trailing(input: &mut Input<'_>) -> PResult<std::ops::Range<usize>> { + terminated((ws, opt(comment)).span(), line_ending).parse_next(input) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn trivia() { + let inputs = [ + "", + r#" "#, + r#" +"#, + r#" +# comment + +# comment2 + + +"#, + r#" + "#, + r#"# comment +# comment2 + + + "#, + ]; + for input in inputs { + dbg!(input); + let parsed = ws_comment_newline.parse(new_input(input)); + assert!(parsed.is_ok(), "{:?}", parsed); + let parsed = parsed.unwrap(); + assert_eq!(parsed, input.as_bytes()); + } + } +} diff --git a/vendor/toml_edit/src/parser/value.rs b/vendor/toml_edit/src/parser/value.rs new file mode 100644 index 0000000..14cd951 --- /dev/null +++ b/vendor/toml_edit/src/parser/value.rs @@ -0,0 +1,155 @@ +use winnow::combinator::alt; +use winnow::combinator::fail; +use winnow::combinator::peek; +use winnow::token::any; + +use crate::parser::array::array; +use crate::parser::datetime::date_time; +use crate::parser::inline_table::inline_table; +use crate::parser::numbers::{float, integer}; +use crate::parser::prelude::*; +use crate::parser::strings::string; +use crate::repr::{Formatted, Repr}; +use crate::value as v; +use crate::RawString; +use crate::Value; + +// val = string / boolean / array / inline-table / date-time / float / integer +pub(crate) fn value<'i>(check: RecursionCheck) -> impl Parser<Input<'i>, v::Value, ContextError> { + move |input: &mut Input<'i>| { + dispatch!{peek(any); + crate::parser::strings::QUOTATION_MARK | + crate::parser::strings::APOSTROPHE => string.map(|s| { + v::Value::String(Formatted::new( + s.into_owned() + )) + }), + crate::parser::array::ARRAY_OPEN => array(check).map(v::Value::Array), + crate::parser::inline_table::INLINE_TABLE_OPEN => inline_table(check).map(v::Value::InlineTable), + // Date/number starts + b'+' | b'-' | b'0'..=b'9' => { + // Uncommon enough not to be worth optimizing at this time + alt(( + date_time + .map(v::Value::from), + float + .map(v::Value::from), + integer + .map(v::Value::from), + )) + }, + // Report as if they were numbers because its most likely a typo + b'_' => { + integer + .map(v::Value::from) + .context(StrContext::Expected(StrContextValue::Description("leading digit"))) + }, + // Report as if they were numbers because its most likely a typo + b'.' => { + float + .map(v::Value::from) + .context(StrContext::Expected(StrContextValue::Description("leading digit"))) + }, + b't' => { + crate::parser::numbers::true_.map(v::Value::from) + .context(StrContext::Label("string")) + .context(StrContext::Expected(StrContextValue::CharLiteral('"'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('\''))) + }, + b'f' => { + crate::parser::numbers::false_.map(v::Value::from) + .context(StrContext::Label("string")) + .context(StrContext::Expected(StrContextValue::CharLiteral('"'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('\''))) + }, + b'i' => { + crate::parser::numbers::inf.map(v::Value::from) + .context(StrContext::Label("string")) + .context(StrContext::Expected(StrContextValue::CharLiteral('"'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('\''))) + }, + b'n' => { + crate::parser::numbers::nan.map(v::Value::from) + .context(StrContext::Label("string")) + .context(StrContext::Expected(StrContextValue::CharLiteral('"'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('\''))) + }, + _ => { + fail + .context(StrContext::Label("string")) + .context(StrContext::Expected(StrContextValue::CharLiteral('"'))) + .context(StrContext::Expected(StrContextValue::CharLiteral('\''))) + }, + } + .with_span() + .try_map(|(value, span)| apply_raw(value, span)) + .parse_next(input) + } +} + +fn apply_raw(mut val: Value, span: std::ops::Range<usize>) -> Result<Value, std::str::Utf8Error> { + match val { + Value::String(ref mut f) => { + let raw = RawString::with_span(span); + f.set_repr_unchecked(Repr::new_unchecked(raw)); + } + Value::Integer(ref mut f) => { + let raw = RawString::with_span(span); + f.set_repr_unchecked(Repr::new_unchecked(raw)); + } + Value::Float(ref mut f) => { + let raw = RawString::with_span(span); + f.set_repr_unchecked(Repr::new_unchecked(raw)); + } + Value::Boolean(ref mut f) => { + let raw = RawString::with_span(span); + f.set_repr_unchecked(Repr::new_unchecked(raw)); + } + Value::Datetime(ref mut f) => { + let raw = RawString::with_span(span); + f.set_repr_unchecked(Repr::new_unchecked(raw)); + } + Value::Array(ref mut arr) => { + arr.span = Some(span); + } + Value::InlineTable(ref mut table) => { + table.span = Some(span); + } + }; + val.decorate("", ""); + Ok(val) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn values() { + let inputs = [ + "1979-05-27T00:32:00.999999", + "-239", + "1e200", + "9_224_617.445_991_228_313", + r#"'''I [dw]on't need \d{2} apples'''"#, + r#"''' +The first newline is +trimmed in raw strings. + All other whitespace + is preserved. +'''"#, + r#""Jos\u00E9\n""#, + r#""\\\"\b/\f\n\r\t\u00E9\U000A0000""#, + r#"{ hello = "world", a = 1}"#, + r#"[ { x = 1, a = "2" }, {a = "a",b = "b", c = "c"} ]"#, + ]; + for input in inputs { + dbg!(input); + let mut parsed = value(Default::default()).parse(new_input(input)); + if let Ok(parsed) = &mut parsed { + parsed.despan(input); + } + assert_eq!(parsed.map(|a| a.to_string()), Ok(input.to_owned())); + } + } +} diff --git a/vendor/toml_edit/src/raw_string.rs b/vendor/toml_edit/src/raw_string.rs new file mode 100644 index 0000000..c5961f1 --- /dev/null +++ b/vendor/toml_edit/src/raw_string.rs @@ -0,0 +1,182 @@ +use crate::InternalString; + +/// Opaque string storage for raw TOML; internal to `toml_edit` +#[derive(PartialEq, Eq, Clone, Hash)] +pub struct RawString(RawStringInner); + +#[derive(PartialEq, Eq, Clone, Hash)] +enum RawStringInner { + Empty, + Explicit(InternalString), + Spanned(std::ops::Range<usize>), +} + +impl RawString { + pub(crate) fn with_span(span: std::ops::Range<usize>) -> Self { + if span.start == span.end { + RawString(RawStringInner::Empty) + } else { + RawString(RawStringInner::Spanned(span)) + } + } + + /// Access the underlying string + pub fn as_str(&self) -> Option<&str> { + match &self.0 { + RawStringInner::Empty => Some(""), + RawStringInner::Explicit(s) => Some(s.as_str()), + RawStringInner::Spanned(_) => None, + } + } + + pub(crate) fn to_str<'s>(&'s self, input: &'s str) -> &'s str { + match &self.0 { + RawStringInner::Empty => "", + RawStringInner::Explicit(s) => s.as_str(), + RawStringInner::Spanned(span) => input.get(span.clone()).unwrap_or_else(|| { + panic!("span {:?} should be in input:\n```\n{}\n```", span, input) + }), + } + } + + pub(crate) fn to_str_with_default<'s>( + &'s self, + input: Option<&'s str>, + default: &'s str, + ) -> &'s str { + match &self.0 { + RawStringInner::Empty => "", + RawStringInner::Explicit(s) => s.as_str(), + RawStringInner::Spanned(span) => { + if let Some(input) = input { + input.get(span.clone()).unwrap_or_else(|| { + panic!("span {:?} should be in input:\n```\n{}\n```", span, input) + }) + } else { + default + } + } + } + } + + /// Access the underlying span + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + match &self.0 { + RawStringInner::Empty => None, + RawStringInner::Explicit(_) => None, + RawStringInner::Spanned(span) => Some(span.clone()), + } + } + + pub(crate) fn despan(&mut self, input: &str) { + match &self.0 { + RawStringInner::Empty => {} + RawStringInner::Explicit(_) => {} + RawStringInner::Spanned(span) => { + *self = Self::from(input.get(span.clone()).unwrap_or_else(|| { + panic!("span {:?} should be in input:\n```\n{}\n```", span, input) + })) + } + } + } + + 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') { + write!(buf, "{}", part)?; + } + Ok(()) + } + + pub(crate) fn encode_with_default( + &self, + buf: &mut dyn std::fmt::Write, + input: Option<&str>, + default: &str, + ) -> std::fmt::Result { + let raw = self.to_str_with_default(input, default); + for part in raw.split('\r') { + write!(buf, "{}", part)?; + } + Ok(()) + } +} + +impl Default for RawString { + fn default() -> Self { + Self(RawStringInner::Empty) + } +} + +impl std::fmt::Debug for RawString { + #[inline] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + match &self.0 { + RawStringInner::Empty => write!(formatter, "empty"), + RawStringInner::Explicit(s) => write!(formatter, "{:?}", s), + RawStringInner::Spanned(s) => write!(formatter, "{:?}", s), + } + } +} + +impl From<&str> for RawString { + #[inline] + fn from(s: &str) -> Self { + if s.is_empty() { + Self(RawStringInner::Empty) + } else { + InternalString::from(s).into() + } + } +} + +impl From<String> for RawString { + #[inline] + fn from(s: String) -> Self { + if s.is_empty() { + Self(RawStringInner::Empty) + } else { + InternalString::from(s).into() + } + } +} + +impl From<&String> for RawString { + #[inline] + fn from(s: &String) -> Self { + if s.is_empty() { + Self(RawStringInner::Empty) + } else { + InternalString::from(s).into() + } + } +} + +impl From<InternalString> for RawString { + #[inline] + fn from(inner: InternalString) -> Self { + Self(RawStringInner::Explicit(inner)) + } +} + +impl From<&InternalString> for RawString { + #[inline] + fn from(s: &InternalString) -> Self { + if s.is_empty() { + Self(RawStringInner::Empty) + } else { + InternalString::from(s).into() + } + } +} + +impl From<Box<str>> for RawString { + #[inline] + fn from(s: Box<str>) -> Self { + if s.is_empty() { + Self(RawStringInner::Empty) + } else { + InternalString::from(s).into() + } + } +} diff --git a/vendor/toml_edit/src/repr.rs b/vendor/toml_edit/src/repr.rs new file mode 100644 index 0000000..d4ab6c2 --- /dev/null +++ b/vendor/toml_edit/src/repr.rs @@ -0,0 +1,253 @@ +use std::borrow::Cow; + +use crate::RawString; + +/// A value together with its `to_string` representation, +/// including surrounding it whitespaces and comments. +#[derive(Eq, PartialEq, Clone, Hash)] +pub struct Formatted<T> { + value: T, + repr: Option<Repr>, + decor: Decor, +} + +impl<T> Formatted<T> +where + T: ValueRepr, +{ + /// Default-formatted value + pub fn new(value: T) -> Self { + Self { + value, + repr: None, + decor: Default::default(), + } + } + + pub(crate) fn set_repr_unchecked(&mut self, repr: Repr) { + self.repr = Some(repr); + } + + /// The wrapped value + pub fn value(&self) -> &T { + &self.value + } + + /// The wrapped value + pub fn into_value(self) -> T { + self.value + } + + /// Returns the raw representation, if available. + pub fn as_repr(&self) -> Option<&Repr> { + self.repr.as_ref() + } + + /// Returns the default raw representation. + pub fn default_repr(&self) -> Repr { + self.value.to_repr() + } + + /// Returns a raw representation. + pub fn display_repr(&self) -> Cow<str> { + self.as_repr() + .and_then(|r| r.as_raw().as_str()) + .map(Cow::Borrowed) + .unwrap_or_else(|| { + Cow::Owned(self.default_repr().as_raw().as_str().unwrap().to_owned()) + }) + } + + /// Returns the location within the original document + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + self.repr.as_ref().and_then(|r| r.span()) + } + + pub(crate) fn despan(&mut self, input: &str) { + self.decor.despan(input); + if let Some(repr) = &mut self.repr { + repr.despan(input); + } + } + + /// Returns the surrounding whitespace + pub fn decor_mut(&mut self) -> &mut Decor { + &mut self.decor + } + + /// Returns the surrounding whitespace + pub fn decor(&self) -> &Decor { + &self.decor + } + + /// Auto formats the value. + pub fn fmt(&mut self) { + self.repr = Some(self.value.to_repr()); + } +} + +impl<T> std::fmt::Debug for Formatted<T> +where + T: std::fmt::Debug, +{ + #[inline] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + let mut d = formatter.debug_struct("Formatted"); + d.field("value", &self.value); + match &self.repr { + Some(r) => d.field("repr", r), + None => d.field("repr", &"default"), + }; + d.field("decor", &self.decor); + d.finish() + } +} + +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, ("", "")) + } +} + +pub trait ValueRepr: crate::private::Sealed { + /// The TOML representation of the value + fn to_repr(&self) -> Repr; +} + +/// TOML-encoded value +#[derive(Eq, PartialEq, Clone, Hash)] +pub struct Repr { + raw_value: RawString, +} + +impl Repr { + pub(crate) fn new_unchecked(raw: impl Into<RawString>) -> Self { + Repr { + raw_value: raw.into(), + } + } + + /// Access the underlying value + pub fn as_raw(&self) -> &RawString { + &self.raw_value + } + + /// Returns the location within the original document + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + self.raw_value.span() + } + + pub(crate) fn despan(&mut self, input: &str) { + self.raw_value.despan(input) + } + + pub(crate) fn encode(&self, buf: &mut dyn std::fmt::Write, input: &str) -> std::fmt::Result { + self.as_raw().encode(buf, input) + } +} + +impl std::fmt::Debug for Repr { + #[inline] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + self.raw_value.fmt(formatter) + } +} + +/// A prefix and suffix, +/// +/// Including comments, whitespaces and newlines. +#[derive(Eq, PartialEq, Clone, Default, Hash)] +pub struct Decor { + prefix: Option<RawString>, + suffix: Option<RawString>, +} + +impl Decor { + /// Creates a new decor from the given prefix and suffix. + pub fn new(prefix: impl Into<RawString>, suffix: impl Into<RawString>) -> Self { + Self { + prefix: Some(prefix.into()), + suffix: Some(suffix.into()), + } + } + + /// Go back to default decor + pub fn clear(&mut self) { + self.prefix = None; + self.suffix = None; + } + + /// Get the prefix. + pub fn prefix(&self) -> Option<&RawString> { + self.prefix.as_ref() + } + + pub(crate) fn prefix_encode( + &self, + buf: &mut dyn std::fmt::Write, + input: Option<&str>, + default: &str, + ) -> std::fmt::Result { + if let Some(prefix) = self.prefix() { + prefix.encode_with_default(buf, input, default) + } else { + write!(buf, "{}", default) + } + } + + /// Set the prefix. + pub fn set_prefix(&mut self, prefix: impl Into<RawString>) { + self.prefix = Some(prefix.into()); + } + + /// Get the suffix. + pub fn suffix(&self) -> Option<&RawString> { + self.suffix.as_ref() + } + + pub(crate) fn suffix_encode( + &self, + buf: &mut dyn std::fmt::Write, + input: Option<&str>, + default: &str, + ) -> std::fmt::Result { + if let Some(suffix) = self.suffix() { + suffix.encode_with_default(buf, input, default) + } else { + write!(buf, "{}", default) + } + } + + /// Set the suffix. + pub fn set_suffix(&mut self, suffix: impl Into<RawString>) { + self.suffix = Some(suffix.into()); + } + + pub(crate) fn despan(&mut self, input: &str) { + if let Some(prefix) = &mut self.prefix { + prefix.despan(input); + } + if let Some(suffix) = &mut self.suffix { + suffix.despan(input); + } + } +} + +impl std::fmt::Debug for Decor { + #[inline] + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + let mut d = formatter.debug_struct("Decor"); + match &self.prefix { + Some(r) => d.field("prefix", r), + None => d.field("prefix", &"default"), + }; + match &self.suffix { + Some(r) => d.field("suffix", r), + None => d.field("suffix", &"default"), + }; + d.finish() + } +} diff --git a/vendor/toml_edit/src/ser/array.rs b/vendor/toml_edit/src/ser/array.rs new file mode 100644 index 0000000..80eba8b --- /dev/null +++ b/vendor/toml_edit/src/ser/array.rs @@ -0,0 +1,84 @@ +use super::Error; + +#[doc(hidden)] +pub struct SerializeValueArray { + values: Vec<crate::Item>, +} + +impl SerializeValueArray { + pub(crate) fn new() -> Self { + Self { values: Vec::new() } + } + + pub(crate) fn with_capacity(len: usize) -> Self { + Self { + values: Vec::with_capacity(len), + } + } +} + +impl serde::ser::SerializeSeq for SerializeValueArray { + type Ok = crate::Value; + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + let value = value.serialize(super::ValueSerializer {})?; + self.values.push(crate::Item::Value(value)); + Ok(()) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(crate::Value::Array(crate::Array::with_vec(self.values))) + } +} + +impl serde::ser::SerializeTuple for SerializeValueArray { + type Ok = crate::Value; + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize, + { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + serde::ser::SerializeSeq::end(self) + } +} + +impl serde::ser::SerializeTupleVariant for 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(self, value) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + serde::ser::SerializeSeq::end(self) + } +} + +impl serde::ser::SerializeTupleStruct for 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(self, value) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + serde::ser::SerializeSeq::end(self) + } +} diff --git a/vendor/toml_edit/src/ser/key.rs b/vendor/toml_edit/src/ser/key.rs new file mode 100644 index 0000000..d5e381b --- /dev/null +++ b/vendor/toml_edit/src/ser/key.rs @@ -0,0 +1,173 @@ +use crate::InternalString; + +use super::Error; + +pub(crate) struct KeySerializer; + +impl serde::ser::Serializer for KeySerializer { + type Ok = InternalString; + type Error = Error; + type SerializeSeq = serde::ser::Impossible<InternalString, Error>; + type SerializeTuple = serde::ser::Impossible<InternalString, Error>; + type SerializeTupleStruct = serde::ser::Impossible<InternalString, Error>; + type SerializeTupleVariant = serde::ser::Impossible<InternalString, Error>; + type SerializeMap = serde::ser::Impossible<InternalString, Error>; + type SerializeStruct = serde::ser::Impossible<InternalString, Error>; + type SerializeStructVariant = serde::ser::Impossible<InternalString, Error>; + + fn serialize_bool(self, _v: bool) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_i8(self, _v: i8) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_i16(self, _v: i16) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_i32(self, _v: i32) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_i64(self, _v: i64) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_u8(self, _v: u8) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_u16(self, _v: u16) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_u32(self, _v: u32) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_u64(self, _v: u64) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_f32(self, _v: f32) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_f64(self, _v: f64) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_char(self, _v: char) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_str(self, value: &str) -> Result<InternalString, Self::Error> { + Ok(InternalString::from(value)) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_none(self) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<InternalString, Self::Error> + where + T: serde::ser::Serialize, + { + Err(Error::KeyNotString) + } + + fn serialize_unit(self) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<InternalString, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result<InternalString, Self::Error> { + Ok(variant.into()) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + value: &T, + ) -> Result<InternalString, Self::Error> + where + T: serde::ser::Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result<InternalString, Self::Error> + where + T: serde::ser::Serialize, + { + Err(Error::KeyNotString) + } + + fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error::KeyNotString) + } +} diff --git a/vendor/toml_edit/src/ser/map.rs b/vendor/toml_edit/src/ser/map.rs new file mode 100644 index 0000000..951a5cb --- /dev/null +++ b/vendor/toml_edit/src/ser/map.rs @@ -0,0 +1,587 @@ +use super::{Error, KeySerializer, ValueSerializer}; + +#[doc(hidden)] +pub enum SerializeMap { + Datetime(SerializeDatetime), + Table(SerializeInlineTable), +} + +impl SerializeMap { + pub(crate) fn table() -> Self { + Self::Table(SerializeInlineTable::new()) + } + + pub(crate) fn table_with_capacity(len: usize) -> Self { + Self::Table(SerializeInlineTable::with_capacity(len)) + } + + pub(crate) fn datetime() -> Self { + Self::Datetime(SerializeDatetime::new()) + } +} + +impl serde::ser::SerializeMap for SerializeMap { + type Ok = crate::Value; + type Error = Error; + + fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + match self { + Self::Datetime(s) => s.serialize_key(input), + Self::Table(s) => s.serialize_key(input), + } + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + match self { + Self::Datetime(s) => s.serialize_value(value), + Self::Table(s) => s.serialize_value(value), + } + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + match self { + Self::Datetime(s) => s.end().map(|items| items.into()), + Self::Table(s) => s.end().map(|items| items.into()), + } + } +} + +impl serde::ser::SerializeStruct for SerializeMap { + type Ok = crate::Value; + type Error = Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + match self { + Self::Datetime(s) => s.serialize_field(key, value), + Self::Table(s) => s.serialize_field(key, value), + } + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + match self { + Self::Datetime(s) => s.end().map(|items| items.into()), + Self::Table(s) => s.end().map(|items| items.into()), + } + } +} + +#[doc(hidden)] +pub struct SerializeDatetime { + value: Option<crate::Datetime>, +} + +impl SerializeDatetime { + pub(crate) fn new() -> Self { + Self { value: None } + } +} + +impl serde::ser::SerializeMap for SerializeDatetime { + type Ok = crate::Datetime; + type Error = Error; + + fn serialize_key<T: ?Sized>(&mut self, _input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + unreachable!("datetimes should only be serialized as structs, not maps") + } + + fn serialize_value<T: ?Sized>(&mut self, _value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + unreachable!("datetimes should only be serialized as structs, not maps") + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + unreachable!("datetimes should only be serialized as structs, not maps") + } +} + +impl serde::ser::SerializeStruct for SerializeDatetime { + type Ok = crate::Datetime; + type Error = Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + if key == toml_datetime::__unstable::FIELD { + self.value = Some(value.serialize(DatetimeFieldSerializer::default())?); + } + + Ok(()) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + self.value.ok_or(Error::UnsupportedNone) + } +} + +#[doc(hidden)] +pub struct SerializeInlineTable { + items: crate::table::KeyValuePairs, + key: Option<crate::InternalString>, +} + +impl SerializeInlineTable { + pub(crate) fn new() -> Self { + Self { + items: Default::default(), + key: Default::default(), + } + } + + pub(crate) fn with_capacity(len: usize) -> Self { + let mut s = Self::new(); + s.items.reserve(len); + s + } +} + +impl serde::ser::SerializeMap for SerializeInlineTable { + type Ok = crate::InlineTable; + type Error = Error; + + fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + self.key = None; + self.key = Some(input.serialize(KeySerializer)?); + Ok(()) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + let mut value_serializer = MapValueSerializer::new(); + let res = value.serialize(&mut value_serializer); + match res { + Ok(item) => { + let key = self.key.take().unwrap(); + let kv = crate::table::TableKeyValue::new( + crate::Key::new(&key), + crate::Item::Value(item), + ); + self.items.insert(key, kv); + } + Err(e) => { + if !(e == Error::UnsupportedNone && value_serializer.is_none) { + return Err(e); + } + } + } + Ok(()) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(crate::InlineTable::with_pairs(self.items)) + } +} + +impl serde::ser::SerializeStruct for SerializeInlineTable { + type Ok = crate::InlineTable; + type Error = Error; + + fn serialize_field<T: ?Sized>( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::ser::Serialize, + { + let mut value_serializer = MapValueSerializer::new(); + let res = value.serialize(&mut value_serializer); + match res { + Ok(item) => { + let kv = crate::table::TableKeyValue::new( + crate::Key::new(key), + crate::Item::Value(item), + ); + self.items.insert(crate::InternalString::from(key), kv); + } + Err(e) => { + if !(e == Error::UnsupportedNone && value_serializer.is_none) { + return Err(e); + } + } + }; + Ok(()) + } + + fn end(self) -> Result<Self::Ok, Self::Error> { + Ok(crate::InlineTable::with_pairs(self.items)) + } +} + +#[derive(Default)] +struct DatetimeFieldSerializer {} + +impl serde::ser::Serializer for DatetimeFieldSerializer { + type Ok = toml_datetime::Datetime; + type Error = Error; + type SerializeSeq = serde::ser::Impossible<Self::Ok, Self::Error>; + type SerializeTuple = serde::ser::Impossible<Self::Ok, Self::Error>; + type SerializeTupleStruct = serde::ser::Impossible<Self::Ok, Self::Error>; + type SerializeTupleVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + type SerializeMap = serde::ser::Impossible<Self::Ok, Self::Error>; + type SerializeStruct = serde::ser::Impossible<Self::Ok, Self::Error>; + type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + + fn serialize_bool(self, _value: bool) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_i8(self, _value: i8) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_i16(self, _value: i16) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_i32(self, _value: i32) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_i64(self, _value: i64) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_u8(self, _value: u8) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_u16(self, _value: u16) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_u32(self, _value: u32) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_u64(self, _value: u64) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_f32(self, _value: f32) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_f64(self, _value: f64) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_char(self, _value: char) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + v.parse::<toml_datetime::Datetime>().map_err(Error::custom) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + Err(Error::DateInvalid) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + _value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + Err(Error::DateInvalid) + } + + 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, + { + Err(Error::DateInvalid) + } + + fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + Err(Error::DateInvalid) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + 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::SerializeValueArray; + type SerializeMap = super::SerializeMap; + type SerializeStruct = super::SerializeMap; + type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + + 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) + } +} diff --git a/vendor/toml_edit/src/ser/mod.rs b/vendor/toml_edit/src/ser/mod.rs new file mode 100644 index 0000000..7f99930 --- /dev/null +++ b/vendor/toml_edit/src/ser/mod.rs @@ -0,0 +1,165 @@ +//! Serializing Rust structures into TOML. +//! +//! This module contains all the Serde support for serializing Rust structures into TOML. + +mod array; +mod key; +mod map; +mod pretty; +mod value; + +pub(crate) use array::*; +pub(crate) use key::*; +pub(crate) use map::*; + +use crate::visit_mut::VisitMut; + +/// Errors that can occur when deserializing a type. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum Error { + /// Type could not be serialized to TOML + UnsupportedType(Option<&'static str>), + /// Value was out of range for the given type + OutOfRange(Option<&'static str>), + /// `None` could not be serialized to TOML + UnsupportedNone, + /// Key was not convertible to `String` for serializing to TOML + KeyNotString, + /// A serialized date was invalid + DateInvalid, + /// Other serialization error + Custom(String), +} + +impl Error { + pub(crate) fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::Custom(msg.to_string()) + } +} + +impl serde::ser::Error for Error { + fn custom<T>(msg: T) -> Self + where + T: std::fmt::Display, + { + Self::custom(msg) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::UnsupportedType(Some(t)) => write!(formatter, "unsupported {t} type"), + Self::UnsupportedType(None) => write!(formatter, "unsupported rust type"), + Self::OutOfRange(Some(t)) => write!(formatter, "out-of-range value for {t} type"), + Self::OutOfRange(None) => write!(formatter, "out-of-range value"), + Self::UnsupportedNone => "unsupported None value".fmt(formatter), + Self::KeyNotString => "map key was not a string".fmt(formatter), + Self::DateInvalid => "a serialized date was invalid".fmt(formatter), + Self::Custom(s) => s.fmt(formatter), + } + } +} + +impl From<crate::TomlError> for Error { + fn from(e: crate::TomlError) -> Error { + Self::custom(e) + } +} + +impl From<Error> for crate::TomlError { + fn from(e: Error) -> crate::TomlError { + Self::custom(e.to_string(), None) + } +} + +impl std::error::Error for Error {} + +/// Serialize the given data structure as a TOML byte vector. +/// +/// 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. +pub fn to_vec<T: ?Sized>(value: &T) -> Result<Vec<u8>, Error> +where + T: serde::ser::Serialize, +{ + to_string(value).map(|e| e.into_bytes()) +} + +/// Serialize the given data structure as a String of TOML. +/// +/// 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. +/// +/// # Examples +/// +/// ``` +/// use serde::Serialize; +/// +/// #[derive(Serialize)] +/// struct Config { +/// database: Database, +/// } +/// +/// #[derive(Serialize)] +/// struct Database { +/// ip: String, +/// port: Vec<u16>, +/// connection_max: u32, +/// enabled: bool, +/// } +/// +/// let config = Config { +/// database: Database { +/// ip: "192.168.1.1".to_string(), +/// port: vec![8001, 8002, 8003], +/// connection_max: 5000, +/// enabled: false, +/// }, +/// }; +/// +/// let toml = toml_edit::ser::to_string(&config).unwrap(); +/// println!("{}", toml) +/// ``` +pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error> +where + T: serde::ser::Serialize, +{ + to_document(value).map(|e| e.to_string()) +} + +/// Serialize the given data structure as a "pretty" String of TOML. +/// +/// This is identical to `to_string` except the output string has a more +/// "pretty" output. See `ValueSerializer::pretty` for more details. +pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error> +where + T: serde::ser::Serialize, +{ + let mut document = to_document(value)?; + pretty::Pretty.visit_document_mut(&mut document); + Ok(document.to_string()) +} + +/// Serialize the given data structure into a TOML document. +/// +/// This would allow custom formatting to be applied, mixing with format preserving edits, etc. +pub fn to_document<T: ?Sized>(value: &T) -> Result<crate::Document, Error> +where + T: serde::ser::Serialize, +{ + let value = value.serialize(ValueSerializer::new())?; + let item = crate::Item::Value(value); + let root = item + .into_table() + .map_err(|_| Error::UnsupportedType(None))?; + Ok(root.into()) +} + +pub use value::ValueSerializer; diff --git a/vendor/toml_edit/src/ser/pretty.rs b/vendor/toml_edit/src/ser/pretty.rs new file mode 100644 index 0000000..2c22f68 --- /dev/null +++ b/vendor/toml_edit/src/ser/pretty.rs @@ -0,0 +1,45 @@ +pub(crate) struct Pretty; + +impl crate::visit_mut::VisitMut for Pretty { + fn visit_document_mut(&mut self, node: &mut crate::Document) { + crate::visit_mut::visit_document_mut(self, node); + } + + fn visit_item_mut(&mut self, node: &mut crate::Item) { + node.make_item(); + + crate::visit_mut::visit_item_mut(self, node); + } + + fn visit_table_mut(&mut self, node: &mut crate::Table) { + node.decor_mut().clear(); + + // Empty tables could be semantically meaningful, so make sure they are not implicit + if !node.is_empty() { + node.set_implicit(true); + } + + crate::visit_mut::visit_table_mut(self, node); + } + + fn visit_value_mut(&mut self, node: &mut crate::Value) { + node.decor_mut().clear(); + + crate::visit_mut::visit_value_mut(self, node); + } + + fn visit_array_mut(&mut self, node: &mut crate::Array) { + crate::visit_mut::visit_array_mut(self, node); + + if (0..=1).contains(&node.len()) { + node.set_trailing(""); + node.set_trailing_comma(false); + } else { + for item in node.iter_mut() { + item.decor_mut().set_prefix("\n "); + } + node.set_trailing("\n"); + node.set_trailing_comma(true); + } + } +} diff --git a/vendor/toml_edit/src/ser/value.rs b/vendor/toml_edit/src/ser/value.rs new file mode 100644 index 0000000..d29390a --- /dev/null +++ b/vendor/toml_edit/src/ser/value.rs @@ -0,0 +1,243 @@ +use super::Error; + +/// Serialization for TOML [values][crate::Value]. +/// +/// This structure implements serialization support for TOML to serialize an +/// arbitrary type to TOML. Note that the TOML format does not support all +/// datatypes in Rust, such as enums, tuples, and tuple structs. These types +/// will generate an error when serialized. +/// +/// Currently a serializer always writes its output to an in-memory `String`, +/// which is passed in when creating the serializer itself. +/// +/// # Examples +/// +/// ``` +/// use serde::Serialize; +/// +/// #[derive(Serialize)] +/// struct Config { +/// database: Database, +/// } +/// +/// #[derive(Serialize)] +/// struct Database { +/// ip: String, +/// port: Vec<u16>, +/// connection_max: u32, +/// enabled: bool, +/// } +/// +/// let config = Config { +/// database: Database { +/// ip: "192.168.1.1".to_string(), +/// port: vec![8001, 8002, 8003], +/// connection_max: 5000, +/// enabled: false, +/// }, +/// }; +/// +/// let value = serde::Serialize::serialize( +/// &config, +/// toml_edit::ser::ValueSerializer::new() +/// ).unwrap(); +/// println!("{}", value) +/// ``` +#[derive(Default)] +#[non_exhaustive] +pub struct ValueSerializer {} + +impl ValueSerializer { + /// Creates a new serializer generate a TOML document. + pub fn new() -> Self { + Self {} + } +} + +impl serde::ser::Serializer for ValueSerializer { + type Ok = crate::Value; + type Error = Error; + type SerializeSeq = super::SerializeValueArray; + type SerializeTuple = super::SerializeValueArray; + type SerializeTupleStruct = super::SerializeValueArray; + type SerializeTupleVariant = super::SerializeValueArray; + type SerializeMap = super::SerializeMap; + type SerializeStruct = super::SerializeMap; + type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>; + + fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> { + Ok(v.into()) + } + + fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> { + Ok(v.into()) + } + + fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> { + let v: i64 = v + .try_into() + .map_err(|_err| Error::OutOfRange(Some("u64")))?; + self.serialize_i64(v) + } + + fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> { + self.serialize_f64(v as f64) + } + + fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> { + Ok(v.into()) + } + + fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> { + let mut buf = [0; 4]; + self.serialize_str(v.encode_utf8(&mut buf)) + } + + fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> { + Ok(v.into()) + } + + fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error> { + use serde::ser::Serialize; + value.serialize(self) + } + + fn serialize_none(self) -> Result<Self::Ok, Self::Error> { + Err(Error::UnsupportedNone) + } + + fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + value.serialize(self) + } + + fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { + Err(Error::UnsupportedType(Some("unit"))) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { + Err(Error::UnsupportedType(Some(name))) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result<Self::Ok, Self::Error> { + self.serialize_str(variant) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + value: &T, + ) -> Result<Self::Ok, Self::Error> + where + T: serde::ser::Serialize, + { + value.serialize(self) + } + + 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, + { + let value = value.serialize(self)?; + let mut table = crate::InlineTable::new(); + table.insert(variant, value); + Ok(table.into()) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + let serializer = match len { + Some(len) => super::SerializeValueArray::with_capacity(len), + None => super::SerializeValueArray::new(), + }; + Ok(serializer) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + let serializer = match len { + Some(len) => super::SerializeMap::table_with_capacity(len), + None => super::SerializeMap::table(), + }; + Ok(serializer) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + if name == toml_datetime::__unstable::NAME { + Ok(super::SerializeMap::datetime()) + } else { + self.serialize_map(Some(len)) + } + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error::UnsupportedType(Some(name))) + } +} diff --git a/vendor/toml_edit/src/table.rs b/vendor/toml_edit/src/table.rs new file mode 100644 index 0000000..45d6d61 --- /dev/null +++ b/vendor/toml_edit/src/table.rs @@ -0,0 +1,757 @@ +use std::iter::FromIterator; + +use indexmap::map::IndexMap; + +use crate::key::Key; +use crate::repr::Decor; +use crate::value::DEFAULT_VALUE_DECOR; +use crate::{InlineTable, InternalString, Item, KeyMut, Value}; + +/// Type representing a TOML non-inline table +#[derive(Clone, Debug, Default)] +pub struct Table { + // Comments/spaces before and after the header + pub(crate) decor: Decor, + // Whether to hide an empty table + pub(crate) implicit: bool, + // Whether this is a proxy for dotted keys + pub(crate) dotted: bool, + // Used for putting tables back in their original order when serialising. + // + // `None` for user created tables (can be overridden with `set_position`) + doc_position: Option<usize>, + pub(crate) span: Option<std::ops::Range<usize>>, + pub(crate) items: KeyValuePairs, +} + +/// Constructors +/// +/// See also `FromIterator` +impl Table { + /// Creates an empty table. + pub fn new() -> Self { + Default::default() + } + + pub(crate) fn with_pos(doc_position: Option<usize>) -> Self { + Self { + doc_position, + ..Default::default() + } + } + + pub(crate) fn with_pairs(items: KeyValuePairs) -> Self { + Self { + items, + ..Default::default() + } + } + + /// Convert to an inline table + pub fn into_inline_table(mut self) -> InlineTable { + for (_, kv) in self.items.iter_mut() { + kv.value.make_value(); + } + let mut t = InlineTable::with_pairs(self.items); + t.fmt(); + t + } +} + +/// Formatting +impl Table { + /// Get key/values for values that are visually children of this table + /// + /// For example, this will return dotted keys + pub fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> { + let mut values = Vec::new(); + let root = Vec::new(); + self.append_values(&root, &mut values); + values + } + + fn append_values<'s, 'c>( + &'s self, + parent: &[&'s Key], + values: &'c mut Vec<(Vec<&'s Key>, &'s Value)>, + ) { + for value in self.items.values() { + let mut path = parent.to_vec(); + path.push(&value.key); + match &value.value { + Item::Table(table) if table.is_dotted() => { + table.append_values(&path, values); + } + Item::Value(value) => { + if let Some(table) = value.as_inline_table() { + if table.is_dotted() { + table.append_values(&path, values); + } else { + values.push((path, value)); + } + } else { + values.push((path, value)); + } + } + _ => {} + } + } + } + + /// Auto formats the table. + pub fn fmt(&mut self) { + decorate_table(self); + } + + /// Sorts Key/Value Pairs of the table. + /// + /// Doesn't affect subtables or subarrays. + pub fn sort_values(&mut self) { + // Assuming standard tables have their doc_position set and this won't negatively impact them + self.items.sort_keys(); + for kv in self.items.values_mut() { + match &mut kv.value { + Item::Table(table) if table.is_dotted() => { + table.sort_values(); + } + _ => {} + } + } + } + + /// Sort Key/Value Pairs of the table using the using the comparison function `compare`. + /// + /// The comparison function receives two key and value pairs to compare (you can sort by keys or + /// values or their combination as needed). + pub fn sort_values_by<F>(&mut self, mut compare: F) + where + F: FnMut(&Key, &Item, &Key, &Item) -> std::cmp::Ordering, + { + self.sort_values_by_internal(&mut compare); + } + + fn sort_values_by_internal<F>(&mut self, compare: &mut F) + where + F: FnMut(&Key, &Item, &Key, &Item) -> std::cmp::Ordering, + { + let modified_cmp = |_: &InternalString, + val1: &TableKeyValue, + _: &InternalString, + val2: &TableKeyValue| + -> std::cmp::Ordering { + compare(&val1.key, &val1.value, &val2.key, &val2.value) + }; + + self.items.sort_by(modified_cmp); + + for kv in self.items.values_mut() { + match &mut kv.value { + Item::Table(table) if table.is_dotted() => { + table.sort_values_by_internal(compare); + } + _ => {} + } + } + } + + /// 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. + /// + /// ``` + /// 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; + } + + /// If a table has no key/value pairs and implicit, it will not be displayed. + pub fn is_implicit(&self) -> bool { + self.implicit + } + + /// Change this table's dotted status + pub fn set_dotted(&mut self, yes: bool) { + self.dotted = yes; + } + + /// Check if this is a wrapper for dotted keys, rather than a standard table + pub fn is_dotted(&self) -> bool { + self.dotted + } + + /// Sets the position of the `Table` within the `Document`. + pub fn set_position(&mut self, doc_position: usize) { + self.doc_position = Some(doc_position); + } + + /// The position of the `Table` within the `Document`. + /// + /// Returns `None` if the `Table` was created manually (i.e. not via parsing) + /// in which case its position is set automatically. This can be overridden with + /// [`Table::set_position`]. + pub fn position(&self) -> Option<usize> { + self.doc_position + } + + /// Returns the surrounding whitespace + pub fn decor_mut(&mut self) -> &mut Decor { + &mut self.decor + } + + /// Returns the decor associated with a given key of the table. + pub fn decor(&self) -> &Decor { + &self.decor + } + + /// Returns the decor associated with a given key of the table. + pub fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { + self.items.get_mut(key).map(|kv| &mut kv.key.decor) + } + + /// Returns the decor associated with a given key of the table. + pub fn key_decor(&self, key: &str) -> Option<&Decor> { + self.items.get(key).map(|kv| &kv.key.decor) + } + + /// Returns the location within the original document + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + self.span.clone() + } + + pub(crate) fn despan(&mut self, input: &str) { + self.span = None; + self.decor.despan(input); + for kv in self.items.values_mut() { + kv.key.despan(input); + kv.value.despan(input); + } + } +} + +impl Table { + /// Returns an iterator over all key/value pairs, including empty. + pub fn iter(&self) -> Iter<'_> { + Box::new( + self.items + .iter() + .filter(|(_, kv)| !kv.value.is_none()) + .map(|(key, kv)| (&key[..], &kv.value)), + ) + } + + /// Returns an mutable iterator over all key/value pairs, including empty. + pub fn iter_mut(&mut self) -> IterMut<'_> { + Box::new( + self.items + .iter_mut() + .filter(|(_, kv)| !kv.value.is_none()) + .map(|(_, kv)| (kv.key.as_mut(), &mut kv.value)), + ) + } + + /// Returns the number of non-empty items in the table. + pub fn len(&self) -> usize { + self.items.iter().filter(|i| !(i.1).value.is_none()).count() + } + + /// Returns true if the table is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Clears the table, removing all key-value pairs. Keeps the allocated memory for reuse. + pub fn clear(&mut self) { + self.items.clear() + } + + /// Gets the given key's corresponding entry in the Table for in-place manipulation. + pub fn entry<'a>(&'a mut self, key: &str) -> Entry<'a> { + // Accept a `&str` rather than an owned type to keep `InternalString`, well, internal + match self.items.entry(key.into()) { + indexmap::map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }), + indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { entry, key: None }), + } + } + + /// Gets the given key's corresponding entry in the Table for in-place manipulation. + pub fn entry_format<'a>(&'a mut self, key: &Key) -> Entry<'a> { + // Accept a `&Key` to be consistent with `entry` + match self.items.entry(key.get().into()) { + indexmap::map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }), + indexmap::map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { + entry, + key: Some(key.to_owned()), + }), + } + } + + /// Returns an optional reference to an item given the key. + pub fn get<'a>(&'a self, key: &str) -> Option<&'a Item> { + self.items.get(key).and_then(|kv| { + if !kv.value.is_none() { + Some(&kv.value) + } else { + None + } + }) + } + + /// Returns an optional mutable reference to an item given the key. + pub fn get_mut<'a>(&'a mut self, key: &str) -> Option<&'a mut Item> { + self.items.get_mut(key).and_then(|kv| { + if !kv.value.is_none() { + Some(&mut kv.value) + } else { + None + } + }) + } + + /// Return references to the key-value pair stored for key, if it is present, else None. + pub fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { + self.items.get(key).and_then(|kv| { + if !kv.value.is_none() { + Some((&kv.key, &kv.value)) + } else { + None + } + }) + } + + /// Return mutable references to the key-value pair stored for key, if it is present, else None. + pub fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> { + self.items.get_mut(key).and_then(|kv| { + if !kv.value.is_none() { + Some((kv.key.as_mut(), &mut kv.value)) + } else { + None + } + }) + } + + /// Returns true if the table contains an item with the given key. + pub fn contains_key(&self, key: &str) -> bool { + if let Some(kv) = self.items.get(key) { + !kv.value.is_none() + } else { + false + } + } + + /// Returns true if the table contains a table with the given key. + pub fn contains_table(&self, key: &str) -> bool { + if let Some(kv) = self.items.get(key) { + kv.value.is_table() + } else { + false + } + } + + /// Returns true if the table contains a value with the given key. + pub fn contains_value(&self, key: &str) -> bool { + if let Some(kv) = self.items.get(key) { + kv.value.is_value() + } else { + false + } + } + + /// Returns true if the table contains an array of tables with the given key. + pub fn contains_array_of_tables(&self, key: &str) -> bool { + if let Some(kv) = self.items.get(key) { + kv.value.is_array_of_tables() + } else { + false + } + } + + /// Inserts a key-value pair into the map. + pub fn insert(&mut self, key: &str, item: Item) -> Option<Item> { + let kv = TableKeyValue::new(Key::new(key), item); + self.items.insert(key.into(), kv).map(|kv| kv.value) + } + + /// Inserts a key-value pair into the map. + pub fn insert_formatted(&mut self, key: &Key, item: Item) -> Option<Item> { + let kv = TableKeyValue::new(key.to_owned(), item); + self.items.insert(key.get().into(), kv).map(|kv| kv.value) + } + + /// Removes an item given the key. + pub fn remove(&mut self, key: &str) -> Option<Item> { + self.items.shift_remove(key).map(|kv| kv.value) + } + + /// Removes a key from the map, returning the stored key and value if the key was previously in the map. + pub fn remove_entry(&mut self, key: &str) -> Option<(Key, Item)> { + self.items.shift_remove(key).map(|kv| (kv.key, kv.value)) + } + + /// Retains only the elements specified by the `keep` predicate. + /// + /// In other words, remove all pairs `(key, item)` for which + /// `keep(&key, &mut item)` returns `false`. + /// + /// The elements are visited in iteration order. + pub fn retain<F>(&mut self, mut keep: F) + where + F: FnMut(&str, &mut Item) -> bool, + { + self.items + .retain(|key, key_value| keep(key, &mut key_value.value)); + } +} + +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)?; + write!(f, "=")?; + value.encode(f, None, DEFAULT_VALUE_DECOR)?; + writeln!(f)?; + } + Ok(()) + } +} + +impl<K: Into<Key>, V: Into<Value>> Extend<(K, V)> for Table { + fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) { + for (key, value) in iter { + let key = key.into(); + let value = Item::Value(value.into()); + let value = TableKeyValue::new(key, value); + self.items.insert(value.key.get().into(), value); + } + } +} + +impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for Table { + fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator<Item = (K, V)>, + { + let mut table = Table::new(); + table.extend(iter); + table + } +} + +impl IntoIterator for Table { + type Item = (InternalString, Item); + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + Box::new(self.items.into_iter().map(|(k, kv)| (k, kv.value))) + } +} + +impl<'s> IntoIterator for &'s Table { + type Item = (&'s str, &'s Item); + type IntoIter = Iter<'s>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +pub(crate) type KeyValuePairs = IndexMap<InternalString, TableKeyValue>; + +fn decorate_table(table: &mut Table) { + for (key_decor, 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())) + { + key_decor.clear(); + value.decor_mut().clear(); + } +} + +// `key1 = value1` +pub(crate) const DEFAULT_KEY_DECOR: (&str, &str) = ("", " "); +pub(crate) const DEFAULT_TABLE_DECOR: (&str, &str) = ("\n", ""); +pub(crate) const DEFAULT_KEY_PATH_DECOR: (&str, &str) = ("", ""); + +#[derive(Debug, Clone)] +pub(crate) struct TableKeyValue { + pub(crate) key: Key, + pub(crate) value: Item, +} + +impl TableKeyValue { + pub(crate) fn new(key: Key, value: Item) -> Self { + TableKeyValue { key, value } + } +} + +/// An owned iterator type over `Table`'s key/value pairs. +pub type IntoIter = Box<dyn Iterator<Item = (InternalString, Item)>>; +/// An iterator type over `Table`'s key/value pairs. +pub type Iter<'a> = Box<dyn Iterator<Item = (&'a str, &'a Item)> + 'a>; +/// A mutable iterator type over `Table`'s key/value pairs. +pub type IterMut<'a> = Box<dyn Iterator<Item = (KeyMut<'a>, &'a mut Item)> + 'a>; + +/// This trait represents either a `Table`, or an `InlineTable`. +pub trait TableLike: crate::private::Sealed { + /// Returns an iterator over key/value pairs. + fn iter(&self) -> Iter<'_>; + /// Returns an mutable iterator over all key/value pairs, including empty. + fn iter_mut(&mut self) -> IterMut<'_>; + /// Returns the number of nonempty items. + fn len(&self) -> usize { + self.iter().filter(|&(_, v)| !v.is_none()).count() + } + /// Returns true if the table is empty. + fn is_empty(&self) -> bool { + self.len() == 0 + } + /// Clears the table, removing all key-value pairs. Keeps the allocated memory for reuse. + fn clear(&mut self); + /// Gets the given key's corresponding entry in the Table for in-place manipulation. + fn entry<'a>(&'a mut self, key: &str) -> Entry<'a>; + /// Gets the given key's corresponding entry in the Table for in-place manipulation. + fn entry_format<'a>(&'a mut self, key: &Key) -> Entry<'a>; + /// Returns an optional reference to an item given the key. + fn get<'s>(&'s self, key: &str) -> Option<&'s Item>; + /// Returns an optional mutable reference to an item given the key. + fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item>; + /// Return references to the key-value pair stored for key, if it is present, else None. + fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)>; + /// Return mutable references to the key-value pair stored for key, if it is present, else None. + fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)>; + /// Returns true if the table contains an item with the given key. + fn contains_key(&self, key: &str) -> bool; + /// Inserts a key-value pair into the map. + fn insert(&mut self, key: &str, value: Item) -> Option<Item>; + /// Removes an item given the key. + fn remove(&mut self, key: &str) -> Option<Item>; + + /// Get key/values for values that are visually children of this table + /// + /// For example, this will return dotted keys + fn get_values(&self) -> Vec<(Vec<&Key>, &Value)>; + + /// Auto formats the table. + fn fmt(&mut self); + /// Sorts Key/Value Pairs of the table. + /// + /// Doesn't affect subtables or subarrays. + fn sort_values(&mut self); + /// Change this table's dotted status + fn set_dotted(&mut self, yes: bool); + /// Check if this is a wrapper for dotted keys, rather than a standard table + fn is_dotted(&self) -> bool; + + /// Returns the decor associated with a given key of the table. + fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor>; + /// Returns the decor associated with a given key of the table. + fn key_decor(&self, key: &str) -> Option<&Decor>; +} + +impl TableLike for Table { + fn iter(&self) -> Iter<'_> { + self.iter() + } + fn iter_mut(&mut self) -> IterMut<'_> { + self.iter_mut() + } + fn clear(&mut self) { + self.clear(); + } + fn entry<'a>(&'a mut self, key: &str) -> Entry<'a> { + self.entry(key) + } + fn entry_format<'a>(&'a mut self, key: &Key) -> Entry<'a> { + self.entry_format(key) + } + fn get<'s>(&'s self, key: &str) -> Option<&'s Item> { + self.get(key) + } + fn get_mut<'s>(&'s mut self, key: &str) -> Option<&'s mut Item> { + self.get_mut(key) + } + fn get_key_value<'a>(&'a self, key: &str) -> Option<(&'a Key, &'a Item)> { + self.get_key_value(key) + } + fn get_key_value_mut<'a>(&'a mut self, key: &str) -> Option<(KeyMut<'a>, &'a mut Item)> { + self.get_key_value_mut(key) + } + fn contains_key(&self, key: &str) -> bool { + self.contains_key(key) + } + fn insert(&mut self, key: &str, value: Item) -> Option<Item> { + self.insert(key, value) + } + fn remove(&mut self, key: &str) -> Option<Item> { + self.remove(key) + } + + fn get_values(&self) -> Vec<(Vec<&Key>, &Value)> { + self.get_values() + } + fn fmt(&mut self) { + self.fmt() + } + fn sort_values(&mut self) { + self.sort_values() + } + fn is_dotted(&self) -> bool { + self.is_dotted() + } + fn set_dotted(&mut self, yes: bool) { + self.set_dotted(yes) + } + + fn key_decor_mut(&mut self, key: &str) -> Option<&mut Decor> { + self.key_decor_mut(key) + } + fn key_decor(&self, key: &str) -> Option<&Decor> { + self.key_decor(key) + } +} + +/// A view into a single location in a map, which may be vacant or occupied. +pub enum Entry<'a> { + /// An occupied Entry. + Occupied(OccupiedEntry<'a>), + /// A vacant Entry. + Vacant(VacantEntry<'a>), +} + +impl<'a> Entry<'a> { + /// Returns the entry key + /// + /// # Examples + /// + /// ``` + /// use toml_edit::Table; + /// + /// let mut map = Table::new(); + /// + /// assert_eq!("hello", map.entry("hello").key()); + /// ``` + pub fn key(&self) -> &str { + match self { + Entry::Occupied(e) => e.key(), + Entry::Vacant(e) => e.key(), + } + } + + /// Ensures a value is in the entry by inserting the default if empty, and returns + /// a mutable reference to the value in the entry. + pub fn or_insert(self, default: Item) -> &'a mut Item { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(default), + } + } + + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with<F: FnOnce() -> Item>(self, default: F) -> &'a mut Item { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(default()), + } + } +} + +/// A view into a single occupied location in a `IndexMap`. +pub struct OccupiedEntry<'a> { + pub(crate) entry: indexmap::map::OccupiedEntry<'a, InternalString, TableKeyValue>, +} + +impl<'a> OccupiedEntry<'a> { + /// Gets a reference to the entry key + /// + /// # Examples + /// + /// ``` + /// use toml_edit::Table; + /// + /// let mut map = Table::new(); + /// + /// assert_eq!("foo", map.entry("foo").key()); + /// ``` + pub fn key(&self) -> &str { + self.entry.key().as_str() + } + + /// Gets a mutable reference to the entry key + pub fn key_mut(&mut self) -> KeyMut<'_> { + self.entry.get_mut().key.as_mut() + } + + /// Gets a reference to the value in the entry. + pub fn get(&self) -> &Item { + &self.entry.get().value + } + + /// Gets a mutable reference to the value in the entry. + pub fn get_mut(&mut self) -> &mut Item { + &mut self.entry.get_mut().value + } + + /// Converts the OccupiedEntry into a mutable reference to the value in the entry + /// with a lifetime bound to the map itself + pub fn into_mut(self) -> &'a mut Item { + &mut self.entry.into_mut().value + } + + /// Sets the value of the entry, and returns the entry's old value + pub fn insert(&mut self, mut value: Item) -> Item { + std::mem::swap(&mut value, &mut self.entry.get_mut().value); + value + } + + /// Takes the value out of the entry, and returns it + pub fn remove(self) -> Item { + self.entry.shift_remove().value + } +} + +/// A view into a single empty location in a `IndexMap`. +pub struct VacantEntry<'a> { + pub(crate) entry: indexmap::map::VacantEntry<'a, InternalString, TableKeyValue>, + pub(crate) key: Option<Key>, +} + +impl<'a> VacantEntry<'a> { + /// Gets a reference to the entry key + /// + /// # Examples + /// + /// ``` + /// use toml_edit::Table; + /// + /// let mut map = Table::new(); + /// + /// assert_eq!("foo", map.entry("foo").key()); + /// ``` + pub fn key(&self) -> &str { + self.entry.key().as_str() + } + + /// Sets the value of the entry with the VacantEntry's key, + /// and returns a mutable reference to it + pub fn insert(self, value: Item) -> &'a mut Item { + let entry = self.entry; + let key = self.key.unwrap_or_else(|| Key::new(entry.key().as_str())); + &mut entry.insert(TableKeyValue::new(key, value)).value + } +} diff --git a/vendor/toml_edit/src/value.rs b/vendor/toml_edit/src/value.rs new file mode 100644 index 0000000..f10da9a --- /dev/null +++ b/vendor/toml_edit/src/value.rs @@ -0,0 +1,372 @@ +use std::iter::FromIterator; +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}; + +/// Representation of a TOML Value (as part of a Key/Value Pair). +#[derive(Debug, Clone)] +pub enum Value { + /// A string value. + String(Formatted<String>), + /// A 64-bit integer value. + Integer(Formatted<i64>), + /// A 64-bit float value. + Float(Formatted<f64>), + /// A boolean value. + Boolean(Formatted<bool>), + /// An RFC 3339 formatted date-time with offset. + Datetime(Formatted<Datetime>), + /// An inline array of values. + Array(Array), + /// An inline table of key/value pairs. + InlineTable(InlineTable), +} + +/// Downcasting +impl Value { + /// Text description of value type + pub fn type_name(&self) -> &'static str { + match self { + Value::String(..) => "string", + Value::Integer(..) => "integer", + Value::Float(..) => "float", + Value::Boolean(..) => "boolean", + Value::Datetime(..) => "datetime", + Value::Array(..) => "array", + Value::InlineTable(..) => "inline table", + } + } + + /// Casts `self` to str. + pub fn as_str(&self) -> Option<&str> { + match *self { + Value::String(ref value) => Some(value.value()), + _ => None, + } + } + + /// Returns true iff `self` is a string. + pub fn is_str(&self) -> bool { + self.as_str().is_some() + } + + /// Casts `self` to integer. + pub fn as_integer(&self) -> Option<i64> { + match *self { + Value::Integer(ref value) => Some(*value.value()), + _ => None, + } + } + + /// Returns true iff `self` is an integer. + pub fn is_integer(&self) -> bool { + self.as_integer().is_some() + } + + /// Casts `self` to float. + pub fn as_float(&self) -> Option<f64> { + match *self { + Value::Float(ref value) => Some(*value.value()), + _ => None, + } + } + + /// Returns true iff `self` is a float. + pub fn is_float(&self) -> bool { + self.as_float().is_some() + } + + /// Casts `self` to boolean. + pub fn as_bool(&self) -> Option<bool> { + match *self { + Value::Boolean(ref value) => Some(*value.value()), + _ => None, + } + } + + /// Returns true iff `self` is a boolean. + pub fn is_bool(&self) -> bool { + self.as_bool().is_some() + } + + /// Casts `self` to date-time. + pub fn as_datetime(&self) -> Option<&Datetime> { + match *self { + Value::Datetime(ref value) => Some(value.value()), + _ => None, + } + } + + /// Returns true iff `self` is a date-time. + pub fn is_datetime(&self) -> bool { + self.as_datetime().is_some() + } + + /// Casts `self` to array. + pub fn as_array(&self) -> Option<&Array> { + match *self { + Value::Array(ref value) => Some(value), + _ => None, + } + } + + /// Casts `self` to mutable array. + pub fn as_array_mut(&mut self) -> Option<&mut Array> { + match *self { + Value::Array(ref mut value) => Some(value), + _ => None, + } + } + + /// Returns true iff `self` is an array. + pub fn is_array(&self) -> bool { + self.as_array().is_some() + } + + /// Casts `self` to inline table. + pub fn as_inline_table(&self) -> Option<&InlineTable> { + match *self { + Value::InlineTable(ref value) => Some(value), + _ => None, + } + } + + /// Casts `self` to mutable inline table. + pub fn as_inline_table_mut(&mut self) -> Option<&mut InlineTable> { + match *self { + Value::InlineTable(ref mut value) => Some(value), + _ => None, + } + } + + /// Returns true iff `self` is an inline table. + pub fn is_inline_table(&self) -> bool { + self.as_inline_table().is_some() + } +} + +impl Value { + /// Get the decoration of the value. + /// # Example + /// ```rust + /// let v = toml_edit::Value::from(true); + /// assert_eq!(v.decor().suffix(), None); + ///``` + pub fn decor_mut(&mut self) -> &mut Decor { + match self { + Value::String(f) => f.decor_mut(), + Value::Integer(f) => f.decor_mut(), + Value::Float(f) => f.decor_mut(), + Value::Boolean(f) => f.decor_mut(), + Value::Datetime(f) => f.decor_mut(), + Value::Array(a) => a.decor_mut(), + Value::InlineTable(t) => t.decor_mut(), + } + } + + /// Get the decoration of the value. + /// # Example + /// ```rust + /// let v = toml_edit::Value::from(true); + /// assert_eq!(v.decor().suffix(), None); + ///``` + pub fn decor(&self) -> &Decor { + match *self { + Value::String(ref f) => f.decor(), + Value::Integer(ref f) => f.decor(), + Value::Float(ref f) => f.decor(), + Value::Boolean(ref f) => f.decor(), + Value::Datetime(ref f) => f.decor(), + Value::Array(ref a) => a.decor(), + Value::InlineTable(ref t) => t.decor(), + } + } + + /// Sets the prefix and the suffix for value. + /// # Example + /// ```rust + /// 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); + self + } + + pub(crate) fn decorate(&mut self, prefix: impl Into<RawString>, suffix: impl Into<RawString>) { + let decor = self.decor_mut(); + *decor = Decor::new(prefix, suffix); + } + + /// Returns the location within the original document + pub(crate) fn span(&self) -> Option<std::ops::Range<usize>> { + match self { + Value::String(f) => f.span(), + Value::Integer(f) => f.span(), + Value::Float(f) => f.span(), + Value::Boolean(f) => f.span(), + Value::Datetime(f) => f.span(), + Value::Array(a) => a.span(), + Value::InlineTable(t) => t.span(), + } + } + + pub(crate) fn despan(&mut self, input: &str) { + match self { + Value::String(f) => f.despan(input), + Value::Integer(f) => f.despan(input), + Value::Float(f) => f.despan(input), + Value::Boolean(f) => f.despan(input), + Value::Datetime(f) => f.despan(input), + Value::Array(a) => a.despan(input), + Value::InlineTable(t) => t.despan(input), + } + } +} + +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) + } +} + +impl<'b> From<&'b Value> for Value { + fn from(s: &'b Value) -> Self { + s.clone() + } +} + +impl<'b> From<&'b str> for Value { + fn from(s: &'b str) -> Self { + s.to_owned().into() + } +} + +impl<'b> From<&'b String> for Value { + fn from(s: &'b String) -> Self { + s.to_owned().into() + } +} + +impl From<String> for Value { + fn from(s: String) -> Self { + Value::String(Formatted::new(s)) + } +} + +impl<'b> From<&'b InternalString> for Value { + fn from(s: &'b InternalString) -> Self { + s.as_str().into() + } +} + +impl From<InternalString> for Value { + fn from(s: InternalString) -> Self { + s.as_str().into() + } +} + +impl From<i64> for Value { + fn from(i: i64) -> Self { + Value::Integer(Formatted::new(i)) + } +} + +impl From<f64> for Value { + fn from(f: f64) -> Self { + Value::Float(Formatted::new(f)) + } +} + +impl From<bool> for Value { + fn from(b: bool) -> Self { + Value::Boolean(Formatted::new(b)) + } +} + +impl From<Datetime> for Value { + fn from(d: Datetime) -> Self { + Value::Datetime(Formatted::new(d)) + } +} + +impl From<Date> for Value { + fn from(d: Date) -> Self { + let d: Datetime = d.into(); + d.into() + } +} + +impl From<Time> for Value { + fn from(d: Time) -> Self { + let d: Datetime = d.into(); + d.into() + } +} + +impl From<Array> for Value { + fn from(array: Array) -> Self { + Value::Array(array) + } +} + +impl From<InlineTable> for Value { + fn from(table: InlineTable) -> Self { + Value::InlineTable(table) + } +} + +impl<V: Into<Value>> FromIterator<V> for Value { + fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator<Item = V>, + { + let array: Array = iter.into_iter().collect(); + Value::Array(array) + } +} + +impl<K: Into<Key>, V: Into<Value>> FromIterator<(K, V)> for Value { + fn from_iter<I>(iter: I) -> Self + where + I: IntoIterator<Item = (K, V)>, + { + let table: InlineTable = iter.into_iter().collect(); + Value::InlineTable(table) + } +} + +impl std::fmt::Display for Value { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + crate::encode::Encode::encode(self, f, None, ("", "")) + } +} + +// `key1 = value1` +pub(crate) const DEFAULT_VALUE_DECOR: (&str, &str) = (" ", ""); +// `{ key = value }` +pub(crate) const DEFAULT_TRAILING_VALUE_DECOR: (&str, &str) = (" ", " "); +// `[value1, value2]` +pub(crate) const DEFAULT_LEADING_VALUE_DECOR: (&str, &str) = ("", ""); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn from_iter_formatting() { + let features = vec!["node".to_owned(), "mouth".to_owned()]; + let features: Value = features.iter().cloned().collect(); + assert_eq!(features.to_string(), r#"["node", "mouth"]"#); + } +} diff --git a/vendor/toml_edit/src/visit.rs b/vendor/toml_edit/src/visit.rs new file mode 100644 index 0000000..1bc640a --- /dev/null +++ b/vendor/toml_edit/src/visit.rs @@ -0,0 +1,236 @@ +#![allow(missing_docs)] + +//! Document tree traversal to walk a shared borrow of a document tree. +//! +//! Each method of the [`Visit`] trait is a hook that can be overridden +//! to customize the behavior when mutating the corresponding type of node. +//! By default, every method recursively visits the substructure of the +//! input by invoking the right visitor method of each of its fields. +//! +//! ``` +//! # use toml_edit::{Item, ArrayOfTables, Table, Value}; +//! +//! pub trait Visit<'doc> { +//! /* ... */ +//! +//! fn visit_item(&mut self, i: &'doc Item) { +//! visit_item(self, i); +//! } +//! +//! /* ... */ +//! # fn visit_value(&mut self, i: &'doc Value); +//! # fn visit_table(&mut self, i: &'doc Table); +//! # fn visit_array_of_tables(&mut self, i: &'doc ArrayOfTables); +//! } +//! +//! pub fn visit_item<'doc, V>(v: &mut V, node: &'doc Item) +//! where +//! V: Visit<'doc> + ?Sized, +//! { +//! match node { +//! Item::None => {} +//! Item::Value(value) => v.visit_value(value), +//! Item::Table(table) => v.visit_table(table), +//! Item::ArrayOfTables(array) => v.visit_array_of_tables(array), +//! } +//! } +//! ``` +//! +//! The API is modeled after [`syn::visit`](https://docs.rs/syn/1/syn/visit). +//! +//! # Examples +//! +//! This visitor stores every string in the document. +//! +//! ``` +//! # use toml_edit::*; +//! use toml_edit::visit::*; +//! +//! #[derive(Default)] +//! struct StringCollector<'doc> { +//! strings: Vec<&'doc str>, +//! } +//! +//! impl<'doc> Visit<'doc> for StringCollector<'doc> { +//! fn visit_string(&mut self, node: &'doc Formatted<String>) { +//! self.strings.push(node.value().as_str()); +//! } +//! } +//! +//! let input = r#" +//! laputa = "sky-castle" +//! the-force = { value = "surrounds-you" } +//! "#; +//! +//! let mut document: Document = input.parse().unwrap(); +//! let mut visitor = StringCollector::default(); +//! 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). + +use crate::{ + Array, ArrayOfTables, Datetime, Document, Formatted, InlineTable, Item, Table, TableLike, Value, +}; + +/// Document tree traversal to mutate an exclusive borrow of a document tree in-place. +/// +/// See the [module documentation](self) for details. +pub trait Visit<'doc> { + fn visit_document(&mut self, node: &'doc Document) { + visit_document(self, node); + } + + fn visit_item(&mut self, node: &'doc Item) { + visit_item(self, node); + } + + fn visit_table(&mut self, node: &'doc Table) { + visit_table(self, node); + } + + fn visit_inline_table(&mut self, node: &'doc InlineTable) { + visit_inline_table(self, node) + } + + fn visit_table_like(&mut self, node: &'doc dyn TableLike) { + visit_table_like(self, node); + } + + fn visit_table_like_kv(&mut self, key: &'doc str, node: &'doc Item) { + visit_table_like_kv(self, key, node); + } + + fn visit_array(&mut self, node: &'doc Array) { + visit_array(self, node); + } + + fn visit_array_of_tables(&mut self, node: &'doc ArrayOfTables) { + visit_array_of_tables(self, node); + } + + fn visit_value(&mut self, node: &'doc Value) { + visit_value(self, node); + } + + fn visit_boolean(&mut self, node: &'doc Formatted<bool>) { + visit_boolean(self, node) + } + + fn visit_datetime(&mut self, node: &'doc Formatted<Datetime>) { + visit_datetime(self, node); + } + + fn visit_float(&mut self, node: &'doc Formatted<f64>) { + visit_float(self, node) + } + + fn visit_integer(&mut self, node: &'doc Formatted<i64>) { + visit_integer(self, node) + } + + fn visit_string(&mut self, node: &'doc Formatted<String>) { + visit_string(self, node) + } +} + +pub fn visit_document<'doc, V>(v: &mut V, node: &'doc Document) +where + V: Visit<'doc> + ?Sized, +{ + v.visit_table(node.as_table()); +} + +pub fn visit_item<'doc, V>(v: &mut V, node: &'doc Item) +where + V: Visit<'doc> + ?Sized, +{ + match node { + Item::None => {} + Item::Value(value) => v.visit_value(value), + Item::Table(table) => v.visit_table(table), + Item::ArrayOfTables(array) => v.visit_array_of_tables(array), + } +} + +pub fn visit_table<'doc, V>(v: &mut V, node: &'doc Table) +where + V: Visit<'doc> + ?Sized, +{ + v.visit_table_like(node) +} + +pub fn visit_inline_table<'doc, V>(v: &mut V, node: &'doc InlineTable) +where + V: Visit<'doc> + ?Sized, +{ + v.visit_table_like(node) +} + +pub fn visit_table_like<'doc, V>(v: &mut V, node: &'doc dyn TableLike) +where + V: Visit<'doc> + ?Sized, +{ + for (key, item) in node.iter() { + v.visit_table_like_kv(key, item) + } +} + +pub fn visit_table_like_kv<'doc, V>(v: &mut V, _key: &'doc str, node: &'doc Item) +where + V: Visit<'doc> + ?Sized, +{ + v.visit_item(node) +} + +pub fn visit_array<'doc, V>(v: &mut V, node: &'doc Array) +where + V: Visit<'doc> + ?Sized, +{ + for value in node.iter() { + v.visit_value(value); + } +} + +pub fn visit_array_of_tables<'doc, V>(v: &mut V, node: &'doc ArrayOfTables) +where + V: Visit<'doc> + ?Sized, +{ + for table in node.iter() { + v.visit_table(table); + } +} + +pub fn visit_value<'doc, V>(v: &mut V, node: &'doc Value) +where + V: Visit<'doc> + ?Sized, +{ + match node { + Value::String(s) => v.visit_string(s), + Value::Integer(i) => v.visit_integer(i), + Value::Float(f) => v.visit_float(f), + Value::Boolean(b) => v.visit_boolean(b), + Value::Datetime(dt) => v.visit_datetime(dt), + Value::Array(array) => v.visit_array(array), + Value::InlineTable(table) => v.visit_inline_table(table), + } +} + +macro_rules! empty_visit { + ($name: ident, $t: ty) => { + fn $name<'doc, V>(_v: &mut V, _node: &'doc $t) + where + V: Visit<'doc> + ?Sized, + { + } + }; +} + +empty_visit!(visit_boolean, Formatted<bool>); +empty_visit!(visit_datetime, Formatted<Datetime>); +empty_visit!(visit_float, Formatted<f64>); +empty_visit!(visit_integer, Formatted<i64>); +empty_visit!(visit_string, Formatted<String>); diff --git a/vendor/toml_edit/src/visit_mut.rs b/vendor/toml_edit/src/visit_mut.rs new file mode 100644 index 0000000..2c2af97 --- /dev/null +++ b/vendor/toml_edit/src/visit_mut.rs @@ -0,0 +1,252 @@ +#![allow(missing_docs)] + +//! Document tree traversal to mutate an exclusive borrow of a document tree in place. +//! +//! +//! Each method of the [`VisitMut`] trait is a hook that can be overridden +//! to customize the behavior when mutating the corresponding type of node. +//! By default, every method recursively visits the substructure of the +//! input by invoking the right visitor method of each of its fields. +//! +//! ``` +//! # use toml_edit::{Item, ArrayOfTables, Table, Value}; +//! +//! pub trait VisitMut { +//! /* ... */ +//! +//! fn visit_item_mut(&mut self, i: &mut Item) { +//! visit_item_mut(self, i); +//! } +//! +//! /* ... */ +//! # fn visit_value_mut(&mut self, i: &mut Value); +//! # fn visit_table_mut(&mut self, i: &mut Table); +//! # fn visit_array_of_tables_mut(&mut self, i: &mut ArrayOfTables); +//! } +//! +//! pub fn visit_item_mut<V>(v: &mut V, node: &mut Item) +//! where +//! V: VisitMut + ?Sized, +//! { +//! match node { +//! Item::None => {} +//! Item::Value(value) => v.visit_value_mut(value), +//! Item::Table(table) => v.visit_table_mut(table), +//! Item::ArrayOfTables(array) => v.visit_array_of_tables_mut(array), +//! } +//! } +//! ``` +//! +//! The API is modeled after [`syn::visit_mut`](https://docs.rs/syn/1/syn/visit_mut). +//! +//! # Examples +//! +//! This visitor replaces every floating point value with its decimal string representation, to +//! 2 decimal points. +//! +//! ``` +//! # use toml_edit::*; +//! use toml_edit::visit_mut::*; +//! +//! struct FloatToString; +//! +//! impl VisitMut for FloatToString { +//! fn visit_value_mut(&mut self, node: &mut Value) { +//! if let Value::Float(f) = node { +//! // Convert the float to a string. +//! let mut s = Formatted::new(format!("{:.2}", f.value())); +//! // Copy over the formatting. +//! std::mem::swap(s.decor_mut(), f.decor_mut()); +//! *node = Value::String(s); +//! } +//! // Most of the time, you will also need to call the default implementation to recurse +//! // further down the document tree. +//! visit_value_mut(self, node); +//! } +//! } +//! +//! let input = r#" +//! banana = 3.26 +//! table = { apple = 4.5 } +//! "#; +//! +//! let mut document: Document = input.parse().unwrap(); +//! let mut visitor = FloatToString; +//! visitor.visit_document_mut(&mut document); +//! +//! let output = r#" +//! banana = "3.26" +//! table = { apple = "4.50" } +//! "#; +//! +//! 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). + +use crate::{ + Array, ArrayOfTables, Datetime, Document, Formatted, InlineTable, Item, KeyMut, Table, + TableLike, Value, +}; + +/// Document tree traversal to mutate an exclusive borrow of a document tree in-place. +/// +/// See the [module documentation](self) for details. +pub trait VisitMut { + fn visit_document_mut(&mut self, node: &mut Document) { + visit_document_mut(self, node); + } + + fn visit_item_mut(&mut self, node: &mut Item) { + visit_item_mut(self, node); + } + + fn visit_table_mut(&mut self, node: &mut Table) { + visit_table_mut(self, node); + } + + fn visit_inline_table_mut(&mut self, node: &mut InlineTable) { + visit_inline_table_mut(self, node) + } + + /// [`visit_table_mut`](Self::visit_table_mut) and + /// [`visit_inline_table_mut`](Self::visit_inline_table_mut) both recurse into this method. + fn visit_table_like_mut(&mut self, node: &mut dyn TableLike) { + visit_table_like_mut(self, node); + } + + fn visit_table_like_kv_mut(&mut self, key: KeyMut<'_>, node: &mut Item) { + visit_table_like_kv_mut(self, key, node); + } + + fn visit_array_mut(&mut self, node: &mut Array) { + visit_array_mut(self, node); + } + + fn visit_array_of_tables_mut(&mut self, node: &mut ArrayOfTables) { + visit_array_of_tables_mut(self, node); + } + + fn visit_value_mut(&mut self, node: &mut Value) { + visit_value_mut(self, node); + } + + fn visit_boolean_mut(&mut self, node: &mut Formatted<bool>) { + visit_boolean_mut(self, node) + } + + fn visit_datetime_mut(&mut self, node: &mut Formatted<Datetime>) { + visit_datetime_mut(self, node); + } + + fn visit_float_mut(&mut self, node: &mut Formatted<f64>) { + visit_float_mut(self, node) + } + + fn visit_integer_mut(&mut self, node: &mut Formatted<i64>) { + visit_integer_mut(self, node) + } + + fn visit_string_mut(&mut self, node: &mut Formatted<String>) { + visit_string_mut(self, node) + } +} + +pub fn visit_document_mut<V>(v: &mut V, node: &mut Document) +where + V: VisitMut + ?Sized, +{ + v.visit_table_mut(node.as_table_mut()); +} + +pub fn visit_item_mut<V>(v: &mut V, node: &mut Item) +where + V: VisitMut + ?Sized, +{ + match node { + Item::None => {} + Item::Value(value) => v.visit_value_mut(value), + Item::Table(table) => v.visit_table_mut(table), + Item::ArrayOfTables(array) => v.visit_array_of_tables_mut(array), + } +} + +pub fn visit_table_mut<V>(v: &mut V, node: &mut Table) +where + V: VisitMut + ?Sized, +{ + v.visit_table_like_mut(node); +} + +pub fn visit_inline_table_mut<V>(v: &mut V, node: &mut InlineTable) +where + V: VisitMut + ?Sized, +{ + v.visit_table_like_mut(node); +} + +pub fn visit_table_like_mut<V>(v: &mut V, node: &mut dyn TableLike) +where + V: VisitMut + ?Sized, +{ + for (key, item) in node.iter_mut() { + v.visit_table_like_kv_mut(key, item); + } +} + +pub fn visit_table_like_kv_mut<V>(v: &mut V, _key: KeyMut<'_>, node: &mut Item) +where + V: VisitMut + ?Sized, +{ + v.visit_item_mut(node) +} + +pub fn visit_array_mut<V>(v: &mut V, node: &mut Array) +where + V: VisitMut + ?Sized, +{ + for value in node.iter_mut() { + v.visit_value_mut(value); + } +} + +pub fn visit_array_of_tables_mut<V>(v: &mut V, node: &mut ArrayOfTables) +where + V: VisitMut + ?Sized, +{ + for table in node.iter_mut() { + v.visit_table_mut(table); + } +} + +pub fn visit_value_mut<V>(v: &mut V, node: &mut Value) +where + V: VisitMut + ?Sized, +{ + match node { + Value::String(s) => v.visit_string_mut(s), + Value::Integer(i) => v.visit_integer_mut(i), + Value::Float(f) => v.visit_float_mut(f), + Value::Boolean(b) => v.visit_boolean_mut(b), + Value::Datetime(dt) => v.visit_datetime_mut(dt), + Value::Array(array) => v.visit_array_mut(array), + Value::InlineTable(table) => v.visit_inline_table_mut(table), + } +} + +macro_rules! empty_visit_mut { + ($name: ident, $t: ty) => { + fn $name<V>(_v: &mut V, _node: &mut $t) + where + V: VisitMut + ?Sized, + { + } + }; +} + +empty_visit_mut!(visit_boolean_mut, Formatted<bool>); +empty_visit_mut!(visit_datetime_mut, Formatted<Datetime>); +empty_visit_mut!(visit_float_mut, Formatted<f64>); +empty_visit_mut!(visit_integer_mut, Formatted<i64>); +empty_visit_mut!(visit_string_mut, Formatted<String>); diff --git a/vendor/toml_edit/tests/decoder.rs b/vendor/toml_edit/tests/decoder.rs new file mode 100644 index 0000000..7306d45 --- /dev/null +++ b/vendor/toml_edit/tests/decoder.rs @@ -0,0 +1,100 @@ +#[derive(Copy, Clone)] +pub struct Decoder; + +impl toml_test_harness::Decoder for Decoder { + fn name(&self) -> &str { + "toml_edit" + } + + fn decode(&self, data: &[u8]) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + let data = std::str::from_utf8(data).map_err(toml_test_harness::Error::new)?; + let document = data + .parse::<toml_edit::Document>() + .map_err(toml_test_harness::Error::new)?; + document_to_decoded(&document) + } +} + +fn document_to_decoded( + value: &toml_edit::Document, +) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + table_to_decoded(value) +} + +fn item_to_decoded( + value: &toml_edit::Item, +) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + match value { + toml_edit::Item::None => unreachable!("No nones"), + toml_edit::Item::Value(v) => value_to_decoded(v), + toml_edit::Item::Table(v) => table_to_decoded(v), + toml_edit::Item::ArrayOfTables(v) => { + let v: Result<_, toml_test_harness::Error> = v.iter().map(table_to_decoded).collect(); + Ok(toml_test_harness::Decoded::Array(v?)) + } + } +} + +fn value_to_decoded( + value: &toml_edit::Value, +) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + match value { + toml_edit::Value::Integer(v) => Ok(toml_test_harness::Decoded::Value( + toml_test_harness::DecodedValue::from(*v.value()), + )), + toml_edit::Value::String(v) => Ok(toml_test_harness::Decoded::Value( + toml_test_harness::DecodedValue::from(v.value()), + )), + toml_edit::Value::Float(v) => Ok(toml_test_harness::Decoded::Value( + toml_test_harness::DecodedValue::from(*v.value()), + )), + toml_edit::Value::Datetime(v) => { + let v = v.value(); + let value = v.to_string(); + let value = match (v.date.is_some(), v.time.is_some(), v.offset.is_some()) { + (true, true, true) => toml_test_harness::DecodedValue::Datetime(value), + (true, true, false) => toml_test_harness::DecodedValue::DatetimeLocal(value), + (true, false, false) => toml_test_harness::DecodedValue::DateLocal(value), + (false, true, false) => toml_test_harness::DecodedValue::TimeLocal(value), + _ => unreachable!("Unsupported case"), + }; + Ok(toml_test_harness::Decoded::Value(value)) + } + toml_edit::Value::Boolean(v) => Ok(toml_test_harness::Decoded::Value( + toml_test_harness::DecodedValue::from(*v.value()), + )), + toml_edit::Value::Array(v) => { + let v: Result<_, toml_test_harness::Error> = v.iter().map(value_to_decoded).collect(); + Ok(toml_test_harness::Decoded::Array(v?)) + } + toml_edit::Value::InlineTable(v) => inline_table_to_decoded(v), + } +} + +fn table_to_decoded( + value: &toml_edit::Table, +) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + let table: Result<_, toml_test_harness::Error> = value + .iter() + .map(|(k, v)| { + let k = k.to_owned(); + let v = item_to_decoded(v)?; + Ok((k, v)) + }) + .collect(); + Ok(toml_test_harness::Decoded::Table(table?)) +} + +fn inline_table_to_decoded( + value: &toml_edit::InlineTable, +) -> Result<toml_test_harness::Decoded, toml_test_harness::Error> { + let table: Result<_, toml_test_harness::Error> = value + .iter() + .map(|(k, v)| { + let k = k.to_owned(); + let v = value_to_decoded(v)?; + Ok((k, v)) + }) + .collect(); + Ok(toml_test_harness::Decoded::Table(table?)) +} diff --git a/vendor/toml_edit/tests/decoder_compliance.rs b/vendor/toml_edit/tests/decoder_compliance.rs new file mode 100644 index 0000000..0f0b350 --- /dev/null +++ b/vendor/toml_edit/tests/decoder_compliance.rs @@ -0,0 +1,17 @@ +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.test(); +} diff --git a/vendor/toml_edit/tests/encoder.rs b/vendor/toml_edit/tests/encoder.rs new file mode 100644 index 0000000..808a20c --- /dev/null +++ b/vendor/toml_edit/tests/encoder.rs @@ -0,0 +1,111 @@ +#[derive(Copy, Clone)] +pub struct Encoder; + +impl toml_test_harness::Encoder for Encoder { + fn name(&self) -> &str { + "toml_edit" + } + + fn encode(&self, data: toml_test_harness::Decoded) -> Result<String, toml_test_harness::Error> { + let doc = decoded_to_document(&data)?; + Ok(doc.to_string()) + } +} + +fn decoded_to_document( + decoded: &toml_test_harness::Decoded, +) -> Result<toml_edit::Document, toml_test_harness::Error> { + let item = root_from_decoded(decoded)?; + let mut doc = toml_edit::Document::new(); + *doc = item; + Ok(doc) +} + +fn root_from_decoded( + decoded: &toml_test_harness::Decoded, +) -> Result<toml_edit::Table, toml_test_harness::Error> { + match decoded { + toml_test_harness::Decoded::Value(_) => { + Err(toml_test_harness::Error::new("Root cannot be a value")) + } + toml_test_harness::Decoded::Table(value) => value + .iter() + .map(|(k, v)| { + let k = k.as_str(); + let v = from_decoded(v)?; + Ok((k, v)) + }) + .collect(), + toml_test_harness::Decoded::Array(_) => { + Err(toml_test_harness::Error::new("Root cannot be an array")) + } + } +} + +fn from_decoded( + decoded: &toml_test_harness::Decoded, +) -> Result<toml_edit::Value, toml_test_harness::Error> { + let value = match decoded { + toml_test_harness::Decoded::Value(value) => from_decoded_value(value)?, + toml_test_harness::Decoded::Table(value) => { + toml_edit::Value::InlineTable(from_table(value)?) + } + toml_test_harness::Decoded::Array(value) => toml_edit::Value::Array(from_array(value)?), + }; + Ok(value) +} + +fn from_decoded_value( + decoded: &toml_test_harness::DecodedValue, +) -> Result<toml_edit::Value, toml_test_harness::Error> { + let value: toml_edit::Value = match decoded { + toml_test_harness::DecodedValue::String(value) => value.into(), + toml_test_harness::DecodedValue::Integer(value) => value + .parse::<i64>() + .map_err(toml_test_harness::Error::new)? + .into(), + toml_test_harness::DecodedValue::Float(value) => value + .parse::<f64>() + .map_err(toml_test_harness::Error::new)? + .into(), + toml_test_harness::DecodedValue::Bool(value) => value + .parse::<bool>() + .map_err(toml_test_harness::Error::new)? + .into(), + toml_test_harness::DecodedValue::Datetime(value) => value + .parse::<toml_edit::Datetime>() + .map_err(toml_test_harness::Error::new)? + .into(), + toml_test_harness::DecodedValue::DatetimeLocal(value) => value + .parse::<toml_edit::Datetime>() + .map_err(toml_test_harness::Error::new)? + .into(), + toml_test_harness::DecodedValue::DateLocal(value) => value + .parse::<toml_edit::Datetime>() + .map_err(toml_test_harness::Error::new)? + .into(), + toml_test_harness::DecodedValue::TimeLocal(value) => value + .parse::<toml_edit::Datetime>() + .map_err(toml_test_harness::Error::new)? + .into(), + }; + Ok(value) +} + +fn from_table( + decoded: &std::collections::HashMap<String, toml_test_harness::Decoded>, +) -> Result<toml_edit::InlineTable, toml_test_harness::Error> { + decoded + .iter() + .map(|(k, v)| { + let v = from_decoded(v)?; + Ok((k, v)) + }) + .collect() +} + +fn from_array( + decoded: &[toml_test_harness::Decoded], +) -> Result<toml_edit::Array, toml_test_harness::Error> { + decoded.iter().map(from_decoded).collect() +} diff --git a/vendor/toml_edit/tests/encoder_compliance.rs b/vendor/toml_edit/tests/encoder_compliance.rs new file mode 100644 index 0000000..ad65d75 --- /dev/null +++ b/vendor/toml_edit/tests/encoder_compliance.rs @@ -0,0 +1,14 @@ +mod decoder; +mod encoder; + +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.test(); +} diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/double-comma-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/double-comma-1.stderr new file mode 100644 index 0000000..543e1b6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/double-comma-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 12 + | +1 | array = [1,,2] + | ^ +invalid array +expected `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/double-comma-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/double-comma-2.stderr new file mode 100644 index 0000000..694d7ec --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/double-comma-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 14 + | +1 | array = [1,2,,] + | ^ +invalid array +expected `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/extending-table.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/extending-table.stderr new file mode 100644 index 0000000..6f92ff6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/extending-table.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 5, column 1 + | +5 | [a.c] + | ^ +invalid table header +dotted key `a` attempted to extend non-table type (array) diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/missing-separator.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/missing-separator.stderr new file mode 100644 index 0000000..8e21f51 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/missing-separator.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 13 + | +1 | wrong = [ 1 2 3 ] + | ^ +invalid array +expected `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/no-close-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/no-close-2.stderr new file mode 100644 index 0000000..81ae5a9 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/no-close-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 11 + | +1 | x = [42 # + | ^ +invalid array +expected `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/no-close-table-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/no-close-table-2.stderr new file mode 100644 index 0000000..535943e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/no-close-table-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 17 + | +1 | x = [{ key = 42 # + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/no-close-table.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/no-close-table.stderr new file mode 100644 index 0000000..b4c3c32 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/no-close-table.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 16 + | +1 | x = [{ key = 42 + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/no-close.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/no-close.stderr new file mode 100644 index 0000000..a4f0a88 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/no-close.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 24 + | +1 | long_array = [ 1, 2, 3 + | ^ +invalid array +expected `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/tables-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/tables-1.stderr new file mode 100644 index 0000000..771b4f6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/tables-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 4, column 1 + | +4 | [[fruit]] # Not allowed + | ^ +invalid table header +duplicate key `fruit` in document root diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/tables-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/tables-2.stderr new file mode 100644 index 0000000..1f88e6e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/tables-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 9, column 3 + | +9 | [fruit.variety] + | ^ +invalid table header +duplicate key `variety` in table `fruit` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/text-after-array-entries.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/text-after-array-entries.stderr new file mode 100644 index 0000000..23b5ac2 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/text-after-array-entries.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 46 + | +2 | "Is there life after an array separator?", No + | ^ +invalid array +expected `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/text-before-array-separator.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/text-before-array-separator.stderr new file mode 100644 index 0000000..9d66799 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/text-before-array-separator.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 46 + | +2 | "Is there life before an array separator?" No, + | ^ +invalid array +expected `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/array/text-in-array.stderr b/vendor/toml_edit/tests/fixtures/invalid/array/text-in-array.stderr new file mode 100644 index 0000000..5802373 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/array/text-in-array.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 3 + | +3 | I don't belong, + | ^ +invalid array +expected `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/almost-false-with-extra.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/almost-false-with-extra.stderr new file mode 100644 index 0000000..cd6c1cd --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/almost-false-with-extra.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | a = falsify + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/almost-false.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/almost-false.stderr new file mode 100644 index 0000000..550020b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/almost-false.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | a = fals + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/almost-true-with-extra.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/almost-true-with-extra.stderr new file mode 100644 index 0000000..c75c553 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/almost-true-with-extra.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | a = truthy + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/almost-true.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/almost-true.stderr new file mode 100644 index 0000000..0c97e00 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/almost-true.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | a = tru + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/just-f.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/just-f.stderr new file mode 100644 index 0000000..ed2b9f0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/just-f.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | a = f + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/just-t.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/just-t.stderr new file mode 100644 index 0000000..2c8b6a5 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/just-t.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | a = t + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/mixed-case.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/mixed-case.stderr new file mode 100644 index 0000000..b7c6192 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/mixed-case.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | valid = False + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/starting-same-false.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/starting-same-false.stderr new file mode 100644 index 0000000..b332089 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/starting-same-false.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 10 + | +1 | a = falsey + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/starting-same-true.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/starting-same-true.stderr new file mode 100644 index 0000000..6053103 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/starting-same-true.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 9 + | +1 | a = truer + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/wrong-case-false.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/wrong-case-false.stderr new file mode 100644 index 0000000..f67444c --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/wrong-case-false.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | b = FALSE + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/bool/wrong-case-true.stderr b/vendor/toml_edit/tests/fixtures/invalid/bool/wrong-case-true.stderr new file mode 100644 index 0000000..82bb619 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/bool/wrong-case-true.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | a = TRUE + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/bare-cr.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/bare-cr.stderr new file mode 100644 index 0000000..f0062f6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/bare-cr.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 1 + | +2 | + | ^ + diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/bare-formfeed.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/bare-formfeed.stderr new file mode 100644 index 0000000..313274a --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/bare-formfeed.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 17 + | +1 | bare-formfeed = + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/bare-null.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/bare-null.stderr Binary files differnew file mode 100644 index 0000000..cd5e936 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/bare-null.stderr diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/bare-vertical-tab.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/bare-vertical-tab.stderr new file mode 100644 index 0000000..c8e01ba --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/bare-vertical-tab.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 21 + | +1 | bare-vertical-tab = + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/comment-cr.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/comment-cr.stderr new file mode 100644 index 0000000..fb262e5 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/comment-cr.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 45 + | +1 | comment-cr = "Carriage return in comment" # +a=1 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/comment-del.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/comment-del.stderr new file mode 100644 index 0000000..3d25d68 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/comment-del.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 24 + | +1 | comment-del = "0x7f" # + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/comment-lf.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/comment-lf.stderr new file mode 100644 index 0000000..1613710 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/comment-lf.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 25 + | +1 | comment-lf = "ctrl-P" # + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/comment-null.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/comment-null.stderr Binary files differnew file mode 100644 index 0000000..4955b9d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/comment-null.stderr diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/comment-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/comment-us.stderr new file mode 100644 index 0000000..b48d4f3 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/comment-us.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 25 + | +1 | comment-us = "ctrl-_" # + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/control.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/control.stderr new file mode 100644 index 0000000..486aacf --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/control.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 9, column 22 + | +9 | string-null = "null\x00" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/multi-del.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/multi-del.stderr new file mode 100644 index 0000000..62702da --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/multi-del.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | multi-del = """null""" + | ^ +invalid multiline basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/multi-lf.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/multi-lf.stderr new file mode 100644 index 0000000..7b7a138 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/multi-lf.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | multi-lf = """null""" + | ^ +invalid multiline basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/multi-null.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/multi-null.stderr Binary files differnew file mode 100644 index 0000000..2d3c335 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/multi-null.stderr diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/multi-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/multi-us.stderr new file mode 100644 index 0000000..cf8e732 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/multi-us.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | multi-us = """null""" + | ^ +invalid multiline basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-del.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-del.stderr new file mode 100644 index 0000000..3beeae0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-del.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 23 + | +1 | rawmulti-del = '''null''' + | ^ +invalid multiline literal string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-lf.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-lf.stderr new file mode 100644 index 0000000..40782a2 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-lf.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 22 + | +1 | rawmulti-lf = '''null''' + | ^ +invalid multiline literal string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-null.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-null.stderr Binary files differnew file mode 100644 index 0000000..d583ce6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-null.stderr diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-us.stderr new file mode 100644 index 0000000..d413d54 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/rawmulti-us.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 22 + | +1 | rawmulti-us = '''null''' + | ^ +invalid multiline literal string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-del.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-del.stderr new file mode 100644 index 0000000..640ba46 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-del.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 22 + | +1 | rawstring-del = 'null' + | ^ +invalid literal string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-lf.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-lf.stderr new file mode 100644 index 0000000..e6499b6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-lf.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | rawstring-lf = 'null' + | ^ +invalid literal string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-null.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-null.stderr Binary files differnew file mode 100644 index 0000000..9227d09 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-null.stderr diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-us.stderr new file mode 100644 index 0000000..492cdf7 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/rawstring-us.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | rawstring-us = 'null' + | ^ +invalid literal string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/string-bs.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/string-bs.stderr new file mode 100644 index 0000000..556ba1d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/string-bs.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 23 + | +1 | string-bs = "backspace" + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/string-del.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/string-del.stderr new file mode 100644 index 0000000..85d7af3 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/string-del.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | string-del = "null" + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/string-lf.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/string-lf.stderr new file mode 100644 index 0000000..fbf0d1a --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/string-lf.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | string-lf = "null" + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/string-null.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/string-null.stderr Binary files differnew file mode 100644 index 0000000..e9fc0be --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/string-null.stderr diff --git a/vendor/toml_edit/tests/fixtures/invalid/control/string-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/control/string-us.stderr new file mode 100644 index 0000000..8278e57 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/control/string-us.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | string-us = "null" + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/hour-over.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/hour-over.stderr new file mode 100644 index 0000000..0e6747d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/hour-over.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 15 + | +2 | d = 2006-01-01T24:00:00-00:00 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/mday-over.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/mday-over.stderr new file mode 100644 index 0000000..edb9769 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/mday-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 13 + | +3 | d = 2006-01-32T00:00:00-00:00 + | ^ +invalid date-time +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/mday-under.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/mday-under.stderr new file mode 100644 index 0000000..6af2050 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/mday-under.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 13 + | +3 | d = 2006-01-00T00:00:00-00:00 + | ^ +invalid date-time +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/minute-over.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/minute-over.stderr new file mode 100644 index 0000000..20f3b4b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/minute-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 19 + | +2 | d = 2006-01-01T00:60:00-00:00 + | ^ +invalid date-time +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/month-over.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/month-over.stderr new file mode 100644 index 0000000..3333475 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/month-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 10 + | +2 | d = 2006-13-01T00:00:00-00:00 + | ^ +invalid date-time +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/month-under.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/month-under.stderr new file mode 100644 index 0000000..5d0cd06 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/month-under.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 10 + | +2 | d = 2007-00-01T00:00:00-00:00 + | ^ +invalid date-time +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/no-leads-with-milli.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/no-leads-with-milli.stderr new file mode 100644 index 0000000..df9190d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/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.12Z + | ^ +invalid date-time diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/no-leads.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/no-leads.stderr new file mode 100644 index 0000000..3e0ccf7 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/no-leads.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/vendor/toml_edit/tests/fixtures/invalid/datetime/no-secs.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/no-secs.stderr new file mode 100644 index 0000000..078d0a0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/no-secs.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 27 + | +2 | no-secs = 1987-07-05T17:45Z + | ^ +invalid date-time diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/no-t.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/no-t.stderr new file mode 100644 index 0000000..15e9554 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/no-t.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 18 + | +2 | no-t = 1987-07-0517:45:00Z + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/second-over.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/second-over.stderr new file mode 100644 index 0000000..186a38d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/second-over.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 22 + | +3 | d = 2006-01-01T00:00:61-00:00 + | ^ +invalid date-time +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/time-no-leads-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/time-no-leads-2.stderr new file mode 100644 index 0000000..fd77fb2 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/time-no-leads-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 11 + | +2 | d = 01:32:0 + | ^ +invalid time diff --git a/vendor/toml_edit/tests/fixtures/invalid/datetime/time-no-leads.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/time-no-leads.stderr new file mode 100644 index 0000000..7a98902 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/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/vendor/toml_edit/tests/fixtures/invalid/datetime/trailing-t.stderr b/vendor/toml_edit/tests/fixtures/invalid/datetime/trailing-t.stderr new file mode 100644 index 0000000..061ec26 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/datetime/trailing-t.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 15 + | +2 | d = 2006-01-30T + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-at-end.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-at-end.stderr new file mode 100644 index 0000000..7a11cf9 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-at-end.stderr @@ -0,0 +1 @@ +incomplete utf-8 byte sequence from index 241
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-comment.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-comment.stderr new file mode 100644 index 0000000..72d1465 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-comment.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 2
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-multiline-literal.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-multiline-literal.stderr new file mode 100644 index 0000000..0c70f28 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-multiline-literal.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 66
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-multiline.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-multiline.stderr new file mode 100644 index 0000000..0c70f28 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-multiline.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 66
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-string-literal.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-string-literal.stderr new file mode 100644 index 0000000..9e1a687 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-string-literal.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 64
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-string.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-string.stderr new file mode 100644 index 0000000..9e1a687 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/bad-utf8-in-string.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 64
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/bom-not-at-start-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/bom-not-at-start-1.stderr new file mode 100644 index 0000000..8d9d90b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/bom-not-at-start-1.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 17
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/bom-not-at-start-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/bom-not-at-start-2.stderr new file mode 100644 index 0000000..8fce408 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/bom-not-at-start-2.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 18
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/utf16-bom.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/utf16-bom.stderr new file mode 100644 index 0000000..b1b9eed --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/utf16-bom.stderr @@ -0,0 +1 @@ +invalid utf-8 sequence of 1 bytes from index 0
\ No newline at end of file diff --git a/vendor/toml_edit/tests/fixtures/invalid/encoding/utf16.stderr b/vendor/toml_edit/tests/fixtures/invalid/encoding/utf16.stderr Binary files differnew file mode 100644 index 0000000..6886165 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/encoding/utf16.stderr diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/double-point-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/double-point-1.stderr new file mode 100644 index 0000000..390520f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/double-point-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | double-point-1 = 0..1 + | ^ +invalid floating-point number +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/double-point-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/double-point-2.stderr new file mode 100644 index 0000000..a020a48 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/double-point-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | double-point-2 = 0.1.2 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-e-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-e-1.stderr new file mode 100644 index 0000000..5411839 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-e-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | exp-double-e-1 = 1ee2 + | ^ +invalid floating-point number diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-e-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-e-2.stderr new file mode 100644 index 0000000..1b99d37 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-e-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | exp-double-e-2 = 1e2e3 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-us.stderr new file mode 100644 index 0000000..6a66e43 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/exp-double-us.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | exp-double-us = 1e__23 + | ^ +invalid floating-point number diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/exp-leading-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/exp-leading-us.stderr new file mode 100644 index 0000000..7696686 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/exp-leading-us.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | exp-leading-us = 1e_23 + | ^ +invalid floating-point number diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/exp-point-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/exp-point-1.stderr new file mode 100644 index 0000000..87f0a0b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/exp-point-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | exp-point-1 = 1e2.3 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/exp-point-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/exp-point-2.stderr new file mode 100644 index 0000000..8089050 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/exp-point-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 17 + | +1 | exp-point-2 = 1.e2 + | ^ +invalid floating-point number +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/exp-trailing-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/exp-trailing-us.stderr new file mode 100644 index 0000000..9a28184 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/exp-trailing-us.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | exp-trailing-us = 1e_23_ + | ^ +invalid floating-point number diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/float.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/float.stderr new file mode 100644 index 0000000..627650f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/float.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 17 + | +1 | leading-zero = 03.14 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-1.stderr new file mode 100644 index 0000000..99fe59b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | inf-incomplete-1 = in + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-2.stderr new file mode 100644 index 0000000..38ef4cf --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | inf-incomplete-2 = +in + | ^ +invalid integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-3.stderr new file mode 100644 index 0000000..af66478 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/inf-incomplete-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | inf-incomplete-3 = -in + | ^ +invalid integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/inf_underscore.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/inf_underscore.stderr new file mode 100644 index 0000000..8254842 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/inf_underscore.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 18 + | +1 | inf_underscore = in_f + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/leading-point-neg.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/leading-point-neg.stderr new file mode 100644 index 0000000..c46efe1 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/leading-point-neg.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 22 + | +1 | leading-point-neg = -.12345 + | ^ +invalid integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/leading-point-plus.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/leading-point-plus.stderr new file mode 100644 index 0000000..a643a7e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/leading-point-plus.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 23 + | +1 | leading-point-plus = +.12345 + | ^ +invalid integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/leading-point.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/leading-point.stderr new file mode 100644 index 0000000..65e66b0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/leading-point.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 17 + | +1 | leading-point = .12345 + | ^ +invalid floating-point number +expected leading digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/leading-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/leading-us.stderr new file mode 100644 index 0000000..e6d8e52 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/leading-us.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 14 + | +1 | leading-us = _1.2 + | ^ +invalid integer +expected leading digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero-neg.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero-neg.stderr new file mode 100644 index 0000000..a60ec4d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero-neg.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 22 + | +1 | leading-zero-neg = -03.14 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero-plus.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero-plus.stderr new file mode 100644 index 0000000..f7c612b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero-plus.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 23 + | +1 | leading-zero-plus = +03.14 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero.stderr new file mode 100644 index 0000000..627650f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/leading-zero.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 17 + | +1 | leading-zero = 03.14 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-1.stderr new file mode 100644 index 0000000..36faeb0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | nan-incomplete-1 = na + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-2.stderr new file mode 100644 index 0000000..38e0151 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | nan-incomplete-2 = +na + | ^ +invalid integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-3.stderr new file mode 100644 index 0000000..e03ff4b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/nan-incomplete-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | nan-incomplete-3 = -na + | ^ +invalid integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/nan_underscore.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/nan_underscore.stderr new file mode 100644 index 0000000..f6dead3 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/nan_underscore.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 18 + | +1 | nan_underscore = na_n + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point-min.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point-min.stderr new file mode 100644 index 0000000..41f4ad9 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point-min.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 25 + | +1 | trailing-point-min = -1. + | ^ +invalid floating-point number +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point-plus.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point-plus.stderr new file mode 100644 index 0000000..9927935 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point-plus.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 26 + | +1 | trailing-point-plus = +1. + | ^ +invalid floating-point number +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point.stderr new file mode 100644 index 0000000..bd345d2 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-point.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | trailing-point = 1. + | ^ +invalid floating-point number +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/trailing-us-exp.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-us-exp.stderr new file mode 100644 index 0000000..811f951 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-us-exp.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 21 + | +2 | trailing-us-exp = 1_e2 + | ^ +invalid integer +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/trailing-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-us.stderr new file mode 100644 index 0000000..aa4f288 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/trailing-us.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 19 + | +1 | trailing-us = 1.2_ + | ^ +invalid floating-point number +expected digit, digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/us-after-point.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/us-after-point.stderr new file mode 100644 index 0000000..d93821d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/us-after-point.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | us-after-point = 1._2 + | ^ +invalid floating-point number +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/float/us-before-point.stderr b/vendor/toml_edit/tests/fixtures/invalid/float/us-before-point.stderr new file mode 100644 index 0000000..109d8f7 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/float/us-before-point.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 21 + | +1 | us-before-point = 1_.2 + | ^ +invalid integer +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/add.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/add.stderr new file mode 100644 index 0000000..4108142 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/add.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 1 + | +3 | [a.b] + | ^ +invalid table header +dotted key `a` attempted to extend non-table type (inline table) diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/double-comma.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/double-comma.stderr new file mode 100644 index 0000000..ab4772b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/double-comma.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | t = {x=3,,y=4} + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/duplicate-key.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/duplicate-key.stderr new file mode 100644 index 0000000..acee967 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/duplicate-key.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 4 + | +2 | a={b=1, b=2} + | ^ +duplicate key `b` diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/empty.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/empty.stderr new file mode 100644 index 0000000..0fcfd34 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/empty.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 6 + | +1 | t = {,} + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-1.stderr new file mode 100644 index 0000000..ed67c3a --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 18 + | +3 | simple = { a = 1 + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-2.stderr new file mode 100644 index 0000000..a815758 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | t = {a=1, + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-3.stderr new file mode 100644 index 0000000..4aff61b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | t = {a=1 + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-4.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-4.stderr new file mode 100644 index 0000000..658456b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/linebreak-4.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 14 + | +1 | json_like = { + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/no-comma.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/no-comma.stderr new file mode 100644 index 0000000..8955218 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/no-comma.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 12 + | +1 | t = {x = 3 y = 4} + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/overwrite.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/overwrite.stderr new file mode 100644 index 0000000..5c48ee2 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/overwrite.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 1 + | +3 | a={} + | ^ +duplicate key `a` in document root diff --git a/vendor/toml_edit/tests/fixtures/invalid/inline-table/trailing-comma.stderr b/vendor/toml_edit/tests/fixtures/invalid/inline-table/trailing-comma.stderr new file mode 100644 index 0000000..b17fca5 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/inline-table/trailing-comma.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 3, column 18 + | +3 | abc = { abc = 123, } + | ^ +invalid inline table +expected `}` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/capital-bin.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/capital-bin.stderr new file mode 100644 index 0000000..333ba92 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/capital-bin.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 16 + | +1 | capital-bin = 0B0 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/capital-hex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/capital-hex.stderr new file mode 100644 index 0000000..ac064f9 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/capital-hex.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 16 + | +1 | capital-hex = 0X1 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/capital-oct.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/capital-oct.stderr new file mode 100644 index 0000000..774a8f2 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/capital-oct.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 16 + | +1 | capital-oct = 0O0 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/double-sign-nex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/double-sign-nex.stderr new file mode 100644 index 0000000..542ba06 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/double-sign-nex.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | double-sign-nex = --99 + | ^ +invalid integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/double-sign-plus.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/double-sign-plus.stderr new file mode 100644 index 0000000..8f8bad0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/double-sign-plus.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | double-sign-plus = ++99 + | ^ +invalid integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/double-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/double-us.stderr new file mode 100644 index 0000000..e229868 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/double-us.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 15 + | +1 | double-us = 1__23 + | ^ +invalid integer +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-bin.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-bin.stderr new file mode 100644 index 0000000..13d7b46 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-bin.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | incomplete-bin = 0b + | ^ +invalid binary integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-hex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-hex.stderr new file mode 100644 index 0000000..ea5073a --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-hex.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | incomplete-hex = 0x + | ^ +invalid hexadecimal integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-oct.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-oct.stderr new file mode 100644 index 0000000..46d51c1 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/incomplete-oct.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | incomplete-oct = 0o + | ^ +invalid octal integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/integer.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/integer.stderr new file mode 100644 index 0000000..f058a2d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/integer.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | leading-zero-1 = 01 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-bin.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-bin.stderr new file mode 100644 index 0000000..62c00fb --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-bin.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | invalid-bin = 0b0012 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-hex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-hex.stderr new file mode 100644 index 0000000..29b112b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-hex.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | invalid-hex = 0xaafz + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-oct.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-oct.stderr new file mode 100644 index 0000000..f3e1ada --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/invalid-oct.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | invalid-oct = 0o778 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-bin.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-bin.stderr new file mode 100644 index 0000000..c893e75 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-bin.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 18 + | +1 | leading-us-bin = _0o1 + | ^ +invalid integer +expected leading digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-hex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-hex.stderr new file mode 100644 index 0000000..12eb8e6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-hex.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 18 + | +1 | leading-us-hex = _0o1 + | ^ +invalid integer +expected leading digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-oct.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-oct.stderr new file mode 100644 index 0000000..c670551 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us-oct.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 18 + | +1 | leading-us-oct = _0o1 + | ^ +invalid integer +expected leading digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us.stderr new file mode 100644 index 0000000..f53275c --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-us.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 14 + | +1 | leading-us = _123 + | ^ +invalid integer +expected leading digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-1.stderr new file mode 100644 index 0000000..f058a2d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | leading-zero-1 = 01 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-2.stderr new file mode 100644 index 0000000..0823814 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | leading-zero-2 = 00 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-3.stderr new file mode 100644 index 0000000..7b0e481 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 19 + | +1 | leading-zero-3 = 0_0 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-1.stderr new file mode 100644 index 0000000..384c9d4 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 25 + | +1 | leading-zero-sign-1 = -01 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-2.stderr new file mode 100644 index 0000000..795c329 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 25 + | +1 | leading-zero-sign-2 = +01 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-3.stderr new file mode 100644 index 0000000..639aef5 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/leading-zero-sign-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 25 + | +1 | leading-zero-sign-3 = +0_1 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/negative-bin.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/negative-bin.stderr new file mode 100644 index 0000000..7122d38 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/negative-bin.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | negative-bin = -0b11010110 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/negative-hex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/negative-hex.stderr new file mode 100644 index 0000000..0c7e584 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/negative-hex.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | negative-hex = -0xff + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/negative-oct.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/negative-oct.stderr new file mode 100644 index 0000000..fcf3140 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/negative-oct.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | negative-oct = -0o99 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/positive-bin.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/positive-bin.stderr new file mode 100644 index 0000000..bc5dc4e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/positive-bin.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | positive-bin = +0b11010110 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/positive-hex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/positive-hex.stderr new file mode 100644 index 0000000..f571114 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/positive-hex.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | positive-hex = +0xff + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/positive-oct.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/positive-oct.stderr new file mode 100644 index 0000000..cc09466 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/positive-oct.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | positive-oct = +0o99 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/text-after-integer.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/text-after-integer.stderr new file mode 100644 index 0000000..0405cb4 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/text-after-integer.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 13 + | +1 | answer = 42 the ultimate answer? + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-bin.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-bin.stderr new file mode 100644 index 0000000..7042a6e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-bin.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 23 + | +1 | trailing-us-bin = 0b1_ + | ^ +invalid binary integer +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-hex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-hex.stderr new file mode 100644 index 0000000..9526a94 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-hex.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 23 + | +1 | trailing-us-hex = 0x1_ + | ^ +invalid hexadecimal integer +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-oct.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-oct.stderr new file mode 100644 index 0000000..bb4330d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us-oct.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 23 + | +1 | trailing-us-oct = 0o1_ + | ^ +invalid octal integer +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us.stderr new file mode 100644 index 0000000..f8c901e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/trailing-us.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 19 + | +1 | trailing-us = 123_ + | ^ +invalid integer +expected digit diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-bin.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-bin.stderr new file mode 100644 index 0000000..1620bc6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-bin.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | us-after-bin = 0b_1 + | ^ +invalid binary integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-hex.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-hex.stderr new file mode 100644 index 0000000..e8283a0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-hex.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | us-after-hex = 0x_1 + | ^ +invalid hexadecimal integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-oct.stderr b/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-oct.stderr new file mode 100644 index 0000000..e6884d0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/integer/us-after-oct.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 18 + | +1 | us-after-oct = 0o_1 + | ^ +invalid octal integer diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/after-array.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/after-array.stderr new file mode 100644 index 0000000..861f82d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/after-array.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 14 + | +1 | [[agencies]] owner = "S Cjelli" + | ^ +invalid table header +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/after-table.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/after-table.stderr new file mode 100644 index 0000000..499a430 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/after-table.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | [error] this = "should not be here" + | ^ +invalid table header +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/after-value.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/after-value.stderr new file mode 100644 index 0000000..9852ec8 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/after-value.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 15 + | +1 | first = "Tom" last = "Preston-Werner" # INVALID + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/bare-invalid-character.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/bare-invalid-character.stderr new file mode 100644 index 0000000..0ba21fd --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/bare-invalid-character.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 5 + | +1 | bare!key = 123 + | ^ +expected `.`, `=` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/dotted-redefine-table.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/dotted-redefine-table.stderr new file mode 100644 index 0000000..3a2b8d5 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/dotted-redefine-table.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 4, column 1 + | +4 | a.b.c = 2 + | ^ +dotted key `a.b` attempted to extend non-table type (integer) diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/duplicate-keys.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/duplicate-keys.stderr new file mode 100644 index 0000000..74149f8 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/duplicate-keys.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 1 + | +2 | dupe = true + | ^ +duplicate key `dupe` in document root diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/duplicate.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/duplicate.stderr new file mode 100644 index 0000000..8c7d7b7 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/duplicate.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 1 + | +3 | name = "Pradyun" + | ^ +duplicate key `name` in document root diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/empty.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/empty.stderr new file mode 100644 index 0000000..b859159 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/empty.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 2 + | +1 | = 1 + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/escape.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/escape.stderr new file mode 100644 index 0000000..2a4ee3f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/escape.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 1 + | +1 | \u00c0 = "latin capital letter A with grave" + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/hash.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/hash.stderr new file mode 100644 index 0000000..15d8048 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/hash.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 2 + | +1 | a# = 1 + | ^ +expected `.`, `=` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/multiline.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/multiline.stderr new file mode 100644 index 0000000..b4241ee --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/multiline.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 3 + | +1 | """long + | ^ +expected `.`, `=` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/newline.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/newline.stderr new file mode 100644 index 0000000..141932e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/newline.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 8 + | +1 | barekey + | ^ +expected `.`, `=` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/no-eol.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/no-eol.stderr new file mode 100644 index 0000000..fc3c01e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/no-eol.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 7 + | +1 | a = 1 b = 2 + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/open-bracket.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/open-bracket.stderr new file mode 100644 index 0000000..eee8cba --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/open-bracket.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 6 + | +1 | [abc = 1 + | ^ +invalid table header +expected `.`, `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/partial-quoted.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/partial-quoted.stderr new file mode 100644 index 0000000..e0a7c32 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/partial-quoted.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 8 + | +1 | partial"quoted" = 5 + | ^ +expected `.`, `=` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/quoted-unclosed-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/quoted-unclosed-1.stderr new file mode 100644 index 0000000..6f15232 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/quoted-unclosed-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 9 + | +1 | "key = x + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/quoted-unclosed-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/quoted-unclosed-2.stderr new file mode 100644 index 0000000..f3fdc7f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/quoted-unclosed-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 5 + | +1 | "key + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/single-open-bracket.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/single-open-bracket.stderr new file mode 100644 index 0000000..022f1fa --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/single-open-bracket.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 2 + | +1 | [ + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/space.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/space.stderr new file mode 100644 index 0000000..cd3258b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/space.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 3 + | +1 | a b = 1 + | ^ +expected `.`, `=` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/special-character.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/special-character.stderr new file mode 100644 index 0000000..7ada2f2 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/special-character.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 1 + | +1 | μ = "greek small letter mu" + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/start-bracket.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/start-bracket.stderr new file mode 100644 index 0000000..43f937b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/start-bracket.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 6 + | +2 | [xyz = 5 + | ^ +invalid table header +expected `.`, `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/start-dot.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/start-dot.stderr new file mode 100644 index 0000000..c71f0cf --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/start-dot.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 1 + | +1 | .key = 1 + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/two-equals.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/two-equals.stderr new file mode 100644 index 0000000..2f92886 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/two-equals.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 6 + | +1 | key= = 1 + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/two-equals2.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/two-equals2.stderr new file mode 100644 index 0000000..f2adb1f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/two-equals2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 3 + | +1 | a==1 + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/two-equals3.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/two-equals3.stderr new file mode 100644 index 0000000..dbee169 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/two-equals3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 3 + | +1 | a=b=1 + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/without-value-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/without-value-1.stderr new file mode 100644 index 0000000..2ddb124 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/without-value-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 4 + | +1 | key + | ^ +expected `.`, `=` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/without-value-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/without-value-2.stderr new file mode 100644 index 0000000..a3f280f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/without-value-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 7 + | +1 | key = + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/without-value-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/without-value-3.stderr new file mode 100644 index 0000000..a6ca6ff --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/without-value-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 6 + | +1 | "key" + | ^ +expected `.`, `=` diff --git a/vendor/toml_edit/tests/fixtures/invalid/key/without-value-4.stderr b/vendor/toml_edit/tests/fixtures/invalid/key/without-value-4.stderr new file mode 100644 index 0000000..c14af0c --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/key/without-value-4.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | "key" = + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/spec/inline-table-2-0.stderr b/vendor/toml_edit/tests/fixtures/invalid/spec/inline-table-2-0.stderr new file mode 100644 index 0000000..7fed269 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/spec/inline-table-2-0.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 1 + | +3 | type.edible = false # INVALID + | ^ +dotted key `type` attempted to extend non-table type (inline table) diff --git a/vendor/toml_edit/tests/fixtures/invalid/spec/inline-table-3-0.stderr b/vendor/toml_edit/tests/fixtures/invalid/spec/inline-table-3-0.stderr new file mode 100644 index 0000000..45ba696 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/spec/inline-table-3-0.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 1 + | +3 | type = { edible = false } # INVALID + | ^ +duplicate key `type` in table `product` diff --git a/vendor/toml_edit/tests/fixtures/invalid/spec/key-value-pair-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/spec/key-value-pair-1.stderr new file mode 100644 index 0000000..ba765a8 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/spec/key-value-pair-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 7 + | +1 | key = # INVALID + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/spec/keys-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/spec/keys-2.stderr new file mode 100644 index 0000000..bdbcce4 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/spec/keys-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 1 + | +1 | = "no key name" # INVALID + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/spec/string-4-0.stderr b/vendor/toml_edit/tests/fixtures/invalid/spec/string-4-0.stderr new file mode 100644 index 0000000..e82601d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/spec/string-4-0.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 46 + | +2 | str5 = """Here are three quotation marks: """.""" # INVALID + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/spec/string-7-0.stderr b/vendor/toml_edit/tests/fixtures/invalid/spec/string-7-0.stderr new file mode 100644 index 0000000..7a928e1 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/spec/string-7-0.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 3, column 48 + | +3 | apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/spec/table-9-0.stderr b/vendor/toml_edit/tests/fixtures/invalid/spec/table-9-0.stderr new file mode 100644 index 0000000..a2e1d49 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/spec/table-9-0.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 5, column 1 + | +5 | [fruit.apple] # INVALID + | ^ +invalid table header +duplicate key `apple` in table `fruit` diff --git a/vendor/toml_edit/tests/fixtures/invalid/spec/table-9-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/spec/table-9-1.stderr new file mode 100644 index 0000000..78dea21 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/spec/table-9-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 6, column 1 + | +6 | [fruit.apple.taste] # INVALID + | ^ +invalid table header +duplicate key `taste` in table `fruit.apple` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-byte-escape.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-byte-escape.stderr new file mode 100644 index 0000000..6d88863 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-byte-escape.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 14 + | +1 | naughty = "\xAg" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-codepoint.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-codepoint.stderr new file mode 100644 index 0000000..4061c79 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-codepoint.stderr @@ -0,0 +1,6 @@ +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/vendor/toml_edit/tests/fixtures/invalid/string/bad-concat.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-concat.stderr new file mode 100644 index 0000000..a7346a4 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-concat.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | no_concat = "first" "second" + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-escape-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-escape-1.stderr new file mode 100644 index 0000000..02cb483 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-escape-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 43 + | +1 | invalid-escape = "This string has a bad \a escape character." + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-escape-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-escape-2.stderr new file mode 100644 index 0000000..57f0ace --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-escape-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 43 + | +1 | invalid-escape = "This string has a bad \ escape character." + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-1.stderr new file mode 100644 index 0000000..5d5577f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | bad-hex-esc-1 = "\x0g" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-2.stderr new file mode 100644 index 0000000..5a40ad4 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | bad-hex-esc-2 = "\xG0" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-3.stderr new file mode 100644 index 0000000..70e1183 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | bad-hex-esc-3 = "\x" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-4.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-4.stderr new file mode 100644 index 0000000..df028ee --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-4.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | bad-hex-esc-4 = "\x 50" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-5.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-5.stderr new file mode 100644 index 0000000..4b5cd33 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc-5.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | bad-hex-esc-5 = "\x 50" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc.stderr new file mode 100644 index 0000000..5d5577f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-hex-esc.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 20 + | +1 | bad-hex-esc-1 = "\x0g" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-multiline.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-multiline.stderr new file mode 100644 index 0000000..f88e0dd --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-multiline.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 20 + | +1 | multi = "first line + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-slash-escape.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-slash-escape.stderr new file mode 100644 index 0000000..19bd111 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-slash-escape.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 43 + | +1 | invalid-escape = "This string has a bad \/ escape character." + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-1.stderr new file mode 100644 index 0000000..a9e439b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 13 + | +1 | str = "val\ue" + | ^ +invalid unicode 4-digit hex code diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-2.stderr new file mode 100644 index 0000000..87c8681 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 13 + | +1 | str = "val\Ux" + | ^ +invalid unicode 8-digit hex code diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-3.stderr new file mode 100644 index 0000000..61f8ded --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-3.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 13 + | +1 | str = "val\U0000000" + | ^ +invalid unicode 8-digit hex code diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-4.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-4.stderr new file mode 100644 index 0000000..1a781d9 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-4.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 13 + | +1 | str = "val\U0000" + | ^ +invalid unicode 8-digit hex code diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-5.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-5.stderr new file mode 100644 index 0000000..88773ca --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/bad-uni-esc-5.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 13 + | +1 | str = "val\Ugggggggg" + | ^ +invalid unicode 8-digit hex code diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/basic-byte-escapes.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/basic-byte-escapes.stderr new file mode 100644 index 0000000..64f8d86 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/basic-byte-escapes.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 13 + | +1 | answer = "\x33" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-out-of-range-unicode-escape-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-out-of-range-unicode-escape-1.stderr new file mode 100644 index 0000000..c4be6a6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-out-of-range-unicode-escape-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 10 + | +1 | a = """\UFFFFFFFF""" + | ^ +invalid unicode 8-digit hex code +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-out-of-range-unicode-escape-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-out-of-range-unicode-escape-2.stderr new file mode 100644 index 0000000..f034203 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-out-of-range-unicode-escape-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 10 + | +1 | a = """\U00D80000""" + | ^ +invalid unicode 8-digit hex code +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-quotes.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-quotes.stderr new file mode 100644 index 0000000..7a16008 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-quotes.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 46 + | +1 | str5 = """Here are three quotation marks: """.""" + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-unknown-escape.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-unknown-escape.stderr new file mode 100644 index 0000000..d2462bf --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/basic-multiline-unknown-escape.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 10 + | +1 | a = """\@""" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/basic-out-of-range-unicode-escape-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/basic-out-of-range-unicode-escape-1.stderr new file mode 100644 index 0000000..806e6e7 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/basic-out-of-range-unicode-escape-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 8 + | +1 | a = "\UFFFFFFFF" + | ^ +invalid unicode 8-digit hex code +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/basic-out-of-range-unicode-escape-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/basic-out-of-range-unicode-escape-2.stderr new file mode 100644 index 0000000..69396c6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/basic-out-of-range-unicode-escape-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 8 + | +1 | a = "\U00D80000" + | ^ +invalid unicode 8-digit hex code +value is out of range diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/basic-unknown-escape.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/basic-unknown-escape.stderr new file mode 100644 index 0000000..a7fbb25 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/basic-unknown-escape.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 8 + | +1 | a = "\@" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/literal-multiline-quotes-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/literal-multiline-quotes-1.stderr new file mode 100644 index 0000000..ed65b33 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/literal-multiline-quotes-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 28 + | +1 | a = '''6 apostrophes: '''''' + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/literal-multiline-quotes-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/literal-multiline-quotes-2.stderr new file mode 100644 index 0000000..3fbb44a --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/literal-multiline-quotes-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 29 + | +1 | a = '''15 apostrophes: '''''''''''''''''' + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/missing-quotes.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/missing-quotes.stderr new file mode 100644 index 0000000..3558aab --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/missing-quotes.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 8 + | +1 | name = value + | ^ +invalid string +expected `"`, `'` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-1.stderr new file mode 100644 index 0000000..1a3b24b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-1.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 11 + | +1 | k = """t\a""" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-2.stderr new file mode 100644 index 0000000..db17685 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 11 + | +2 | k = """t\ t""" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-3.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-3.stderr new file mode 100644 index 0000000..646aa4d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-bad-escape-3.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 11 + | +2 | k = """t\ """ + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/multiline-escape-space.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-escape-space.stderr new file mode 100644 index 0000000..4b3c32b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-escape-space.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 9 + | +2 | foo \ \n + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\`, `"` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/multiline-no-close-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-no-close-2.stderr new file mode 100644 index 0000000..be5420a --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-no-close-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 7 + | +1 | x=""" + | ^ +invalid multiline basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/multiline-no-close.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-no-close.stderr new file mode 100644 index 0000000..99e967a --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-no-close.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 2, column 20 + | +2 | this will fail + | ^ +invalid multiline basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/multiline-quotes-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-quotes-1.stderr new file mode 100644 index 0000000..c3cf4c6 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/multiline-quotes-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 23 + | +1 | a = """6 quotes: """""" + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/no-close.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/no-close.stderr new file mode 100644 index 0000000..f23223d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/no-close.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 42 + | +1 | no-ending-quote = "One time, at band camp + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/text-after-string.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/text-after-string.stderr new file mode 100644 index 0000000..f05e33b --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/text-after-string.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 41 + | +1 | string = "Is there life after strings?" No. + | ^ +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/string/wrong-close.stderr b/vendor/toml_edit/tests/fixtures/invalid/string/wrong-close.stderr new file mode 100644 index 0000000..9a785e0 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/string/wrong-close.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 39 + | +1 | bad-ending-quote = "double and single' + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/append-with-dotted-keys-1.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/append-with-dotted-keys-1.stderr new file mode 100644 index 0000000..54ee50e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/append-with-dotted-keys-1.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 17, column 3 + | +17 | b.c.t = "Using dotted keys to add to [a.b.c] after explicitly defining it above is not allowed" + | ^ +duplicate key `c` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/append-with-dotted-keys-2.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/append-with-dotted-keys-2.stderr new file mode 100644 index 0000000..7c665f9 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/append-with-dotted-keys-2.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 8, column 3 + | +8 | b.c.d.k.t = "Using dotted keys to add to [a.b.c.d] after explicitly defining it above is not allowed" + | ^ +duplicate key `d` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/array-empty.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/array-empty.stderr new file mode 100644 index 0000000..ad2440a --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/array-empty.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 3 + | +1 | [[]] + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/array-implicit.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/array-implicit.stderr new file mode 100644 index 0000000..ed1ab7f --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/array-implicit.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 13, column 1 + | +13 | [[albums]] + | ^ +invalid table header +duplicate key `albums` in document root diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/array-missing-bracket.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/array-missing-bracket.stderr new file mode 100644 index 0000000..ed370ef --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/array-missing-bracket.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | [[albums] + | ^ +invalid table header +expected `.`, `]]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-dotted-table.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-dotted-table.stderr new file mode 100644 index 0000000..3cbc0a3 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-dotted-table.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 4, column 1 + | +4 | [fruit.apple] # INVALID + | ^ +invalid table header +duplicate key `apple` in table `fruit` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-dotted-table2.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-dotted-table2.stderr new file mode 100644 index 0000000..c5ab1eb --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-dotted-table2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 4, column 1 + | +4 | [fruit.apple.taste] # INVALID + | ^ +invalid table header +duplicate key `taste` in table `fruit.apple` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-table.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-table.stderr new file mode 100644 index 0000000..bc76d9c --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-key-table.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 4, column 1 + | +4 | [fruit.type] + | ^ +invalid table header +duplicate key `type` in table `fruit` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-table-array.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-table-array.stderr new file mode 100644 index 0000000..536fdc3 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-table-array.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 1 + | +2 | [[tbl]] + | ^ +invalid table header +duplicate key `tbl` in document root diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-table-array2.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-table-array2.stderr new file mode 100644 index 0000000..81c27fb --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate-table-array2.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 2, column 1 + | +2 | [tbl] + | ^ +invalid table header +duplicate key `tbl` in document root diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/duplicate.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate.stderr new file mode 100644 index 0000000..81bf4ed --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/duplicate.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 4, column 1 + | +4 | [a] + | ^ +invalid table header +duplicate key `a` in document root diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/empty-implicit-table.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/empty-implicit-table.stderr new file mode 100644 index 0000000..a7f7444 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/empty-implicit-table.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | [naughty..naughty] + | ^ +invalid table header +expected `.`, `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/empty.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/empty.stderr new file mode 100644 index 0000000..5dd0d56 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/empty.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 2 + | +1 | [] + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/equals-sign.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/equals-sign.stderr new file mode 100644 index 0000000..52451c9 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/equals-sign.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 6 + | +1 | [name=bad] + | ^ +invalid table header +expected `.`, `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/llbrace.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/llbrace.stderr new file mode 100644 index 0000000..316590d --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/llbrace.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 3 + | +1 | [ [table]] + | ^ +invalid key diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/nested-brackets-close.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/nested-brackets-close.stderr new file mode 100644 index 0000000..e74e178 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/nested-brackets-close.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 4 + | +1 | [a]b] + | ^ +invalid table header +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/nested-brackets-open.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/nested-brackets-open.stderr new file mode 100644 index 0000000..094cf7c --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/nested-brackets-open.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 3 + | +1 | [a[b] + | ^ +invalid table header +expected `.`, `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/quoted-no-close.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/quoted-no-close.stderr new file mode 100644 index 0000000..2b05e95 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/quoted-no-close.stderr @@ -0,0 +1,5 @@ +TOML parse error at line 1, column 21 + | +1 | ["where will it end] + | ^ +invalid basic string diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/redefine.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/redefine.stderr new file mode 100644 index 0000000..99c1f98 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/redefine.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 5, column 1 + | +5 | [a.b] + | ^ +invalid table header +duplicate key `b` in table `a` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/rrbrace.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/rrbrace.stderr new file mode 100644 index 0000000..adcdf90 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/rrbrace.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 8 + | +1 | [[table] ] + | ^ +invalid table header +expected `.`, `]]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/text-after-table.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/text-after-table.stderr new file mode 100644 index 0000000..e7d7c4e --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/text-after-table.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 9 + | +1 | [error] this shouldn't be here + | ^ +invalid table header +expected newline, `#` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/whitespace.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/whitespace.stderr new file mode 100644 index 0000000..aa149d2 --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/whitespace.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 10 + | +1 | [invalid key] + | ^ +invalid table header +expected `.`, `]` diff --git a/vendor/toml_edit/tests/fixtures/invalid/table/with-pound.stderr b/vendor/toml_edit/tests/fixtures/invalid/table/with-pound.stderr new file mode 100644 index 0000000..f5531cc --- /dev/null +++ b/vendor/toml_edit/tests/fixtures/invalid/table/with-pound.stderr @@ -0,0 +1,6 @@ +TOML parse error at line 1, column 5 + | +1 | [key#group] + | ^ +invalid table header +expected `.`, `]` diff --git a/vendor/toml_edit/tests/invalid.rs b/vendor/toml_edit/tests/invalid.rs new file mode 100644 index 0000000..9fff235 --- /dev/null +++ b/vendor/toml_edit/tests/invalid.rs @@ -0,0 +1,26 @@ +use toml_edit::Document; + +fn main() { + let args = libtest_mimic::Arguments::from_args(); + let tests = toml_test_data::invalid() + .map(|case| { + libtest_mimic::Trial::test(case.name.display().to_string(), || { + let expect_path = + std::path::Path::new("tests/fixtures").join(case.name.with_extension("stderr")); + let err = match run_case(case.fixture) { + Ok(()) => "".to_owned(), + Err(err) => err, + }; + snapbox::assert_eq_path(expect_path, err); + Ok(()) + }) + }) + .collect(); + libtest_mimic::run(&args, tests).exit() +} + +fn run_case(input: &[u8]) -> Result<(), String> { + let raw = std::str::from_utf8(input).map_err(|e| e.to_string())?; + let _ = raw.parse::<Document>().map_err(|e| e.to_string())?; + Ok(()) +} diff --git a/vendor/toml_edit/tests/testsuite/convert.rs b/vendor/toml_edit/tests/testsuite/convert.rs new file mode 100644 index 0000000..98f9397 --- /dev/null +++ b/vendor/toml_edit/tests/testsuite/convert.rs @@ -0,0 +1,79 @@ +use snapbox::assert_eq; + +use toml_edit::{Document, Item, Value}; + +#[test] +fn table_into_inline() { + let toml = r#" +[table] +string = "value" +array = [1, 2, 3] +inline = { "1" = 1, "2" = 2 } + +[table.child] +other = "world" +"#; + let mut doc = toml.parse::<Document>().unwrap(); + + doc.get_mut("table").unwrap().make_value(); + + let actual = doc.to_string(); + // `table=` is because we didn't re-format the table key, only the value + let expected = r#"table= { string = "value", array = [1, 2, 3], inline = { "1" = 1, "2" = 2 }, child = { other = "world" } } +"#; + assert_eq(expected, actual); +} + +#[test] +fn inline_table_to_table() { + let toml = r#"table = { string = "value", array = [1, 2, 3], inline = { "1" = 1, "2" = 2 }, child = { other = "world" } } +"#; + let mut doc = toml.parse::<Document>().unwrap(); + + let t = doc.remove("table").unwrap(); + let t = match t { + Item::Value(Value::InlineTable(t)) => t, + _ => unreachable!("Unexpected {:?}", t), + }; + let t = t.into_table(); + doc.insert("table", Item::Table(t)); + + let actual = doc.to_string(); + let expected = r#"[table] +string = "value" +array = [1, 2, 3] +inline = { "1" = 1, "2" = 2 } +child = { other = "world" } +"#; + assert_eq(expected, actual); +} + +#[test] +fn array_of_tables_to_array() { + let toml = r#" +[[table]] +string = "value" +array = [1, 2, 3] +inline = { "1" = 1, "2" = 2 } + +[table.child] +other = "world" + +[[table]] +string = "value" +array = [1, 2, 3] +inline = { "1" = 1, "2" = 2 } + +[table.child] +other = "world" +"#; + let mut doc = toml.parse::<Document>().unwrap(); + + doc.get_mut("table").unwrap().make_value(); + + let actual = doc.to_string(); + // `table=` is because we didn't re-format the table key, only the value + let expected = r#"table= [{ string = "value", array = [1, 2, 3], inline = { "1" = 1, "2" = 2 }, child = { other = "world" } }, { string = "value", array = [1, 2, 3], inline = { "1" = 1, "2" = 2 }, child = { other = "world" } }] +"#; + assert_eq(expected, actual); +} diff --git a/vendor/toml_edit/tests/testsuite/datetime.rs b/vendor/toml_edit/tests/testsuite/datetime.rs new file mode 100644 index 0000000..541f8ea --- /dev/null +++ b/vendor/toml_edit/tests/testsuite/datetime.rs @@ -0,0 +1,256 @@ +macro_rules! bad { + ($toml:expr, $msg:expr) => { + match $toml.parse::<toml_edit::Document>() { + Ok(s) => panic!("parsed to: {:#?}", s), + Err(e) => snapbox::assert_eq($msg, e.to_string()), + } + }; +} + +#[test] +fn times() { + fn dogood(s: &str, serialized: &str) { + let to_parse = format!("foo = {}", s); + let document = to_parse.parse::<toml_edit::Document>().unwrap(); + assert_eq!( + document["foo"].as_datetime().unwrap().to_string(), + serialized + ); + } + fn good(s: &str) { + dogood(s, s); + dogood(&s.replace('T', " "), s); + dogood(&s.replace('T', "t"), s); + dogood(&s.replace('Z', "z"), s); + } + + good("1997-09-09T09:09:09Z"); + good("1997-09-09T09:09:09+09:09"); + good("1997-09-09T09:09:09-09:09"); + good("1997-09-09T09:09:09"); + good("1997-09-09"); + dogood("1997-09-09 ", "1997-09-09"); + dogood("1997-09-09 # comment", "1997-09-09"); + good("09:09:09"); + good("1997-09-09T09:09:09.09Z"); + good("1997-09-09T09:09:09.09+09:09"); + good("1997-09-09T09:09:09.09-09:09"); + good("1997-09-09T09:09:09.09"); + good("09:09:09.09"); +} + +#[test] +fn bad_times() { + bad!( + "foo = 199-09-09", + "\ +TOML parse error at line 1, column 10 + | +1 | foo = 199-09-09 + | ^ +expected newline, `#` +" + ); + bad!( + "foo = 199709-09", + "\ +TOML parse error at line 1, column 13 + | +1 | foo = 199709-09 + | ^ +expected newline, `#` +" + ); + bad!( + "foo = 1997-9-09", + "\ +TOML parse error at line 1, column 12 + | +1 | foo = 1997-9-09 + | ^ +invalid date-time +" + ); + bad!( + "foo = 1997-09-9", + "\ +TOML parse error at line 1, column 15 + | +1 | foo = 1997-09-9 + | ^ +invalid date-time +" + ); + bad!( + "foo = 1997-09-0909:09:09", + "\ +TOML parse error at line 1, column 17 + | +1 | foo = 1997-09-0909:09:09 + | ^ +expected newline, `#` +" + ); + bad!( + "foo = 1997-09-09T09:09:09.", + "\ +TOML parse error at line 1, column 26 + | +1 | foo = 1997-09-09T09:09:09. + | ^ +expected newline, `#` +" + ); + bad!( + "foo = T", + r#"TOML parse error at line 1, column 7 + | +1 | foo = T + | ^ +invalid string +expected `"`, `'` +"# + ); + bad!( + "foo = T.", + r#"TOML parse error at line 1, column 7 + | +1 | foo = T. + | ^ +invalid string +expected `"`, `'` +"# + ); + bad!( + "foo = TZ", + r#"TOML parse error at line 1, column 7 + | +1 | foo = TZ + | ^ +invalid string +expected `"`, `'` +"# + ); + bad!( + "foo = 1997-09-09T09:09:09.09+", + r#"TOML parse error at line 1, column 30 + | +1 | foo = 1997-09-09T09:09:09.09+ + | ^ +invalid time offset +"# + ); + bad!( + "foo = 1997-09-09T09:09:09.09+09", + r#"TOML parse error at line 1, column 32 + | +1 | foo = 1997-09-09T09:09:09.09+09 + | ^ +invalid time offset +"# + ); + bad!( + "foo = 1997-09-09T09:09:09.09+09:9", + r#"TOML parse error at line 1, column 33 + | +1 | foo = 1997-09-09T09:09:09.09+09:9 + | ^ +invalid time offset +"# + ); + bad!( + "foo = 1997-09-09T09:09:09.09+0909", + r#"TOML parse error at line 1, column 32 + | +1 | foo = 1997-09-09T09:09:09.09+0909 + | ^ +invalid time offset +"# + ); + bad!( + "foo = 1997-09-09T09:09:09.09-", + r#"TOML parse error at line 1, column 30 + | +1 | foo = 1997-09-09T09:09:09.09- + | ^ +invalid time offset +"# + ); + bad!( + "foo = 1997-09-09T09:09:09.09-09", + r#"TOML parse error at line 1, column 32 + | +1 | foo = 1997-09-09T09:09:09.09-09 + | ^ +invalid time offset +"# + ); + bad!( + "foo = 1997-09-09T09:09:09.09-09:9", + r#"TOML parse error at line 1, column 33 + | +1 | foo = 1997-09-09T09:09:09.09-09:9 + | ^ +invalid time offset +"# + ); + bad!( + "foo = 1997-09-09T09:09:09.09-0909", + r#"TOML parse error at line 1, column 32 + | +1 | foo = 1997-09-09T09:09:09.09-0909 + | ^ +invalid time offset +"# + ); + + bad!( + "foo = 1997-00-09T09:09:09.09Z", + r#"TOML parse error at line 1, column 12 + | +1 | foo = 1997-00-09T09:09:09.09Z + | ^ +invalid date-time +value is out of range +"# + ); + bad!( + "foo = 1997-09-00T09:09:09.09Z", + r#"TOML parse error at line 1, column 15 + | +1 | foo = 1997-09-00T09:09:09.09Z + | ^ +invalid date-time +value is out of range +"# + ); + bad!( + "foo = 1997-09-09T30:09:09.09Z", + r#"TOML parse error at line 1, column 17 + | +1 | foo = 1997-09-09T30:09:09.09Z + | ^ +expected newline, `#` +"# + ); + bad!( + "foo = 1997-09-09T12:69:09.09Z", + r#"TOML parse error at line 1, column 21 + | +1 | foo = 1997-09-09T12:69:09.09Z + | ^ +invalid date-time +value is out of range +"# + ); + bad!( + "foo = 1997-09-09T12:09:69.09Z", + r#"TOML parse error at line 1, column 24 + | +1 | foo = 1997-09-09T12:09:69.09Z + | ^ +invalid date-time +value is out of range +"# + ); +} diff --git a/vendor/toml_edit/tests/testsuite/edit.rs b/vendor/toml_edit/tests/testsuite/edit.rs new file mode 100644 index 0000000..28f73c1 --- /dev/null +++ b/vendor/toml_edit/tests/testsuite/edit.rs @@ -0,0 +1,855 @@ +use std::fmt; +use std::iter::FromIterator; + +use snapbox::assert_eq; +use toml_edit::{array, table, value, Document, Item, Key, Table, Value}; + +macro_rules! parse_key { + ($s:expr) => {{ + let key = $s.parse::<Key>(); + assert!(key.is_ok()); + key.unwrap() + }}; +} + +macro_rules! as_table { + ($e:ident) => {{ + assert!($e.is_table()); + $e.as_table_mut().unwrap() + }}; +} + +// Copied from https://github.com/colin-kiegel/rust-pretty-assertions/issues/24 +/// Wrapper around string slice that makes debug output `{:?}` to print string same way as `{}`. +/// Used in different `assert*!` macros in combination with `pretty_assertions` crate to make +/// test failures to show nice diffs. +#[derive(PartialEq, Eq)] +struct PrettyString<'a>(pub &'a str); +/// Make diff to display string as multi-line string +impl<'a> fmt::Debug for PrettyString<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.0) + } +} + +struct Test { + doc: Document, +} + +fn given(input: &str) -> Test { + let doc = input.parse::<Document>(); + assert!(doc.is_ok()); + Test { doc: doc.unwrap() } +} + +impl Test { + fn running<F>(&mut self, func: F) -> &mut Self + where + F: Fn(&mut Table), + { + { + let root = self.doc.as_table_mut(); + func(root); + } + self + } + + #[track_caller] + fn produces_display(&self, expected: &str) -> &Self { + assert_eq(expected, self.doc.to_string()); + self + } +} + +// insertion + +#[test] +fn test_insert_leaf_table() { + given( + r#"[servers] + + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [other.table]"#, + ) + .running(|root| { + root["servers"]["beta"] = table(); + root["servers"]["beta"]["ip"] = value("10.0.0.2"); + root["servers"]["beta"]["dc"] = value("eqdc10"); + }) + .produces_display( + r#"[servers] + + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + +[servers.beta] +ip = "10.0.0.2" +dc = "eqdc10" + + [other.table] +"#, + ); +} + +#[test] +fn test_inserted_leaf_table_goes_after_last_sibling() { + given( + r#" + [package] + [dependencies] + [[example]] + [dependencies.opencl] + [dev-dependencies]"#, + ) + .running(|root| { + root["dependencies"]["newthing"] = table(); + }) + .produces_display( + r#" + [package] + [dependencies] + [[example]] + [dependencies.opencl] + +[dependencies.newthing] + [dev-dependencies] +"#, + ); +} + +#[test] +fn test_inserting_tables_from_different_parsed_docs() { + given("[a]") + .running(|root| { + let other = "[b]".parse::<Document>().unwrap(); + root["b"] = other["b"].clone(); + }) + .produces_display("[a]\n[b]\n"); +} +#[test] +fn test_insert_nonleaf_table() { + given( + r#" + [other.table]"#, + ) + .running(|root| { + root["servers"] = table(); + root["servers"]["alpha"] = table(); + root["servers"]["alpha"]["ip"] = value("10.0.0.1"); + root["servers"]["alpha"]["dc"] = value("eqdc10"); + }) + .produces_display( + r#" + [other.table] + +[servers] + +[servers.alpha] +ip = "10.0.0.1" +dc = "eqdc10" +"#, + ); +} + +#[test] +fn test_insert_array() { + given( + r#" + [package] + title = "withoutarray""#, + ) + .running(|root| { + root["bin"] = array(); + assert!(root["bin"].is_array_of_tables()); + let array = root["bin"].as_array_of_tables_mut().unwrap(); + { + let mut table = Table::new(); + table["hello"] = value("world"); + array.push(table); + } + array.push(Table::new()); + }) + .produces_display( + r#" + [package] + title = "withoutarray" + +[[bin]] +hello = "world" + +[[bin]] +"#, + ); +} + +#[test] +fn test_insert_values() { + given( + r#" + [tbl.son]"#, + ) + .running(|root| { + root["tbl"]["key1"] = value("value1"); + root["tbl"]["key2"] = value(42); + root["tbl"]["key3"] = value(8.1415926); + }) + .produces_display( + r#"[tbl] +key1 = "value1" +key2 = 42 +key3 = 8.1415926 + + [tbl.son] +"#, + ); +} + +// removal + +#[test] +fn test_remove_leaf_table() { + given( + r#" + [servers] + + # Indentation (tabs and/or spaces) is allowed but not required +[servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10""#, + ) + .running(|root| { + let servers = root.get_mut("servers").unwrap(); + let servers = as_table!(servers); + assert!(servers.remove("alpha").is_some()); + }) + .produces_display( + r#" + [servers] + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" +"#, + ); +} + +#[test] +fn test_remove_nonleaf_table() { + given( + r#" + title = "not relevant" + + # comment 1 + [a.b.c] # comment 1.1 + key1 = 1 # comment 1.2 + # comment 2 + [b] # comment 2.1 + key2 = 2 # comment 2.2 + + # comment 3 + [a] # comment 3.1 + key3 = 3 # comment 3.2 + [[a.'array']] + b = 1 + + [[a.b.c.trololololololo]] # ohohohohoho + c = 2 + key3 = 42 + + # comment on some other table + [some.other.table] + + + + + # comment 4 + [a.b] # comment 4.1 + key4 = 4 # comment 4.2 + key41 = 41 # comment 4.3 + + + "#, + ) + .running(|root| { + assert!(root.remove("a").is_some()); + }) + .produces_display( + r#" + title = "not relevant" + # comment 2 + [b] # comment 2.1 + key2 = 2 # comment 2.2 + + # comment on some other table + [some.other.table] + + + "#, + ); +} + +#[test] +fn test_remove_array_entry() { + given( + r#" + [package] + name = "hello" + version = "1.0.0" + + [[bin]] + name = "world" + path = "src/bin/world/main.rs" + + [dependencies] + nom = "4.0" # future is here + + [[bin]] + name = "delete me please" + path = "src/bin/dmp/main.rs""#, + ) + .running(|root| { + let dmp = root.get_mut("bin").unwrap(); + assert!(dmp.is_array_of_tables()); + let dmp = dmp.as_array_of_tables_mut().unwrap(); + assert_eq!(dmp.len(), 2); + dmp.remove(1); + assert_eq!(dmp.len(), 1); + }) + .produces_display( + r#" + [package] + name = "hello" + version = "1.0.0" + + [[bin]] + name = "world" + path = "src/bin/world/main.rs" + + [dependencies] + nom = "4.0" # future is here +"#, + ); +} + +#[test] +fn test_remove_array() { + given( + r#" + [package] + name = "hello" + version = "1.0.0" + + [[bin]] + name = "world" + path = "src/bin/world/main.rs" + + [dependencies] + nom = "4.0" # future is here + + [[bin]] + name = "delete me please" + path = "src/bin/dmp/main.rs""#, + ) + .running(|root| { + assert!(root.remove("bin").is_some()); + }) + .produces_display( + r#" + [package] + name = "hello" + version = "1.0.0" + + [dependencies] + nom = "4.0" # future is here +"#, + ); +} + +#[test] +fn test_remove_value() { + given( + r#" + name = "hello" + # delete this + version = "1.0.0" # please + documentation = "https://docs.rs/hello""#, + ) + .running(|root| { + let value = root.remove("version"); + assert!(value.is_some()); + let value = value.unwrap(); + assert!(value.is_value()); + let value = value.as_value().unwrap(); + assert!(value.is_str()); + let value = value.as_str().unwrap(); + assert_eq(value, "1.0.0"); + }) + .produces_display( + r#" + name = "hello" + documentation = "https://docs.rs/hello" +"#, + ); +} + +#[test] +fn test_remove_last_value_from_implicit() { + given( + r#" + [a] + b = 1"#, + ) + .running(|root| { + let a = root.get_mut("a").unwrap(); + assert!(a.is_table()); + let a = as_table!(a); + a.set_implicit(true); + let value = a.remove("b"); + assert!(value.is_some()); + let value = value.unwrap(); + assert!(value.is_value()); + let value = value.as_value().unwrap(); + assert_eq!(value.as_integer(), Some(1)); + }) + .produces_display(r#""#); +} + +// values + +#[test] +fn test_sort_values() { + given( + r#" + [a.z] + + [a] + # this comment is attached to b + b = 2 # as well as this + a = 1 + c = 3 + + [a.y]"#, + ) + .running(|root| { + let a = root.get_mut("a").unwrap(); + let a = as_table!(a); + a.sort_values(); + }) + .produces_display( + r#" + [a.z] + + [a] + a = 1 + # this comment is attached to b + b = 2 # as well as this + c = 3 + + [a.y] +"#, + ); +} + +#[test] +fn test_sort_values_by() { + given( + r#" + [a.z] + + [a] + # this comment is attached to b + b = 2 # as well as this + a = 1 + "c" = 3 + + [a.y]"#, + ) + .running(|root| { + let a = root.get_mut("a").unwrap(); + let a = as_table!(a); + // Sort by the representation, not the value. So "\"c\"" sorts before "a" because '"' sorts + // before 'a'. + a.sort_values_by(|k1, _, k2, _| k1.display_repr().cmp(&k2.display_repr())); + }) + .produces_display( + r#" + [a.z] + + [a] + "c" = 3 + a = 1 + # this comment is attached to b + b = 2 # as well as this + + [a.y] +"#, + ); +} + +#[test] +fn test_set_position() { + given( + r#" + [package] + [dependencies] + [dependencies.opencl] + [dev-dependencies]"#, + ) + .running(|root| { + for (header, table) in root.iter_mut() { + if header == "dependencies" { + let tab = as_table!(table); + tab.set_position(0); + let (_, segmented) = tab.iter_mut().next().unwrap(); + as_table!(segmented).set_position(5) + } + } + }) + .produces_display( + r#" [dependencies] + + [package] + [dev-dependencies] + [dependencies.opencl] +"#, + ); +} + +#[test] +fn test_multiple_zero_positions() { + given( + r#" + [package] + [dependencies] + [dependencies.opencl] + a="" + [dev-dependencies]"#, + ) + .running(|root| { + for (_, table) in root.iter_mut() { + as_table!(table).set_position(0) + } + }) + .produces_display( + r#" + [package] + [dependencies] + [dev-dependencies] + [dependencies.opencl] + a="" +"#, + ); +} + +#[test] +fn test_multiple_max_usize_positions() { + given( + r#" + [package] + [dependencies] + [dependencies.opencl] + a="" + [dev-dependencies]"#, + ) + .running(|root| { + for (_, table) in root.iter_mut() { + as_table!(table).set_position(usize::MAX) + } + }) + .produces_display( + r#" [dependencies.opencl] + a="" + + [package] + [dependencies] + [dev-dependencies] +"#, + ); +} + +macro_rules! as_array { + ($entry:ident) => {{ + assert!($entry.is_value()); + let a = $entry.as_value_mut().unwrap(); + assert!(a.is_array()); + a.as_array_mut().unwrap() + }}; +} + +#[test] +fn test_insert_replace_into_array() { + given( + r#" + a = [1,2,3] + b = []"#, + ) + .running(|root| { + { + let a = root.get_mut("a").unwrap(); + let a = as_array!(a); + assert_eq!(a.len(), 3); + assert!(a.get(2).is_some()); + a.push(4); + assert_eq!(a.len(), 4); + a.fmt(); + } + let b = root.get_mut("b").unwrap(); + let b = as_array!(b); + assert!(b.is_empty()); + b.push("hello"); + assert_eq!(b.len(), 1); + + b.push_formatted(Value::from("world").decorated("\n", "\n")); + b.push_formatted(Value::from("test").decorated("", "")); + + b.insert(1, "beep"); + b.insert_formatted(2, Value::from("boop").decorated(" ", " ")); + + // This should preserve formatting. + assert_eq!(b.replace(2, "zoink").as_str(), Some("boop")); + // This should replace formatting. + assert_eq!( + b.replace_formatted(4, Value::from("yikes").decorated(" ", "")) + .as_str(), + Some("test") + ); + dbg!(root); + }) + .produces_display( + r#" + a = [1, 2, 3, 4] + b = ["hello", "beep", "zoink" , +"world" +, "yikes"] +"#, + ); +} + +#[test] +fn test_remove_from_array() { + given( + r#" + a = [1, 2, 3, 4] + b = ["hello"]"#, + ) + .running(|root| { + { + let a = root.get_mut("a").unwrap(); + let a = as_array!(a); + assert_eq!(a.len(), 4); + assert!(a.remove(3).is_integer()); + assert_eq!(a.len(), 3); + } + let b = root.get_mut("b").unwrap(); + let b = as_array!(b); + assert_eq!(b.len(), 1); + assert!(b.remove(0).is_str()); + assert!(b.is_empty()); + }) + .produces_display( + r#" + a = [1, 2, 3] + b = [] +"#, + ); +} + +#[test] +fn test_format_array() { + given( + r#" + a = [ + 1, + "2", + 3.0, + ] + "#, + ) + .running(|root| { + for (_, v) in root.iter_mut() { + if let Item::Value(Value::Array(array)) = v { + array.fmt(); + } + } + }) + .produces_display( + r#" + a = [1, "2", 3.0] + "#, + ); +} + +macro_rules! as_inline_table { + ($entry:ident) => {{ + assert!($entry.is_value()); + let a = $entry.as_value_mut().unwrap(); + assert!(a.is_inline_table()); + a.as_inline_table_mut().unwrap() + }}; +} + +#[test] +fn test_insert_into_inline_table() { + given( + r#" + a = {a=2, c = 3} + b = {}"#, + ) + .running(|root| { + { + let a = root.get_mut("a").unwrap(); + let a = as_inline_table!(a); + assert_eq!(a.len(), 2); + assert!(a.contains_key("a") && a.get("c").is_some() && a.get_mut("c").is_some()); + a.get_or_insert("b", 42); + assert_eq!(a.len(), 3); + a.fmt(); + } + let b = root.get_mut("b").unwrap(); + let b = as_inline_table!(b); + assert!(b.is_empty()); + b.get_or_insert("hello", "world"); + assert_eq!(b.len(), 1); + b.fmt() + }) + .produces_display( + r#" + a = { a = 2, c = 3, b = 42 } + b = { hello = "world" } +"#, + ); +} + +#[test] +fn test_remove_from_inline_table() { + given( + r#" + a = {a=2, c = 3, b = 42} + b = {'hello' = "world"}"#, + ) + .running(|root| { + { + let a = root.get_mut("a").unwrap(); + let a = as_inline_table!(a); + assert_eq!(a.len(), 3); + assert!(a.remove("c").is_some()); + assert_eq!(a.len(), 2); + } + let b = root.get_mut("b").unwrap(); + let b = as_inline_table!(b); + assert_eq!(b.len(), 1); + assert!(b.remove("hello").is_some()); + assert!(b.is_empty()); + }) + .produces_display( + r#" + a = {a=2, b = 42} + b = {} +"#, + ); +} + +#[test] +fn test_as_table_like() { + given( + r#" + a = {a=2, c = 3, b = 42} + x = {} + [[bin]] + [b] + x = "y" + [empty]"#, + ) + .running(|root| { + let a = root["a"].as_table_like(); + assert!(a.is_some()); + let a = a.unwrap(); + assert_eq!(a.iter().count(), 3); + assert_eq!(a.len(), 3); + assert_eq!(a.get("a").and_then(Item::as_integer), Some(2)); + + let b = root["b"].as_table_like(); + assert!(b.is_some()); + let b = b.unwrap(); + assert_eq!(b.iter().count(), 1); + assert_eq!(b.len(), 1); + assert_eq!(b.get("x").and_then(Item::as_str), Some("y")); + + assert_eq!(root["x"].as_table_like().map(|t| t.iter().count()), Some(0)); + assert_eq!( + root["empty"].as_table_like().map(|t| t.is_empty()), + Some(true) + ); + + assert!(root["bin"].as_table_like().is_none()); + }); +} + +#[test] +fn test_inline_table_append() { + let mut a = Value::from_iter(vec![ + (parse_key!("a"), 1), + (parse_key!("b"), 2), + (parse_key!("c"), 3), + ]); + let a = a.as_inline_table_mut().unwrap(); + + let mut b = Value::from_iter(vec![ + (parse_key!("c"), 4), + (parse_key!("d"), 5), + (parse_key!("e"), 6), + ]); + let b = b.as_inline_table_mut().unwrap(); + + a.extend(b.iter()); + assert_eq!(a.len(), 5); + assert!(a.contains_key("e")); + assert_eq!(b.len(), 3); +} + +#[test] +fn test_insert_dotted_into_std_table() { + given("") + .running(|root| { + root["nixpkgs"] = table(); + + root["nixpkgs"]["src"] = table(); + root["nixpkgs"]["src"] + .as_table_like_mut() + .unwrap() + .set_dotted(true); + root["nixpkgs"]["src"]["git"] = value("https://github.com/nixos/nixpkgs"); + }) + .produces_display( + r#"[nixpkgs] +src.git = "https://github.com/nixos/nixpkgs" +"#, + ); +} + +#[test] +fn test_insert_dotted_into_implicit_table() { + given("") + .running(|root| { + root["nixpkgs"] = table(); + + root["nixpkgs"]["src"]["git"] = value("https://github.com/nixos/nixpkgs"); + root["nixpkgs"]["src"] + .as_table_like_mut() + .unwrap() + .set_dotted(true); + }) + .produces_display( + r#"[nixpkgs] +src.git = "https://github.com/nixos/nixpkgs" +"#, + ); +} diff --git a/vendor/toml_edit/tests/testsuite/invalid.rs b/vendor/toml_edit/tests/testsuite/invalid.rs new file mode 100644 index 0000000..cb13b4e --- /dev/null +++ b/vendor/toml_edit/tests/testsuite/invalid.rs @@ -0,0 +1,211 @@ +#[test] +fn incomplete_inline_table_issue_296() { + let err = "native = {".parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 1, column 11 + | +1 | native = { + | ^ +invalid inline table +expected `}` +"#, + err.to_string(), + ); +} + +#[test] +fn bare_value_disallowed_issue_293() { + let err = "value=zzz".parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 1, column 7 + | +1 | value=zzz + | ^ +invalid string +expected `"`, `'` +"#, + err.to_string(), + ); +} + +#[test] +fn bare_value_in_array_disallowed_issue_293() { + let err = "value=[zzz]".parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 1, column 8 + | +1 | value=[zzz] + | ^ +invalid array +expected `]` +"#, + err.to_string(), + ); +} + +#[test] +fn duplicate_table_after_dotted_key_issue_509() { + let err = " +[dependencies.foo] +version = \"0.16\" + +[dependencies] +libc = \"0.2\" + +[dependencies] +rand = \"0.3.14\" +" + .parse::<toml_edit::Document>() + .unwrap_err(); + snapbox::assert_eq( + r#"TOML parse error at line 8, column 1 + | +8 | [dependencies] + | ^ +invalid table header +duplicate key `dependencies` in document root +"#, + err.to_string(), + ); +} + +#[test] +fn bad() { + let toml_input = "a = 01"; + let expected_err = "\ +TOML parse error at line 1, column 6 + | +1 | a = 01 + | ^ +expected newline, `#` +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = 1__1"; + let expected_err = "\ +TOML parse error at line 1, column 7 + | +1 | a = 1__1 + | ^ +invalid integer +expected digit +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = 1_"; + let expected_err = "\ +TOML parse error at line 1, column 7 + | +1 | a = 1_ + | ^ +invalid integer +expected digit +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "''"; + let expected_err = "\ +TOML parse error at line 1, column 3 + | +1 | '' + | ^ +expected `.`, `=` +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = 9e99999"; + let expected_err = "\ +TOML parse error at line 1, column 5 + | +1 | a = 9e99999 + | ^ +invalid floating-point number +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = \"\u{7f}\""; + let expected_err = "\ +TOML parse error at line 1, column 6 + | +1 | a = \"\u{7f}\" + | ^ +invalid basic string +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = '\u{7f}'"; + let expected_err = "\ +TOML parse error at line 1, column 6 + | +1 | a = '\u{7f}' + | ^ +invalid literal string +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = -0x1"; + let expected_err = "\ +TOML parse error at line 1, column 7 + | +1 | a = -0x1 + | ^ +expected newline, `#` +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = 0x-1"; + let expected_err = "\ +TOML parse error at line 1, column 7 + | +1 | a = 0x-1 + | ^ +invalid hexadecimal integer +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + // Dotted keys. + let toml_input = "a.b.c = 1 + a.b = 2 + "; + let expected_err = "\ +TOML parse error at line 2, column 10 + | +2 | a.b = 2 + | ^ +duplicate key `b` in document root +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = 1 + a.b = 2"; + let expected_err = "\ +TOML parse error at line 2, column 10 + | +2 | a.b = 2 + | ^ +dotted key `a` attempted to extend non-table type (integer) +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); + + let toml_input = "a = {k1 = 1, k1.name = \"joe\"}"; + let expected_err = "\ +TOML parse error at line 1, column 6 + | +1 | a = {k1 = 1, k1.name = \"joe\"} + | ^ +dotted key `k1` attempted to extend non-table type (integer) +"; + let err = toml_input.parse::<toml_edit::Document>().unwrap_err(); + snapbox::assert_eq(expected_err, err.to_string()); +} diff --git a/vendor/toml_edit/tests/testsuite/main.rs b/vendor/toml_edit/tests/testsuite/main.rs new file mode 100644 index 0000000..1476c5d --- /dev/null +++ b/vendor/toml_edit/tests/testsuite/main.rs @@ -0,0 +1,8 @@ +#![recursion_limit = "256"] + +mod convert; +mod datetime; +mod edit; +mod invalid; +mod parse; +mod stackoverflow; diff --git a/vendor/toml_edit/tests/testsuite/parse.rs b/vendor/toml_edit/tests/testsuite/parse.rs new file mode 100644 index 0000000..f1c3c27 --- /dev/null +++ b/vendor/toml_edit/tests/testsuite/parse.rs @@ -0,0 +1,1490 @@ +use snapbox::assert_eq; +use toml_edit::{Document, Key, Value}; + +macro_rules! parse { + ($s:expr, $ty:ty) => {{ + let v = $s.parse::<$ty>(); + assert!(v.is_ok(), "Failed with {}", v.unwrap_err()); + v.unwrap() + }}; +} + +macro_rules! parse_value { + ($s:expr) => { + parse!($s, Value) + }; +} + +macro_rules! test_key { + ($s:expr, $expected:expr) => {{ + let key = parse!($s, Key); + assert_eq!($expected, key.get(), ""); + }}; +} + +#[test] +fn test_key_from_str() { + test_key!("a", "a"); + test_key!(r#"'hello key'"#, "hello key"); + test_key!( + r#""Jos\u00E9\U000A0000\n\t\r\f\b\"""#, + "Jos\u{00E9}\u{A0000}\n\t\r\u{c}\u{8}\"" + ); + test_key!("\"\"", ""); + test_key!("\"'hello key'bla\"", "'hello key'bla"); + test_key!( + "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\cargo-edit-test.YizxPxxElXn9'", + "C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\cargo-edit-test.YizxPxxElXn9" + ); +} + +#[test] +fn test_value_from_str() { + assert!(parse_value!("1979-05-27T00:32:00.999999-07:00").is_datetime()); + assert!(parse_value!("1979-05-27T00:32:00.999999Z").is_datetime()); + assert!(parse_value!("1979-05-27T00:32:00.999999").is_datetime()); + assert!(parse_value!("1979-05-27T00:32:00").is_datetime()); + assert!(parse_value!("1979-05-27").is_datetime()); + assert!(parse_value!("00:32:00").is_datetime()); + assert!(parse_value!("-239").is_integer()); + assert!(parse_value!("1e200").is_float()); + assert!(parse_value!("9_224_617.445_991_228_313").is_float()); + assert!(parse_value!(r#""basic string\nJos\u00E9\n""#).is_str()); + assert!(parse_value!( + r#"""" +multiline basic string +""""# + ) + .is_str()); + assert!(parse_value!(r#"'literal string\ \'"#).is_str()); + assert!(parse_value!( + r#"'''multiline +literal \ \ +string'''"# + ) + .is_str()); + assert!(parse_value!(r#"{ hello = "world", a = 1}"#).is_inline_table()); + assert!( + parse_value!(r#"[ { x = 1, a = "2" }, {a = "a",b = "b", c = "c"} ]"#).is_array() + ); + let wp = "C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\cargo-edit-test.YizxPxxElXn9"; + let lwp = "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\cargo-edit-test.YizxPxxElXn9'"; + assert_eq!(Value::from(wp).as_str(), parse_value!(lwp).as_str()); + assert!(parse_value!(r#""\\\"\b\f\n\r\t\u00E9\U000A0000""#).is_str()); +} + +#[test] +fn test_key_unification() { + let toml = r#" +[a] +[a.'b'.c] +[a."b".c.e] +[a.b.c.d] +"#; + let expected = r#" +[a] +[a.'b'.c] +[a.'b'.c.e] +[a.'b'.c.d] +"#; + let doc = toml.parse::<Document>(); + assert!(doc.is_ok()); + let doc = doc.unwrap(); + + assert_eq(expected, doc.to_string()); +} + +macro_rules! bad { + ($toml:expr, $msg:expr) => { + match $toml.parse::<Document>() { + Ok(s) => panic!("parsed to: {:#?}", s), + Err(e) => snapbox::assert_eq($msg, e.to_string()), + } + }; +} + +#[test] +fn crlf() { + "\ + [project]\r\n\ + \r\n\ + name = \"splay\"\r\n\ + version = \"0.1.0\"\r\n\ + authors = [\"alex@crichton.co\"]\r\n\ + \r\n\ + [[lib]]\r\n\ + \r\n\ + path = \"lib.rs\"\r\n\ + name = \"splay\"\r\n\ + description = \"\"\"\ + A Rust implementation of a TAR file reader and writer. This library does not\r\n\ + currently handle compression, but it is abstract over all I/O readers and\r\n\ + writers. Additionally, great lengths are taken to ensure that the entire\r\n\ + contents are never required to be entirely resident in memory all at once.\r\n\ + \"\"\"\ + " + .parse::<Document>() + .unwrap(); +} + +#[test] +fn fun_with_strings() { + let table = r#" +bar = "\U00000000" +key1 = "One\nTwo" +key2 = """One\nTwo""" +key3 = """ +One +Two""" + +key4 = "The quick brown fox jumps over the lazy dog." +key5 = """ +The quick brown \ + + +fox jumps over \ +the lazy dog.""" +key6 = """\ + The quick brown \ + fox jumps over \ + the lazy dog.\ + """ +# What you see is what you get. +winpath = 'C:\Users\nodejs\templates' +winpath2 = '\\ServerX\admin$\system32\' +quoted = 'Tom "Dubs" Preston-Werner' +regex = '<\i\c*\s*>' + +regex2 = '''I [dw]on't need \d{2} apples''' +lines = ''' +The first newline is +trimmed in raw strings. +All other whitespace +is preserved. +''' +"# + .parse::<Document>() + .unwrap(); + assert_eq!(table["bar"].as_str(), Some("\0")); + assert_eq!(table["key1"].as_str(), Some("One\nTwo")); + assert_eq!(table["key2"].as_str(), Some("One\nTwo")); + assert_eq!(table["key3"].as_str(), Some("One\nTwo")); + + let msg = "The quick brown fox jumps over the lazy dog."; + assert_eq!(table["key4"].as_str(), Some(msg)); + assert_eq!(table["key5"].as_str(), Some(msg)); + assert_eq!(table["key6"].as_str(), Some(msg)); + + assert_eq!( + table["winpath"].as_str(), + Some(r"C:\Users\nodejs\templates") + ); + assert_eq!( + table["winpath2"].as_str(), + Some(r"\\ServerX\admin$\system32\") + ); + assert_eq!( + table["quoted"].as_str(), + Some(r#"Tom "Dubs" Preston-Werner"#) + ); + assert_eq!(table["regex"].as_str(), Some(r"<\i\c*\s*>")); + assert_eq!( + table["regex2"].as_str(), + Some(r"I [dw]on't need \d{2} apples") + ); + assert_eq!( + table["lines"].as_str(), + Some( + "The first newline is\n\ + trimmed in raw strings.\n\ + All other whitespace\n\ + is preserved.\n" + ) + ); +} + +#[test] +fn tables_in_arrays() { + let table = r#" +[[foo]] +#… +[foo.bar] +#… + +[[foo]] # ... +#… +[foo.bar] +#... +"# + .parse::<Document>() + .unwrap(); + table["foo"][0]["bar"].as_table().unwrap(); + table["foo"][1]["bar"].as_table().unwrap(); +} + +#[test] +fn empty_table() { + let table = r#" +[foo]"# + .parse::<Document>() + .unwrap(); + table["foo"].as_table().unwrap(); +} + +#[test] +fn mixed_table_issue_527() { + let input = r#" +[package] +metadata.msrv = "1.65.0" + +[package.metadata.release.pre-release-replacements] +"#; + let document = input.parse::<Document>().unwrap(); + let actual = document.to_string(); + assert_eq(input, actual); +} + +#[test] +fn fruit() { + let table = r#" +[[fruit]] +name = "apple" + +[fruit.physical] +color = "red" +shape = "round" + +[[fruit.variety]] +name = "red delicious" + +[[fruit.variety]] +name = "granny smith" + +[[fruit]] +name = "banana" + +[[fruit.variety]] +name = "plantain" +"# + .parse::<Document>() + .unwrap(); + assert_eq!(table["fruit"][0]["name"].as_str(), Some("apple")); + assert_eq!(table["fruit"][0]["physical"]["color"].as_str(), Some("red")); + assert_eq!( + table["fruit"][0]["physical"]["shape"].as_str(), + Some("round") + ); + assert_eq!( + table["fruit"][0]["variety"][0]["name"].as_str(), + Some("red delicious") + ); + assert_eq!( + table["fruit"][0]["variety"][1]["name"].as_str(), + Some("granny smith") + ); + assert_eq!(table["fruit"][1]["name"].as_str(), Some("banana")); + assert_eq!( + table["fruit"][1]["variety"][0]["name"].as_str(), + Some("plantain") + ); +} + +#[test] +fn stray_cr() { + bad!( + "\r", + "\ +TOML parse error at line 1, column 1 + | +1 | \r + | ^ + +" + ); + bad!( + "a = [ \r ]", + "\ +TOML parse error at line 1, column 7 + | +1 | a = [ \r + ] + | ^ +invalid array +expected `]` +" + ); + bad!( + "a = \"\"\"\r\"\"\"", + "\ +TOML parse error at line 1, column 8 + | +1 | a = \"\"\"\r +\"\"\" + | ^ +invalid multiline basic string +" + ); + bad!( + "a = \"\"\"\\ \r \"\"\"", + "\ +TOML parse error at line 1, column 10 + | +1 | a = \"\"\"\\ \r + \"\"\" + | ^ +invalid escape sequence +expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\\`, `\"` +" + ); + bad!( + "a = '''\r'''", + "\ +TOML parse error at line 1, column 8 + | +1 | a = '''\r +''' + | ^ +invalid multiline literal string +" + ); + bad!( + "a = '\r'", + "\ +TOML parse error at line 1, column 6 + | +1 | a = '\r +' + | ^ +invalid literal string +" + ); + bad!( + "a = \"\r\"", + "\ +TOML parse error at line 1, column 6 + | +1 | a = \"\r +\" + | ^ +invalid basic string +" + ); +} + +#[test] +fn blank_literal_string() { + let table = "foo = ''".parse::<Document>().unwrap(); + assert_eq!(table["foo"].as_str(), Some("")); +} + +#[test] +fn many_blank() { + let table = "foo = \"\"\"\n\n\n\"\"\"".parse::<Document>().unwrap(); + assert_eq!(table["foo"].as_str(), Some("\n\n")); +} + +#[test] +fn literal_eats_crlf() { + let table = " + foo = \"\"\"\\\r\n\"\"\" + bar = \"\"\"\\\r\n \r\n \r\n a\"\"\" + " + .parse::<Document>() + .unwrap(); + assert_eq!(table["foo"].as_str(), Some("")); + assert_eq!(table["bar"].as_str(), Some("a")); +} + +#[test] +fn string_no_newline() { + bad!( + "a = \"\n\"", + "\ +TOML parse error at line 1, column 6 + | +1 | a = \" + | ^ +invalid basic string +" + ); + bad!( + "a = '\n'", + "\ +TOML parse error at line 1, column 6 + | +1 | a = ' + | ^ +invalid literal string +" + ); +} + +#[test] +fn bad_leading_zeros() { + bad!( + "a = 00", + "\ +TOML parse error at line 1, column 6 + | +1 | a = 00 + | ^ +expected newline, `#` +" + ); + bad!( + "a = -00", + "\ +TOML parse error at line 1, column 7 + | +1 | a = -00 + | ^ +expected newline, `#` +" + ); + bad!( + "a = +00", + "\ +TOML parse error at line 1, column 7 + | +1 | a = +00 + | ^ +expected newline, `#` +" + ); + bad!( + "a = 00.0", + "\ +TOML parse error at line 1, column 6 + | +1 | a = 00.0 + | ^ +expected newline, `#` +" + ); + bad!( + "a = -00.0", + "\ +TOML parse error at line 1, column 7 + | +1 | a = -00.0 + | ^ +expected newline, `#` +" + ); + bad!( + "a = +00.0", + "\ +TOML parse error at line 1, column 7 + | +1 | a = +00.0 + | ^ +expected newline, `#` +" + ); + bad!( + "a = 9223372036854775808", + "\ +TOML parse error at line 1, column 5 + | +1 | a = 9223372036854775808 + | ^ +number too large to fit in target type +" + ); + bad!( + "a = -9223372036854775809", + "\ +TOML parse error at line 1, column 5 + | +1 | a = -9223372036854775809 + | ^ +number too small to fit in target type +" + ); +} + +#[test] +fn bad_floats() { + bad!( + "a = 0.", + "\ +TOML parse error at line 1, column 7 + | +1 | a = 0. + | ^ +invalid floating-point number +expected digit +" + ); + bad!( + "a = 0.e", + "\ +TOML parse error at line 1, column 7 + | +1 | a = 0.e + | ^ +invalid floating-point number +expected digit +" + ); + bad!( + "a = 0.E", + "\ +TOML parse error at line 1, column 7 + | +1 | a = 0.E + | ^ +invalid floating-point number +expected digit +" + ); + bad!( + "a = 0.0E", + "\ +TOML parse error at line 1, column 9 + | +1 | a = 0.0E + | ^ +invalid floating-point number +" + ); + bad!( + "a = 0.0e", + "\ +TOML parse error at line 1, column 9 + | +1 | a = 0.0e + | ^ +invalid floating-point number +" + ); + bad!( + "a = 0.0e-", + "\ +TOML parse error at line 1, column 10 + | +1 | a = 0.0e- + | ^ +invalid floating-point number +" + ); + bad!( + "a = 0.0e+", + "\ +TOML parse error at line 1, column 10 + | +1 | a = 0.0e+ + | ^ +invalid floating-point number +" + ); +} + +#[test] +fn floats() { + macro_rules! t { + ($actual:expr, $expected:expr) => {{ + let f = format!("foo = {}", $actual); + println!("{}", f); + let a = f.parse::<Document>().unwrap(); + assert_eq!(a["foo"].as_float().unwrap(), $expected); + }}; + } + + t!("1.0", 1.0); + t!("1.0e0", 1.0); + t!("1.0e+0", 1.0); + t!("1.0e-0", 1.0); + t!("1E-0", 1.0); + t!("1.001e-0", 1.001); + t!("2e10", 2e10); + t!("2e+10", 2e10); + t!("2e-10", 2e-10); + t!("2_0.0", 20.0); + t!("2_0.0_0e1_0", 20.0e10); + t!("2_0.1_0e1_0", 20.1e10); +} + +#[test] +fn bare_key_names() { + let a = " + foo = 3 + foo_3 = 3 + foo_-2--3--r23f--4-f2-4 = 3 + _ = 3 + - = 3 + 8 = 8 + \"a\" = 3 + \"!\" = 3 + \"a^b\" = 3 + \"\\\"\" = 3 + \"character encoding\" = \"value\" + 'ʎǝʞ' = \"value\" + " + .parse::<Document>() + .unwrap(); + let _ = &a["foo"]; + let _ = &a["-"]; + let _ = &a["_"]; + let _ = &a["8"]; + let _ = &a["foo_3"]; + let _ = &a["foo_-2--3--r23f--4-f2-4"]; + let _ = &a["a"]; + let _ = &a["!"]; + let _ = &a["\""]; + let _ = &a["character encoding"]; + let _ = &a["ʎǝʞ"]; +} + +#[test] +fn bad_keys() { + bad!( + "key\n=3", + "\ +TOML parse error at line 1, column 4 + | +1 | key + | ^ +expected `.`, `=` +" + ); + bad!( + "key=\n3", + "\ +TOML parse error at line 1, column 5 + | +1 | key= + | ^ +invalid string +expected `\"`, `'` +" + ); + bad!( + "key|=3", + "\ +TOML parse error at line 1, column 4 + | +1 | key|=3 + | ^ +expected `.`, `=` +" + ); + bad!( + "=3", + "\ +TOML parse error at line 1, column 1 + | +1 | =3 + | ^ +invalid key +" + ); + bad!( + "\"\"|=3", + "\ +TOML parse error at line 1, column 3 + | +1 | \"\"|=3 + | ^ +expected `.`, `=` +" + ); + bad!( + "\"\n\"|=3", + "\ +TOML parse error at line 1, column 2 + | +1 | \" + | ^ +invalid basic string +" + ); + bad!( + "\"\r\"|=3", + "\ +TOML parse error at line 1, column 2 + | +1 | \"\r\"|=3 + | ^ +invalid basic string +" + ); + bad!( + "''''''=3", + "\ +TOML parse error at line 1, column 3 + | +1 | ''''''=3 + | ^ +expected `.`, `=` +" + ); + bad!( + "\"\"\"\"\"\"=3", + "\ +TOML parse error at line 1, column 3 + | +1 | \"\"\"\"\"\"=3 + | ^ +expected `.`, `=` +" + ); + bad!( + "'''key'''=3", + "\ +TOML parse error at line 1, column 3 + | +1 | '''key'''=3 + | ^ +expected `.`, `=` +" + ); + bad!( + "\"\"\"key\"\"\"=3", + "\ +TOML parse error at line 1, column 3 + | +1 | \"\"\"key\"\"\"=3 + | ^ +expected `.`, `=` +" + ); +} + +#[test] +fn bad_table_names() { + bad!( + "[]", + "\ +TOML parse error at line 1, column 2 + | +1 | [] + | ^ +invalid key +" + ); + bad!( + "[.]", + "\ +TOML parse error at line 1, column 2 + | +1 | [.] + | ^ +invalid key +" + ); + bad!( + "[a.]", + "\ +TOML parse error at line 1, column 3 + | +1 | [a.] + | ^ +invalid table header +expected `.`, `]` +" + ); + bad!( + "[!]", + "\ +TOML parse error at line 1, column 2 + | +1 | [!] + | ^ +invalid key +" + ); + bad!( + "[\"\n\"]", + "\ +TOML parse error at line 1, column 3 + | +1 | [\" + | ^ +invalid basic string +" + ); + bad!( + "[a.b]\n[a.\"b\"]", + "\ +TOML parse error at line 2, column 1 + | +2 | [a.\"b\"] + | ^ +invalid table header +duplicate key `b` in table `a` +" + ); + bad!( + "[']", + "\ +TOML parse error at line 1, column 4 + | +1 | ['] + | ^ +invalid literal string +" + ); + bad!( + "[''']", + "\ +TOML parse error at line 1, column 4 + | +1 | ['''] + | ^ +invalid table header +expected `.`, `]` +" + ); + bad!( + "['''''']", + "\ +TOML parse error at line 1, column 4 + | +1 | [''''''] + | ^ +invalid table header +expected `.`, `]` +" + ); + bad!( + "['''foo''']", + "\ +TOML parse error at line 1, column 4 + | +1 | ['''foo'''] + | ^ +invalid table header +expected `.`, `]` +" + ); + bad!( + "[\"\"\"bar\"\"\"]", + "\ +TOML parse error at line 1, column 4 + | +1 | [\"\"\"bar\"\"\"] + | ^ +invalid table header +expected `.`, `]` +" + ); + bad!( + "['\n']", + "\ +TOML parse error at line 1, column 3 + | +1 | [' + | ^ +invalid literal string +" + ); + bad!( + "['\r\n']", + "\ +TOML parse error at line 1, column 3 + | +1 | [' + | ^ +invalid literal string +" + ); +} + +#[test] +fn table_names() { + let a = " + [a.\"b\"] + [\"f f\"] + [\"f.f\"] + [\"\\\"\"] + ['a.a'] + ['\"\"'] + " + .parse::<Document>() + .unwrap(); + println!("{:?}", a); + let _ = &a["a"]["b"]; + let _ = &a["f f"]; + let _ = &a["f.f"]; + let _ = &a["\""]; + let _ = &a["\"\""]; +} + +#[test] +fn invalid_bare_numeral() { + bad!( + "4", + "\ +TOML parse error at line 1, column 2 + | +1 | 4 + | ^ +expected `.`, `=` +" + ); +} + +#[test] +fn inline_tables() { + "a = {}".parse::<Document>().unwrap(); + "a = {b=1}".parse::<Document>().unwrap(); + "a = { b = 1 }".parse::<Document>().unwrap(); + "a = {a=1,b=2}".parse::<Document>().unwrap(); + "a = {a=1,b=2,c={}}".parse::<Document>().unwrap(); + + bad!( + "a = {a=1,}", + "\ +TOML parse error at line 1, column 9 + | +1 | a = {a=1,} + | ^ +invalid inline table +expected `}` +" + ); + bad!( + "a = {,}", + "\ +TOML parse error at line 1, column 6 + | +1 | a = {,} + | ^ +invalid inline table +expected `}` +" + ); + bad!( + "a = {a=1,a=1}", + "\ +TOML parse error at line 1, column 6 + | +1 | a = {a=1,a=1} + | ^ +duplicate key `a` +" + ); + bad!( + "a = {\n}", + "\ +TOML parse error at line 1, column 6 + | +1 | a = { + | ^ +invalid inline table +expected `}` +" + ); + bad!( + "a = {", + "\ +TOML parse error at line 1, column 6 + | +1 | a = { + | ^ +invalid inline table +expected `}` +" + ); + + "a = {a=[\n]}".parse::<Document>().unwrap(); + "a = {\"a\"=[\n]}".parse::<Document>().unwrap(); + "a = [\n{},\n{},\n]".parse::<Document>().unwrap(); +} + +#[test] +fn number_underscores() { + macro_rules! t { + ($actual:expr, $expected:expr) => {{ + let f = format!("foo = {}", $actual); + let table = f.parse::<Document>().unwrap(); + assert_eq!(table["foo"].as_integer().unwrap(), $expected); + }}; + } + + t!("1_0", 10); + t!("1_0_0", 100); + t!("1_000", 1000); + t!("+1_000", 1000); + t!("-1_000", -1000); +} + +#[test] +fn bad_underscores() { + bad!( + "foo = 0_", + "\ +TOML parse error at line 1, column 8 + | +1 | foo = 0_ + | ^ +expected newline, `#` +" + ); + bad!( + "foo = 0__0", + "\ +TOML parse error at line 1, column 8 + | +1 | foo = 0__0 + | ^ +expected newline, `#` +" + ); + bad!( + "foo = __0", + "\ +TOML parse error at line 1, column 7 + | +1 | foo = __0 + | ^ +invalid integer +expected leading digit +" + ); + bad!( + "foo = 1_0_", + "\ +TOML parse error at line 1, column 11 + | +1 | foo = 1_0_ + | ^ +invalid integer +expected digit +" + ); +} + +#[test] +fn bad_unicode_codepoint() { + bad!( + "foo = \"\\uD800\"", + "\ +TOML parse error at line 1, column 10 + | +1 | foo = \"\\uD800\" + | ^ +invalid unicode 4-digit hex code +value is out of range +" + ); +} + +#[test] +fn bad_strings() { + bad!( + "foo = \"\\uxx\"", + "\ +TOML parse error at line 1, column 10 + | +1 | foo = \"\\uxx\" + | ^ +invalid unicode 4-digit hex code +" + ); + bad!( + "foo = \"\\u\"", + "\ +TOML parse error at line 1, column 10 + | +1 | foo = \"\\u\" + | ^ +invalid unicode 4-digit hex code +" + ); + bad!( + "foo = \"\\", + "\ +TOML parse error at line 1, column 8 + | +1 | foo = \"\\ + | ^ +invalid basic string +" + ); + bad!( + "foo = '", + "\ +TOML parse error at line 1, column 8 + | +1 | foo = ' + | ^ +invalid literal string +" + ); +} + +#[test] +fn empty_string() { + assert_eq!( + "foo = \"\"".parse::<Document>().unwrap()["foo"] + .as_str() + .unwrap(), + "" + ); +} + +#[test] +fn booleans() { + let table = "foo = true".parse::<Document>().unwrap(); + assert_eq!(table["foo"].as_bool(), Some(true)); + + let table = "foo = false".parse::<Document>().unwrap(); + assert_eq!(table["foo"].as_bool(), Some(false)); + + bad!( + "foo = true2", + "\ +TOML parse error at line 1, column 11 + | +1 | foo = true2 + | ^ +expected newline, `#` +" + ); + bad!( + "foo = false2", + "\ +TOML parse error at line 1, column 12 + | +1 | foo = false2 + | ^ +expected newline, `#` +" + ); + bad!( + "foo = t1", + "\ +TOML parse error at line 1, column 7 + | +1 | foo = t1 + | ^ +invalid string +expected `\"`, `'` +" + ); + bad!( + "foo = f2", + "\ +TOML parse error at line 1, column 7 + | +1 | foo = f2 + | ^ +invalid string +expected `\"`, `'` +" + ); +} + +#[test] +fn bad_nesting() { + bad!( + " + a = [2] + [[a]] + b = 5 + ", + "\ +TOML parse error at line 3, column 9 + | +3 | [[a]] + | ^ +invalid table header +duplicate key `a` in document root +" + ); + bad!( + " + a = 1 + [a.b] + ", + "\ +TOML parse error at line 3, column 9 + | +3 | [a.b] + | ^ +invalid table header +dotted key `a` attempted to extend non-table type (integer) +" + ); + bad!( + " + a = [] + [a.b] + ", + "\ +TOML parse error at line 3, column 9 + | +3 | [a.b] + | ^ +invalid table header +dotted key `a` attempted to extend non-table type (array) +" + ); + bad!( + " + a = [] + [[a.b]] + ", + "\ +TOML parse error at line 3, column 9 + | +3 | [[a.b]] + | ^ +invalid table header +dotted key `a` attempted to extend non-table type (array) +" + ); + bad!( + " + [a] + b = { c = 2, d = {} } + [a.b] + c = 2 + ", + "\ +TOML parse error at line 4, column 9 + | +4 | [a.b] + | ^ +invalid table header +duplicate key `b` in table `a` +" + ); +} + +#[test] +fn bad_table_redefine() { + bad!( + " + [a] + foo=\"bar\" + [a.b] + foo=\"bar\" + [a] + ", + "\ +TOML parse error at line 6, column 9 + | +6 | [a] + | ^ +invalid table header +duplicate key `a` in document root +" + ); + bad!( + " + [a] + foo=\"bar\" + b = { foo = \"bar\" } + [a] + ", + "\ +TOML parse error at line 5, column 9 + | +5 | [a] + | ^ +invalid table header +duplicate key `a` in document root +" + ); + bad!( + " + [a] + b = {} + [a.b] + ", + "\ +TOML parse error at line 4, column 9 + | +4 | [a.b] + | ^ +invalid table header +duplicate key `b` in table `a` +" + ); + + bad!( + " + [a] + b = {} + [a] + ", + "\ +TOML parse error at line 4, column 9 + | +4 | [a] + | ^ +invalid table header +duplicate key `a` in document root +" + ); +} + +#[test] +fn datetimes() { + macro_rules! t { + ($actual:expr) => {{ + let f = format!("foo = {}", $actual); + let toml = f.parse::<Document>().expect(&format!("failed: {}", f)); + assert_eq!(toml["foo"].as_datetime().unwrap().to_string(), $actual); + }}; + } + + t!("2016-09-09T09:09:09Z"); + t!("2016-09-09T09:09:09.1Z"); + t!("2016-09-09T09:09:09.2+10:00"); + t!("2016-09-09T09:09:09.123456789-02:00"); + bad!( + "foo = 2016-09-09T09:09:09.Z", + "\ +TOML parse error at line 1, column 26 + | +1 | foo = 2016-09-09T09:09:09.Z + | ^ +expected newline, `#` +" + ); + bad!( + "foo = 2016-9-09T09:09:09Z", + "\ +TOML parse error at line 1, column 12 + | +1 | foo = 2016-9-09T09:09:09Z + | ^ +invalid date-time +" + ); + bad!( + "foo = 2016-09-09T09:09:09+2:00", + "\ +TOML parse error at line 1, column 27 + | +1 | foo = 2016-09-09T09:09:09+2:00 + | ^ +invalid time offset +" + ); + bad!( + "foo = 2016-09-09T09:09:09-2:00", + "\ +TOML parse error at line 1, column 27 + | +1 | foo = 2016-09-09T09:09:09-2:00 + | ^ +invalid time offset +" + ); + bad!( + "foo = 2016-09-09T09:09:09Z-2:00", + "\ +TOML parse error at line 1, column 27 + | +1 | foo = 2016-09-09T09:09:09Z-2:00 + | ^ +expected newline, `#` +" + ); +} + +#[test] +fn require_newline_after_value() { + bad!( + "0=0r=false", + "\ +TOML parse error at line 1, column 4 + | +1 | 0=0r=false + | ^ +expected newline, `#` +" + ); + bad!( + r#" +0=""o=""m=""r=""00="0"q="""0"""e="""0""" +"#, + r#"TOML parse error at line 2, column 5 + | +2 | 0=""o=""m=""r=""00="0"q="""0"""e="""0""" + | ^ +expected newline, `#` +"# + ); + bad!( + r#" +[[0000l0]] +0="0"[[0000l0]] +0="0"[[0000l0]] +0="0"l="0" +"#, + r#"TOML parse error at line 3, column 6 + | +3 | 0="0"[[0000l0]] + | ^ +expected newline, `#` +"# + ); + bad!( + r#" +0=[0]00=[0,0,0]t=["0","0","0"]s=[1000-00-00T00:00:00Z,2000-00-00T00:00:00Z] +"#, + r#"TOML parse error at line 2, column 6 + | +2 | 0=[0]00=[0,0,0]t=["0","0","0"]s=[1000-00-00T00:00:00Z,2000-00-00T00:00:00Z] + | ^ +expected newline, `#` +"# + ); + bad!( + r#" +0=0r0=0r=false +"#, + r#"TOML parse error at line 2, column 4 + | +2 | 0=0r0=0r=false + | ^ +expected newline, `#` +"# + ); + bad!( + r#" +0=0r0=0r=falsefal=false +"#, + r#"TOML parse error at line 2, column 4 + | +2 | 0=0r0=0r=falsefal=false + | ^ +expected newline, `#` +"# + ); +} + +#[test] +fn dont_use_dotted_key_prefix_on_table_fuzz_57049() { + // This could generate + // ```toml + // [ + // p.o] + // ``` + let input = r#" +p.a=4 +[p.o] +"#; + let document = input.parse::<Document>().unwrap(); + let actual = document.to_string(); + assert_eq(input, actual); +} + +#[test] +fn despan_keys() { + let mut doc = r#"aaaaaa = 1"#.parse::<Document>().unwrap(); + let key = "bbb".parse::<Key>().unwrap(); + let table = doc.as_table_mut(); + table.insert_formatted( + &key, + toml_edit::Item::Value(Value::Integer(toml_edit::Formatted::new(2))), + ); + + assert_eq!(doc.to_string(), "aaaaaa = 1\nbbb = 2\n"); +} diff --git a/vendor/toml_edit/tests/testsuite/stackoverflow.rs b/vendor/toml_edit/tests/testsuite/stackoverflow.rs new file mode 100644 index 0000000..de4c722 --- /dev/null +++ b/vendor/toml_edit/tests/testsuite/stackoverflow.rs @@ -0,0 +1,54 @@ +#[test] +#[cfg(not(feature = "unbounded"))] +fn array_recursion_limit() { + let depths = [(1, true), (20, true), (300, false)]; + for (depth, is_ok) in depths { + let input = format!("x={}{}", &"[".repeat(depth), &"]".repeat(depth)); + let document = input.parse::<toml_edit::Document>(); + assert_eq!(document.is_ok(), is_ok, "depth: {}", depth); + } +} + +#[test] +#[cfg(not(feature = "unbounded"))] +fn inline_table_recursion_limit() { + let depths = [(1, true), (20, true), (300, false)]; + for (depth, is_ok) in depths { + let input = format!("x={}true{}", &"{ x = ".repeat(depth), &"}".repeat(depth)); + let document = input.parse::<toml_edit::Document>(); + assert_eq!(document.is_ok(), is_ok, "depth: {}", depth); + } +} + +#[test] +#[cfg(not(feature = "unbounded"))] +fn table_key_recursion_limit() { + let depths = [(1, true), (20, true), (300, false)]; + for (depth, is_ok) in depths { + let input = format!("[x{}]", &".x".repeat(depth)); + let document = input.parse::<toml_edit::Document>(); + assert_eq!(document.is_ok(), is_ok, "depth: {}", depth); + } +} + +#[test] +#[cfg(not(feature = "unbounded"))] +fn dotted_key_recursion_limit() { + let depths = [(1, true), (20, true), (300, false)]; + for (depth, is_ok) in depths { + let input = format!("x{} = true", &".x".repeat(depth)); + let document = input.parse::<toml_edit::Document>(); + assert_eq!(document.is_ok(), is_ok, "depth: {}", depth); + } +} + +#[test] +#[cfg(not(feature = "unbounded"))] +fn inline_dotted_key_recursion_limit() { + let depths = [(1, true), (20, true), (300, false)]; + for (depth, is_ok) in depths { + let input = format!("x = {{ x{} = true }}", &".x".repeat(depth)); + let document = input.parse::<toml_edit::Document>(); + assert_eq!(document.is_ok(), is_ok, "depth: {}", depth); + } +} |