diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5c70449 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: Build & Tests + +on: + push: + pull_request: + +env: + CARGO_TERM_COLOR: always + +jobs: + build_test: + name: Build & test + runs-on: ubuntu-22.04 + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.job.target }} + + - name: Use cached dependencies + uses: Swatinem/rust-cache@v2 + + - name: Build + run: cargo build + + - name: Test + run: cargo test diff --git a/Cargo.lock b/Cargo.lock index 79998c8..02f881f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -16,35 +16,27 @@ name = "ambi_mock_client" version = "0.1.0" dependencies = [ "clap", + "env_logger", + "log", "rand", "regex", "reqwest", "serde", "serde_json", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", + "thiserror", ] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.13.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bitflags" @@ -54,21 +46,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytes" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" -version = "1.0.72" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -78,26 +70,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.2" +version = "4.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e538f9ee5aa3b3963f09a997035f883677966ed50fce0292611927ce6f6d8c6" +checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3" dependencies = [ - "atty", "bitflags", "clap_derive", "clap_lex", - "indexmap", - "lazy_static", + "is-terminal", + "once_cell", "strsim", "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.2.2" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f98063cac4652f23ccda556b8d04347a7fc4b2cff1f7577cc8c6546e0d8078" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" dependencies = [ "heck", "proc-macro-error", @@ -108,18 +98,18 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" dependencies = [ "os_str_bytes", ] [[package]] name = "core-foundation" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -133,18 +123,52 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "encoding_rs" -version = "0.8.30" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "fastrand" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -172,52 +196,51 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "futures-channel" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-io" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-sink" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-core", "futures-io", @@ -230,9 +253,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", @@ -241,9 +264,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.10" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -260,41 +283,47 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "http" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa", ] [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", @@ -303,9 +332,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -313,11 +342,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", @@ -328,7 +363,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 0.4.8", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -352,20 +387,19 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] [[package]] name = "indexmap" -version = "1.8.0" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -380,29 +414,45 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "io-lifetimes" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "ipnet" -version = "2.3.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" [[package]] -name = "itoa" -version = "0.4.8" +name = "is-terminal" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.45.0", +] [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "js-sys" -version = "0.3.56" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -415,30 +465,30 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mime" @@ -448,31 +498,21 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mio" -version = "0.7.14" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "wasi", + "windows-sys 0.45.0", ] [[package]] name = "native-tls" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -486,45 +526,48 @@ dependencies = [ "tempfile", ] -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi", -] - [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] [[package]] name = "once_cell" -version = "1.9.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "openssl" -version = "0.10.38" +version = "0.10.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" dependencies = [ "bitflags", "cfg-if", "foreign-types", "libc", "once_cell", + "openssl-macros", "openssl-sys", ] +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -533,9 +576,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.72" +version = "0.9.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" dependencies = [ "autocfg", "cc", @@ -546,21 +589,21 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pin-project-lite" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -570,15 +613,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-error" @@ -606,32 +649,31 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.14" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -646,36 +688,27 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -684,9 +717,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -699,9 +732,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.9" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ "base64", "bytes", @@ -715,10 +748,10 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", "pin-project-lite", "serde", @@ -726,6 +759,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-native-tls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -733,27 +767,40 @@ dependencies = [ "winreg", ] +[[package]] +name = "rustix" +version = "0.36.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "winapi", + "windows-sys 0.42.0", ] [[package]] name = "security-framework" -version = "2.5.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d09d3c15d814eda1d6a836f2f2b56a6abc1446c8a34351cb3180d3db92ffe4ce" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -764,9 +811,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.5.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90dd10c41c6bfc633da6e0c659bd25d31e0791e5974ac42970267d59eba87f7" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -774,18 +821,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.133" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97565067517b60e2d1ea8b268e59ce036de907ac523ad83a0475da04e818989a" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.133" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed201699328568d8d08208fdd080e3ff594e6c422e438b6705905da01005d537" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -794,11 +841,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.74" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] @@ -810,22 +857,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa", "ryu", "serde", ] [[package]] name = "slab" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -839,13 +889,13 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.85" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -864,54 +914,70 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] [[package]] -name = "textwrap" -version = "0.15.0" +name = "thiserror" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.15.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" +checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", "pin-project-lite", - "winapi", + "socket2", + "windows-sys 0.42.0", ] [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", @@ -919,29 +985,29 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.9" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", "futures-sink", - "log", "pin-project-lite", "tokio", + "tracing", ] [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", @@ -950,49 +1016,48 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -1020,15 +1085,15 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1036,13 +1101,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -1051,9 +1116,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.29" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if", "js-sys", @@ -1063,9 +1128,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1073,9 +1138,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -1086,15 +1151,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.79" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.56" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -1131,11 +1196,92 @@ 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", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + [[package]] name = "winreg" -version = "0.7.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index d6b6388..a00a0cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,7 @@ [package] name = "ambi_mock_client" +authors = ["Rust Never Sleeps community (https://github.com/Jim-Hodapp-Coaching/)"] +description = "Provides a mock Ambi client that emulates real sensor hardware such as an Edge client." version = "0.1.0" edition = "2021" @@ -7,13 +9,16 @@ edition = "2021" [dependencies] rand = "0.8.4" -reqwest = { version = "0.11.9", features = ["blocking"] } +reqwest = { version = "0.11.14", features = ["blocking"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.74" -clap = { version = "3.1.7", features = ["derive"] } +clap = { version = "4.1.4", features = ["derive"] } +thiserror = "1.0.38" +log = "0.4.0" +env_logger = "0.10.0" [dev-dependencies] -regex = "1.5.4" +regex = "1.7.1" [lib] name = "ambi_mock_client" diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..820b579 --- /dev/null +++ b/src/data.rs @@ -0,0 +1,103 @@ +use core::fmt; + +use rand::{rngs::ThreadRng, Rng}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize)] +pub(crate) struct Reading { + temperature: f64, + humidity: f64, + pressure: i32, + dust_concentration: f64, + air_purity: String, +} + +impl Reading { + pub(crate) fn new( + temperature: f64, + humidity: f64, + pressure: i32, + dust_concentration: f64, + air_purity: String, + ) -> Reading { + Reading { + temperature, + humidity, + pressure, + dust_concentration, + air_purity, + } + } +} + +#[derive(Debug, PartialEq)] +pub(crate) enum AirPurity { + Dangerous, + High, + Low, + FreshAir, +} + +impl AirPurity { + pub(crate) fn from_value(value: f64) -> AirPurity { + match value { + value if value < 50.0 => AirPurity::FreshAir, + value if value > 50.0 && value <= 100.0 => AirPurity::Low, + value if value > 100.0 && value <= 150.0 => AirPurity::High, + _ => AirPurity::Dangerous, + } + } +} + +// implements fmt::Display for AirPurity so that we can call .to_string() on +// each enum value +impl fmt::Display for AirPurity { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + AirPurity::Low => write!(f, "Low Pollution"), + AirPurity::High => write!(f, "High Pollution"), + AirPurity::Dangerous => write!(f, "Dangerous Pollution"), + AirPurity::FreshAir => write!(f, "Fresh Air"), + } + } +} + +pub(crate) fn random_gen_humidity(rng: &mut ThreadRng) -> f64 { + let value = rng.gen_range(0.0..=100.0); + // Limit to 2 decimals + f64::trunc(value * 100.0) / 100.0 +} + +pub(crate) fn random_gen_temperature(rng: &mut ThreadRng) -> f64 { + let value = rng.gen_range(15.0..=35.0); + // Limit to 2 decimals + f64::trunc(value * 100.0) / 100.0 +} + +pub(crate) fn random_gen_pressure(rng: &mut ThreadRng) -> i32 { + rng.gen_range(900..=1100) +} + +pub(crate) fn random_gen_dust_concentration(rng: &mut ThreadRng) -> f64 { + let value = rng.gen_range(0.0..=1000.0); + f64::trunc(value * 100.0) / 100.0 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn air_purity_from_value_returns_correct_enum() { + let mut rng = rand::thread_rng(); + let fresh_air = rng.gen_range(0.0..=50.0); + let low = rng.gen_range(51.0..=100.0); + let high = rng.gen_range(101.0..=150.0); + let dangerous = rng.gen_range(151.0..f64::MAX); + + assert_eq!(AirPurity::from_value(fresh_air), AirPurity::FreshAir); + assert_eq!(AirPurity::from_value(low), AirPurity::Low); + assert_eq!(AirPurity::from_value(high), AirPurity::High); + assert_eq!(AirPurity::from_value(dangerous), AirPurity::Dangerous); + } +} diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..c478a3a --- /dev/null +++ b/src/error.rs @@ -0,0 +1,11 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum PostSchedulerError { + #[error("Invalid value \"{value}\" for argument {argument_name}. {message}")] + InvalidArgument { + argument_name: String, + value: String, + message: String, + }, +} diff --git a/src/lib.rs b/src/lib.rs index e4b8560..1cdf594 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,181 +9,105 @@ //! See the `LICENSE` file for Copyright and license details. //! +mod data; +pub mod error; +mod sensor_posts; + +use crate::sensor_posts::{send_data, PostSchedulerBuilder}; use clap::Parser; -use rand::{thread_rng, Rng}; -use reqwest::blocking::Client; -use reqwest::header::CONTENT_TYPE; -use serde::{Deserialize, Serialize}; -use std::fmt; +use error::PostSchedulerError; +use log::debug; +use sensor_posts::MAX_NUM_THREADS; +use std::time::Duration; + +const URL: &str = "http://localhost:8000/api/readings/add"; /// Defines the Ambi Mock Client command line interface as a struct #[derive(Parser, Debug)] -#[clap(name = "Ambi Mock Client")] -#[clap(author = "Rust Never Sleeps community (https://github.com/Jim-Hodapp-Coaching/)")] -#[clap(version = "0.1.0")] -#[clap( - about = "Provides a mock Ambi client that emulates real sensor hardware such as an Edge client." -)] -#[clap( +#[command( + name = "Ambi Mock Client", + author, + version, + about, long_about = "This application emulates a real set of hardware sensors that can report on environmental conditions such as temperature, pressure, humidity, etc." )] pub struct Cli { - /// Turns verbose console debug output on - #[clap(short, long)] + /// Turns verbose console debug output on. + #[arg(short, long)] pub debug: bool, + /// The number of sensor readings to post. + /// [DEFAULT: 1] + #[arg(short = 'n', long)] + pub post_amount: Option, + /// The time between each sensor reading post (in seconds). + /// [DEFAULT: 10] + #[arg(short = 't', long = "time-per-post")] + pub time_per_post_s: Option, + /// The total time over which all the sensor reading posts must be sent (in seconds, alternative to -t). + #[arg(short = 'T', long = "total-time")] + pub total_time_s: Option, + /// The number of threads to spawn. The workload will be cloned to each thread, not divided. + /// [DEFAULT: 1] + #[arg(short = 'p', long, value_parser = is_valid_num_of_threads)] + pub num_threads: Option, } -#[derive(Serialize, Deserialize)] -struct Reading { - temperature: f64, - humidity: f64, - pressure: i32, - dust_concentration: f64, - air_purity: String, -} - -impl Reading { - fn new( - temperature: f64, - humidity: f64, - pressure: i32, - dust_concentration: f64, - air_purity: String, - ) -> Reading { - Reading { - temperature, - humidity, - pressure, - dust_concentration, - air_purity, - } +/// Ensures that the number of threads are in [1, `MAX_NUM_THREADS`]. +fn is_valid_num_of_threads(val: &str) -> Result { + match val.parse::() { + Ok(num_threads) => match num_threads { + 0 => Err("You must use at least 1 thread.".to_string()), + 1..=MAX_NUM_THREADS => Ok(num_threads), + _ => Err(format!( + "You can't use more than {MAX_NUM_THREADS} threads." + )), + }, + Err(_) => Err(String::from("value wasn't a number!")), } } -#[derive(Debug, PartialEq)] -enum AirPurity { - Dangerous, - High, - Low, - FreshAir, -} +pub fn run(cli: &Cli) -> Result<(), PostSchedulerError> { + debug!("cli: {cli:?}"); -impl AirPurity { - fn from_value(value: f64) -> AirPurity { - match value { - value if value >= f64::MIN && value <= 50.0 => return AirPurity::FreshAir, - value if value > 50.0 && value <= 100.0 => return AirPurity::Low, - value if value > 100.0 && value <= 150.0 => return AirPurity::High, - _ => return AirPurity::Dangerous, - } - } -} - -// implements fmt::Display for AirPurity so that we can call .to_string() on -// each enum value -impl fmt::Display for AirPurity { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - AirPurity::Low => write!(f, "Fresh Air"), - AirPurity::High => write!(f, "Low Pollution"), - AirPurity::Dangerous => write!(f, "High Pollution"), - AirPurity::FreshAir => write!(f, "Dangerous Pollution"), - } - } -} + let req_scheduler = PostSchedulerBuilder::default() + .with_some_post_amount(&cli.post_amount) + .with_some_time_per_post(&cli.time_per_post_s.map(Duration::from_secs)) + .with_some_total_time(&cli.total_time_s.map(Duration::from_secs)) + .with_some_num_threads(&cli.num_threads) + .build()?; -fn random_gen_humidity() -> f64 { - let mut rng = thread_rng(); - let value = rng.gen_range(0.0..=100.0); - // Limit to 2 decimals - f64::trunc(value * 100.0) / 100.0 -} + send_data(req_scheduler); -fn random_gen_temperature() -> f64 { - let mut rng = thread_rng(); - let value = rng.gen_range(15.0..=35.0); - // Limit to 2 decimals - f64::trunc(value * 100.0) / 100.0 + Ok(()) } -fn random_gen_pressure() -> i32 { - let mut rng = thread_rng(); - rng.gen_range(900..=1100) -} +#[cfg(test)] +mod tests { + use clap::{error::ErrorKind, CommandFactory, Parser}; -fn random_gen_dust_concentration() -> f64 { - let mut rng = thread_rng(); - let value = rng.gen_range(0.0..=1000.0); - f64::trunc(value * 100.0) / 100.0 -} + use crate::{sensor_posts::MAX_NUM_THREADS, Cli}; -pub fn run(cli: &Cli) { - println!("\r\ncli: {:?}\r\n", cli); - - let dust_concentration = random_gen_dust_concentration(); - let air_purity = AirPurity::from_value(dust_concentration).to_string(); - let reading = Reading::new( - random_gen_temperature(), - random_gen_humidity(), - random_gen_pressure(), - dust_concentration, - air_purity, - ); - - let json = serde_json::to_string(&reading).unwrap(); - const URL: &str = "http://localhost:4000/api/readings/add"; - - println!("Sending POST request to {} as JSON: {}", URL, json); - - let client = Client::new(); - let res = client - .post(URL) - .header(CONTENT_TYPE, "application/json") - .body(json) - .send(); - - match res { - Ok(response) => match cli.debug { - true => println!("Response from Ambi backend: {:#?}", response), - false => println!( - "Response from Ambi backend: {:?}", - response.status().as_str() - ), - }, - Err(e) => { - match cli.debug { - // Print out the entire reqwest::Error for verbose debugging - true => eprintln!("Response error from Ambi backend: {:?}", e), - // Keep the error reports more succinct - false => { - if e.is_request() { - eprintln!("Response error from Ambi backend: request error"); - } else if e.is_timeout() { - eprintln!("Response error from Ambi backend: request timed out"); - } else { - eprintln!("Response error from Ambi backend: specific error type unknown"); - } - } - } - } + #[test] + fn verify_cli() { + Cli::command().debug_assert(); } -} -#[cfg(test)] -mod tests { - use super::*; + #[test] + fn test_invalid_num_threads_low() { + let cli = Cli::try_parse_from(vec!["", "-p", "0"]); + assert!(cli.is_err()); + + let cli_err = cli.unwrap_err(); + assert_eq!(cli_err.kind(), ErrorKind::ValueValidation); + } #[test] - fn air_purity_from_value_returns_correct_enum() { - let mut rng = thread_rng(); - let fresh_air = rng.gen_range(0.0..=50.0); - let low = rng.gen_range(51.0..=100.0); - let high = rng.gen_range(101.0..=150.0); - let dangerous = rng.gen_range(151.0..f64::MAX); - - assert_eq!(AirPurity::from_value(fresh_air), AirPurity::FreshAir); - assert_eq!(AirPurity::from_value(low), AirPurity::Low); - assert_eq!(AirPurity::from_value(high), AirPurity::High); - assert_eq!(AirPurity::from_value(dangerous), AirPurity::Dangerous); + fn test_invalid_num_threads_high() { + let num = MAX_NUM_THREADS + 1; + let cli = Cli::try_parse_from(vec!["", "-p", &num.to_string()]); + assert!(cli.is_err()); + + let cli_err = cli.unwrap_err(); + assert_eq!(cli_err.kind(), ErrorKind::ValueValidation); } } diff --git a/src/main.rs b/src/main.rs index bab8a18..e67392f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,28 +1,38 @@ -//! # Provides a mock Ambi client that emulates real sensor hardware such as +//! # Provides a mock Ambi client that emulates real sensor hardware such as //! an Edge client. //! //! This application emulates a real set of hardware sensors that can report on //! environmental conditions such as temperature, pressure, humidity, etc. -//! +//! //! Please see the `ambi` repository for the web backend that this client connects to //! and the `edge-rs` repository for what this client is emulating. //! //! See the `LICENSE` file for Copyright and license details. -//! - -use clap::{Parser}; +//! -// Internal library namespace for separation of app logic -use ambi_mock_client; +use ambi_mock_client::error::PostSchedulerError; +use clap::Parser; +use log::LevelFilter; -fn main() { +fn main() -> Result<(), PostSchedulerError> { // Parses the provided command line interface arguments and flags let cli = ambi_mock_client::Cli::parse(); - match cli.debug { - true => println!("Debug mode is now *on*"), - false => println!("Debug mode is now *off*") - } - - ambi_mock_client::run(&cli); + init_logging(cli.debug); + + ambi_mock_client::run(&cli) +} + +fn init_logging(is_debug: bool) { + let mut logger_builder = env_logger::Builder::new(); + + match is_debug { + true => logger_builder.filter_level(LevelFilter::Debug), + false => logger_builder.filter_level(LevelFilter::Info), + }; + + // The format_target is what makes the logs include `ambi_mock_client` everywhere. I left it + // here in case anyone wants to disable it in the future. It is enabled because not all logs + // originate from this crate (reqwest for instance makes a few as well). + logger_builder.format_target(true).init(); } diff --git a/src/sensor_posts.rs b/src/sensor_posts.rs new file mode 100644 index 0000000..d1fe390 --- /dev/null +++ b/src/sensor_posts.rs @@ -0,0 +1,210 @@ +use std::{thread, time::Duration}; + +use log::{debug, error, info}; +use rand::rngs::ThreadRng; +use reqwest::{blocking::Client, header::CONTENT_TYPE}; + +use crate::{ + data::{ + random_gen_dust_concentration, random_gen_humidity, random_gen_pressure, + random_gen_temperature, AirPurity, Reading, + }, + error::PostSchedulerError, + URL, +}; + +const DEFAULT_POST_AMOUNT: u32 = 1; +const DEFAULT_TIME_PER_POST: Duration = Duration::from_secs(10); +const DEFAULT_NUM_THREADS: u32 = 1; +pub const MAX_NUM_THREADS: u32 = 10; + +#[derive(Clone, Copy)] +pub struct PostSchedulerBuilder { + post_amount: Option, + time_per_post: Option, + total_time: Option, + num_threads: Option, +} + +impl PostSchedulerBuilder { + pub fn default() -> Self { + PostSchedulerBuilder { + post_amount: None, + time_per_post: None, + total_time: None, + num_threads: None, + } + } + + pub fn with_some_post_amount(mut self, post_amount: &Option) -> Self { + self.post_amount = *post_amount; + self + } + + pub fn with_some_time_per_post(mut self, time_per_post: &Option) -> Self { + self.time_per_post = *time_per_post; + self + } + + pub fn with_some_total_time(mut self, total_time: &Option) -> Self { + self.total_time = *total_time; + self + } + + pub fn with_some_num_threads(mut self, num_threads: &Option) -> Self { + self.num_threads = *num_threads; + self + } + + pub fn build(self) -> Result { + // Loop indefinitely if no req amt is set. If time per req is also not set then don't loop. + let loop_indefinitely = self.post_amount.is_none() && self.time_per_post.is_some(); + + let post_amount = self.post_amount.unwrap_or(DEFAULT_POST_AMOUNT); + + let time_per_post = match (&self.time_per_post, &self.total_time) { + (None, None) => DEFAULT_TIME_PER_POST, + (None, Some(total_time)) => *total_time / post_amount, + (Some(time_per_post), None) => *time_per_post, + (Some(time_per_post), Some(_)) => *time_per_post, + }; + + let num_threads = self.num_threads.unwrap_or(DEFAULT_NUM_THREADS); + // At this point we know that the number of threads is in [1, `MAX_NUM_THREADS`]. + // Validation is done in `lib::is_valid_num_of_threads`. + + Ok(PostScheduler { + post_amount, + time_per_post, + num_threads, + loop_indefinitely, + }) + } +} + +#[derive(Clone, Copy)] +pub struct PostScheduler { + post_amount: u32, + time_per_post: Duration, + num_threads: u32, + loop_indefinitely: bool, +} + +pub fn send_data(req_scheduler: PostScheduler) { + // If 1 thread is specified, we can use the current thread. + if req_scheduler.num_threads == 1 { + debug!("num_threads is set to 1, use current thread."); + + send_data_internal(req_scheduler, 0, Client::new(), &mut rand::thread_rng()); + return; + } + + debug!("Spawning {} threads.", req_scheduler.num_threads); + + let handles = (0..req_scheduler.num_threads) + .map(|thread_id| { + thread::spawn(move || { + send_data_internal( + req_scheduler, + thread_id, + Client::new(), + &mut rand::thread_rng(), + ) + }) + }) + .collect::>(); + + debug!("Threads spawned."); + + let _result: Vec<_> = handles.into_iter().map(|x| x.join()).collect(); + + debug!("Threads joined."); +} + +/// This code might run on separate threads, any logs should be prefixed by the thread id +/// for easier debugging. +/// +/// You can log the thread id by prepending `[Thread {thread_id}]: ` to your logs. +fn send_data_internal( + req_scheduler: PostScheduler, + thread_id: u32, + client: Client, + rng: &mut ThreadRng, +) { + if req_scheduler.loop_indefinitely { + loop { + make_post(thread_id, &client, rng); + thread::sleep(req_scheduler.time_per_post) + } + } + + for i in 0..req_scheduler.post_amount { + make_post(thread_id, &client, rng); + + // Only use thread.sleep if we are not on the last request + if i != req_scheduler.post_amount - 1 { + thread::sleep(req_scheduler.time_per_post) + } + } +} + +/// This also can run in parallel, refer to [`send_data_internal`]. +fn make_post(thread_id: u32, client: &Client, rng: &mut ThreadRng) { + let json = generate_random_reading(rng); + info!("[Thread {thread_id}]: Sending POST request to {}", URL); + debug!("[Thread {thread_id}]: Post JSON: {}", json); + + let res = client + .post(URL) + .header(CONTENT_TYPE, "application/json") + .body(json) + .send(); + + match res { + Ok(response) => { + let response_format_str = format!( + "[Thread {thread_id}]: Response from Ambi backend: {}", + response.status().as_str() + ); + + match response.status().is_success() { + true => info!("{}", response_format_str), + false => error!("{}", response_format_str), + } + + debug!( + "[Thread {thread_id}]: Response from Ambi backend: {:#?}", + response + ); + } + Err(e) => { + if e.is_request() { + error!("[Thread {thread_id}]: Response error from Ambi backend: request error"); + } else if e.is_timeout() { + error!("[Thread {thread_id}]: Response error from Ambi backend: request timed out"); + } else { + error!("[Thread {thread_id}]: Response error from Ambi backend: specific error type unknown"); + } + + debug!("[Thread {thread_id}]: {}", e.to_string()); + debug!( + "[Thread {thread_id}]: Response error from Ambi backend: {:?}", + e + ); + } + } +} + +fn generate_random_reading(rng: &mut ThreadRng) -> String { + let dust_concentration = random_gen_dust_concentration(rng); + let air_purity = AirPurity::from_value(dust_concentration).to_string(); + let reading = Reading::new( + random_gen_temperature(rng), + random_gen_humidity(rng), + random_gen_pressure(rng), + dust_concentration, + air_purity, + ); + + serde_json::to_string(&reading).unwrap() +}