From 72e2e9f18261c6bbd96156305a4aa7e0e4bfd331 Mon Sep 17 00:00:00 2001 From: vandechat96 Date: Mon, 3 Jul 2023 19:26:17 +0200 Subject: [PATCH] initial commit --- .gitignore | 2 + Cargo.lock | 4006 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 34 + src/api.rs | 132 ++ src/config.rs | 55 + src/downloader_api.rs | 84 + src/explore_fs.rs | 65 + src/extractor.rs | 110 + src/install.rs | 181 ++ src/lib.rs | 11 + src/main.rs | 19 + src/mod_parser.rs | 83 + src/ui/app.rs | 769 +++++++ src/ui/download.rs | 108 + src/ui/download_bar.rs | 120 ++ src/ui/installcheckbox.rs | 164 ++ src/ui/mod.rs | 6 + src/ui/modcheckbox.rs | 57 + src/ui/util.rs | 27 + src/util.rs | 147 ++ 20 files changed, 6180 insertions(+) create mode 100755 .gitignore create mode 100755 Cargo.lock create mode 100755 Cargo.toml create mode 100755 src/api.rs create mode 100644 src/config.rs create mode 100755 src/downloader_api.rs create mode 100755 src/explore_fs.rs create mode 100755 src/extractor.rs create mode 100755 src/install.rs create mode 100755 src/lib.rs create mode 100755 src/main.rs create mode 100755 src/mod_parser.rs create mode 100755 src/ui/app.rs create mode 100755 src/ui/download.rs create mode 100755 src/ui/download_bar.rs create mode 100755 src/ui/installcheckbox.rs create mode 100755 src/ui/mod.rs create mode 100755 src/ui/modcheckbox.rs create mode 100755 src/ui/util.rs create mode 100755 src/util.rs diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..3a8cabc --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +.idea diff --git a/Cargo.lock b/Cargo.lock new file mode 100755 index 0000000..8156b0c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4006 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ab_glyph" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcdbc68024b653943864d436fe8a24b028095bc1cf91a8926f8241e4aaffe59" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330223a1aecc308757b9926e9391c9b47f8ef2dbd8aea9df88312aea18c5e8d6" + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.8", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "ash" +version = "0.37.1+1.3.235" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911015c962d56e2e4052f40182ca5462ba60a3d2ff04e827c365a0ab3d65726d" +dependencies = [ + "libloading", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "aw-mod-installer" +version = "0.1.0" +dependencies = [ + "anyhow", + "dirs-next", + "dotenv", + "env_logger", + "iced", + "lazy_static", + "log", + "native-dialog", + "open", + "regex", + "reqwest", + "scraper", + "serde", + "serde_json", + "sevenz-rust", + "strum", + "thiserror", + "tokio", + "zip", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64ct" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + +[[package]] +name = "bytemuck" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" + +[[package]] +name = "bzip2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "calloop" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19457a0da465234abd76134a5c2a910c14bd3c5558463e4396ab9a37a328e465" +dependencies = [ + "log", + "nix 0.25.1", + "slotmap", + "thiserror", + "vec_map", +] + +[[package]] +name = "cc" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + +[[package]] +name = "clipboard-win" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4ab1b92798304eedc095b53942963240037c0516452cb11aeba709d420b2219" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + +[[package]] +name = "clipboard_macos" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145a7f9e9b89453bc0a5e32d166456405d389cea5b578f57f1274b1397588a95" +dependencies = [ + "objc", + "objc-foundation", + "objc_id", +] + +[[package]] +name = "clipboard_wayland" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f6364a9f7a66f2ac1a1a098aa1c7f6b686f2496c6ac5e5c0d773445df912747" +dependencies = [ + "smithay-clipboard", +] + +[[package]] +name = "clipboard_x11" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "983a7010836ecd04dde2c6d27a0cb56ec5d21572177e782bdcb24a600124e921" +dependencies = [ + "thiserror", + "x11rb", +] + +[[package]] +name = "cmake" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" +dependencies = [ + "cc", +] + +[[package]] +name = "cocoa" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics", + "foreign-types 0.3.2", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +dependencies = [ + "bitflags", + "block", + "core-foundation", + "core-graphics-types", + "foreign-types 0.3.2", + "libc", + "objc", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "const_panic" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58baae561b85ca19b3122a9ddd35c8ec40c3bcd14fe89921824eae73f7baffbf" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types 0.3.2", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +dependencies = [ + "bitflags", + "core-foundation", + "foreign-types 0.3.2", + "libc", +] + +[[package]] +name = "core-text" +version = "19.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +dependencies = [ + "core-foundation", + "core-graphics", + "foreign-types 0.3.2", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d0165d2900ae6778e36e80bbc4da3b5eefccee9ba939761f9c2882a5d9af3ff" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.7.1", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossfont" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21fd3add36ea31aba1520aa5288714dd63be506106753226d0eb387a93bc9c45" +dependencies = [ + "cocoa", + "core-foundation", + "core-foundation-sys", + "core-graphics", + "core-text", + "dwrote", + "foreign-types 0.5.0", + "freetype-rs", + "libc", + "log", + "objc", + "once_cell", + "pkg-config", + "servo-fontconfig", + "winapi", +] + +[[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 = "cssparser" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa 0.4.8", + "matches", + "phf 0.8.0", + "proc-macro2", + "quote", + "smallvec", + "syn", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "cty" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + +[[package]] +name = "d3d12" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "827914e1f53b1e0e025ecd3d967a7836b7bcb54520f90e21ef8df7b4d88a2759" +dependencies = [ + "bitflags", + "libloading", + "winapi", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer 0.10.3", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" +dependencies = [ + "libloading", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + +[[package]] +name = "dtoa-short" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dwrote" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +dependencies = [ + "lazy_static", + "libc", + "serde", + "serde_derive", + "winapi", + "wio", +] + +[[package]] +name = "ego-tree" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "encase" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a516181e9a36e8982cb37933c5e7dba638c42938cacde46ee4e5b4156f881b9" +dependencies = [ + "const_panic", + "encase_derive", + "glam", + "thiserror", +] + +[[package]] +name = "encase_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5b802412eea315f29f2bb2da3a5963cd6121f56eaa06aebcdc0c54eea578f22" +dependencies = [ + "encase_derive_impl", +] + +[[package]] +name = "encase_derive_impl" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2f4de457d974f548d2c2a16f709ebd81013579e543bd1a9b19ced88132c2cf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + +[[package]] +name = "euclid" +version = "0.22.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b52c2ef4a78da0ba68fbe1fd920627411096d2ac478f7f4c9f3a54ba6705bade" +dependencies = [ + "num-traits", +] + +[[package]] +name = "expat-sys" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" +dependencies = [ + "cmake", + "pkg-config", +] + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "find-crate" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2" +dependencies = [ + "toml", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8469d0d40519bc608ec6863f1cc88f3f1deee15913f2f3b3e573d81ed38cccc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "freetype-rs" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74eadec9d0a5c28c54bb9882e54787275152a4e36ce206b45d7451384e5bf5fb" +dependencies = [ + "bitflags", + "freetype-sys", + "libc", +] + +[[package]] +name = "freetype-sys" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +dependencies = [ + "cmake", + "libc", + "pkg-config", +] + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" + +[[package]] +name = "futures-executor" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" + +[[package]] +name = "futures-macro" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" + +[[package]] +name = "futures-task" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" + +[[package]] +name = "futures-util" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "glam" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815" + +[[package]] +name = "glow" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glyph_brush" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac02497410cdb5062cc056a33f2e1e19ff69fbf26a4be9a02bf29d6e17ea105b" +dependencies = [ + "glyph_brush_draw_cache", + "glyph_brush_layout", + "log", + "ordered-float", + "rustc-hash", + "twox-hash", +] + +[[package]] +name = "glyph_brush_draw_cache" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6010675390f6889e09a21e2c8b575b3ee25667ea8237a8d59423f73cb8c28610" +dependencies = [ + "ab_glyph", + "crossbeam-channel", + "crossbeam-deque", + "linked-hash-map", + "rayon", + "rustc-hash", +] + +[[package]] +name = "glyph_brush_layout" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" +dependencies = [ + "ab_glyph", + "approx", + "xi-unicode", +] + +[[package]] +name = "gpu-alloc" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" +dependencies = [ + "bitflags", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" +dependencies = [ + "bitflags", +] + +[[package]] +name = "gpu-descriptor" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" +dependencies = [ + "bitflags", + "gpu-descriptor-types", + "hashbrown", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" +dependencies = [ + "bitflags", +] + +[[package]] +name = "guillotiere" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" +dependencies = [ + "euclid", + "svg_fmt", +] + +[[package]] +name = "h2" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.5", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.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.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 1.0.5", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iced" +version = "0.6.0" +source = "git+https://github.com/iced-rs/iced#a6d0d5773f0561a841a84b538523cbd97e91eccd" +dependencies = [ + "iced_core", + "iced_futures", + "iced_graphics", + "iced_native", + "iced_wgpu", + "iced_winit", + "thiserror", +] + +[[package]] +name = "iced_core" +version = "0.6.2" +source = "git+https://github.com/iced-rs/iced#a6d0d5773f0561a841a84b538523cbd97e91eccd" +dependencies = [ + "bitflags", + "palette", + "wasm-timer", +] + +[[package]] +name = "iced_futures" +version = "0.5.1" +source = "git+https://github.com/iced-rs/iced#a6d0d5773f0561a841a84b538523cbd97e91eccd" +dependencies = [ + "futures", + "log", + "tokio", + "wasm-bindgen-futures", + "wasm-timer", +] + +[[package]] +name = "iced_graphics" +version = "0.5.0" +source = "git+https://github.com/iced-rs/iced#a6d0d5773f0561a841a84b538523cbd97e91eccd" +dependencies = [ + "bitflags", + "bytemuck", + "glam", + "iced_native", + "iced_style", + "log", + "raw-window-handle 0.5.0", + "thiserror", +] + +[[package]] +name = "iced_native" +version = "0.7.0" +source = "git+https://github.com/iced-rs/iced#a6d0d5773f0561a841a84b538523cbd97e91eccd" +dependencies = [ + "iced_core", + "iced_futures", + "iced_style", + "num-traits", + "twox-hash", + "unicode-segmentation", +] + +[[package]] +name = "iced_style" +version = "0.5.1" +source = "git+https://github.com/iced-rs/iced#a6d0d5773f0561a841a84b538523cbd97e91eccd" +dependencies = [ + "iced_core", + "once_cell", + "palette", +] + +[[package]] +name = "iced_wgpu" +version = "0.7.0" +source = "git+https://github.com/iced-rs/iced#a6d0d5773f0561a841a84b538523cbd97e91eccd" +dependencies = [ + "bitflags", + "bytemuck", + "encase", + "futures", + "glam", + "glyph_brush", + "guillotiere", + "iced_graphics", + "iced_native", + "log", + "raw-window-handle 0.5.0", + "wgpu", + "wgpu_glyph", +] + +[[package]] +name = "iced_winit" +version = "0.6.0" +source = "git+https://github.com/iced-rs/iced#a6d0d5773f0561a841a84b538523cbd97e91eccd" +dependencies = [ + "iced_futures", + "iced_graphics", + "iced_native", + "log", + "thiserror", + "web-sys", + "winapi", + "window_clipboard", + "winit", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ipnet" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e" + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "khronos-egl" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memmap2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "metal" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" +dependencies = [ + "bitflags", + "block", + "core-graphics-types", + "foreign-types 0.3.2", + "log", + "objc", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.42.0", +] + +[[package]] +name = "naga" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "262d2840e72dbe250e8cf2f522d080988dfca624c4112c096238a4845f591707" +dependencies = [ + "bit-set", + "bitflags", + "codespan-reporting", + "hexf-parse", + "indexmap", + "log", + "num-traits", + "rustc-hash", + "spirv", + "termcolor", + "thiserror", + "unicode-xid", +] + +[[package]] +name = "native-dialog" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab637f328b31bd0855c43bd38a4a4455e74324d9e74e0aac6a803422f43abc6" +dependencies = [ + "block", + "cocoa", + "dirs-next", + "objc", + "objc-foundation", + "objc_id", + "once_cell", + "raw-window-handle 0.4.3", + "thiserror", + "wfd", + "which", + "winapi", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "raw-window-handle 0.5.0", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-glue" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f" +dependencies = [ + "libc", + "log", + "ndk", + "ndk-context", + "ndk-macro", + "ndk-sys", + "once_cell", + "parking_lot 0.12.1", +] + +[[package]] +name = "ndk-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nix" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", + "objc_exception", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_exception" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +dependencies = [ + "cc", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "open" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" +dependencies = [ + "pathdiff", + "windows-sys 0.42.0", +] + +[[package]] +name = "openssl" +version = "0.10.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types 0.3.2", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-float" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf" +dependencies = [ + "num-traits", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18904d3c65493a9f0d7542293d1a7f69bfdc309a6b9ef4f46dc3e58b0577edc5" +dependencies = [ + "ttf-parser", +] + +[[package]] +name = "palette" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f9cd68f7112581033f157e56c77ac4a5538ec5836a2e39284e65bd7d7275e49" +dependencies = [ + "approx", + "num-traits", + "palette_derive", + "phf 0.11.1", +] + +[[package]] +name = "palette_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05eedf46a8e7c27f74af0c9cfcdb004ceca158cb1b918c6f68f8d7a549b3e427" +dependencies = [ + "find-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.5", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.42.0", +] + +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.6", + "hmac", + "password-hash", + "sha2 0.10.6", +] + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_macros 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +dependencies = [ + "phf_macros 0.11.1", + "phf_shared 0.11.1", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +dependencies = [ + "phf_shared 0.11.1", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_macros" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" +dependencies = [ + "phf_generator 0.11.1", + "phf_shared 0.11.1", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "png" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" +dependencies = [ + "bitflags", + "crc32fast", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-crate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +dependencies = [ + "once_cell", + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74605f360ce573babfe43964cbe520294dcb081afbf8c108fc6e23036b4da2df" + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.8", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "range-alloc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" + +[[package]] +name = "raw-window-handle" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76" +dependencies = [ + "libc", + "raw-window-handle 0.4.3", +] + +[[package]] +name = "raw-window-handle" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41" +dependencies = [ + "cty", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a" +dependencies = [ + "cty", +] + +[[package]] +name = "rayon" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.8", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "renderdoc-sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" + +[[package]] +name = "reqwest" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "safe_arch" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ff3d6d9696af502cc3110dacce942840fb06ff4514cad92236ecc455f2ce05" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static", + "windows-sys 0.36.1", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scraper" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5684396b456f3eb69ceeb34d1b5cb1a2f6acf7ca4452131efa3ba0ee2c2d0a70" +dependencies = [ + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "matches", + "selectors", + "smallvec", + "tendril", +] + +[[package]] +name = "sctk-adwaita" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61270629cc6b4d77ec1907db1033d5c2e1a404c412743621981a871dc9c12339" +dependencies = [ + "crossfont", + "log", + "smithay-client-toolkit", + "tiny-skia", +] + +[[package]] +name = "security-framework" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "matches", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", + "thin-slice", +] + +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" + +[[package]] +name = "serde" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +dependencies = [ + "itoa 1.0.5", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.5", + "ryu", + "serde", +] + +[[package]] +name = "servo-fontconfig" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" +dependencies = [ + "libc", + "servo-fontconfig-sys", +] + +[[package]] +name = "servo-fontconfig-sys" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" +dependencies = [ + "expat-sys", + "freetype-sys", + "pkg-config", +] + +[[package]] +name = "servo_arc" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sevenz-rust" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "788cb55c676785bf6d182c1d528106790eedcc9a5e40ac35dcebe252b53b2c6e" +dependencies = [ + "bit-set", + "byteorder", + "crc", + "sha2 0.9.9", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.6", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.6", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "smithay-client-toolkit" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454" +dependencies = [ + "bitflags", + "calloop", + "dlib", + "lazy_static", + "log", + "memmap2", + "nix 0.24.3", + "pkg-config", + "wayland-client", + "wayland-cursor", + "wayland-protocols", +] + +[[package]] +name = "smithay-clipboard" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" +dependencies = [ + "smithay-client-toolkit", + "wayland-client", +] + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spirv" +version = "0.2.0+1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" +dependencies = [ + "bitflags", + "num-traits", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + +[[package]] +name = "string_cache" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot 0.12.1", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "svg_fmt" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thin-slice" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa 1.0.5", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-skia" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642680569bb895b16e4b9d181c60be1ed136fa0c9c7f11d004daf053ba89bf82" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "bytemuck", + "cfg-if", + "png", + "safe_arch", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c114d32f0c2ee43d585367cb013dfaba967ab9f62b90d9af0d696e955e70fa6c" +dependencies = [ + "arrayref", + "bytemuck", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.42.0", +] + +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +dependencies = [ + "serde", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "ttf-parser" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375812fa44dab6df41c195cd2f7fecb488f6c09fbaafb62807488cefab642bff" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[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.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wayland-client" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" +dependencies = [ + "bitflags", + "downcast-rs", + "libc", + "nix 0.24.3", + "scoped-tls", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" +dependencies = [ + "nix 0.24.3", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" +dependencies = [ + "nix 0.24.3", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" +dependencies = [ + "bitflags", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" +dependencies = [ + "proc-macro2", + "quote", + "xml-rs", +] + +[[package]] +name = "wayland-sys" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" +dependencies = [ + "dlib", + "lazy_static", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wfd" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e713040b67aae5bf1a0ae3e1ebba8cc29ab2b90da9aa1bff6e09031a8a41d7a8" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "wgpu" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f643110d228fd62a60c5ed2ab56c4d5b3704520bd50561174ec4ec74932937" +dependencies = [ + "arrayvec 0.7.2", + "js-sys", + "log", + "naga", + "parking_lot 0.12.1", + "raw-window-handle 0.5.0", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6000d1284ef8eec6076fd5544a73125fd7eb9b635f18dceeb829d826f41724ca" +dependencies = [ + "arrayvec 0.7.2", + "bit-vec", + "bitflags", + "cfg_aliases", + "codespan-reporting", + "fxhash", + "log", + "naga", + "parking_lot 0.12.1", + "profiling", + "raw-window-handle 0.5.0", + "smallvec", + "thiserror", + "web-sys", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-hal" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cc320a61acb26be4f549c9b1b53405c10a223fbfea363ec39474c32c348d12f" +dependencies = [ + "android_system_properties", + "arrayvec 0.7.2", + "ash", + "bit-set", + "bitflags", + "block", + "core-graphics-types", + "d3d12", + "foreign-types 0.3.2", + "fxhash", + "glow", + "gpu-alloc", + "gpu-descriptor", + "js-sys", + "khronos-egl", + "libloading", + "log", + "metal", + "naga", + "objc", + "parking_lot 0.12.1", + "profiling", + "range-alloc", + "raw-window-handle 0.5.0", + "renderdoc-sys", + "smallvec", + "thiserror", + "wasm-bindgen", + "web-sys", + "wgpu-types", + "winapi", +] + +[[package]] +name = "wgpu-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb6b28ef22cac17b9109b25b3bf8c9a103eeb293d7c5f78653979b09140375f6" +dependencies = [ + "bitflags", +] + +[[package]] +name = "wgpu_glyph" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cafb82773e0f124a33674dab5de4dff73175aeb921949047ab014efb58fb446" +dependencies = [ + "bytemuck", + "glyph_brush", + "log", + "wgpu", +] + +[[package]] +name = "which" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +dependencies = [ + "either", + "libc", + "once_cell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "window_clipboard" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b47d7fb4df5cd1fea61e5ee3841380f54359bac814e227d8f72709f4f193f8cf" +dependencies = [ + "clipboard-win", + "clipboard_macos", + "clipboard_wayland", + "clipboard_x11", + "raw-window-handle 0.3.4", + "thiserror", +] + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[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 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + +[[package]] +name = "winit" +version = "0.27.2" +source = "git+https://github.com/iced-rs/winit.git?rev=940457522e9fb9f5dac228b0ecfafe0138b4048c#940457522e9fb9f5dac228b0ecfafe0138b4048c" +dependencies = [ + "bitflags", + "cocoa", + "core-foundation", + "core-graphics", + "dispatch", + "instant", + "libc", + "log", + "mio", + "ndk", + "ndk-glue", + "objc", + "once_cell", + "parking_lot 0.12.1", + "percent-encoding", + "raw-window-handle 0.4.3", + "raw-window-handle 0.5.0", + "sctk-adwaita", + "smithay-client-toolkit", + "wasm-bindgen", + "wayland-client", + "wayland-protocols", + "web-sys", + "windows-sys 0.36.1", + "x11-dl", +] + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + +[[package]] +name = "x11-dl" +version = "2.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1536d6965a5d4e573c7ef73a2c15ebcd0b2de3347bdf526c34c297c00ac40f0" +dependencies = [ + "lazy_static", + "libc", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e99be55648b3ae2a52342f9a870c0e138709a3493261ce9b469afe6e4df6d8a" +dependencies = [ + "gethostname", + "nix 0.22.3", + "winapi", + "winapi-wsapoll", +] + +[[package]] +name = "xcursor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" +dependencies = [ + "nom", +] + +[[package]] +name = "xi-unicode" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "zip" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537ce7411d25e54e8ae21a7ce0b15840e7bfcff15b51d697ec3266cc76bdf080" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.4+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" +dependencies = [ + "cc", + "libc", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100755 index 0000000..864d9fa --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "aw-mod-installer" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lazy_static = "1.4" +anyhow = "1.0" +thiserror = "1.0" +log = "0.4" +env_logger = "0.9" + +tokio = { version = "1", features = ["fs","macros"] } + +# utils +regex = "1" +dotenv = "0.15" +dirs-next = "2" +strum = { version = "0.24", features = ["derive"] } + +# file and net +reqwest = { version = "0.11", features = ["json"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +scraper = "0.13" +zip = "0.6" +sevenz-rust = "0.1" + +# ui +iced = {git ="https://github.com/iced-rs/iced", features =["tokio"]} +native-dialog = "0.6" +open = "3" \ No newline at end of file diff --git a/src/api.rs b/src/api.rs new file mode 100755 index 0000000..08f14b2 --- /dev/null +++ b/src/api.rs @@ -0,0 +1,132 @@ +pub mod forum { + // this will be ugly until access to forum API + + use crate::util::{read_cache_file, write_to_cache_json}; + use anyhow::Result; + use log::info; + use scraper::Node::Text; + use scraper::{Html, Selector}; + use serde::{Deserialize, Serialize}; + + #[derive(Debug, Serialize, Deserialize)] + pub struct Post { + pub url: String, + pub author: String, + pub title: String, + pub content: String, + } + + pub async fn get_post_info(url: &str) -> Result { + let response = reqwest::get(url).await?; + let txt = response.text().await?; + let doc = Html::parse_document(&txt); + + let info_selector = Selector::parse( + r#"div[class="ipsPhotoPanel ipsPhotoPanel_small ipsPhotoPanel_notPhone ipsClearfix"]"#, + ) + .unwrap(); + let info = doc.select(&info_selector).next().unwrap(); + + let author_selector = Selector::parse(r#"a[class="ipsType_break"]"#).unwrap(); + let author_elem = info.select(&author_selector).next().unwrap(); + + let selector = Selector::parse("h1").unwrap(); + let h1 = info.select(&selector).next().unwrap(); + let title_selector = + Selector::parse(r#"span[class="ipsType_break ipsContained"]"#).unwrap(); + let title_elem = h1.select(&title_selector).next().unwrap(); + + let selector = Selector::parse("span").unwrap(); + let span = title_elem.select(&selector).next().unwrap(); + + let title = span.inner_html(); + let mut author = author_elem.inner_html(); + + let parsed = Html::parse_fragment(&author); + let selector = Selector::parse("span").unwrap(); + if let Some(span) = parsed.select(&selector).next() { + let mut children = span.children(); + while let Some(child) = children.next() { + if let Text(name) = child.value() { + author = name.to_string(); + break; + } + children = child.children(); + } + } + + let article_selector = Selector::parse("article").unwrap(); + let article = doc.select(&article_selector).next().unwrap(); + + let selector = Selector::parse(r#"div[class="cPost_contentWrap ipsPad"]"#).unwrap(); + let div = article.select(&selector).next().unwrap(); + + let p_selector = Selector::parse("p").unwrap(); + let mut content = String::new(); + for p in div.select(&p_selector) { + content.push_str(&p.inner_html()); + content.push('\n'); + } + Ok(Post { + url: url.to_string(), + title, + author, + content, + }) + } + + pub async fn get_posts() -> Result> { + let url = "https://armoredlabs.net/index.php?/forum/45-game-mods-add-ons"; + let mut posts_url = Vec::new(); + + for i in 1..=5 { + info!("Parsing page {}", i); + let url = format!("{}/page/{}", url, i); + info!("{}", url); + if let Ok(response) = reqwest::get(url).await { + let txt = response.text().await?; + let doc = Html::parse_document(&txt); + let main_selector = Selector::parse(r#"div[id="ipsLayout_mainArea"]"#).unwrap(); + + let main = doc.select(&main_selector).next().unwrap(); + let post_selector = + Selector::parse(r#"span[class="ipsType_break ipsContained"]"#).unwrap(); + + for element in main.select(&post_selector) { + let selector = Selector::parse("a").unwrap(); + let a = element.select(&selector).next().unwrap(); + let post_url = a.value().attr("href").unwrap(); + posts_url.push(post_url.to_owned()); + } + } else { + info!("Error while fetching page : {}", i); + } + } + let mut posts = Vec::new(); + for url in posts_url { + for i in 1..=4 { + if let Ok(post) = get_post_info(&url).await { + info!("Found post : {} - {}", post.title, post.author); + posts.push(post); + break; + } else { + info!("Error while fetching mod : {}", url); + info!("Retrying {} of 4...", i); + } + } + } + Ok(posts) + } + + pub async fn write_posts_to_disk() -> Result<()> { + let posts = get_posts().await?; + write_to_cache_json(&posts, "posts").await + } + + pub async fn fetch_posts_from_disk() -> Result> { + let content = read_cache_file("posts.json").await?; + + let posts = serde_json::from_slice(&content)?; + Ok(posts) + } +} diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..25e0183 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,55 @@ +use crate::util::{find_aw_path, get_app_config_path, read_file, write_to_json, LoadError}; +use serde::{Deserialize, Serialize}; +use std::fs::File; +use std::path::PathBuf; + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct Config { + pub aw_path: PathBuf, + pub installed_mod: Vec, +} + +impl Default for Config { + fn default() -> Self { + Self { + aw_path: find_aw_path(), + installed_mod: vec![], + } + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct InstalledMod { + pub download: String, + pub title: String, + pub path: PathBuf, +} + +impl InstalledMod { + pub fn new(download: String, title: String, path: PathBuf) -> Self { + Self { download, title, path } + } +} + +pub async fn get_config() -> Result { + let path = get_app_config_path().map_err(|_| LoadError::File)?; + + if !path.exists() { + File::create(&path).map_err(|_| LoadError::File)?; + write_to_json(&Config::default(), &path) + .await + .map_err(|_| LoadError::File)?; + } + + let content = read_file(path).await.map_err(|_| LoadError::File)?; + + serde_json::from_slice(&content).map_err(|_| LoadError::Format) +} + +pub async fn update_config(cfg: Config) -> Result<(), LoadError> { + let path = get_app_config_path().map_err(|_| LoadError::File)?; + + write_to_json(&cfg, &path) + .await + .map_err(|_| LoadError::File) +} diff --git a/src/downloader_api.rs b/src/downloader_api.rs new file mode 100755 index 0000000..67e60d6 --- /dev/null +++ b/src/downloader_api.rs @@ -0,0 +1,84 @@ +use crate::util::get_app_download_path; +use anyhow::{Context, Result}; +use lazy_static::lazy_static; +use regex::Regex; +use serde::Deserialize; +use std::path::PathBuf; + +lazy_static! { + static ref DRIVE_API_KEY: Result = + std::env::var("DRIVE_API_KEY").map_err(|_| InfoError::APIKey("Drive".to_string())); + static ref DRIVE_RE: Regex = + Regex::new(r#"https://drive.google.com/file/d/([-_\w]+)/"#).unwrap(); + static ref FORUM_RE: Regex = Regex::new( + r#"https://armoredlabs.net/applications/core/interface/file/attachment.php?id=(\d+)"# + ) + .unwrap(); +} + +#[derive(Debug, Clone)] +pub enum InfoError { + File, + Connection, + FormatUrl(String), + FormatResponse, + APIKey(String), +} +pub type ResponseInfo = Result<(String, PathBuf), InfoError>; + +#[derive(Debug, Clone)] +pub struct DownloadInfo { + pub(crate) title: String, + pub(crate) info: ResponseInfo, +} + +pub async fn get_download_info(url: String) -> ResponseInfo { + if let Some(capt) = DRIVE_RE.captures(&url) { + let id = capt + .get(1) + .context("Id not found in url") + .map_err(|_| InfoError::FormatUrl(url.clone()))? + .as_str(); + get_drive_download_info(id).await + } else if let Some(capt) = DRIVE_RE.captures(&url) { + let id = capt + .get(1) + .context("Id not found in url") + .map_err(|_| InfoError::FormatUrl(url.clone()))? + .as_str(); + let mut path = get_app_download_path().map_err(|_| InfoError::File)?; + path.push(id); + Ok((url, path)) + } else { + Err(InfoError::FormatUrl(url)) + } +} + +#[derive(Deserialize)] +pub struct DriveResponse { + name: String, +} + +async fn get_drive_download_info(id: &str) -> ResponseInfo { + let key = &*DRIVE_API_KEY.clone()?; + let base_url = "https://www.googleapis.com/drive/v3/files"; + let mut file_url = format!("{base_url}/{id}?key={key}"); + + let response = reqwest::get(&file_url) + .await + .map_err(|_| InfoError::Connection)?; + match response.error_for_status() { + Ok(res) => { + let info: DriveResponse = res.json().await.map_err(|_| InfoError::FormatResponse)?; + + let file_name = info.name; + let mut path = get_app_download_path().map_err(|_| InfoError::File)?; + path.push(file_name); + + file_url.push_str("&alt=media"); + + Ok((file_url, path)) + } + Err(_) => Err(InfoError::Connection), + } +} diff --git a/src/explore_fs.rs b/src/explore_fs.rs new file mode 100755 index 0000000..bfe2c4b --- /dev/null +++ b/src/explore_fs.rs @@ -0,0 +1,65 @@ +use std::path::{Path, PathBuf}; + +pub async fn _explore() { + /* + let gs_path = PathBuf::from("/run/media/jika/Windows/MyGames/Armored Warfare MyCom/gamesdk/"); + let el_path = PathBuf::from( + "/run/media/jika/Windows/MyGames/Armored Warfare MyCom/localization/english/", + ); + let mut list = list_files(&gs_path); + list.extend(list_files(&el_path)); + list = list + .into_iter() + .map(|x| { + x.strip_prefix("/run/media/jika/Windows/MyGames/Armored Warfare MyCom/") + .unwrap() + .to_path_buf() + }) + .collect(); + write_to_cache_json(&list, "files").await.unwrap(); + + + let mut file = File::create("./list.txt").unwrap(); + file.write_all(format!("{:#?}", list).as_bytes()).unwrap(); + println!("a"); + + let mut unique_name = vec![]; + for file in &list { + if let Some(name) = file.file_name() { + let name = name.to_os_string(); + if !unique_name.contains(&name) { + unique_name.push(name); + } + } + } + let mut file = File::create("./unique_name.txt").unwrap(); + file.write_all(format!("{:#?}", unique_name).as_bytes()) + .unwrap(); + println!("b"); + + let mut file = File::create("./unique_list.txt").unwrap(); + for name in unique_name { + let list: Vec<&PathBuf> = list + .iter() + .filter(|path| path.file_name().unwrap() == name) + .collect(); + + file.write_all(format!("=== {} ==={}", name.to_str().unwrap(), list.len()).as_bytes()) + .unwrap(); + file.write_all(format!("{:#?}", list).as_bytes()).unwrap(); + } + + */ +} + +fn _list_files(path: &Path) -> Vec { + if let Ok(read_dir) = path.read_dir() { + let mut list = vec![]; + for entry in read_dir.flatten() { + list.extend(_list_files(&entry.path())); + } + list + } else { + vec![path.to_path_buf()] + } +} diff --git a/src/extractor.rs b/src/extractor.rs new file mode 100755 index 0000000..fdcbcc4 --- /dev/null +++ b/src/extractor.rs @@ -0,0 +1,110 @@ +use anyhow::{bail, Result}; +use log::debug; +use std::fs::File; +use std::future::Future; +use std::path::PathBuf; +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::{fs, io}; + +#[derive(Debug, Clone)] +pub struct ModArchive { + pub title: String, + pub path: PathBuf, +} + +#[derive(Debug, Clone)] +pub enum ExtractError { + File, +} + +pub async fn extract_all( + files: Vec, +) -> std::result::Result, ExtractError> { + ExtractAll { files, current: 0 }.await +} + +#[derive(Debug)] +pub struct ExtractAll { + pub files: Vec, + current: usize, +} +impl Future for ExtractAll { + type Output = std::result::Result, ExtractError>; + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if self.current >= self.files.len() { + Poll::Ready(Ok(self.files.to_owned())) + } else { + self.current += 1; + let file = &self.files[self.current - 1]; + + match extract_archive(&file.path) { + Ok(_) => {} + Err(_) => { + return Poll::Ready(Err(ExtractError::File)); + } + }; + // Schedule future for another poll() + cx.waker().clone().wake(); + + Poll::Pending + } + } +} + +pub fn extract_archive(path: &PathBuf) -> Result<()> { + if let Some(ext) = path.extension() { + match ext.to_str().unwrap() { + "7z" => extract_7zip(path.to_owned())?, + "zip" => extract_zip(path.to_owned())?, + _ => {} + } + } else { + bail!("not file") + } + Ok(()) +} + +pub fn extract_zip(path: PathBuf) -> Result<()> { + let dest_path = path.with_extension("d"); + fs::create_dir_all(&dest_path)?; + let file = File::open(&path)?; + let mut zip = zip::ZipArchive::new(file)?; + + for i in 0..zip.len() { + let mut file = zip.by_index(i)?; + debug!("Filename: {}", file.name()); + let mut outpath = dest_path.clone(); + match file.enclosed_name() { + Some(path) => outpath.push(path), + None => continue, + }; + + if (*file.name()).ends_with('/') { + debug!("File {} extracted to \"{}\"", i, outpath.display()); + fs::create_dir_all(&outpath).unwrap(); + } else { + debug!( + "File {} extracted to \"{}\" ({} bytes)", + i, + outpath.display(), + file.size() + ); + if let Some(p) = outpath.parent() { + if !p.exists() { + fs::create_dir_all(&p).unwrap(); + } + } + let mut outfile = File::create(&outpath).unwrap(); + io::copy(&mut file, &mut outfile).unwrap(); + } + } + Ok(()) +} + +pub fn extract_7zip(path: PathBuf) -> Result<()> { + let des_path = path.with_extension("d"); + fs::create_dir_all(&des_path)?; + sevenz_rust::decompress_file(path, des_path)?; + Ok(()) +} diff --git a/src/install.rs b/src/install.rs new file mode 100755 index 0000000..501373e --- /dev/null +++ b/src/install.rs @@ -0,0 +1,181 @@ +use crate::util::{get_app_download_path, read_cache_file_sync, LoadError}; +use lazy_static::lazy_static; +use log::debug; +use std::ffi::OsStr; +use std::fs; +use std::fs::create_dir_all; +use std::path::{Path, PathBuf}; +use thiserror::Error; + +lazy_static! { + static ref GAME_FILES: Result, LoadError> = fetch_file_list_from_disk(); +} + +#[derive(Debug, Clone)] +pub struct State { + pub(crate) show_children: bool, + pub(crate) selected: bool, + pub(crate) id: usize, +} + +#[derive(Debug, Clone)] +pub enum FSElement { + Dir(String, PathBuf, Vec, State), + File(String, PathBuf, State), +} +impl FSElement { + pub fn is_dir(&self) -> bool { + match self { + FSElement::Dir(..) => true, + FSElement::File(..) => false, + } + } +} + +pub fn crawl(id: usize, path: &Path) -> (usize, FSElement) { + let name = path.file_name().unwrap().to_str().unwrap().to_string(); + let state = State { + show_children: false, + selected: true, + id, + }; + if let Ok(read_dir) = path.read_dir() { + let mut list = vec![]; + let mut id = id; + for entry in read_dir.flatten() { + let (sub_id, elem) = crawl(id + 1, &entry.path()); + id = sub_id; + list.push(elem) + } + (id, FSElement::Dir(name, path.to_path_buf(), list, state)) + } else { + (id, FSElement::File(name, path.to_path_buf(), state)) + } +} + +pub fn list_mod() -> Vec { + let path = get_app_download_path().unwrap(); + let mut list = vec![]; + if let Ok(read_dir) = path.read_dir() { + for entry in read_dir.flatten() { + if entry.metadata().unwrap().is_dir() { + let (_, elem) = crawl(0, &entry.path()); + list.push(elem) + } + } + } + list +} + +#[derive(Error, Clone, Debug)] +pub enum InstallError { + #[error("Path is not a downloaded mod path")] + Path, + #[error("Failed to install this mod type")] + ModType, + #[error("Failed to copy the mod to the target location")] + Copy, + #[error("Game file list could not be loaded")] + Files, +} + +fn is_known_name(name: &str) -> Option<&str> { + match name { + "localization" => Some(""), + "english" | "french" | "german" | "polish" | "russian" => Some("localization"), + "animations" | "Levels" | "libs" | "materials" | "movies" | "music" | "objects" + | "sounds" | "textures" => Some("localization/english"), + _ => None, + } +} +fn dir_copy(from: &Path, to: &Path, lang: &str) -> anyhow::Result<()> { + debug!("Create dir {:?} ", to); + create_dir_all(to)?; + let mut to_path = to.to_path_buf(); + let name = match from.file_name().unwrap() { + a if a == "english" => OsStr::new(lang), + a => a, + }; + to_path.push(name); + + if let Ok(read_dir) = from.read_dir() { + for entry in read_dir.flatten() { + debug!("Process {:?} to {:?}", entry.path(), to_path); + dir_copy(&entry.path(), &to_path, lang)? + } + } else { + debug!("copy file {:?}", to_path); + fs::copy(from, to_path)?; + } + Ok(()) +} + +pub fn install(mod_: &FSElement, game_path: &Path, lang: &str) -> Result<(), InstallError> { + match mod_ { + FSElement::Dir(name, path, children, state) => { + if !state.selected { + return Ok(()); + } + // if folder name is known copy it to game folder + if let Some(install_path) = is_known_name(name) { + let mut game_path = game_path.to_path_buf(); + game_path.push(install_path.replace("english", lang)); + + dir_copy(path, &game_path, lang).map_err(|_| InstallError::Copy)?; + } else { + for child in children { + install(child, game_path, lang)?; + } + } + + Ok(()) + } + FSElement::File(name, from, state) => { + if !state.selected { + return Ok(()); + } + let files = (*GAME_FILES).as_ref().map_err(|_| InstallError::Files)?; + let mut iter = files.iter(); + let test = |x: &&String| { + let v: Vec<&str> = x.split('/').collect(); + let n = v.last().unwrap(); + + *n == name + }; + if let Some(path) = iter.find(test) { + if iter.find(test).is_some() { + return Err(InstallError::ModType); + } + + let mut found_path = path.clone(); + + if path.starts_with("gamesdk") { + let replace = format!("localization/{}", lang); + found_path = found_path.replace("gamesdk", &replace); + } + let mut to = game_path.to_path_buf(); + to.push(found_path); + create_dir_all(to.parent().unwrap()).map_err(|_| InstallError::Copy)?; + fs::copy(from, to).map_err(|_| InstallError::Copy)?; + } + Ok(()) + } + } +} + +fn fetch_file_list_from_disk() -> Result, LoadError> { + let content = read_cache_file_sync("files.json").map_err(|_| LoadError::File)?; + + serde_json::from_slice(&content).map_err(|_| LoadError::Format) +} + +pub fn remove_mods(aw_path: &Path) -> anyhow::Result<()> { + if let Ok(read_dir) = aw_path.read_dir() { + for entry in read_dir.flatten() { + if entry.file_name() != "movies" { + fs::remove_dir_all(entry.path())?; + } + } + } + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100755 index 0000000..5c75b8c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,11 @@ +extern crate core; + +pub mod api; +pub mod config; +pub mod downloader_api; +pub mod explore_fs; +pub mod extractor; +pub mod install; +pub mod mod_parser; +pub mod ui; +pub mod util; diff --git a/src/main.rs b/src/main.rs new file mode 100755 index 0000000..f7b4f74 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,19 @@ +use anyhow::{Context, Result}; +use aw_mod_installer::ui::app::App; +use iced::{Application, Settings}; +use std::env; + +//#[tokio::main] +fn main() -> Result<()> { + env_logger::init(); + + dotenv::dotenv().context("Error while reading .env file")?; + + if cfg!(windows) && env::var("WGPU_BACKEND").is_err() { + env::set_var("WGPU_BACKEND", "DX12") + } + + App::run(Settings::default()).context("App could not be started")?; + + Ok(()) +} diff --git a/src/mod_parser.rs b/src/mod_parser.rs new file mode 100755 index 0000000..7dd6484 --- /dev/null +++ b/src/mod_parser.rs @@ -0,0 +1,83 @@ +use crate::api::forum::Post; +use crate::util::{read_cache_file, write_to_cache_json, LoadError}; +use anyhow::Result; +use log::info; +use regex::Regex; +use serde::{Deserialize, Serialize}; +use strum::{Display, EnumIter}; + +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone, EnumIter, Display)] +pub enum Tag { + All, + Sound, + Skin, + Model, + Camo, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Mod { + pub url: String, + pub author: String, + pub title: String, + pub content: String, + pub downloads: Vec, + pub tags: Vec, +} + +impl From for Mod { + fn from(post: Post) -> Self { + Self { + url: post.url, + author: post.author, + title: post.title, + content: post.content, + downloads: vec![], + tags: vec![], + } + } +} + +pub fn filter_mods(posts: Vec) -> Vec { + let title_regex = Regex::new(r"\?|guide|tuto|tutorial|request").unwrap(); + let download_regex = + Regex::new(r##""((https://cloud.mail.ru/|https://mega.nz/|https://drive.google.com/|https://disk.yandex.ru/|https://armoredlabs.net/applications/core/interface/file/attachment.php?)[\w/=?\-#]+)""##) + .unwrap(); + + let mut mods = Vec::new(); + for post in posts { + let mut urls = Vec::new(); + info!("== {} ==", post.title); + match post.title { + x if title_regex.is_match(&x) => continue, + _ => { + for captures in download_regex.captures_iter(&post.content) { + if let Some(match_) = captures.get(1) { + let url = match_.as_str(); + urls.push(url.to_string()); + info!("Found {:?}", url); + } + } + } + } + if !urls.is_empty() { + let mut mod_: Mod = post.into(); + mod_.downloads = urls; + mods.push(mod_); + } + } + mods +} + +pub async fn write_mod_list(posts: Vec) -> Result<()> { + let mods = filter_mods(posts); + write_to_cache_json(&mods, "mods").await +} + +pub async fn fetch_mods_from_disk() -> std::result::Result, LoadError> { + let content = read_cache_file("mods.json") + .await + .map_err(|_| LoadError::File)?; + + serde_json::from_slice(&content).map_err(|_| LoadError::Format) +} diff --git a/src/ui/app.rs b/src/ui/app.rs new file mode 100755 index 0000000..542b4a5 --- /dev/null +++ b/src/ui/app.rs @@ -0,0 +1,769 @@ +use crate::config::{get_config, update_config, Config, InstalledMod}; +use crate::downloader_api::{get_download_info, DownloadInfo, InfoError}; +use crate::extractor::{extract_all, ExtractError, ModArchive}; +use crate::install::{install, remove_mods, FSElement}; +use crate::mod_parser::{fetch_mods_from_disk, Mod, Tag}; +use crate::ui; +use crate::ui::download::Progress; +use crate::ui::download_bar::DownloadBar; +use crate::ui::installcheckbox::InstallCheckbox; +use crate::ui::modcheckbox::ModCheckbox; +use crate::ui::util::{open_url, show_error_dialog, show_question_dialog}; +use crate::util::{find_aw_path, get_app_cache_path, get_app_config_path, is_aw_dir, LoadError}; +use iced::alignment::Horizontal; +use iced::widget::{ + button, checkbox, column, container, horizontal_space, pick_list, row, scrollable, text, + text_input, vertical_space, Button, Column, +}; +use iced::{theme, Alignment, Application, Command, Element, Length, Subscription, Theme}; +use lazy_static::lazy_static; +use native_dialog::FileDialog; +use std::path::{Path, PathBuf}; +use std::string::ToString; +use strum::IntoEnumIterator; + +lazy_static! { + static ref LANGUAGE_LIST: Vec = vec![ + String::from("english"), + String::from("french"), + String::from("german"), + String::from("polish"), + String::from("russian"), + ]; +} + +pub struct App { + steps: Steps, + config: Config, +} + +#[derive(Debug, Clone)] +pub enum Message { + BackPressed, + NextPressed, + StepMessage(StepMessage), + ModsLoaded(Result, LoadError>), + ConfigLoaded(Result), + UpdateConfig(Result<(), LoadError>), +} + +impl Application for App { + type Executor = iced::executor::Default; + type Message = Message; + type Theme = Theme; + type Flags = (); + + fn new(_flags: ()) -> (Self, Command) { + ( + Self { + steps: Steps::new(), + + config: Config::default(), + }, + Command::perform(get_config(), Message::ConfigLoaded), + ) + } + + fn title(&self) -> String { + format!("{} - AW mod installer", self.steps.title()) + } + + fn update(&mut self, event: Message) -> Command { + match event { + Message::BackPressed => { + self.steps.go_back(); + + if let Step::Installation(extracting, ..) = + &mut self.steps.steps[self.steps.current + 1] + { + *extracting = false; + } + + Command::none() + } + Message::NextPressed => { + let cmd = match &self.steps.steps[self.steps.current] { + Step::Welcome(path) => { + self.config.aw_path = path.to_owned(); + + Command::none() + } + Step::Selection(state) => { + let urls: Vec<_> = state + .mod_list + .iter() + .filter(|x| x.selected) + .map(|mod_| { + let url = mod_.get_download_url(); + let title = mod_.m.title.clone(); + + if !self.config.installed_mod.iter().any(|m| m.download == url) { + self.config.installed_mod.push(InstalledMod::new( + url.clone(), + mod_.m.title.clone(), + PathBuf::new(), + )); + } + + Command::perform(get_download_info(url), |x| { + Message::StepMessage(StepMessage::DownloadInfoFound( + DownloadInfo { title, info: x }, + )) + }) + }) + .collect(); + if !urls.is_empty() { + if let Step::Download(bool, _) = + &mut self.steps.steps[self.steps.current + 1] + { + *bool = false; + } + } + Command::batch(urls) + } + Step::Download(_, downloads) => { + let mut mods = vec![]; + if let Step::Installation(_, extracted, ..) = + &self.steps.steps[self.steps.current + 1] + { + for download in downloads { + if let Some(found) = self + .config + .installed_mod + .iter_mut() + .find(|m| m.title == download.title) + { + found.path = download.path.clone(); + } + if !extracted.iter().any(|x| x.path == download.path) { + mods.push(ModArchive { + title: download.title.clone(), + path: download.path.clone(), + }) + } + } + } + + Command::perform(extract_all(mods), |x| { + Message::StepMessage(StepMessage::Extracted(x)) + }) + } + Step::Installation(_, install_list, lang, clean) => { + if *clean { + if install_list.is_empty() { + self.config.installed_mod = vec![]; + } + let mut path = self.config.aw_path.clone(); + path.push("localization"); + path.push(lang); + + remove_mods(&path).unwrap_or_else(|_| { + show_error_dialog( + "Error removing mods", + "An error occurred while removing installed mods.\ + \nSome mod could have not been removed.\ + \nYou can remove them manually and restart the process.", + ) + }); + } + + for mod_ in install_list { + if let FSElement::Dir(_, _, _, state) = &mod_.file_list { + if !state.selected { + if let Some(id) = self + .config + .installed_mod + .iter() + .position(|m| mod_.title == m.title) + { + self.config.installed_mod.remove(id); + } + } + }; + install(&mod_.file_list, &self.config.aw_path, lang).unwrap_or_else( + |e| { + let content = format!( + "The mod {} could not be correctly installed.\ + \n Please report the issue if possible.\n Error :{:?}", + mod_.title, e + ); + show_error_dialog("Error installing Mod", &content); + }, + ) + } + Command::none() + } + _ => Command::none(), + }; + self.steps.advance(); + + let update_cmd = + Command::perform(update_config(self.config.clone()), Message::UpdateConfig); + Command::batch([cmd, update_cmd]) + } + Message::ConfigLoaded(result) => { + match result { + Ok(cfg) => self.config = cfg, + Err(_) => show_error_dialog( + "Error loading config", + "The configuration file could not be loaded using default settings.", + ), + } + + Command::perform(fetch_mods_from_disk(), Message::ModsLoaded) + } + Message::ModsLoaded(loaded) => { + if let Ok(mods) = loaded { + let cfg = &self.config; + let mut mod_list: Vec = vec![]; + let mut installed_list = vec![]; + let mut extracted_list = vec![]; + + for m in mods { + let mut selected = false; + let mut version = None; + if let Some(found) = cfg.installed_mod.iter().find(|c| c.title == m.title) { + if let Some(i) = m.downloads.iter().position(|x| *x == found.download) { + selected = true; + if m.downloads.len() > 1 { + version = Some(i); + } + installed_list.push(DownloadBar::from_installed(i, found.clone())); + extracted_list.push(InstallCheckbox::from(found.clone())); + } + } + mod_list.push(ModCheckbox::new(m, selected, version)); + } + let new_steps = Steps::get_next_steps(mod_list, installed_list, extracted_list); + self.steps.steps.extend(new_steps); + } else { + let content = format!( + "The mod file could not be loaded!\ + \nPlease restart the app and try again.\ + \nIf the error persist check the files in {}", + get_app_cache_path().unwrap_or_default().to_str().unwrap() + ); + show_error_dialog("Error loading mods", &content) + } + + Command::none() + } + Message::StepMessage(step_msg) => { + self.steps.update(step_msg); + + Command::none() + } + Message::UpdateConfig(res) => { + match res { + Ok(_) => {} + Err(_) => { + let path = get_app_config_path().unwrap_or_default(); + let content = format!("Configuration could not be saved ! Please restart the app and/or check the file at {:?}.",path); + show_error_dialog("Error saving config", &content); + } + }; + Command::none() + } + } + } + + fn view(&self) -> Element { + let Self { steps, .. } = self; + + let mut controls = row![]; + + if steps.can_go_back() { + controls = controls.push( + button_c("Back") + .on_press(Message::BackPressed) + .style(theme::Button::Secondary), + ); + } + + controls = controls.push(horizontal_space(Length::Fill)); + + if steps.can_continue() { + controls = controls.push( + button_c("Next") + .on_press(Message::NextPressed) + .style(theme::Button::Primary), + ); + } + + let content = column![steps.view().map(Message::StepMessage), controls,] + .spacing(20) + .padding(20) + .max_width(1000); + + match self.steps.steps[self.steps.current] { + Step::Selection(_) => container(content) + .center_x() + .center_y() + .height(Length::Fill) + .width(Length::Fill) + .into(), + _ => { + let scrollable = scrollable(container(content).width(Length::Fill).center_x()); + + container(scrollable).height(Length::Fill).center_y().into() + } + } + } + + fn theme(&self) -> Self::Theme { + Theme::Dark + } + + fn subscription(&self) -> Subscription { + self.steps.subscription().map(Message::StepMessage) + } +} + +struct Steps { + steps: Vec, + current: usize, +} + +impl Steps { + fn new() -> Steps { + Steps { + steps: vec![Step::Welcome(find_aw_path())], + current: 0, + } + } + + fn get_next_steps( + mod_list: Vec, + installed_list: Vec, + extracted_list: Vec, + ) -> Vec { + vec![ + Step::Selection(SelectionStruct::new(mod_list)), + Step::Download(true, installed_list), + Step::Installation(false, extracted_list, "english".to_string(), false), + Step::End, + ] + } + + fn update(&mut self, msg: StepMessage) { + self.steps[self.current].update(msg); + } + + fn subscription(&self) -> Subscription { + Subscription::batch(self.steps.iter().map(Step::subscription)) + } + + fn view(&self) -> Element { + self.steps[self.current].view() + } + + fn advance(&mut self) { + if self.can_continue() { + self.current += 1; + } + } + + fn go_back(&mut self) { + if self.can_go_back() { + self.current -= 1; + } + } + + fn can_go_back(&self) -> bool { + self.current > 0 && self.steps[self.current].can_go_back() + } + + fn can_continue(&self) -> bool { + self.steps.len() > 1 + && self.current + 1 < self.steps.len() + && self.steps[self.current].can_continue() + } + + fn title(&self) -> &str { + self.steps[self.current].title() + } +} + +struct SelectionStruct { + input: String, + mod_list: Vec, + filter: Tag, +} + +impl SelectionStruct { + pub fn new(mod_list: Vec) -> Self { + Self { + input: String::new(), + mod_list, + filter: Tag::All, + } + } +} +enum Step { + Welcome(PathBuf), + Selection(SelectionStruct), + Download(bool, Vec), + Installation(bool, Vec, String, bool), + End, +} + +#[derive(Debug, Clone)] +pub enum StepMessage { + ModChecked(usize, bool), + VersionSelected(usize, usize), + OpenExt(String), + AWPathInputChanged(String), + SelectAWPath, + FilterInputChanged(String), + ChangeFilter(Tag), + DownloadInfoFound(DownloadInfo), + Download(usize), + DownloadProgressed((usize, Progress)), + Extracted(Result, ExtractError>), + InstallModChecked(usize, usize), + InstallModShow(usize, usize), + LangSelected(String), + ToggleCleanInstall(bool), +} + +impl<'a> Step { + fn subscription(&self) -> Subscription { + match self { + Step::Download(_, downloads) => { + Subscription::batch(downloads.iter().map(DownloadBar::subscription)) + } + _ => Subscription::none(), + } + } + + fn update(&mut self, msg: StepMessage) { + match msg { + StepMessage::ModChecked(i, checked) => { + if let Step::Selection(state) = self { + let m = state.mod_list.get_mut(i).unwrap(); + if m.m.downloads.len() <= 1 || m.version.is_some() { + m.selected = checked; + } + } + } + StepMessage::VersionSelected(i, version) => { + if let Step::Selection(state) = self { + let m = state.mod_list.get_mut(i).unwrap(); + m.version = Some(version); + } + } + StepMessage::OpenExt(url) => { + open_url(url); + } + StepMessage::AWPathInputChanged(path) => { + if let Step::Welcome(old_path) = self { + *old_path = PathBuf::from(path); + } + } + StepMessage::SelectAWPath => { + if let Step::Welcome(old_path) = self { + let path = FileDialog::new() + .add_filter("exe", &["exe"]) + .show_open_single_file() + .unwrap(); + + let path = match path { + Some(path) => path, + None => return, + }; + if let Some(path) = path.parent() { + if let Some(path) = path.parent() { + if is_aw_dir(path.to_path_buf()) { + *old_path = path.to_path_buf(); + } + } + } + } + } + StepMessage::FilterInputChanged(input) => { + if let Step::Selection(state) = self { + state.input = input; + } + } + StepMessage::ChangeFilter(new_filter) => { + if let Step::Selection(state) = self { + state.filter = new_filter; + } + } + StepMessage::DownloadInfoFound(res) => { + if let Step::Download(bool, downloads) = self { + *bool = true; + match res.info { + Ok((url, path)) => { + if !downloads + .iter() + .any(|d| d.url == url || (d.path == path && d.url == "skip")) + { + let id = downloads.len(); + let mut download = DownloadBar::new(id, url, path, res.title); + download.start(); + downloads.push(download) + } + } + Err(err) => match err { + InfoError::FormatUrl(url) => { + let response = show_question_dialog("Mod could not be downloaded","A mod could not be automatically downloaded would you like to open the download link in a browser ?"); + if response { + open_url(url) + } + } + InfoError::APIKey(api) => { + let txt = format!( + "The key for the {} API was not found int the .env file.", + api + ); + show_error_dialog("API key not found !", txt.as_str()) + } + _ => {} + }, + } + } + } + StepMessage::Download(index) => { + if let Step::Download(_, downloads) = self { + if let Some(download) = downloads.get_mut(index) { + download.start(); + } + } + } + StepMessage::DownloadProgressed((id, progress)) => { + if let Step::Download(_, downloads) = self { + if let Some(download) = downloads.iter_mut().find(|download| download.id == id) + { + download.progress(progress); + } + } + } + StepMessage::Extracted(r) => { + if let Step::Installation(extracting, extracted, ..) = self { + if let Ok(extracted_) = r { + for arch in extracted_ { + extracted.push(arch.into()); + } + } + *extracting = true; + } + } + StepMessage::InstallModChecked(box_id, fs_id) => { + if let Step::Installation(_, extracted, ..) = self { + let box_ = &mut extracted[box_id]; + box_.toggle_checked(fs_id) + } + } + StepMessage::InstallModShow(box_id, fs_id) => { + if let Step::Installation(_, extracted, ..) = self { + let box_ = &mut extracted[box_id]; + box_.toggle_show(fs_id) + } + } + StepMessage::LangSelected(lang) => { + if let Step::Installation(.., current_lang, _) = self { + *current_lang = lang; + } + } + StepMessage::ToggleCleanInstall(new) => { + if let Step::Installation(.., clean) = self { + *clean = new; + } + } + } + } + + fn title(&self) -> &str { + match self { + Step::Welcome(_) => "Welcome", + Step::Selection(_) => "Selection", + Step::Download(..) => "Download", + Step::Installation(..) => "Installation", + Step::End => "End", + } + } + + fn can_download_continue(downloads: &Vec) -> bool { + for d in downloads { + match d.state { + ui::download_bar::State::Finished { .. } => {} + _ => return false, + } + } + true + } + + pub fn can_go_back(&self) -> bool { + match self { + Step::Download(bool, downloads) => *bool && Self::can_download_continue(downloads), + Step::Installation(bool, ..) => *bool, + _ => true, + } + } + + fn can_continue(&self) -> bool { + match self { + Step::End => false, + Step::Welcome(path) => is_aw_dir(path.clone()), + Step::Download(bool, downloads) => *bool && Self::can_download_continue(downloads), + Step::Installation(bool, ..) => *bool, + _ => true, + } + } + + fn view(&self) -> Element { + match self { + Step::Welcome(path) => Self::welcome(path), + Step::Selection(state) => Self::selection(state), + Step::Download(fetched, downloads) => Self::download(fetched, downloads), + Step::Installation(extracting, extracted, lang, clean) => { + Self::installation(extracting, extracted, lang.clone(), clean) + } + Step::End => Self::end(), + } + .into() + } + + fn container(title: &str) -> Column<'a, StepMessage> { + column![text(title).size(50)].spacing(20) + } + + fn welcome(path: &Path) -> Column<'a, StepMessage> { + let msg = Self::container("Welcome!") + .push( + "This is a simple utility to help you chose and install Armored Warfare mods to your client..", + ) + .push( + "It will guide you trough the different steps. Press \"next\" to continue", + ).push("Before continuing please verify that this is the correct path to your Armored Warfare installation"); + + let text_input = text_input( + "Path to AW directory", + path.to_str().unwrap(), + StepMessage::AWPathInputChanged, + ) + .padding(10); + + let btn_select_path = button_c("...").on_press(StepMessage::SelectAWPath); + + let path_input = row![text_input, btn_select_path].align_items(Alignment::Center); + let mut col = column![ + msg, + path_input, + text("*Select the exe file in 'bin64'").size(15) + ]; + if !is_aw_dir(path.to_path_buf()) { + col = col.push(text("Not an Armored Warfare directory")) + }; + + col.spacing(20) + } + + fn selection(state: &'a SelectionStruct) -> Column<'a, StepMessage> { + let mods = &state.mod_list; + let input = &state.input; + let filter = &state.filter; + + let title = Self::container("Selection").width(Length::Fill); + let mod_list = column( + mods.iter() + .enumerate() + .filter(|(_, m)| m.m.title.to_lowercase().contains(&input.to_lowercase())) + .map(|(i, x)| x.view(i)) + .collect(), + ); + let scroll = scrollable(mod_list); + + let input = text_input( + "Filter mods by name...", + input, + StepMessage::FilterInputChanged, + ) + .padding(15) + .size(30); + + let filter_butons = row(Tag::iter() + .map(|tag| { + let txt = text(&tag.to_string()).size(25); + button(txt) + .style(if tag == *filter { + theme::Button::Primary + } else { + theme::Button::Text + }) + .padding(5) + .on_press(StepMessage::ChangeFilter(tag)) + .into() + }) + .collect()); + + let filter_row = + row![input, filter_butons.width(Length::Shrink)].align_items(Alignment::Center); + + column![title, filter_row, scroll] + .spacing(20) + .padding(20) + .height(Length::Fill) + } + + fn download(fetched: &'a bool, downloads: &'a [DownloadBar]) -> Column<'a, StepMessage> { + let title = Self::container("Download"); + let downloads = if !downloads.is_empty() { + Column::with_children(downloads.iter().map(DownloadBar::view).collect()) + .spacing(20) + .align_items(Alignment::End) + } else { + column![ + vertical_space(Length::Units(30)), + text(if !*fetched { + "Fetching mod information" + } else { + "No mod selected to download" + }), + vertical_space(Length::Units(100)) + ] + }; + + column![title, downloads].padding(20) + } + + fn installation( + extracted: &bool, + mods: &'a [InstallCheckbox], + lang: String, + clean: &bool, + ) -> Column<'a, StepMessage> { + let mut content = Self::container("Installation"); + let pickup = pick_list(&*LANGUAGE_LIST, Some(lang), move |x| { + StepMessage::LangSelected(x) + }); + content = content.push( + row![text("Select your game language : "), pickup].align_items(Alignment::Center), + ); + let check = checkbox("", *clean, StepMessage::ToggleCleanInstall); + content = content.push( + row![text("Clean install (will delete installed mods) : "), check] + .align_items(Alignment::Center), + ); + if !*extracted { + content = content.push(text("extracting...")); + } else { + let mod_list = column(mods.iter().enumerate().map(|(i, x)| x.view(i)).collect()); + content = content.push(mod_list); + } + content + } + + fn end() -> Column<'a, StepMessage> { + Self::container("You reached the end!") + .push("The selected mods have now been installed. Enjoy!") + .push("You can go back and make changes if you want to.") + } +} + +fn button_c<'a, Message: Clone>(label: &str) -> Button<'a, Message> { + iced::widget::button(text(label).horizontal_alignment(Horizontal::Center)) + .padding(12) + .width(Length::Units(100)) +} diff --git a/src/ui/download.rs b/src/ui/download.rs new file mode 100755 index 0000000..1ccb455 --- /dev/null +++ b/src/ui/download.rs @@ -0,0 +1,108 @@ +use anyhow::Context; +use iced::subscription; +use std::hash::Hash; +use std::path::PathBuf; +use tokio::fs::File; +use tokio::io::AsyncWriteExt; + +// Just a little utility function +pub fn file( + id: I, + url: T, + path: PathBuf, +) -> iced::Subscription<(I, Progress)> { + subscription::unfold(id, State::Ready(url.to_string(), path), move |state| { + download(id, state) + }) +} + +#[derive(Debug, Hash, Clone)] +pub struct Download { + id: I, + url: String, +} + +async fn download(id: I, state: State) -> (Option<(I, Progress)>, State) { + match state { + State::Ready(url, path) => { + let response = reqwest::get(&url).await; + + match response { + Ok(response) => { + if let Some(total) = response.content_length() { + let file = File::create(&path) + .await + .context("Cloud not create file") + .unwrap(); + ( + Some((id, Progress::Started)), + State::Downloading { + response: Box::new(response), + total, + downloaded: 0, + file, + }, + ) + } else { + (Some((id, Progress::Errored)), State::Finished) + } + } + Err(_) => (Some((id, Progress::Errored)), State::Finished), + } + } + State::Downloading { + mut response, + total, + downloaded, + mut file, + } => match response.chunk().await { + Ok(Some(chunk)) => { + file.write_all(&chunk) + .await + .context("Could not write to file") + .unwrap(); + + let downloaded = downloaded + chunk.len() as u64; + + let percentage = (downloaded as f32 / total as f32) * 100.0; + + ( + Some((id, Progress::Advanced(percentage))), + State::Downloading { + response, + total, + downloaded, + file, + }, + ) + } + Ok(None) => (Some((id, Progress::Finished)), State::Finished), + Err(_) => (Some((id, Progress::Errored)), State::Finished), + }, + State::Finished => { + // We do not let the stream die, as it would start a + // new download repeatedly if the user is not careful + // in case of errors. + iced::futures::future::pending().await + } + } +} + +#[derive(Debug, Clone)] +pub enum Progress { + Started, + Advanced(f32), + Finished, + Errored, +} + +pub enum State { + Ready(String, PathBuf), + Downloading { + response: Box, + total: u64, + downloaded: u64, + file: File, + }, + Finished, +} diff --git a/src/ui/download_bar.rs b/src/ui/download_bar.rs new file mode 100755 index 0000000..4610dce --- /dev/null +++ b/src/ui/download_bar.rs @@ -0,0 +1,120 @@ +use crate::config::InstalledMod; +use crate::ui::app::StepMessage; +use crate::ui::download; +use iced::widget::{button, column, progress_bar, text, Column}; +use iced::{Alignment, Element, Subscription}; +use std::path::PathBuf; + +#[derive(Debug)] +pub struct DownloadBar { + pub id: usize, + pub state: State, + pub url: String, + pub path: PathBuf, + pub title: String, +} + +#[derive(Debug)] +pub enum State { + Idle, + Downloading { progress: f32 }, + Finished, + Errored, +} + +impl DownloadBar { + pub fn new(id: usize, url: String, path: PathBuf, title: String) -> Self { + DownloadBar { + id, + state: State::Idle, + url, + path, + title, + } + } + + pub fn from_installed(id: usize, installed: InstalledMod) -> Self { + DownloadBar { + id, + state: State::Finished, + url: "skip".to_string(), + path: installed.path, + title: installed.title, + } + } + + pub fn start(&mut self) { + match self.state { + State::Idle { .. } | State::Finished { .. } | State::Errored { .. } => { + self.state = State::Downloading { progress: 0.0 }; + } + _ => {} + } + } + + pub fn progress(&mut self, new_progress: download::Progress) { + if let State::Downloading { progress } = &mut self.state { + match new_progress { + download::Progress::Started => { + *progress = 0.0; + } + download::Progress::Advanced(percentage) => { + *progress = percentage; + } + download::Progress::Finished => { + self.state = State::Finished; + } + download::Progress::Errored => { + self.state = State::Errored; + } + } + } + } + + pub fn subscription(&self) -> Subscription { + match self.state { + State::Downloading { .. } => download::file(self.id, &self.url, self.path.to_owned()) + .map(StepMessage::DownloadProgressed), + _ => Subscription::none(), + } + } + + pub fn view(&self) -> Element { + let current_progress = match &self.state { + State::Idle { .. } => 0.0, + State::Downloading { progress } => *progress, + State::Finished { .. } => 100.0, + State::Errored { .. } => 0.0, + }; + + let progress_bar = progress_bar(0.0..=100.0, current_progress); + + let control: Element<_> = match &self.state { + State::Idle => text("Download starting...").into(), + State::Finished => text("Download finished!").into(), + State::Downloading { .. } => text(format!( + "Downloading {}... {:.2}%", + self.title, current_progress + )) + .into(), + State::Errored => column![ + text(format!( + "Something went wrong downloading {} :(", + self.title + )), + button("Try again").on_press(StepMessage::Download(self.id)), + ] + .spacing(10) + .align_items(Alignment::Center) + .into(), + }; + + Column::new() + .spacing(10) + .padding(10) + .align_items(Alignment::Center) + .push(progress_bar) + .push(control) + .into() + } +} diff --git a/src/ui/installcheckbox.rs b/src/ui/installcheckbox.rs new file mode 100755 index 0000000..8075c1c --- /dev/null +++ b/src/ui/installcheckbox.rs @@ -0,0 +1,164 @@ +use crate::config::InstalledMod; +use crate::extractor::ModArchive; +use crate::install::{crawl, FSElement, State}; +use crate::ui::app::StepMessage; +use iced::widget::{button, checkbox, column, horizontal_space, row, text}; +use iced::{Alignment, Element, Length}; +use std::path::{PathBuf, MAIN_SEPARATOR}; + +#[derive(Clone)] +pub struct InstallCheckbox { + pub title: String, + pub path: PathBuf, + pub file_list: FSElement, +} +impl From for InstallCheckbox { + fn from(m: ModArchive) -> Self { + let (_, file_list) = crawl(0, &m.path.with_extension("d")); + + Self { + title: m.title, + path: m.path, + file_list, + } + } +} + +impl From for InstallCheckbox { + fn from(m: InstalledMod) -> Self { + let (_, file_list) = crawl(0, &m.path.with_extension("d")); + + Self { + title: m.title, + path: m.path, + file_list, + } + } +} +impl InstallCheckbox { + pub fn view(&self, id: usize) -> Element { + if let FSElement::Dir(_, _, children, state) = &self.file_list { + view_dir(id, 0, &self.title, children, state) + } else { + column![].into() + } + } + + pub fn toggle_show(&mut self, id: usize) { + apply_to_elem(&mut self.file_list, id, |element| match element { + FSElement::Dir(_, _, _, state) | FSElement::File(_, _, state) => { + state.show_children = !state.show_children + } + }); + } + pub fn toggle_checked(&mut self, id: usize) { + apply_to_elem(&mut self.file_list, id, |x| { + let selected = match x { + FSElement::Dir(_, _, _, state) | FSElement::File(_, _, state) => !state.selected, + }; + toggle_recursive(x, selected) + }); + } +} + +fn view_dir<'a>( + id: usize, + space: u16, + name: &'a str, + children: &'a Vec, + state: &'a State, +) -> Element<'a, StepMessage> { + let expand = button(text("+").size(20)) + .on_press(StepMessage::InstallModShow(id, state.id)) + .padding(0); + + let mut name_ = name.to_string(); + let mut children_ = children; + while space != 0 && children_.len() == 1 && children_[0].is_dir() { + if let FSElement::Dir(new_name, _, new_children, _) = &children_[0] { + name_ = format!("{}{}{}", name_, MAIN_SEPARATOR, new_name); + children_ = new_children; + } + } + + let c = checkbox(name_, state.selected, move |_| { + StepMessage::InstallModChecked(id, state.id) + }); + let row = row![expand, c].align_items(Alignment::Center); + + let mut list = column!().padding(5); + if state.show_children { + for child in children_ { + list = list.push(view_children(id, space + 1, child)) + } + } + + column![row, list].into() +} + +fn view_children(id: usize, space: u16, elem: &FSElement) -> Element { + let card: Element = match elem { + FSElement::Dir(name, _, children, state) => view_dir(id, space, name, children, state), + FSElement::File(name, _, state) => checkbox(name, state.selected, move |_| { + StepMessage::InstallModChecked(id, state.id) + }) + .into(), + }; + let space = horizontal_space(Length::Units(space * 5)); + row![space, card].into() +} + +fn toggle_recursive(element: &mut FSElement, selected: bool) { + match element { + FSElement::Dir(_, _, children, state) => { + state.selected = selected; + for child in children { + toggle_recursive(child, selected); + } + } + FSElement::File(_, _, state) => { + state.selected = selected; + } + } +} + +fn apply_to_elem(element: &mut FSElement, id: usize, mut apply: F) -> bool +where + F: FnMut(&mut FSElement), +{ + match element { + FSElement::Dir(_, _, children, state) => { + if state.id == id { + apply(element); + true + } else { + for i in 0..children.len() { + if let Some(elem) = children.get(i + 1) { + if let FSElement::Dir(_, _, _, state) = elem { + if state.id > id { + return apply_to_elem(&mut children[i], id, apply); + } + } + } else { + return apply_to_elem(&mut children[i], id, apply); + } + if let FSElement::File(_, _, state) = &mut children[i] { + if state.id == id { + apply(&mut children[i]); + return true; + } + } + } + false + } + } + FSElement::File(_, _, state) => { + if state.id == id { + apply(element); + true + } else { + false + } + } + } +} diff --git a/src/ui/mod.rs b/src/ui/mod.rs new file mode 100755 index 0000000..1ba30a3 --- /dev/null +++ b/src/ui/mod.rs @@ -0,0 +1,6 @@ +pub mod app; +pub mod download; +mod download_bar; +mod installcheckbox; +mod modcheckbox; +mod util; diff --git a/src/ui/modcheckbox.rs b/src/ui/modcheckbox.rs new file mode 100755 index 0000000..21d07cb --- /dev/null +++ b/src/ui/modcheckbox.rs @@ -0,0 +1,57 @@ +use crate::mod_parser::Mod; +use crate::ui::app::StepMessage; +use iced::alignment::Horizontal; +use iced::widget::{button, checkbox, pick_list, row, text}; +use iced::{Alignment, Element, Length}; + +#[derive(Clone)] +pub struct ModCheckbox { + pub(crate) m: Mod, + pub(crate) selected: bool, + pub(crate) version: Option, +} + +impl ModCheckbox { + pub fn new(m: Mod, selected: bool, version: Option) -> Self { + Self { + m, + selected, + version, + } + } + pub fn get_download_url(&self) -> String { + match self.version { + Some(n) => self.m.downloads[n].clone(), + None => self.m.downloads[0].clone(), + } + } + pub fn view(&self, i: usize) -> Element { + let title = format!("{} by ", self.m.title); + let author = text(&self.m.author).size(24); + let checkbox = checkbox(title, self.selected, move |x| StepMessage::ModChecked(i, x)); + + let txt = text("open").horizontal_alignment(Horizontal::Center); + let ext_button = button(txt) + .padding(10) + .width(Length::Units(65)) + .on_press(StepMessage::OpenExt(self.m.url.clone())); + + let check_mod = if self.m.downloads.len() > 1 { + let list: Vec = (1..=self.m.downloads.len()).collect(); + + let pickup = pick_list(list, self.version.map(|n| n + 1), move |x| { + StepMessage::VersionSelected(i, x - 1) + }) + .placeholder("..."); + row![checkbox, author, pickup] + } else { + row![checkbox, author,] + } + .align_items(Alignment::Center) + .width(Length::Fill); + row![check_mod, ext_button] + .align_items(Alignment::Center) + .padding(5) + .into() + } +} diff --git a/src/ui/util.rs b/src/ui/util.rs new file mode 100755 index 0000000..afdc674 --- /dev/null +++ b/src/ui/util.rs @@ -0,0 +1,27 @@ +use log::error; +use std::thread; + +pub fn show_error_dialog(title: &str, content: &str) { + native_dialog::MessageDialog::new() + .set_type(native_dialog::MessageType::Error) + .set_title(title) + .set_text(content) + .show_alert() + .unwrap_or_default(); +} +pub fn show_question_dialog(title: &str, content: &str) -> bool { + native_dialog::MessageDialog::new() + .set_type(native_dialog::MessageType::Warning) + .set_title(title) + .set_text(content) + .show_confirm() + .unwrap_or_default() +} + +pub fn open_url(url: String) { + thread::spawn(|| { + if open::that(url).is_err() { + error!("Could not open external link") + }; + }); +} diff --git a/src/util.rs b/src/util.rs new file mode 100755 index 0000000..7c67064 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,147 @@ +use crate::util::Error::ReadCache; +use anyhow::Result; +use serde::Serialize; +use std::path::{Path, PathBuf}; +use thiserror::Error; +use tokio::fs; +use tokio::fs::File; +use tokio::io::AsyncReadExt; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Error reading cache dir")] + ReadCache, +} + +#[derive(Debug, Clone)] +pub enum LoadError { + File, + Format, +} + +pub(crate) fn get_app_cache_path() -> Result { + let mut path = dirs_next::cache_dir().ok_or(ReadCache)?; + path.push("aw-mod-installer"); + + if !path.exists() { + std::fs::create_dir_all(&path)?; + } + Ok(path) +} + +pub(crate) fn get_app_config_path() -> Result { + let mut path = dirs_next::config_dir().ok_or(ReadCache)?; + path.push("aw-mod-installer"); + + if !path.exists() { + std::fs::create_dir_all(&path)?; + } + path.push("config.json"); + + Ok(path) +} + +pub(crate) fn get_app_download_path() -> Result { + let mut path = dirs_next::download_dir().ok_or(ReadCache)?; + path.push("aw-mod-installer"); + + if !path.exists() { + std::fs::create_dir_all(&path)?; + } + Ok(path) +} +pub(crate) async fn write_to_json(val: &T, path: &Path) -> Result<()> +where + T: Serialize, +{ + let j = serde_json::to_string(val)?; + fs::write(path, &j).await?; + + Ok(()) +} + +pub(crate) async fn write_to_cache_json(val: &T, file_name: &str) -> Result<()> +where + T: Serialize, +{ + let mut file = get_app_cache_path()?; + file.push(format!("{file_name}.json")); + + write_to_json(val, &file).await +} + +pub(crate) async fn read_file(path: PathBuf) -> Result> { + let mut file = File::open(path).await?; + + let mut contents = vec![]; + file.read_to_end(&mut contents).await?; + Ok(contents) +} + +pub(crate) async fn read_cache_file(file_name: &str) -> Result> { + let mut path = get_app_cache_path()?; + path.push(file_name); + + read_file(path).await +} + +pub(crate) fn read_cache_file_sync(file_name: &str) -> Result> { + use std::io::Read; + let mut path = get_app_cache_path()?; + path.push(file_name); + + let mut file = std::fs::File::open(path)?; + + let mut contents = vec![]; + file.read_to_end(&mut contents)?; + Ok(contents) +} + +pub fn find_aw_path() -> PathBuf { + let launcher_dirs = vec!["MyGames", "MGLauncher"]; + let steam_path; + let root; + + if cfg!(windows) { + root = "C:\\"; + steam_path = format!( + "{root}Program Files (x86)\\Steam\\steamapps\\common\\Armored Warfare\\13_2000009" + ); + } else { + root = "/"; + let home = dirs_next::home_dir().unwrap(); + steam_path = format!( + "{}/.steam/steam/steamapps/common/Armored Warfare/13_2000009/", + home.to_str().unwrap() + ); + }; + + for ld in launcher_dirs { + let root_path = format!("{root}{ld}"); + let path = Path::new(&root_path); + if let Ok(p) = path.read_dir() { + for entry in p.flatten() { + if let Ok(t) = entry.file_type() { + if t.is_dir() && is_aw_dir(entry.path()) { + return entry.path(); + } + } + } + } + } + + let steam_path = PathBuf::from(&steam_path); + if steam_path.exists() && is_aw_dir(steam_path.clone()) { + return steam_path; + } + + PathBuf::new() +} + +pub fn is_aw_dir(path: PathBuf) -> bool { + let exe_path = ("bin64", "ArmoredWarfare.exe"); + let mut p = path; + p.push(exe_path.0); + p.push(exe_path.1); + p.exists() +}