From ff96c3c358e066cd0cad731425b216e93d1d23c9 Mon Sep 17 00:00:00 2001 From: DongHyun Kim Date: Wed, 24 Jan 2024 03:33:41 +0900 Subject: [PATCH] Apply Rinf version 6 --- .github/workflows/release.yml | 30 -- Cargo.lock | 339 +++++++++++++++--- README.md | 6 +- lib/main.dart | 4 +- .../providers/crop_borders_provider.dart | 31 +- lib/services/boa_js.dart | 33 +- messages/README.md | 3 + messages/boa_js.proto | 13 +- messages/crop_borders.proto | 8 +- native/hub/Cargo.toml | 9 +- native/hub/src/boa_js.rs | 40 +-- native/hub/src/bridge/generated.io.rs | 174 --------- native/hub/src/bridge/generated.rs | 245 ------------- native/hub/src/bridge/generated.web.rs | 122 ------- native/hub/src/bridge/interface.rs | 270 ++------------ native/hub/src/bridge/interface_os.rs | 119 ++++++ native/hub/src/bridge/interface_web.rs | 64 ++++ native/hub/src/bridge/mod.rs | 91 +---- native/hub/src/imagecrop.rs | 35 +- native/hub/src/lib.rs | 15 +- native/hub/src/with_request.rs | 32 -- pubspec.lock | 8 +- pubspec.yaml | 2 +- 23 files changed, 608 insertions(+), 1085 deletions(-) create mode 100644 messages/README.md delete mode 100644 native/hub/src/bridge/generated.io.rs delete mode 100644 native/hub/src/bridge/generated.rs delete mode 100644 native/hub/src/bridge/generated.web.rs create mode 100644 native/hub/src/bridge/interface_os.rs create mode 100644 native/hub/src/bridge/interface_web.rs delete mode 100644 native/hub/src/with_request.rs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 35603aac..25cd2598 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,11 +27,6 @@ jobs: - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable - - - name: Setup Protobuf compiler - uses: arduino/setup-protoc@v2 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Java toolchain (Only Android target) uses: actions/setup-java@v3 @@ -92,11 +87,6 @@ jobs: - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable - - name: Setup Protobuf compiler - uses: arduino/setup-protoc@v2 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Install the CLI tool run: cargo install rinf @@ -147,11 +137,6 @@ jobs: - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable - - name: Setup Protobuf compiler - uses: arduino/setup-protoc@v2 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Install the CLI tool run: cargo install rinf @@ -201,11 +186,6 @@ jobs: # - name: Setup Rust toolchain # uses: dtolnay/rust-toolchain@stable - # - name: Setup Protobuf compiler - # uses: arduino/setup-protoc@v2 - # with: - # repo-token: ${{ secrets.GITHUB_TOKEN }} - # - name: Install the CLI tool # run: cargo install rinf @@ -261,11 +241,6 @@ jobs: - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable - - name: Setup Protobuf compiler - uses: arduino/setup-protoc@v2 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Install the CLI tool run: cargo install rinf @@ -317,11 +292,6 @@ jobs: - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable - - name: Setup Protobuf compiler - uses: arduino/setup-protoc@v2 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - - name: Install the CLI tool run: cargo install rinf diff --git a/Cargo.lock b/Cargo.lock index 2e13a141..8aef85dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ dependencies = [ [[package]] name = "allo-isolate" -version = "0.1.20" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56b7997817c178b853573e8bdfb6c3afe02810b43f17d766d6703560074b0c3" +checksum = "f2f5a5fd28223e6f3cafb7d9cd685f51eafdd71d33ca1229f8316925d5957240" dependencies = [ "atomic", ] @@ -95,6 +95,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "bit_field" version = "0.10.2" @@ -299,7 +305,7 @@ dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -374,15 +380,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "dart-sys" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d8b5680b5c2cc52f50acb2457d9b3a3b58adcca785db13a0e3655626f601de6" -dependencies = [ - "cc", -] - [[package]] name = "dashmap" version = "5.5.3" @@ -475,6 +472,15 @@ dependencies = [ "spin", ] +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -547,10 +553,20 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "hub" version = "0.1.0" dependencies = [ + "allo-isolate", "boa_engine", "image", "prost", @@ -698,6 +714,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "image" version = "0.24.7" @@ -753,19 +779,13 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "lebe" version = "0.5.2" @@ -833,7 +853,7 @@ checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -958,9 +978,15 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "phf" version = "0.11.2" @@ -1066,9 +1092,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fdd22f3b9c31b53c060df4a0613a1c7f062d4115a2b984dd15b1858f7e340d" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" dependencies = [ "bytes", "prost-derive", @@ -1076,9 +1102,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", "itertools", @@ -1087,6 +1113,16 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "protoc-prebuilt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37aee930fb53074ec083bf049aa6133bb1a93cce8fc39f83e07f36a0937304dd" +dependencies = [ + "ureq", + "zip", +] + [[package]] name = "qoi" version = "0.4.1" @@ -1176,20 +1212,29 @@ dependencies = [ [[package]] name = "rinf" -version = "4.16.3" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d805a4a3ba0e2564baa19a9360d2b334c3a7b016e434512ece130ce74d4ca76c" +checksum = "394a11182639141467cd388456a9fcb091ea0db5cfb3e8297eda242dfaa23860" dependencies = [ - "allo-isolate", "backtrace", - "bytemuck", - "dart-sys", + "home", "js-sys", - "lazy_static", - "libc", "os-thread-local", - "wasm-bindgen", - "web-sys", + "protoc-prebuilt", +] + +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.48.0", ] [[package]] @@ -1204,6 +1249,28 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.16" @@ -1222,6 +1289,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "serde" version = "1.0.193" @@ -1287,7 +1364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1405,6 +1482,21 @@ dependencies = [ "zerovec", ] +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.33.0" @@ -1421,7 +1513,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1437,9 +1529,9 @@ dependencies = [ [[package]] name = "tokio_with_wasm" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22578519b09a4fd0f3e55e1b4fdf337fe0b8ce53c6a853009f37bee1b0b7127c" +checksum = "9e3e506fe942e7be6a129f928f263d4bf5d9c8c7104c885574aedb5c6138a164" dependencies = [ "futures-channel", "js-sys", @@ -1466,18 +1558,65 @@ dependencies = [ "winnow", ] +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[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-xid" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" +dependencies = [ + "base64", + "log", + "once_cell", + "rustls", + "rustls-webpki", + "url", + "webpki-roots", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "utf16_iter" version = "1.0.5" @@ -1504,9 +1643,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1514,9 +1653,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", @@ -1541,9 +1680,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1551,9 +1690,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", @@ -1564,9 +1703,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "web-sys" @@ -1578,6 +1717,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" + [[package]] name = "weezl" version = "0.1.7" @@ -1612,7 +1757,7 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -1621,7 +1766,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1630,13 +1784,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -1645,42 +1814,84 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.5.30" @@ -1790,6 +2001,18 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", +] + [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/README.md b/README.md index 0b4efb2e..6bef2031 100644 --- a/README.md +++ b/README.md @@ -47,16 +47,14 @@ Get the app from our [releases page](https://github.com/kodjodevf/mangayomi/rele This project use Rust for the [auto-image-cropper](https://github.com/ritiek/auto-image-cropper) crate and [boa](https://github.com/boa-dev/boa) crate utilizing the capabilities of the [Rinf](https://pub.dev/packages/rinf) framework. To run and build this app, you need to have -[Flutter SDK](https://docs.flutter.dev/get-started/install), -[Rust toolchain](https://www.rust-lang.org/tools/install), -and [Protobuf compiler](https://grpc.io/docs/protoc-installation) +[Flutter SDK](https://docs.flutter.dev/get-started/install) +and [Rust toolchain](https://www.rust-lang.org/tools/install) installed on your system. You can check that your system is ready with the commands below. Note that all the Flutter subcomponents should be installed. ```bash rustc --version -protoc --version flutter doctor ``` diff --git a/lib/main.dart b/lib/main.dart index ac8c856c..7b9619d3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,7 +17,7 @@ import 'package:mangayomi/modules/more/settings/appearance/providers/pure_black_ import 'package:mangayomi/modules/more/settings/appearance/providers/theme_mode_state_provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:media_kit/media_kit.dart'; -import 'package:rinf/rinf.dart'; +import 'package:mangayomi/messages/generated.dart'; import 'package:window_manager/window_manager.dart'; // Global instance of the Isar database. @@ -35,7 +35,7 @@ class MyHttpoverrides extends HttpOverrides { /// Entry point of the application. void main(List args) async { - await Rinf.ensureInitialized(); + await Rinf.initialize(); // Override the default HTTP client. HttpOverrides.global = MyHttpoverrides(); // If running on desktop platforms and web view title bar widget is active, exit. diff --git a/lib/modules/manga/reader/providers/crop_borders_provider.dart b/lib/modules/manga/reader/providers/crop_borders_provider.dart index 7ab7d8a4..739288af 100644 --- a/lib/modules/manga/reader/providers/crop_borders_provider.dart +++ b/lib/modules/manga/reader/providers/crop_borders_provider.dart @@ -1,13 +1,15 @@ +import 'dart:async'; import 'dart:io'; import 'package:extended_image/extended_image.dart'; import 'package:flutter/foundation.dart'; -import 'package:mangayomi/messages/crop_borders.pb.dart' as crop_borders; +import 'package:mangayomi/messages/crop_borders.pb.dart'; import 'package:mangayomi/modules/manga/reader/reader_view.dart'; import 'package:mangayomi/utils/reg_exp_matcher.dart'; -import 'package:rinf/rinf.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'crop_borders_provider.g.dart'; +int currentId = 0; + @Riverpod(keepAlive: true) Future cropBorders(CropBordersRef ref, {required UChapDataPreload datas, required bool cropBorder}) async { @@ -29,15 +31,22 @@ Future cropBorders(CropBordersRef ref, if (imageBytes == null) { return null; } - final requestMessage = crop_borders.ReadRequest( - image: imageBytes, - ); - final rustRequest = RustRequest( - resource: crop_borders.ID, - operation: RustOperation.Read, - message: requestMessage.writeToBuffer()); - final rustResponse = await requestToRust(rustRequest); - return rustResponse.blob; + + final completer = Completer(); + CropBordersInput( + interactionId: currentId, + ).sendSignalToRust(imageBytes); + final stream = CropBordersOutput.rustSignalStream; + final subscription = stream.listen((rustSignal) { + if (rustSignal.message.interactionId == currentId) { + completer.complete(rustSignal.blob!); + } + }); + final image = await completer.future; + subscription.cancel(); + currentId++; + + return image; } return null; } diff --git a/lib/services/boa_js.dart b/lib/services/boa_js.dart index 02f7ebf4..ad9be5f0 100644 --- a/lib/services/boa_js.dart +++ b/lib/services/boa_js.dart @@ -1,18 +1,23 @@ import 'package:mangayomi/messages/boa_js.pb.dart'; -import 'package:rinf/rinf.dart'; +import 'dart:async'; + +int currentId = 0; Future evalJs(String script) async { - final requestMessage = ReadRequest(codeScript: script); - final rustRequest = RustRequest( - resource: ID, - operation: RustOperation.Read, - message: requestMessage.writeToBuffer()); - final rustResponse = await requestToRust(rustRequest); - if (rustResponse.successful) { - final responseMessage = ReadResponse.fromBuffer( - rustResponse.message!, - ); - return responseMessage.response; - } - return ""; + final completer = Completer(); + BoaInput( + interactionId: currentId, + codeScript: script, + ).sendSignalToRust(null); + final stream = BoaOutput.rustSignalStream; + final subscription = stream.listen((rustSignal) { + if (rustSignal.message.interactionId == currentId) { + completer.complete(rustSignal.message.response); + } + }); + final response = await completer.future; + subscription.cancel(); + currentId++; + + return response; } diff --git a/messages/README.md b/messages/README.md new file mode 100644 index 00000000..85c54229 --- /dev/null +++ b/messages/README.md @@ -0,0 +1,3 @@ +# Protobuf Messages + +This folder contains Protobuf message files that serve as an API between Dart and Rust. `.proto` files can be compiled into Dart and Rust code with the command `rinf message`, provided by the [Rinf](https://rinf.cunarist.com) framework. diff --git a/messages/boa_js.proto b/messages/boa_js.proto index 071cdca1..4255cca2 100644 --- a/messages/boa_js.proto +++ b/messages/boa_js.proto @@ -1,9 +1,14 @@ syntax = "proto3"; package boa_js; -message ReadRequest { - string code_script = 1; +// [RINF:DART-SIGNAL] +message BoaInput { + int32 interaction_id = 1; + string code_script = 2; } -message ReadResponse { - string response = 1; + +// [RINF:RUST-SIGNAL] +message BoaOutput { + int32 interaction_id = 1; + string response = 2; } diff --git a/messages/crop_borders.proto b/messages/crop_borders.proto index 10cd8451..f93b85be 100644 --- a/messages/crop_borders.proto +++ b/messages/crop_borders.proto @@ -1,6 +1,8 @@ syntax = "proto3"; package crop_borders; -message ReadRequest { - bytes image = 1; -} +// [RINF:DART-SIGNAL] +message CropBordersInput { int32 interaction_id = 1; } + +// [RINF:RUST-SIGNAL] +message CropBordersOutput { int32 interaction_id = 1; } diff --git a/native/hub/Cargo.toml b/native/hub/Cargo.toml index 85f72402..ca46285c 100644 --- a/native/hub/Cargo.toml +++ b/native/hub/Cargo.toml @@ -12,9 +12,10 @@ edition = "2021" crate-type = ["lib", "cdylib", "staticlib"] [dependencies] -rinf = "4.16.3" -tokio_with_wasm = "0.3.2" -wasm-bindgen = "0.2.87" -prost = "0.12.0" +rinf = "6.0.1" +allo-isolate = "0.1.24" +wasm-bindgen = "0.2.90" +prost = "0.12.3" +tokio_with_wasm = "0.4.0" image = "0.24.7" boa_engine = "0.17.3" diff --git a/native/hub/src/boa_js.rs b/native/hub/src/boa_js.rs index 1fccb6d2..50eeafb5 100644 --- a/native/hub/src/boa_js.rs +++ b/native/hub/src/boa_js.rs @@ -1,32 +1,20 @@ -use crate::bridge::{RustOperation, RustRequest, RustResponse}; +use crate::messages; use boa_engine::{Context, Source}; -use prost::Message; -pub async fn eval_js(rust_request: RustRequest) -> RustResponse { - use crate::messages::boa_js::{ReadRequest, ReadResponse}; +pub async fn eval_js() { + use messages::boa_js::*; - match rust_request.operation { - RustOperation::Create => RustResponse::default(), - RustOperation::Read => { - let mut context = Context::default(); - - let code_script = rust_request.message.unwrap(); - let request_message = ReadRequest::decode(code_script.as_slice()).unwrap(); - let response_message = ReadResponse { - response: match context - .eval(Source::from_bytes(request_message.code_script.as_bytes())) - { - Ok(res) => res.to_string(&mut context).unwrap().to_std_string_escaped(), - Err(_e) => "error".to_string(), - }, - }; - RustResponse { - successful: true, - message: Some(response_message.encode_to_vec()), - blob: None, - } + let mut receiver = BoaInput::get_dart_signal_receiver(); + while let Some(dart_signal) = receiver.recv().await { + let mut context = Context::default(); + let code_script = dart_signal.message.code_script; + BoaOutput { + interaction_id: dart_signal.message.interaction_id, + response: match context.eval(Source::from_bytes(code_script.as_bytes())) { + Ok(res) => res.to_string(&mut context).unwrap().to_std_string_escaped(), + Err(_e) => "error".to_string(), + }, } - RustOperation::Delete => RustResponse::default(), - RustOperation::Update => RustResponse::default(), + .send_signal_to_dart(None); } } diff --git a/native/hub/src/bridge/generated.io.rs b/native/hub/src/bridge/generated.io.rs deleted file mode 100644 index 7a8e7921..00000000 --- a/native/hub/src/bridge/generated.io.rs +++ /dev/null @@ -1,174 +0,0 @@ -use super::*; -// Section: wire functions - -#[no_mangle] -pub extern "C" fn wire_prepare_rust_signal_stream(port_: i64) { - wire_prepare_rust_signal_stream_impl(port_) -} - -#[no_mangle] -pub extern "C" fn wire_prepare_rust_response_stream(port_: i64) { - wire_prepare_rust_response_stream_impl(port_) -} - -#[no_mangle] -pub extern "C" fn wire_prepare_rust_report_stream(port_: i64) { - wire_prepare_rust_report_stream_impl(port_) -} - -#[no_mangle] -pub extern "C" fn wire_prepare_channels(port_: i64) { - wire_prepare_channels_impl(port_) -} - -#[no_mangle] -pub extern "C" fn wire_check_rust_streams(port_: i64) { - wire_check_rust_streams_impl(port_) -} - -#[no_mangle] -pub extern "C" fn wire_start_rust_logic(port_: i64) { - wire_start_rust_logic_impl(port_) -} - -#[no_mangle] -pub extern "C" fn wire_stop_rust_logic(port_: i64) { - wire_stop_rust_logic_impl(port_) -} - -#[no_mangle] -pub extern "C" fn wire_request_to_rust(port_: i64, request_unique: *mut wire_RustRequestUnique) { - wire_request_to_rust_impl(port_, request_unique) -} - -// Section: allocate functions - -#[no_mangle] -pub extern "C" fn new_box_autoadd_rust_request_unique_0() -> *mut wire_RustRequestUnique { - support::new_leak_box_ptr(wire_RustRequestUnique::new_with_null_ptr()) -} - -#[no_mangle] -pub extern "C" fn new_uint_8_list_0(len: i32) -> *mut wire_uint_8_list { - let ans = wire_uint_8_list { - ptr: support::new_leak_vec_ptr(Default::default(), len), - len, - }; - support::new_leak_box_ptr(ans) -} - -// Section: related functions - -// Section: impl Wire2Api - -impl Wire2Api for *mut wire_RustRequestUnique { - fn wire2api(self) -> RustRequestUnique { - let wrap = unsafe { support::box_from_leak_ptr(self) }; - Wire2Api::::wire2api(*wrap).into() - } -} - -impl Wire2Api for wire_RustRequest { - fn wire2api(self) -> RustRequest { - RustRequest { - resource: self.resource.wire2api(), - operation: self.operation.wire2api(), - message: self.message.wire2api(), - blob: self.blob.wire2api(), - } - } -} -impl Wire2Api for wire_RustRequestUnique { - fn wire2api(self) -> RustRequestUnique { - RustRequestUnique { - id: self.id.wire2api(), - request: self.request.wire2api(), - } - } -} - -impl Wire2Api> for *mut wire_uint_8_list { - fn wire2api(self) -> Vec { - unsafe { - let wrap = support::box_from_leak_ptr(self); - support::vec_from_leak_ptr(wrap.ptr, wrap.len) - } - } -} -// Section: wire structs - -#[repr(C)] -#[derive(Clone)] -pub struct wire_RustRequest { - resource: i32, - operation: i32, - message: *mut wire_uint_8_list, - blob: *mut wire_uint_8_list, -} - -#[repr(C)] -#[derive(Clone)] -pub struct wire_RustRequestUnique { - id: i32, - request: wire_RustRequest, -} - -#[repr(C)] -#[derive(Clone)] -pub struct wire_uint_8_list { - ptr: *mut u8, - len: i32, -} - -// Section: impl NewWithNullPtr - -pub trait NewWithNullPtr { - fn new_with_null_ptr() -> Self; -} - -impl NewWithNullPtr for *mut T { - fn new_with_null_ptr() -> Self { - std::ptr::null_mut() - } -} - -impl NewWithNullPtr for wire_RustRequest { - fn new_with_null_ptr() -> Self { - Self { - resource: Default::default(), - operation: Default::default(), - message: core::ptr::null_mut(), - blob: core::ptr::null_mut(), - } - } -} - -impl Default for wire_RustRequest { - fn default() -> Self { - Self::new_with_null_ptr() - } -} - -impl NewWithNullPtr for wire_RustRequestUnique { - fn new_with_null_ptr() -> Self { - Self { - id: Default::default(), - request: Default::default(), - } - } -} - -impl Default for wire_RustRequestUnique { - fn default() -> Self { - Self::new_with_null_ptr() - } -} - -// Section: sync execution mode utility - -#[no_mangle] -pub extern "C" fn free_WireSyncReturn(ptr: support::WireSyncReturn) { - unsafe { - let _ = support::box_from_leak_ptr(ptr); - }; -} diff --git a/native/hub/src/bridge/generated.rs b/native/hub/src/bridge/generated.rs deleted file mode 100644 index adc94445..00000000 --- a/native/hub/src/bridge/generated.rs +++ /dev/null @@ -1,245 +0,0 @@ -#![allow( - non_camel_case_types, - unused, - clippy::redundant_closure, - clippy::useless_conversion, - clippy::unit_arg, - clippy::double_parens, - non_snake_case, - clippy::too_many_arguments -)] -// AUTO GENERATED FILE, DO NOT EDIT. -// Generated by flutter_rust_bridge_codegen@ 1.79.0. - -use crate::bridge::interface::*; -use core::panic::UnwindSafe; -use rinf::engine::rust2dart::IntoIntoDart; -use rinf::engine::*; -use std::ffi::c_void; -use std::sync::Arc; - -// Section: imports - -// Section: wire functions - -fn wire_prepare_rust_signal_stream_impl(port_: MessagePort) { - BRIDGE_HANDLER.wrap::<_, _, _, ()>( - WrapInfo { - debug_name: "prepare_rust_signal_stream", - port: Some(port_), - mode: FfiCallMode::Stream, - }, - move || { - move |task_callback| { - Ok(prepare_rust_signal_stream( - task_callback.stream_sink::<_, RustSignal>(), - )) - } - }, - ) -} -fn wire_prepare_rust_response_stream_impl(port_: MessagePort) { - BRIDGE_HANDLER.wrap::<_, _, _, ()>( - WrapInfo { - debug_name: "prepare_rust_response_stream", - port: Some(port_), - mode: FfiCallMode::Stream, - }, - move || { - move |task_callback| { - Ok(prepare_rust_response_stream( - task_callback.stream_sink::<_, RustResponseUnique>(), - )) - } - }, - ) -} -fn wire_prepare_rust_report_stream_impl(port_: MessagePort) { - BRIDGE_HANDLER.wrap::<_, _, _, ()>( - WrapInfo { - debug_name: "prepare_rust_report_stream", - port: Some(port_), - mode: FfiCallMode::Stream, - }, - move || { - move |task_callback| { - Ok(prepare_rust_report_stream( - task_callback.stream_sink::<_, String>(), - )) - } - }, - ) -} -fn wire_prepare_channels_impl(port_: MessagePort) { - BRIDGE_HANDLER.wrap::<_, _, _, ()>( - WrapInfo { - debug_name: "prepare_channels", - port: Some(port_), - mode: FfiCallMode::Normal, - }, - move || move |task_callback| Ok(prepare_channels()), - ) -} -fn wire_check_rust_streams_impl(port_: MessagePort) { - BRIDGE_HANDLER.wrap::<_, _, _, bool>( - WrapInfo { - debug_name: "check_rust_streams", - port: Some(port_), - mode: FfiCallMode::Normal, - }, - move || move |task_callback| Ok(check_rust_streams()), - ) -} -fn wire_start_rust_logic_impl(port_: MessagePort) { - BRIDGE_HANDLER.wrap::<_, _, _, ()>( - WrapInfo { - debug_name: "start_rust_logic", - port: Some(port_), - mode: FfiCallMode::Normal, - }, - move || move |task_callback| Ok(start_rust_logic()), - ) -} -fn wire_stop_rust_logic_impl(port_: MessagePort) { - BRIDGE_HANDLER.wrap::<_, _, _, ()>( - WrapInfo { - debug_name: "stop_rust_logic", - port: Some(port_), - mode: FfiCallMode::Normal, - }, - move || move |task_callback| Ok(stop_rust_logic()), - ) -} -fn wire_request_to_rust_impl( - port_: MessagePort, - request_unique: impl Wire2Api + UnwindSafe, -) { - BRIDGE_HANDLER.wrap::<_, _, _, ()>( - WrapInfo { - debug_name: "request_to_rust", - port: Some(port_), - mode: FfiCallMode::Normal, - }, - move || { - let api_request_unique = request_unique.wire2api(); - move |task_callback| Ok(request_to_rust(api_request_unique)) - }, - ) -} -// Section: wrapper structs - -// Section: static checks - -// Section: allocate functions - -// Section: related functions - -// Section: impl Wire2Api - -pub trait Wire2Api { - fn wire2api(self) -> T; -} - -impl Wire2Api> for *mut S -where - *mut S: Wire2Api, -{ - fn wire2api(self) -> Option { - (!self.is_null()).then(|| self.wire2api()) - } -} - -impl Wire2Api for i32 { - fn wire2api(self) -> i32 { - self - } -} - -impl Wire2Api for i32 { - fn wire2api(self) -> RustOperation { - match self { - 0 => RustOperation::Create, - 1 => RustOperation::Read, - 2 => RustOperation::Update, - 3 => RustOperation::Delete, - _ => unreachable!("Invalid variant for RustOperation: {}", self), - } - } -} - -impl Wire2Api for u8 { - fn wire2api(self) -> u8 { - self - } -} - -// Section: impl IntoDart - -impl support::IntoDart for RustResponse { - fn into_dart(self) -> support::DartAbi { - vec![ - self.successful.into_into_dart().into_dart(), - self.message.into_dart(), - self.blob.into_dart(), - ] - .into_dart() - } -} -impl support::IntoDartExceptPrimitive for RustResponse {} -impl rust2dart::IntoIntoDart for RustResponse { - fn into_into_dart(self) -> Self { - self - } -} - -impl support::IntoDart for RustResponseUnique { - fn into_dart(self) -> support::DartAbi { - vec![ - self.id.into_into_dart().into_dart(), - self.response.into_into_dart().into_dart(), - ] - .into_dart() - } -} -impl support::IntoDartExceptPrimitive for RustResponseUnique {} -impl rust2dart::IntoIntoDart for RustResponseUnique { - fn into_into_dart(self) -> Self { - self - } -} - -impl support::IntoDart for RustSignal { - fn into_dart(self) -> support::DartAbi { - vec![ - self.resource.into_into_dart().into_dart(), - self.message.into_dart(), - self.blob.into_dart(), - ] - .into_dart() - } -} -impl support::IntoDartExceptPrimitive for RustSignal {} -impl rust2dart::IntoIntoDart for RustSignal { - fn into_into_dart(self) -> Self { - self - } -} - -// Section: executor - -support::lazy_static! { - pub static ref BRIDGE_HANDLER: support::DefaultHandler = Default::default(); -} - -/// cbindgen:ignore -#[cfg(target_family = "wasm")] -#[path = "generated.web.rs"] -mod web; -#[cfg(target_family = "wasm")] -pub use web::*; - -#[cfg(not(target_family = "wasm"))] -#[path = "generated.io.rs"] -mod io; -#[cfg(not(target_family = "wasm"))] -pub use io::*; diff --git a/native/hub/src/bridge/generated.web.rs b/native/hub/src/bridge/generated.web.rs deleted file mode 100644 index 8be08444..00000000 --- a/native/hub/src/bridge/generated.web.rs +++ /dev/null @@ -1,122 +0,0 @@ -use super::*; -// Section: wire functions - -#[wasm_bindgen] -pub fn wire_prepare_rust_signal_stream(port_: MessagePort) { - wire_prepare_rust_signal_stream_impl(port_) -} - -#[wasm_bindgen] -pub fn wire_prepare_rust_response_stream(port_: MessagePort) { - wire_prepare_rust_response_stream_impl(port_) -} - -#[wasm_bindgen] -pub fn wire_prepare_rust_report_stream(port_: MessagePort) { - wire_prepare_rust_report_stream_impl(port_) -} - -#[wasm_bindgen] -pub fn wire_prepare_channels(port_: MessagePort) { - wire_prepare_channels_impl(port_) -} - -#[wasm_bindgen] -pub fn wire_check_rust_streams(port_: MessagePort) { - wire_check_rust_streams_impl(port_) -} - -#[wasm_bindgen] -pub fn wire_start_rust_logic(port_: MessagePort) { - wire_start_rust_logic_impl(port_) -} - -#[wasm_bindgen] -pub fn wire_stop_rust_logic(port_: MessagePort) { - wire_stop_rust_logic_impl(port_) -} - -#[wasm_bindgen] -pub fn wire_request_to_rust(port_: MessagePort, request_unique: JsValue) { - wire_request_to_rust_impl(port_, request_unique) -} - -// Section: allocate functions - -// Section: related functions - -// Section: impl Wire2Api - -impl Wire2Api>> for Option> { - fn wire2api(self) -> Option> { - self.map(Wire2Api::wire2api) - } -} - -impl Wire2Api for JsValue { - fn wire2api(self) -> RustRequest { - let self_ = self.dyn_into::().unwrap(); - assert_eq!( - self_.length(), - 4, - "Expected 4 elements, got {}", - self_.length() - ); - RustRequest { - resource: self_.get(0).wire2api(), - operation: self_.get(1).wire2api(), - message: self_.get(2).wire2api(), - blob: self_.get(3).wire2api(), - } - } -} -impl Wire2Api for JsValue { - fn wire2api(self) -> RustRequestUnique { - let self_ = self.dyn_into::().unwrap(); - assert_eq!( - self_.length(), - 2, - "Expected 2 elements, got {}", - self_.length() - ); - RustRequestUnique { - id: self_.get(0).wire2api(), - request: self_.get(1).wire2api(), - } - } -} - -impl Wire2Api> for Box<[u8]> { - fn wire2api(self) -> Vec { - self.into_vec() - } -} -// Section: impl Wire2Api for JsValue - -impl Wire2Api for JsValue { - fn wire2api(self) -> i32 { - self.unchecked_into_f64() as _ - } -} -impl Wire2Api>> for JsValue { - fn wire2api(self) -> Option> { - (!self.is_undefined() && !self.is_null()).then(|| self.wire2api()) - } -} -impl Wire2Api for JsValue { - fn wire2api(self) -> RustOperation { - (self.unchecked_into_f64() as i32).wire2api() - } -} -impl Wire2Api for JsValue { - fn wire2api(self) -> u8 { - self.unchecked_into_f64() as _ - } -} -impl Wire2Api> for JsValue { - fn wire2api(self) -> Vec { - self.unchecked_into::() - .to_vec() - .into() - } -} diff --git a/native/hub/src/bridge/interface.rs b/native/hub/src/bridge/interface.rs index bbfefa9b..4398ec94 100644 --- a/native/hub/src/bridge/interface.rs +++ b/native/hub/src/bridge/interface.rs @@ -1,245 +1,53 @@ #![allow(dead_code)] -use rinf::engine::StreamSink; -use rinf::externs::lazy_static::lazy_static; use std::cell::RefCell; -use std::sync::Arc; use std::sync::Mutex; -use tokio::sync::mpsc::channel; -use tokio::sync::mpsc::Receiver; -use tokio::sync::mpsc::Sender; -use tokio_with_wasm::tokio; - -/// Available operations that a `RustRequest` object can hold. -/// There are 4 options, `Create`,`Read`,`Update`, and `Delete`. -pub enum RustOperation { - Create, - Read, - Update, - Delete, -} - -/// Holds the data that Rust streams to Dart. -#[derive(Clone)] -pub struct RustSignal { - pub resource: i32, - pub message: Option>, - pub blob: Option>, -} - -/// Request object that is sent from Dart to Rust. -pub struct RustRequest { - pub resource: i32, - pub operation: RustOperation, - pub message: Option>, - pub blob: Option>, -} - -/// Wrapper for `RustRequest` with a unique ID. -pub struct RustRequestUnique { - pub id: i32, - pub request: RustRequest, -} - -/// Response object that is sent from Rust to Dart. -#[derive(Clone)] -pub struct RustResponse { - pub successful: bool, - pub message: Option>, - pub blob: Option>, -} - -impl Default for RustResponse { - /// Empty response with the successful value of false. - fn default() -> RustResponse { - RustResponse { - successful: false, - message: None, - blob: None, - } - } -} - -/// Wrapper for `RustResponse` with a unique ID. -#[derive(Clone)] -pub struct RustResponseUnique { - pub id: i32, - pub response: RustResponse, -} - -type Cell = RefCell>; -type SharedCell = Arc>>; - -type RustSignalStream = StreamSink; -type RustResponseStream = StreamSink; -type RustReportStream = StreamSink; -type RustRequestSender = Sender; -type RustRequestReceiver = Receiver; - -// Native: Main thread -// Web: Worker thread -thread_local! { - pub static REQUEST_SENDER: Cell = RefCell::new(None); -} - -// Native: `tokio` runtime threads -// Web: Worker thread -thread_local! { - pub static SIGNAL_STREAM: Cell = RefCell::new(None); - pub static RESPONSE_STREAM: Cell = RefCell::new(None); - pub static REPORT_STREAM: Cell = RefCell::new(None); -} - -// Native: All threads -// Web: Worker thread -lazy_static! { - pub static ref SIGNAL_STREAM_SHARED: SharedCell = - Arc::new(Mutex::new(RefCell::new(None))); - pub static ref RESPONSE_STREAM_SHARED: SharedCell = - Arc::new(Mutex::new(RefCell::new(None))); - pub static ref REPORT_STREAM_SHARED: SharedCell = - Arc::new(Mutex::new(RefCell::new(None))); - pub static ref REQUST_RECEIVER_SHARED: SharedCell = - Arc::new(Mutex::new(RefCell::new(None))); -} +use std::sync::OnceLock; #[cfg(not(target_family = "wasm"))] -lazy_static! { - pub static ref TOKIO_RUNTIME: rinf::externs::os_thread_local::ThreadLocal> = - rinf::externs::os_thread_local::ThreadLocal::new(|| RefCell::new(None)); -} - +pub use super::interface_os::*; #[cfg(target_family = "wasm")] -thread_local! { - pub static IS_MAIN_STARTED: RefCell = RefCell::new(false); +pub use super::interface_web::*; + +/// This contains a message from Dart. +/// Optionally, a custom binary called `blob` can also be included. +/// This type is generic, and the message +/// can be of any type declared in Protobuf. +pub struct DartSignal { + pub message: T, + pub blob: Option>, } -/// Returns a stream object in Dart that listens to Rust. -pub fn prepare_rust_signal_stream(signal_stream: StreamSink) { - let cell = SIGNAL_STREAM_SHARED.lock().unwrap(); - cell.replace(Some(signal_stream)); +/// This is a mutable cell type that can be shared across threads. +pub type SharedCell = OnceLock>>>; + +/// Send a signal to Dart. +pub fn send_rust_signal(message_id: i32, message_bytes: Vec, blob: Option>) { + send_rust_signal_extern( + message_id, + message_bytes, + blob.is_some(), + blob.unwrap_or_default(), + ); } -/// Returns a stream object in Dart that gives responses from Rust. -pub fn prepare_rust_response_stream(response_stream: StreamSink) { - let cell = RESPONSE_STREAM_SHARED.lock().unwrap(); - cell.replace(Some(response_stream)); -} - -/// Returns a stream object in Dart that gives strings to print from Rust. -pub fn prepare_rust_report_stream(print_stream: StreamSink) { - let cell = REPORT_STREAM_SHARED.lock().unwrap(); - cell.replace(Some(print_stream)); -} - -/// Prepare channels that are used in the Rust world. -pub fn prepare_channels() { - let (request_sender, request_receiver) = channel(1024); - REQUEST_SENDER.with(move |inner| { - inner.replace(Some(request_sender)); - }); - let cell = REQUST_RECEIVER_SHARED.lock().unwrap(); - cell.replace(Some(request_receiver)); -} - -/// Check if the streams are ready in Rust. -/// This should be done before starting the Rust logic. -pub fn check_rust_streams() -> bool { - let mut are_all_ready = true; - let cell = SIGNAL_STREAM_SHARED.lock().unwrap(); - if cell.borrow().is_none() { - are_all_ready = false; - }; - let cell = RESPONSE_STREAM_SHARED.lock().unwrap(); - if cell.borrow().is_none() { - are_all_ready = false; - }; - #[cfg(debug_assertions)] - { - let cell = REPORT_STREAM_SHARED.lock().unwrap(); - if cell.borrow().is_none() { - are_all_ready = false; - }; - } - are_all_ready -} - -/// Start the main function of Rust. -pub fn start_rust_logic() { - #[cfg(not(target_family = "wasm"))] - { - use rinf::externs::backtrace; +/// Delegates the printing operation to Flutter, +/// which excels at handling various platforms +/// including web and mobile emulators. +/// When debugging, using this macro is recommended over `println!()`, +/// as it seamlessly adapts to different environments. +/// Note that this macro does nothing in release mode. +#[macro_export] +macro_rules! debug_print { + ( $( $t:tt )* ) => { + let rust_report = format!( $( $t )* ); #[cfg(debug_assertions)] - std::panic::set_hook(Box::new(|panic_info| { - let mut frames_filtered = Vec::new(); - backtrace::trace(|frame| { - // Filter some backtrace frames - // as those from infrastructure functions are not needed. - let mut should_keep_tracing = true; - backtrace::resolve_frame(frame, |symbol| { - if let Some(symbol_name) = symbol.name() { - let name = symbol_name.to_string(); - let name_trimmed = name.trim_start_matches('_'); - if name_trimmed.starts_with("rust_begin_unwind") { - frames_filtered.clear(); - return; - } - if name_trimmed.starts_with("rust_try") { - should_keep_tracing = false; - return; - } - } - let backtrace_frame = backtrace::BacktraceFrame::from(frame.to_owned()); - frames_filtered.push(backtrace_frame); - }); - should_keep_tracing - }); - let mut backtrace_filtered = backtrace::Backtrace::from(frames_filtered); - backtrace_filtered.resolve(); - crate::debug_print!( - "A panic occurred in Rust.\n{}\n{:?}", - panic_info, - backtrace_filtered - ); - })); - TOKIO_RUNTIME.with(move |inner| { - let tokio_runtime = tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .unwrap(); - tokio_runtime.spawn(crate::main()); - inner.replace(Some(tokio_runtime)); - }); - } - #[cfg(target_family = "wasm")] - { - #[cfg(debug_assertions)] - std::panic::set_hook(Box::new(|panic_info| { - crate::debug_print!("A panic occurred in Rust.\n{panic_info}"); - })); - IS_MAIN_STARTED.with(move |ref_cell| { - let is_started = *ref_cell.borrow(); - if !is_started { - tokio::spawn(crate::main()); - ref_cell.replace(true); - } - }); + $crate::bridge::send_rust_signal( + -1, // This is a special message ID for Rust reports + Vec::new(), + Some(rust_report.into_bytes()), + ); + #[cfg(not(debug_assertions))] + let _ = rust_report; } } - -/// Stop and terminate all Rust tasks. -pub fn stop_rust_logic() { - #[cfg(not(target_family = "wasm"))] - TOKIO_RUNTIME.with(move |ref_cell| { - ref_cell.replace(None); - }); -} - -/// Send a request to Rust and receive a response in Dart. -pub fn request_to_rust(request_unique: RustRequestUnique) { - REQUEST_SENDER.with(move |inner| { - let borrowed = inner.borrow(); - let sender = borrowed.as_ref().unwrap(); - sender.try_send(request_unique).ok(); - }); -} diff --git a/native/hub/src/bridge/interface_os.rs b/native/hub/src/bridge/interface_os.rs new file mode 100644 index 00000000..eb3d764d --- /dev/null +++ b/native/hub/src/bridge/interface_os.rs @@ -0,0 +1,119 @@ +use super::SharedCell; +use crate::debug_print; +use crate::tokio::runtime::Builder; +use crate::tokio::runtime::Runtime; +use allo_isolate::IntoDart; +use allo_isolate::Isolate; +use allo_isolate::ZeroCopyBuffer; +use rinf::externs::backtrace::Backtrace; +use rinf::externs::os_thread_local::ThreadLocal; +use std::cell::RefCell; +use std::panic::catch_unwind; +use std::sync::Mutex; +use std::sync::OnceLock; + +static DART_ISOLATE: SharedCell = OnceLock::new(); + +#[no_mangle] +pub extern "C" fn prepare_isolate_extern(port: i64) { + let _ = catch_unwind(|| { + let dart_isolate = Isolate::new(port); + let cell = DART_ISOLATE + .get_or_init(|| Mutex::new(RefCell::new(None))) + .lock() + .unwrap(); + cell.replace(Some(dart_isolate)); + }); +} + +// We use `os_thread_local` so that when the program fails +// and the main thread exits unexpectedly, +// the whole async tokio runtime can disappear as well. +type TokioRuntime = OnceLock>>>; +static TOKIO_RUNTIME: TokioRuntime = OnceLock::new(); + +#[no_mangle] +pub extern "C" fn start_rust_logic_extern() { + let _ = catch_unwind(|| { + // Enable backtrace output for panics. + #[cfg(debug_assertions)] + { + std::panic::set_hook(Box::new(|panic_info| { + let backtrace = Backtrace::new(); + debug_print!("A panic occurred in Rust.\n{panic_info}\n{backtrace:?}"); + })); + } + + // Run the main function. + let tokio_runtime = Builder::new_multi_thread().enable_all().build().unwrap(); + tokio_runtime.spawn(crate::main()); + let os_cell = TOKIO_RUNTIME.get_or_init(|| ThreadLocal::new(|| RefCell::new(None))); + os_cell.with(move |cell| { + // If there was already a tokio runtime previously, + // most likely due to Dart's hot restart, + // its tasks as well as itself will be terminated, + // being replaced with the new one. + cell.replace(Some(tokio_runtime)); + }); + }); +} + +#[no_mangle] +pub extern "C" fn stop_rust_logic_extern() { + let _ = catch_unwind(|| { + let os_cell = TOKIO_RUNTIME.get_or_init(|| ThreadLocal::new(|| RefCell::new(None))); + os_cell.with(move |cell| { + // If there was already a tokio runtime previously, + // most likely due to Dart's hot restart, + // its tasks as well as itself will be terminated, + // being replaced with the new one. + cell.replace(None); + }); + }); +} + +#[no_mangle] +pub extern "C" fn send_dart_signal_extern( + message_id: i64, + message_pointer: *const u8, + message_size: usize, + blob_valid: bool, + blob_pointer: *const u8, + blob_size: usize, +) { + let message_bytes = + unsafe { Vec::from_raw_parts(message_pointer as *mut u8, message_size, message_size) }; + let blob = if blob_valid { + unsafe { + Some(Vec::from_raw_parts( + blob_pointer as *mut u8, + blob_size, + blob_size, + )) + } + } else { + None + }; + let _ = catch_unwind(|| { + crate::messages::generated::handle_dart_signal(message_id as i32, message_bytes, blob); + }); +} + +pub fn send_rust_signal_extern( + message_id: i32, + message_bytes: Vec, + blob_valid: bool, + blob_bytes: Vec, +) { + let cell = DART_ISOLATE.get().unwrap().lock().unwrap(); + let dart_isolate = cell.borrow().unwrap(); + dart_isolate.post( + vec![ + message_id.into_dart(), + ZeroCopyBuffer(message_bytes).into_dart(), + blob_valid.into_dart(), + ZeroCopyBuffer(blob_bytes).into_dart(), + ] + .into_dart(), + ); +} diff --git a/native/hub/src/bridge/interface_web.rs b/native/hub/src/bridge/interface_web.rs new file mode 100644 index 00000000..d3683040 --- /dev/null +++ b/native/hub/src/bridge/interface_web.rs @@ -0,0 +1,64 @@ +use crate::debug_print; +use crate::tokio; +use rinf::externs::js_sys::Uint8Array; +use std::panic::catch_unwind; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn start_rust_logic_extern() { + let _ = catch_unwind(|| { + // Add kind description for panics. + #[cfg(debug_assertions)] + { + std::panic::set_hook(Box::new(|panic_info| { + debug_print!("A panic occurred in Rust.\n{panic_info}"); + })); + } + + // Run the main function. + tokio::spawn(crate::main()); + }); +} + +#[wasm_bindgen] +pub fn send_dart_signal_extern( + message_id: i32, + message_bytes: &[u8], + blob_valid: bool, + blob_bytes: &[u8], +) { + let message_bytes = message_bytes.to_vec(); + let blob = if blob_valid { + Some(blob_bytes.to_vec()) + } else { + None + }; + let _ = catch_unwind(|| { + crate::messages::generated::handle_dart_signal(message_id, message_bytes, blob); + }); +} + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_name = rinf_send_rust_signal_extern)] + pub fn send_rust_signal_extern_raw( + resource: i32, + message_bytes: Uint8Array, + blob_valid: bool, + blob_bytes: Uint8Array, + ); +} + +pub fn send_rust_signal_extern( + message_id: i32, + message_bytes: Vec, + blob_valid: bool, + blob_bytes: Vec, +) { + send_rust_signal_extern_raw( + message_id, + rinf::externs::js_sys::Uint8Array::from(message_bytes.as_slice()), + blob_valid, + rinf::externs::js_sys::Uint8Array::from(blob_bytes.as_slice()), + ); +} diff --git a/native/hub/src/bridge/mod.rs b/native/hub/src/bridge/mod.rs index 78885acb..b576747b 100644 --- a/native/hub/src/bridge/mod.rs +++ b/native/hub/src/bridge/mod.rs @@ -1,93 +1,12 @@ //! This module supports communication with Dart. -//! More specifically, sending responses and -//! stream signals to Dart are supported. //! DO NOT EDIT. #![allow(dead_code)] -pub use interface::*; -use tokio::sync::mpsc::Receiver; -use tokio_with_wasm::tokio; - -mod generated; mod interface; +pub use interface::*; -/// This function is expected to be used only once -/// during the initialization of the Rust logic. -pub fn get_request_receiver() -> Receiver { - let cell = REQUST_RECEIVER_SHARED.lock().unwrap(); - let option = cell.replace(None); - option.unwrap() -} - -/// Sending the signal will notify the Flutter widgets -/// and trigger the rebuild. -/// No memory copy is involved as the bytes are moved directly to Dart. -pub fn send_rust_signal(rust_signal: RustSignal) { - SIGNAL_STREAM.with(|inner| { - let mut borrowed = inner.borrow_mut(); - let option = borrowed.as_ref(); - if let Some(stream) = option { - stream.add(rust_signal); - } else { - let cell = SIGNAL_STREAM_SHARED.lock().unwrap(); - let stream = cell.borrow().as_ref().unwrap().clone(); - stream.add(rust_signal); - borrowed.replace(stream); - } - }); -} - -/// Sends a response to Dart with a unique interaction ID -/// to remember which request that response corresponds to. -/// No memory copy is involved as the bytes are moved directly to Dart. -pub fn respond_to_dart(response_unique: RustResponseUnique) { - RESPONSE_STREAM.with(|inner| { - let mut borrowed = inner.borrow_mut(); - let option = borrowed.as_ref(); - if let Some(stream) = option { - stream.add(response_unique); - } else { - let cell = RESPONSE_STREAM_SHARED.lock().unwrap(); - let stream = cell.borrow().as_ref().unwrap().clone(); - stream.add(response_unique); - borrowed.replace(stream); - } - }); -} - -/// Delegates the printing operation to Flutter, -/// which excels at handling various platforms -/// including web and mobile emulators. -/// When debugging, using this macro is recommended over `println!()`, -/// as it seamlessly adapts to different environments. -/// Note that this macro does nothing in release mode. -#[macro_export] -macro_rules! debug_print { - ( $( $t:tt )* ) => { - let rust_report = format!( $( $t )* ); - #[cfg(debug_assertions)] - $crate::bridge::send_rust_report(rust_report.into()); - #[cfg(not(debug_assertions))] - let _ = rust_report; - } -} - -/// Sends a string to Dart that should be printed in the CLI. -/// Do NOT use this function directly in the code. -/// Use `debug_print!` macro instead. -#[cfg(debug_assertions)] -pub fn send_rust_report(rust_report: String) { - REPORT_STREAM.with(|inner| { - let mut borrowed = inner.borrow_mut(); - let option = borrowed.as_ref(); - if let Some(stream) = option { - stream.add(rust_report); - } else { - let cell = REPORT_STREAM_SHARED.lock().unwrap(); - let stream = cell.borrow().as_ref().unwrap().clone(); - stream.add(rust_report); - borrowed.replace(stream); - } - }); -} +#[cfg(not(target_family = "wasm"))] +mod interface_os; +#[cfg(target_family = "wasm")] +mod interface_web; diff --git a/native/hub/src/imagecrop.rs b/native/hub/src/imagecrop.rs index 836dc79e..d586b7d6 100644 --- a/native/hub/src/imagecrop.rs +++ b/native/hub/src/imagecrop.rs @@ -19,9 +19,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/ -use crate::bridge::{RustOperation, RustRequest, RustResponse}; +use crate::messages; use image::{DynamicImage, GenericImageView, ImageOutputFormat, ImageResult, Rgba}; -use prost::Message; use std::io::Cursor; pub struct Point { @@ -138,27 +137,19 @@ fn crop_image(image: Vec) -> DynamicImage { return sub_image; } -pub async fn start_croping(rust_request: RustRequest) -> RustResponse { - use crate::messages::crop_borders::ReadRequest; +pub async fn start_croping() { + use messages::crop_borders::*; - match rust_request.operation { - RustOperation::Create => RustResponse::default(), - RustOperation::Read => { - let message_bytes = rust_request.message.unwrap(); - let request_message = ReadRequest::decode(message_bytes.as_slice()).unwrap(); - - let res = crop_image(request_message.image); - let mut image_data: Vec = Vec::new(); - res.write_to(&mut Cursor::new(&mut image_data), ImageOutputFormat::Png) - .unwrap(); - - RustResponse { - successful: true, - message: None, - blob: Some(image_data), - } + let mut receiver = CropBordersInput::get_dart_signal_receiver(); + while let Some(dart_signal) = receiver.recv().await { + let image = dart_signal.blob.unwrap(); + let res = crop_image(image); + let mut image_data: Vec = Vec::new(); + res.write_to(&mut Cursor::new(&mut image_data), ImageOutputFormat::Png) + .unwrap(); + CropBordersOutput { + interaction_id: dart_signal.message.interaction_id, } - RustOperation::Delete => RustResponse::default(), - RustOperation::Update => RustResponse::default(), + .send_signal_to_dart(Some(image_data)); } } diff --git a/native/hub/src/lib.rs b/native/hub/src/lib.rs index adce075f..7f41fa26 100644 --- a/native/hub/src/lib.rs +++ b/native/hub/src/lib.rs @@ -1,24 +1,15 @@ -use bridge::respond_to_dart; -use with_request::handle_request; use tokio_with_wasm::tokio; +mod boa_js; mod bridge; mod imagecrop; mod messages; -mod with_request; -mod boa_js; /// This `hub` crate is the entry point for the Rust logic. /// Always use non-blocking async functions such as `tokio::fs::File::open`. async fn main() { - // This is `tokio::sync::mpsc::Reciver` that receives the requests from Dart. - let mut request_receiver = bridge::get_request_receiver(); // Repeat `crate::spawn` anywhere in your code // if more concurrent tasks are needed. - while let Some(request_unique) = request_receiver.recv().await { - tokio::spawn(async { - let response_unique = handle_request(request_unique).await; - respond_to_dart(response_unique); - }); - } + tokio::spawn(boa_js::eval_js()); + tokio::spawn(imagecrop::start_croping()); } diff --git a/native/hub/src/with_request.rs b/native/hub/src/with_request.rs deleted file mode 100644 index 95754017..00000000 --- a/native/hub/src/with_request.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! This module runs the corresponding function -//! when a `RustRequest` was received from Dart -//! and returns `RustResponse`. - -use crate::bridge::{RustRequestUnique, RustResponse, RustResponseUnique}; -use crate::imagecrop; -use crate::boa_js; -use crate::messages; - -pub async fn handle_request(request_unique: RustRequestUnique) -> RustResponseUnique { - // Get the request data. - let rust_request = request_unique.request; - let interaction_id = request_unique.id; - - // Run the function that corresponds to the address. - let rust_resource = rust_request.resource; - let rust_response = match rust_resource { - messages::crop_borders::ID => { - imagecrop::start_croping(rust_request).await // ADD THIS BLOCK - } - messages::boa_js::ID => { - boa_js::eval_js(rust_request).await // ADD THIS BLOCK - } - _ => RustResponse::default(), - }; - - // Return the response. - RustResponseUnique { - id: interaction_id, - response: rust_response, - } -} diff --git a/pubspec.lock b/pubspec.lock index ebe84d69..38c6f403 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -310,10 +310,10 @@ packages: dependency: transitive description: name: dbus - sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" url: "https://pub.dev" source: hosted - version: "0.7.8" + version: "0.7.10" desktop_webview_window: dependency: "direct main" description: @@ -1115,10 +1115,10 @@ packages: dependency: "direct main" description: name: rinf - sha256: a76b3d53b9cf740ccff0e8edffc465b0fb81bcad090b83d8d1486dd70aadbd6a + sha256: "1b86528233c20b2ec9c5f08d94a1cfae471cdb279aa22ea2afdfeca189dd890c" url: "https://pub.dev" source: hosted - version: "4.20.0" + version: "6.0.1" riverpod: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8787d73a..10aee096 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,7 +60,7 @@ dependencies: ref: 0ab6b10ea660ead8e8e1694517aabe3582f25d5c media_kit_libs_video: ^1.0.4 crypto: ^3.0.3 - rinf: ^4.19.0 + rinf: ^6.0.1 protobuf: ^3.1.0 cupertino_icons: ^1.0.2 window_manager: ^0.3.7