diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39a63cc..da43dbb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,12 @@ -name: RueCi +name: ci -on: [push, pull_request] +on: + push: + branches: + - main + pull_request: + branches: + - main env: CARGO_TERM_COLOR: always @@ -20,8 +26,8 @@ jobs: - name: Install dependencies run: | - cargo install cargo-clippy - cargo install cargo-fmt + rustup component add clippy + rustup component add rustfmt - name: Format code run: | diff --git a/Cargo.lock b/Cargo.lock index 12bd3e4..1e14e35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,136 +3,52 @@ version = 3 [[package]] -name = "anyhow" -version = "1.0.69" +name = "addr2line" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" - - -[[package]] -name = "async-attributes" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "quote", - "syn", + "gimli", ] [[package]] -name = "async-channel" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.3.0" +name = "adler" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da5b41ee986eed3f524c380e6d64965aea573882a8907682ad100f7859305ca" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-lock", - "blocking", - "futures-lite", - "once_cell", -] +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] -name = "async-io" -version = "1.9.0" +name = "ahash" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83e21f3a490c72b3b0cf44962180e60045de2925d8dff97918f7ee43c8f637c7" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ - "autocfg", - "concurrent-queue", - "futures-lite", - "libc", - "log", + "cfg-if 1.0.0", "once_cell", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "winapi", + "version_check", + "zerocopy", ] [[package]] -name = "async-lock" -version = "2.5.0" +name = "aho-corasick" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ - "event-listener", + "memchr", ] [[package]] -name = "async-process" -version = "1.5.0" +name = "allocator-api2" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" -dependencies = [ - "async-io", - "autocfg", - "blocking", - "cfg-if 1.0.0", - "event-listener", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi", -] +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] -name = "async-std" -version = "1.12.0" +name = "anyhow" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" -dependencies = [ - "async-attributes", - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "async-stream" @@ -152,27 +68,30 @@ checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] -[[package]] -name = "async-task" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" - -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.0" @@ -186,18 +105,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "blocking" -version = "1.2.0" +name = "bitflags" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" -dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", -] +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bumpalo" @@ -217,12 +128,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" -[[package]] -name = "cache-padded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" - [[package]] name = "cassowary" version = "0.3.0" @@ -248,12 +153,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "concurrent-queue" -version = "1.2.4" +name = "color-eyre" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" dependencies = [ - "cache-padded", + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", ] [[package]] @@ -272,23 +195,13 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "crossbeam-utils" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" -dependencies = [ - "cfg-if 1.0.0", - "once_cell", -] - [[package]] name = "crossterm" -version = "0.23.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +checksum = "ab9f7409c70a38a56216480fba371ee460207dd8926ccf5b4160591759559170" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crossterm_winapi", "libc", "mio", @@ -300,11 +213,11 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.24.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab9f7409c70a38a56216480fba371ee460207dd8926ccf5b4160591759559170" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags", + "bitflags 2.4.2", "crossterm_winapi", "libc", "mio", @@ -316,21 +229,20 @@ dependencies = [ [[package]] name = "crossterm_winapi" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ "winapi", ] [[package]] -name = "ctor" -version = "0.1.23" +name = "directories" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ - "quote", - "syn", + "dirs-sys 0.4.1", ] [[package]] @@ -339,7 +251,7 @@ version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" dependencies = [ - "dirs-sys", + "dirs-sys 0.3.7", ] [[package]] @@ -353,6 +265,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dns-parser" version = "0.8.0" @@ -363,6 +287,12 @@ dependencies = [ "quick-error", ] +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -382,15 +312,19 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 1.0.98", "synstructure", ] [[package]] -name = "event-listener" -version = "2.5.3" +name = "eyre" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" +dependencies = [ + "indenter", + "once_cell", +] [[package]] name = "fastrand" @@ -480,21 +414,6 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-macro" version = "0.3.21" @@ -503,7 +422,7 @@ checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -548,16 +467,10 @@ dependencies = [ ] [[package]] -name = "gloo-timers" -version = "0.2.4" +name = "gimli" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" @@ -584,6 +497,22 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022" +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -675,6 +604,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "indexmap" version = "1.9.1" @@ -682,9 +617,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.2", ] +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" + [[package]] name = "instant" version = "0.1.12" @@ -700,6 +641,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.2" @@ -715,15 +665,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -732,9 +673,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "lock_api" @@ -753,7 +694,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", - "value-bag", +] + +[[package]] +name = "lru" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2c024b41519440580066ba82aab04092b333e09066a5eb86c7c4890df31f22" +dependencies = [ + "hashbrown 0.14.3", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", ] [[package]] @@ -764,11 +722,10 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mdns" -version = "3.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c769962ac75a6ea437f0922b27834bcccd4c013d591383a16ae5731e3ef0f3f3" +checksum = "7f027925e9ffffd302d46b5e9ca5ba084d56ea2282c527bb89fed1656e929287" dependencies = [ - "async-std", "async-stream", "dns-parser", "err-derive", @@ -776,6 +733,7 @@ dependencies = [ "futures-util", "log", "net2", + "tokio", ] [[package]] @@ -790,6 +748,15 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.4" @@ -799,7 +766,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -831,6 +798,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num_cpus" version = "1.13.1" @@ -841,11 +818,20 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.13.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" @@ -853,7 +839,7 @@ version = "0.10.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if 1.0.0", "foreign-types", "libc", @@ -870,7 +856,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -893,10 +879,22 @@ dependencies = [ ] [[package]] -name = "parking" -version = "2.0.0" +name = "option-ext" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking_lot" @@ -918,9 +916,15 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.36.1", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -945,20 +949,6 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" -[[package]] -name = "polling" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899b00b9c8ab553c743b3e11e87c5c7d423b2a2de229ba95b24a756344748011" -dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "libc", - "log", - "wepoll-ffi", - "winapi", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -968,7 +958,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.98", "version_check", ] @@ -985,9 +975,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -1000,20 +990,39 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.20" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] +[[package]] +name = "ratatui" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5659e52e4ba6e07b2dad9f1158f578ef84a73762625ddb51536019f34d180eb" +dependencies = [ + "bitflags 2.4.2", + "cassowary", + "crossterm 0.27.0", + "indoc", + "itertools", + "lru", + "paste", + "stability", + "strum", + "unicode-segmentation", + "unicode-width", +] + [[package]] name = "redox_syscall" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1027,6 +1036,50 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.3.7", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1078,19 +1131,31 @@ name = "rue" version = "0.1.0" dependencies = [ "anyhow", + "color-eyre", "crossterm 0.24.0", + "directories", "dirs", "futures", + "lazy_static", "log", "mdns", + "ratatui", "reqwest", "serde", "serde_json", "thiserror", "tokio", - "tui", + "tracing", + "tracing-error", + "tracing-subscriber", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustversion" version = "1.0.9" @@ -1110,7 +1175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -1125,7 +1190,7 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -1159,7 +1224,7 @@ checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -1185,11 +1250,20 @@ dependencies = [ "serde", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" dependencies = [ "libc", "signal-hook-registry", @@ -1237,6 +1311,38 @@ dependencies = [ "winapi", ] +[[package]] +name = "stability" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd1b177894da2a2d9120208c3386066af06a488255caabc5de8ddca22dbc3ce" +dependencies = [ + "quote", + "syn 1.0.98", +] + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + [[package]] name = "syn" version = "1.0.98" @@ -1248,6 +1354,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -1256,7 +1373,7 @@ checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", "unicode-xid", ] @@ -1291,7 +1408,17 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", ] [[package]] @@ -1337,7 +1464,7 @@ checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", ] [[package]] @@ -1372,43 +1499,81 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", ] [[package]] -name = "try-lock" -version = "0.2.3" +name = "tracing-error" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] [[package]] -name = "tui" -version = "0.18.0" +name = "tracing-log" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fe69244ec2af261bced1d9046a6fee6c8c2a6b0228e59e5ba39bc8ba4ed729" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "bitflags", - "cassowary", - "crossterm 0.23.2", - "unicode-segmentation", - "unicode-width", + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + [[package]] name = "unicode-bidi" version = "0.3.8" @@ -1432,9 +1597,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" @@ -1461,14 +1626,10 @@ dependencies = [ ] [[package]] -name = "value-bag" -version = "1.0.0-alpha.9" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" -dependencies = [ - "ctor", - "version_check", -] +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vcpkg" @@ -1482,12 +1643,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - [[package]] name = "want" version = "0.3.0" @@ -1525,7 +1680,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 1.0.98", "wasm-bindgen-shared", ] @@ -1559,7 +1714,7 @@ checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1580,15 +1735,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - [[package]] name = "winapi" version = "0.3.9" @@ -1617,43 +1763,109 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "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.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "winreg" version = "0.10.1" @@ -1662,3 +1874,23 @@ checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] diff --git a/Cargo.toml b/Cargo.toml index f8e0f01..934aa5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,10 +3,8 @@ name = "rue" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tui = "0.18" crossterm = "0.24" reqwest = {version = "0.11.8",features = ["json","blocking"]} tokio = { version = "1.20.4", features = ["full"] } @@ -16,7 +14,15 @@ serde_json = "1.0.59" futures = "0.3" dirs = "4.0.0" log = "0.4.17" -mdns = "3.0.0" -anyhow = "1.0.69" +# Currently downgraded due to https://github.com/dylanmckay/mdns/issues/26 +mdns = "2.0.2" +anyhow = "1.0.69" thiserror = "1.0.38" +ratatui = "0.25.0" +tracing-error = "0.2.0" +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +directories = "5.0.1" +lazy_static = "1.4.0" +color-eyre = "0.6.2" diff --git a/src/app/mod.rs b/src/app/mod.rs index c175a30..251ecf9 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,10 +1,10 @@ use crate::config::User; use crate::ui::TabsState; +#[derive(Clone)] pub struct App { pub user: Option, pub tabstate: TabsState, - pub bridge_discover_progress: u32, } impl App { @@ -17,9 +17,16 @@ impl App { App { user, tabstate: TabsState::new(), - bridge_discover_progress: 0, } } + // Reload user + pub fn update_user(&mut self) { + let user = match User::load() { + Ok(user) => Some(user), + Err(_) => None, + }; + self.user = user; + } pub fn authorized(&self) -> bool { self.user.is_some() } diff --git a/src/banner.rs b/src/banner.rs new file mode 100644 index 0000000..e674730 --- /dev/null +++ b/src/banner.rs @@ -0,0 +1,10 @@ +pub const BANNER: &str = r#" + /$$$$$$$ /$$ /$$ /$$$$$$$$ +| $$__ $$| $$ | $$| $$_____/ +| $$ \ $$| $$ | $$| $$ +| $$$$$$$/| $$ | $$| $$$$$ +| $$__ $$| $$ | $$| $$__/ +| $$ \ $$| $$ | $$| $$ +| $$ | $$| $$$$$$/| $$$$$$$$ +|__/ |__/ \______/ |________/ +"#; diff --git a/src/bridge.rs b/src/bridge.rs index 5c869cb..8263d2f 100644 --- a/src/bridge.rs +++ b/src/bridge.rs @@ -1,45 +1,59 @@ use crate::{config::User, errors::BridgeError}; use futures::{pin_mut, stream, StreamExt}; +//use mdns_sd::{ServiceDaemon, ServiceEvent}; use mdns::{Record, RecordKind}; -use reqwest::Client; +use reqwest::{Client, StatusCode}; use serde::Deserialize; use serde_json::Value; use std::collections::HashMap; -use std::{net::IpAddr, thread, time::Duration}; +use std::{ + net::IpAddr, + sync::{Arc, Mutex}, + time::Duration, +}; use tokio::sync::mpsc; -const MDNS_SERVICE_NAME: &str = "_hue._tcp.local"; +const MDNS_BRIDGE_SERVICE_NAME: &str = "_hue._tcp.local"; const DISCOVERY_URL: &str = "https://discovery.meethue.com/"; #[derive(Deserialize, Debug, Clone)] pub struct Bridge { - internal_ip_address: String, + #[serde(rename = "internalipaddress")] + internal_ip_address: IpAddr, } impl Bridge { + pub async fn discover_bridges() -> Result, BridgeError> { + match Bridge::mdns_discovery().await { + Ok(bridges) => Ok(bridges), + Err(_) => Bridge::nupnp_discovery().await, + } + } // find bridges using discovery url - pub async fn find_bridges() -> Result, BridgeError> { - let request: Vec = reqwest::get(DISCOVERY_URL).await?.json().await?; - Ok(request) + async fn nupnp_discovery() -> Result, BridgeError> { + let response = reqwest::get(DISCOVERY_URL).await?; + match response.status() { + StatusCode::OK => { + let bridges: Vec = response.json().await?; + Ok(bridges) + } + _ => Err(BridgeError::ResponseError(response.text().await?)), + } } /// Find bridges using mdns method /// https://developers.meethue.com/develop/application-design-guidance/hue-bridge-discovery/#mDNS - // FIXME: remove print later and refactor to_ip_addr(record: &Record) - pub async fn mdns_discovery() -> Result, mdns::Error> { - println!("Starting mdns search..."); - let stream = mdns::discover::all(MDNS_SERVICE_NAME, Duration::from_secs(10))?.listen(); + async fn mdns_discovery() -> Result, BridgeError> { + let stream = + mdns::discover::all(MDNS_BRIDGE_SERVICE_NAME, Duration::from_secs(5))?.listen(); pin_mut!(stream); let mut bridges: Vec = vec![]; - while let Some(Ok(response)) = stream.next().await { - let addr = response.records().find_map(Bridge::to_ip_addr); - + for response in (stream.next().await).into_iter().flatten() { + let addr = response.records().find_map(Self::to_ip_addr); if let Some(addr) = addr { - println!("Found bridge at {}", addr); bridges.push(Bridge { - internal_ip_address: addr.to_string(), + internal_ip_address: addr, }); - break; } else { - println!("Bridge does not advertise address"); + return Err(BridgeError::NoBridgesFound); } } Ok(bridges) @@ -53,52 +67,60 @@ impl Bridge { } // Send parallel requests to all bridges found - pub async fn create_user() -> Result<(), BridgeError> { - // Search bridges using mdns method if no result - // search using discovery endpoint - // - let bridges = match Bridge::mdns_discovery().await { - Ok(bridges) => bridges, - Err(_) => Bridge::find_bridges().await?, - }; - + pub async fn create_user( + bridges: Vec, + loader_progress: Arc>, + ) -> Result<(), BridgeError> { // Poll bridge for minute - for _ in 1..25 { + for _ in 0..25 { let (tx, mut rx) = mpsc::channel(4); let requests = stream::iter(bridges.clone()) .map(|bridge| { tokio::spawn(async move { - Bridge::authorize_user_request(&bridge.internal_ip_address).await + Bridge::authorize_user_request(bridge.internal_ip_address).await }) }) .buffer_unordered(bridges.len()); + // Use channel to because we cant break main loop from this scope + // FIXME: Maybe there is better way to do this for now leave it as is requests .for_each(|b| async { match b { - Ok(Ok(b)) => { - let _ = tx.send(b).await; + Ok(resp) => { + let _ = tx.send(resp).await; + } + Err(e) => { + let _ = tx + .send(Err(BridgeError::InternalError(e.to_string()))) + .await; } - // FIXME: Shouldn't print to std - Ok(Err(e)) => println!("Got a reqwest::Error: {:?}", e), - Err(e) => println!("Error: {}", e), } }) .await; - if let Some(user) = rx.recv().await { - user.save() - .await - .map_err(|e| BridgeError::SaveUser(e.to_string()))?; - break; + if let Some(resp) = rx.recv().await { + match resp { + Ok(user) => { + user.save() + .await + .map_err(|e| BridgeError::SaveUser(e.to_string()))?; + break; + } + Err(BridgeError::ButtonNotPressed) => (), + Err(_) => (), + } }; - thread::sleep(Duration::from_secs(5)); + let mut loader = loader_progress.lock().unwrap(); + *loader += 4; + + std::thread::sleep(Duration::from_secs(5)); } Ok(()) } /// Send request to bridge to get User - pub async fn authorize_user_request(ip: &str) -> Result { + pub async fn authorize_user_request(ip: IpAddr) -> Result { let address = format!("http://{}/api", ip); let client = Client::new(); let mut body = HashMap::new(); @@ -113,16 +135,25 @@ impl Bridge { .text() .await .map_err(|e| BridgeError::ResponseError(e.to_string()))?; - let value: Value = serde_json::from_str(&data).unwrap(); + let value: Value = + serde_json::from_str(&data).map_err(|e| BridgeError::InternalError(e.to_string()))?; + // FIXME: Add better response parsing + // + println!("{:?}", value); match value[0].get("success") { Some(message) => { - let username: String = serde_json::from_value(message.to_owned()).unwrap(); - let user = User { - username, - bridge_address: ip.into(), - }; - Ok(user) + let user: HashMap = serde_json::from_value(message.to_owned()) + .map_err(|e| BridgeError::InternalError(e.to_string()))?; + if let Some(username) = user.get("username") { + let user = User { + username: username.to_owned(), + bridge_address: ip, + }; + Ok(user) + } else { + Err(BridgeError::ResponseError("Can't decode username".into())) + } } None => Err(BridgeError::ButtonNotPressed), } diff --git a/src/config.rs b/src/config.rs index 6ba5893..668b538 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,16 +3,17 @@ use serde::{Deserialize, Serialize}; use std::{ fs, io::{BufReader, Write}, + net::IpAddr, path::{Path, PathBuf}, }; const CONFIG_DIR: &str = ".config/rue"; -const CONFIG_NAME: &str = "rue.json"; +const CONFIG_NAME: &str = "rue.conf"; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct User { pub username: String, - pub bridge_address: String, + pub bridge_address: IpAddr, } impl User { diff --git a/src/errors.rs b/src/errors.rs index 713c976..c35933d 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -26,6 +26,10 @@ pub enum BridgeError { ResponseError(String), #[error("Save user error")] SaveUser(String), + #[error("Internal error")] + InternalError(String), + #[error("Mdns error")] + MdnsError(String), } impl From for BridgeError { @@ -33,4 +37,8 @@ impl From for BridgeError { BridgeError::RequestError(error.to_string()) } } - +impl From for BridgeError { + fn from(error: mdns::Error) -> Self { + BridgeError::RequestError(error.to_string()) + } +} diff --git a/src/main.rs b/src/main.rs index b4e59d2..1934253 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,12 @@ +use anyhow::Result; use app::App; -use std::sync::{Arc, Mutex}; +use banner::BANNER; +use bridge::Bridge; +use std::io; +use std::sync::Arc; pub mod app; +pub mod banner; pub mod bridge; pub mod config; pub mod errors; @@ -11,7 +16,18 @@ pub mod lights; pub mod ui; #[tokio::main] -async fn main() { - let app = Arc::new(Mutex::new(App::new())); - ui::start_ui(&app).await.unwrap(); +async fn main() -> Result<()> { + let app = Arc::new(tokio::sync::Mutex::new(App::new())); + println!("{}", BANNER); + println!("Looking for bridges.."); + let bridges = Bridge::discover_bridges().await?; + println!( + "Found {} bridges do you want to authorize? y/n", + &bridges.len() + ); + let mut user_input = String::new(); + let stdin = io::stdin(); + stdin.read_line(&mut user_input)?; + ui::start_ui(&app, bridges).await?; + Ok(()) } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index e2a78d1..ab4b34e 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -1,23 +1,30 @@ -use crate::App; - -use crate::event::{events, key::Key}; +use crate::{ + banner::BANNER, + bridge::Bridge, + event::{events, key::Key}, + App, +}; use anyhow::Result; -use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; -use std::{io, time::Duration}; -use tui::{ - backend::CrosstermBackend, - layout::{Alignment, Constraint, Direction, Layout}, - style::{Color, Modifier, Style}, - symbols, - text::{Span, Spans}, - widgets::{Block, Borders, LineGauge, Paragraph, Tabs}, - Terminal, +use color_eyre::owo_colors::OwoColorize; +use crossterm::{ + event::DisableMouseCapture, + execute, + style::Colors, + terminal::{disable_raw_mode, enable_raw_mode, LeaveAlternateScreen}, }; +use ratatui::{ + layout::{Constraint, Direction, Layout}, + prelude::{CrosstermBackend, Terminal}, + text::Span, + widgets::{Block, Borders, Gauge, Paragraph}, +}; +use std::{io, time::Duration}; use std::sync::{Arc, Mutex}; +#[derive(Clone)] pub struct TabsState { - pub titles: Vec, + pub pages: Vec, pub index: usize, } @@ -25,20 +32,20 @@ pub struct TabsState { impl TabsState { pub fn new() -> Self { TabsState { - titles: vec!["Rooms".into(), "Lights".into(), "Groups".into()], + pages: vec!["Rooms".into(), "Lights".into(), "Groups".into()], index: 0, } } pub fn next(&mut self) { - self.index = (self.index + 1) % self.titles.len(); + self.index = (self.index + 1) % self.pages.len(); } pub fn previous(&mut self) { if self.index > 0 { self.index -= 1; } else { - self.index = self.titles.len() - 1; + self.index = self.pages.len() - 1; } } } @@ -49,30 +56,8 @@ impl Default for TabsState { } } -pub fn draw_tabs(app: &App) -> Tabs { - let tabs = app - .tabstate - .titles - .iter() - .map(|t| { - Spans::from(vec![Span::styled( - t, - Style::default() - .fg(Color::Yellow) - .add_modifier(Modifier::UNDERLINED), - )]) - }) - .collect(); - Tabs::new(tabs) - .block(Block::default().borders(Borders::ALL).title("Menu")) - .select(app.tabstate.index) - .style(Style::default().fg(Color::Cyan)) - .highlight_style( - Style::default() - .fg(Color::LightGreen) - .add_modifier(Modifier::BOLD) - .bg(Color::Black), - ) +pub fn draw_tabs<'a>(app: &'a App) { + todo!() } /// TODO: Draw groups page @@ -96,61 +81,60 @@ pub fn draw_help() -> Result<(), io::Error> { /// Draw app title and version fn draw_title<'a>() -> Paragraph<'a> { - Paragraph::new("Rue") - .style(Style::default().fg(Color::Red).add_modifier(Modifier::BOLD)) - .alignment(Alignment::Center) - .block(Block::default().borders(Borders::NONE)) + todo!() } -pub fn draw_discovery_screen<'a>(counter: u64) -> LineGauge<'a> { - let sec = Duration::from_secs(counter).as_secs(); - let ratio = sec as f64 / 100.0; - LineGauge::default() - .block( - Block::default() - .borders(Borders::ALL) - .title("Looking for bridges"), - ) - .gauge_style( - Style::default() - .fg(Color::Cyan) - .bg(Color::Black) - .add_modifier(Modifier::BOLD), - ) - .line_set(symbols::line::THICK) - .ratio(ratio) +pub fn draw_discovery_screen<'a>(counter: u64) { + todo!() } -pub async fn start_ui(app: &Arc>) -> Result<()> { - let stdout = io::stdout(); - let backend = CrosstermBackend::new(stdout); +pub async fn start_register_user_ui(_app: &Arc>) -> Result<()> { + todo!() +} - enable_raw_mode()?; - let mut terminal = Terminal::new(backend)?; - terminal.clear()?; - let app_state = app.lock().unwrap(); +fn exit() -> Result<()> { + crossterm::execute!(std::io::stderr(), crossterm::terminal::LeaveAlternateScreen)?; + crossterm::terminal::disable_raw_mode()?; + Ok(()) +} + +pub async fn start_ui(app: &Arc>, bridges: Vec) -> Result<()> { + crossterm::terminal::enable_raw_mode()?; + crossterm::execute!(std::io::stderr(), crossterm::terminal::EnterAlternateScreen)?; + let mut terminal = Terminal::new(CrosstermBackend::new(std::io::stderr()))?; + + let mut app_state = app.lock().await; let events = events::EventsHandler::new(Duration::from_millis(500)); + let loader_progress = Arc::new(Mutex::new(0)); - loop { - let tabs = draw_tabs(&app_state); + let counter = Arc::clone(&loader_progress); + if app_state.user.is_none() { + tokio::spawn(async move { Bridge::create_user(bridges, counter).await }); + } + loop { + let loader_progress = Arc::clone(&loader_progress); terminal.draw(|f| { - let title = draw_title(); - let size = f.size(); - let chunks = Layout::default() + let gauge = Gauge::default() + .block(Block::default().title("Progress").borders(Borders::ALL)) + .gauge_style(ratatui::style::Style::default()) + .ratio(*loader_progress.lock().unwrap() as f64 / 10 as f64); + let row4 = Layout::default() .direction(Direction::Vertical) - .margin(3) - .constraints([Constraint::Length(3), Constraint::Min(0)].as_ref()) - .split(size); - f.render_widget(title, chunks[0]); - - if app_state.user.is_none() { - let progress = draw_discovery_screen(1); - f.render_widget(progress, chunks[0]); - } else { - f.render_widget(tabs, chunks[1]); - } + .constraints( + [ + Constraint::Length(3), + Constraint::Length(8), + Constraint::Length(0 as u16 + 2), + Constraint::Percentage(40), + ] + .as_ref(), + ) + .split(f.size()); + + f.render_widget(gauge, row4[0]); })?; + app_state.update_user(); match events.next()? { events::IoEvent::Input(key) => { if key == Key::Char('q') { @@ -159,15 +143,12 @@ pub async fn start_ui(app: &Arc>) -> Result<()> { todo!(); } } - events::IoEvent::Tick => { app_state.update_on_tick(); } } } - // restore terminal - disable_raw_mode()?; - terminal.clear()?; - terminal.show_cursor()?; + //restore terminal + exit()?; Ok(()) }