From 4547b622d8d29df964fa2914213088b148c498fc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:32 +0200 Subject: Merging upstream version 1.67.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/writeable/.cargo-checksum.json | 1 + vendor/writeable/Cargo.lock | 654 +++++++++++++++++++++++++ vendor/writeable/Cargo.toml | 55 +++ vendor/writeable/LICENSE | 51 ++ vendor/writeable/README.md | 52 ++ vendor/writeable/benches/writeable.rs | 162 ++++++ vendor/writeable/examples/writeable_message.rs | 60 +++ vendor/writeable/src/impls.rs | 213 ++++++++ vendor/writeable/src/lib.rs | 390 +++++++++++++++ vendor/writeable/src/ops.rs | 291 +++++++++++ vendor/writeable/tests/writeable.rs | 34 ++ 11 files changed, 1963 insertions(+) create mode 100644 vendor/writeable/.cargo-checksum.json create mode 100644 vendor/writeable/Cargo.lock create mode 100644 vendor/writeable/Cargo.toml create mode 100644 vendor/writeable/LICENSE create mode 100644 vendor/writeable/README.md create mode 100644 vendor/writeable/benches/writeable.rs create mode 100644 vendor/writeable/examples/writeable_message.rs create mode 100644 vendor/writeable/src/impls.rs create mode 100644 vendor/writeable/src/lib.rs create mode 100644 vendor/writeable/src/ops.rs create mode 100644 vendor/writeable/tests/writeable.rs (limited to 'vendor/writeable') diff --git a/vendor/writeable/.cargo-checksum.json b/vendor/writeable/.cargo-checksum.json new file mode 100644 index 000000000..fe32e7569 --- /dev/null +++ b/vendor/writeable/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"efd045d3270108f64d75d49125e15940cf26b54c2944a13354698223d0c4ce17","Cargo.toml":"32b4d9ebb1a5c179aafb27b212e94203a1a2158b7c0387c712f25de31188b7a6","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"a47b1fa1adda09e2ca28f7f49878c61d8f2057b8f3c42af7d39d646fedbd9934","benches/writeable.rs":"edc81c5524f98e77f0b3a45545606c4b526f63791e6dd8f90c88679c758c4834","examples/writeable_message.rs":"58bf4007f54f9f80428af7b687531837a294aecde533395a0a4c4cf55c9cad7d","src/impls.rs":"c13310eaf5ecb2f4bb87896ea0ee4f060b7828e7ea07b333e69a397a03ef39ae","src/lib.rs":"056631819550bd2845084f97fa1ee6ae130927c7021af86c8cf83337ae638f77","src/ops.rs":"4e49b1e8a8da46c3bcfecbdcb91f6e2d87afab47b76fcc2c4f005bf3cef675f1","tests/writeable.rs":"6dc3db45174180bcbf8980e640525b441c31b0b9db238721888d8cc0bd998ded"},"package":"f8e6ab4f5da1b24daf2c590cfac801bacb27b15b4f050e84eb60149ea726f06b"} \ No newline at end of file diff --git a/vendor/writeable/Cargo.lock b/vendor/writeable/Cargo.lock new file mode 100644 index 000000000..c4110d507 --- /dev/null +++ b/vendor/writeable/Cargo.lock @@ -0,0 +1,654 @@ +# 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.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" +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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "once_cell", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "getrandom" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[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 = "icu_benchmark_macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c867656f2d9c90b13709ac88e710a9d6afe33998c1dfa22384bab8804e8b3d4" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +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.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" + +[[package]] +name = "plotters-svg" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +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.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "serde" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" + +[[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.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +dependencies = [ + "itoa 1.0.3", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[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-ident" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[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 = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "web-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +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" + +[[package]] +name = "writeable" +version = "0.5.0" +dependencies = [ + "criterion", + "icu_benchmark_macros", + "rand", +] diff --git a/vendor/writeable/Cargo.toml b/vendor/writeable/Cargo.toml new file mode 100644 index 000000000..1c9d41303 --- /dev/null +++ b/vendor/writeable/Cargo.toml @@ -0,0 +1,55 @@ +# 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" +name = "writeable" +version = "0.5.0" +authors = ["The ICU4X Project Developers"] +include = [ + "src/**/*", + "examples/**/*", + "benches/**/*", + "tests/**/*", + "Cargo.toml", + "LICENSE", + "README.md", +] +description = "A more efficient alternative to fmt::Display" +readme = "README.md" +license = "Unicode-DFS-2016" +repository = "https://github.com/unicode-org/icu4x" +resolver = "2" + +[package.metadata.docs.rs] +all-features = true + +[lib] +path = "src/lib.rs" +bench = false + +[[bench]] +name = "writeable" +harness = false + +[dev-dependencies.criterion] +version = "0.3" + +[dev-dependencies.icu_benchmark_macros] +version = "0.7" + +[dev-dependencies.rand] +version = "0.8" +features = ["small_rng"] + +[features] +bench = [] +default = [] diff --git a/vendor/writeable/LICENSE b/vendor/writeable/LICENSE new file mode 100644 index 000000000..9858d01ab --- /dev/null +++ b/vendor/writeable/LICENSE @@ -0,0 +1,51 @@ +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE + +See Terms of Use +for definitions of Unicode Inc.’s Data Files and Software. + +NOTICE TO USER: Carefully read the following legal agreement. +BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S +DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), +YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. +IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE +THE DATA FILES OR SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2022 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in https://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. + +— + +Portions of ICU4X may have been adapted from ICU4C and/or ICU4J. +ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others. diff --git a/vendor/writeable/README.md b/vendor/writeable/README.md new file mode 100644 index 000000000..55343c37e --- /dev/null +++ b/vendor/writeable/README.md @@ -0,0 +1,52 @@ +# writeable [![crates.io](https://img.shields.io/crates/v/writeable)](https://crates.io/crates/writeable) + +`writeable` is a utility crate of the [`ICU4X`] project. + +It includes [`Writeable`], a core trait representing an object that can be written to a +sink implementing `std::fmt::Write`. It is an alternative to `std::fmt::Display` with the +addition of a function indicating the number of bytes to be written. + +`Writeable` improves upon `std::fmt::Display` in two ways: + +1. More efficient, since the sink can pre-allocate bytes. +2. Smaller code, since the format machinery can be short-circuited. + +## Examples + +```rust +use std::fmt; +use writeable::assert_writeable_eq; +use writeable::LengthHint; +use writeable::Writeable; + +struct WelcomeMessage<'s> { + pub name: &'s str, +} + +impl<'s> Writeable for WelcomeMessage<'s> { + fn write_to(&self, sink: &mut W) -> fmt::Result { + sink.write_str("Hello, ")?; + sink.write_str(self.name)?; + sink.write_char('!')?; + Ok(()) + } + + fn writeable_length_hint(&self) -> LengthHint { + // "Hello, " + '!' + length of name + LengthHint::exact(8 + self.name.len()) + } +} + +let message = WelcomeMessage { name: "Alice" }; +assert_writeable_eq!(&message, "Hello, Alice!"); + +// Types implementing `Writeable` are recommended to also implement `fmt::Display`. +// This can be simply done by redirecting to the `Writeable` implementation: +writeable::impl_display_with_writeable!(WelcomeMessage<'_>); +``` + +[`ICU4X`]: ../icu/index.html + +## More Information + +For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x). diff --git a/vendor/writeable/benches/writeable.rs b/vendor/writeable/benches/writeable.rs new file mode 100644 index 000000000..fc433f895 --- /dev/null +++ b/vendor/writeable/benches/writeable.rs @@ -0,0 +1,162 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use std::fmt; +use writeable::LengthHint; +use writeable::Writeable; + +/// A sample type implementing Writeable +struct WriteableMessage<'s> { + message: &'s str, +} + +impl Writeable for WriteableMessage<'_> { + fn write_to(&self, sink: &mut W) -> fmt::Result { + sink.write_str(self.message) + } + + fn writeable_length_hint(&self) -> LengthHint { + LengthHint::exact(self.message.len()) + } +} + +writeable::impl_display_with_writeable!(WriteableMessage<'_>); + +/// A sample type implementing Display +struct DisplayMessage<'s> { + message: &'s str, +} + +impl fmt::Display for DisplayMessage<'_> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(self.message) + } +} + +const SHORT_STR: &str = "short"; +const MEDIUM_STR: &str = "this is a medium-length string"; +const LONG_STR: &str = "this string is very very very very very very very very very very very very very very very very very very very very very very very very long"; + +fn overview_bench(c: &mut Criterion) { + c.bench_function("writeable/overview", |b| { + b.iter(|| { + // This benchmark runs to_string on short, medium, and long strings in one batch. + WriteableMessage { + message: black_box(SHORT_STR), + } + .write_to_string(); + WriteableMessage { + message: black_box(MEDIUM_STR), + } + .write_to_string(); + WriteableMessage { + message: black_box(LONG_STR), + } + .write_to_string(); + }); + }); + + #[cfg(feature = "bench")] + { + writeable_benches(c); + writeable_dyn_benches(c); + display_benches(c); + } +} + +#[cfg(feature = "bench")] +fn writeable_benches(c: &mut Criterion) { + c.bench_function("writeable/to_string/short", |b| { + b.iter(|| { + WriteableMessage { + message: black_box(SHORT_STR), + } + .write_to_string() + .into_owned() + }); + }); + c.bench_function("writeable/to_string/medium", |b| { + b.iter(|| { + WriteableMessage { + message: black_box(MEDIUM_STR), + } + .write_to_string() + .into_owned() + }); + }); + c.bench_function("writeable/to_string/long", |b| { + b.iter(|| { + WriteableMessage { + message: black_box(LONG_STR), + } + .write_to_string() + .into_owned() + }); + }); +} + +#[cfg(feature = "bench")] +fn writeable_dyn_benches(c: &mut Criterion) { + // Same as `write_to_string`, but casts to a `dyn fmt::Write` + fn writeable_dyn_to_string(w: &impl Writeable) -> String { + let mut output = String::with_capacity(w.writeable_length_hint().capacity()); + w.write_to(&mut output as &mut dyn fmt::Write) + .expect("impl Write for String is infallible"); + output + } + + c.bench_function("writeable_dyn/to_string/short", |b| { + b.iter(|| { + writeable_dyn_to_string(&WriteableMessage { + message: black_box(SHORT_STR), + }) + }); + }); + c.bench_function("writeable_dyn/to_string/medium", |b| { + b.iter(|| { + writeable_dyn_to_string(&WriteableMessage { + message: black_box(MEDIUM_STR), + }) + }); + }); + c.bench_function("writeable_dyn/to_string/long", |b| { + b.iter(|| { + writeable_dyn_to_string(&WriteableMessage { + message: black_box(LONG_STR), + }) + }); + }); +} + +#[cfg(feature = "bench")] +fn display_benches(c: &mut Criterion) { + c.bench_function("display/to_string/short", |b| { + b.iter(|| { + DisplayMessage { + message: black_box(SHORT_STR), + } + .to_string() + }); + }); + c.bench_function("display/to_string/medium", |b| { + b.iter(|| { + DisplayMessage { + message: black_box(MEDIUM_STR), + } + .to_string() + }); + }); + c.bench_function("display/to_string/long", |b| { + b.iter(|| { + DisplayMessage { + message: black_box(LONG_STR), + } + .to_string() + }); + }); +} + +criterion_group!(benches, overview_bench,); +criterion_main!(benches); diff --git a/vendor/writeable/examples/writeable_message.rs b/vendor/writeable/examples/writeable_message.rs new file mode 100644 index 000000000..b342fdb26 --- /dev/null +++ b/vendor/writeable/examples/writeable_message.rs @@ -0,0 +1,60 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +// This example illustrates a very simple type implementing Writeable. +icu_benchmark_macros::static_setup!(); + +use std::fmt; +use writeable::*; + +struct WriteableMessage(W); + +const GREETING: Part = Part { + category: "meaning", + value: "greeting", +}; + +const EMOJI: Part = Part { + category: "meaning", + value: "emoji", +}; + +impl Writeable for WriteableMessage { + fn write_to_parts(&self, sink: &mut W) -> fmt::Result { + use fmt::Write; + sink.with_part(GREETING, |g| { + g.write_str("Hello")?; + g.write_str(" ")?; + self.0.write_to(g) + })?; + sink.write_char(' ')?; + sink.with_part(EMOJI, |e| e.write_char('😅')) + } + + fn writeable_length_hint(&self) -> LengthHint { + LengthHint::exact(11) + self.0.writeable_length_hint() + } +} + +impl fmt::Display for WriteableMessage { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.write_to(f) + } +} + +fn main() { + icu_benchmark_macros::main_setup!(); + + let (string, parts) = writeable_to_parts_for_test(&WriteableMessage("world")).unwrap(); + + assert_eq!(string, "Hello world 😅"); + + // Print the greeting only + let (start, end, _) = parts + .into_iter() + .find(|(_, _, part)| part == &GREETING) + .unwrap(); + println!("{}", &string[start..end]); +} diff --git a/vendor/writeable/src/impls.rs b/vendor/writeable/src/impls.rs new file mode 100644 index 000000000..649ede4d5 --- /dev/null +++ b/vendor/writeable/src/impls.rs @@ -0,0 +1,213 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::*; +use alloc::borrow::Cow; +use core::fmt; + +macro_rules! impl_write_num { + ($u:ty, $i:ty, $test:ident, $log10:ident) => { + impl $crate::Writeable for $u { + fn write_to(&self, sink: &mut W) -> core::fmt::Result { + let mut buf = [b'0'; $log10(<$u>::MAX) as usize + 1]; + let mut n = *self; + let mut i = buf.len(); + #[allow(clippy::indexing_slicing)] // n < 10^i + while n != 0 { + i -= 1; + buf[i] = b'0' + (n % 10) as u8; + n /= 10; + } + if i == buf.len() { + debug_assert_eq!(*self, 0); + i -= 1; + } + #[allow(clippy::indexing_slicing)] // buf is ASCII + let s = unsafe { core::str::from_utf8_unchecked(&buf[i..]) }; + sink.write_str(s) + } + + fn writeable_length_hint(&self) -> $crate::LengthHint { + $crate::LengthHint::exact(if *self == 0 { + 1 + } else { + $log10(*self) as usize + 1 + }) + } + } + + // TODO: use the library functions once stabilized. + // https://github.com/unicode-org/icu4x/issues/1428 + #[inline] + const fn $log10(s: $u) -> u32 { + let b = (<$u>::BITS - 1) - s.leading_zeros(); + // s ∈ [2ᵇ, 2ᵇ⁺¹-1] => ⌊log₁₀(s)⌋ ∈ [⌊log₁₀(2ᵇ)⌋, ⌊log₁₀(2ᵇ⁺¹-1)⌋] + // <=> ⌊log₁₀(s)⌋ ∈ [⌊log₁₀(2ᵇ)⌋, ⌊log₁₀(2ᵇ⁺¹)⌋] + // <=> ⌊log₁₀(s)⌋ ∈ [⌊b log₁₀(2)⌋, ⌊(b+1) log₁₀(2)⌋] + // The second line holds because there is no integer in + // [log₁₀(2ᶜ-1), log₁₀(2ᶜ)], if there were, there'd be some 10ⁿ in + // [2ᶜ-1, 2ᶜ], but it can't be 2ᶜ-1 due to parity nor 2ᶜ due to prime + // factors. + + const M: u32 = (core::f64::consts::LOG10_2 * (1 << 26) as f64) as u32; + let low = (b * M) >> 26; + let high = ((b + 1) * M) >> 26; + + // If the bounds aren't tight (e.g. 87 ∈ [64, 127] ⟹ ⌊log₁₀(87)⌋ ∈ [1,2]), + // compare to 10ʰ (100). This shouldn't happen too often as there are more + // powers of 2 than 10 (it happens for 14% of u32s). + if high == low { + low + } else if s < (10 as $u).pow(high) { + low + } else { + high + } + } + + impl $crate::Writeable for $i { + fn write_to(&self, sink: &mut W) -> core::fmt::Result { + if self.is_negative() { + sink.write_str("-")?; + } + self.unsigned_abs().write_to(sink) + } + + fn writeable_length_hint(&self) -> $crate::LengthHint { + $crate::LengthHint::exact(if self.is_negative() { 1 } else { 0 }) + + self.unsigned_abs().writeable_length_hint() + } + } + + #[test] + fn $test() { + use $crate::assert_writeable_eq; + assert_writeable_eq!(&(0 as $u), "0"); + assert_writeable_eq!(&(0 as $u), "0"); + assert_writeable_eq!(&(-0 as $i), "0"); + assert_writeable_eq!(&(1 as $u), "1"); + assert_writeable_eq!(&(1 as $i), "1"); + assert_writeable_eq!(&(-1 as $i), "-1"); + assert_writeable_eq!(&(10 as $u), "10"); + assert_writeable_eq!(&(10 as $i), "10"); + assert_writeable_eq!(&(-10 as $i), "-10"); + assert_writeable_eq!(&(99 as $u), "99"); + assert_writeable_eq!(&(99 as $i), "99"); + assert_writeable_eq!(&(-99 as $i), "-99"); + assert_writeable_eq!(&(100 as $u), "100"); + assert_writeable_eq!(&(-100 as $i), "-100"); + assert_writeable_eq!(&<$u>::MAX, <$u>::MAX.to_string()); + assert_writeable_eq!(&<$i>::MAX, <$i>::MAX.to_string()); + assert_writeable_eq!(&<$i>::MIN, <$i>::MIN.to_string()); + + use rand::{rngs::SmallRng, Rng, SeedableRng}; + let mut rng = SmallRng::seed_from_u64(4); // chosen by fair dice roll. + // guaranteed to be random. + for _ in 0..1000 { + let rand = rng.gen::<$u>(); + assert_writeable_eq!(rand, rand.to_string()); + } + } + }; +} + +impl_write_num!(u8, i8, test_u8, log10_u8); +impl_write_num!(u16, i16, test_u16, log10_u16); +impl_write_num!(u32, i32, test_u32, log10_u32); +impl_write_num!(u64, i64, test_u64, log10_u64); +impl_write_num!(u128, i128, test_u128, log10_u128); + +#[test] +fn assert_log10_approximation() { + for i in 1..u128::BITS { + assert_eq!(i * 59 / 196, 2f64.powf(i.into()).log10().floor() as u32); + } +} + +impl Writeable for str { + #[inline] + fn write_to(&self, sink: &mut W) -> fmt::Result { + sink.write_str(self) + } + + #[inline] + fn writeable_length_hint(&self) -> LengthHint { + LengthHint::exact(self.len()) + } + + /// Returns a borrowed `str`. + /// + /// # Examples + /// + /// ``` + /// use std::borrow::Cow; + /// use writeable::Writeable; + /// + /// let cow = "foo".write_to_string(); + /// assert!(matches!(cow, Cow::Borrowed(_))); + /// ``` + #[inline] + fn write_to_string(&self) -> Cow { + Cow::Borrowed(self) + } +} + +impl Writeable for String { + #[inline] + fn write_to(&self, sink: &mut W) -> fmt::Result { + sink.write_str(self) + } + + #[inline] + fn writeable_length_hint(&self) -> LengthHint { + LengthHint::exact(self.len()) + } + + #[inline] + fn write_to_string(&self) -> Cow { + Cow::Borrowed(self) + } +} + +impl<'a, T: Writeable + ?Sized> Writeable for &T { + #[inline] + fn write_to(&self, sink: &mut W) -> fmt::Result { + (*self).write_to(sink) + } + + #[inline] + fn write_to_parts(&self, sink: &mut W) -> fmt::Result { + (*self).write_to_parts(sink) + } + + #[inline] + fn writeable_length_hint(&self) -> LengthHint { + (*self).writeable_length_hint() + } + + #[inline] + fn write_to_string(&self) -> Cow { + (*self).write_to_string() + } +} + +#[test] +fn test_string_impls() { + fn check_writeable_slice(writeables: &[W]) { + assert_writeable_eq!(&writeables[0], ""); + assert_writeable_eq!(&writeables[1], "abc"); + } + + // test str impl + let arr: &[&str] = &["", "abc"]; + check_writeable_slice(arr); + + // test String impl + let arr: &[String] = &["".to_string(), "abc".to_string()]; + check_writeable_slice(arr); + + // test &T impl + let arr: &[&String] = &[&"".to_string(), &"abc".to_string()]; + check_writeable_slice(arr); +} diff --git a/vendor/writeable/src/lib.rs b/vendor/writeable/src/lib.rs new file mode 100644 index 000000000..66be7f33b --- /dev/null +++ b/vendor/writeable/src/lib.rs @@ -0,0 +1,390 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +// https://github.com/unicode-org/icu4x/blob/main/docs/process/boilerplate.md#library-annotations +#![cfg_attr(all(not(test), not(doc)), no_std)] +#![cfg_attr( + not(test), + deny( + clippy::indexing_slicing, + clippy::unwrap_used, + clippy::expect_used, + clippy::panic, + clippy::exhaustive_structs, + clippy::exhaustive_enums, + missing_debug_implementations, + ) +)] + +//! `writeable` is a utility crate of the [`ICU4X`] project. +//! +//! It includes [`Writeable`], a core trait representing an object that can be written to a +//! sink implementing `std::fmt::Write`. It is an alternative to `std::fmt::Display` with the +//! addition of a function indicating the number of bytes to be written. +//! +//! `Writeable` improves upon `std::fmt::Display` in two ways: +//! +//! 1. More efficient, since the sink can pre-allocate bytes. +//! 2. Smaller code, since the format machinery can be short-circuited. +//! +//! # Examples +//! +//! ``` +//! use std::fmt; +//! use writeable::assert_writeable_eq; +//! use writeable::LengthHint; +//! use writeable::Writeable; +//! +//! struct WelcomeMessage<'s> { +//! pub name: &'s str, +//! } +//! +//! impl<'s> Writeable for WelcomeMessage<'s> { +//! fn write_to(&self, sink: &mut W) -> fmt::Result { +//! sink.write_str("Hello, ")?; +//! sink.write_str(self.name)?; +//! sink.write_char('!')?; +//! Ok(()) +//! } +//! +//! fn writeable_length_hint(&self) -> LengthHint { +//! // "Hello, " + '!' + length of name +//! LengthHint::exact(8 + self.name.len()) +//! } +//! } +//! +//! let message = WelcomeMessage { name: "Alice" }; +//! assert_writeable_eq!(&message, "Hello, Alice!"); +//! +//! // Types implementing `Writeable` are recommended to also implement `fmt::Display`. +//! // This can be simply done by redirecting to the `Writeable` implementation: +//! writeable::impl_display_with_writeable!(WelcomeMessage<'_>); +//! ``` +//! +//! [`ICU4X`]: ../icu/index.html + +extern crate alloc; + +mod impls; +mod ops; + +use alloc::borrow::Cow; +use alloc::string::String; +use alloc::vec::Vec; +use core::fmt; + +/// A hint to help consumers of `Writeable` pre-allocate bytes before they call +/// [`write_to`](Writeable::write_to). +/// +/// This behaves like `Iterator::size_hint`: it is a tuple where the first element is the +/// lower bound, and the second element is the upper bound. If the upper bound is `None` +/// either there is no known upper bound, or the upper bound is larger than `usize`. +/// +/// `LengthHint` implements std`::ops::{Add, Mul}` and similar traits for easy composition. +/// During computation, the lower bound will saturate at `usize::MAX`, while the upper +/// bound will become `None` if `usize::MAX` is exceeded. +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[non_exhaustive] +pub struct LengthHint(pub usize, pub Option); + +impl LengthHint { + pub fn undefined() -> Self { + Self(0, None) + } + + /// `write_to` will use exactly n bytes. + pub fn exact(n: usize) -> Self { + Self(n, Some(n)) + } + + /// `write_to` will use at least n bytes. + pub fn at_least(n: usize) -> Self { + Self(n, None) + } + + /// `write_to` will use at most n bytes. + pub fn at_most(n: usize) -> Self { + Self(0, Some(n)) + } + + /// `write_to` will use between `n` and `m` bytes. + pub fn between(n: usize, m: usize) -> Self { + Self(Ord::min(n, m), Some(Ord::max(n, m))) + } + + /// Returns a recommendation for the number of bytes to pre-allocate. + /// If an upper bound exists, this is used, otherwise the lower bound + /// (which might be 0). + /// + /// # Examples + /// + /// ``` + /// use writeable::Writeable; + /// + /// fn pre_allocate_string(w: &impl Writeable) -> String { + /// String::with_capacity(w.writeable_length_hint().capacity()) + /// } + /// ``` + pub fn capacity(&self) -> usize { + self.1.unwrap_or(self.0) + } + + /// Returns whether the `LengthHint` indicates that the string is exactly 0 bytes long. + pub fn is_zero(&self) -> bool { + self.1 == Some(0) + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[allow(clippy::exhaustive_structs)] // stable +pub struct Part { + pub category: &'static str, + pub value: &'static str, +} + +/// A sink that supports annotating parts of the string with `Part`s. +pub trait PartsWrite: fmt::Write { + type SubPartsWrite: PartsWrite + ?Sized; + + fn with_part( + &mut self, + part: Part, + f: impl FnMut(&mut Self::SubPartsWrite) -> fmt::Result, + ) -> fmt::Result; +} + +/// `Writeable` is an alternative to `std::fmt::Display` with the addition of a length function. +pub trait Writeable { + /// Writes a string to the given sink. Errors from the sink are bubbled up. + /// The default implementation delegates to `write_to_parts`, and discards any + /// `Part` annotations. + fn write_to(&self, sink: &mut W) -> fmt::Result { + struct CoreWriteAsPartsWrite(W); + impl fmt::Write for CoreWriteAsPartsWrite { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.0.write_str(s) + } + + fn write_char(&mut self, c: char) -> fmt::Result { + self.0.write_char(c) + } + } + + impl PartsWrite for CoreWriteAsPartsWrite { + type SubPartsWrite = CoreWriteAsPartsWrite; + + fn with_part( + &mut self, + _part: Part, + mut f: impl FnMut(&mut Self::SubPartsWrite) -> fmt::Result, + ) -> fmt::Result { + f(self) + } + } + + self.write_to_parts(&mut CoreWriteAsPartsWrite(sink)) + } + + /// Write bytes and `Part` annotations to the given sink. Errors from the + /// sink are bubbled up. The default implementation delegates to `write_to`, + /// and doesn't produce any `Part` annotations. + fn write_to_parts(&self, sink: &mut S) -> fmt::Result { + self.write_to(sink) + } + + /// Returns a hint for the number of UTF-8 bytes that will be written to the sink. + /// + /// Override this method if it can be computed quickly. + fn writeable_length_hint(&self) -> LengthHint { + LengthHint::undefined() + } + + /// Creates a new `String` with the data from this `Writeable`. Like `ToString`, + /// but smaller and faster. + /// + /// The default impl allocates an owned `String`. However, if it is possible to return a + /// borrowed string, overwrite this method to return a `Cow::Borrowed`. + /// + /// To remove the `Cow` wrapper, call `.into_owned()` or `.as_str()` as appropriate. + /// + /// # Examples + /// + /// Inspect a `Writeable` before writing it to the sink: + /// + /// ``` + /// use core::fmt::{Result, Write}; + /// use writeable::Writeable; + /// + /// fn write_if_ascii(w: &W, sink: &mut S) -> Result + /// where + /// W: Writeable + ?Sized, + /// S: Write + ?Sized, + /// { + /// let s = w.write_to_string(); + /// if s.is_ascii() { + /// sink.write_str(&s) + /// } else { + /// Ok(()) + /// } + /// } + /// ``` + /// + /// Convert the `Writeable` into a fully owned `String`: + /// + /// ``` + /// use writeable::Writeable; + /// + /// fn make_string(w: &impl Writeable) -> String { + /// w.write_to_string().into_owned() + /// } + /// ``` + fn write_to_string(&self) -> Cow { + let mut output = String::with_capacity(self.writeable_length_hint().capacity()); + let _ = self.write_to(&mut output); + Cow::Owned(output) + } +} + +/// Implements [`Display`](core::fmt::Display) for types that implement [`Writeable`]. +/// +/// It's recommended to do this for every [`Writeable`] type, as it will add +/// support for `core::fmt` features like [`fmt!`](std::fmt), +/// [`print!`](std::print), [`write!`](std::write), etc. +#[macro_export] +macro_rules! impl_display_with_writeable { + ($type:ty) => { + /// This trait is implemented for compatibility with [`fmt!`](alloc::fmt). + /// To create a string, [`Writeable::write_to_string`] is usually more efficient. + impl core::fmt::Display for $type { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + $crate::Writeable::write_to(&self, f) + } + } + }; +} + +/// Testing macros for types implementing Writeable. The first argument should be a +/// `Writeable`, the second argument a string, and the third argument (*_parts_eq only) +/// a list of parts (`[(usize, usize, Part)]`). +/// +/// The macros tests for equality of string content, parts (*_parts_eq only), and +/// verify the size hint. +/// +/// # Examples +/// +/// ``` +/// # use writeable::Writeable; +/// # use writeable::LengthHint; +/// # use writeable::Part; +/// # use writeable::assert_writeable_eq; +/// # use writeable::assert_writeable_parts_eq; +/// # use std::fmt::{self, Write}; +/// +/// const WORD: Part = Part { +/// category: "foo", +/// value: "word", +/// }; +/// +/// struct Demo; +/// impl Writeable for Demo { +/// fn write_to_parts(&self, sink: &mut S) -> fmt::Result { +/// sink.with_part(WORD, |w| w.write_str("foo")) +/// } +/// fn writeable_length_hint(&self) -> LengthHint { +/// LengthHint::exact(3) +/// } +/// } +/// +/// writeable::impl_display_with_writeable!(Demo); +/// +/// assert_writeable_eq!(&Demo, "foo"); +/// assert_writeable_eq!(&Demo, "foo", "Message: {}", "Hello World"); +/// +/// assert_writeable_parts_eq!(&Demo, "foo", [(0, 3, WORD)]); +/// assert_writeable_parts_eq!(&Demo, "foo", [(0, 3, WORD)], "Message: {}", "Hello World"); +/// ``` +#[macro_export] +macro_rules! assert_writeable_eq { + ($actual_writeable:expr, $expected_str:expr $(,)?) => { + $crate::assert_writeable_eq!($actual_writeable, $expected_str, ""); + }; + ($actual_writeable:expr, $expected_str:expr, $($arg:tt)+) => {{ + let actual_writeable = &$actual_writeable; + let (actual_str, _) = $crate::writeable_to_parts_for_test(actual_writeable).unwrap(); + assert_eq!(actual_str, $expected_str, $($arg)*); + assert_eq!(actual_str, $crate::Writeable::write_to_string(actual_writeable), $($arg)+); + let length_hint = $crate::Writeable::writeable_length_hint(actual_writeable); + assert!(length_hint.0 <= actual_str.len(), $($arg)*); + if let Some(upper) = length_hint.1 { + assert!(actual_str.len() <= upper, $($arg)*); + } + }}; +} + +/// See [`assert_writeable_eq`]. +#[macro_export] +macro_rules! assert_writeable_parts_eq { + ($actual_writeable:expr, $expected_str:expr, $expected_parts:expr $(,)?) => { + $crate::assert_writeable_parts_eq!($actual_writeable, $expected_str, $expected_parts, ""); + }; + ($actual_writeable:expr, $expected_str:expr, $expected_parts:expr, $($arg:tt)+) => {{ + let actual_writeable = &$actual_writeable; + let (actual_str, actual_parts) = $crate::writeable_to_parts_for_test(actual_writeable).unwrap(); + assert_eq!(actual_str, $expected_str, $($arg)+); + assert_eq!(actual_str, $crate::Writeable::write_to_string(actual_writeable), $($arg)+); + assert_eq!(actual_parts, $expected_parts, $($arg)+); + let length_hint = $crate::Writeable::writeable_length_hint(actual_writeable); + assert!(length_hint.0 <= actual_str.len(), $($arg)+); + if let Some(upper) = length_hint.1 { + assert!(actual_str.len() <= upper, $($arg)+); + } + }}; +} + +#[doc(hidden)] +#[allow(clippy::type_complexity)] +pub fn writeable_to_parts_for_test( + writeable: &W, +) -> Result<(String, Vec<(usize, usize, Part)>), fmt::Error> { + struct State { + string: alloc::string::String, + parts: Vec<(usize, usize, Part)>, + } + + impl fmt::Write for State { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.string.write_str(s) + } + fn write_char(&mut self, c: char) -> fmt::Result { + self.string.write_char(c) + } + } + + impl PartsWrite for State { + type SubPartsWrite = Self; + fn with_part( + &mut self, + part: Part, + mut f: impl FnMut(&mut Self::SubPartsWrite) -> fmt::Result, + ) -> fmt::Result { + let start = self.string.len(); + f(self)?; + self.parts.push((start, self.string.len(), part)); + Ok(()) + } + } + + let mut state = State { + string: alloc::string::String::new(), + parts: Vec::new(), + }; + writeable.write_to_parts(&mut state)?; + + // Sort by first open and last closed + state + .parts + .sort_unstable_by_key(|(begin, end, _)| (*begin, end.wrapping_neg())); + Ok((state.string, state.parts)) +} diff --git a/vendor/writeable/src/ops.rs b/vendor/writeable/src/ops.rs new file mode 100644 index 000000000..3ed4406d7 --- /dev/null +++ b/vendor/writeable/src/ops.rs @@ -0,0 +1,291 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::LengthHint; + +impl core::ops::Add for LengthHint { + type Output = Self; + + fn add(self, other: LengthHint) -> Self { + LengthHint( + self.0.saturating_add(other.0), + match (self.1, other.1) { + (Some(c), Some(d)) => c.checked_add(d), + _ => None, + }, + ) + } +} + +impl core::ops::AddAssign for LengthHint { + fn add_assign(&mut self, other: Self) { + *self = *self + other; + } +} + +impl core::iter::Sum for LengthHint { + fn sum(iter: I) -> Self + where + I: Iterator, + { + iter.fold(LengthHint::exact(0), core::ops::Add::add) + } +} + +impl core::ops::Add for LengthHint { + type Output = Self; + + fn add(self, other: usize) -> Self { + Self( + self.0.saturating_add(other), + self.1.and_then(|upper| upper.checked_add(other)), + ) + } +} + +impl core::ops::AddAssign for LengthHint { + fn add_assign(&mut self, other: usize) { + *self = *self + other; + } +} + +impl core::ops::Mul for LengthHint { + type Output = Self; + + fn mul(self, other: usize) -> Self { + Self( + self.0.saturating_mul(other), + self.1.and_then(|upper| upper.checked_mul(other)), + ) + } +} + +impl core::ops::MulAssign for LengthHint { + fn mul_assign(&mut self, other: usize) { + *self = *self * other; + } +} + +impl core::ops::BitOr for LengthHint { + type Output = Self; + + /// Returns a new hint that is correct wherever `self` is correct, and wherever + /// `other` is correct. + /// + /// Example: + /// ``` + /// # use writeable::{LengthHint, Writeable}; + /// # use core::fmt; + /// # fn coin_flip() -> bool { true } + /// + /// struct NonDeterministicWriteable(String, String); + /// + /// impl Writeable for NonDeterministicWriteable { + /// fn write_to(&self, sink: &mut W) -> fmt::Result { + /// sink.write_str(if coin_flip() { &self.0 } else { &self.1 }) + /// } + /// + /// fn writeable_length_hint(&self) -> LengthHint { + /// LengthHint::exact(self.0.len()) | LengthHint::exact(self.1.len()) + /// } + /// } + /// + /// writeable::impl_display_with_writeable!(NonDeterministicWriteable); + /// ``` + fn bitor(self, other: LengthHint) -> Self { + LengthHint( + Ord::min(self.0, other.0), + match (self.1, other.1) { + (Some(c), Some(d)) => Some(Ord::max(c, d)), + _ => None, + }, + ) + } +} + +impl core::ops::BitOrAssign for LengthHint { + fn bitor_assign(&mut self, other: Self) { + *self = *self | other; + } +} + +impl core::iter::Sum for LengthHint { + fn sum(iter: I) -> Self + where + I: Iterator, + { + LengthHint::exact(iter.sum::()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_add() { + assert_eq!(LengthHint::exact(3) + 2, LengthHint::exact(5)); + assert_eq!( + LengthHint::exact(3) + LengthHint::exact(2), + LengthHint::exact(5) + ); + assert_eq!( + LengthHint::exact(3) + LengthHint::undefined(), + LengthHint::at_least(3) + ); + + assert_eq!(LengthHint::undefined() + 2, LengthHint::at_least(2)); + assert_eq!( + LengthHint::undefined() + LengthHint::exact(2), + LengthHint::at_least(2) + ); + assert_eq!( + LengthHint::undefined() + LengthHint::undefined(), + LengthHint::undefined() + ); + + assert_eq!( + LengthHint::at_least(15) + LengthHint::exact(3), + LengthHint::at_least(18) + ); + + assert_eq!( + LengthHint::at_least(15) + LengthHint::at_most(3), + LengthHint::at_least(15) + ); + + assert_eq!(LengthHint::between(48, 92) + 5, LengthHint::between(53, 97)); + + let mut len = LengthHint::exact(5); + len += LengthHint::exact(3); + assert_eq!(len, LengthHint::exact(8)); + len += 2; + assert_eq!(len, LengthHint::exact(10)); + len += LengthHint::undefined(); + assert_eq!(len, LengthHint::at_least(10)); + + len += LengthHint::exact(3); + assert_eq!(len, LengthHint::at_least(13)); + len += 2; + assert_eq!(len, LengthHint::at_least(15)); + len += LengthHint::undefined(); + assert_eq!(len, LengthHint::at_least(15)); + + assert_eq!( + LengthHint::between(usize::MAX - 10, usize::MAX - 5) + LengthHint::exact(20), + LengthHint::at_least(usize::MAX) + ); + } + + #[test] + fn test_sum() { + let lens = vec![ + LengthHint::exact(4), + LengthHint::exact(1), + LengthHint::exact(1), + ]; + assert_eq!( + lens.iter().copied().sum::(), + LengthHint::exact(6) + ); + + let lens = vec![ + LengthHint::exact(4), + LengthHint::undefined(), + LengthHint::at_least(1), + ]; + assert_eq!( + lens.iter().copied().sum::(), + LengthHint::at_least(5) + ); + + let lens = vec![ + LengthHint::exact(4), + LengthHint::undefined(), + LengthHint::at_most(1), + ]; + assert_eq!( + lens.iter().copied().sum::(), + LengthHint::at_least(4) + ); + + let lens = vec![4, 1, 1]; + assert_eq!( + lens.iter().copied().sum::(), + LengthHint::exact(6) + ); + } + + #[test] + fn test_mul() { + assert_eq!(LengthHint::exact(3) * 2, LengthHint::exact(6)); + + assert_eq!(LengthHint::undefined() * 2, LengthHint::undefined()); + + assert_eq!( + LengthHint::between(48, 92) * 2, + LengthHint::between(96, 184) + ); + + let mut len = LengthHint::exact(5); + len *= 2; + assert_eq!(len, LengthHint::exact(10)); + + assert_eq!( + LengthHint::between(usize::MAX - 10, usize::MAX - 5) * 2, + LengthHint::at_least(usize::MAX) + ); + } + + #[test] + fn test_bitor() { + assert_eq!( + LengthHint::exact(3) | LengthHint::exact(2), + LengthHint::between(2, 3) + ); + assert_eq!( + LengthHint::exact(3) | LengthHint::undefined(), + LengthHint::undefined() + ); + + assert_eq!( + LengthHint::undefined() | LengthHint::undefined(), + LengthHint::undefined() + ); + + assert_eq!( + LengthHint::exact(10) | LengthHint::exact(10), + LengthHint::exact(10) + ); + + assert_eq!( + LengthHint::at_least(15) | LengthHint::exact(3), + LengthHint::at_least(3) + ); + + assert_eq!( + LengthHint::at_least(15) | LengthHint::at_most(18), + LengthHint::undefined() + ); + + assert_eq!( + LengthHint::at_least(15) | LengthHint::at_least(18), + LengthHint::at_least(15) + ); + + assert_eq!( + LengthHint::at_most(15) | LengthHint::at_most(18), + LengthHint::at_most(18) + ); + + assert_eq!( + LengthHint::between(5, 10) | LengthHint::at_most(3), + LengthHint::at_most(10) + ); + + let mut len = LengthHint::exact(5); + len |= LengthHint::exact(3); + assert_eq!(len, LengthHint::between(5, 3)); + } +} diff --git a/vendor/writeable/tests/writeable.rs b/vendor/writeable/tests/writeable.rs new file mode 100644 index 000000000..b48310e88 --- /dev/null +++ b/vendor/writeable/tests/writeable.rs @@ -0,0 +1,34 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use std::fmt; +use writeable::assert_writeable_eq; +use writeable::LengthHint; +use writeable::Writeable; + +/// A sample type implementing Writeable +struct WriteableMessage<'s> { + message: &'s str, +} + +impl Writeable for WriteableMessage<'_> { + fn write_to(&self, sink: &mut W) -> fmt::Result { + sink.write_str(self.message) + } + + fn writeable_length_hint(&self) -> LengthHint { + LengthHint::exact(self.message.len()) + } +} + +writeable::impl_display_with_writeable!(WriteableMessage<'_>); + +#[test] +fn test_basic() { + let input_string = "hello world"; + let message = WriteableMessage { + message: input_string, + }; + assert_writeable_eq!(&message, input_string); +} -- cgit v1.2.3