diff --git a/Cargo.lock b/Cargo.lock index 00f5517..baa42e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,188 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "actix-codec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" +dependencies = [ + "bitflags 2.5.0", + "bytes", + "futures-core", + "futures-sink", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-http" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae682f693a9cd7b058f2b0b5d9a6d7728a8555779bedbbc35dd88528611d020" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "ahash", + "base64 0.22.1", + "bitflags 2.5.0", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "futures-core", + "h2 0.3.26", + "http 0.2.12", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand", + "sha1", + "smallvec", + "tokio", + "tokio-util", + "tracing", + "zstd", +] + +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "actix-router" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" +dependencies = [ + "bytestring", + "cfg-if", + "http 0.2.12", + "regex", + "regex-lite", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" +dependencies = [ + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b02303ce8d4e8be5b855af6cf3c3a08f3eff26880faad82bab679c22d3650cb5" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "socket2 0.5.7", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +dependencies = [ + "futures-core", + "paste", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1988c02af8d2b718c05bc4aeb6a66395b7cdf32858c2c71131e5637a8c05a9ff" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "ahash", + "bytes", + "bytestring", + "cfg-if", + "cookie 0.16.2", + "derive_more", + "encoding_rs", + "futures-core", + "futures-util", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "regex-lite", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2 0.5.7", + "time", + "url", +] + +[[package]] +name = "actix-web-codegen" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "addr2line" version = "0.21.0" @@ -17,12 +199,97 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "aligned-vec" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "amq-protocol" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0234884b3641db74d22ccc20fc2594db5f23d7d41ade5c93d7ee33d200960c" +dependencies = [ + "amq-protocol-tcp", + "amq-protocol-types", + "amq-protocol-uri", + "cookie-factory", + "nom", + "serde", +] + +[[package]] +name = "amq-protocol-tcp" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "265dca43d9dbb3d5bbb0b3ef1b0cd9044ce3aa5d697d5b66cde974d1f6063f09" +dependencies = [ + "amq-protocol-uri", + "tcp-stream", + "tracing", +] + +[[package]] +name = "amq-protocol-types" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7412353b58923fa012feb9a64ccc0c811747babee2e5a2fd63eb102dc8054c3" +dependencies = [ + "cookie-factory", + "nom", + "serde", + "serde_json", +] + +[[package]] +name = "amq-protocol-uri" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be91352c805d5704784e079117d5291fd5bf2569add53c914ebce6d1a795d33" +dependencies = [ + "amq-protocol-types", + "percent-encoding", + "url", +] + [[package]] name = "anyhow" version = "1.0.86" @@ -52,6 +319,145 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand 2.1.0", + "futures-lite 2.3.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel", + "async-executor", + "async-io 2.3.3", + "async-lock 3.4.0", + "blocking", + "futures-lite 2.3.0", + "once_cell", +] + +[[package]] +name = "async-global-executor-trait" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33dd14c5a15affd2abcff50d84efd4009ada28a860f01c14f9d654f3e81b3f75" +dependencies = [ + "async-global-executor", + "async-trait", + "executor-trait", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.5.2", + "rustix 0.37.13", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +dependencies = [ + "async-lock 3.4.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.7.2", + "rustix 0.38.34", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-reactor-trait" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6012d170ad00de56c9ee354aef2e358359deb1ec504254e0e5a3774771de0e" +dependencies = [ + "async-io 1.13.0", + "async-trait", + "futures-core", + "reactor-trait", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -144,6 +550,49 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c12d1856e42f0d817a835fe55853957c85c8c8a470114029143d3f12671446e" +[[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 = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite 2.3.0", + "piper", +] + +[[package]] +name = "brotli" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "built" version = "0.7.3" @@ -180,6 +629,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "bytestring" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +dependencies = [ + "bytes", +] + [[package]] name = "cc" version = "1.0.97" @@ -224,6 +682,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie" version = "0.16.2" @@ -246,6 +719,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "cookie-factory" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" + [[package]] name = "cookie_store" version = "0.21.0" @@ -279,6 +758,15 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.4.2" @@ -319,6 +807,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[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 = "deranged" version = "0.3.11" @@ -328,6 +826,29 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[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 = "dirs-next" version = "2.0.0" @@ -349,6 +870,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "either" version = "1.12.0" @@ -405,6 +932,42 @@ dependencies = [ "str-buf", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] + +[[package]] +name = "executor-trait" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a1052dd43212a7777ec6a69b117da52f5e52f07aec47d00c1a2b33b85d06b08" +dependencies = [ + "async-trait", +] + [[package]] name = "exr" version = "1.72.0" @@ -444,6 +1007,15 @@ dependencies = [ "webdriver", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.1.0" @@ -485,6 +1057,8 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ + "futures-core", + "futures-sink", "spin 0.9.8", ] @@ -566,6 +1140,34 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.1.0", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -607,6 +1209,22 @@ dependencies = [ "slab", ] +[[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 = "get-port" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "888123007db34fbff15b5a347d46364dfbad531d6cb43de52cc0b62558f570e2" + [[package]] name = "getrandom" version = "0.2.14" @@ -634,6 +1252,25 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.5" @@ -679,7 +1316,13 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" name = "hermit-abi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "http" @@ -765,7 +1408,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -781,7 +1424,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.1", "httparse", @@ -817,7 +1460,7 @@ dependencies = [ "http 1.1.0", "hyper 1.4.1", "hyper-util", - "rustls 0.23.11", + "rustls 0.23.5", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -866,7 +1509,7 @@ dependencies = [ "http-body 1.0.1", "hyper 1.4.1", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower", "tower-service", @@ -942,6 +1585,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + [[package]] name = "interpolate_name" version = "0.2.4" @@ -953,6 +1605,17 @@ dependencies = [ "syn", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -998,6 +1661,34 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "lapin" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "209b09a06f4bd4952a0fd0594f90d53cf4496b062f59acc838a2823e1bb7d95c" +dependencies = [ + "amq-protocol", + "async-global-executor-trait", + "async-reactor-trait", + "async-trait", + "executor-trait", + "flume", + "futures-core", + "futures-io", + "parking_lot", + "pinky-swear", + "reactor-trait", + "serde", + "tracing", + "waker-fn", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1037,12 +1728,35 @@ dependencies = [ "libc", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "local-channel" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +dependencies = [ + "futures-core", + "futures-sink", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" + [[package]] name = "lock_api" version = "0.4.12" @@ -1122,6 +1836,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] @@ -1250,7 +1965,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -1313,6 +2028,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.2" @@ -1380,6 +2101,29 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pinky-swear" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cfae3ead413ca051a681152bd266438d3bfa301c9bdf836939a14c721bb2a21" +dependencies = [ + "doc-comment", + "flume", + "parking_lot", + "tracing", +] + +[[package]] +name = "piper" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +dependencies = [ + "atomic-waker", + "fastrand 2.1.0", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.30" @@ -1399,6 +2143,35 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" +dependencies = [ + "autocfg", + "cfg-if", + "libc", + "log", + "wepoll-ffi", + "windows-sys 0.42.0", +] + +[[package]] +name = "polling" +version = "3.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix 0.38.34", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -1589,6 +2362,17 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "reactor-trait" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "438a4293e4d097556730f4711998189416232f009c137389e0f961d2bc0ddc58" +dependencies = [ + "async-trait", + "futures-core", + "futures-io", +] + [[package]] name = "redox_syscall" version = "0.5.1" @@ -1609,6 +2393,41 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + [[package]] name = "reqwest" version = "0.12.5" @@ -1622,7 +2441,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.1", "http-body-util", @@ -1699,6 +2518,29 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[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.37.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79bef90eb6d984c72722595b5b1348ab39275a5e5123faca6863bf07d75a4e0" +dependencies = [ + "bitflags 1.2.1", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.34" @@ -1708,7 +2550,7 @@ dependencies = [ "bitflags 2.5.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] @@ -1726,9 +2568,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "afabcee0551bd1aa3e18e5adbf2c0544722014b899adb31bd186ec638d3da97e" dependencies = [ "once_cell", "rustls-pki-types", @@ -1837,6 +2679,7 @@ dependencies = [ "envy", "fantoccini", "futures", + "get-port", "image", "reqwest", "scout-lexer", @@ -1862,6 +2705,22 @@ dependencies = [ "test-case", ] +[[package]] +name = "scout-worker" +version = "0.1.0" +dependencies = [ + "actix-web", + "futures-lite 2.3.0", + "lapin", + "reqwest", + "scout-interpreter", + "serde", + "serde_json", + "tokio", + "toml", + "tracing", +] + [[package]] name = "scoutlang" version = "0.6.0" @@ -1911,6 +2770,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" version = "1.0.203" @@ -1944,9 +2809,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -1963,6 +2828,17 @@ dependencies = [ "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.2" @@ -2002,6 +2878,16 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.5.7" @@ -2096,6 +2982,17 @@ version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +[[package]] +name = "tcp-stream" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "495b0abdce3dc1f8fd27240651c9e68890c14e9d9c61527b1ce44d8a5a7bd3d5" +dependencies = [ + "cfg-if", + "native-tls", + "rustls-pemfile 2.1.2", +] + [[package]] name = "tempfile" version = "3.10.1" @@ -2103,8 +3000,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand", - "rustix", + "fastrand 2.1.0", + "rustix 0.38.34", "windows-sys 0.52.0", ] @@ -2232,7 +3129,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.7", "tokio-macros", "windows-sys 0.48.0", ] @@ -2275,7 +3172,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.11", + "rustls 0.23.5", "rustls-pki-types", "tokio", ] @@ -2295,9 +3192,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" dependencies = [ "serde", "serde_spanned", @@ -2307,18 +3204,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" dependencies = [ "indexmap", "serde", @@ -2360,10 +3257,23 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -2379,6 +3289,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -2470,6 +3386,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "want" version = "0.3.1" @@ -2596,6 +3518,15 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2618,6 +3549,21 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -2667,6 +3613,12 @@ dependencies = [ "windows_x86_64_msvc 0.52.5", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -2679,6 +3631,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -2691,6 +3649,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -2709,6 +3673,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -2721,6 +3691,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -2733,6 +3709,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -2745,6 +3727,12 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -2776,12 +3764,60 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.12+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "zune-core" version = "0.4.12" diff --git a/Cargo.toml b/Cargo.toml index 74357a6..d0a7cc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["scout-interpreter", "scout-lexer", "scout-parser"] +members = ["scout-interpreter", "scout-lexer", "scout-parser", "scout-worker"] # Config for 'cargo dist' [workspace.metadata.dist] diff --git a/README.md b/README.md index f12f707..45c407c 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ The `scout` binary ran with a filename will read and interpret a script file. Wi Available ENV variables: - `SCOUT_DEBUG`: Whether or not to open the debug browser. Defaults to `false`. -- `SCOUT_PORT`: Which port to run Scout on. Defaults to `4444`. +- `SCOUT_PORT`: Which port to run Scout on. Defaults to a random open port. Do not set if you intend to run multiple scout instances at once as ports will conflict. - `SCOUT_PROXY`: An optional URL to proxy requests to. Defaults to none. - `SCOUT_PATH`: A path to where Scout installs dependencies, like the standard lib. Defaults to `$HOME/scout-lang/`. diff --git a/scout-interpreter/Cargo.toml b/scout-interpreter/Cargo.toml index e4f63e2..be24fa3 100644 --- a/scout-interpreter/Cargo.toml +++ b/scout-interpreter/Cargo.toml @@ -27,6 +27,7 @@ scout-lexer = { version = "0.6.0", path = "../scout-lexer/" } url = "2.5.2" reqwest = { version = "0.12", features = ["json", "cookies"] } envy = "0.4.2" +get-port = "4.0.0" [dev-dependencies] test-case = "3.3.1" diff --git a/scout-interpreter/src/builder.rs b/scout-interpreter/src/builder.rs index 854c61b..137f1ed 100644 --- a/scout-interpreter/src/builder.rs +++ b/scout-interpreter/src/builder.rs @@ -1,3 +1,5 @@ +use get_port::Ops; + use crate::{env::EnvPointer, eval::ScrapeResultsPtr, EnvVars, Interpreter}; #[derive(Debug)] @@ -32,20 +34,27 @@ impl InterpreterBuilder { pub async fn build(self) -> Result { let env_vars = envy::from_env::().map_err(|e| BuilderError::EnvError(e.to_string()))?; + let port = env_vars + .port() + .unwrap_or_else(|| get_port::tcp::TcpPort::any("127.0.0.1").unwrap() as usize); + let child = crate::GeckDriverProc::new(port); let crawler = match self.crawler { Some(c) => Ok(c), - None => new_crawler(&env_vars).await, + None => new_crawler(&env_vars, port).await, }?; + let interpreter = Interpreter::new( - self.env.unwrap_or(EnvPointer::default()), - self.results.unwrap_or(ScrapeResultsPtr::default()), + self.env.unwrap_or_default(), + self.results.unwrap_or_default(), crawler, + child, ); + Ok(interpreter) } } -async fn new_crawler(env_vars: &EnvVars) -> Result { +async fn new_crawler(env_vars: &EnvVars, port: usize) -> Result { let mut caps = serde_json::map::Map::new(); if !env_vars.scout_debug { let opts = serde_json::json!({ "args": ["--headless"] }); @@ -58,7 +67,7 @@ async fn new_crawler(env_vars: &EnvVars) -> Result, #[serde(default)] scout_proxy: Option, @@ -31,7 +34,7 @@ impl EnvVars { self.scout_debug } - pub fn port(&self) -> usize { + pub fn port(&self) -> Option { self.scout_port } @@ -40,28 +43,49 @@ impl EnvVars { } } -fn default_port() -> usize { - 4444 -} - #[derive(Debug)] pub enum InterpreterError { EvalError(EvalError), ParserError(ParseError), } +pub struct GeckDriverProc(Child); + +impl GeckDriverProc { + pub fn new(port: usize) -> Self { + let child = Command::new("geckodriver") + .arg("--port") + .arg(port.to_string()) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .spawn() + .expect("error spinning up driver process"); + + // sleep to allow driver to start + std::thread::sleep(std::time::Duration::from_millis(50)); + Self(child) + } +} + pub struct Interpreter { env: EnvPointer, results: ScrapeResultsPtr, crawler: fantoccini::Client, + _geckodriver_proc: GeckDriverProc, } impl Interpreter { - pub fn new(env: EnvPointer, results: ScrapeResultsPtr, crawler: fantoccini::Client) -> Self { + pub fn new( + env: EnvPointer, + results: ScrapeResultsPtr, + crawler: fantoccini::Client, + geckodriver_proc: GeckDriverProc, + ) -> Self { Self { env, results, crawler, + _geckodriver_proc: geckodriver_proc, } } pub async fn eval(&self, content: &str) -> Result, InterpreterError> { @@ -79,7 +103,16 @@ impl Interpreter { } } - pub async fn finalize(self) { + pub fn results(&self) -> ScrapeResultsPtr { + self.results.clone() + } + + pub fn reset(&mut self) { + self.env = EnvPointer::default(); + self.results = ScrapeResultsPtr::default(); + } + + pub async fn close(self) { let _ = self.crawler.close().await; } } @@ -89,3 +122,27 @@ impl From for InterpreterError { InterpreterError::EvalError(value) } } + +impl Drop for GeckDriverProc { + fn drop(&mut self) { + #[cfg(target_os = "windows")] + let mut kill = Command::new("taskkill") + .arg("/PID") + .arg(&self.0.id().to_string()) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .arg("/F") + .spawn() + .expect("error sending driver kill"); + + #[cfg(not(target_os = "windows"))] + let mut kill = Command::new("kill") + .args(["-s", "TERM", &self.0.id().to_string()]) + .stdout(std::process::Stdio::null()) + .stderr(std::process::Stdio::null()) + .spawn() + .expect("error sending driver kill"); + + kill.wait().expect("error waiting for driver kill"); + } +} diff --git a/scout-worker/Cargo.toml b/scout-worker/Cargo.toml new file mode 100644 index 0000000..ef11991 --- /dev/null +++ b/scout-worker/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "scout-worker" +version = "0.1.0" +edition = "2021" + +[dependencies] +scout-interpreter = { version = "0.6.0", path = "../scout-interpreter/" } +actix-web = "4" +tokio = { version = "1", features = ["full"] } +serde = { version = "1.0.203", features = ["derive"] } +toml = "0.8.16" +lapin = { version = "2.5.0", default-features = false, features = ["native-tls"] } +futures-lite = "2.3.0" +serde_json = "1.0" +tracing = "0.1.40" +reqwest = "0.12.5" \ No newline at end of file diff --git a/scout-worker/README.md b/scout-worker/README.md new file mode 100644 index 0000000..324afd5 --- /dev/null +++ b/scout-worker/README.md @@ -0,0 +1 @@ +Scout-worker is a processing framework for ScoutLang. It provides multiple input/output types that are driven via configuration. diff --git a/scout-worker/src/config.rs b/scout-worker/src/config.rs new file mode 100644 index 0000000..f1abd24 --- /dev/null +++ b/scout-worker/src/config.rs @@ -0,0 +1,71 @@ +use std::fs; + +use serde::Deserialize; + +use crate::WorkerError; + +const DFEAULT_CONFIG_FILE: &str = "scout.toml"; + +#[derive(Debug, Default, Deserialize)] +pub struct Config { + pub inputs: ConfigInputs, + pub outputs: Option, +} + +#[derive(Debug, Default, Deserialize)] +pub struct ConfigOutputs { + pub rmq: Option, + pub http: Option, +} + +#[derive(Debug, Default, Deserialize)] +pub struct ConfigInputs { + pub http: Option, + pub rmq: Option, +} + +#[derive(Debug, Deserialize)] +pub struct ConfigInputHttp { + pub addr: String, + pub port: usize, +} + +#[derive(Debug, Deserialize)] +pub enum OutputMethods { + POST, + PUT, + PATCH, +} + +#[derive(Debug, Deserialize)] +pub struct ConfigOutputHttp { + pub endpoint: String, + pub method: OutputMethods, +} + +#[derive(Debug, Deserialize)] +pub struct ConfigRMQ { + pub addr: String, + pub queue: String, + pub exchange: String, + pub routing_key: String, +} + +impl Config { + pub fn load_file(path: Option<&str>) -> Result { + let path = path.unwrap_or(DFEAULT_CONFIG_FILE); + let content = + fs::read_to_string(path).map_err(|e| WorkerError::ConfigError(e.to_string()))?; + toml::from_str(&content).map_err(|e| WorkerError::ConfigError(e.to_string())) + } +} + +impl std::fmt::Display for OutputMethods { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::PATCH => write!(f, "PATCH"), + Self::POST => write!(f, "POST"), + Self::PUT => write!(f, "PUT"), + } + } +} diff --git a/scout-worker/src/http/mod.rs b/scout-worker/src/http/mod.rs new file mode 100644 index 0000000..587a0dc --- /dev/null +++ b/scout-worker/src/http/mod.rs @@ -0,0 +1,2 @@ +pub mod sender; +pub mod server; diff --git a/scout-worker/src/http/sender.rs b/scout-worker/src/http/sender.rs new file mode 100644 index 0000000..9e6fa11 --- /dev/null +++ b/scout-worker/src/http/sender.rs @@ -0,0 +1,37 @@ +use reqwest::Method; +use tracing::info; + +use crate::config::OutputMethods; + +pub struct Sender { + client: reqwest::Client, + method: Method, + endpoint: String, +} + +impl Sender { + pub fn new( + method: &OutputMethods, + endpoint: String, + ) -> Result> { + let client = reqwest::Client::new(); + let method = Method::from_bytes(method.to_string().as_bytes())?; + Ok(Self { + client, + method, + endpoint, + }) + } + + pub async fn send(&self, payload: &str) -> Result<(), reqwest::Error> { + info!("sending output to {} {}", self.method, self.endpoint); + let req = self + .client + .request(self.method.clone(), &self.endpoint) + .body(payload.to_owned()) + .build()?; + let res = self.client.execute(req).await?; + info!("received response code {}", res.status()); + Ok(()) + } +} diff --git a/scout-worker/src/http/server.rs b/scout-worker/src/http/server.rs new file mode 100644 index 0000000..f5e6926 --- /dev/null +++ b/scout-worker/src/http/server.rs @@ -0,0 +1,72 @@ +use std::{ + fs, + io::{self, ErrorKind}, + sync::Arc, +}; + +use actix_web::{ + get, + http::StatusCode, + post, + web::{self, Data}, + App, HttpResponse, HttpServer, Responder, +}; +use scout_interpreter::builder::InterpreterBuilder; +use tracing::info; + +use crate::{config::ConfigInputHttp, models::incoming, Output}; + +#[post("/")] +async fn crawl( + outputs: Data>>, + body: web::Json, +) -> impl Responder { + match fs::read_to_string(&body.file) { + Ok(content) => { + let interpreter = InterpreterBuilder::default().build().await.unwrap(); + if let Err(e) = interpreter.eval(&content).await { + return HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR) + .body(format!("interpreter error: {e:?}")); + } + let res = interpreter.results(); + let payload = res.lock().await.to_json(); + interpreter.close().await; + + for output in outputs.iter() { + if let Err(e) = output.send(&payload).await { + println!("error sending to output: {e}"); + } + } + + HttpResponse::build(StatusCode::OK) + .content_type("application/json") + .body(payload) + } + Err(e) if e.kind() == ErrorKind::NotFound => HttpResponse::build(StatusCode::BAD_REQUEST) + .body(format!("unknown file: {}", body.file)), + Err(e) => HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR) + .body(format!("error reading file: {e}")), + } +} + +#[get("/health")] +async fn health() -> impl Responder { + "OK" +} + +pub async fn start_http_consumer( + config: &ConfigInputHttp, + outputs: Arc>, +) -> Result<(), io::Error> { + info!("starting HTTP server on {}:{}", config.addr, config.port); + let data = Data::new(outputs.clone()); + HttpServer::new(move || { + App::new() + .app_data(data.clone()) + .service(crawl) + .service(health) + }) + .bind((config.addr.as_str(), config.port as u16))? + .run() + .await +} diff --git a/scout-worker/src/main.rs b/scout-worker/src/main.rs new file mode 100644 index 0000000..5452411 --- /dev/null +++ b/scout-worker/src/main.rs @@ -0,0 +1,56 @@ +use std::sync::Arc; + +use config::Config; +use http::sender::Sender; +use output::Output; +use rmq::producer::Producer; +use tracing::error; + +mod config; +mod http; +mod models; +mod output; +mod rmq; + +pub enum WorkerError { + ConfigError(String), +} + +async fn start(config: Config) -> Result<(), Box> { + let mut outputs = Vec::new(); + if let Some(outputs_config) = config.outputs { + if let Some(rmq) = outputs_config.rmq { + let rmq_out = Producer::new(&rmq).await?; + outputs.push(Output::RMQ(rmq_out)); + } + + if let Some(http) = outputs_config.http { + let http_out = Sender::new(&http.method, http.endpoint)?; + outputs.push(Output::HTTP(http_out)); + } + } + + let aoutputs = Arc::new(outputs); + if let Some(http_config) = config.inputs.http { + http::server::start_http_consumer(&http_config, aoutputs.clone()).await?; + } else if let Some(rmq_config) = config.inputs.rmq { + rmq::consumer::Consumer::new(&rmq_config, aoutputs.clone()) + .await? + .start() + .await?; + } + + Ok(()) +} + +#[tokio::main] +async fn main() { + if std::env::var("RUST_LOG").is_err() { + std::env::set_var("RUST_LOG", "info"); + } + + let config = Config::load_file(None).unwrap_or_default(); + if let Err(e) = start(config).await { + error!("error starting worker: {e}"); + } +} diff --git a/scout-worker/src/models/incoming.rs b/scout-worker/src/models/incoming.rs new file mode 100644 index 0000000..efed12f --- /dev/null +++ b/scout-worker/src/models/incoming.rs @@ -0,0 +1,6 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +pub struct Incoming { + pub file: String, +} diff --git a/scout-worker/src/models/mod.rs b/scout-worker/src/models/mod.rs new file mode 100644 index 0000000..28f2603 --- /dev/null +++ b/scout-worker/src/models/mod.rs @@ -0,0 +1 @@ +pub mod incoming; diff --git a/scout-worker/src/output.rs b/scout-worker/src/output.rs new file mode 100644 index 0000000..e1f0977 --- /dev/null +++ b/scout-worker/src/output.rs @@ -0,0 +1,21 @@ +use crate::{http, rmq}; + +pub enum Output { + RMQ(rmq::producer::Producer), + HTTP(http::sender::Sender), +} + +impl Output { + pub async fn send(&self, payload: &str) -> Result<(), Box> { + match self { + Output::RMQ(p) => { + p.send(payload).await?; + Ok(()) + } + Output::HTTP(sender) => { + sender.send(payload).await?; + Ok(()) + } + } + } +} diff --git a/scout-worker/src/rmq/consumer.rs b/scout-worker/src/rmq/consumer.rs new file mode 100644 index 0000000..49b0261 --- /dev/null +++ b/scout-worker/src/rmq/consumer.rs @@ -0,0 +1,147 @@ +use futures_lite::StreamExt; +use lapin::{ + options::{ + BasicAckOptions, BasicConsumeOptions, BasicNackOptions, ExchangeDeclareOptions, + QueueBindOptions, QueueDeclareOptions, + }, + types::FieldTable, + Channel, Connection, ConnectionProperties, ExchangeKind, +}; +use scout_interpreter::{ + builder::{BuilderError, InterpreterBuilder}, + Interpreter, InterpreterError, +}; +use std::{fmt::Display, fs, str, sync::Arc}; +use tracing::{error, info}; + +use crate::{config::ConfigRMQ, models::incoming, Output}; + +#[derive(Debug)] +pub enum ConsumerError { + RabbitError, + ScoutError, +} + +pub struct Consumer { + chann: Channel, + queue: String, + interpreter: Interpreter, + outputs: Arc>, +} + +impl Consumer { + pub async fn new(config: &ConfigRMQ, outputs: Arc>) -> Result { + let conn = Connection::connect(&config.addr, ConnectionProperties::default()).await?; + let chann = conn.create_channel().await?; + let interpreter = InterpreterBuilder::default().build().await?; + + chann + .exchange_declare( + &config.exchange, + ExchangeKind::Topic, + ExchangeDeclareOptions::default(), + FieldTable::default(), + ) + .await?; + + let _ = chann + .queue_declare( + &config.queue, + QueueDeclareOptions::default(), + FieldTable::default(), + ) + .await?; + + chann + .queue_bind( + &config.queue, + &config.exchange, + &config.routing_key, + QueueBindOptions::default(), + FieldTable::default(), + ) + .await?; + + Ok(Self { + chann, + queue: config.queue.clone(), + interpreter, + outputs, + }) + } + + async fn process(&mut self, data: &[u8]) -> Result { + let raw = str::from_utf8(data).map_err(|_| ConsumerError::RabbitError)?; + let incoming: incoming::Incoming = + serde_json::from_str(raw).map_err(|_| ConsumerError::RabbitError)?; + let content = fs::read_to_string(incoming.file).map_err(|_| ConsumerError::RabbitError)?; + let _ = self.interpreter.eval(&content).await?; + let res = self.interpreter.results(); + let payload = res.lock().await.to_json(); + self.interpreter.reset(); + Ok(payload) + } + + pub async fn start(&mut self) -> Result<(), lapin::Error> { + let mut consumer = self + .chann + .basic_consume( + &self.queue, + "scout-worker", + BasicConsumeOptions::default(), + FieldTable::default(), + ) + .await?; + + info!("listening on queue {}", self.queue); + while let Some(delivery) = consumer.next().await { + if let Ok(delivery) = delivery { + info!("processing msg"); + match self.process(&delivery.data).await { + Ok(res) => { + for output in self.outputs.iter() { + if let Err(e) = output.send(&res).await { + error!("error sending to output: {e}"); + } + } + delivery.ack(BasicAckOptions::default()).await?; + } + Err(_) => { + delivery.nack(BasicNackOptions::default()).await?; + } + } + } + } + + Ok(()) + } +} + +impl From for ConsumerError { + fn from(_value: lapin::Error) -> Self { + Self::RabbitError + } +} + +impl From for ConsumerError { + fn from(_value: InterpreterError) -> Self { + Self::ScoutError + } +} + +impl From for ConsumerError { + fn from(_value: BuilderError) -> Self { + Self::ScoutError + } +} + +impl Display for ConsumerError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::RabbitError => write!(f, "consumer rabbit error"), + Self::ScoutError => write!(f, "consumer scout error"), + } + } +} + +impl std::error::Error for ConsumerError {} diff --git a/scout-worker/src/rmq/mod.rs b/scout-worker/src/rmq/mod.rs new file mode 100644 index 0000000..934046a --- /dev/null +++ b/scout-worker/src/rmq/mod.rs @@ -0,0 +1,2 @@ +pub mod consumer; +pub mod producer; diff --git a/scout-worker/src/rmq/producer.rs b/scout-worker/src/rmq/producer.rs new file mode 100644 index 0000000..f3ef99c --- /dev/null +++ b/scout-worker/src/rmq/producer.rs @@ -0,0 +1,81 @@ +use std::fmt::Display; + +use lapin::{ + options::{BasicPublishOptions, ExchangeDeclareOptions, QueueDeclareOptions}, + types::FieldTable, + BasicProperties, Channel, Connection, ConnectionProperties, ExchangeKind, +}; +use tracing::info; + +use crate::config::ConfigRMQ; + +#[derive(Debug)] +pub enum ProducerError { + RabbitError, +} + +pub struct Producer { + chann: Channel, + exchange: String, + out_key: String, +} + +impl Producer { + pub async fn new(config: &ConfigRMQ) -> Result { + let conn = Connection::connect(&config.addr, ConnectionProperties::default()).await?; + let chann = conn.create_channel().await?; + + chann + .exchange_declare( + &config.exchange, + ExchangeKind::Topic, + ExchangeDeclareOptions::default(), + FieldTable::default(), + ) + .await?; + + let _ = chann + .queue_declare( + &config.queue, + QueueDeclareOptions::default(), + FieldTable::default(), + ) + .await?; + + Ok(Self { + chann, + exchange: config.exchange.clone(), + out_key: config.routing_key.clone(), + }) + } + + pub async fn send(&self, payload: &str) -> Result<(), ProducerError> { + info!("publishing message to {}", self.out_key); + self.chann + .basic_publish( + &self.exchange, + &self.out_key, + BasicPublishOptions::default(), + &payload.as_bytes(), + BasicProperties::default(), + ) + .await?; + Ok(()) + } +} + +impl From for ProducerError { + fn from(_value: lapin::Error) -> Self { + Self::RabbitError + } +} + +impl Display for ProducerError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::RabbitError => write!(f, "rmq error"), + } + } +} + +impl std::error::Error for ProducerError {} diff --git a/src/main.rs b/src/main.rs index 5d5c63e..6b07a7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,29 +1,22 @@ -use std::{env, fs, process::Command}; +use std::{env, fs}; use repl::run_repl; -use scout_interpreter::{builder::InterpreterBuilder, env::Env, eval::ScrapeResultsPtr, EnvVars}; +use scout_interpreter::{builder::InterpreterBuilder, Interpreter}; mod repl; async fn run( file: Option, - results: ScrapeResultsPtr, + interpreter: &Interpreter, ) -> Result<(), Box> { - let env = Env::default(); match file { - None => run_repl(results, env).await, + None => run_repl(interpreter).await, Some(f) => { let contents = fs::read_to_string(f)?; - let interpret = InterpreterBuilder::default() - .with_results(results) - .build() - .await?; - if let Err(e) = interpret.eval(&contents).await { + if let Err(e) = interpreter.eval(&contents).await { println!("Interpeter error: {:?}", e); } - interpret.finalize().await; - Ok(()) } } @@ -31,44 +24,17 @@ async fn run( #[tokio::main] async fn main() { - let env_vars = envy::from_env::().expect("error loading env config"); let args: Vec = env::args().collect(); - let child = Command::new("geckodriver") - .arg("--port") - .arg(env_vars.port().to_string()) - .stdout(std::process::Stdio::null()) - .stderr(std::process::Stdio::null()) - .spawn() - .expect("error spinning up driver process"); - - // sleep to allow driver to start - std::thread::sleep(std::time::Duration::from_millis(50)); - - let results = ScrapeResultsPtr::default(); - if let Err(e) = run(args.get(1).cloned(), results.clone()).await { + let interpreter = InterpreterBuilder::default() + .build() + .await + .expect("failed to build interpreter"); + if let Err(e) = run(args.get(1).cloned(), &interpreter).await { println!("Error: {}", e); } - let json_results = results.lock().await.to_json(); + let json_results = interpreter.results().lock().await.to_json(); println!("{}", json_results); - #[cfg(target_os = "windows")] - let mut kill = Command::new("taskkill") - .arg("/PID") - .arg(&child.id().to_string()) - .stdout(std::process::Stdio::null()) - .stderr(std::process::Stdio::null()) - .arg("/F") - .spawn() - .expect("error sending driver kill"); - - #[cfg(not(target_os = "windows"))] - let mut kill = Command::new("kill") - .args(["-s", "TERM", &child.id().to_string()]) - .stdout(std::process::Stdio::null()) - .stderr(std::process::Stdio::null()) - .spawn() - .expect("error sending driver kill"); - - kill.wait().expect("error waiting for driver kill"); + interpreter.close().await; } diff --git a/src/repl.rs b/src/repl.rs index df5a77f..0186726 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -1,23 +1,10 @@ -use std::sync::Arc; - -use futures::lock::Mutex; use rustyline::{error::ReadlineError, Editor}; -use scout_interpreter::{builder::InterpreterBuilder, env::Env, eval::ScrapeResultsPtr}; +use scout_interpreter::Interpreter; const PROMPT: &str = ">> "; -pub async fn run_repl( - results: ScrapeResultsPtr, - env: Env, -) -> Result<(), Box> { +pub async fn run_repl(interpreter: &Interpreter) -> Result<(), Box> { let mut rl = Editor::<()>::new(); - let env = Arc::new(Mutex::new(env)); - - let interpreter = InterpreterBuilder::default() - .with_env(env.clone()) - .with_results(results.clone()) - .build() - .await?; if rl.load_history("history.txt").is_err() { println!("No previous history."); } @@ -49,6 +36,5 @@ pub async fn run_repl( } } rl.save_history("history.txt").unwrap(); - interpreter.finalize().await; Ok(()) }