diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index b2b308b..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,1771 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "anyhow" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" - -[[package]] -name = "assert2" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf98d1183406dcb8f8b545e1f24829d75c1a9d35eec4b86309a22aa8b6d8e95" -dependencies = [ - "assert2-macros", - "is-terminal", - "yansi", -] - -[[package]] -name = "assert2-macros" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c55bdf3e6f792f8f1c750bb6886b7ca40fa5a354ddb7a4dee550b93985a9235" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", -] - -[[package]] -name = "async-trait" -version = "0.1.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "axum" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" -dependencies = [ - "async-trait", - "axum-core", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "basic-toml" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "ciborium" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" - -[[package]] -name = "ciborium-ll" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "bitflags 1.3.2", - "clap_lex", - "indexmap 1.9.3", - "textwrap", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "criterion" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" -dependencies = [ - "anes", - "atty", - "cast", - "ciborium", - "clap", - "criterion-plot", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "fastwebsockets" -version = "0.7.0" -dependencies = [ - "anyhow", - "assert2", - "async-trait", - "axum", - "axum-core", - "base64", - "bytes", - "criterion", - "http", - "http-body-util", - "hyper", - "hyper-util", - "pin-project", - "rand", - "rustls-pemfile", - "sha1", - "simdutf8", - "thiserror", - "tokio", - "tokio-rustls", - "trybuild", - "utf-8", - "webpki-roots", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "h2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 2.2.3", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" - -[[package]] -name = "http" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "tokio", - "want", -] - -[[package]] -name = "hyper-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tracing", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" -dependencies = [ - "equivalent", - "hashbrown 0.14.3", -] - -[[package]] -name = "is-terminal" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" -dependencies = [ - "hermit-abi 0.3.4", - "rustix", - "windows-sys 0.52.0", -] - -[[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 = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "js-sys" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" -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.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" - -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.4", - "libc", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "plotters" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" - -[[package]] -name = "plotters-svg" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -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.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - -[[package]] -name = "ring" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" -dependencies = [ - "bitflags 2.4.2", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.21.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring 0.17.7", - "rustls-webpki 0.101.7", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64", -] - -[[package]] -name = "rustls-webpki" -version = "0.100.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6a5fc258f1c1276dfe3016516945546e2d5383911efc0fc4f1cdc5df3a4ae3" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[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.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", -] - -[[package]] -name = "semver" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" - -[[package]] -name = "serde" -version = "1.0.195" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.195" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "serde_json" -version = "1.0.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" -dependencies = [ - "itoa", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - -[[package]] -name = "thiserror" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[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 = "tokio" -version = "1.35.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "trybuild" -version = "1.0.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9d3ba662913483d6722303f619e75ea10b7855b0f8e0d72799cf8621bb488f" -dependencies = [ - "basic-toml", - "glob", - "once_cell", - "serde", - "serde_derive", - "serde_json", - "termcolor", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "walkdir" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[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.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.48", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" - -[[package]] -name = "web-sys" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" -dependencies = [ - "rustls-webpki 0.100.3", -] - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/Cargo.toml b/Cargo.toml index 0b1a256..8d06325 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,10 +46,15 @@ axum-core = { version = "0.4.3", optional = true } http = { version = "1", optional = true } async-trait = { version = "0.1", optional = true } + +# Futrues integration +futures-lite = {version = "2.2.0", optional = true} + [features] -default = ["simd"] +default = ["simd", "upgrade", "unstable-split"] simd = ["simdutf8/aarch64_neon"] upgrade = ["hyper", "pin-project", "base64", "sha1", "hyper-util", "http-body-util"] +futures = ["futures-lite"] unstable-split = [] # Axum integration with_axum = ["axum-core", "http", "async-trait"] @@ -65,9 +70,13 @@ assert2 = "0.3.4" trybuild = "1.0.80" criterion = "0.4.0" anyhow = "1.0.71" -webpki-roots = "0.23.0" +webpki-roots = "0.25.2" bytes = "1.4.0" axum = "0.7.4" +async-std = {version ="1.12.0", features=["attributes", "unstable"]} +futures-rustls = "0.24.0" +futures-lite = "2.2.0" + [[bench]] name = "unmask" diff --git a/examples/autobahn_client.rs b/examples/autobahn_client.rs index 89d578b..d8280b2 100644 --- a/examples/autobahn_client.rs +++ b/examples/autobahn_client.rs @@ -24,9 +24,17 @@ use hyper::header::CONNECTION; use hyper::header::UPGRADE; use hyper::upgrade::Upgraded; use hyper::Request; -use hyper_util::rt::TokioIo; + +#[cfg(not(feature = "futures"))] +use hyper_util::rt::TokioIo as IoWrapper; +#[cfg(not(feature = "futures"))] use tokio::net::TcpStream; +#[cfg(feature = "futures")] +use async_std::net::TcpStream; +#[cfg(feature = "futures")] +use fastwebsockets::FuturesIo as IoWrapper; + struct SpawnExecutor; impl hyper::rt::Executor for SpawnExecutor @@ -39,7 +47,7 @@ where } } -async fn connect(path: &str) -> Result>> { +async fn connect(path: &str) -> Result>> { let stream = TcpStream::connect("localhost:9001").await?; let req = Request::builder() @@ -67,7 +75,19 @@ async fn get_case_count() -> Result { Ok(std::str::from_utf8(&msg.payload)?.parse()?) } -#[tokio::main(flavor = "current_thread")] +macro_rules! runtime_main { + ($($body:tt)*) => { + #[cfg(feature = "futures")] + #[async_std::main] + $($body)* + + #[cfg(not(feature = "futures"))] + #[tokio::main] + $($body)* + }; +} + +runtime_main! { async fn main() -> Result<()> { let count = get_case_count().await?; @@ -103,3 +123,4 @@ async fn main() -> Result<()> { Ok(()) } +} diff --git a/examples/echo_server.rs b/examples/echo_server.rs index aefe739..0a294e9 100644 --- a/examples/echo_server.rs +++ b/examples/echo_server.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(feature = "futures")] +use async_std::net::TcpListener; use fastwebsockets::upgrade; use fastwebsockets::OpCode; use fastwebsockets::WebSocketError; @@ -22,6 +24,7 @@ use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::Request; use hyper::Response; +#[cfg(not(feature = "futures"))] use tokio::net::TcpListener; async fn handle_client(fut: upgrade::UpgradeFut) -> Result<(), WebSocketError> { @@ -45,36 +48,67 @@ async fn server_upgrade( ) -> Result>, WebSocketError> { let (response, fut) = upgrade::upgrade(&mut req)?; + #[cfg(not(feature = "futures"))] tokio::task::spawn(async move { if let Err(e) = tokio::task::unconstrained(handle_client(fut)).await { eprintln!("Error in websocket connection: {}", e); } }); + #[cfg(feature = "futures")] + async_std::task::spawn(async move { + if let Err(e) = handle_client(fut).await { + eprintln!("Error in websocket connection: {}", e); + } + }); Ok(response) } fn main() -> Result<(), WebSocketError> { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .build() - .unwrap(); + #[cfg(feature = "futures")] + { + async_std::task::block_on(async move { + let listener = TcpListener::bind("127.0.0.1:8080").await?; + println!("Server started, listening on {}", "127.0.0.1:8080"); + loop { + let (stream, _) = listener.accept().await?; + println!("client connected"); + async_std::task::spawn(async move { + let io = fastwebsockets::FuturesIo::new(stream); + let conn_fut = http1::Builder::new() + .serve_connection(io, service_fn(server_upgrade)) + .with_upgrades(); + if let Err(e) = conn_fut.await { + println!("An error occured {:?}", e); + } + }); + } + }) + } - rt.block_on(async move { - let listener = TcpListener::bind("127.0.0.1:8080").await?; - println!("Server started, listening on {}", "127.0.0.1:8080"); - loop { - let (stream, _) = listener.accept().await?; - println!("Client connected"); - tokio::spawn(async move { - let io = hyper_util::rt::TokioIo::new(stream); - let conn_fut = http1::Builder::new() - .serve_connection(io, service_fn(server_upgrade)) - .with_upgrades(); - if let Err(e) = conn_fut.await { - println!("An error occurred: {:?}", e); - } - }); - } - }) + #[cfg(not(feature = "futures"))] + { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .build() + .unwrap(); + + rt.block_on(async move { + let listener = TcpListener::bind("127.0.0.1:8080").await?; + println!("Server started, listening on {}", "127.0.0.1:8080"); + loop { + let (stream, _) = listener.accept().await?; + println!("Client connected"); + tokio::spawn(async move { + let io = hyper_util::rt::TokioIo::new(stream); + let conn_fut = http1::Builder::new() + .serve_connection(io, service_fn(server_upgrade)) + .with_upgrades(); + if let Err(e) = conn_fut.await { + println!("An error occurred: {:?}", e); + } + }); + } + }) + } } diff --git a/examples/echo_server_split.rs b/examples/echo_server_split.rs index 034f781..7c91dc5 100644 --- a/examples/echo_server_split.rs +++ b/examples/echo_server_split.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(feature = "futures")] +use async_std::net::TcpListener; use fastwebsockets::upgrade; use fastwebsockets::FragmentCollectorRead; use fastwebsockets::OpCode; @@ -23,11 +25,16 @@ use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::Request; use hyper::Response; +#[cfg(not(feature = "futures"))] use tokio::net::TcpListener; async fn handle_client(fut: upgrade::UpgradeFut) -> Result<(), WebSocketError> { let ws = fut.await?; + + #[cfg(not(feature = "futures"))] let (rx, mut tx) = ws.split(tokio::io::split); + #[cfg(feature = "futures")] + let (rx, mut tx) = ws.split(futures_lite::io::split); let mut rx = FragmentCollectorRead::new(rx); loop { // Empty send_fn is fine because the benchmark does not create obligated writes. @@ -47,41 +54,74 @@ async fn handle_client(fut: upgrade::UpgradeFut) -> Result<(), WebSocketError> { Ok(()) } + async fn server_upgrade( mut req: Request, ) -> Result>, WebSocketError> { let (response, fut) = upgrade::upgrade(&mut req)?; + #[cfg(not(feature = "futures"))] tokio::task::spawn(async move { if let Err(e) = tokio::task::unconstrained(handle_client(fut)).await { eprintln!("Error in websocket connection: {}", e); } }); + #[cfg(feature = "futures")] + async_std::task::spawn(async move { + if let Err(e) = handle_client(fut).await { + eprintln!("Error in websocket connection: {}", e); + } + }); + Ok(response) } fn main() -> Result<(), WebSocketError> { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_io() - .build() - .unwrap(); + #[cfg(feature = "futures")] + { + async_std::task::block_on(async move { + let listener = TcpListener::bind("127.0.0.1:8080").await?; + println!("Server started, listening on {}", "127.0.0.1:8080"); + loop { + let (stream, _) = listener.accept().await?; + println!("client connected"); + async_std::task::spawn(async move { + let io = fastwebsockets::FuturesIo::new(stream); + let conn_fut = http1::Builder::new() + .serve_connection(io, service_fn(server_upgrade)) + .with_upgrades(); + if let Err(e) = conn_fut.await { + println!("An error occured {:?}", e); + } + }); + } + }) + } - rt.block_on(async move { - let listener = TcpListener::bind("127.0.0.1:8080").await?; - println!("Server started, listening on {}", "127.0.0.1:8080"); - loop { - let (stream, _) = listener.accept().await?; - println!("Client connected"); - tokio::spawn(async move { - let io = hyper_util::rt::TokioIo::new(stream); - let conn_fut = http1::Builder::new() - .serve_connection(io, service_fn(server_upgrade)) - .with_upgrades(); - if let Err(e) = conn_fut.await { - println!("An error occurred: {:?}", e); - } - }); - } - }) + #[cfg(not(feature = "futures"))] + { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .build() + .unwrap(); + + rt.block_on(async move { + let listener = TcpListener::bind("127.0.0.1:8080").await?; + println!("Server started, listening on {}", "127.0.0.1:8080"); + loop { + let (stream, _) = listener.accept().await?; + println!("Client connected"); + tokio::spawn(async move { + let io = hyper_util::rt::TokioIo::new(stream); + let conn_fut = http1::Builder::new() + .serve_connection(io, service_fn(server_upgrade)) + .with_upgrades(); + if let Err(e) = conn_fut.await { + println!("An error occurred: {:?}", e); + } + }); + } + }) + } } diff --git a/examples/tls_client.rs b/examples/tls_client.rs index 75456bc..3d10fde 100644 --- a/examples/tls_client.rs +++ b/examples/tls_client.rs @@ -11,11 +11,26 @@ use hyper::header::CONNECTION; use hyper::header::UPGRADE; use hyper::upgrade::Upgraded; use hyper::Request; -use hyper_util::rt::TokioIo; + +#[cfg(feature = "futures")] +use async_std::net::TcpStream; +#[cfg(feature = "futures")] +use fastwebsockets::FuturesIo as IoWrapper; +#[cfg(feature = "futures")] +use futures_rustls::{ + rustls::{self, ClientConfig, OwnedTrustAnchor, RootCertStore}, + TlsConnector, +}; + +#[cfg(not(feature = "futures"))] +use hyper_util::rt::TokioIo as IoWrapper; +#[cfg(not(feature = "futures"))] use tokio::net::TcpStream; -use tokio_rustls::rustls::ClientConfig; -use tokio_rustls::rustls::OwnedTrustAnchor; -use tokio_rustls::TlsConnector; +#[cfg(not(feature = "futures"))] +use tokio_rustls::{ + rustls::{self, ClientConfig, OwnedTrustAnchor, RootCertStore}, + TlsConnector, +}; struct SpawnExecutor; @@ -25,41 +40,44 @@ where Fut::Output: Send + 'static, { fn execute(&self, fut: Fut) { + #[cfg(not(feature = "futures"))] tokio::task::spawn(fut); + + #[cfg(feature = "futures")] + async_std::task::spawn(fut); } } fn tls_connector() -> Result { - let mut root_store = tokio_rustls::rustls::RootCertStore::empty(); - - root_store.add_server_trust_anchors( - webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| { + let mut root_store = RootCertStore::empty(); + root_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map( + |ta| { OwnedTrustAnchor::from_subject_spki_name_constraints( ta.subject, ta.spki, ta.name_constraints, ) - }), - ); + }, + )); let config = ClientConfig::builder() .with_safe_defaults() .with_root_certificates(root_store) .with_no_client_auth(); - Ok(TlsConnector::from(Arc::new(config))) } -async fn connect(domain: &str) -> Result>> { +async fn connect( + domain: &str, +) -> Result>> { let mut addr = String::from(domain); addr.push_str(":9443"); // Port number for binance stream let tcp_stream = TcpStream::connect(&addr).await?; let tls_connector = tls_connector().unwrap(); - let domain = - tokio_rustls::rustls::ServerName::try_from(domain).map_err(|_| { - std::io::Error::new(std::io::ErrorKind::InvalidInput, "invalid dnsname") - })?; + let domain = rustls::ServerName::try_from(domain).map_err(|_| { + std::io::Error::new(std::io::ErrorKind::InvalidInput, "invalid dnsname") + })?; let tls_stream = tls_connector.connect(domain, tcp_stream).await?; @@ -81,7 +99,19 @@ async fn connect(domain: &str) -> Result>> { Ok(FragmentCollector::new(ws)) } -#[tokio::main(flavor = "current_thread")] +macro_rules! runtime_main { + ($($body:tt)*) => { + #[cfg(feature = "futures")] + #[async_std::main] + $($body)* + + #[cfg(not(feature = "futures"))] + #[tokio::main] + $($body)* + }; +} + +runtime_main! { async fn main() -> Result<()> { let domain = "data-stream.binance.com"; let mut ws = connect(domain).await?; @@ -111,3 +141,4 @@ async fn main() -> Result<()> { } Ok(()) } +} diff --git a/examples/tls_server.rs b/examples/tls_server.rs index 532a258..e88948a 100644 --- a/examples/tls_server.rs +++ b/examples/tls_server.rs @@ -23,11 +23,20 @@ use hyper::service::service_fn; use hyper::Request; use hyper::Response; use std::sync::Arc; + +#[cfg(not(feature = "futures"))] use tokio::net::TcpListener; -use tokio_rustls::rustls; -use tokio_rustls::rustls::Certificate; -use tokio_rustls::rustls::PrivateKey; -use tokio_rustls::TlsAcceptor; +#[cfg(not(feature = "futures"))] +use tokio_rustls::{ + rustls, rustls::Certificate, rustls::PrivateKey, TlsAcceptor, +}; + +#[cfg(feature = "futures")] +use async_std::net::TcpListener; +#[cfg(feature = "futures")] +use futures_rustls::{ + rustls, rustls::Certificate, rustls::PrivateKey, TlsAcceptor, +}; async fn handle_client(fut: upgrade::UpgradeFut) -> Result<()> { let mut ws = fut.await?; @@ -53,12 +62,20 @@ async fn server_upgrade( ) -> Result>> { let (response, fut) = upgrade::upgrade(&mut req)?; + #[cfg(not(feature = "futures"))] tokio::spawn(async move { if let Err(e) = handle_client(fut).await { eprintln!("Error in websocket connection: {}", e); } }); + #[cfg(feature = "futures")] + async_std::task::spawn(async move { + if let Err(e) = handle_client(fut).await { + eprintln!("Error in websocket connection: {}", e); + } + }); + Ok(response) } @@ -81,7 +98,19 @@ fn tls_acceptor() -> Result { Ok(TlsAcceptor::from(Arc::new(config))) } -#[tokio::main(flavor = "current_thread")] +macro_rules! runtime_main { + ($($body:tt)*) => { + #[cfg(feature = "futures")] + #[async_std::main] + $($body)* + + #[cfg(not(feature = "futures"))] + #[tokio::main(flavor = "current_thread")] + $($body)* + }; +} + +runtime_main! { async fn main() -> Result<()> { let acceptor = tls_acceptor()?; let listener = TcpListener::bind("127.0.0.1:8080").await?; @@ -92,7 +121,10 @@ async fn main() -> Result<()> { let acceptor = acceptor.clone(); tokio::spawn(async move { let stream = acceptor.accept(stream).await.unwrap(); + #[cfg(not(feature = "futures"))] let io = hyper_util::rt::TokioIo::new(stream); + #[cfg(feature = "futures")] + let io = fastwebsockets::FuturesIo::new(stream); let conn_fut = http1::Builder::new() .serve_connection(io, service_fn(server_upgrade)) .with_upgrades(); @@ -102,3 +134,4 @@ async fn main() -> Result<()> { }); } } +} diff --git a/src/fragment.rs b/src/fragment.rs index 1e5147a..b6f51f8 100644 --- a/src/fragment.rs +++ b/src/fragment.rs @@ -17,14 +17,13 @@ use std::future::Future; use crate::error::WebSocketError; use crate::frame::Frame; +use crate::rt; use crate::OpCode; use crate::ReadHalf; use crate::WebSocket; #[cfg(feature = "unstable-split")] use crate::WebSocketRead; use crate::WriteHalf; -use tokio::io::AsyncReadExt; -use tokio::io::AsyncWriteExt; pub enum Fragment { Text(Option, Vec), @@ -85,7 +84,7 @@ impl<'f, S> FragmentCollector { /// Creates a new `FragmentCollector` with the provided `WebSocket`. pub fn new(ws: WebSocket) -> FragmentCollector where - S: AsyncReadExt + AsyncWriteExt + Unpin, + S: rt::Read + rt::Write + Unpin, { let (stream, read_half, write_half) = ws.into_parts_internal(); FragmentCollector { @@ -101,7 +100,7 @@ impl<'f, S> FragmentCollector { /// Text frames payload is guaranteed to be valid UTF-8. pub async fn read_frame(&mut self) -> Result, WebSocketError> where - S: AsyncReadExt + AsyncWriteExt + Unpin, + S: rt::Read + rt::Write + Unpin, { loop { let (res, obligated_send) = @@ -130,7 +129,7 @@ impl<'f, S> FragmentCollector { frame: Frame<'f>, ) -> Result<(), WebSocketError> where - S: AsyncReadExt + AsyncWriteExt + Unpin, + S: rt::Read + rt::Write + Unpin, { self.write_half.write_frame(&mut self.stream, frame).await?; Ok(()) @@ -149,7 +148,7 @@ impl<'f, S> FragmentCollectorRead { /// Creates a new `FragmentCollector` with the provided `WebSocket`. pub fn new(ws: WebSocketRead) -> FragmentCollectorRead where - S: AsyncReadExt + Unpin, + S: rt::Read + Unpin, { let (stream, read_half) = ws.into_parts_internal(); FragmentCollectorRead { @@ -167,7 +166,7 @@ impl<'f, S> FragmentCollectorRead { send_fn: &mut impl FnMut(Frame<'f>) -> R, ) -> Result, WebSocketError> where - S: AsyncReadExt + Unpin, + S: rt::Read + Unpin, E: Into>, R: Future>, { diff --git a/src/frame.rs b/src/frame.rs index 9ac133d..39fd53d 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -12,12 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use tokio::io::AsyncWriteExt; - use bytes::BytesMut; use core::ops::Deref; -use crate::WebSocketError; +use crate::{rt, WebSocketError}; macro_rules! repr_u8 { ($(#[$meta:meta])* $vis:vis enum $name:ident { @@ -290,7 +288,7 @@ impl<'f> Frame<'f> { stream: &mut S, ) -> Result<(), std::io::Error> where - S: AsyncWriteExt + Unpin, + S: rt::Write + Unpin, { use std::io::IoSlice; diff --git a/src/handshake.rs b/src/handshake.rs index dd7cc7b..24d496d 100644 --- a/src/handshake.rs +++ b/src/handshake.rs @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(feature = "futures")] +use crate::rt::FuturesIo; +#[cfg(feature = "futures")] +use futures_lite::{AsyncRead, AsyncWrite}; use hyper::body::Incoming; use hyper::upgrade::Upgraded; use hyper::Request; @@ -21,9 +25,10 @@ use hyper::StatusCode; use base64::engine::general_purpose::STANDARD; use base64::Engine; +#[cfg(not(feature = "futures"))] use hyper_util::rt::TokioIo; -use tokio::io::AsyncRead; -use tokio::io::AsyncWrite; +#[cfg(not(feature = "futures"))] +use tokio::io::{AsyncRead, AsyncWrite}; use std::future::Future; use std::pin::Pin; @@ -82,6 +87,8 @@ use crate::WebSocketError; /// } /// } /// ``` + +#[cfg(not(feature = "futures"))] pub async fn client( executor: &E, request: Request, @@ -115,6 +122,40 @@ where } } +#[cfg(feature = "futures")] +pub async fn client( + executor: &E, + request: Request, + socket: S, +) -> Result<(WebSocket>, Response), WebSocketError> +where + S: AsyncRead + AsyncWrite + Send + Unpin + 'static, + E: hyper::rt::Executor + Send>>>, + B: hyper::body::Body + 'static + Send, + B::Data: Send, + B::Error: Into>, +{ + let (mut sender, conn) = + hyper::client::conn::http1::handshake(FuturesIo::new(socket)).await?; + let fut = Box::pin(async move { + if let Err(e) = conn.with_upgrades().await { + eprintln!("Error polling connection: {}", e); + } + }); + executor.execute(fut); + + let mut response = sender.send_request(request).await?; + verify(&response)?; + + match hyper::upgrade::on(&mut response).await { + Ok(upgraded) => Ok(( + WebSocket::after_handshake(FuturesIo::new(upgraded), Role::Client), + response, + )), + Err(e) => Err(e.into()), + } +} + /// Generate a random key for the `Sec-WebSocket-Key` header. pub fn generate_key() -> String { // a base64-encoded (see Section 4 of [RFC4648]) value that, diff --git a/src/lib.rs b/src/lib.rs index 2f25d9c..ca599de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -159,20 +159,19 @@ mod frame; #[cfg_attr(docsrs, doc(cfg(feature = "upgrade")))] pub mod handshake; mod mask; +mod rt; +#[cfg(feature = "futures")] +pub use rt::FuturesIo; /// HTTP upgrades. #[cfg(feature = "upgrade")] #[cfg_attr(docsrs, doc(cfg(feature = "upgrade")))] pub mod upgrade; - use bytes::Buf; use bytes::BytesMut; #[cfg(feature = "unstable-split")] use std::future::Future; -use tokio::io::AsyncReadExt; -use tokio::io::AsyncWriteExt; - pub use crate::close::CloseCode; pub use crate::error::WebSocketError; pub use crate::fragment::FragmentCollector; @@ -228,8 +227,8 @@ pub fn after_handshake_split( role: Role, ) -> (WebSocketRead, WebSocketWrite) where - R: AsyncWriteExt + Unpin, - W: AsyncWriteExt + Unpin, + R: rt::Read + Unpin, + W: rt::Write + Unpin, { ( WebSocketRead { @@ -289,7 +288,7 @@ impl<'f, S> WebSocketRead { send_fn: &mut impl FnMut(Frame<'f>) -> R, ) -> Result where - S: AsyncReadExt + Unpin, + S: rt::Read + Unpin, E: Into>, R: Future>, { @@ -336,7 +335,7 @@ impl<'f, S> WebSocketWrite { frame: Frame<'f>, ) -> Result<(), WebSocketError> where - S: AsyncWriteExt + Unpin, + S: rt::Write + Unpin, { self.write_half.write_frame(&mut self.stream, frame).await } @@ -371,7 +370,7 @@ impl<'f, S> WebSocket { /// ``` pub fn after_handshake(stream: S, role: Role) -> Self where - S: AsyncReadExt + AsyncWriteExt + Unpin, + S: rt::Read + rt::Write + Unpin, { Self { stream, @@ -389,9 +388,9 @@ impl<'f, S> WebSocket { split_fn: impl Fn(S) -> (R, W), ) -> (WebSocketRead, WebSocketWrite) where - S: AsyncReadExt + AsyncWriteExt + Unpin, - R: AsyncReadExt + Unpin, - W: AsyncWriteExt + Unpin, + S: rt::Read + rt::Write + Unpin, + R: rt::Read + Unpin, + W: rt::Write + Unpin, { let (stream, read, write) = self.into_parts_internal(); let (r, w) = split_fn(stream); @@ -487,7 +486,7 @@ impl<'f, S> WebSocket { frame: Frame<'f>, ) -> Result<(), WebSocketError> where - S: AsyncReadExt + AsyncWriteExt + Unpin, + S: rt::Read + rt::Write + Unpin, { self.write_half.write_frame(&mut self.stream, frame).await?; Ok(()) @@ -521,7 +520,7 @@ impl<'f, S> WebSocket { /// ``` pub async fn read_frame(&mut self) -> Result, WebSocketError> where - S: AsyncReadExt + AsyncWriteExt + Unpin, + S: rt::Read + rt::Write + Unpin, { loop { let (res, obligated_send) = @@ -570,7 +569,7 @@ impl ReadHalf { stream: &mut S, ) -> (Result>, WebSocketError>, Option>) where - S: AsyncReadExt + Unpin, + S: rt::Read + Unpin, { let mut frame = match self.parse_frame_header(stream).await { Ok(frame) => frame, @@ -632,7 +631,7 @@ impl ReadHalf { stream: &mut S, ) -> Result, WebSocketError> where - S: AsyncReadExt + Unpin, + S: rt::Read + Unpin, { macro_rules! eof { ($n:expr) => {{ @@ -739,7 +738,7 @@ impl WriteHalf { mut frame: Frame<'a>, ) -> Result<(), WebSocketError> where - S: AsyncWriteExt + Unpin, + S: rt::Write + Unpin, { if self.role == Role::Client && self.auto_apply_mask { frame.mask(); @@ -765,6 +764,10 @@ impl WriteHalf { #[cfg(test)] mod tests { use super::*; + #[cfg(feature = "futures")] + use async_std::net::TcpStream; + #[cfg(not(feature = "futures"))] + use tokio::net::TcpStream; const _: () = { const fn assert_unsync() { @@ -788,6 +791,6 @@ mod tests { // `$x` implements `AmbiguousIfImpl`. let _ = >::some_item; } - assert_unsync::>(); + assert_unsync::>(); }; } diff --git a/src/rt/hyper_compat.rs b/src/rt/hyper_compat.rs new file mode 100644 index 0000000..904bdcb --- /dev/null +++ b/src/rt/hyper_compat.rs @@ -0,0 +1,125 @@ +use core::slice; +use pin_project::pin_project; +use std::io; +use std::pin::Pin; +use std::task::{Context, Poll}; + +#[pin_project] +pub struct FuturesIo { + #[pin] + inner: T, +} + +impl FuturesIo { + pub fn new(inner: T) -> Self { + Self { inner } + } + + pub fn inner(&self) -> &T { + &self.inner + } + + pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { + self.project().inner + } +} + +impl hyper::rt::Write for FuturesIo +where + T: futures_lite::AsyncWrite, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + self.get_pin_mut().poll_write(cx, buf) + } + + fn poll_flush( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + self.get_pin_mut().poll_flush(cx) + } + + fn poll_shutdown( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + self.get_pin_mut().poll_close(cx) + } +} + +impl hyper::rt::Read for FuturesIo +where + T: futures_lite::AsyncRead, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + mut buf: hyper::rt::ReadBufCursor<'_>, + ) -> Poll> { + let read_slice = unsafe { + let buffer = buf.as_mut(); + buffer.as_mut_ptr().write_bytes(0, buffer.len()); + slice::from_raw_parts_mut(buffer.as_mut_ptr() as *mut u8, buffer.len()) + }; + self.get_pin_mut().poll_read(cx, read_slice).map(|n| { + if let Ok(n) = n { + unsafe { buf.advance(n) }; + } + Ok(()) + }) + } +} + +impl futures_lite::AsyncRead for FuturesIo +where + T: hyper::rt::Read, +{ + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + let mut buffer = hyper::rt::ReadBuf::new(buf); + let filled = match hyper::rt::Read::poll_read( + self.get_pin_mut(), + cx, + buffer.unfilled(), + ) { + Poll::Ready(Ok(())) => buffer.filled().len(), + Poll::Pending => return Poll::Pending, + Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), + }; + Poll::Ready(Ok(filled)) + } +} + +impl futures_lite::AsyncWrite for FuturesIo +where + T: hyper::rt::Write, +{ + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + hyper::rt::Write::poll_write(self.get_pin_mut(), cx, buf) + } + + fn poll_flush( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_flush(self.get_pin_mut(), cx) + } + + fn poll_close( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + hyper::rt::Write::poll_shutdown(self.get_pin_mut(), cx) + } +} diff --git a/src/rt/io.rs b/src/rt/io.rs new file mode 100644 index 0000000..4b4630d --- /dev/null +++ b/src/rt/io.rs @@ -0,0 +1,79 @@ +#[cfg(feature = "futures")] +use super::read_buf; +use bytes::BufMut; +use std::future::Future; +use std::io::{self, IoSlice}; + +// Read bytes from a source +pub trait Read { + fn read_buf<'a, B: BufMut + ?Sized>( + &'a mut self, + buf: &'a mut B, + ) -> impl Future> + '_; +} + +pub trait Write { + fn write_vectored<'a>( + &'a mut self, + bufs: &'a [IoSlice<'_>], + ) -> impl Future> + '_; + + fn write_all<'a>( + &'a mut self, + src: &'a [u8], + ) -> impl Future> + '_; +} + +#[cfg(not(feature = "futures"))] +impl Read for T { + fn read_buf<'a, B: BufMut + ?Sized>( + &'a mut self, + buf: &'a mut B, + ) -> impl Future> + '_ { + self.read_buf(buf) + } +} + +#[cfg(not(feature = "futures"))] +impl Write for T { + fn write_all<'a>( + &'a mut self, + src: &'a [u8], + ) -> impl Future> + '_ { + self.write_all(src) + } + + fn write_vectored<'a>( + &'a mut self, + bufs: &'a [IoSlice<'_>], + ) -> impl Future> + '_ { + self.write_vectored(bufs) + } +} + +#[cfg(feature = "futures")] +impl Read for T { + fn read_buf<'a, B: BufMut + ?Sized>( + &'a mut self, + buf: &'a mut B, + ) -> impl Future> + '_ { + read_buf::read_buf(self, buf) + } +} + +#[cfg(feature = "futures")] +impl Write for T { + fn write_all<'a>( + &'a mut self, + src: &'a [u8], + ) -> impl Future> + '_ { + self.write_all(src) + } + + fn write_vectored<'a>( + &'a mut self, + bufs: &'a [IoSlice<'_>], + ) -> impl Future> + '_ { + self.write_vectored(bufs) + } +} diff --git a/src/rt/mod.rs b/src/rt/mod.rs new file mode 100644 index 0000000..4f22740 --- /dev/null +++ b/src/rt/mod.rs @@ -0,0 +1,11 @@ +mod io; +pub use io::{Read, Write}; + +#[cfg(feature = "futures")] +mod read_buf; + +#[cfg(all(feature = "upgrade", feature = "futures"))] +mod hyper_compat; + +#[cfg(all(feature = "upgrade", feature = "futures"))] +pub use hyper_compat::FuturesIo; diff --git a/src/rt/read_buf.rs b/src/rt/read_buf.rs new file mode 100644 index 0000000..2656c4e --- /dev/null +++ b/src/rt/read_buf.rs @@ -0,0 +1,59 @@ +use bytes::BufMut; +use futures_lite::ready; +use futures_lite::AsyncRead; +use pin_project::pin_project; +use std::future::Future; +use std::marker::PhantomPinned; +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::{io, mem}; + +#[pin_project] +#[derive(Debug)] +#[must_use = "Futures do nothing unless polled"] +pub(crate) struct ReadBuf<'a, R: ?Sized, B: ?Sized> { + reader: &'a mut R, + buf: &'a mut B, + #[pin] + _pin: PhantomPinned, +} + +pub(crate) fn read_buf<'a, R, B>( + reader: &'a mut R, + buf: &'a mut B, +) -> ReadBuf<'a, R, B> +where + R: AsyncRead + Unpin + ?Sized, + B: BufMut + ?Sized, +{ + ReadBuf { + reader, + buf, + _pin: PhantomPinned, + } +} + +impl Future for ReadBuf<'_, R, B> +where + R: AsyncRead + Unpin + ?Sized, + B: BufMut + ?Sized, +{ + type Output = io::Result; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.project(); + if !this.buf.has_remaining_mut() { + return Poll::Ready(Ok(0)); + } + let n = { + let spare = unsafe { + &mut *(this.buf.chunk_mut() as *mut _ as *mut [mem::MaybeUninit]) + }; + let mut buf = tokio::io::ReadBuf::uninit(spare); + ready!(Pin::new(this.reader).poll_read(cx, buf.initialize_unfilled()))? + }; + unsafe { + this.buf.advance_mut(n); + } + Poll::Ready(Ok(n)) + } +} diff --git a/src/upgrade.rs b/src/upgrade.rs index 5f1d1fc..f7be3ed 100644 --- a/src/upgrade.rs +++ b/src/upgrade.rs @@ -18,6 +18,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(feature = "futures")] +use crate::rt::FuturesIo as AsyncIo; use base64; use base64::engine::general_purpose::STANDARD; use base64::Engine; @@ -25,7 +27,8 @@ use http_body_util::Empty; use hyper::body::Bytes; use hyper::Request; use hyper::Response; -use hyper_util::rt::TokioIo; +#[cfg(not(feature = "futures"))] +use hyper_util::rt::TokioIo as AsyncIo; use pin_project::pin_project; use sha1::Digest; use sha1::Sha1; @@ -216,7 +219,7 @@ fn trim_end(data: &[u8]) -> &[u8] { } impl std::future::Future for UpgradeFut { - type Output = Result>, Error>; + type Output = Result>, Error>; fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { let this = self.project(); @@ -225,7 +228,7 @@ impl std::future::Future for UpgradeFut { Poll::Ready(x) => x, }; Poll::Ready(Ok(WebSocket::after_handshake( - TokioIo::new(upgraded?), + AsyncIo::new(upgraded?), Role::Server, ))) } diff --git a/tests/concurrency.rs b/tests/concurrency.rs index 5132509..a3e4dc1 100644 --- a/tests/concurrency.rs +++ b/tests/concurrency.rs @@ -23,16 +23,29 @@ use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::Request; use hyper::Response; -use hyper_util::rt::TokioIo; -use tokio::net::TcpListener; - +#[cfg(not(feature = "futures"))] +use hyper_util::rt::TokioIo as IoWrapper; + +#[cfg(feature = "futures")] +use fastwebsockets::FuturesIo as IoWrapper; + +#[cfg(not(feature = "futures"))] +use tokio::{ + net::{TcpListener, TcpStream}, + spawn, +}; + +#[cfg(feature = "futures")] +use async_std::{ + net::{TcpListener, TcpStream}, + task::spawn, +}; use fastwebsockets::handshake; use fastwebsockets::WebSocket; use hyper::header::CONNECTION; use hyper::header::UPGRADE; use hyper::upgrade::Upgraded; use std::future::Future; -use tokio::net::TcpStream; const N_CLIENTS: usize = 20; @@ -64,14 +77,21 @@ async fn server_upgrade( .unwrap() .parse() .unwrap(); + + #[cfg(not(feature = "futures"))] tokio::spawn(async move { handle_client(client_id, fut).await.unwrap(); }); + #[cfg(feature = "futures")] + async_std::task::spawn(async move { + handle_client(client_id, fut).await.unwrap(); + }); + Ok(response) } -async fn connect(client_id: usize) -> Result>> { +async fn connect(client_id: usize) -> Result>> { let stream = TcpStream::connect("localhost:8080").await?; let req = Request::builder() @@ -108,30 +128,52 @@ async fn start_client(client_id: usize) -> Result<()> { Ok(()) } -#[tokio::test(flavor = "multi_thread")] -async fn test() -> Result<()> { - let listener = TcpListener::bind("127.0.0.1:8080").await?; - println!("Server started, listening on {}", "127.0.0.1:8080"); - tokio::spawn(async move { - loop { - let (stream, _) = listener.accept().await.unwrap(); - tokio::spawn(async move { - let io = TokioIo::new(stream); - let conn_fut = http1::Builder::new() - .serve_connection(io, service_fn(server_upgrade)) - .with_upgrades(); - conn_fut.await.unwrap(); - }); +macro_rules! runtime_test { + ($($body:tt)*) => { + #[cfg(feature = "futures")] + #[async_std::test] + $($body)* + + #[cfg(not(feature = "futures"))] + #[tokio::test(flavor = "multi_thread")] + $($body)* + }; +} + +runtime_test! { + async fn test() -> Result<()> { + let listener = TcpListener::bind("127.0.0.1:8080").await?; + println!("Server started, listening on {}", "127.0.0.1:8080"); + spawn(async move { + loop { + let (stream, _) = listener.accept().await.unwrap(); + spawn(async move { + let io = IoWrapper::new(stream); + let conn_fut = http1::Builder::new() + .serve_connection(io, service_fn(server_upgrade)) + .with_upgrades(); + conn_fut.await.unwrap(); + }); + } + }); + let mut tasks = Vec::with_capacity(N_CLIENTS); + for client in 0..N_CLIENTS { + tasks.push(spawn(start_client(client))); + } + for handle in tasks { + + #[cfg(not(feature = "futures"))] + { + handle.await.unwrap().unwrap() + } + #[cfg(feature = "futures")] + { + + handle.await.unwrap() + } + } + Ok(()) } - }); - let mut tasks = Vec::with_capacity(N_CLIENTS); - for client in 0..N_CLIENTS { - tasks.push(tokio::spawn(start_client(client))); - } - for handle in tasks { - handle.await.unwrap().unwrap(); - } - Ok(()) } struct SpawnExecutor; @@ -142,6 +184,10 @@ where Fut::Output: Send + 'static, { fn execute(&self, fut: Fut) { + #[cfg(not(feature = "futures"))] tokio::task::spawn(fut); + + #[cfg(feature = "futures")] + async_std::task::spawn(fut); } } diff --git a/tests/split.rs b/tests/split.rs index de04c4a..022822a 100644 --- a/tests/split.rs +++ b/tests/split.rs @@ -13,9 +13,19 @@ // limitations under the License. use anyhow::Result; +#[cfg(feature = "futures")] +use async_std::{ + net::{TcpListener, TcpStream}, + sync::Mutex, + task::spawn, +}; use fastwebsockets::upgrade; use fastwebsockets::Frame; +#[cfg(feature = "futures")] +use fastwebsockets::FuturesIo as IoWrapper; use fastwebsockets::OpCode; +#[cfg(feature = "futures")] +use futures_lite::io::{self, ReadHalf, WriteHalf}; use http_body_util::Empty; use hyper::body::Bytes; use hyper::body::Incoming; @@ -23,8 +33,15 @@ use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::Request; use hyper::Response; -use hyper_util::rt::TokioIo; -use tokio::net::TcpListener; +#[cfg(not(feature = "futures"))] +use hyper_util::rt::TokioIo as IoWrapper; +#[cfg(not(feature = "futures"))] +use tokio::{ + io::{self, ReadHalf, WriteHalf}, + net::{TcpListener, TcpStream}, + spawn, + sync::Mutex, +}; use fastwebsockets::handshake; use fastwebsockets::WebSocketRead; @@ -32,13 +49,10 @@ use fastwebsockets::WebSocketWrite; use hyper::header::CONNECTION; use hyper::header::UPGRADE; use hyper::upgrade::Upgraded; -use tokio::sync::Mutex; use std::future::Future; use std::rc::Rc; -use tokio::net::TcpStream; - const N_CLIENTS: usize = 20; async fn handle_client( @@ -69,7 +83,8 @@ async fn server_upgrade( .unwrap() .parse() .unwrap(); - tokio::spawn(async move { + + spawn(async move { handle_client(client_id, fut).await.unwrap(); }); @@ -79,8 +94,8 @@ async fn server_upgrade( async fn connect( client_id: usize, ) -> Result<( - WebSocketRead>>, - WebSocketWrite>>, + WebSocketRead>>, + WebSocketWrite>>, )> { let stream = TcpStream::connect("localhost:8080").await?; @@ -98,8 +113,8 @@ async fn connect( .header("Sec-WebSocket-Version", "13") .body(Empty::::new())?; - let (ws, _) = handshake::client(&SpawnExecutor, req, stream).await?; - Ok(ws.split(tokio::io::split)) + let (ws, _) = handshake::client(&TestExecutor, req, stream).await?; + Ok(ws.split(io::split)) } async fn start_client(client_id: usize) -> Result<()> { @@ -124,40 +139,58 @@ async fn start_client(client_id: usize) -> Result<()> { Ok(()) } -#[tokio::test(flavor = "multi_thread")] -async fn test() -> Result<()> { - let listener = TcpListener::bind("127.0.0.1:8080").await?; - println!("Server started, listening on {}", "127.0.0.1:8080"); - tokio::spawn(async move { - loop { - let (stream, _) = listener.accept().await.unwrap(); - tokio::spawn(async move { - let io = TokioIo::new(stream); - let conn_fut = http1::Builder::new() - .serve_connection(io, service_fn(server_upgrade)) - .with_upgrades(); - conn_fut.await.unwrap(); - }); +macro_rules! runtime_test { + ($($body:tt)*) => { + #[cfg(feature = "futures")] + #[async_std::test] + $($body)* + + #[cfg(not(feature = "futures"))] + #[tokio::test(flavor = "multi_thread")] + $($body)* + }; +} + +runtime_test! { + async fn test() -> Result<()> { + let listener = TcpListener::bind("127.0.0.1:8080").await?; + println!("Server started, listening on {}", "127.0.0.1:8080"); + spawn(async move { + loop { + let (stream, _) = listener.accept().await.unwrap(); + spawn(async move { + let io = IoWrapper::new(stream); + let conn_fut = http1::Builder::new() + .serve_connection(io, service_fn(server_upgrade)) + .with_upgrades(); + conn_fut.await.unwrap(); + }); + } + }); + + let mut tasks = Vec::with_capacity(N_CLIENTS); + for client in 0..N_CLIENTS { + tasks.push(start_client(client)); + } + for handle in tasks { + handle.await.unwrap(); + } + Ok(()) } - }); - let mut tasks = Vec::with_capacity(N_CLIENTS); - for client in 0..N_CLIENTS { - tasks.push(start_client(client)); - } - for handle in tasks { - handle.await.unwrap(); - } - Ok(()) } -struct SpawnExecutor; +struct TestExecutor; -impl hyper::rt::Executor for SpawnExecutor +impl hyper::rt::Executor for TestExecutor where Fut: Future + Send + 'static, Fut::Output: Send + 'static, { fn execute(&self, fut: Fut) { + #[cfg(not(feature = "futures"))] tokio::task::spawn(fut); + + #[cfg(feature = "futures")] + async_std::task::spawn(fut); } } diff --git a/tests/ui/01-send-executor.rs b/tests/ui/01-send-executor.rs index ae44193..ebf3874 100644 --- a/tests/ui/01-send-executor.rs +++ b/tests/ui/01-send-executor.rs @@ -1,14 +1,21 @@ use fastwebsockets::WebSocket; +use http_body_util::Empty; +use hyper::body::Bytes; use hyper::header::CONNECTION; use hyper::header::UPGRADE; use hyper::upgrade::Upgraded; -use hyper::body::Bytes; -use http_body_util::Empty; use hyper::Request; use std::future::Future; -use tokio::net::TcpStream; -use hyper_util::rt::tokio::TokioIo; + use anyhow::Result; +#[cfg(feature = "futures")] +use async_std::{net::TcpStream, task::spawn}; +#[cfg(feature = "futures")] +use fastwebsockets::FuturesIo as IoWrapper; +#[cfg(not(feature = "futures"))] +use hyper_util::rt::tokio::TokioIo as IoWrapper; +#[cfg(not(feature = "futures"))] +use tokio::{net::TcpStream, spawn}; struct SpawnExecutor; @@ -18,13 +25,11 @@ where Fut::Output: Send + 'static, { fn execute(&self, fut: Fut) { - tokio::task::spawn(fut); + spawn(fut); } } -async fn connect( - path: &str, -) -> Result>> { +async fn connect(path: &str) -> Result>> { let stream = TcpStream::connect("localhost:9001").await?; let req = Request::builder() diff --git a/tests/ui/02-!send-executor.rs b/tests/ui/02-!send-executor.rs index 7bc40a5..09def0d 100644 --- a/tests/ui/02-!send-executor.rs +++ b/tests/ui/02-!send-executor.rs @@ -1,14 +1,21 @@ +use anyhow::Result; use fastwebsockets::WebSocket; +use http_body_util::Empty; +use hyper::body::Bytes; use hyper::header::CONNECTION; use hyper::header::UPGRADE; use hyper::upgrade::Upgraded; -use hyper::body::Bytes; -use http_body_util::Empty; use hyper::Request; use std::future::Future; -use tokio::net::TcpStream; -use hyper_util::rt::tokio::TokioIo; -use anyhow::Result; + +#[cfg(feature = "futures")] +use async_std::{net::TcpStream, task::spawn_local}; +#[cfg(feature = "futures")] +use fastwebsockets::FuturesIo as IoWrapper; +#[cfg(not(feature = "futures"))] +use hyper_util::rt::tokio::TokioIo as IoWrapper; +#[cfg(not(feature = "futures"))] +use tokio::{net::TcpStream, task::spawn_local}; struct SpawnLocalExecutor; @@ -22,9 +29,7 @@ where } } -async fn connect( - path: &str, -) -> Result>> { +async fn connect(path: &str) -> Result>> { let stream = TcpStream::connect("localhost:9001").await?; let req = Request::builder() diff --git a/tests/upgrade.rs b/tests/upgrade.rs index 2611b0b..341a1a0 100644 --- a/tests/upgrade.rs +++ b/tests/upgrade.rs @@ -9,10 +9,24 @@ use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::Request; use hyper::Response; -use hyper_util::rt::TokioIo; + +#[cfg(feature = "futures")] +use fastwebsockets::FuturesIo as IoWrapper; +#[cfg(not(feature = "futures"))] +use hyper_util::rt::TokioIo as IoWrapper; + +#[cfg(feature = "futures")] +use async_std::{ + net::{TcpListener, TcpStream}, + task::spawn, +}; use std::future::Future; use std::net::Ipv6Addr; -use tokio::net::TcpStream; +#[cfg(not(feature = "futures"))] +use tokio::{ + net::{TcpListener, TcpStream}, + spawn, +}; use assert2::assert; use assert2::let_assert; @@ -25,26 +39,38 @@ where Fut::Output: Send + 'static, { fn execute(&self, fut: Fut) { - tokio::spawn(fut); + spawn(fut); } } -#[tokio::test] +macro_rules! runtime_test { + ($($body:tt)*) => { + #[cfg(feature = "futures")] + #[async_std::test] + $($body)* + + #[cfg(not(feature = "futures"))] + #[tokio::test] + $($body)* + }; +} + +runtime_test! { async fn hyper() { // Bind a TCP listener to an ephemeral port. let_assert!( Ok(listener) = - tokio::net::TcpListener::bind((Ipv6Addr::LOCALHOST, 0u16)).await + TcpListener::bind((Ipv6Addr::LOCALHOST, 0u16)).await ); let_assert!(Ok(bind_addr) = listener.local_addr()); // Spawn the server in a task. - tokio::spawn(async move { + spawn(async move { loop { let (stream, _) = listener.accept().await.unwrap(); - let io = TokioIo::new(stream); + let io = IoWrapper::new(stream); - tokio::spawn(async move { + spawn(async move { if let Err(err) = http1::Builder::new() .serve_connection(io, service_fn(upgrade_websocket)) .with_upgrades() @@ -86,6 +112,7 @@ async fn hyper() { let_assert!(Ok(close_frame) = stream.read_frame().await); assert!(close_frame.opcode == fastwebsockets::OpCode::Close); } +} async fn upgrade_websocket( mut request: Request, @@ -93,7 +120,7 @@ async fn upgrade_websocket( assert!(fastwebsockets::upgrade::is_upgrade_request(&request) == true); let (response, stream) = fastwebsockets::upgrade::upgrade(&mut request)?; - tokio::spawn(async move { + spawn(async move { let_assert!(Ok(mut stream) = stream.await); assert!(let Ok(()) = stream.write_frame(fastwebsockets::Frame::text(b"Hello!".to_vec().into())).await); let_assert!(Ok(reply) = stream.read_frame().await);