feat: add display UI with splash screen, dashboard, and RSSI sparkline
Implement full SSD1306 OLED display support: - Splash screen on boot (1.5s) with project name, version, board - Dashboard showing radio state, config, counters, RSSI/SNR - RSSI history sparkline (64-sample ring buffer, 2px-wide bars) - DisplayOn/DisplayOff host commands routed via dedicated channel - Pure render functions against generic DrawTarget (no hardware coupling) - Display on/off control bypasses radio task entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
17624 files changed
+4564928
-38
No files matched your search
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"files":{".cargo_vcs_info.json":"7133ba2e14ed875f5ca8d5e87b752b7a2b0a7fb3fa829013e45d8480f7635396","Cargo.lock":"241f90fc76d66fc00bf9f67c05507fd9102418344ed16ec8574e936c4b808b21","Cargo.toml":"32140fa952977c75b638e7560d33700ef9fa8ecda48323fdb1ca35ac65f0d05b","Cargo.toml.orig":"b833edcf3cc83ba68ed65863f3676a5c22e290dff98efc30c1aeb7d22b01972f","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"6efb0476a1cc085077ed49357026d8c173bf33017278ef440f222fb9cbcb66e6","README.md":"ff5ec0cab6f854264c291930b14e6f39072d241985969fc30bbc62a9999a61a7","examples/decode.rs":"5742451499c0cbe481aa90c116cc219db12b3ca5b3734a4d19b558958d97501d","examples/enum_external.rs":"3875b625e537459e3fc161eeb7b204e16282331efc0fc4a0837fe9c50646b9a5","examples/toml2json.rs":"6472dbff3bd8809aa1e66598e03a8068d997bc8afd09531c6d9da10fecacaf7e","src/de.rs":"24cebb489ef6470d12f642b7fc92c0a015afa70bda8ae01b9508c8511844fc82","src/edit.rs":"596f5695a711ed4f3ea715c043ac6e2dd0c35c532c0488ef002fce0992e67fe2","src/fmt.rs":"b6b14bcfaaf6a283d0bdc7b43d9d13c127cf94c9de41efb4a3a9e1eb02bdc799","src/lib.rs":"3a40e7f8f5684b0f9016a6cd3da675df08d84dc5494fb3a38684b3e4d44ecda8","src/macros.rs":"a7214ed97b1c15391748a3d5b904b31963130ee19ecd6ed3dc705649737f3b29","src/map.rs":"6ea7d38a26462fc8edb3d5dd9eb4f0eba6cb52dacaa33fdc3025649b3e0f2bb0","src/ser/array.rs":"44f3184b2e7c1d069f546c25a56005983a3c424328a8b131c8bd40916480dd69","src/ser/map.rs":"6b3dd67b3d5c89f04cff3a00d6dc03451897d7398abbea3d5e0ee09279f53db4","src/ser/mod.rs":"cbb8bb08488b769b8068022f9689ca01305b000e9de69adf48e473adcba3ed98","src/ser/ser_value/array.rs":"9d200eaf70f2e27f065ecbe659e03fc8b68f5b00c13269345e14b0062d705ce3","src/ser/ser_value/map.rs":"5cb3f260a52c9fcde5cb78b95de617935a739198e2f0065270e5a002a41a1255","src/ser/ser_value/mod.rs":"35fdd6a50f7cfa83724a8df261429b1e0308642fd578598e4b200b9ba7c372f3","src/table.rs":"eeb3471f4d56e84b0ccb8ed709b44543729941501558fa3e98dbf001c8a7ea92","src/value.rs":"31cb7ae89a4eabc47c022e7d8ec8279c2b3603d16573afe0d423291ad88e6039"},"package":"dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"git": {
|
||||
"sha1": "838a0223142a2137b530e020cb7231aba46f7946"
|
||||
},
|
||||
"path_in_vcs": "crates/toml"
|
||||
}
|
||||
+808
@@ -0,0 +1,808 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon 1.0.2",
|
||||
"colorchoice",
|
||||
"is-terminal",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon 3.0.8",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[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.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb690e81c7840c0d7aade59f242ea3b41b9bc27bcd5997890e7702ae4b32e487"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ed2e96bc16d8d740f6f48d663eddf4b8a0983e79210fd55479b7bcd0a69860e"
|
||||
dependencies = [
|
||||
"anstream 0.3.2",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "escape8259"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba4f4911e3666fcd7826997b4745c8224295a6f3072f1418c3067b97a67557ee"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr",
|
||||
"log",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
|
||||
dependencies = [
|
||||
"globset",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"memchr",
|
||||
"regex",
|
||||
"same-file",
|
||||
"thread_local",
|
||||
"walkdir",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "include_dir"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd"
|
||||
dependencies = [
|
||||
"include_dir_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "include_dir_macros"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b52b2de84ed0341893ce61ca1af04fa54eea0a764ecc38c6855cc5db84dc1927"
|
||||
dependencies = [
|
||||
"is-terminal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[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.154"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||
|
||||
[[package]]
|
||||
name = "libtest-mimic"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc0bda45ed5b3a2904262c1bb91e526127aa70e7ef3758aba2ef93cf896b9b58"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"escape8259",
|
||||
"termcolor",
|
||||
"threadpool",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
|
||||
[[package]]
|
||||
name = "normalize-line-endings"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ecf5dec444661aad892044dfcc6ea9b2d1be3db6c78916b91bbf9d903fc3006"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[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.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640"
|
||||
|
||||
[[package]]
|
||||
name = "snapbox"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96dcfc4581e3355d70ac2ee14cfdf81dce3d85c85f1ed9e2c1d3013f53b3436b"
|
||||
dependencies = [
|
||||
"anstream 0.6.18",
|
||||
"anstyle",
|
||||
"normalize-line-endings",
|
||||
"similar",
|
||||
"snapbox-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snapbox-macros"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16569f53ca23a41bb6f62e0a5084aa1661f4814a67fa33696a79073e03a664af"
|
||||
dependencies = [
|
||||
"anstream 0.6.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"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.8.23"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_spanned",
|
||||
"snapbox",
|
||||
"toml-test-data",
|
||||
"toml-test-harness",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml-test"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53982b927f6461ca125109a60be318c2a3d9d90dcdeb01a0800d6575303749c5"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml-test-data"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "237d73ae5b2aff9ff3049927b6825e69455591db9c59deedce622b0719eb18ba"
|
||||
dependencies = [
|
||||
"include_dir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml-test-harness"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6603b6d4f82a25179a629f8d9a131aec8cc8829ef7a50cdaadbd6f9cfc5fdf3"
|
||||
dependencies = [
|
||||
"ignore",
|
||||
"libtest-mimic",
|
||||
"snapbox",
|
||||
"toml-test",
|
||||
"toml-test-data",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_write",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_write"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[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.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
Vendored
+250
@@ -0,0 +1,250 @@
|
||||
# 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"
|
||||
name = "toml"
|
||||
version = "0.8.23"
|
||||
build = false
|
||||
include = [
|
||||
"build.rs",
|
||||
"src/**/*",
|
||||
"Cargo.toml",
|
||||
"Cargo.lock",
|
||||
"LICENSE*",
|
||||
"README.md",
|
||||
"examples/**/*",
|
||||
]
|
||||
autolib = false
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
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.
|
||||
"""
|
||||
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",
|
||||
"--generate-link-to-definition",
|
||||
]
|
||||
|
||||
[[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 -->"
|
||||
|
||||
[features]
|
||||
default = [
|
||||
"parse",
|
||||
"display",
|
||||
]
|
||||
display = [
|
||||
"dep:toml_edit",
|
||||
"toml_edit?/display",
|
||||
]
|
||||
parse = [
|
||||
"dep:toml_edit",
|
||||
"toml_edit?/parse",
|
||||
]
|
||||
preserve_order = ["indexmap"]
|
||||
unbounded = ["toml_edit?/unbounded"]
|
||||
|
||||
[lib]
|
||||
name = "toml"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[example]]
|
||||
name = "decode"
|
||||
path = "examples/decode.rs"
|
||||
required-features = [
|
||||
"parse",
|
||||
"display",
|
||||
]
|
||||
|
||||
[[example]]
|
||||
name = "enum_external"
|
||||
path = "examples/enum_external.rs"
|
||||
required-features = [
|
||||
"parse",
|
||||
"display",
|
||||
]
|
||||
|
||||
[[example]]
|
||||
name = "toml2json"
|
||||
path = "examples/toml2json.rs"
|
||||
required-features = [
|
||||
"parse",
|
||||
"display",
|
||||
]
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "2.0.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0.145"
|
||||
|
||||
[dependencies.serde_spanned]
|
||||
version = "0.6.9"
|
||||
features = ["serde"]
|
||||
|
||||
[dependencies.toml_datetime]
|
||||
version = "0.6.11"
|
||||
features = ["serde"]
|
||||
|
||||
[dependencies.toml_edit]
|
||||
version = "0.22.27"
|
||||
features = ["serde"]
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.serde]
|
||||
version = "1.0.199"
|
||||
features = ["derive"]
|
||||
|
||||
[dev-dependencies.serde_json]
|
||||
version = "1.0.116"
|
||||
|
||||
[dev-dependencies.snapbox]
|
||||
version = "0.6.0"
|
||||
|
||||
[dev-dependencies.toml-test-data]
|
||||
version = "2.3.0"
|
||||
|
||||
[dev-dependencies.toml-test-harness]
|
||||
version = "1.3.2"
|
||||
features = ["snapshot"]
|
||||
|
||||
[dev-dependencies.walkdir]
|
||||
version = "2.5.0"
|
||||
|
||||
[lints.clippy]
|
||||
bool_assert_comparison = "allow"
|
||||
branches_sharing_code = "allow"
|
||||
checked_conversions = "warn"
|
||||
collapsible_else_if = "allow"
|
||||
create_dir = "warn"
|
||||
dbg_macro = "warn"
|
||||
debug_assert_with_mut_call = "warn"
|
||||
doc_markdown = "warn"
|
||||
empty_enum = "warn"
|
||||
enum_glob_use = "warn"
|
||||
expl_impl_clone_on_copy = "warn"
|
||||
explicit_deref_methods = "warn"
|
||||
explicit_into_iter_loop = "warn"
|
||||
fallible_impl_from = "warn"
|
||||
filter_map_next = "warn"
|
||||
flat_map_option = "warn"
|
||||
float_cmp_const = "warn"
|
||||
fn_params_excessive_bools = "warn"
|
||||
from_iter_instead_of_collect = "warn"
|
||||
if_same_then_else = "allow"
|
||||
implicit_clone = "warn"
|
||||
imprecise_flops = "warn"
|
||||
inconsistent_struct_constructor = "warn"
|
||||
inefficient_to_string = "warn"
|
||||
infinite_loop = "warn"
|
||||
invalid_upcast_comparisons = "warn"
|
||||
large_digit_groups = "warn"
|
||||
large_stack_arrays = "warn"
|
||||
large_types_passed_by_value = "warn"
|
||||
let_and_return = "allow"
|
||||
linkedlist = "warn"
|
||||
lossy_float_literal = "warn"
|
||||
macro_use_imports = "warn"
|
||||
mem_forget = "warn"
|
||||
mutex_integer = "warn"
|
||||
needless_continue = "allow"
|
||||
needless_for_each = "warn"
|
||||
negative_feature_names = "warn"
|
||||
path_buf_push_overwrite = "warn"
|
||||
ptr_as_ptr = "warn"
|
||||
rc_mutex = "warn"
|
||||
redundant_feature_names = "warn"
|
||||
ref_option_ref = "warn"
|
||||
rest_pat_in_fully_bound_structs = "warn"
|
||||
result_large_err = "allow"
|
||||
same_functions_in_if_condition = "warn"
|
||||
self_named_module_files = "warn"
|
||||
semicolon_if_nothing_returned = "warn"
|
||||
str_to_string = "warn"
|
||||
string_add = "warn"
|
||||
string_add_assign = "warn"
|
||||
string_lit_as_bytes = "warn"
|
||||
string_to_string = "warn"
|
||||
todo = "warn"
|
||||
trait_duplication_in_bounds = "warn"
|
||||
uninlined_format_args = "warn"
|
||||
verbose_file_reads = "warn"
|
||||
wildcard_imports = "warn"
|
||||
zero_sized_map_values = "warn"
|
||||
|
||||
[lints.rust]
|
||||
unnameable_types = "allow"
|
||||
unreachable_pub = "warn"
|
||||
unsafe_op_in_unsafe_fn = "warn"
|
||||
unused_lifetimes = "warn"
|
||||
unused_macro_rules = "warn"
|
||||
unused_qualifications = "warn"
|
||||
|
||||
[lints.rust.rust_2018_idioms]
|
||||
level = "warn"
|
||||
priority = -1
|
||||
Vendored
+202
@@ -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.
|
||||
|
||||
Vendored
+19
@@ -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.
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
# toml
|
||||
|
||||
[](https://crates.io/crates/toml)
|
||||
[](https://docs.rs/toml)
|
||||
|
||||
A [serde]-compatible [TOML][toml] decoder and encoder for Rust.
|
||||
|
||||
For format-preserving editing 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
|
||||
|
||||
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 the work by you, as defined in the Apache-2.0
|
||||
license, shall be dual-licensed as above, without any additional terms or
|
||||
conditions.
|
||||
Vendored
+54
@@ -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:#?}");
|
||||
}
|
||||
+45
@@ -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:#?}");
|
||||
}
|
||||
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
use std::env;
|
||||
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 input = if args.len() > 1 {
|
||||
let name = args.nth(1).unwrap();
|
||||
std::fs::read_to_string(name).unwrap()
|
||||
} else {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_to_string(&mut input).unwrap();
|
||||
input
|
||||
};
|
||||
|
||||
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()),
|
||||
}
|
||||
}
|
||||
Vendored
+313
@@ -0,0 +1,313 @@
|
||||
//! 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(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::fmt::Debug 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> 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 inner = toml_edit::de::Deserializer::parse(self.input).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 = toml_edit::de::Deserializer::parse(self.input).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 = toml_edit::de::Deserializer::parse(self.input).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 = toml_edit::de::Deserializer::parse(self.input).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 = toml_edit::de::Deserializer::parse(self.input).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> 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 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
|
||||
}
|
||||
}
|
||||
Vendored
+91
@@ -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(crate) struct Error {
|
||||
inner: String,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Add key while unwinding
|
||||
pub(crate) fn add_key(&mut self, _key: String) {}
|
||||
|
||||
/// What went wrong
|
||||
pub(crate) 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 {}
|
||||
}
|
||||
Vendored
+66
@@ -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::DocumentMut) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+185
@@ -0,0 +1,185 @@
|
||||
//! A [serde]-compatible [TOML]-parsing library
|
||||
//!
|
||||
//! TOML itself is a simple, ergonomic, and readable configuration format:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [package]
|
||||
//! name = "toml"
|
||||
//!
|
||||
//! [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/
|
||||
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
// 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)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(clippy::print_stderr)]
|
||||
#![warn(clippy::print_stdout)]
|
||||
|
||||
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;
|
||||
|
||||
#[doc = include_str!("../README.md")]
|
||||
#[cfg(doctest)]
|
||||
pub struct ReadmeDoctests;
|
||||
Vendored
+455
@@ -0,0 +1,455 @@
|
||||
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"
|
||||
///
|
||||
/// [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.copysign(-1.0))
|
||||
};
|
||||
|
||||
(@value (nan)) => {
|
||||
$crate::Value::Float(::std::f64::NAN.copysign(1.0))
|
||||
};
|
||||
|
||||
(@value nan) => {
|
||||
$crate::Value::Float(::std::f64::NAN.copysign(1.0))
|
||||
};
|
||||
|
||||
(@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
|
||||
}
|
||||
Vendored
+636
@@ -0,0 +1,636 @@
|
||||
// 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>(&self, key: &Q) -> Option<&Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
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>(&self, key: &Q) -> bool
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
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>(&mut self, key: &Q) -> Option<&mut Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
self.map.get_mut(key)
|
||||
}
|
||||
|
||||
/// Returns the key-value pair matching the given 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_key_value<Q>(&self, key: &Q) -> Option<(&String, &Value)>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: ?Sized + Ord + Eq + Hash,
|
||||
{
|
||||
self.map.get_key_value(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>(&mut self, key: &Q) -> Option<Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
{
|
||||
self.map.remove(key)
|
||||
}
|
||||
#[cfg(feature = "preserve_order")]
|
||||
{
|
||||
self.map.shift_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<Q> ops::Index<&Q> for Map<String, Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
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<Q> ops::IndexMut<&Q> for Map<String, Value>
|
||||
where
|
||||
String: Borrow<Q>,
|
||||
Q: Ord + Eq + Hash + ?Sized,
|
||||
{
|
||||
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 {
|
||||
#[cfg(not(feature = "preserve_order"))]
|
||||
{
|
||||
self.occupied.remove()
|
||||
}
|
||||
#[cfg(feature = "preserve_order")]
|
||||
{
|
||||
self.occupied.shift_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);
|
||||
Vendored
+107
@@ -0,0 +1,107 @@
|
||||
use super::write_document;
|
||||
use super::{Error, Serializer};
|
||||
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 serde::ser::SerializeSeq for SerializeDocumentArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeTuple for SerializeDocumentArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeTupleStruct for SerializeDocumentArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 InnerSerializeDocumentTupleVariant =
|
||||
<toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeTupleVariant;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeDocumentTupleVariant<'d> {
|
||||
inner: InnerSerializeDocumentTupleVariant,
|
||||
dst: &'d mut String,
|
||||
settings: DocumentFormatter,
|
||||
}
|
||||
|
||||
impl<'d> SerializeDocumentTupleVariant<'d> {
|
||||
pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentTupleVariant) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dst: ser.dst,
|
||||
settings: ser.settings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeTupleVariant for SerializeDocumentTupleVariant<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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())
|
||||
}
|
||||
}
|
||||
Vendored
+118
@@ -0,0 +1,118 @@
|
||||
use super::write_document;
|
||||
use super::{Error, Serializer};
|
||||
use crate::fmt::DocumentFormatter;
|
||||
|
||||
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 serde::ser::SerializeMap for SerializeDocumentTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_key<T>(&mut self, input: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_key(input).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeStruct for SerializeDocumentTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStructVariant for SerializeDocumentTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
serde::ser::SerializeStruct::serialize_field(self, key, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
serde::ser::SerializeStruct::end(self)
|
||||
}
|
||||
}
|
||||
|
||||
type InnerSerializeDocumentStructVariant =
|
||||
<toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeStructVariant;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeDocumentStructVariant<'d> {
|
||||
inner: InnerSerializeDocumentStructVariant,
|
||||
dst: &'d mut String,
|
||||
settings: DocumentFormatter,
|
||||
}
|
||||
|
||||
impl<'d> SerializeDocumentStructVariant<'d> {
|
||||
pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentStructVariant) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dst: ser.dst,
|
||||
settings: ser.settings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStructVariant for SerializeDocumentStructVariant<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_field(key, value).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
write_document(self.dst, self.settings, self.inner.end())
|
||||
}
|
||||
}
|
||||
Vendored
+484
@@ -0,0 +1,484 @@
|
||||
//! 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.
|
||||
|
||||
#[cfg(feature = "display")]
|
||||
mod array;
|
||||
#[cfg(feature = "display")]
|
||||
mod map;
|
||||
#[cfg(feature = "display")]
|
||||
mod ser_value;
|
||||
|
||||
#[cfg(feature = "display")]
|
||||
pub use ser_value::ValueSerializer;
|
||||
|
||||
/// 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>(value: &T) -> Result<String, Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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::DocumentMut`](https://docs.rs/toml_edit/latest/toml_edit/struct.DocumentMut.html).
|
||||
#[cfg(feature = "display")]
|
||||
pub fn to_string_pretty<T>(value: &T) -> Result<String, Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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(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::fmt::Debug 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`].
|
||||
#[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::DocumentMut`](https://docs.rs/toml_edit/latest/toml_edit/struct.DocumentMut.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 = array::SerializeDocumentArray<'d>;
|
||||
type SerializeTuple = array::SerializeDocumentArray<'d>;
|
||||
type SerializeTupleStruct = array::SerializeDocumentArray<'d>;
|
||||
type SerializeTupleVariant = array::SerializeDocumentTupleVariant<'d>;
|
||||
type SerializeMap = map::SerializeDocumentTable<'d>;
|
||||
type SerializeStruct = map::SerializeDocumentTable<'d>;
|
||||
type SerializeStructVariant = map::SerializeDocumentStructVariant<'d>;
|
||||
|
||||
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>(self, v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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>(self, name: &'static str, v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
write_document(
|
||||
self.dst,
|
||||
self.settings,
|
||||
toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v),
|
||||
)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 = array::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> {
|
||||
let ser = toml_edit::ser::ValueSerializer::new()
|
||||
.serialize_tuple_variant(name, variant_index, variant, len)
|
||||
.map_err(Error::wrap)?;
|
||||
let ser = array::SerializeDocumentTupleVariant::new(self, ser);
|
||||
Ok(ser)
|
||||
}
|
||||
|
||||
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 = map::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> {
|
||||
let ser = toml_edit::ser::ValueSerializer::new()
|
||||
.serialize_struct_variant(name, variant_index, variant, len)
|
||||
.map_err(Error::wrap)?;
|
||||
let ser = map::SerializeDocumentStructVariant::new(self, ser);
|
||||
Ok(ser)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "display")]
|
||||
pub(crate) fn write_document(
|
||||
dst: &mut String,
|
||||
mut settings: crate::fmt::DocumentFormatter,
|
||||
value: Result<toml_edit::Value, crate::edit::ser::Error>,
|
||||
) -> Result<(), Error> {
|
||||
use std::fmt::Write;
|
||||
use toml_edit::visit_mut::VisitMut as _;
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
settings.visit_table_mut(&mut table);
|
||||
|
||||
let doc: toml_edit::DocumentMut = table.into();
|
||||
write!(dst, "{doc}").unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
use super::write_value;
|
||||
use super::{Error, ValueSerializer};
|
||||
|
||||
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 serde::ser::SerializeSeq for SerializeValueArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeTuple for SerializeValueArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_element<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeTupleStruct for SerializeValueArray<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 InnerSerializeValueTupleVariant =
|
||||
<toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeTupleVariant;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeValueTupleVariant<'d> {
|
||||
inner: InnerSerializeValueTupleVariant,
|
||||
dst: &'d mut String,
|
||||
}
|
||||
|
||||
impl<'d> SerializeValueTupleVariant<'d> {
|
||||
pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueTupleVariant) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dst: ser.dst,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeTupleVariant for SerializeValueTupleVariant<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_field(value).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
write_value(self.dst, self.inner.end())
|
||||
}
|
||||
}
|
||||
Vendored
+95
@@ -0,0 +1,95 @@
|
||||
use super::write_value;
|
||||
use super::{Error, ValueSerializer};
|
||||
|
||||
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 serde::ser::SerializeMap for SerializeValueTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_key<T>(&mut self, input: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_key(input).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 serde::ser::SerializeStruct for SerializeValueTable<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
type InnerSerializeValueStructVariant =
|
||||
<toml_edit::ser::ValueSerializer as serde::Serializer>::SerializeStructVariant;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct SerializeValueStructVariant<'d> {
|
||||
inner: InnerSerializeValueStructVariant,
|
||||
dst: &'d mut String,
|
||||
}
|
||||
|
||||
impl<'d> SerializeValueStructVariant<'d> {
|
||||
pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueStructVariant) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
dst: ser.dst,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::ser::SerializeStructVariant for SerializeValueStructVariant<'_> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
self.inner.serialize_field(key, value).map_err(Error::wrap)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||
write_value(self.dst, self.inner.end())
|
||||
}
|
||||
}
|
||||
Vendored
+328
@@ -0,0 +1,328 @@
|
||||
mod array;
|
||||
mod map;
|
||||
|
||||
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 mut value = String::new();
|
||||
/// serde::Serialize::serialize(
|
||||
/// &config,
|
||||
/// toml::ser::ValueSerializer::new(&mut value)
|
||||
/// ).unwrap();
|
||||
/// println!("{}", value)
|
||||
/// ```
|
||||
#[cfg(feature = "display")]
|
||||
pub struct ValueSerializer<'d> {
|
||||
dst: &'d mut String,
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> serde::ser::Serializer for ValueSerializer<'d> {
|
||||
type Ok = ();
|
||||
type Error = Error;
|
||||
type SerializeSeq = array::SerializeValueArray<'d>;
|
||||
type SerializeTuple = array::SerializeValueArray<'d>;
|
||||
type SerializeTupleStruct = array::SerializeValueArray<'d>;
|
||||
type SerializeTupleVariant = array::SerializeValueTupleVariant<'d>;
|
||||
type SerializeMap = map::SerializeValueTable<'d>;
|
||||
type SerializeStruct = map::SerializeValueTable<'d>;
|
||||
type SerializeStructVariant = map::SerializeValueStructVariant<'d>;
|
||||
|
||||
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>(self, v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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>(self, name: &'static str, v: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
write_value(
|
||||
self.dst,
|
||||
toml_edit::ser::ValueSerializer::new().serialize_newtype_struct(name, v),
|
||||
)
|
||||
}
|
||||
|
||||
fn serialize_newtype_variant<T>(
|
||||
self,
|
||||
name: &'static str,
|
||||
variant_index: u32,
|
||||
variant: &'static str,
|
||||
value: &T,
|
||||
) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: serde::ser::Serialize + ?Sized,
|
||||
{
|
||||
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 = array::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> {
|
||||
let ser = toml_edit::ser::ValueSerializer::new()
|
||||
.serialize_tuple_variant(name, variant_index, variant, len)
|
||||
.map_err(Error::wrap)?;
|
||||
let ser = array::SerializeValueTupleVariant::new(self, ser);
|
||||
Ok(ser)
|
||||
}
|
||||
|
||||
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 = map::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> {
|
||||
let ser = toml_edit::ser::ValueSerializer::new()
|
||||
.serialize_struct_variant(name, variant_index, variant, len)
|
||||
.map_err(Error::wrap)?;
|
||||
let ser = map::SerializeValueStructVariant::new(self, ser);
|
||||
Ok(ser)
|
||||
}
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
Vendored
+115
@@ -0,0 +1,115 @@
|
||||
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 entries are stored in
|
||||
/// [lexicographic order](https://doc.rust-lang.org/std/primitive.str.html#impl-Ord-for-str)
|
||||
/// of the keys. Enable the `preserve_order` feature to store entries in the order they appear in
|
||||
/// the source file.
|
||||
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 std::fmt::Display for Table {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::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::IntoDeserializer<'_, crate::de::Error> for Table {
|
||||
type Deserializer = Self;
|
||||
|
||||
fn into_deserializer(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
Vendored
+1495
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user