diff options
Diffstat (limited to 'vendor/valuable')
-rw-r--r-- | vendor/valuable/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/valuable/Cargo.lock | 617 | ||||
-rw-r--r-- | vendor/valuable/Cargo.toml | 41 | ||||
-rw-r--r-- | vendor/valuable/benches/structable.rs | 128 | ||||
-rw-r--r-- | vendor/valuable/build.rs | 39 | ||||
-rw-r--r-- | vendor/valuable/examples/derive.rs | 26 | ||||
-rw-r--r-- | vendor/valuable/examples/hello_world.rs | 68 | ||||
-rw-r--r-- | vendor/valuable/examples/print.rs | 106 | ||||
-rw-r--r-- | vendor/valuable/no_atomic.rs | 63 | ||||
-rw-r--r-- | vendor/valuable/src/enumerable.rs | 682 | ||||
-rw-r--r-- | vendor/valuable/src/field.rs | 166 | ||||
-rw-r--r-- | vendor/valuable/src/lib.rs | 146 | ||||
-rw-r--r-- | vendor/valuable/src/listable.rs | 257 | ||||
-rw-r--r-- | vendor/valuable/src/mappable.rs | 191 | ||||
-rw-r--r-- | vendor/valuable/src/named_values.rs | 222 | ||||
-rw-r--r-- | vendor/valuable/src/slice.rs | 428 | ||||
-rw-r--r-- | vendor/valuable/src/structable.rs | 496 | ||||
-rw-r--r-- | vendor/valuable/src/tuplable.rs | 339 | ||||
-rw-r--r-- | vendor/valuable/src/valuable.rs | 339 | ||||
-rw-r--r-- | vendor/valuable/src/value.rs | 877 | ||||
-rw-r--r-- | vendor/valuable/src/visit.rs | 459 |
21 files changed, 5691 insertions, 0 deletions
diff --git a/vendor/valuable/.cargo-checksum.json b/vendor/valuable/.cargo-checksum.json new file mode 100644 index 000000000..79ed9d549 --- /dev/null +++ b/vendor/valuable/.cargo-checksum.json @@ -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"}
\ No newline at end of file diff --git a/vendor/valuable/Cargo.lock b/vendor/valuable/Cargo.lock new file mode 100644 index 000000000..f7715f999 --- /dev/null +++ b/vendor/valuable/Cargo.lock @@ -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" diff --git a/vendor/valuable/Cargo.toml b/vendor/valuable/Cargo.toml new file mode 100644 index 000000000..408651897 --- /dev/null +++ b/vendor/valuable/Cargo.toml @@ -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"] diff --git a/vendor/valuable/benches/structable.rs b/vendor/valuable/benches/structable.rs new file mode 100644 index 000000000..3d00cd754 --- /dev/null +++ b/vendor/valuable/benches/structable.rs @@ -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); diff --git a/vendor/valuable/build.rs b/vendor/valuable/build.rs new file mode 100644 index 000000000..ad0dd06ae --- /dev/null +++ b/vendor/valuable/build.rs @@ -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"); +} diff --git a/vendor/valuable/examples/derive.rs b/vendor/valuable/examples/derive.rs new file mode 100644 index 000000000..b67aaf3a7 --- /dev/null +++ b/vendor/valuable/examples/derive.rs @@ -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()); +} diff --git a/vendor/valuable/examples/hello_world.rs b/vendor/valuable/examples/hello_world.rs new file mode 100644 index 000000000..7c3d173f0 --- /dev/null +++ b/vendor/valuable/examples/hello_world.rs @@ -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); +} diff --git a/vendor/valuable/examples/print.rs b/vendor/valuable/examples/print.rs new file mode 100644 index 000000000..b6998d37a --- /dev/null +++ b/vendor/valuable/examples/print.rs @@ -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); +} diff --git a/vendor/valuable/no_atomic.rs b/vendor/valuable/no_atomic.rs new file mode 100644 index 000000000..3c2515560 --- /dev/null +++ b/vendor/valuable/no_atomic.rs @@ -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", +]; diff --git a/vendor/valuable/src/enumerable.rs b/vendor/valuable/src/enumerable.rs new file mode 100644 index 000000000..3161f19f0 --- /dev/null +++ b/vendor/valuable/src/enumerable.rs @@ -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()]), + } + } +} diff --git a/vendor/valuable/src/field.rs b/vendor/valuable/src/field.rs new file mode 100644 index 000000000..faa00f420 --- /dev/null +++ b/vendor/valuable/src/field.rs @@ -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 + } +} diff --git a/vendor/valuable/src/lib.rs b/vendor/valuable/src/lib.rs new file mode 100644 index 000000000..5ba6341a0 --- /dev/null +++ b/vendor/valuable/src/lib.rs @@ -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; diff --git a/vendor/valuable/src/listable.rs b/vendor/valuable/src/listable.rs new file mode 100644 index 000000000..b79317f9c --- /dev/null +++ b/vendor/valuable/src/listable.rs @@ -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() + } +} diff --git a/vendor/valuable/src/mappable.rs b/vendor/valuable/src/mappable.rs new file mode 100644 index 000000000..c7c30bf0b --- /dev/null +++ b/vendor/valuable/src/mappable.rs @@ -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() + } +} diff --git a/vendor/valuable/src/named_values.rs b/vendor/valuable/src/named_values.rs new file mode 100644 index 000000000..4f436522a --- /dev/null +++ b/vendor/valuable/src/named_values.rs @@ -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<'_, '_> {} diff --git a/vendor/valuable/src/slice.rs b/vendor/valuable/src/slice.rs new file mode 100644 index 000000000..a6ada6e67 --- /dev/null +++ b/vendor/valuable/src/slice.rs @@ -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(()), +} diff --git a/vendor/valuable/src/structable.rs b/vendor/valuable/src/structable.rs new file mode 100644 index 000000000..611a7e58b --- /dev/null +++ b/vendor/valuable/src/structable.rs @@ -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>, +} diff --git a/vendor/valuable/src/tuplable.rs b/vendor/valuable/src/tuplable.rs new file mode 100644 index 000000000..8c7169ff2 --- /dev/null +++ b/vendor/valuable/src/tuplable.rs @@ -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 { .. }) + } +} diff --git a/vendor/valuable/src/valuable.rs b/vendor/valuable/src/valuable.rs new file mode 100644 index 000000000..e8fa5ddcf --- /dev/null +++ b/vendor/valuable/src/valuable.rs @@ -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) + } +} diff --git a/vendor/valuable/src/value.rs b/vendor/valuable/src/value.rs new file mode 100644 index 000000000..2db9cd10a --- /dev/null +++ b/vendor/valuable/src/value.rs @@ -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, +} diff --git a/vendor/valuable/src/visit.rs b/vendor/valuable/src/visit.rs new file mode 100644 index 000000000..f91a04cad --- /dev/null +++ b/vendor/valuable/src/visit.rs @@ -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()); +} |