Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/valuable/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/valuable/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.lock":"fea5e41d2befef0b42734010a85f95548b5255ff1e4ee2dd2e6827adb8fe5f3e","Cargo.toml":"995a2454b4e3e583124d60b694e106ebd193b9742df3e050a6f49e5801b3597b","benches/structable.rs":"1baad763d1b0900004682b139efd58b17c974dc2068ede2229f8786e4a21372e","build.rs":"4ad508d818c27ee58bf7da2b9b4b425dae3e2656850327b3080fe2ad38767928","examples/derive.rs":"238473e63c0647cdb6652f1613575e24b323d40db5c8f3e5c32d64a3ea6b4048","examples/hello_world.rs":"75e48360e53b37e077e574d9c1aa2754b197f551ac5d604b03ebec9d31bab5cf","examples/print.rs":"924c55402b18e518317acc013a6cf407fcc13532c1eca8d9cd5f5631e79df960","no_atomic.rs":"b1c5cb0bd10733eb20516d10edc047b45aa67943f3347ae44fb779ed7fc7aff2","src/enumerable.rs":"008fe833c558f7e956ba0238a9d66947a671f66c5762905ed79d48a428c0ad44","src/field.rs":"c3d96f215c4bfc2a3910d0616fb335332d17f7dcf93ca739c933d88e1f98d229","src/lib.rs":"6954630c4c7c389192f3f8b5097076bbba6e43b5c4cd4ec68b4ffc18bff0a5b4","src/listable.rs":"f1a0743ed650604634972c19b66505a5727a6a6e2d7b54861e65cdcf10949432","src/mappable.rs":"ef7d334ef00d6b34cbff45b73b13935de6659933abafff9ad3d5d2a16d7ccac1","src/named_values.rs":"df5009074379ea59b02ebaf730890d0a4b6fa5c67c4057cc60f84d3652ca2bc5","src/slice.rs":"e382f56eb14ea7848276a4c8bda537f5207a4a6ed7a4b2ee4d2dde7feebce3b4","src/structable.rs":"369b17701d59bab138eac22ec043d434a052f49976236cc5ee680e72ca23ed6e","src/tuplable.rs":"e8b64a0761263666d984257109b5d54337cd97be59f08b08ec153e68ec1636c5","src/valuable.rs":"f8fdef201d3181935330fb86b27c455a5c86079f9f2cad363cda765801d7dd50","src/value.rs":"479d2c5b9d84c930e3abfe0032734ad92b243cf095f5fea6226a9da5eec81484","src/visit.rs":"060bacd3e1c0b333692f96c3ca970ca47a859cc28700713630996d9f0dc1668e"},"package":"830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"}
|
||||
617
third-party/vendor/valuable/Cargo.lock
generated
vendored
Normal file
617
third-party/vendor/valuable/Cargo.lock
generated
vendored
Normal file
|
|
@ -0,0 +1,617 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"cast",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"csv",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_cbor",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"csv-core",
|
||||
"itoa 0.4.8",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv-core"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[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.112"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[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 = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.133"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a"
|
||||
|
||||
[[package]]
|
||||
name = "serde_cbor"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
|
||||
dependencies = [
|
||||
"half",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.133"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142"
|
||||
dependencies = [
|
||||
"itoa 1.0.1",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"valuable-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "valuable-derive"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d44690c645190cfce32f91a1582281654b2338c6073fa250b0949fd25c55b32"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
41
third-party/vendor/valuable/Cargo.toml
vendored
Normal file
41
third-party/vendor/valuable/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.51.0"
|
||||
name = "valuable"
|
||||
version = "0.1.0"
|
||||
description = "Object-safe value inspection, used to pass un-typed structured data across trait-object boundaries.\n"
|
||||
readme = "../README.md"
|
||||
keywords = ["valuable", "serialization", "debugging", "no_std"]
|
||||
categories = ["development-tools::debugging", "encoding"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/tokio-rs/valuable"
|
||||
resolver = "2"
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[[bench]]
|
||||
name = "structable"
|
||||
harness = false
|
||||
[dependencies.valuable-derive]
|
||||
version = "0.1.0"
|
||||
optional = true
|
||||
[dev-dependencies.criterion]
|
||||
version = "0.3"
|
||||
|
||||
[features]
|
||||
alloc = []
|
||||
default = ["std"]
|
||||
derive = ["valuable-derive"]
|
||||
std = ["alloc"]
|
||||
128
third-party/vendor/valuable/benches/structable.rs
vendored
Normal file
128
third-party/vendor/valuable/benches/structable.rs
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use valuable::*;
|
||||
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
#[derive(Default)]
|
||||
struct HelloWorld {
|
||||
one: usize,
|
||||
two: usize,
|
||||
three: usize,
|
||||
four: usize,
|
||||
five: usize,
|
||||
six: usize,
|
||||
}
|
||||
|
||||
static FIELDS: &[NamedField<'static>] = &[
|
||||
NamedField::new("one"),
|
||||
NamedField::new("two"),
|
||||
NamedField::new("three"),
|
||||
NamedField::new("four"),
|
||||
NamedField::new("five"),
|
||||
NamedField::new("six"),
|
||||
];
|
||||
|
||||
impl Structable for HelloWorld {
|
||||
fn definition(&self) -> StructDef<'_> {
|
||||
StructDef::new_static("HelloWorld", Fields::Named(FIELDS))
|
||||
}
|
||||
}
|
||||
|
||||
impl Valuable for HelloWorld {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Structable(self)
|
||||
}
|
||||
|
||||
fn visit(&self, v: &mut dyn Visit) {
|
||||
v.visit_named_fields(&NamedValues::new(
|
||||
FIELDS,
|
||||
&[
|
||||
Value::Usize(self.one),
|
||||
Value::Usize(self.two),
|
||||
Value::Usize(self.three),
|
||||
Value::Usize(self.four),
|
||||
Value::Usize(self.five),
|
||||
Value::Usize(self.six),
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
fn criterion_benchmark(c: &mut Criterion) {
|
||||
const NUM: usize = 50;
|
||||
|
||||
let hello_world = black_box(HelloWorld::default());
|
||||
let structable = &hello_world as &dyn Structable;
|
||||
let f = match structable.definition() {
|
||||
StructDef::Static {
|
||||
fields: Fields::Named(fields),
|
||||
..
|
||||
} => &fields[5],
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
struct Sum(usize, &'static NamedField<'static>);
|
||||
|
||||
impl Visit for Sum {
|
||||
fn visit_named_fields(&mut self, record: &NamedValues<'_>) {
|
||||
self.0 += match record.get(self.1) {
|
||||
Some(Value::Usize(v)) => v,
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, _: Value<'_>) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
c.bench_function("struct", |b| {
|
||||
b.iter(|| {
|
||||
let mut num = 0;
|
||||
for _ in 0..NUM {
|
||||
let hello_world = black_box(HelloWorld::default());
|
||||
num += hello_world.six;
|
||||
}
|
||||
|
||||
black_box(num);
|
||||
})
|
||||
});
|
||||
|
||||
c.bench_function("valuable", |b| {
|
||||
b.iter(|| {
|
||||
let mut v = Sum(black_box(0), f);
|
||||
|
||||
for _ in 0..NUM {
|
||||
v.visit_named_fields(&NamedValues::new(
|
||||
FIELDS,
|
||||
&[
|
||||
Value::Usize(0),
|
||||
Value::Usize(0),
|
||||
Value::Usize(0),
|
||||
Value::Usize(0),
|
||||
Value::Usize(0),
|
||||
Value::Usize(0),
|
||||
],
|
||||
));
|
||||
/*
|
||||
v.visit_struct(&Record::new(
|
||||
&definition,
|
||||
&[
|
||||
Value::Usize(hello_world.one),
|
||||
Value::Usize(hello_world.two),
|
||||
Value::Usize(hello_world.three),
|
||||
Value::Usize(hello_world.four),
|
||||
Value::Usize(hello_world.five),
|
||||
Value::Usize(hello_world.six),
|
||||
]
|
||||
));
|
||||
*/
|
||||
// hello_world.visit(&mut v);
|
||||
}
|
||||
|
||||
black_box(v.0);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, criterion_benchmark);
|
||||
criterion_main!(benches);
|
||||
39
third-party/vendor/valuable/build.rs
vendored
Normal file
39
third-party/vendor/valuable/build.rs
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#![warn(rust_2018_idioms, single_use_lifetimes)]
|
||||
|
||||
use std::env;
|
||||
|
||||
include!("no_atomic.rs");
|
||||
|
||||
// The rustc-cfg strings below are *not* public API. Please let us know by
|
||||
// opening a GitHub issue if your build environment requires some way to enable
|
||||
// these cfgs other than by executing our build script.
|
||||
fn main() {
|
||||
let target = match env::var("TARGET") {
|
||||
Ok(target) => target,
|
||||
Err(e) => {
|
||||
println!(
|
||||
"cargo:warning=valuable: unable to get TARGET environment variable: {}",
|
||||
e
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Note that this is `no_*`, not `has_*`. This allows treating
|
||||
// `cfg(target_has_atomic = "ptr")` as true when the build script doesn't
|
||||
// run. This is needed for compatibility with non-cargo build systems that
|
||||
// don't run the build script.
|
||||
if NO_ATOMIC_CAS.contains(&&*target) {
|
||||
println!("cargo:rustc-cfg=valuable_no_atomic_cas");
|
||||
}
|
||||
if NO_ATOMIC.contains(&&*target) {
|
||||
println!("cargo:rustc-cfg=valuable_no_atomic");
|
||||
println!("cargo:rustc-cfg=valuable_no_atomic_64");
|
||||
} else if NO_ATOMIC_64.contains(&&*target) {
|
||||
println!("cargo:rustc-cfg=valuable_no_atomic_64");
|
||||
} else {
|
||||
// Otherwise, assuming `"max-atomic-width" == 64`.
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed=no_atomic.rs");
|
||||
}
|
||||
26
third-party/vendor/valuable/examples/derive.rs
vendored
Normal file
26
third-party/vendor/valuable/examples/derive.rs
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
use valuable::Valuable;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
// `Debug` not implemented for struct, the debug implementation is going via
|
||||
// valuable.
|
||||
#[derive(Valuable)]
|
||||
struct Person {
|
||||
name: String,
|
||||
age: u8,
|
||||
phones: Vec<String>,
|
||||
favorites: HashMap<String, String>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut p = Person {
|
||||
name: "John Doe".to_string(),
|
||||
age: 42,
|
||||
phones: vec!["876-5309".to_string()],
|
||||
favorites: HashMap::new(),
|
||||
};
|
||||
|
||||
p.favorites.insert("color".to_string(), "blue".to_string());
|
||||
|
||||
println!("{:#?}", p.as_value());
|
||||
}
|
||||
68
third-party/vendor/valuable/examples/hello_world.rs
vendored
Normal file
68
third-party/vendor/valuable/examples/hello_world.rs
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
use valuable::*;
|
||||
|
||||
struct HelloWorld {
|
||||
hello: &'static str,
|
||||
world: World,
|
||||
}
|
||||
|
||||
struct World {
|
||||
answer: usize,
|
||||
}
|
||||
|
||||
static HELLO_WORLD_FIELDS: &[NamedField<'static>] =
|
||||
&[NamedField::new("hello"), NamedField::new("world")];
|
||||
|
||||
impl Structable for HelloWorld {
|
||||
fn definition(&self) -> StructDef<'_> {
|
||||
StructDef::new_static("HelloWorld", Fields::Named(HELLO_WORLD_FIELDS))
|
||||
}
|
||||
}
|
||||
|
||||
impl Valuable for HelloWorld {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Structable(self)
|
||||
}
|
||||
|
||||
fn visit(&self, v: &mut dyn Visit) {
|
||||
v.visit_named_fields(&NamedValues::new(
|
||||
HELLO_WORLD_FIELDS,
|
||||
&[Value::String(self.hello), Value::Structable(&self.world)],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
static WORLD_FIELDS: &[NamedField<'static>] = &[NamedField::new("answer")];
|
||||
|
||||
impl Valuable for World {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Structable(self)
|
||||
}
|
||||
|
||||
fn visit(&self, v: &mut dyn Visit) {
|
||||
v.visit_named_fields(&NamedValues::new(
|
||||
WORLD_FIELDS,
|
||||
&[Value::Usize(self.answer)],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
impl Structable for World {
|
||||
fn definition(&self) -> StructDef<'_> {
|
||||
StructDef::new_static("World", Fields::Named(WORLD_FIELDS))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let hello_world = HelloWorld {
|
||||
hello: "wut",
|
||||
world: World { answer: 42 },
|
||||
};
|
||||
|
||||
let value = Value::Structable(&hello_world);
|
||||
println!("{:#?}", value);
|
||||
|
||||
let slice = &[1, 2, 3][..];
|
||||
|
||||
let value = &slice as &dyn Valuable;
|
||||
println!("{:?}", value);
|
||||
}
|
||||
106
third-party/vendor/valuable/examples/print.rs
vendored
Normal file
106
third-party/vendor/valuable/examples/print.rs
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
use valuable::{NamedValues, Valuable, Value, Visit};
|
||||
|
||||
struct Print(String);
|
||||
|
||||
impl Print {
|
||||
fn indent(&self) -> Print {
|
||||
Print(format!("{} ", self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Print {
|
||||
fn visit_value(&mut self, value: Value<'_>) {
|
||||
match value {
|
||||
Value::Structable(v) => {
|
||||
let def = v.definition();
|
||||
// Print the struct name
|
||||
println!("{}{}:", self.0, def.name());
|
||||
|
||||
// Visit fields
|
||||
let mut visit = self.indent();
|
||||
v.visit(&mut visit);
|
||||
}
|
||||
Value::Enumerable(v) => {
|
||||
let def = v.definition();
|
||||
let variant = v.variant();
|
||||
// Print the enum name
|
||||
println!("{}{}::{}:", self.0, def.name(), variant.name());
|
||||
|
||||
// Visit fields
|
||||
let mut visit = self.indent();
|
||||
v.visit(&mut visit);
|
||||
}
|
||||
Value::Listable(v) => {
|
||||
println!("{}", self.0);
|
||||
|
||||
// Visit fields
|
||||
let mut visit = self.indent();
|
||||
v.visit(&mut visit);
|
||||
}
|
||||
Value::Mappable(v) => {
|
||||
println!("{}", self.0);
|
||||
|
||||
// Visit fields
|
||||
let mut visit = self.indent();
|
||||
v.visit(&mut visit);
|
||||
}
|
||||
// Primitive or unknown type, just render Debug
|
||||
v => println!("{:?}", v),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
for (field, value) in named_values {
|
||||
print!("{}- {}: ", self.0, field.name());
|
||||
value.visit(self);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
for value in values {
|
||||
print!("{}- ", self.0);
|
||||
value.visit(self);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
|
||||
print!("{}- {:?}: ", self.0, key);
|
||||
value.visit(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Valuable)]
|
||||
struct Person {
|
||||
name: String,
|
||||
age: u32,
|
||||
addresses: Vec<Address>,
|
||||
}
|
||||
|
||||
#[derive(Valuable)]
|
||||
struct Address {
|
||||
street: String,
|
||||
city: String,
|
||||
zip: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let person = Person {
|
||||
name: "Angela Ashton".to_string(),
|
||||
age: 31,
|
||||
addresses: vec![
|
||||
Address {
|
||||
street: "123 1st Ave".to_string(),
|
||||
city: "Townsville".to_string(),
|
||||
zip: "12345".to_string(),
|
||||
},
|
||||
Address {
|
||||
street: "555 Main St.".to_string(),
|
||||
city: "New Old Town".to_string(),
|
||||
zip: "55555".to_string(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let mut print = Print("".to_string());
|
||||
valuable::visit(&person, &mut print);
|
||||
}
|
||||
63
third-party/vendor/valuable/no_atomic.rs
vendored
Normal file
63
third-party/vendor/valuable/no_atomic.rs
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// This file is @generated by no_atomic.sh.
|
||||
// It is not intended for manual editing.
|
||||
|
||||
const NO_ATOMIC_CAS: &[&str] = &[
|
||||
"avr-unknown-gnu-atmega328",
|
||||
"bpfeb-unknown-none",
|
||||
"bpfel-unknown-none",
|
||||
"msp430-none-elf",
|
||||
"riscv32i-unknown-none-elf",
|
||||
"riscv32imc-unknown-none-elf",
|
||||
"thumbv4t-none-eabi",
|
||||
"thumbv6m-none-eabi",
|
||||
];
|
||||
const NO_ATOMIC_64: &[&str] = &[
|
||||
"arm-linux-androideabi",
|
||||
"armebv7r-none-eabi",
|
||||
"armebv7r-none-eabihf",
|
||||
"armv4t-unknown-linux-gnueabi",
|
||||
"armv5te-unknown-linux-gnueabi",
|
||||
"armv5te-unknown-linux-musleabi",
|
||||
"armv5te-unknown-linux-uclibceabi",
|
||||
"armv7r-none-eabi",
|
||||
"armv7r-none-eabihf",
|
||||
"hexagon-unknown-linux-musl",
|
||||
"m68k-unknown-linux-gnu",
|
||||
"mips-unknown-linux-gnu",
|
||||
"mips-unknown-linux-musl",
|
||||
"mips-unknown-linux-uclibc",
|
||||
"mipsel-unknown-linux-gnu",
|
||||
"mipsel-unknown-linux-musl",
|
||||
"mipsel-unknown-linux-uclibc",
|
||||
"mipsel-unknown-none",
|
||||
"mipsisa32r6-unknown-linux-gnu",
|
||||
"mipsisa32r6el-unknown-linux-gnu",
|
||||
"powerpc-unknown-freebsd",
|
||||
"powerpc-unknown-linux-gnu",
|
||||
"powerpc-unknown-linux-gnuspe",
|
||||
"powerpc-unknown-linux-musl",
|
||||
"powerpc-unknown-netbsd",
|
||||
"powerpc-unknown-openbsd",
|
||||
"powerpc-wrs-vxworks",
|
||||
"powerpc-wrs-vxworks-spe",
|
||||
"riscv32gc-unknown-linux-gnu",
|
||||
"riscv32gc-unknown-linux-musl",
|
||||
"riscv32imac-unknown-none-elf",
|
||||
"riscv32imc-esp-espidf",
|
||||
"thumbv7em-none-eabi",
|
||||
"thumbv7em-none-eabihf",
|
||||
"thumbv7m-none-eabi",
|
||||
"thumbv8m.base-none-eabi",
|
||||
"thumbv8m.main-none-eabi",
|
||||
"thumbv8m.main-none-eabihf",
|
||||
"armv6k-nintendo-3ds",
|
||||
"mipsel-sony-psp",
|
||||
"thumbv4t-none-eabi",
|
||||
"thumbv6m-none-eabi",
|
||||
];
|
||||
const NO_ATOMIC: &[&str] = &[
|
||||
"avr-unknown-gnu-atmega328",
|
||||
"msp430-none-elf",
|
||||
"riscv32i-unknown-none-elf",
|
||||
"riscv32imc-unknown-none-elf",
|
||||
];
|
||||
682
third-party/vendor/valuable/src/enumerable.rs
vendored
Normal file
682
third-party/vendor/valuable/src/enumerable.rs
vendored
Normal file
|
|
@ -0,0 +1,682 @@
|
|||
use crate::field::*;
|
||||
use crate::*;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::format;
|
||||
use core::fmt;
|
||||
|
||||
/// An enum-like [`Valuable`] sub-type.
|
||||
///
|
||||
/// Implemented by [`Valuable`] types that have an enum-like shape. Fields may
|
||||
/// be named or unnamed (tuple). Values that implement `Enumerable` must return
|
||||
/// [`Value::Enumerable`] from their [`Valuable::as_value`] implementation.
|
||||
///
|
||||
/// # Inspecting
|
||||
///
|
||||
/// The [`variant()`] method returns the `Enumerable` instance's variant. The
|
||||
/// `Enumerable` may also have unnamed fields (tuple) or named fields.
|
||||
/// Inspecting the field values is done by visiting the enum. When visiting an
|
||||
/// `Enumerable`, either the [`visit_named_fields()`] or the
|
||||
/// [`visit_unnamed_fields()`] methods of [`Visit`] are called. Each method may
|
||||
/// be called multiple times per `Enumerable`, but the two methods are never
|
||||
/// mixed.
|
||||
///
|
||||
/// [`variant()`]: Enumerable::variant
|
||||
/// [`visit_named_fields()`]: Visit::visit_named_fields
|
||||
/// [`visit_unnamed_fields()`]: Visit::visit_unnamed_fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Valuable, Value, Visit};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum MyEnum {
|
||||
/// Foo,
|
||||
/// Bar(u32),
|
||||
/// }
|
||||
///
|
||||
/// struct PrintVariant;
|
||||
///
|
||||
/// impl Visit for PrintVariant {
|
||||
/// fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
/// for value in values {
|
||||
/// println!(" - {:?}", value);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// match value {
|
||||
/// Value::Enumerable(v) => {
|
||||
/// println!("{}", v.variant().name());
|
||||
/// v.visit(self)
|
||||
/// }
|
||||
/// _ => {}
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let my_enum = MyEnum::Bar(123);
|
||||
///
|
||||
/// valuable::visit(&my_enum, &mut PrintVariant);
|
||||
/// ```
|
||||
///
|
||||
/// If the enum is **statically** defined, then all variants, and variant fields
|
||||
/// are known ahead of time and may be accessed via the [`EnumDef`] instance
|
||||
/// returned by [`definition()`].
|
||||
///
|
||||
/// [`definition()`]: Enumerable::definition
|
||||
///
|
||||
/// # Implementing
|
||||
///
|
||||
/// Implementing `Enumerable` is usually done by adding `#[derive(Valuable)]` to
|
||||
/// a Rust `enum` definition.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Valuable, Enumerable, EnumDef};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum MyEnum {
|
||||
/// Foo,
|
||||
/// Bar(u32),
|
||||
/// }
|
||||
///
|
||||
/// let my_enum = MyEnum::Bar(123);
|
||||
///
|
||||
/// let variants = match my_enum.definition() {
|
||||
/// EnumDef::Static { name, variants, .. } => {
|
||||
/// assert_eq!("MyEnum", name);
|
||||
/// variants
|
||||
/// }
|
||||
/// _ => unreachable!(),
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(2, variants.len());
|
||||
/// assert_eq!("Foo", variants[0].name());
|
||||
/// assert!(variants[0].fields().is_unnamed());
|
||||
/// ```
|
||||
pub trait Enumerable: Valuable {
|
||||
/// Returns the enum's definition.
|
||||
///
|
||||
/// See [`EnumDef`] documentation for more details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Enumerable, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum MyEnum {
|
||||
/// Foo,
|
||||
/// Bar(u32),
|
||||
/// }
|
||||
///
|
||||
/// let my_enum = MyEnum::Bar(123);
|
||||
///
|
||||
/// assert_eq!("MyEnum", my_enum.definition().name());
|
||||
/// ```
|
||||
fn definition(&self) -> EnumDef<'_>;
|
||||
|
||||
/// Returns the `enum`'s current variant.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Enumerable, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum MyEnum {
|
||||
/// Foo,
|
||||
/// Bar(u32),
|
||||
/// }
|
||||
///
|
||||
/// let my_enum = MyEnum::Foo;
|
||||
/// assert_eq!("Foo", my_enum.variant().name());
|
||||
/// ```
|
||||
fn variant(&self) -> Variant<'_>;
|
||||
}
|
||||
|
||||
/// An enum's variants, variant fields, and other enum-level information.
|
||||
///
|
||||
/// Returned by [`Enumerable::definition()`], `EnumDef` provides the caller with
|
||||
/// information about the enum's definition.
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug)]
|
||||
pub enum EnumDef<'a> {
|
||||
/// The enum is statically-defined, all variants and variant-level fields
|
||||
/// are known ahead of time.
|
||||
///
|
||||
/// Most `Enumerable` definitions for Rust enum types will be
|
||||
/// `EnumDef::Static`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A statically defined enum
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Valuable, Enumerable, EnumDef};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum MyEnum {
|
||||
/// Foo,
|
||||
/// Bar(u32),
|
||||
/// }
|
||||
///
|
||||
/// let my_enum = MyEnum::Bar(123);
|
||||
///
|
||||
/// let variants = match my_enum.definition() {
|
||||
/// EnumDef::Static { name, variants, .. } => {
|
||||
/// assert_eq!("MyEnum", name);
|
||||
/// variants
|
||||
/// }
|
||||
/// _ => unreachable!(),
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(2, variants.len());
|
||||
/// assert_eq!("Foo", variants[0].name());
|
||||
/// assert_eq!("Bar", variants[1].name());
|
||||
/// ```
|
||||
#[non_exhaustive]
|
||||
Static {
|
||||
/// The enum's name
|
||||
name: &'static str,
|
||||
|
||||
/// The enum's variants
|
||||
variants: &'static [VariantDef<'static>],
|
||||
},
|
||||
|
||||
/// The enum is dynamically-defined, not all variants and fields are known
|
||||
/// ahead of time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// The enum variant is tracked as a string
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Enumerable, EnumDef, Fields, VariantDef, Valuable, Value, Variant, Visit};
|
||||
///
|
||||
/// /// A dynamic enum
|
||||
/// struct DynEnum {
|
||||
/// // The enum name
|
||||
/// name: String,
|
||||
///
|
||||
/// // The current variant
|
||||
/// variant: String,
|
||||
/// }
|
||||
///
|
||||
/// impl Valuable for DynEnum {
|
||||
/// fn as_value(&self) -> Value<'_> {
|
||||
/// Value::Enumerable(self)
|
||||
/// }
|
||||
///
|
||||
/// fn visit(&self, _visit: &mut dyn Visit) {
|
||||
/// // No variant fields, so there is nothing to call here.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Enumerable for DynEnum {
|
||||
/// fn definition(&self) -> EnumDef<'_> {
|
||||
/// EnumDef::new_dynamic(&self.name, &[])
|
||||
/// }
|
||||
///
|
||||
/// fn variant(&self) -> Variant<'_> {
|
||||
/// Variant::Dynamic(VariantDef::new(&self.variant, Fields::Unnamed(0)))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[non_exhaustive]
|
||||
Dynamic {
|
||||
/// The enum's name
|
||||
name: &'a str,
|
||||
|
||||
/// The enum's variants
|
||||
variants: &'a [VariantDef<'a>],
|
||||
},
|
||||
}
|
||||
|
||||
/// An enum variant definition.
|
||||
///
|
||||
/// Included with [`EnumDef`] returned by [`Enumerable::definition()`],
|
||||
/// `VariantDef` provides the caller with information about a specific variant.
|
||||
#[derive(Debug)]
|
||||
pub struct VariantDef<'a> {
|
||||
/// Variant name
|
||||
name: &'a str,
|
||||
|
||||
/// Variant fields
|
||||
fields: Fields<'a>,
|
||||
}
|
||||
|
||||
/// An enum variant
|
||||
///
|
||||
/// Returned by [`Enumerable::variant()`], `Variant` represents a single enum
|
||||
/// variant.
|
||||
#[derive(Debug)]
|
||||
pub enum Variant<'a> {
|
||||
/// The variant is statically defined by the associated enum.
|
||||
Static(&'static VariantDef<'static>),
|
||||
|
||||
/// The variant is dynamically defined and not included as part of
|
||||
/// [`Enumerable::definition()`].
|
||||
Dynamic(VariantDef<'a>),
|
||||
}
|
||||
|
||||
impl<'a> EnumDef<'a> {
|
||||
/// Create a new [`EnumDef::Static`] instance.
|
||||
///
|
||||
/// This should be used when an enum's variants are fixed and known ahead of
|
||||
/// time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{EnumDef, Fields, VariantDef};
|
||||
///
|
||||
/// static VARIANTS: &[VariantDef<'static>] = &[
|
||||
/// VariantDef::new("Bar", Fields::Unnamed(1)),
|
||||
/// ];
|
||||
///
|
||||
/// let def = EnumDef::new_static( "Foo", VARIANTS);
|
||||
/// ```
|
||||
pub const fn new_static(
|
||||
name: &'static str,
|
||||
variants: &'static [VariantDef<'static>],
|
||||
) -> EnumDef<'a> {
|
||||
EnumDef::Static { name, variants }
|
||||
}
|
||||
|
||||
/// Create a new [`EnumDef::Dynamic`] instance.
|
||||
///
|
||||
/// This is used when the enum's variants may vary at runtime.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{EnumDef, Fields, VariantDef};
|
||||
///
|
||||
/// let def = EnumDef::new_dynamic(
|
||||
/// "Foo",
|
||||
/// &[VariantDef::new("Bar", Fields::Unnamed(1))]
|
||||
/// );
|
||||
/// ```
|
||||
pub const fn new_dynamic(name: &'a str, variants: &'a [VariantDef<'a>]) -> EnumDef<'a> {
|
||||
EnumDef::Dynamic { name, variants }
|
||||
}
|
||||
|
||||
/// Returns the enum's name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Enumerable, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum Foo {
|
||||
/// Bar,
|
||||
/// Baz,
|
||||
/// }
|
||||
///
|
||||
/// let def = Foo::Bar.definition();
|
||||
/// assert_eq!("Foo", def.name());
|
||||
/// ```
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
EnumDef::Static { name, .. } => name,
|
||||
EnumDef::Dynamic { name, .. } => name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the enum's variants
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Enumerable, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum Foo {
|
||||
/// Bar,
|
||||
/// Baz,
|
||||
/// }
|
||||
///
|
||||
/// let def = Foo::Bar.definition();
|
||||
/// let variants = def.variants();
|
||||
///
|
||||
/// assert_eq!(2, variants.len());
|
||||
/// assert_eq!("Bar", variants[0].name());
|
||||
/// ```
|
||||
pub fn variants(&self) -> &[VariantDef<'_>] {
|
||||
match self {
|
||||
EnumDef::Static { variants, .. } => variants,
|
||||
EnumDef::Dynamic { variants, .. } => variants,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the enum is [statically defined](EnumDef::Static).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a static enum
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Enumerable, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum Foo {
|
||||
/// Bar,
|
||||
/// Baz,
|
||||
/// }
|
||||
///
|
||||
/// let def = Foo::Bar.definition();
|
||||
/// assert!(def.is_static());
|
||||
/// ```
|
||||
///
|
||||
/// With a dynamic enum
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{EnumDef, Fields, VariantDef};
|
||||
///
|
||||
/// let def = EnumDef::new_dynamic("Foo", &[]);
|
||||
/// assert!(!def.is_static());
|
||||
/// ```
|
||||
pub fn is_static(&self) -> bool {
|
||||
matches!(self, EnumDef::Static { .. })
|
||||
}
|
||||
|
||||
/// Returns `true` if the enum is [dynamically defined](EnumDef::Dynamic).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a static enum
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Enumerable, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum Foo {
|
||||
/// Bar,
|
||||
/// Baz,
|
||||
/// }
|
||||
///
|
||||
/// let def = Foo::Bar.definition();
|
||||
/// assert!(!def.is_dynamic());
|
||||
/// ```
|
||||
///
|
||||
/// With a dynamic enum
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{EnumDef, Fields, VariantDef};
|
||||
///
|
||||
/// let def = EnumDef::new_dynamic("Foo", &[]);
|
||||
/// assert!(def.is_dynamic());
|
||||
/// ```
|
||||
pub fn is_dynamic(&self) -> bool {
|
||||
matches!(self, EnumDef::Dynamic { .. })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VariantDef<'a> {
|
||||
/// Creates a new `VariantDef` instance.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, VariantDef};
|
||||
///
|
||||
/// let def = VariantDef::new("Foo", Fields::Unnamed(2));
|
||||
/// ```
|
||||
pub const fn new(name: &'a str, fields: Fields<'a>) -> VariantDef<'a> {
|
||||
VariantDef { name, fields }
|
||||
}
|
||||
|
||||
/// Returns the variant's name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, VariantDef};
|
||||
///
|
||||
/// let def = VariantDef::new("Foo", Fields::Unnamed(2));
|
||||
/// assert_eq!("Foo", def.name());
|
||||
/// ```
|
||||
pub fn name(&self) -> &str {
|
||||
self.name
|
||||
}
|
||||
|
||||
/// Returns the variant's fields
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, VariantDef};
|
||||
///
|
||||
/// let def = VariantDef::new("Foo", Fields::Unnamed(3));
|
||||
/// assert!(matches!(def.fields(), Fields::Unnamed(_)));
|
||||
/// ```
|
||||
pub fn fields(&self) -> &Fields<'_> {
|
||||
&self.fields
|
||||
}
|
||||
}
|
||||
|
||||
impl Variant<'_> {
|
||||
/// Returns the variant's name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, Variant, VariantDef};
|
||||
///
|
||||
/// static VARIANT: &VariantDef<'static> = &VariantDef::new(
|
||||
/// "Foo", Fields::Unnamed(2));
|
||||
///
|
||||
/// let variant = Variant::Static(VARIANT);
|
||||
/// assert_eq!("Foo", variant.name());
|
||||
/// ```
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
Variant::Static(v) => v.name(),
|
||||
Variant::Dynamic(v) => v.name(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the variant's fields
|
||||
pub fn fields(&self) -> &Fields<'_> {
|
||||
match self {
|
||||
Variant::Static(v) => v.fields(),
|
||||
Variant::Dynamic(v) => v.fields(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the variant has associated named fields.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With named fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, NamedField, Variant, VariantDef};
|
||||
///
|
||||
/// static VARIANT: &VariantDef<'static> = &VariantDef::new(
|
||||
/// "Foo", Fields::Named(&[NamedField::new("hello")]));
|
||||
///
|
||||
/// let variant = Variant::Static(VARIANT);
|
||||
/// assert!(variant.is_named_fields());
|
||||
/// ```
|
||||
///
|
||||
/// With unnamed fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, Variant, VariantDef};
|
||||
///
|
||||
/// static VARIANT: &VariantDef<'static> = &VariantDef::new(
|
||||
/// "Foo", Fields::Unnamed(1));
|
||||
///
|
||||
/// let variant = Variant::Static(VARIANT);
|
||||
/// assert!(!variant.is_named_fields());
|
||||
/// ```
|
||||
pub fn is_named_fields(&self) -> bool {
|
||||
self.fields().is_named()
|
||||
}
|
||||
|
||||
/// Returns `true` if the variant has associated unnamed fields.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With named fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, NamedField, Variant, VariantDef};
|
||||
///
|
||||
/// static VARIANT: &VariantDef<'static> = &VariantDef::new(
|
||||
/// "Foo", Fields::Named(&[NamedField::new("hello")]));
|
||||
///
|
||||
/// let variant = Variant::Static(VARIANT);
|
||||
/// assert!(!variant.is_unnamed_fields());
|
||||
/// ```
|
||||
///
|
||||
/// With unnamed fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, Variant, VariantDef};
|
||||
///
|
||||
/// static VARIANT: &VariantDef<'static> = &VariantDef::new(
|
||||
/// "Foo", Fields::Unnamed(1));
|
||||
///
|
||||
/// let variant = Variant::Static(VARIANT);
|
||||
/// assert!(variant.is_unnamed_fields());
|
||||
/// ```
|
||||
pub fn is_unnamed_fields(&self) -> bool {
|
||||
!self.is_named_fields()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn Enumerable + '_ {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let variant = self.variant();
|
||||
#[cfg(feature = "alloc")]
|
||||
let name = format!("{}::{}", self.definition().name(), variant.name());
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
let name = variant.name();
|
||||
|
||||
if variant.is_named_fields() {
|
||||
struct DebugEnum<'a, 'b> {
|
||||
fmt: fmt::DebugStruct<'a, 'b>,
|
||||
}
|
||||
|
||||
let mut debug = DebugEnum {
|
||||
fmt: fmt.debug_struct(&name),
|
||||
};
|
||||
|
||||
impl Visit for DebugEnum<'_, '_> {
|
||||
fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
for (field, value) in named_values {
|
||||
self.fmt.field(field.name(), value);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, _: Value<'_>) {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
self.visit(&mut debug);
|
||||
|
||||
debug.fmt.finish()
|
||||
} else {
|
||||
struct DebugEnum<'a, 'b> {
|
||||
fmt: fmt::DebugTuple<'a, 'b>,
|
||||
}
|
||||
|
||||
let mut debug = DebugEnum {
|
||||
fmt: fmt.debug_tuple(&name),
|
||||
};
|
||||
|
||||
impl Visit for DebugEnum<'_, '_> {
|
||||
fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
for value in values {
|
||||
self.fmt.field(value);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, _: Value<'_>) {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
self.visit(&mut debug);
|
||||
|
||||
debug.fmt.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! deref {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<T: ?Sized + Enumerable> Enumerable for $ty {
|
||||
fn definition(&self) -> EnumDef<'_> {
|
||||
T::definition(&**self)
|
||||
}
|
||||
|
||||
fn variant(&self) -> Variant<'_> {
|
||||
T::variant(&**self)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
deref! {
|
||||
&T,
|
||||
&mut T,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::boxed::Box<T>,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::rc::Rc<T>,
|
||||
#[cfg(not(valuable_no_atomic_cas))]
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::sync::Arc<T>,
|
||||
}
|
||||
|
||||
static RESULT_VARIANTS: &[VariantDef<'static>] = &[
|
||||
VariantDef::new("Ok", Fields::Unnamed(1)),
|
||||
VariantDef::new("Err", Fields::Unnamed(1)),
|
||||
];
|
||||
|
||||
impl<T, E> Enumerable for Result<T, E>
|
||||
where
|
||||
T: Valuable,
|
||||
E: Valuable,
|
||||
{
|
||||
fn definition(&self) -> EnumDef<'_> {
|
||||
EnumDef::new_static("Result", RESULT_VARIANTS)
|
||||
}
|
||||
|
||||
fn variant(&self) -> Variant<'_> {
|
||||
match self {
|
||||
Ok(_) => Variant::Static(&RESULT_VARIANTS[0]),
|
||||
Err(_) => Variant::Static(&RESULT_VARIANTS[1]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Valuable for Result<T, E>
|
||||
where
|
||||
T: Valuable,
|
||||
E: Valuable,
|
||||
{
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Enumerable(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visitor: &mut dyn Visit) {
|
||||
match self {
|
||||
Ok(val) => visitor.visit_unnamed_fields(&[val.as_value()]),
|
||||
Err(val) => visitor.visit_unnamed_fields(&[val.as_value()]),
|
||||
}
|
||||
}
|
||||
}
|
||||
166
third-party/vendor/valuable/src/field.rs
vendored
Normal file
166
third-party/vendor/valuable/src/field.rs
vendored
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
/// Data stored within a `Structable` or an `Enumerable`.
|
||||
#[derive(Debug)]
|
||||
pub enum Fields<'a> {
|
||||
/// Named fields
|
||||
Named(&'a [NamedField<'a>]),
|
||||
|
||||
/// Unnamed (positional) fields or unit
|
||||
///
|
||||
/// The `usize` value represents the number of fields.
|
||||
Unnamed(usize),
|
||||
}
|
||||
|
||||
/// A named field
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct NamedField<'a>(&'a str);
|
||||
|
||||
impl Fields<'_> {
|
||||
/// Returns `true` if the fields are named.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Named fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Fields;
|
||||
///
|
||||
/// let fields = Fields::Named(&[]);
|
||||
/// assert!(fields.is_named());
|
||||
/// ```
|
||||
///
|
||||
/// Unnamed fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Fields;
|
||||
///
|
||||
/// let fields = Fields::Unnamed(2);
|
||||
/// assert!(!fields.is_named());
|
||||
/// ```
|
||||
pub const fn is_named(&self) -> bool {
|
||||
matches!(self, Fields::Named(..))
|
||||
}
|
||||
|
||||
/// Returns `true` if the fields are unnamed.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Named fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Fields;
|
||||
///
|
||||
/// let fields = Fields::Named(&[]);
|
||||
/// assert!(!fields.is_unnamed());
|
||||
/// ```
|
||||
///
|
||||
/// Unnamed fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Fields;
|
||||
///
|
||||
/// let fields = Fields::Unnamed(3);
|
||||
/// assert!(fields.is_unnamed());
|
||||
/// ```
|
||||
pub const fn is_unnamed(&self) -> bool {
|
||||
matches!(self, Fields::Unnamed(_))
|
||||
}
|
||||
|
||||
/// Returns the number of fields.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Named fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, NamedField};
|
||||
///
|
||||
/// let fields = &[
|
||||
/// NamedField::new("alice"),
|
||||
/// NamedField::new("bob"),
|
||||
/// ];
|
||||
/// let fields = Fields::Named(fields);
|
||||
///
|
||||
/// assert_eq!(fields.len(), 2);
|
||||
/// ```
|
||||
///
|
||||
/// Unnamed fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Fields;
|
||||
///
|
||||
/// let fields = Fields::Unnamed(2);
|
||||
/// assert_eq!(fields.len(), 2);
|
||||
/// ```
|
||||
pub const fn len(&self) -> usize {
|
||||
match self {
|
||||
Self::Named(names) => names.len(),
|
||||
Self::Unnamed(len) => *len,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this set of fields defines no fields.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Named fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, NamedField};
|
||||
///
|
||||
/// let fields = &[
|
||||
/// NamedField::new("alice"),
|
||||
/// NamedField::new("bob"),
|
||||
/// ];
|
||||
/// let non_empty = Fields::Named(fields);
|
||||
///
|
||||
/// let empty = Fields::Named(&[]);
|
||||
///
|
||||
/// assert!(!non_empty.is_empty());
|
||||
/// assert!(empty.is_empty());
|
||||
/// ```
|
||||
///
|
||||
/// Unnamed fields
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Fields;
|
||||
///
|
||||
/// let non_empty = Fields::Unnamed(2);
|
||||
/// let empty = Fields::Unnamed(0);
|
||||
///
|
||||
/// assert!(!non_empty.is_empty());
|
||||
/// assert!(empty.is_empty());
|
||||
/// ```
|
||||
pub const fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> NamedField<'a> {
|
||||
/// Create a new `NamedField` instance with the given name.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::NamedField;
|
||||
///
|
||||
/// let field = NamedField::new("hello");
|
||||
/// assert_eq!("hello", field.name());
|
||||
/// ```
|
||||
pub const fn new(name: &'a str) -> NamedField<'a> {
|
||||
NamedField(name)
|
||||
}
|
||||
|
||||
/// Returns the field name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::NamedField;
|
||||
///
|
||||
/// let field = NamedField::new("hello");
|
||||
/// assert_eq!("hello", field.name());
|
||||
/// ```
|
||||
pub const fn name(&self) -> &str {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
146
third-party/vendor/valuable/src/lib.rs
vendored
Normal file
146
third-party/vendor/valuable/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#![warn(
|
||||
missing_debug_implementations,
|
||||
missing_docs,
|
||||
rust_2018_idioms,
|
||||
unreachable_pub
|
||||
)]
|
||||
//! Valuable provides object-safe value inspection. Use cases include passing
|
||||
//! structured data to trait objects and object-safe serialization.
|
||||
//!
|
||||
//! # Getting started
|
||||
//!
|
||||
//! First, derive [`Valuable`][macro@crate::Valuable] on your types.
|
||||
//!
|
||||
//! ```
|
||||
//! use valuable::Valuable;
|
||||
//!
|
||||
//! #[derive(Valuable)]
|
||||
//! struct HelloWorld {
|
||||
//! message: Message,
|
||||
//! }
|
||||
//!
|
||||
//! #[derive(Valuable)]
|
||||
//! enum Message {
|
||||
//! HelloWorld,
|
||||
//! Custom(String),
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Then, implement a [visitor][Visit] to inspect the data.
|
||||
//!
|
||||
//! ```
|
||||
//! use valuable::{NamedValues, Value, Valuable, Visit};
|
||||
//!
|
||||
//! struct Print;
|
||||
//!
|
||||
//! impl Visit for Print {
|
||||
//! fn visit_value(&mut self, value: Value<'_>) {
|
||||
//! match value {
|
||||
//! Value::Structable(v) => {
|
||||
//! println!("struct {}", v.definition().name());
|
||||
//! v.visit(self);
|
||||
//! }
|
||||
//! Value::Enumerable(v) => {
|
||||
//! println!("enum {}::{}", v.definition().name(), v.variant().name());
|
||||
//! v.visit(self);
|
||||
//! }
|
||||
//! Value::Listable(v) => {
|
||||
//! println!("list");
|
||||
//! v.visit(self);
|
||||
//! }
|
||||
//! Value::Mappable(v) => {
|
||||
//! println!("map");
|
||||
//! v.visit(self);
|
||||
//! }
|
||||
//! _ => {
|
||||
//! println!("value {:?}", value);
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn visit_named_fields(&mut self, named_fields: &NamedValues<'_>) {
|
||||
//! for (field, value) in named_fields.iter() {
|
||||
//! println!("named field {}", field.name());
|
||||
//! value.visit(self);
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
//! for value in values {
|
||||
//! value.visit(self);
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
|
||||
//! println!("key / value");
|
||||
//! key.visit(self);
|
||||
//! value.visit(self);
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Then, use the visitor to visit the value.
|
||||
//!
|
||||
//! ```
|
||||
//! # use valuable::*;
|
||||
//! # #[derive(Valuable)]
|
||||
//! # struct HelloWorld { message: Message }
|
||||
//! # #[derive(Valuable)]
|
||||
//! # enum Message { HelloWorld }
|
||||
//! # struct Print;
|
||||
//! # impl Visit for Print {
|
||||
//! # fn visit_value(&mut self, _: Value<'_>) {}
|
||||
//! # }
|
||||
//! let hello_world = HelloWorld { message: Message::HelloWorld };
|
||||
//! hello_world.visit(&mut Print);
|
||||
//! ```
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg, doc_cfg_hide))]
|
||||
#![cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg_hide(
|
||||
not(valuable_no_atomic_cas),
|
||||
not(valuable_no_atomic),
|
||||
not(valuable_no_atomic_64)
|
||||
))
|
||||
)]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
mod enumerable;
|
||||
pub use enumerable::{EnumDef, Enumerable, Variant, VariantDef};
|
||||
|
||||
mod field;
|
||||
pub use field::{Fields, NamedField};
|
||||
|
||||
mod listable;
|
||||
pub use listable::Listable;
|
||||
|
||||
mod mappable;
|
||||
pub use mappable::Mappable;
|
||||
|
||||
mod named_values;
|
||||
pub use named_values::NamedValues;
|
||||
|
||||
mod slice;
|
||||
pub use slice::Slice;
|
||||
|
||||
mod structable;
|
||||
pub use structable::{StructDef, Structable};
|
||||
|
||||
mod tuplable;
|
||||
pub use tuplable::{Tuplable, TupleDef};
|
||||
|
||||
mod valuable;
|
||||
pub use crate::valuable::Valuable;
|
||||
|
||||
mod value;
|
||||
pub use value::Value;
|
||||
|
||||
mod visit;
|
||||
pub use visit::{visit, Visit};
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
pub use valuable_derive::Valuable;
|
||||
257
third-party/vendor/valuable/src/listable.rs
vendored
Normal file
257
third-party/vendor/valuable/src/listable.rs
vendored
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
use crate::*;
|
||||
|
||||
use core::fmt;
|
||||
|
||||
/// A list-like [`Valuable`] sub-type.
|
||||
///
|
||||
/// Implemented by [`Valuable`] types that have a list-like shape. This includes
|
||||
/// [`Vec`] and other Rust [collection] types. `Listable` types may or may not
|
||||
/// store items in contiguous memory. Any type that implements [`IntoIterator`]
|
||||
/// may implement `Listable`. Values that implement `Listable` must return
|
||||
/// [`Value::Listable`] from their [`Valuable::as_value`] implementation.
|
||||
///
|
||||
/// [collection]: https://doc.rust-lang.org/stable/std/collections/index.html
|
||||
///
|
||||
/// # Inspecting
|
||||
///
|
||||
/// Inspecting `Listable` items is done by visiting the collection. When
|
||||
/// visiting a `Listable`, contained values are either passed one-by-one by
|
||||
/// repeatedly calling [`visit_value()`] or all at once by calling
|
||||
/// [`visit_primitive_slice()`]. The [`visit_primitive_slice()`] method has
|
||||
/// lower overhead but can only be used when the `Listable` type contains
|
||||
/// primitive values.
|
||||
///
|
||||
/// See [`Visit`] documentation for more details.
|
||||
///
|
||||
/// # Implementing
|
||||
///
|
||||
/// If the type stores values in slices internally, then those slices are passed
|
||||
/// to [`Valuable::visit_slice`], which handles calling
|
||||
/// [`visit_primitive_slice()`] if possible.
|
||||
///
|
||||
/// [`visit_value()`]: Visit::visit_value
|
||||
/// [`visit_primitive_slice()`]: Visit::visit_primitive_slice
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Listable, Valuable, Value, Visit};
|
||||
///
|
||||
/// struct MyCollection<T> {
|
||||
/// chunks: Vec<Vec<T>>,
|
||||
/// }
|
||||
///
|
||||
/// impl<T: Valuable> Valuable for MyCollection<T> {
|
||||
/// fn as_value(&self) -> Value<'_> {
|
||||
/// Value::Listable(self)
|
||||
/// }
|
||||
///
|
||||
/// fn visit(&self, visit: &mut dyn Visit) {
|
||||
/// for chunk in &self.chunks {
|
||||
/// // Handles visiting the slice
|
||||
/// Valuable::visit_slice(chunk, visit);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl<T: Valuable> Listable for MyCollection<T> {
|
||||
/// fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
/// let len = self.chunks.iter().map(|chunk| chunk.len()).sum();
|
||||
/// (len, Some(len))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait Listable: Valuable {
|
||||
/// Returns the bounds on the remaining length of the `Listable`.
|
||||
///
|
||||
/// Specifically, `size_hint()` returns a tuple where the first element
|
||||
/// is the lower bound, and the second element is the upper bound.
|
||||
///
|
||||
/// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`.
|
||||
/// A [`None`] here means that either there is no known upper bound, or the
|
||||
/// upper bound is larger than [`usize`].
|
||||
///
|
||||
/// # Implementation notes
|
||||
///
|
||||
/// It is not enforced that a `Listable` implementation yields the declared
|
||||
/// number of elements. A buggy iterator may yield less than the lower bound
|
||||
/// or more than the upper bound of elements.
|
||||
///
|
||||
/// `size_hint()` is primarily intended to be used for optimizations such as
|
||||
/// reserving space for the elements of the `Listable`, but must not be
|
||||
/// trusted to e.g., omit bounds checks in unsafe code. An incorrect
|
||||
/// implementation of `size_hint()` should not lead to memory safety
|
||||
/// violations.
|
||||
///
|
||||
/// That said, the implementation should provide a correct estimation,
|
||||
/// because otherwise it would be a violation of the trait's protocol.
|
||||
///
|
||||
/// [`usize`]: type@usize
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Listable;
|
||||
///
|
||||
/// let a = vec![1, 2, 3];
|
||||
///
|
||||
/// assert_eq!((3, Some(3)), a.size_hint());
|
||||
/// ```
|
||||
fn size_hint(&self) -> (usize, Option<usize>);
|
||||
}
|
||||
|
||||
macro_rules! deref {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<T: ?Sized + Listable> Listable for $ty {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
T::size_hint(&**self)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
deref! {
|
||||
&T,
|
||||
&mut T,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::boxed::Box<T>,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::rc::Rc<T>,
|
||||
#[cfg(not(valuable_no_atomic_cas))]
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::sync::Arc<T>,
|
||||
}
|
||||
|
||||
macro_rules! slice {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
($($generics:tt)*) $ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<$($generics)*> Valuable for $ty {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Listable(self as &dyn Listable)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
T::visit_slice(self, visit);
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$attrs])*
|
||||
impl<$($generics)*> Listable for $ty {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len(), Some(self.len()))
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
slice! {
|
||||
(T: Valuable) &'_ [T],
|
||||
#[cfg(feature = "alloc")]
|
||||
(T: Valuable) alloc::boxed::Box<[T]>,
|
||||
#[cfg(feature = "alloc")]
|
||||
(T: Valuable) alloc::rc::Rc<[T]>,
|
||||
#[cfg(not(valuable_no_atomic_cas))]
|
||||
#[cfg(feature = "alloc")]
|
||||
(T: Valuable) alloc::sync::Arc<[T]>,
|
||||
(T: Valuable, const N: usize) [T; N],
|
||||
#[cfg(feature = "alloc")]
|
||||
(T: Valuable) alloc::vec::Vec<T>,
|
||||
}
|
||||
|
||||
macro_rules! collection {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
($($generics:tt)*) $ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<$($generics)*> Valuable for $ty {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Listable(self as &dyn Listable)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
for value in self.iter() {
|
||||
visit.visit_value(value.as_value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$attrs])*
|
||||
impl<$($generics)*> Listable for $ty {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len(), Some(self.len()))
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
collection! {
|
||||
#[cfg(feature = "alloc")]
|
||||
(T: Valuable) alloc::collections::LinkedList<T>,
|
||||
#[cfg(feature = "alloc")]
|
||||
(T: Valuable + Ord) alloc::collections::BinaryHeap<T>,
|
||||
#[cfg(feature = "alloc")]
|
||||
(T: Valuable + Ord) alloc::collections::BTreeSet<T>,
|
||||
#[cfg(feature = "std")]
|
||||
(T: Valuable + Eq + std::hash::Hash, H: std::hash::BuildHasher) std::collections::HashSet<T, H>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T: Valuable> Valuable for alloc::collections::VecDeque<T> {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Listable(self as &dyn Listable)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
let (first, second) = self.as_slices();
|
||||
T::visit_slice(first, visit);
|
||||
T::visit_slice(second, visit);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<T: Valuable> Listable for alloc::collections::VecDeque<T> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len(), Some(self.len()))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn Listable + '_ {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
struct DebugListable<'a, 'b> {
|
||||
fmt: fmt::DebugList<'a, 'b>,
|
||||
}
|
||||
|
||||
impl Visit for DebugListable<'_, '_> {
|
||||
fn visit_value(&mut self, value: Value<'_>) {
|
||||
self.fmt.entry(&value);
|
||||
}
|
||||
}
|
||||
|
||||
let mut debug = DebugListable {
|
||||
fmt: fmt.debug_list(),
|
||||
};
|
||||
|
||||
self.visit(&mut debug);
|
||||
debug.fmt.finish()
|
||||
}
|
||||
}
|
||||
191
third-party/vendor/valuable/src/mappable.rs
vendored
Normal file
191
third-party/vendor/valuable/src/mappable.rs
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
use crate::*;
|
||||
|
||||
use core::fmt;
|
||||
|
||||
/// A map-like [`Valuable`] sub-type.
|
||||
///
|
||||
/// Implemented by [`Valuable`] types that have a map-like shape. This includes
|
||||
/// [`HashMap`] and other Rust [collection] types. Values that implement
|
||||
/// `Mappable` must return [`Value::Mappable`] from their [`Value::as_value`]
|
||||
/// implementation.
|
||||
///
|
||||
/// [collection]: https://doc.rust-lang.org/stable/std/collections/index.html
|
||||
///
|
||||
/// # Inspecting
|
||||
///
|
||||
/// Inspecting `Mappable` entries is done by visiting the value. When visiting a
|
||||
/// `Mappable`, contained entries are passed one-by-one to the visitor by
|
||||
/// repeatedly calling [`visit_entry()`].
|
||||
///
|
||||
/// See [`Visit`] documentation for more details.
|
||||
///
|
||||
/// [`visit_entry()`]: Visit::visit_entry
|
||||
/// [`HashMap`]: std::collections::HashMap
|
||||
///
|
||||
/// # Implementing
|
||||
///
|
||||
/// Implementing `Mappable` for a custom map type. The map is represented using
|
||||
/// a `Vec` of key/value pairs.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Mappable, Valuable, Value, Visit};
|
||||
///
|
||||
/// struct MyMap<K, V> {
|
||||
/// entries: Vec<(K, V)>,
|
||||
/// }
|
||||
///
|
||||
/// impl<K: Valuable, V: Valuable> Valuable for MyMap<K, V> {
|
||||
/// fn as_value(&self) -> Value<'_> {
|
||||
/// Value::Mappable(self)
|
||||
/// }
|
||||
///
|
||||
/// fn visit(&self, visit: &mut dyn Visit) {
|
||||
/// for (k, v) in &self.entries {
|
||||
/// visit.visit_entry(k.as_value(), v.as_value());
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl<K: Valuable, V: Valuable> Mappable for MyMap<K, V> {
|
||||
/// fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
/// let len = self.entries.len();
|
||||
/// (len, Some(len))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait Mappable: Valuable {
|
||||
/// Returns the bounds on the remaining length of the `Mappable`.
|
||||
///
|
||||
/// Specifically, `size_hint()` returns a tuple where the first element is
|
||||
/// the lower bound, and the second element is the upper bound.
|
||||
///
|
||||
/// The second half of the tuple that is returned is an
|
||||
/// [`Option`]`<`[`usize`]`>`. A [`None`] here means that either there is no
|
||||
/// known upper bound, or the upper bound is larger than [`usize`].
|
||||
///
|
||||
/// # Implementation notes
|
||||
///
|
||||
/// It is not enforced that a `Mappable` implementation yields the declared
|
||||
/// number of elements. A buggy implementation may yield less than the lower
|
||||
/// bound or more than the upper bound of elements.
|
||||
///
|
||||
/// `size_hint()` is primarily intended to be used for optimizations such as
|
||||
/// reserving space for the elements of the `Mappable`, but must not be
|
||||
/// trusted to e.g., omit bounds checks in unsafe code. An incorrect
|
||||
/// implementation of `size_hint()` should not lead to memory safety
|
||||
/// violations.
|
||||
///
|
||||
/// That said, the implementation should provide a correct estimation,
|
||||
/// because otherwise it would be a violation of the trait's protocol.
|
||||
///
|
||||
/// [`usize`]: type@usize
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Mappable;
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// let mut map = HashMap::new();
|
||||
/// map.insert("one", 1);
|
||||
/// map.insert("two", 2);
|
||||
/// map.insert("three", 3);
|
||||
///
|
||||
/// assert_eq!((3, Some(3)), map.size_hint());
|
||||
/// ```
|
||||
fn size_hint(&self) -> (usize, Option<usize>);
|
||||
}
|
||||
|
||||
macro_rules! deref {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<T: ?Sized + Mappable> Mappable for $ty {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
T::size_hint(&**self)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
deref! {
|
||||
&T,
|
||||
&mut T,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::boxed::Box<T>,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::rc::Rc<T>,
|
||||
#[cfg(not(valuable_no_atomic_cas))]
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::sync::Arc<T>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<K: Valuable, V: Valuable> Valuable for std::collections::HashMap<K, V> {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Mappable(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
for (key, value) in self.iter() {
|
||||
visit.visit_entry(key.as_value(), value.as_value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<K: Valuable, V: Valuable> Mappable for std::collections::HashMap<K, V> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter().size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<K: Valuable, V: Valuable> Valuable for alloc::collections::BTreeMap<K, V> {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Mappable(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
for (key, value) in self.iter() {
|
||||
visit.visit_entry(key.as_value(), value.as_value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<K: Valuable, V: Valuable> Mappable for alloc::collections::BTreeMap<K, V> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter().size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn Mappable + '_ {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
struct DebugMappable<'a, 'b> {
|
||||
fmt: fmt::DebugMap<'a, 'b>,
|
||||
}
|
||||
|
||||
impl Visit for DebugMappable<'_, '_> {
|
||||
fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
|
||||
self.fmt.entry(&key, &value);
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, _: Value<'_>) {}
|
||||
}
|
||||
|
||||
let mut debug = DebugMappable {
|
||||
fmt: fmt.debug_map(),
|
||||
};
|
||||
self.visit(&mut debug);
|
||||
debug.fmt.finish()
|
||||
}
|
||||
}
|
||||
222
third-party/vendor/valuable/src/named_values.rs
vendored
Normal file
222
third-party/vendor/valuable/src/named_values.rs
vendored
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
use core::iter::{self, FusedIterator};
|
||||
|
||||
use crate::field::*;
|
||||
use crate::*;
|
||||
|
||||
/// Set of values from a `Structable` or `Enumerable` with named fields.
|
||||
#[derive(Debug)]
|
||||
pub struct NamedValues<'a> {
|
||||
fields: &'a [NamedField<'a>],
|
||||
values: &'a [Value<'a>],
|
||||
}
|
||||
|
||||
impl<'a> NamedValues<'a> {
|
||||
/// Create a new `NamedValues` instance.
|
||||
///
|
||||
/// Both `fields` and `values` must be the same length.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// The method panics if `fields` and `values` are different lengths.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedField, NamedValues, Value};
|
||||
///
|
||||
/// let fields = [
|
||||
/// NamedField::new("foo"),
|
||||
/// NamedField::new("bar")
|
||||
/// ];
|
||||
/// let values = [
|
||||
/// Value::U32(123),
|
||||
/// Value::U32(456),
|
||||
/// ];
|
||||
///
|
||||
/// let named_values = NamedValues::new(&fields, &values);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// named_values.get(&fields[0]).unwrap().as_u32(),
|
||||
/// Some(123));
|
||||
/// ```
|
||||
pub fn new(fields: &'a [NamedField<'a>], values: &'a [Value<'a>]) -> NamedValues<'a> {
|
||||
assert!(
|
||||
fields.len() == values.len(),
|
||||
"`fields` and `values` must be the same length"
|
||||
);
|
||||
NamedValues { fields, values }
|
||||
}
|
||||
|
||||
/// Get a value using a `NamedField` reference.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedField, NamedValues, Value};
|
||||
///
|
||||
/// let fields = [
|
||||
/// NamedField::new("foo"),
|
||||
/// NamedField::new("bar")
|
||||
/// ];
|
||||
/// let values = [
|
||||
/// Value::U32(123),
|
||||
/// Value::U32(456),
|
||||
/// ];
|
||||
///
|
||||
/// let named_values = NamedValues::new(&fields, &values);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// named_values.get(&fields[0]).unwrap().as_u32(),
|
||||
/// Some(123));
|
||||
/// ```
|
||||
pub fn get(&self, field: &NamedField<'_>) -> Option<&Value<'_>> {
|
||||
use core::mem;
|
||||
|
||||
let idx = (field as *const _ as usize - &self.fields[0] as *const _ as usize)
|
||||
/ mem::size_of::<NamedField<'_>>();
|
||||
self.values.get(idx)
|
||||
}
|
||||
|
||||
/// Get a value using string.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedField, NamedValues, Value};
|
||||
///
|
||||
/// let fields = [
|
||||
/// NamedField::new("foo"),
|
||||
/// NamedField::new("bar")
|
||||
/// ];
|
||||
/// let values = [
|
||||
/// Value::U32(123),
|
||||
/// Value::U32(456),
|
||||
/// ];
|
||||
///
|
||||
/// let named_values = NamedValues::new(&fields, &values);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// named_values.get_by_name("foo").unwrap().as_u32(),
|
||||
/// Some(123));
|
||||
/// ```
|
||||
pub fn get_by_name(&self, name: impl AsRef<str>) -> Option<&Value<'_>> {
|
||||
let name = name.as_ref();
|
||||
|
||||
for (index, field) in self.fields.iter().enumerate() {
|
||||
if field.name() == name {
|
||||
return Some(&self.values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Iterate all name-value pairs.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedField, NamedValues, Value};
|
||||
///
|
||||
/// let fields = [
|
||||
/// NamedField::new("foo"),
|
||||
/// NamedField::new("bar")
|
||||
/// ];
|
||||
/// let values = [
|
||||
/// Value::U32(123),
|
||||
/// Value::U32(456),
|
||||
/// ];
|
||||
///
|
||||
/// let named_values = NamedValues::new(&fields, &values);
|
||||
///
|
||||
/// for (field, value) in named_values.iter() {
|
||||
/// println!("{:?}: {:?}", field, value);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn iter<'b>(&'b self) -> Iter<'a, 'b> {
|
||||
Iter {
|
||||
iter: self.fields.iter().enumerate(),
|
||||
values: self.values,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the length of fields.
|
||||
pub fn len(&self) -> usize {
|
||||
self.fields.len()
|
||||
}
|
||||
|
||||
/// Returns `true` if fields have a length of 0.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.fields.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> IntoIterator for &'b NamedValues<'a> {
|
||||
type Item = (&'b NamedField<'a>, &'b Value<'a>);
|
||||
type IntoIter = Iter<'a, 'b>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator of name-value pairs contained by [`NamedValues`].
|
||||
///
|
||||
/// Instances are created by the [`iter()`][NamedValues::iter] method on
|
||||
/// [`NamedValues`]. See its documentation for more.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedField, NamedValues, Value};
|
||||
///
|
||||
/// let fields = [
|
||||
/// NamedField::new("foo"),
|
||||
/// NamedField::new("bar")
|
||||
/// ];
|
||||
/// let values = [
|
||||
/// Value::U32(123),
|
||||
/// Value::U32(456),
|
||||
/// ];
|
||||
///
|
||||
/// let named_values = NamedValues::new(&fields, &values);
|
||||
///
|
||||
/// for (field, value) in named_values.iter() {
|
||||
/// println!("{:?}: {:?}", field, value);
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct Iter<'a, 'b> {
|
||||
iter: iter::Enumerate<core::slice::Iter<'b, NamedField<'a>>>,
|
||||
values: &'a [Value<'a>],
|
||||
}
|
||||
|
||||
impl<'a, 'b> Iterator for Iter<'a, 'b> {
|
||||
type Item = (&'b NamedField<'a>, &'b Value<'a>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter
|
||||
.next()
|
||||
.map(move |(i, field)| (field, &self.values[i]))
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Iter<'_, '_> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.iter
|
||||
.next_back()
|
||||
.map(move |(i, field)| (field, &self.values[i]))
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Iter<'_, '_> {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl FusedIterator for Iter<'_, '_> {}
|
||||
428
third-party/vendor/valuable/src/slice.rs
vendored
Normal file
428
third-party/vendor/valuable/src/slice.rs
vendored
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
use crate::*;
|
||||
|
||||
use core::fmt;
|
||||
use core::iter::FusedIterator;
|
||||
|
||||
macro_rules! slice {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$variant:ident($ty:ty),
|
||||
)*
|
||||
) => {
|
||||
/// A slice containing primitive values.
|
||||
///
|
||||
/// The `Slice` enum is used to pass multiple primitive-values to the
|
||||
/// [visitor][`Visit`]. This is used as an optimization when visiting
|
||||
/// [`Listable`] types to avoid a dynamic dispatch call to [`Visit`] for
|
||||
/// each element in the collection.
|
||||
///
|
||||
/// `Slice` instances are usually not created explicitly. Instead, they
|
||||
/// are created when calling [`Valuable::visit_slice()`].
|
||||
#[non_exhaustive]
|
||||
pub enum Slice<'a> {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant(&'a [$ty]),
|
||||
)*
|
||||
}
|
||||
|
||||
/// [`Slice`] iterator
|
||||
///
|
||||
/// Instances are created by the [`iter()`][Slice::iter] method on
|
||||
/// [`Slice`]. See its documentation for more.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let slice = Slice::U32(&[1, 1, 2, 3, 5]);
|
||||
///
|
||||
/// for value in slice.iter() {
|
||||
/// println!("{:?}", value);
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct Iter<'a>(IterKind<'a>);
|
||||
|
||||
#[derive(Debug)]
|
||||
enum IterKind<'a> {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant(core::slice::Iter<'a, $ty>),
|
||||
)*
|
||||
}
|
||||
|
||||
impl<'a> Slice<'a> {
|
||||
/// Returns the number of elements in the slice
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let slice = Slice::U32(&[1, 1, 2, 3, 5]);
|
||||
/// assert_eq!(5, slice.len());
|
||||
/// ```
|
||||
pub fn len(&self) -> usize {
|
||||
#[allow(unused_doc_comments)]
|
||||
match self {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
Slice::$variant(s) => s.len(),
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Returns `true` if the slice is not empty.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let slice = Slice::U32(&[1, 1, 2, 3, 5]);
|
||||
/// assert!(!slice.is_empty());
|
||||
/// ```
|
||||
/// ```
|
||||
/// # use valuable::Slice;
|
||||
/// let slice = Slice::U32(&[]);
|
||||
/// assert!(slice.is_empty());
|
||||
/// ```
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
/// Returns an iterator over the slice.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let slice = Slice::U32(&[1, 1, 2, 3, 5]);
|
||||
///
|
||||
/// for value in slice.iter() {
|
||||
/// println!("{:?}", value);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn iter(&self) -> Iter<'a> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for Slice<'a> {
|
||||
type Item = Value<'a>;
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
(&self).into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'_ Slice<'a> {
|
||||
type Item = Value<'a>;
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
#[allow(unused_doc_comments)]
|
||||
Iter(match self {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
Slice::$variant(s) => IterKind::$variant(s.iter()),
|
||||
)*
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Slice<'_> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use Slice::*;
|
||||
|
||||
let mut d = fmt.debug_list();
|
||||
|
||||
#[allow(unused_doc_comments)]
|
||||
match *self {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant(v) => d.entries(v),
|
||||
)*
|
||||
};
|
||||
|
||||
d.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = Value<'a>;
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
use IterKind::*;
|
||||
|
||||
#[allow(unused_doc_comments)]
|
||||
match &self.0 {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant(v) => v.size_hint(),
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&mut self) -> Option<Value<'a>> {
|
||||
use IterKind::*;
|
||||
|
||||
#[allow(unused_doc_comments)]
|
||||
match &mut self.0 {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant(v) => v.next().map(Valuable::as_value),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Iter<'_> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
use IterKind::*;
|
||||
|
||||
#[allow(unused_doc_comments)]
|
||||
match &mut self.0 {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant(v) => v.next_back().map(Valuable::as_value),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Iter<'_> {
|
||||
fn len(&self) -> usize {
|
||||
use IterKind::*;
|
||||
|
||||
#[allow(unused_doc_comments)]
|
||||
match &self.0 {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant(v) => v.len(),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FusedIterator for Iter<'_> {}
|
||||
}
|
||||
}
|
||||
|
||||
slice! {
|
||||
/// A slice containing `bool` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::Bool(&[true, true, false]);
|
||||
/// ```
|
||||
Bool(bool),
|
||||
|
||||
/// A slice containing `char` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::Char(&['a', 'b', 'c']);
|
||||
/// ```
|
||||
Char(char),
|
||||
|
||||
/// A slice containing `f32` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::F32(&[3.1415, 2.71828]);
|
||||
/// ```
|
||||
F32(f32),
|
||||
|
||||
/// A slice containing `f64` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::F64(&[3.1415, 2.71828]);
|
||||
/// ```
|
||||
F64(f64),
|
||||
|
||||
/// A slice containing `i8` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::I8(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
I8(i8),
|
||||
|
||||
/// A slice containing `i16` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::I16(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
I16(i16),
|
||||
|
||||
/// A slice containing `I32` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::I32(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
I32(i32),
|
||||
|
||||
/// A slice containing `I64` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::I64(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
I64(i64),
|
||||
|
||||
/// A slice containing `I128` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::I128(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
I128(i128),
|
||||
|
||||
/// A slice containing `isize` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::Isize(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
Isize(isize),
|
||||
|
||||
/// A slice containing `str` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::Str(&["foo", "bar", "baz"]);
|
||||
/// ```
|
||||
Str(&'a str),
|
||||
|
||||
/// A slice containing `String` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::String(&["foo".to_string(), "bar".to_string()]);
|
||||
/// ```
|
||||
#[cfg(feature = "alloc")]
|
||||
String(alloc::string::String),
|
||||
|
||||
/// A slice containing `u8` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::U8(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
U8(u8),
|
||||
|
||||
/// A slice containing `u16` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::U16(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
U16(u16),
|
||||
|
||||
/// A slice containing `u32` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::U32(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
U32(u32),
|
||||
|
||||
/// A slice containing `u64` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::U64(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
U64(u64),
|
||||
|
||||
/// A slice containing `u128` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::U128(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
U128(u128),
|
||||
|
||||
/// A slice containing `usize` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::Usize(&[1, 1, 2, 3, 5]);
|
||||
/// ```
|
||||
Usize(usize),
|
||||
|
||||
/// A slice containing `()` values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Slice;
|
||||
///
|
||||
/// let v = Slice::Unit(&[(), (), ()]);
|
||||
/// ```
|
||||
Unit(()),
|
||||
}
|
||||
496
third-party/vendor/valuable/src/structable.rs
vendored
Normal file
496
third-party/vendor/valuable/src/structable.rs
vendored
Normal file
|
|
@ -0,0 +1,496 @@
|
|||
use crate::field::*;
|
||||
use crate::*;
|
||||
|
||||
use core::fmt;
|
||||
|
||||
/// A struct-like [`Valuable`] sub-type.
|
||||
///
|
||||
/// Implemented by [`Valuable`] types that have a struct-like shape. Fields may
|
||||
/// be named or unnamed (tuple). Values that implement `Structable` must return
|
||||
/// [`Value::Structable`] from their [`Valuable::as_value`] implementation.
|
||||
///
|
||||
/// # Inspecting
|
||||
///
|
||||
/// Inspecting fields contained by a `Structable` instance is done by visiting
|
||||
/// the struct. When visiting a `Structable`, either the `visit_named_fields()`
|
||||
/// or the `visit_unnamed_fields()` methods of `Visit` are called. Each method
|
||||
/// may be called multiple times per `Structable`, but the two methods are never
|
||||
/// mixed.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedValues, Valuable, Value, Visit};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct MyStruct {
|
||||
/// foo: u32,
|
||||
/// bar: u32,
|
||||
/// }
|
||||
///
|
||||
/// struct PrintFields;
|
||||
///
|
||||
/// impl Visit for PrintFields {
|
||||
/// fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
/// for (field, value) in named_values.iter() {
|
||||
/// println!("{}: {:?}", field.name(), value);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// match value {
|
||||
/// Value::Structable(v) => v.visit(self),
|
||||
/// _ => {} // do nothing for other types
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = MyStruct {
|
||||
/// foo: 123,
|
||||
/// bar: 456,
|
||||
/// };
|
||||
///
|
||||
/// valuable::visit(&my_struct, &mut PrintFields);
|
||||
/// ```
|
||||
///
|
||||
/// If the struct is **statically** defined, then all fields are known ahead of
|
||||
/// time and may be accessed via the [`StructDef`] instance returned by
|
||||
/// [`definition()`]. [`NamedField`] instances returned by [`definition()`]
|
||||
/// maybe used to efficiently extract specific field values.
|
||||
///
|
||||
/// # Implementing
|
||||
///
|
||||
/// Implementing `Structable` is usually done by adding `#[derive(Valuable)]` to
|
||||
/// a Rust `struct` definition.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, Valuable, Structable, StructDef};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct MyStruct {
|
||||
/// foo: &'static str,
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = MyStruct { foo: "Hello" };
|
||||
/// let fields = match my_struct.definition() {
|
||||
/// StructDef::Static { name, fields, .. } => {
|
||||
/// assert_eq!("MyStruct", name);
|
||||
/// fields
|
||||
/// }
|
||||
/// _ => unreachable!(),
|
||||
/// };
|
||||
///
|
||||
/// match fields {
|
||||
/// Fields::Named(named_fields) => {
|
||||
/// assert_eq!(1, named_fields.len());
|
||||
/// assert_eq!("foo", named_fields[0].name());
|
||||
/// }
|
||||
/// _ => unreachable!(),
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`definition()`]: Structable::definition()
|
||||
pub trait Structable: Valuable {
|
||||
/// Returns the struct's definition.
|
||||
///
|
||||
/// See [`StructDef`] documentation for more details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Structable, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct MyStruct {
|
||||
/// foo: u32,
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = MyStruct {
|
||||
/// foo: 123,
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!("MyStruct", my_struct.definition().name());
|
||||
fn definition(&self) -> StructDef<'_>;
|
||||
}
|
||||
|
||||
/// A struct's name, fields, and other struct-level information.
|
||||
///
|
||||
/// Returned by [`Structable::definition()`], `StructDef` provides the caller
|
||||
/// with information about the struct's definition.
|
||||
///
|
||||
/// [`Structable::definition()`]: Structable::definition
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum StructDef<'a> {
|
||||
/// The struct is statically-defined, all fields are known ahead of time.
|
||||
///
|
||||
/// Most `Structable` definitions for Rust struct types will be
|
||||
/// `StructDef::Static`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A statically defined struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, Valuable, Structable, StructDef};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct MyStruct {
|
||||
/// foo: &'static str,
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = MyStruct { foo: "Hello" };
|
||||
/// let fields = match my_struct.definition() {
|
||||
/// StructDef::Static { name, fields, ..} => {
|
||||
/// assert_eq!("MyStruct", name);
|
||||
/// fields
|
||||
/// }
|
||||
/// _ => unreachable!(),
|
||||
/// };
|
||||
///
|
||||
/// match fields {
|
||||
/// Fields::Named(named_fields) => {
|
||||
/// assert_eq!(1, named_fields.len());
|
||||
/// assert_eq!("foo", named_fields[0].name());
|
||||
/// }
|
||||
/// _ => unreachable!(),
|
||||
/// }
|
||||
/// ```
|
||||
#[non_exhaustive]
|
||||
Static {
|
||||
/// The struct's name.
|
||||
name: &'static str,
|
||||
|
||||
/// The struct's fields.
|
||||
fields: Fields<'static>,
|
||||
},
|
||||
|
||||
/// The struct is dynamically-defined, not all fields are known ahead of
|
||||
/// time.
|
||||
///
|
||||
/// A dynamically-defined struct **could** be represented using
|
||||
/// [`Mappable`], though, using `Structable` offers benefits in a couple of
|
||||
/// cases. For example, when serializing a `Value`, some formats will
|
||||
/// serialize maps and structs differently. In this case, differentiating
|
||||
/// the two is required. There also are times when **some** struct fields
|
||||
/// are known statically, but not all of them (see second example).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// The struct stores field values in a `HashMap`.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, NamedField, NamedValues, Structable, StructDef, Value, Valuable, Visit};
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// /// A dynamic struct
|
||||
/// struct Dyn {
|
||||
/// // The struct name
|
||||
/// name: String,
|
||||
///
|
||||
/// // Named values.
|
||||
/// values: HashMap<String, Box<dyn Valuable>>,
|
||||
/// }
|
||||
///
|
||||
/// impl Valuable for Dyn {
|
||||
/// fn as_value(&self) -> Value<'_> {
|
||||
/// Value::Structable(self)
|
||||
/// }
|
||||
///
|
||||
/// fn visit(&self, visit: &mut dyn Visit) {
|
||||
/// // This could be optimized to batch some.
|
||||
/// for (field, value) in self.values.iter() {
|
||||
/// visit.visit_named_fields(&NamedValues::new(
|
||||
/// &[NamedField::new(field)],
|
||||
/// &[value.as_value()],
|
||||
/// ));
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Structable for Dyn {
|
||||
/// fn definition(&self) -> StructDef<'_> {
|
||||
/// StructDef::new_dynamic(&self.name, Fields::Named(&[]))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Some fields are known statically.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Fields, NamedField, NamedValues, Structable, StructDef, Value, Valuable, Visit};
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// struct HalfStatic {
|
||||
/// foo: u32,
|
||||
/// bar: u32,
|
||||
/// extra_values: HashMap<String, Box<dyn Valuable>>,
|
||||
/// }
|
||||
///
|
||||
/// impl Valuable for HalfStatic {
|
||||
/// fn as_value(&self) -> Value<'_> {
|
||||
/// Value::Structable(self)
|
||||
/// }
|
||||
///
|
||||
/// fn visit(&self, visit: &mut dyn Visit) {
|
||||
/// // First, visit static fields
|
||||
/// visit.visit_named_fields(&NamedValues::new(
|
||||
/// FIELDS,
|
||||
/// &[self.foo.as_value(), self.bar.as_value()],
|
||||
/// ));
|
||||
///
|
||||
/// // This could be optimized to batch some.
|
||||
/// for (field, value) in self.extra_values.iter() {
|
||||
/// visit.visit_named_fields(&NamedValues::new(
|
||||
/// &[NamedField::new(field)],
|
||||
/// &[value.as_value()],
|
||||
/// ));
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// static FIELDS: &[NamedField<'static>] = &[
|
||||
/// NamedField::new("foo"),
|
||||
/// NamedField::new("bar"),
|
||||
/// ];
|
||||
///
|
||||
/// impl Structable for HalfStatic {
|
||||
/// fn definition(&self) -> StructDef<'_> {
|
||||
/// // Include known fields.
|
||||
/// StructDef::new_dynamic(
|
||||
/// "HalfStatic",
|
||||
/// Fields::Named(FIELDS))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[non_exhaustive]
|
||||
Dynamic {
|
||||
/// The struct's name
|
||||
name: &'a str,
|
||||
|
||||
/// The struct's fields.
|
||||
fields: Fields<'a>,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn Structable + '_ {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let def = self.definition();
|
||||
|
||||
if def.fields().is_named() {
|
||||
struct DebugStruct<'a, 'b> {
|
||||
fmt: fmt::DebugStruct<'a, 'b>,
|
||||
}
|
||||
|
||||
let mut debug = DebugStruct {
|
||||
fmt: fmt.debug_struct(def.name()),
|
||||
};
|
||||
|
||||
impl Visit for DebugStruct<'_, '_> {
|
||||
fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
for (field, value) in named_values {
|
||||
self.fmt.field(field.name(), value);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, _: Value<'_>) {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
self.visit(&mut debug);
|
||||
|
||||
debug.fmt.finish()
|
||||
} else {
|
||||
struct DebugStruct<'a, 'b> {
|
||||
fmt: fmt::DebugTuple<'a, 'b>,
|
||||
}
|
||||
|
||||
let mut debug = DebugStruct {
|
||||
fmt: fmt.debug_tuple(def.name()),
|
||||
};
|
||||
|
||||
impl Visit for DebugStruct<'_, '_> {
|
||||
fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
for value in values {
|
||||
self.fmt.field(value);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, _: Value<'_>) {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
self.visit(&mut debug);
|
||||
|
||||
debug.fmt.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> StructDef<'a> {
|
||||
/// Create a new [`StructDef::Static`] instance.
|
||||
///
|
||||
/// This should be used when a struct's fields are fixed and known ahead of time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_static("Foo", Fields::Unnamed(2));
|
||||
/// ```
|
||||
pub const fn new_static(name: &'static str, fields: Fields<'static>) -> StructDef<'a> {
|
||||
StructDef::Static { name, fields }
|
||||
}
|
||||
|
||||
/// Create a new [`StructDef::Dynamic`] instance.
|
||||
///
|
||||
/// This is used when the struct's fields may vary at runtime.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(3));
|
||||
/// ```
|
||||
pub const fn new_dynamic(name: &'a str, fields: Fields<'a>) -> StructDef<'a> {
|
||||
StructDef::Dynamic { name, fields }
|
||||
}
|
||||
|
||||
/// Returns the struct's name
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a static struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_static("Foo", Fields::Unnamed(1));
|
||||
/// assert_eq!("Foo", def.name());
|
||||
/// ```
|
||||
///
|
||||
/// With a dynamic struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(2));
|
||||
/// assert_eq!("Foo", def.name());
|
||||
/// ```
|
||||
pub const fn name(&self) -> &'a str {
|
||||
match self {
|
||||
StructDef::Static { name, .. } => name,
|
||||
StructDef::Dynamic { name, .. } => name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the struct's fields
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a static struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_static("Foo", Fields::Unnamed(3));
|
||||
/// assert!(matches!(def.fields(), Fields::Unnamed(_)));
|
||||
/// ```
|
||||
///
|
||||
/// With a dynamic struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(1));
|
||||
/// assert!(matches!(def.fields(), Fields::Unnamed(_)));
|
||||
/// ```
|
||||
pub const fn fields(&self) -> &Fields<'a> {
|
||||
match self {
|
||||
StructDef::Static { fields, .. } => fields,
|
||||
StructDef::Dynamic { fields, .. } => fields,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the struct is [statically defined](StructDef::Static).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a static struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_static("Foo", Fields::Unnamed(2));
|
||||
/// assert!(def.is_static());
|
||||
/// ```
|
||||
///
|
||||
/// With a dynamic struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(4));
|
||||
/// assert!(!def.is_static());
|
||||
/// ```
|
||||
pub const fn is_static(&self) -> bool {
|
||||
matches!(self, StructDef::Static { .. })
|
||||
}
|
||||
|
||||
/// Returns `true` if the struct is [dynamically defined](StructDef::Dynamic).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a static struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_static("Foo", Fields::Unnamed(1));
|
||||
/// assert!(!def.is_dynamic());
|
||||
/// ```
|
||||
///
|
||||
/// With a dynamic struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{StructDef, Fields};
|
||||
///
|
||||
/// let def = StructDef::new_dynamic("Foo", Fields::Unnamed(1));
|
||||
/// assert!(def.is_dynamic());
|
||||
/// ```
|
||||
pub const fn is_dynamic(&self) -> bool {
|
||||
matches!(self, StructDef::Dynamic { .. })
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! deref {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<T: ?Sized + Structable> Structable for $ty {
|
||||
fn definition(&self) -> StructDef<'_> {
|
||||
T::definition(&**self)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
deref! {
|
||||
&T,
|
||||
&mut T,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::boxed::Box<T>,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::rc::Rc<T>,
|
||||
#[cfg(not(valuable_no_atomic_cas))]
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::sync::Arc<T>,
|
||||
}
|
||||
339
third-party/vendor/valuable/src/tuplable.rs
vendored
Normal file
339
third-party/vendor/valuable/src/tuplable.rs
vendored
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
use crate::{Valuable, Value, Visit};
|
||||
|
||||
use core::fmt;
|
||||
|
||||
/// A tuple-like [`Valuable`] sub-type.
|
||||
///
|
||||
/// Implemented by [`Valuable`] types that have a tuple-like shape. Fields are
|
||||
/// always unnamed. Values that implement `Tuplable` must return
|
||||
/// [`Value::Tuplable`] from their [`Valuable::as_value`] implementation.
|
||||
///
|
||||
/// It is uncommon for users to implement this type as the crate provides
|
||||
/// implementations of `Tuplable` for Rust tuples.
|
||||
///
|
||||
/// # Inspecting
|
||||
///
|
||||
/// Inspecting fields contained by a `Tuplable` instance is done by visiting the
|
||||
/// tuple. When visiting a `Tuple`, the `visit_unnamed_fields()` method is
|
||||
/// called. When the tuple is statically defined, `visit_unnamed_fields()` is
|
||||
/// called once with the values of all the fields. A dynamic tuple
|
||||
/// implementation may call `visit_unnamed_fields()` multiple times.
|
||||
pub trait Tuplable: Valuable {
|
||||
/// Returns the tuple's definition.
|
||||
///
|
||||
/// See [`TupleDef`] documentation for more details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Tuplable, TupleDef};
|
||||
///
|
||||
/// let tuple = (123, "hello");
|
||||
///
|
||||
/// if let TupleDef::Static { fields, .. } = tuple.definition() {
|
||||
/// assert_eq!(2, fields);
|
||||
/// }
|
||||
/// ```
|
||||
fn definition(&self) -> TupleDef;
|
||||
}
|
||||
|
||||
/// The number of fields and other tuple-level information.
|
||||
///
|
||||
/// Returned by [`Tuplable::definition()`], `TupleDef` provides the caller with
|
||||
/// information about the tuple's definition.
|
||||
///
|
||||
/// This includes the number of fields contained by the tuple.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum TupleDef {
|
||||
/// The tuple is statically-defined, all fields are known ahead of time.
|
||||
///
|
||||
/// Static tuple implementations are provided by the crate.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A statically defined tuple.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Tuplable, TupleDef};
|
||||
///
|
||||
/// let tuple = (123, "hello");
|
||||
///
|
||||
/// match tuple.definition() {
|
||||
/// TupleDef::Static { fields, .. } => {
|
||||
/// assert_eq!(2, fields);
|
||||
/// }
|
||||
/// _ => unreachable!(),
|
||||
/// };
|
||||
/// ```
|
||||
#[non_exhaustive]
|
||||
Static {
|
||||
/// The number of fields contained by the tuple.
|
||||
fields: usize,
|
||||
},
|
||||
/// The tuple is dynamically-defined, not all fields are known ahead of
|
||||
/// time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Tuplable, TupleDef, Valuable, Value, Visit};
|
||||
///
|
||||
/// struct MyTuple;
|
||||
///
|
||||
/// impl Valuable for MyTuple {
|
||||
/// fn as_value(&self) -> Value<'_> {
|
||||
/// Value::Tuplable(self)
|
||||
/// }
|
||||
///
|
||||
/// fn visit(&self, visit: &mut dyn Visit) {
|
||||
/// visit.visit_unnamed_fields(&[Value::I32(123)]);
|
||||
/// visit.visit_unnamed_fields(&[Value::String("hello world")]);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Tuplable for MyTuple {
|
||||
/// fn definition(&self) -> TupleDef {
|
||||
/// TupleDef::new_dynamic((1, Some(3)))
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[non_exhaustive]
|
||||
Dynamic {
|
||||
/// Returns the bounds on the number of tuple fields.
|
||||
///
|
||||
/// Specifically, the first element is the lower bound, and the second
|
||||
/// element is the upper bound.
|
||||
fields: (usize, Option<usize>),
|
||||
},
|
||||
}
|
||||
|
||||
macro_rules! deref {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<T: ?Sized + Tuplable> Tuplable for $ty {
|
||||
fn definition(&self) -> TupleDef {
|
||||
T::definition(&**self)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
deref! {
|
||||
&T,
|
||||
&mut T,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::boxed::Box<T>,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::rc::Rc<T>,
|
||||
#[cfg(not(valuable_no_atomic_cas))]
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::sync::Arc<T>,
|
||||
}
|
||||
|
||||
impl Tuplable for () {
|
||||
fn definition(&self) -> TupleDef {
|
||||
TupleDef::Static { fields: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tuple_impls {
|
||||
(
|
||||
$( $len:expr => ( $($n:tt $name:ident)+ ) )+
|
||||
) => {
|
||||
$(
|
||||
impl<$($name),+> Valuable for ($($name,)+)
|
||||
where
|
||||
$($name: Valuable,)+
|
||||
{
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Tuplable(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_unnamed_fields(&[
|
||||
$(
|
||||
self.$n.as_value(),
|
||||
)+
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($name),+> Tuplable for ($($name,)+)
|
||||
where
|
||||
$($name: Valuable,)+
|
||||
{
|
||||
fn definition(&self) -> TupleDef {
|
||||
TupleDef::Static { fields: $len }
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
tuple_impls! {
|
||||
1 => (0 T0)
|
||||
2 => (0 T0 1 T1)
|
||||
3 => (0 T0 1 T1 2 T2)
|
||||
4 => (0 T0 1 T1 2 T2 3 T3)
|
||||
5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
|
||||
6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
|
||||
7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
|
||||
8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
|
||||
9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
|
||||
10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
|
||||
11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
|
||||
12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
|
||||
13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
|
||||
14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
|
||||
15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
|
||||
16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn Tuplable + '_ {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.definition().is_unit() {
|
||||
().fmt(fmt)
|
||||
} else {
|
||||
struct DebugTuple<'a, 'b> {
|
||||
fmt: fmt::DebugTuple<'a, 'b>,
|
||||
}
|
||||
|
||||
impl Visit for DebugTuple<'_, '_> {
|
||||
fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
for value in values {
|
||||
self.fmt.field(value);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, _: Value<'_>) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
let mut debug = DebugTuple {
|
||||
fmt: fmt.debug_tuple(""),
|
||||
};
|
||||
|
||||
self.visit(&mut debug);
|
||||
debug.fmt.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TupleDef {
|
||||
/// Create a new [`TupleDef::Static`] instance
|
||||
///
|
||||
/// This should be used when the tuple's fields are fixed and known ahead of time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::TupleDef;
|
||||
///
|
||||
/// let def = TupleDef::new_static(2);
|
||||
/// ```
|
||||
pub const fn new_static(fields: usize) -> TupleDef {
|
||||
TupleDef::Static { fields }
|
||||
}
|
||||
|
||||
/// Create a new [`TupleDef::Dynamic`] instance.
|
||||
///
|
||||
/// This is used when the tuple's fields may vary at runtime.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::TupleDef;
|
||||
///
|
||||
/// let def = TupleDef::new_dynamic((2, Some(10)));
|
||||
/// ```
|
||||
pub const fn new_dynamic(fields: (usize, Option<usize>)) -> TupleDef {
|
||||
TupleDef::Dynamic { fields }
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` represents the [unit][primitive@unit] tuple.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With the unit tuple
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Tuplable;
|
||||
///
|
||||
/// let tuple: &dyn Tuplable = &();
|
||||
/// assert!(tuple.definition().is_unit());
|
||||
/// ```
|
||||
///
|
||||
/// When not the unit tuple.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Tuplable;
|
||||
///
|
||||
/// let tuple: &dyn Tuplable = &(123,456);
|
||||
/// assert!(!tuple.definition().is_unit());
|
||||
/// ```
|
||||
pub fn is_unit(&self) -> bool {
|
||||
match *self {
|
||||
TupleDef::Static { fields } => fields == 0,
|
||||
TupleDef::Dynamic { fields } => fields == (0, Some(0)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the tuple is [statically defined](TupleDef::Static).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a static tuple
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::TupleDef;
|
||||
///
|
||||
/// let def = TupleDef::new_static(2);
|
||||
/// assert!(def.is_static());
|
||||
/// ```
|
||||
///
|
||||
/// With a dynamic tuple
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::TupleDef;
|
||||
///
|
||||
/// let def = TupleDef::new_dynamic((2, None));
|
||||
/// assert!(!def.is_static());
|
||||
/// ```
|
||||
pub fn is_static(&self) -> bool {
|
||||
matches!(self, TupleDef::Static { .. })
|
||||
}
|
||||
|
||||
/// Returns `true` if the tuple is [dynamically defined](TupleDef::Dynamic).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// With a static tuple
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::TupleDef;
|
||||
///
|
||||
/// let def = TupleDef::new_static(2);
|
||||
/// assert!(!def.is_dynamic());
|
||||
/// ```
|
||||
///
|
||||
/// With a dynamic tuple
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::TupleDef;
|
||||
///
|
||||
/// let def = TupleDef::new_dynamic((2, None));
|
||||
/// assert!(def.is_dynamic());
|
||||
/// ```
|
||||
pub fn is_dynamic(&self) -> bool {
|
||||
matches!(self, TupleDef::Dynamic { .. })
|
||||
}
|
||||
}
|
||||
339
third-party/vendor/valuable/src/valuable.rs
vendored
Normal file
339
third-party/vendor/valuable/src/valuable.rs
vendored
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
use crate::{Slice, Value, Visit};
|
||||
|
||||
use core::fmt;
|
||||
use core::num::Wrapping;
|
||||
|
||||
/// A type that can be converted to a [`Value`].
|
||||
///
|
||||
/// `Valuable` types are inspected by defining a [`Visit`] implementation and
|
||||
/// using it when calling [`Valuable::visit`]. See [`Visit`] documentation for
|
||||
/// more details.
|
||||
///
|
||||
/// The `Valuable` procedural macro makes implementing `Valuable` easy. Users
|
||||
/// can add add [`#[derive(Valuable)]`][macro] to their types.
|
||||
///
|
||||
/// `Valuable` provides implementations for many Rust primitives and standard
|
||||
/// library types.
|
||||
///
|
||||
/// Types implementing `Valuable` may also implement one of the more specific
|
||||
/// traits: [`Structable`], [`Enumerable`], [`Listable`], and [`Mappable`]. These traits
|
||||
/// should be implemented when the type is a nested container of other `Valuable` types.
|
||||
///
|
||||
/// [`Value`]: Value
|
||||
/// [`Visit`]: Visit
|
||||
/// [`Valuable::visit`]: Valuable::visit
|
||||
/// [`Structable`]: crate::Structable
|
||||
/// [`Enumerable`]: crate::Enumerable
|
||||
/// [`Listable`]: crate::Listable
|
||||
/// [`Mappable`]: crate::Mappable
|
||||
/// [macro]: macro@crate::Valuable
|
||||
pub trait Valuable {
|
||||
/// Converts self into a [`Value`] instance.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Valuable;
|
||||
///
|
||||
/// let _ = "hello".as_value();
|
||||
/// ```
|
||||
fn as_value(&self) -> Value<'_>;
|
||||
|
||||
/// Calls the relevant method on [`Visit`] to extract data from `self`.
|
||||
///
|
||||
/// This method is used to extract type-specific data from the value and is
|
||||
/// intended to be an implementation detail. For example, `Vec` implements
|
||||
/// `visit` by calling [`visit_value()`] on each of its elements. Structs
|
||||
/// implement `visit` by calling [`visit_named_fields()`] or
|
||||
/// [`visit_unnamed_fields()`].
|
||||
///
|
||||
/// Usually, users will call the [`visit`] function instead.
|
||||
///
|
||||
/// [`Visit`]: Visit
|
||||
/// [`visit`]: visit()
|
||||
/// [`visit_value()`]: Visit::visit_value()
|
||||
/// [`visit_named_fields()`]: Visit::visit_named_fields()
|
||||
/// [`visit_unnamed_fields()`]: Visit::visit_unnamed_fields()
|
||||
fn visit(&self, visit: &mut dyn Visit);
|
||||
|
||||
/// Calls [`Visit::visit_primitive_slice()`] with `self`.
|
||||
///
|
||||
/// This method is an implementation detail used to optimize visiting
|
||||
/// primitive slices.
|
||||
///
|
||||
/// [`Visit::visit_primitive_slice()`]: Visit::visit_primitive_slice
|
||||
fn visit_slice(slice: &[Self], visit: &mut dyn Visit)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
for item in slice {
|
||||
visit.visit_value(item.as_value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! deref {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<T: ?Sized + Valuable> Valuable for $ty {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
T::as_value(&**self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
T::visit(&**self, visit);
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
deref! {
|
||||
&T,
|
||||
&mut T,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::boxed::Box<T>,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::rc::Rc<T>,
|
||||
#[cfg(not(valuable_no_atomic_cas))]
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::sync::Arc<T>,
|
||||
}
|
||||
|
||||
macro_rules! valuable {
|
||||
(
|
||||
$(
|
||||
$variant:ident($ty:ty),
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
impl Valuable for $ty {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::$variant(*self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(self.as_value());
|
||||
}
|
||||
|
||||
fn visit_slice(slice: &[Self], visit: &mut dyn Visit)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
visit.visit_primitive_slice(Slice::$variant(slice));
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
valuable! {
|
||||
Bool(bool),
|
||||
Char(char),
|
||||
F32(f32),
|
||||
F64(f64),
|
||||
I8(i8),
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
I128(i128),
|
||||
Isize(isize),
|
||||
U8(u8),
|
||||
U16(u16),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
U128(u128),
|
||||
Usize(usize),
|
||||
}
|
||||
|
||||
macro_rules! nonzero {
|
||||
(
|
||||
$(
|
||||
$variant:ident($ty:ident),
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
impl Valuable for core::num::$ty {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::$variant(self.get())
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(self.as_value());
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
nonzero! {
|
||||
I8(NonZeroI8),
|
||||
I16(NonZeroI16),
|
||||
I32(NonZeroI32),
|
||||
I64(NonZeroI64),
|
||||
I128(NonZeroI128),
|
||||
Isize(NonZeroIsize),
|
||||
U8(NonZeroU8),
|
||||
U16(NonZeroU16),
|
||||
U32(NonZeroU32),
|
||||
U64(NonZeroU64),
|
||||
U128(NonZeroU128),
|
||||
Usize(NonZeroUsize),
|
||||
}
|
||||
|
||||
#[cfg(not(valuable_no_atomic))]
|
||||
macro_rules! atomic {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$variant:ident($ty:ident),
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl Valuable for core::sync::atomic::$ty {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
// Use SeqCst to match Debug and serde which use SeqCst.
|
||||
// https://github.com/rust-lang/rust/blob/1.52.1/library/core/src/sync/atomic.rs#L1361-L1366
|
||||
// https://github.com/serde-rs/serde/issues/1496
|
||||
Value::$variant(self.load(core::sync::atomic::Ordering::SeqCst))
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(self.as_value());
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(valuable_no_atomic))]
|
||||
atomic! {
|
||||
Bool(AtomicBool),
|
||||
I8(AtomicI8),
|
||||
I16(AtomicI16),
|
||||
I32(AtomicI32),
|
||||
#[cfg(not(valuable_no_atomic_64))]
|
||||
I64(AtomicI64),
|
||||
Isize(AtomicIsize),
|
||||
U8(AtomicU8),
|
||||
U16(AtomicU16),
|
||||
U32(AtomicU32),
|
||||
#[cfg(not(valuable_no_atomic_64))]
|
||||
U64(AtomicU64),
|
||||
Usize(AtomicUsize),
|
||||
}
|
||||
|
||||
impl<T: Valuable> Valuable for Wrapping<T> {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
self.0.as_value()
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
self.0.visit(visit);
|
||||
}
|
||||
}
|
||||
|
||||
impl Valuable for () {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Tuplable(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_unnamed_fields(&[]);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Valuable> Valuable for Option<T> {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
match self {
|
||||
Some(v) => v.as_value(),
|
||||
None => Value::Unit,
|
||||
}
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(self.as_value());
|
||||
}
|
||||
}
|
||||
|
||||
impl Valuable for &'_ str {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::String(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(Value::String(self));
|
||||
}
|
||||
|
||||
fn visit_slice(slice: &[Self], visit: &mut dyn Visit)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
visit.visit_primitive_slice(Slice::Str(slice));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl Valuable for alloc::string::String {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::String(&self[..])
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(Value::String(self));
|
||||
}
|
||||
|
||||
fn visit_slice(slice: &[Self], visit: &mut dyn Visit)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
visit.visit_primitive_slice(Slice::String(slice));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Valuable for &std::path::Path {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Path(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(Value::Path(self));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Valuable for std::path::PathBuf {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Path(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(Value::Path(self));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Valuable for dyn std::error::Error + 'static {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
Value::Error(self)
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(self.as_value());
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn Valuable + '_ {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let value = self.as_value();
|
||||
value.fmt(fmt)
|
||||
}
|
||||
}
|
||||
877
third-party/vendor/valuable/src/value.rs
vendored
Normal file
877
third-party/vendor/valuable/src/value.rs
vendored
Normal file
|
|
@ -0,0 +1,877 @@
|
|||
use crate::{Enumerable, Listable, Mappable, Structable, Tuplable, Valuable, Visit};
|
||||
|
||||
use core::fmt;
|
||||
|
||||
macro_rules! value {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$variant:ident($ty:ty),
|
||||
)*
|
||||
) => {
|
||||
/// Any Rust value
|
||||
///
|
||||
/// The `Value` enum is used to pass single values to the
|
||||
/// [visitor][`Visit`]. Primitive types are enumerated and other types
|
||||
/// are represented at trait objects.
|
||||
///
|
||||
/// Values are converted to `Value` instances using
|
||||
/// [`Valuable::as_value()`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Convert a primitive type
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Value, Valuable};
|
||||
///
|
||||
/// let num = 123;
|
||||
/// let val = num.as_value();
|
||||
///
|
||||
/// assert!(matches!(val, Value::I32(v) if v == 123));
|
||||
/// ```
|
||||
///
|
||||
/// Converting a struct
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Value, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable, Debug)]
|
||||
/// struct HelloWorld {
|
||||
/// message: String,
|
||||
/// }
|
||||
///
|
||||
/// let hello = HelloWorld {
|
||||
/// message: "greetings".to_string(),
|
||||
/// };
|
||||
///
|
||||
/// let val = hello.as_value();
|
||||
///
|
||||
/// assert!(matches!(val, Value::Structable(_v)));
|
||||
///
|
||||
/// // The Value `Debug` output matches the struct's
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", val),
|
||||
/// format!("{:?}", hello),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// [visitor]: Visit
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Value<'a> {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant($ty),
|
||||
)*
|
||||
|
||||
/// A Rust `()` or `None` value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::Unit;
|
||||
/// ```
|
||||
Unit,
|
||||
}
|
||||
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<'a> From<$ty> for Value<'a> {
|
||||
fn from(src: $ty) -> Value<'a> {
|
||||
Value::$variant(src)
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
impl<'a> From<()> for Value<'a> {
|
||||
fn from(_: ()) -> Value<'a> {
|
||||
Value::Tuplable(&())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Value<'_> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use Value::*;
|
||||
|
||||
// Doc comments are expanded into the branch arms, which results
|
||||
// in a warning. It isn't a big deal, so silence it.
|
||||
#[allow(unused_doc_comments)]
|
||||
match self {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
$variant(v) => fmt::Debug::fmt(v, fmt),
|
||||
)*
|
||||
Unit => ().fmt(fmt),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value! {
|
||||
/// A Rust `bool` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::Bool(true);
|
||||
/// ```
|
||||
Bool(bool),
|
||||
|
||||
/// A Rust `char` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::Char('h');
|
||||
/// ```
|
||||
Char(char),
|
||||
|
||||
/// A Rust `f32` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::F32(3.1415);
|
||||
/// ```
|
||||
F32(f32),
|
||||
|
||||
/// A Rust `f64` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::F64(3.1415);
|
||||
/// ```
|
||||
F64(f64),
|
||||
|
||||
/// A Rust `i8` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::I8(42);
|
||||
/// ```
|
||||
I8(i8),
|
||||
|
||||
/// A Rust `i16` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::I16(42);
|
||||
/// ```
|
||||
I16(i16),
|
||||
|
||||
/// A Rust `i32` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::I32(42);
|
||||
/// ```
|
||||
I32(i32),
|
||||
|
||||
/// A Rust `i64` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::I64(42);
|
||||
/// ```
|
||||
I64(i64),
|
||||
|
||||
/// A Rust `i128` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::I128(42);
|
||||
/// ```
|
||||
I128(i128),
|
||||
|
||||
/// A Rust `isize` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::Isize(42);
|
||||
/// ```
|
||||
Isize(isize),
|
||||
|
||||
/// A Rust `&str` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::String("hello");
|
||||
/// ```
|
||||
String(&'a str),
|
||||
|
||||
/// A Rust `u8` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::U8(42);
|
||||
/// ```
|
||||
U8(u8),
|
||||
|
||||
/// A Rust `u16` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::U16(42);
|
||||
/// ```
|
||||
U16(u16),
|
||||
|
||||
/// A Rust `u32` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::U32(42);
|
||||
/// ```
|
||||
U32(u32),
|
||||
|
||||
/// A Rust `u64` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::U64(42);
|
||||
/// ```
|
||||
U64(u64),
|
||||
|
||||
/// A Rust `u128` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::U128(42);
|
||||
/// ```
|
||||
U128(u128),
|
||||
|
||||
/// A Rust `usize` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let v = Value::Usize(42);
|
||||
/// ```
|
||||
Usize(usize),
|
||||
|
||||
/// A Rust `&Path` value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// let path = Path::new("a.txt");
|
||||
/// let v = Value::Path(path);
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
Path(&'a std::path::Path),
|
||||
|
||||
/// A Rust error value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
/// use std::io;
|
||||
///
|
||||
/// let err: io::Error = io::ErrorKind::Other.into();
|
||||
/// let v = Value::Error(&err);
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
Error(&'a (dyn std::error::Error +'static)),
|
||||
|
||||
/// A Rust list value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let vals = vec![1, 2, 3, 4, 5];
|
||||
/// let v = Value::Listable(&vals);
|
||||
/// ```
|
||||
Listable(&'a dyn Listable),
|
||||
|
||||
/// A Rust map value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// let mut map = HashMap::new();
|
||||
/// map.insert("foo", 1);
|
||||
/// map.insert("bar", 2);
|
||||
///
|
||||
/// let v = Value::Mappable(&map);
|
||||
/// ```
|
||||
Mappable(&'a dyn Mappable),
|
||||
|
||||
/// A Rust struct value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Value, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct MyStruct {
|
||||
/// field: u32,
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = MyStruct {
|
||||
/// field: 123,
|
||||
/// };
|
||||
///
|
||||
/// let v = Value::Structable(&my_struct);
|
||||
/// ```
|
||||
Structable(&'a dyn Structable),
|
||||
|
||||
/// A Rust enum value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Value, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum MyEnum {
|
||||
/// Foo,
|
||||
/// Bar,
|
||||
/// }
|
||||
///
|
||||
/// let my_enum = MyEnum::Foo;
|
||||
/// let v = Value::Enumerable(&my_enum);
|
||||
/// ```
|
||||
Enumerable(&'a dyn Enumerable),
|
||||
|
||||
/// A tuple value
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Value, Valuable};
|
||||
///
|
||||
/// let my_tuple = (123, 456);
|
||||
/// let v = Value::Tuplable(&my_tuple);
|
||||
/// ```
|
||||
Tuplable(&'a dyn Tuplable),
|
||||
}
|
||||
|
||||
impl Valuable for Value<'_> {
|
||||
fn as_value(&self) -> Value<'_> {
|
||||
*self
|
||||
}
|
||||
|
||||
fn visit(&self, visit: &mut dyn Visit) {
|
||||
visit.visit_value(*self);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Value<'_> {
|
||||
fn default() -> Self {
|
||||
Value::Unit
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! convert {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$ty:ty => $as:ident,
|
||||
)*
|
||||
) => {
|
||||
impl<'a> Value<'a> {
|
||||
/// Return a `bool` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::Bool(true).as_bool(), Some(true));
|
||||
/// assert_eq!(Value::Char('c').as_bool(), None);
|
||||
/// ```
|
||||
pub fn as_bool(&self) -> Option<bool> {
|
||||
match *self {
|
||||
Value::Bool(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `char` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::Char('c').as_char(), Some('c'));
|
||||
/// assert_eq!(Value::Bool(true).as_char(), None);
|
||||
/// ```
|
||||
pub fn as_char(&self) -> Option<char> {
|
||||
match *self {
|
||||
Value::Char(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `f32` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::F32(3.1415).as_f32(), Some(3.1415));
|
||||
/// assert_eq!(Value::Bool(true).as_f32(), None);
|
||||
/// ```
|
||||
pub fn as_f32(&self) -> Option<f32> {
|
||||
match *self {
|
||||
Value::F32(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `f64` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::F64(3.1415).as_f64(), Some(3.1415));
|
||||
/// assert_eq!(Value::Bool(true).as_f64(), None);
|
||||
/// ```
|
||||
pub fn as_f64(&self) -> Option<f64> {
|
||||
match *self {
|
||||
Value::F64(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
pub fn $as(&self) -> Option<$ty> {
|
||||
use Value::*;
|
||||
use core::convert::TryInto;
|
||||
|
||||
match *self {
|
||||
I8(v) => v.try_into().ok(),
|
||||
I16(v) => v.try_into().ok(),
|
||||
I32(v) => v.try_into().ok(),
|
||||
I64(v) => v.try_into().ok(),
|
||||
I128(v) => v.try_into().ok(),
|
||||
Isize(v) => v.try_into().ok(),
|
||||
U8(v) => v.try_into().ok(),
|
||||
U16(v) => v.try_into().ok(),
|
||||
U32(v) => v.try_into().ok(),
|
||||
U64(v) => v.try_into().ok(),
|
||||
U128(v) => v.try_into().ok(),
|
||||
Usize(v) => v.try_into().ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
/// Return a `&str` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::String("hello").as_str(), Some("hello"));
|
||||
/// assert_eq!(Value::Bool(true).as_str(), None);
|
||||
/// ```
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
match *self {
|
||||
Value::String(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `&Path` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// let path = Path::new("a.txt");
|
||||
///
|
||||
/// assert!(Value::Path(path).as_path().is_some());
|
||||
/// assert!(Value::Bool(true).as_path().is_none());
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
pub fn as_path(&self) -> Option<&std::path::Path> {
|
||||
match *self {
|
||||
Value::Path(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `&dyn Error` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
/// use std::io;
|
||||
///
|
||||
/// let err: io::Error = io::ErrorKind::Other.into();
|
||||
///
|
||||
/// assert!(Value::Error(&err).as_error().is_some());
|
||||
/// assert!(Value::Bool(true).as_error().is_none());
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
pub fn as_error(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match *self {
|
||||
Value::Error(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Return a `&dyn Listable` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let list = vec![1, 2, 3, 4];
|
||||
///
|
||||
/// assert!(Value::Listable(&list).as_listable().is_some());
|
||||
/// assert!(Value::Bool(true).as_listable().is_none());
|
||||
/// ```
|
||||
pub fn as_listable(&self) -> Option<&dyn Listable> {
|
||||
match *self {
|
||||
Value::Listable(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `&dyn Mappable` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// let mut map = HashMap::new();
|
||||
/// map.insert("foo", 123);
|
||||
/// map.insert("bar", 456);
|
||||
///
|
||||
/// assert!(Value::Mappable(&map).as_mappable().is_some());
|
||||
/// assert!(Value::Bool(true).as_mappable().is_none());
|
||||
/// ```
|
||||
pub fn as_mappable(&self) -> Option<&dyn Mappable> {
|
||||
match *self {
|
||||
Value::Mappable(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `&dyn Structable` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Value, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct Hello {
|
||||
/// message: &'static str,
|
||||
/// }
|
||||
///
|
||||
/// let hello = Hello { message: "Hello world" };
|
||||
///
|
||||
/// assert!(Value::Structable(&hello).as_structable().is_some());
|
||||
/// assert!(Value::Bool(true).as_structable().is_none());
|
||||
/// ```
|
||||
pub fn as_structable(&self) -> Option<&dyn Structable> {
|
||||
match *self {
|
||||
Value::Structable(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `&dyn Enumerable` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Value, Valuable};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// enum Greet {
|
||||
/// Hello,
|
||||
/// World,
|
||||
/// }
|
||||
///
|
||||
/// let greet = Greet::Hello;
|
||||
///
|
||||
/// assert!(Value::Enumerable(&greet).as_enumerable().is_some());
|
||||
/// assert!(Value::Bool(true).as_enumerable().is_none());
|
||||
/// ```
|
||||
pub fn as_enumerable(&self) -> Option<&dyn Enumerable> {
|
||||
match *self {
|
||||
Value::Enumerable(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a `&dyn Tuplable` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// let my_tuple = (123, 456);
|
||||
///
|
||||
/// assert!(Value::Tuplable(&my_tuple).as_tuplable().is_some());
|
||||
/// assert!(Value::Bool(true).as_tuplable().is_none());
|
||||
/// ```
|
||||
pub fn as_tuplable(&self) -> Option<&dyn Tuplable> {
|
||||
match *self {
|
||||
Value::Tuplable(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
convert! {
|
||||
/// Return a `i8` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::I8(42).as_i8(), Some(42));
|
||||
/// assert_eq!(Value::I32(42).as_i8(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::I64(i64::MAX).as_i8(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_i8(), None);
|
||||
/// ```
|
||||
i8 => as_i8,
|
||||
|
||||
/// Return a `i16` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::I16(42).as_i16(), Some(42));
|
||||
/// assert_eq!(Value::I32(42).as_i16(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::I64(i64::MAX).as_i16(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_i16(), None);
|
||||
/// ```
|
||||
i16 => as_i16,
|
||||
|
||||
/// Return a `i32` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::I32(42).as_i32(), Some(42));
|
||||
/// assert_eq!(Value::I64(42).as_i32(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::I64(i64::MAX).as_i32(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_i32(), None);
|
||||
/// ```
|
||||
i32 => as_i32,
|
||||
|
||||
/// Return a `i64` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::I64(42).as_i64(), Some(42));
|
||||
/// assert_eq!(Value::I128(42).as_i64(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::I128(i128::MAX).as_i64(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_i64(), None);
|
||||
/// ```
|
||||
i64 => as_i64,
|
||||
|
||||
/// Return a `i128` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::I128(42).as_i128(), Some(42));
|
||||
/// assert_eq!(Value::U128(42).as_i128(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::U128(u128::MAX).as_i128(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_i128(), None);
|
||||
/// ```
|
||||
i128 => as_i128,
|
||||
|
||||
/// Return a `isize` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::Isize(42).as_isize(), Some(42));
|
||||
/// assert_eq!(Value::Usize(42).as_isize(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::Usize(usize::MAX).as_isize(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_isize(), None);
|
||||
/// ```
|
||||
isize => as_isize,
|
||||
|
||||
/// Return a `u8` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::U8(42).as_u8(), Some(42));
|
||||
/// assert_eq!(Value::U32(42).as_u8(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::U32(u32::MAX).as_u8(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_u8(), None);
|
||||
/// ```
|
||||
u8 => as_u8,
|
||||
|
||||
/// Return a `u16` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::U16(42).as_u16(), Some(42));
|
||||
/// assert_eq!(Value::U32(42).as_u16(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::U32(u32::MAX).as_u16(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_u16(), None);
|
||||
/// ```
|
||||
u16 => as_u16,
|
||||
|
||||
/// Return a `u32` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::U32(42).as_u32(), Some(42));
|
||||
/// assert_eq!(Value::U64(42).as_u32(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::U64(u64::MAX).as_u32(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_u32(), None);
|
||||
/// ```
|
||||
u32 => as_u32,
|
||||
|
||||
/// Return a `u64` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::U64(42).as_u64(), Some(42));
|
||||
/// assert_eq!(Value::U128(42).as_u64(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::U128(u128::MAX).as_u64(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_u64(), None);
|
||||
/// ```
|
||||
u64 => as_u64,
|
||||
|
||||
/// Return a `u128` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::U128(42).as_u128(), Some(42));
|
||||
/// assert_eq!(Value::I32(42).as_u128(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::I32(-5).as_u128(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_u128(), None);
|
||||
/// ```
|
||||
u128 => as_u128,
|
||||
|
||||
/// Return a `usize` representation of `self`, if possible.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::Value;
|
||||
///
|
||||
/// assert_eq!(Value::Usize(42).as_usize(), Some(42));
|
||||
/// assert_eq!(Value::I8(42).as_usize(), Some(42));
|
||||
///
|
||||
/// assert_eq!(Value::I8(-5).as_usize(), None);
|
||||
/// assert_eq!(Value::Bool(true).as_usize(), None);
|
||||
/// ```
|
||||
usize => as_usize,
|
||||
}
|
||||
459
third-party/vendor/valuable/src/visit.rs
vendored
Normal file
459
third-party/vendor/valuable/src/visit.rs
vendored
Normal file
|
|
@ -0,0 +1,459 @@
|
|||
use crate::*;
|
||||
|
||||
/// Traverse a value's fields and variants.
|
||||
///
|
||||
/// Each method of the `Visit` trait is a hook that enables the implementor to
|
||||
/// observe value fields. By default, most methods are implemented as a no-op.
|
||||
/// The `visit_primitive_slice` default implementation will iterate the slice,
|
||||
/// calling `visit_value` with each item.
|
||||
///
|
||||
/// To recurse, the implementor must implement methods to visit the arguments.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Recursively printing a Rust value.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedValues, Valuable, Value, Visit};
|
||||
///
|
||||
/// struct Print(String);
|
||||
///
|
||||
/// impl Print {
|
||||
/// fn indent(&self) -> Print {
|
||||
/// Print(format!("{} ", self.0))
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Visit for Print {
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// match value {
|
||||
/// Value::Structable(v) => {
|
||||
/// let def = v.definition();
|
||||
/// // Print the struct name
|
||||
/// println!("{}{}:", self.0, def.name());
|
||||
///
|
||||
/// // Visit fields
|
||||
/// let mut visit = self.indent();
|
||||
/// v.visit(&mut visit);
|
||||
/// }
|
||||
/// Value::Enumerable(v) => {
|
||||
/// let def = v.definition();
|
||||
/// let variant = v.variant();
|
||||
/// // Print the enum name
|
||||
/// println!("{}{}::{}:", self.0, def.name(), variant.name());
|
||||
///
|
||||
/// // Visit fields
|
||||
/// let mut visit = self.indent();
|
||||
/// v.visit(&mut visit);
|
||||
/// }
|
||||
/// Value::Listable(v) => {
|
||||
/// println!("{}", self.0);
|
||||
///
|
||||
/// // Visit fields
|
||||
/// let mut visit = self.indent();
|
||||
/// v.visit(&mut visit);
|
||||
/// }
|
||||
/// Value::Mappable(v) => {
|
||||
/// println!("{}", self.0);
|
||||
///
|
||||
/// // Visit fields
|
||||
/// let mut visit = self.indent();
|
||||
/// v.visit(&mut visit);
|
||||
/// }
|
||||
/// // Primitive or unknown type, just render Debug
|
||||
/// v => println!("{:?}", v),
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
/// for (field, value) in named_values {
|
||||
/// print!("{}- {}: ", self.0, field.name());
|
||||
/// value.visit(self);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
/// for value in values {
|
||||
/// print!("{}- ", self.0);
|
||||
/// value.visit(self);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
|
||||
/// print!("{}- {:?}: ", self.0, key);
|
||||
/// value.visit(self);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct Person {
|
||||
/// name: String,
|
||||
/// age: u32,
|
||||
/// addresses: Vec<Address>,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct Address {
|
||||
/// street: String,
|
||||
/// city: String,
|
||||
/// zip: String,
|
||||
/// }
|
||||
///
|
||||
/// let person = Person {
|
||||
/// name: "Angela Ashton".to_string(),
|
||||
/// age: 31,
|
||||
/// addresses: vec![
|
||||
/// Address {
|
||||
/// street: "123 1st Ave".to_string(),
|
||||
/// city: "Townsville".to_string(),
|
||||
/// zip: "12345".to_string(),
|
||||
/// },
|
||||
/// Address {
|
||||
/// street: "555 Main St.".to_string(),
|
||||
/// city: "New Old Town".to_string(),
|
||||
/// zip: "55555".to_string(),
|
||||
/// },
|
||||
/// ],
|
||||
/// };
|
||||
///
|
||||
/// let mut print = Print("".to_string());
|
||||
/// valuable::visit(&person, &mut print);
|
||||
/// ```
|
||||
pub trait Visit {
|
||||
/// Visit a single value.
|
||||
///
|
||||
/// The `visit_value` method is called once when visiting single primitive
|
||||
/// values. When visiting `Listable` types, the `visit_value` method is
|
||||
/// called once per item in the listable type.
|
||||
///
|
||||
/// Note, in the case of Listable types containing primitive types,
|
||||
/// `visit_primitive_slice` can be implemented instead for less overhead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Visiting a single value.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Valuable, Visit, Value};
|
||||
///
|
||||
/// struct Print;
|
||||
///
|
||||
/// impl Visit for Print {
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// println!("{:?}", value);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let my_val = 123;
|
||||
/// my_val.visit(&mut Print);
|
||||
/// ```
|
||||
///
|
||||
/// Visiting multiple values in a list.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Valuable, Value, Visit};
|
||||
///
|
||||
/// struct PrintList { comma: bool };
|
||||
///
|
||||
/// impl Visit for PrintList {
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// match value {
|
||||
/// Value::Listable(v) => v.visit(self),
|
||||
/// value => {
|
||||
/// if self.comma {
|
||||
/// println!(", {:?}", value);
|
||||
/// } else {
|
||||
/// print!("{:?}", value);
|
||||
/// self.comma = true;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let my_list = vec![1, 2, 3, 4, 5];
|
||||
/// valuable::visit(&my_list, &mut PrintList { comma: false });
|
||||
/// ```
|
||||
fn visit_value(&mut self, value: Value<'_>);
|
||||
|
||||
/// Visit a struct or enum's named fields.
|
||||
///
|
||||
/// When the struct/enum is statically defined, all fields are known ahead
|
||||
/// of time and `visit_named_fields` is called once with all field values.
|
||||
/// When the struct/enum is dynamic, then the `visit_named_fields` method
|
||||
/// may be called multiple times.
|
||||
///
|
||||
/// See [`Structable`] and [`Enumerable`] for static vs. dynamic details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Visiting all fields in a struct.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedValues, Valuable, Value, Visit};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct MyStruct {
|
||||
/// hello: String,
|
||||
/// world: u32,
|
||||
/// }
|
||||
///
|
||||
/// struct Print;
|
||||
///
|
||||
/// impl Visit for Print {
|
||||
/// fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
/// for (field, value) in named_values {
|
||||
/// println!("{:?}: {:?}", field, value);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// match value {
|
||||
/// Value::Structable(v) => v.visit(self),
|
||||
/// _ => {} // do nothing for other types
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = MyStruct {
|
||||
/// hello: "Hello world".to_string(),
|
||||
/// world: 42,
|
||||
/// };
|
||||
///
|
||||
/// valuable::visit(&my_struct, &mut Print);
|
||||
/// ```
|
||||
fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
let _ = named_values;
|
||||
}
|
||||
|
||||
/// Visit a struct or enum's unnamed fields.
|
||||
///
|
||||
/// When the struct/enum is statically defined, all fields are known ahead
|
||||
/// of time and `visit_unnamed_fields` is called once with all field values.
|
||||
/// When the struct/enum is dynamic, then the `visit_unnamed_fields` method
|
||||
/// may be called multiple times.
|
||||
///
|
||||
/// See [`Structable`] and [`Enumerable`] for static vs. dynamic details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Visiting all fields in a struct.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Valuable, Value, Visit};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct MyStruct(String, u32);
|
||||
///
|
||||
/// struct Print;
|
||||
///
|
||||
/// impl Visit for Print {
|
||||
/// fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
/// for value in values {
|
||||
/// println!("{:?}", value);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// match value {
|
||||
/// Value::Structable(v) => v.visit(self),
|
||||
/// _ => {} // do nothing for other types
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = MyStruct("Hello world".to_string(), 42);
|
||||
///
|
||||
/// valuable::visit(&my_struct, &mut Print);
|
||||
/// ```
|
||||
fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
let _ = values;
|
||||
}
|
||||
|
||||
/// Visit a primitive slice.
|
||||
///
|
||||
/// This method exists as an optimization when visiting [`Listable`] types.
|
||||
/// By default, `Listable` types are visited by passing each item to
|
||||
/// `visit_value`. However, if the listable stores a **primitive** type
|
||||
/// within contiguous memory, then `visit_primitive_slice` is called
|
||||
/// instead.
|
||||
///
|
||||
/// When implementing `visit_primitive_slice`, be aware that the method may
|
||||
/// be called multiple times for a single `Listable` type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A vec calls `visit_primitive_slice` one time, but a `VecDeque` will call
|
||||
/// `visit_primitive_slice` twice.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Valuable, Value, Visit, Slice};
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// struct Count(u32);
|
||||
///
|
||||
/// impl Visit for Count {
|
||||
/// fn visit_primitive_slice(&mut self, slice: Slice<'_>) {
|
||||
/// self.0 += 1;
|
||||
/// }
|
||||
///
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// match value {
|
||||
/// Value::Listable(v) => v.visit(self),
|
||||
/// _ => {} // do nothing for other types
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let vec = vec![1, 2, 3, 4, 5];
|
||||
///
|
||||
/// let mut count = Count(0);
|
||||
/// valuable::visit(&vec, &mut count);
|
||||
/// assert_eq!(1, count.0);
|
||||
///
|
||||
/// let mut vec_deque = VecDeque::from(vec);
|
||||
///
|
||||
/// let mut count = Count(0);
|
||||
/// valuable::visit(&vec_deque, &mut count);
|
||||
///
|
||||
/// assert_eq!(2, count.0);
|
||||
/// ```
|
||||
fn visit_primitive_slice(&mut self, slice: Slice<'_>) {
|
||||
for value in slice {
|
||||
self.visit_value(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// Visit a `Mappable`'s entries.
|
||||
///
|
||||
/// The `visit_entry` method is called once for each entry contained by a
|
||||
/// `Mappable.`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Visit a map's entries
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{Valuable, Value, Visit};
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// let mut map = HashMap::new();
|
||||
/// map.insert("hello", 123);
|
||||
/// map.insert("world", 456);
|
||||
///
|
||||
/// struct Print;
|
||||
///
|
||||
/// impl Visit for Print {
|
||||
/// fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
|
||||
/// println!("{:?} => {:?}", key, value);
|
||||
/// }
|
||||
///
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// match value {
|
||||
/// Value::Mappable(v) => v.visit(self),
|
||||
/// _ => {} // do nothing for other types
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// valuable::visit(&map, &mut Print);
|
||||
/// ```
|
||||
fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
|
||||
let _ = (key, value);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! deref {
|
||||
(
|
||||
$(
|
||||
$(#[$attrs:meta])*
|
||||
$ty:ty,
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attrs])*
|
||||
impl<T: ?Sized + Visit> Visit for $ty {
|
||||
fn visit_value(&mut self, value: Value<'_>) {
|
||||
T::visit_value(&mut **self, value)
|
||||
}
|
||||
|
||||
fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
T::visit_named_fields(&mut **self, named_values)
|
||||
}
|
||||
|
||||
fn visit_unnamed_fields(&mut self, values: &[Value<'_>]) {
|
||||
T::visit_unnamed_fields(&mut **self, values)
|
||||
}
|
||||
|
||||
fn visit_primitive_slice(&mut self, slice: Slice<'_>) {
|
||||
T::visit_primitive_slice(&mut **self, slice)
|
||||
}
|
||||
|
||||
fn visit_entry(&mut self, key: Value<'_>, value: Value<'_>) {
|
||||
T::visit_entry(&mut **self, key, value)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
deref! {
|
||||
&mut T,
|
||||
#[cfg(feature = "alloc")]
|
||||
alloc::boxed::Box<T>,
|
||||
}
|
||||
|
||||
/// Inspects a value by calling the relevant [`Visit`] methods with `value`'s
|
||||
/// data.
|
||||
///
|
||||
/// This method calls [`Visit::visit_value()`] with the provided [`Valuable`]
|
||||
/// instance. See [`Visit`] documentation for more details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Extract a single field from a struct. Note: if the same field is repeatedly
|
||||
/// extracted from a struct, it is preferable to obtain the associated
|
||||
/// [`NamedField`] once and use it repeatedly.
|
||||
///
|
||||
/// ```
|
||||
/// use valuable::{NamedValues, Valuable, Value, Visit};
|
||||
///
|
||||
/// #[derive(Valuable)]
|
||||
/// struct MyStruct {
|
||||
/// foo: usize,
|
||||
/// bar: usize,
|
||||
/// }
|
||||
///
|
||||
/// struct GetFoo(usize);
|
||||
///
|
||||
/// impl Visit for GetFoo {
|
||||
/// fn visit_named_fields(&mut self, named_values: &NamedValues<'_>) {
|
||||
/// if let Some(foo) = named_values.get_by_name("foo") {
|
||||
/// if let Some(val) = foo.as_usize() {
|
||||
/// self.0 = val;
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn visit_value(&mut self, value: Value<'_>) {
|
||||
/// if let Value::Structable(v) = value {
|
||||
/// v.visit(self);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = MyStruct {
|
||||
/// foo: 123,
|
||||
/// bar: 456,
|
||||
/// };
|
||||
///
|
||||
/// let mut get_foo = GetFoo(0);
|
||||
/// valuable::visit(&my_struct, &mut get_foo);
|
||||
///
|
||||
/// assert_eq!(123, get_foo.0);
|
||||
/// ```
|
||||
///
|
||||
/// [`Visit`]: Visit [`NamedField`]: crate::NamedField
|
||||
pub fn visit(value: &impl Valuable, visit: &mut dyn Visit) {
|
||||
visit.visit_value(value.as_value());
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue