diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 812d32b4..0e9071e0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -198,11 +198,52 @@ jobs: windows: runs-on: windows-latest - timeout-minutes: 30 + timeout-minutes: 45 steps: - uses: actions/checkout@v4 + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: 9.15.4 + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Setup pnpm cache + uses: actions/cache@v4 + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Cache node_modules + uses: actions/cache@v4 + with: + path: | + node_modules + examples/*/node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-node-modules- + + - name: Cache Rust dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + ~/.cargo/bin + target + examples/*/target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + - name: Install Rust uses: dtolnay/rust-toolchain@stable with: @@ -217,16 +258,26 @@ jobs: - name: Cargo check Windows run: cargo check --target x86_64-pc-windows-msvc - - name: Install pnpm - uses: pnpm/action-setup@v2 - with: - version: 9.15.4 - - name: Install dependencies run: pnpm install - name: TypeScript check run: pnpm check + # Plugin lib test exe hits 0xc0000139 (STATUS_ENTRYPOINT_NOT_FOUND) on GHA Windows. + # Hub/PTY coverage stays on Ubuntu/macOS nextest; still run the rest of the workspace. + - name: Run Rust tests (workspace except plugin lib exe) + run: cargo test --workspace --exclude tauri-plugin-serialplugin + - name: Run JavaScript tests run: pnpm test + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-windows + path: | + coverage/ + test-results/ + if-no-files-found: warn diff --git a/.release-it.json b/.release-it.json new file mode 100644 index 00000000..177e3de8 --- /dev/null +++ b/.release-it.json @@ -0,0 +1,25 @@ +{ + "git": { + "commitMessage": "chore(release): ${version}", + "tagName": "v${version}", + "requireCleanWorkingDir": true, + "push": true + }, + "github": { + "release": true + }, + "npm": { + "publish": false + }, + "plugins": { + "@release-it/conventional-changelog": { + "preset": "conventionalcommits", + "infile": "CHANGELOG.md", + "header": "# Changelog\n" + } + }, + "hooks": { + "after:bump": "node scripts/sync-cargo-version.cjs ${version} && git add Cargo.toml CHANGELOG.md package.json", + "after:release": "echo \"Tagged v${version}. Next: pnpm whoami || pnpm login; then pnpm release:publish\"" + } +} diff --git a/.versionrc.json b/.versionrc.json deleted file mode 100644 index 153ab383..00000000 --- a/.versionrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "types": [ - { "type": "feat", "section": "Features" }, - { "type": "fix", "section": "Bug Fixes" }, - { "type": "chore", "hidden": true }, - { "type": "docs", "hidden": true }, - { "type": "style", "hidden": true }, - { "type": "refactor", "hidden": true }, - { "type": "test", "hidden": true } - ], - "commitUrlFormat": "https://github.com/s00d/tauri-plugin-serialplugin/commit/{{hash}}", - "compareUrlFormat": "https://github.com/s00d/tauri-plugin-serialplugin/compare/{{previousTag}}...{{currentTag}}", - "issueUrlFormat": "https://github.com/s00d/tauri-plugin-serialplugin/issues/{{id}}", - "scripts": { - "postbump": "jq -r .version package.json > VERSION && sed -i '' \"s/^version = .*$/version = \\\"$(cat VERSION)\\\"/\" Cargo.toml && rm VERSION && sleep 10 && git add Cargo.toml Cargo.lock CHANGELOG.md examples/serialport-test/src-tauri/Cargo.lock && git commit -m \"chore: update version and changelog\" && git push", - "postchangelog": "git add CHANGELOG.md Cargo.toml" - } -} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..ead8ec2c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,96 @@ +# Contributing + +Thanks for helping improve **tauri-plugin-serialplugin**. + +## Prerequisites + +- Rust stable (see `rust-version` in `Cargo.toml`) +- Node 20+ and [pnpm](https://pnpm.io) 9.15.x (see `packageManager` in `package.json`) +- For Android / Robolectric: **JDK 17** + +## Quick start + +```bash +pnpm install +pnpm check && pnpm test && pnpm build +cargo fmt --all -- --check +cargo clippy --workspace --all-targets -- -D warnings +cargo test --workspace +``` + +Faster local gate (no Android cross / Robolectric): + +```bash +./scripts/ci-fast.sh +``` + +Playground app: + +```bash +pnpm playground +``` + +## Project layout + +| Path | Role | +|------|------| +| `src/` | Rust plugin (desktop + Android) | +| `guest-js/` | TypeScript API published as `tauri-plugin-serialplugin-api` | +| `permissions/` | Tauri ACL permission TOMLs | +| `android/` | Kotlin / Gradle Android module | +| `crates/android-usb-serial/` | Pure-Rust USB serial drivers | +| `examples/serialport-test/` | Demo / playground | +| `tests/` | Jest suites for guest-js | + +## Pull requests + +1. Keep changes focused; prefer small PRs. +2. Match existing style; run fmt / clippy / tests before pushing. +3. Update `CHANGELOG.md` for user-visible changes (or rely on `pnpm release:patch` / `release:minor` / `release:major`, which write it via release-it). +4. Do **not** add new top-level CI workflows unless an existing job cannot cover the need. +5. Public API changes (Rust or JS) need a clear migration note for the next semver bump. + +### Semver reminders + +- **Patch**: bugfixes, docs, internal refactors with no public API break. +- **Minor**: additive API (new commands / options) that stays backward compatible. +- **Major**: removed / renamed JS or Rust exports, ACL identifier renames, behavior breaks. + +Deprecated Rust items (e.g. `PortBackend`) stay until the next major. + +## Publishing (maintainers) + +Full checklist: **[PUBLISHING.md](./PUBLISHING.md)**. + +Bump (pick one): + +```bash +pnpm release:patch +pnpm release:minor +pnpm release:major +``` + +Auth + publish: + +```bash +pnpm whoami +# if logged out: +pnpm login +cargo login + +pnpm release:publish +``` + +Dry-run: `./scripts/publish.sh --dry-run` +Surface check: `pnpm publish:check` + +`release-it` bumps `package.json` + `Cargo.toml` (via `scripts/sync-cargo-version.cjs`), writes `CHANGELOG.md`, tags, and opens a GitHub Release. +`scripts/publish.sh` publishes with **pnpm** first, then `cargo publish`. + +## Security + +See [SECURITY.md](./SECURITY.md). Do not file public issues for vulnerabilities. + +## License + +Contributions are dual-licensed under MIT and Apache-2.0, same as the repository. diff --git a/Cargo.lock b/Cargo.lock index 26985946..c093b7d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,7 +51,7 @@ checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" name = "android-usb-serial" version = "0.1.1" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "libc", "log", "nusb", @@ -131,6 +131,27 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "1.3.2" @@ -170,7 +191,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" dependencies = [ - "objc2 0.6.1", + "objc2 0.6.4", ] [[package]] @@ -285,7 +306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257" dependencies = [ "serde", - "toml", + "toml 0.8.23", ] [[package]] @@ -346,7 +367,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -359,12 +380,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "cookie" version = "0.18.1" @@ -404,6 +419,19 @@ dependencies = [ "libc", ] +[[package]] +name = "core-graphics" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" +dependencies = [ + "bitflags 2.9.1", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + [[package]] name = "core-graphics-types" version = "0.2.0" @@ -460,19 +488,15 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.29.6" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "matches", - "phf 0.10.1", - "proc-macro2", - "quote", + "phf", "smallvec", - "syn 1.0.109", ] [[package]] @@ -487,14 +511,20 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.9" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +checksum = "352d39c2f7bef1d6ad73db6f5160efcaed66d94ef8c6c573a8410c00bf909a98" dependencies = [ - "quote", - "syn 2.0.104", + "ctor-proc-macro", + "dtor", ] +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + [[package]] name = "darling" version = "0.20.11" @@ -530,6 +560,17 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "dbus" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab69f03cc8c4340c9c8e315114e1658e6775a9b16a04357973aa21cec22b32e" +dependencies = [ + "libc", + "libdbus-sys", + "windows-sys 0.61.2", +] + [[package]] name = "deranged" version = "0.4.0" @@ -542,11 +583,19 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.20" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "convert_case", "proc-macro2", "quote", "rustc_version", @@ -584,12 +633,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - [[package]] name = "dispatch2" version = "0.3.0" @@ -597,7 +640,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.1", + "block2 0.6.1", + "libc", + "objc2 0.6.4", ] [[package]] @@ -613,9 +658,9 @@ dependencies = [ [[package]] name = "dlopen2" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" dependencies = [ "dlopen2_derive", "libc", @@ -634,6 +679,21 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "dom_query" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" +dependencies = [ + "bit-set", + "cssparser", + "foldhash", + "html5ever", + "precomputed-hash", + "selectors", + "tendril", +] + [[package]] name = "dpi" version = "0.1.2" @@ -658,6 +718,21 @@ dependencies = [ "dtoa", ] +[[package]] +name = "dtor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1057d6c64987086ff8ed0fd3fbf377a6b7d205cc7715868cd401705f715cbe4" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + [[package]] name = "dunce" version = "1.0.5" @@ -679,7 +754,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml", + "toml 0.8.23", "vswhom", "winreg", ] @@ -716,6 +791,12 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + [[package]] name = "fdeflate" version = "0.3.7" @@ -751,6 +832,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.5.0" @@ -787,16 +874,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - [[package]] name = "futures-channel" version = "0.3.31" @@ -869,15 +946,6 @@ dependencies = [ "slab", ] -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "gdk" version = "0.18.2" @@ -987,17 +1055,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.16" @@ -1183,9 +1240,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -1207,14 +1264,12 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "html5ever" -version = "0.29.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" dependencies = [ "log", - "mac", "markup5ever", - "match_token", ] [[package]] @@ -1326,12 +1381,12 @@ dependencies = [ [[package]] name = "ico" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98" +checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371" dependencies = [ "byteorder", - "png", + "png 0.17.16", ] [[package]] @@ -1460,13 +1515,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", - "hashbrown 0.15.4", + "hashbrown 0.17.1", "serde", + "serde_core", ] [[package]] @@ -1504,16 +1560,6 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "itoa" version = "1.0.15" @@ -1608,24 +1654,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "kuchikiki" -version = "0.8.8-speedreader" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" -dependencies = [ - "cssparser", - "html5ever", - "indexmap 2.10.0", - "selectors", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "libappindicator" version = "0.9.0" @@ -1652,9 +1680,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libdbus-sys" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" +dependencies = [ + "pkg-config", +] [[package]] name = "libloading" @@ -1720,15 +1757,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "mac" -version = "0.1.1" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "mach2" @@ -1750,35 +1781,15 @@ dependencies = [ [[package]] name = "markup5ever" -version = "0.14.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" dependencies = [ "log", - "phf 0.11.3", - "phf_codegen 0.11.3", - "string_cache", - "string_cache_codegen", "tendril", + "web_atoms", ] -[[package]] -name = "match_token" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "memchr" version = "2.7.5" @@ -1823,23 +1834,23 @@ dependencies = [ [[package]] name = "muda" -version = "0.17.0" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b89bf91c19bf036347f1ab85a81c560f08c0667c8601bece664d860a600988" +checksum = "1dd04e60bc0b07438a6771710ee1698f98f6ebbc7f89b61264af1563b8aeb878" dependencies = [ "crossbeam-channel", "dpi", "gtk", "keyboard-types", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-app-kit", "objc2-core-foundation", "objc2-foundation 0.3.1", "once_cell", - "png", + "png 0.18.1", "serde", "thiserror 2.0.12", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1857,12 +1868,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - [[package]] name = "ndk-sys" version = "0.6.0+11769913" @@ -1889,12 +1894,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - [[package]] name = "num-conv" version = "0.1.0" @@ -1934,19 +1933,23 @@ dependencies = [ [[package]] name = "nusb" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "215a49c10e8cff30a0da93b258b21846c4e9242f7683748cfa8474fdc2e4d22b" +checksum = "18ef13beb3b3a8fc16fd7aea912ebd3d45dde00a9a5b968d0742297468065845" dependencies = [ "core-foundation", "core-foundation-sys", "futures-core", "io-kit-sys 0.5.0", + "js-sys", "linux-raw-sys", "log", "once_cell", "rustix", "slab", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", "windows-sys 0.60.2", ] @@ -1968,9 +1971,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", "objc2-exception-helper", @@ -1984,15 +1987,9 @@ checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ "bitflags 2.9.1", "block2 0.6.1", - "libc", - "objc2 0.6.1", - "objc2-cloud-kit", - "objc2-core-data", + "objc2 0.6.4", "objc2-core-foundation", - "objc2-core-graphics", - "objc2-core-image", "objc2-foundation 0.3.1", - "objc2-quartz-core 0.3.1", ] [[package]] @@ -2002,7 +1999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-foundation 0.3.1", ] @@ -2012,8 +2009,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d" dependencies = [ - "bitflags 2.9.1", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-foundation 0.3.1", ] @@ -2025,7 +2021,7 @@ checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ "bitflags 2.9.1", "dispatch2", - "objc2 0.6.1", + "objc2 0.6.4", ] [[package]] @@ -2036,7 +2032,7 @@ checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" dependencies = [ "bitflags 2.9.1", "dispatch2", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-core-foundation", "objc2-io-surface", ] @@ -2047,7 +2043,17 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e" dependencies = [ - "objc2 0.6.1", + "objc2 0.6.4", + "objc2-foundation 0.3.1", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac0f75792558aa9d618443bbb5db7426a7a0b6fddf96903f86ef9ad02e135740" +dependencies = [ + "objc2 0.6.4", "objc2-foundation 0.3.1", ] @@ -2086,8 +2092,7 @@ checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ "bitflags 2.9.1", "block2 0.6.1", - "libc", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -2098,7 +2103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -2134,7 +2139,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.1", + "objc2 0.6.4", + "objc2-core-foundation", "objc2-foundation 0.3.1", ] @@ -2145,8 +2151,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" dependencies = [ "bitflags 2.9.1", - "objc2 0.6.1", + "block2 0.6.1", + "objc2 0.6.4", + "objc2-cloud-kit", + "objc2-core-data", "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.3.1", + "objc2-quartz-core 0.3.1", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3f5ec77a81d9e0c5a0b32159b0cb143d7086165e79708351e02bf37dfc65cd" +dependencies = [ + "objc2 0.6.4", "objc2-foundation 0.3.1", ] @@ -2158,7 +2182,7 @@ checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad" dependencies = [ "bitflags 2.9.1", "block2 0.6.1", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-app-kit", "objc2-core-foundation", "objc2-foundation 0.3.1", @@ -2241,106 +2265,43 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" -dependencies = [ - "phf_shared 0.8.0", -] - -[[package]] -name = "phf" -version = "0.10.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "phf_macros 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", -] - -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_macros 0.11.3", - "phf_shared 0.11.3", -] - -[[package]] -name = "phf_codegen" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", + "phf_macros", + "phf_shared", + "serde", ] [[package]] name = "phf_codegen" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", + "phf_generator", + "phf_shared", ] [[package]] name = "phf_generator" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" -dependencies = [ - "phf_shared 0.8.0", - "rand 0.7.3", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand 0.8.5", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared 0.11.3", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.10.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", + "fastrand", + "phf_shared", ] [[package]] name = "phf_macros" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", + "phf_generator", + "phf_shared", "proc-macro2", "quote", "syn 2.0.104", @@ -2348,29 +2309,11 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -dependencies = [ - "siphasher 0.3.11", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher 0.3.11", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ - "siphasher 1.0.1", + "siphasher", ] [[package]] @@ -2398,7 +2341,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d77244ce2d584cd84f6a15f86195b8c9b2a0dfbfd817c09e0464244091a58ed" dependencies = [ "base64 0.22.1", - "indexmap 2.10.0", + "indexmap 2.14.2", "quick-xml", "serde", "time", @@ -2417,6 +2360,19 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.9.1", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "potential_utf" version = "0.1.2" @@ -2432,15 +2388,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "precomputed-hash" version = "0.1.1" @@ -2499,12 +2446,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" version = "1.0.95" @@ -2538,87 +2479,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] - [[package]] name = "raw-window-handle" version = "0.6.2" @@ -2696,9 +2556,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.21" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8cea6b35bcceb099f30173754403d2eba0a5dc18cea3630fccd88251909288" +checksum = "04e9018c9d814e5f30cc16a0f03271aeab3571e609612d9fe78c1aa8d11c2f62" dependencies = [ "base64 0.22.1", "bytes", @@ -2715,7 +2575,6 @@ dependencies = [ "pin-project-lite", "serde", "serde_json", - "serde_urlencoded", "sync_wrapper", "tokio", "tokio-util", @@ -2735,6 +2594,12 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -2763,12 +2628,6 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "same-file" version = "1.0.6" @@ -2837,18 +2696,19 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "selectors" -version = "0.24.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" +checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.9.1", "cssparser", "derive_more", - "fxhash", "log", - "phf 0.8.0", - "phf_codegen 0.8.0", + "new_debug_unreachable", + "phf", + "phf_codegen", "precomputed-hash", + "rustc-hash", "servo_arc", "smallvec", ] @@ -2864,10 +2724,11 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ + "serde_core", "serde_derive", ] @@ -2882,15 +2743,24 @@ dependencies = [ "typeid", ] +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn 3.0.5", ] [[package]] @@ -2906,14 +2776,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -2937,15 +2808,12 @@ dependencies = [ ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "serde_spanned" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", + "serde_core", ] [[package]] @@ -2958,7 +2826,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.10.0", + "indexmap 2.14.2", "schemars 0.9.0", "schemars 1.0.3", "serde", @@ -2982,9 +2850,9 @@ dependencies = [ [[package]] name = "serialize-to-javascript" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5" dependencies = [ "serde", "serde_json", @@ -2993,20 +2861,20 @@ dependencies = [ [[package]] name = "serialize-to-javascript-impl" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.104", ] [[package]] name = "serialport" -version = "4.9.0" +version = "4.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d91116f97173694f1642263b2ff837f80d933aa837e2314969f6728f661df3" +checksum = "6a2f4ac56b5d3af3c40fbbee17be96d532cba02fa5853926aacdb77d926272ab" dependencies = [ "bitflags 2.9.1", "cfg-if", @@ -3023,11 +2891,10 @@ dependencies = [ [[package]] name = "servo_arc" -version = "0.2.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" dependencies = [ - "nodrop", "stable_deref_trait", ] @@ -3054,12 +2921,6 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - [[package]] name = "siphasher" version = "1.0.1" @@ -3096,7 +2957,7 @@ checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" dependencies = [ "bytemuck", "cfg_aliases", - "core-graphics", + "core-graphics 0.24.0", "foreign-types", "js-sys", "log", @@ -3144,25 +3005,24 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "string_cache" -version = "0.8.9" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" dependencies = [ "new_debug_unreachable", "parking_lot", - "phf_shared 0.11.3", + "phf_shared", "precomputed-hash", - "serde", ] [[package]] name = "string_cache_codegen" -version = "0.5.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", + "phf_generator", + "phf_shared", "proc-macro2", "quote", ] @@ -3191,7 +3051,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote", "unicode-ident", ] @@ -3206,6 +3065,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sync_wrapper" version = "1.0.2" @@ -3235,40 +3105,41 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml", + "toml 0.8.23", "version-compare", ] [[package]] name = "tao" -version = "0.34.0" +version = "0.35.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49c380ca75a231b87b6c9dd86948f035012e7171d1a7c40a9c2890489a7ffd8a" +checksum = "d1c93047acf68669466a34690ac58cca7010bd1b201e1ec86f1fd0a75d3dd4a9" dependencies = [ "bitflags 2.9.1", + "block2 0.6.1", "core-foundation", - "core-graphics", + "core-graphics 0.25.0", "crossbeam-channel", - "dispatch", + "dbus", + "dispatch2", "dlopen2", "dpi", "gdkwayland-sys", "gdkx11-sys", "gtk", "jni", - "lazy_static", "libc", "log", "ndk", - "ndk-context", "ndk-sys", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-app-kit", "objc2-foundation 0.3.1", + "objc2-ui-kit", "once_cell", "parking_lot", + "percent-encoding", "raw-window-handle", - "scopeguard", "tao-macros", "unicode-segmentation", "url", @@ -3297,12 +3168,13 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.6.2" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "124e129c9c0faa6bec792c5948c89e86c90094133b0b9044df0ce5f0a8efaa0d" +checksum = "667b20e2726d572dea2de7370da16e188eb06008faf9a92fab7cdc46791190b5" dependencies = [ "anyhow", "bytes", + "cookie", "dirs", "dunce", "embed_plist", @@ -3316,10 +3188,11 @@ dependencies = [ "log", "mime", "muda", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-app-kit", "objc2-foundation 0.3.1", "objc2-ui-kit", + "objc2-web-kit", "percent-encoding", "plist", "raw-window-handle", @@ -3338,7 +3211,6 @@ dependencies = [ "tokio", "tray-icon", "url", - "urlpattern", "webkit2gtk", "webview2-com", "window-vibrancy", @@ -3347,9 +3219,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.3.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f025c389d3adb83114bec704da973142e82fc6ec799c7c750c5e21cefaec83" +checksum = "bc9ce40b16101cb6ea63d3e221567affd1c3a9205f95d7bc574941a10636b632" dependencies = [ "anyhow", "cargo_toml", @@ -3363,22 +3235,21 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "toml", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.3.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5df493a1075a241065bc865ed5ef8d0fbc1e76c7afdc0bf0eccfaa7d4f0e406" +checksum = "08279169ff42f8fc45a1dbc9dcae888893ba95288142e5880c59b93a26d2cfc5" dependencies = [ "base64 0.22.1", "brotli", "ico", "json-patch", "plist", - "png", + "png 0.17.16", "proc-macro2", "quote", "semver", @@ -3396,9 +3267,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.3.1" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f237fbea5866fa5f2a60a21bea807a2d6e0379db070d89c3a10ac0f2d4649bbc" +checksum = "e8b394794f399a421811d06966343e7933fcae92d59f5180b9388d1174497a45" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3410,9 +3281,9 @@ dependencies = [ [[package]] name = "tauri-plugin" -version = "2.3.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9a0bd00bf1930ad1a604d08b0eb6b2a9c1822686d65d7f4731a7723b8901d3" +checksum = "74be5dd4bed9afbd145e5716b5fa2ec28cbc29c34ffa61c258c9273d896c8020" dependencies = [ "anyhow", "glob", @@ -3421,7 +3292,6 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "toml", "walkdir", ] @@ -3441,39 +3311,41 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.7.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7bb73d1bceac06c20b3f755b2c8a2cb13b20b50083084a8cf3700daf397ba4" +checksum = "b0b4bc95aed361b0019067d189a1174a603d460d0f6c72606512d59fc9c12ec8" dependencies = [ "cookie", "dpi", "gtk", "http", "jni", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-ui-kit", + "objc2-web-kit", "raw-window-handle", "serde", "serde_json", "tauri-utils", "thiserror 2.0.12", "url", + "webkit2gtk", + "webview2-com", "windows", ] [[package]] name = "tauri-runtime-wry" -version = "2.7.1" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "902b5aa9035e16f342eb64f8bf06ccdc2808e411a2525ed1d07672fa4e780bad" +checksum = "4e6fac707727b7a2f48e4ded90976324267371073edbb415ffb73bb0458d203f" dependencies = [ "gtk", "http", "jni", "log", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-app-kit", - "objc2-foundation 0.3.1", "once_cell", "percent-encoding", "raw-window-handle", @@ -3490,24 +3362,24 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.5.0" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41743bbbeb96c3a100d234e5a0b60a46d5aa068f266160862c7afdbf828ca02e" +checksum = "3e176a18e67764923c4f1ce66f25ae4abe5f688384d5eb1a0fa6c77f3d90f887" dependencies = [ "anyhow", "brotli", "cargo_metadata", "ctor", + "dom_query", "dunce", "glob", - "html5ever", "http", "infer", "json-patch", - "kuchikiki", "log", "memchr", - "phf 0.11.3", + "phf", + "plist", "proc-macro2", "quote", "regex", @@ -3519,7 +3391,7 @@ dependencies = [ "serde_with", "swift-rs", "thiserror 2.0.12", - "toml", + "toml 1.1.5+spec-1.1.0", "url", "urlpattern", "uuid", @@ -3533,19 +3405,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8d321dbc6f998d825ab3f0d62673e810c861aac2d0de2cc2c395328f1d113b4" dependencies = [ "embed-resource", - "indexmap 2.10.0", - "toml", + "indexmap 2.14.2", + "toml 0.8.23", ] [[package]] name = "tendril" -version = "0.4.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +checksum = "5fed54709c5b3a53d09bb1c113ea4f5ceafd1e772ddcb0030a82e1d56c087b08" dependencies = [ - "futf", - "mac", - "utf-8", + "new_debug_unreachable", ] [[package]] @@ -3664,11 +3534,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_edit 0.22.27", ] +[[package]] +name = "toml" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12c0ba9680044b4ce98d391a62094047eada0d64860b80166c39f4a6b5640785" +dependencies = [ + "indexmap 2.14.2", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.4", +] + [[package]] name = "toml_datetime" version = "0.6.11" @@ -3678,14 +3563,23 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.10.0", - "toml_datetime", + "indexmap 2.14.2", + "toml_datetime 0.6.11", "winnow 0.5.40", ] @@ -3695,8 +3589,8 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.10.0", - "toml_datetime", + "indexmap 2.14.2", + "toml_datetime 0.6.11", "winnow 0.5.40", ] @@ -3706,20 +3600,35 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.10.0", + "indexmap 2.14.2", "serde", - "serde_spanned", - "toml_datetime", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", "toml_write", "winnow 0.7.11", ] +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow 1.0.4", +] + [[package]] name = "toml_write" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + [[package]] name = "tower" version = "0.5.2" @@ -3737,20 +3646,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "bitflags 2.9.1", "bytes", "futures-util", "http", "http-body", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -3786,24 +3695,24 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da75ec677957aa21f6e0b361df0daab972f13a5bee3606de0638fd4ee1c666a" +checksum = "045979e3f037cd18ad1cb2a419dfda133c5c29c9f3453370079f2255d46c257e" dependencies = [ "crossbeam-channel", "dirs", "libappindicator", "muda", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", "objc2-foundation 0.3.1", "once_cell", - "png", + "png 0.18.1", "serde", "thiserror 2.0.12", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3910,12 +3819,6 @@ dependencies = [ "url", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -3985,12 +3888,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -4100,11 +3997,23 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web_atoms" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8b815c1b593dc0baf78dd0f4fc8fdb2de53198fb1163738093e9a311c33fb3" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + [[package]] name = "webkit2gtk" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +checksum = "a1027150013530fb2eaf806408df88461ae4815a45c541c8975e61d6f2fc4793" dependencies = [ "bitflags 1.3.2", "cairo-rs", @@ -4126,9 +4035,9 @@ dependencies = [ [[package]] name = "webkit2gtk-sys" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +checksum = "916a5f65c2ef0dfe12fff695960a2ec3d4565359fdbb2e9943c974e06c734ea5" dependencies = [ "bitflags 1.3.2", "cairo-sys-rs", @@ -4202,7 +4111,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4217,7 +4126,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" dependencies = [ - "objc2 0.6.1", + "objc2 0.6.4", "objc2-app-kit", "objc2-core-foundation", "objc2-foundation 0.3.1", @@ -4235,7 +4144,7 @@ dependencies = [ "windows-collections", "windows-core", "windows-future", - "windows-link", + "windows-link 0.1.3", "windows-numerics", ] @@ -4256,7 +4165,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", - "windows-link", + "windows-link 0.1.3", "windows-result", "windows-strings", ] @@ -4268,7 +4177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.1.3", "windows-threading", ] @@ -4300,6 +4209,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-numerics" version = "0.2.0" @@ -4307,7 +4222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ "windows-core", - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -4316,7 +4231,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -4325,7 +4240,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -4364,6 +4279,15 @@ dependencies = [ "windows-targets 0.53.2", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -4417,7 +4341,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -4426,7 +4350,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -4585,6 +4509,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" + [[package]] name = "winreg" version = "0.55.0" @@ -4612,26 +4542,26 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "wry" -version = "0.52.1" +version = "0.55.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a714d9ba7075aae04a6e50229d6109e3d584774b99a6a8c60de1698ca111b9" +checksum = "186f9871daa55fd9c016578b810d149de58367113db7fb72b462d2323ce19514" dependencies = [ "base64 0.22.1", "block2 0.6.1", "cookie", "crossbeam-channel", + "dirs", + "dom_query", "dpi", "dunce", "gdkx11", "gtk", - "html5ever", "http", "javascriptcore-rs", "jni", - "kuchikiki", "libc", "ndk", - "objc2 0.6.1", + "objc2 0.6.4", "objc2-app-kit", "objc2-core-foundation", "objc2-foundation 0.3.1", @@ -4699,26 +4629,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "zerofrom" version = "0.1.6" @@ -4772,3 +4682,9 @@ dependencies = [ "quote", "syn 2.0.104", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index c64fe199..cd4e7eac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,17 +11,36 @@ name = "tauri-plugin-serialplugin" version = "3.0.4" description = "Tauri plugin for serial port access (desktop and Android)." edition = "2021" -authors = ["Tauri Programme within The Commons Conservancy"] +authors = ["s00d"] license = "Apache-2.0 OR MIT" rust-version = "1.79" links = "tauri-plugin-serialplugin" +readme = "README.md" repository = "https://github.com/s00d/tauri-plugin-serialplugin" -# Keep crate under crates.io 10MB limit; examples live in the git repo. +homepage = "https://github.com/s00d/tauri-plugin-serialplugin" +documentation = "https://docs.rs/tauri-plugin-serialplugin" +keywords = ["tauri-plugin", "serial", "serialport", "usb", "android"] +categories = ["hardware-support", "api-bindings"] +# Keep crate lean for crates.io; examples/tests/tooling stay in git. exclude = [ "examples/**", ".github/**", "docs/**", "banner.png", + "tests/**", + "scripts/**", + "crates/**", + "coverage/**", + "test-results/**", + "android/src/test/**", + "android/BUILD_INSTRUCTIONS.md", + "jest.config.js", + ".jestignore", + ".versionrc.json", + "pnpm-lock.yaml", + "pnpm-workspace.yaml", + "tsconfig.json", + "rollup.config.mjs", ] [features] @@ -30,7 +49,8 @@ android-test-harness = ["android-usb-serial/fake-transport"] [package.metadata.docs.rs] rustc-args = [ "--cfg", "docsrs" ] rustdoc-args = [ "--cfg", "docsrs" ] -targets = ["x86_64-linux-android"] +# Desktop APIs are the common docs.rs surface; Android JNI is cfg-gated. +targets = ["x86_64-unknown-linux-gnu"] [package.metadata.platforms.support] windows = { level = "full", notes = "" } @@ -39,21 +59,26 @@ macos = { level = "full", notes = "" } android = { level = "full", notes = "" } [build-dependencies] -tauri-plugin = { version = "2.3.0", features = [ "build" ] } +tauri-plugin = { version = "2", features = [ "build" ] } [dependencies] -tauri = { version = "2.6.2", features = ["test"] } -serde = { version = "1.0.219", features = ["derive"] } -serde_json = "1.0.140" +tauri = { version = "2" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" [target.'cfg(target_os = "android")'.dependencies] +# Stay on 0.21 — 0.22 EnvUnowned / GlobalRef breaks our JNI bridge. jni = "0.21" android-usb-serial = { path = "crates/android-usb-serial", version = "0.1.1" } -serialport = "4.9.0" +serialport = "4.10" log = { version = "0.4", features = ["std"] } [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] -serialport = "4.9.0" +serialport = "4.10" + +[dev-dependencies] +# `test` feature only for this crate's unit tests — keep it off the published dependency graph. +tauri = { version = "2", features = ["test"] } [profile.release] codegen-units = 1 diff --git a/LICENSE_APACHE-2.0 b/LICENSE-APACHE similarity index 100% rename from LICENSE_APACHE-2.0 rename to LICENSE-APACHE diff --git a/LICENSE_MIT b/LICENSE-MIT similarity index 94% rename from LICENSE_MIT rename to LICENSE-MIT index 4d754725..d4ea2efb 100755 --- a/LICENSE_MIT +++ b/LICENSE-MIT @@ -1,6 +1,7 @@ MIT License Copyright (c) 2017 - Present Tauri Apps Contributors +Copyright (c) 2024 - 2026 s00d and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +19,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 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. \ No newline at end of file +SOFTWARE. diff --git a/LICENSE.spdx b/LICENSE.spdx index cdd0df5a..8bb676d8 100755 --- a/LICENSE.spdx +++ b/LICENSE.spdx @@ -1,20 +1,17 @@ SPDXVersion: SPDX-2.1 DataLicense: CC0-1.0 -PackageName: tauri +PackageName: tauri-plugin-serialplugin DataFormat: SPDXRef-1 -PackageSupplier: Organization: The Tauri Programme in the Commons Conservancy -PackageHomePage: https://tauri.app +PackageSupplier: Person: s00d +PackageHomePage: https://github.com/s00d/tauri-plugin-serialplugin PackageLicenseDeclared: Apache-2.0 PackageLicenseDeclared: MIT -PackageCopyrightText: 2019-2022, The Tauri Programme in the Commons Conservancy -PackageSummary: Tauri is a rust project that enables developers to make secure -and small desktop applications using a web frontend. +PackageCopyrightText: 2017-Present Tauri Apps Contributors; 2024-2026 s00d and contributors +PackageSummary: Tauri plugin for serial port access on desktop and Android. -PackageComment: The package includes the following libraries; see -Relationship information. +PackageComment: Dual-licensed Apache-2.0 OR MIT. Upstream Tauri notice retained +for derivative code; see LICENSE-MIT and LICENSE-APACHE. -Created: 2019-05-20T09:00:00Z -PackageDownloadLocation: git://github.com/tauri-apps/tauri -PackageDownloadLocation: git+https://github.com/tauri-apps/tauri.git -PackageDownloadLocation: git+ssh://github.com/tauri-apps/tauri.git -Creator: Person: Daniel Thompson-Yvetot \ No newline at end of file +Created: 2024-02-04T00:00:00Z +PackageDownloadLocation: git+https://github.com/s00d/tauri-plugin-serialplugin.git +Creator: Person: s00d diff --git a/PUBLISHING.md b/PUBLISHING.md new file mode 100644 index 00000000..9c9f3a06 --- /dev/null +++ b/PUBLISHING.md @@ -0,0 +1,82 @@ +# Publishing + +Maintainer checklist. Everything registry-side uses **pnpm** (not mixed with `npm` CLI). + +## 1. Bump version + +Pick **one**: + +```bash +pnpm release:patch +pnpm release:minor +pnpm release:major +``` + +Each runs release-it: bumps `package.json` + `Cargo.toml`, updates `CHANGELOG.md`, commits, tags `v*`, pushes, creates a GitHub Release. + +## 2. Auth + +npm registry sessions expire often. Check and fix with pnpm only: + +```bash +pnpm whoami +# if that fails: +pnpm login +``` + +crates.io — either interactive login **or** a token env var: + +```bash +cargo login +# writes ~/.cargo/credentials.toml + +# CI / non-interactive alternative: +export CARGO_REGISTRY_TOKEN=... # from https://crates.io/settings/tokens +``` + +`scripts/publish.sh` accepts either the credentials file or `CARGO_REGISTRY_TOKEN`. + +## 3. Publish + +```bash +pnpm release:publish +``` + +What it does, in order: + +1. `pnpm whoami` — abort if logged out +2. cargo auth (`CARGO_REGISTRY_TOKEN` or `~/.cargo/credentials.toml`) +3. `pnpm install --frozen-lockfile` +4. build + pack surface check +5. `pnpm publish` → `tauri-plugin-serialplugin-api` +6. `cargo publish` → `tauri-plugin-serialplugin` + +Dry-run: + +```bash +./scripts/publish.sh --dry-run +``` + +Surface check only: + +```bash +pnpm publish:check +``` + +## android-usb-serial + +If you changed that crate’s version, publish it **before** the plugin crate: + +```bash +cargo publish -p android-usb-serial +# wait for crates.io index, then: +pnpm release:publish +``` + +## Packages + +| Registry | Package | Version file | +|-----------|---------------------------------|---------------------------------------------------| +| npm | `tauri-plugin-serialplugin-api` | `package.json` | +| crates.io | `tauri-plugin-serialplugin` | `Cargo.toml` (synced on bump) | +| crates.io | `android-usb-serial` | `crates/android-usb-serial/Cargo.toml` (manual) | diff --git a/README.md b/README.md index c92b63fc..24889b31 100755 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Legacy Tauri events (`plugin-serialplugin-read-*`) and Android plugin triggers ( | Option | Desktop | Android | |--------|---------|---------| | `timeout` | Batch coalescing window (ms) | Coalescing / flush hint where supported | -| `serialDataFlushIntervalMs` | Preferred batch interval; falls back to `timeout` | `BufferedEmitter` flush (10–2000 ms) | +| `serialDataFlushIntervalMs` | Preferred batch interval for hub `batch_timeout_ms` (falls back to `timeout`) | Same; clamped typically 10–2000 ms | | `size` | Read chunk size per syscall | Reserved | | `decode` | JS-only: `TextDecoder` on `onData` | JS-only | @@ -92,11 +92,10 @@ Legacy Tauri events (`plugin-serialplugin-read-*`) and Android plugin triggers ( 7.8. [Auto-Reconnect](#auto-reconnect-management) 8. [Common Use Cases](#common-use-cases) 9. [Android Setup](#android-setup) -10. [Contributing](#contributing) -11. [Development Setup](#development-setup) -12. [Testing](#testing) -13. [Partners](#partners) -14. [License](#license) +10. [Development Setup](#development-setup) +11. [Testing](#testing) +12. [Partners](#partners) +13. [License](#license) --- @@ -104,7 +103,7 @@ Legacy Tauri events (`plugin-serialplugin-read-*`) and Android plugin triggers ( ### Prerequisites -- **Rust** version 1.70 or higher +- **Rust** version 1.79 or higher (MSRV) - **Tauri** 2.0 or higher - **Node.js** and an npm-compatible package manager (npm, yarn, pnpm) @@ -876,7 +875,17 @@ use tauri_plugin_serialplugin::commands::{ capabilities, // Runtime info watch, // Stream events via Channel unwatch, // Stop watch session - cancel_read, // Cancel poll read or active watch (shared stop channel) + cancel_read, // Cancel in-flight poll read only (does not detach watch) + exchange, // Write + read-until + exchange_binary, // Binary exchange + cancel_exchange, // Cancel in-flight exchange / AT job + at, // Native AT queue command + at_phases, // Multi-phase AT job + send_sms_pdu, // CMGS PDU helper + configure_at_session, // AT session defaults + enable_mux, // Enter CMUX + open_mux_channel, // Open virtual CMUX channel + disable_mux, // Tear down CMUX // Port configuration set_baud_rate, // Set baud rate @@ -930,7 +939,7 @@ pub fn open( parity: Option, stop_bits: Option, timeout: Option, -) -> Result<(), Error> +) -> Result // canonical path (Android session key / desktop echo) // Write data pub fn write( @@ -1157,13 +1166,13 @@ class SerialPort { class SerialPort { /** * Opens the serial port with specified configuration - * @returns {Promise} + * @returns {Promise} Canonical path (Android re-keys to session path; desktop echoes input) * @throws {Error} If port is already open or invalid configuration * @example * const port = new SerialPort({ path: "COM1", baudRate: 9600 }); - * await port.open(); + * const canonical = await port.open(); */ - async open(): Promise; + async open(): Promise; /** * Closes the serial port connection @@ -1693,12 +1702,6 @@ See [`android/README.md`](android/README.md) and [`android/BUILD_INSTRUCTIONS.md --- -## Contributing - -Pull requests are welcome! Please read our contributing guidelines before you start. - ---- - ## Development Setup ```bash @@ -1749,6 +1752,18 @@ Use `watch()`, `exchange()`, and `sendAt()` against that path; unplugging the pe --- +## Contributing + +See [CONTRIBUTING.md](./CONTRIBUTING.md) for build, test, and PR guidelines. + +## Publishing + +See [PUBLISHING.md](./PUBLISHING.md) (`pnpm release:patch|minor|major` → `pnpm login` if needed → `pnpm release:publish`). + +## Security + +See [SECURITY.md](./SECURITY.md) to report vulnerabilities privately. + ## Partners If you find this plugin valuable and would like to support further development, feel free to donate via [DonationAlerts](https://www.donationalerts.com/r/s00d88). Any contribution is greatly appreciated! @@ -1757,4 +1772,4 @@ If you find this plugin valuable and would like to support further development, ## License -This code is dual-licensed under MIT or Apache-2.0, where applicable, © 2019–2025 Tauri Programme within The Commons Conservancy. +Dual-licensed under MIT or Apache-2.0. See [LICENSE-MIT](./LICENSE-MIT) and [LICENSE-APACHE](./LICENSE-APACHE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..230e13b0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,36 @@ +# Security Policy + +## Supported versions + +| Version | Supported | +|---------|-----------| +| 3.x | Yes | +| 2.x | Security fixes only, while practical | +| < 2.0 | No | + +## Reporting a vulnerability + +Please **do not** open a public GitHub issue for security reports. + +Prefer one of: + +1. [GitHub Security Advisories](https://github.com/s00d/tauri-plugin-serialplugin/security/advisories/new) (private report) +2. Email the maintainer listed on [npm](https://www.npmjs.com/package/tauri-plugin-serialplugin-api) / GitHub profile for `s00d` + +Include: + +- Affected version(s) and platform (desktop OS / Android) +- Impact (e.g. unexpected port access, crash, data exposure) +- Minimal reproduction or PoC if you have one +- Whether you are OK being credited + +You should get an acknowledgement within a few days. Coordinated disclosure is preferred; we will work with you on a fix and release timeline. + +## Scope notes + +This plugin talks to local serial / USB serial devices. Reports about: + +- ACL / capability misconfiguration in *consumer apps* (missing `allow-*` permissions) +- Bugs in third-party USB chipset drivers outside this repo + +…are often application or hardware issues rather than vulnerabilities in the plugin itself — still feel free to report if unsure. diff --git a/android/src/main/kotlin/app/tauri/serialplugin/MobileBridge.kt b/android/src/main/kotlin/app/tauri/serialplugin/MobileBridge.kt index 123be022..3b8ba779 100644 --- a/android/src/main/kotlin/app/tauri/serialplugin/MobileBridge.kt +++ b/android/src/main/kotlin/app/tauri/serialplugin/MobileBridge.kt @@ -56,4 +56,12 @@ object MobileBridge { /** Debug-only: fail the next bulk-IN read (reader → onUsbError). */ @JvmStatic external fun testFakeInjectError(deviceName: String, reason: String): Boolean + + /** Debug-only: install AT exchange waiter on the hub for [path]. */ + @JvmStatic + external fun testExchangeBegin(path: String, command: String): Boolean + + /** Debug-only: wait for harness exchange; returns `OK:…` or `ERR:…`. */ + @JvmStatic + external fun testExchangeWait(path: String, timeoutMs: Long): String } diff --git a/android/src/main/kotlin/app/tauri/serialplugin/manager/UsbFdBridge.kt b/android/src/main/kotlin/app/tauri/serialplugin/manager/UsbFdBridge.kt index 3b0aea6a..335d2d80 100644 --- a/android/src/main/kotlin/app/tauri/serialplugin/manager/UsbFdBridge.kt +++ b/android/src/main/kotlin/app/tauri/serialplugin/manager/UsbFdBridge.kt @@ -68,6 +68,9 @@ class UsbFdBridge private constructor( @Volatile private var shutDown = false + /** Permission wait budget; short in testMode so denied/timeout tests stay fast. */ + @Volatile private var permissionWaitMs: Long = if (testMode) 200L else 30_000L + private val ioExecutor: Executor = if (testMode) { Executor { it.run() } } else { @@ -76,6 +79,7 @@ class UsbFdBridge private constructor( private val usbManager = context?.getSystemService(Context.USB_SERVICE) as? UsbManager private val connections = ConcurrentHashMap() private val permissionFutures = ConcurrentHashMap>() + private val permissionLock = Any() private val usbReceiver = object : BroadcastReceiver() { override fun onReceive(ctx: Context, intent: Intent) { @@ -128,7 +132,29 @@ class UsbFdBridge private constructor( permissionFutures[deviceName]?.complete(granted) } + /** + * Test-only: stretch [requestPermission] wait so shutdown can be asserted to + * unblock before the timeout (default test wait is 200ms). + */ + fun setPermissionWaitMsForTest(ms: Long) { + check(testMode) + permissionWaitMs = ms + } + + /** Fail any in-flight permission waits so blocked IO threads can exit. */ + private fun failPendingPermissionsLocked() { + permissionFutures.keys.toList().forEach { name -> + permissionFutures.remove(name)?.complete(false) + } + } + fun shutdown() { + // Flip + drain under the same lock as future registration so a waiter + // cannot insert after failPendingPermissions and then block for 30s. + synchronized(permissionLock) { + shutDown = true + failPendingPermissionsLocked() + } if (testMode) { connections.keys.toList().forEach { closeDeviceFd(it) } if (registerReceiver && context != null) { @@ -139,7 +165,6 @@ class UsbFdBridge private constructor( } return } - shutDown = true val pool = ioExecutor as ExecutorService val ctx = context val shouldUnregister = registerReceiver @@ -199,6 +224,7 @@ class UsbFdBridge private constructor( } fun openDeviceFd(deviceName: String): Int { + if (shutDown) throw IOException("USB fd bridge shut down") connections[deviceName]?.let { Log.i(TAG, "openDeviceFd reuse $deviceName fd=${it.fileDescriptor}") return it.fileDescriptor @@ -207,6 +233,7 @@ class UsbFdBridge private constructor( val device = mgr.deviceList.values.find { it.deviceName == deviceName } ?: throw IOException("device not found: $deviceName") if (!mgr.hasPermission(device)) requestPermission(device) + if (shutDown) throw IOException("USB fd bridge shut down") // Do NOT claimInterface here — Rust nusb detach_and_claim owns claiming. // Pre-claim makes the same fd report "io interface is busy" on open. val conn = mgr.openDevice(device) ?: throw IOException("open failed: $deviceName") @@ -262,7 +289,10 @@ class UsbFdBridge private constructor( val ctx = context ?: throw IOException("no context") val name = device.deviceName val fut = CompletableFuture() - permissionFutures[name] = fut + synchronized(permissionLock) { + if (shutDown) throw IOException("USB fd bridge shut down") + permissionFutures[name] = fut + } val intent = Intent(ACTION_USB_PERMISSION).apply { setPackage(ctx.packageName) } @@ -273,15 +303,16 @@ class UsbFdBridge private constructor( } val pi = PendingIntent.getBroadcast(ctx, 0, intent, flags) mgr.requestPermission(device, pi) + // Wait budget: short in normal tests; production / stretched tests use 30s. + // shutdown()'s failPendingPermissions completes the future early. val granted = try { - if (testMode) { - fut.get(200, TimeUnit.MILLISECONDS) - } else { - fut.get(30, TimeUnit.SECONDS) - } + fut.get(permissionWaitMs, TimeUnit.MILLISECONDS) } catch (_: TimeoutException) { false + } finally { + permissionFutures.remove(name, fut) } + if (shutDown) throw IOException("USB fd bridge shut down") if (!granted) { throw IOException("USB permission denied for $name") } diff --git a/android/src/test/kotlin/app/tauri/serialplugin/manager/UsbFdBridgeTest.kt b/android/src/test/kotlin/app/tauri/serialplugin/manager/UsbFdBridgeTest.kt index bfc59089..a07c7d24 100644 --- a/android/src/test/kotlin/app/tauri/serialplugin/manager/UsbFdBridgeTest.kt +++ b/android/src/test/kotlin/app/tauri/serialplugin/manager/UsbFdBridgeTest.kt @@ -249,4 +249,86 @@ class UsbFdBridgeTest { assertEquals(55, harness.bridge.openDeviceFd(DEVICE)) verify(harness.usbManager, times(1)).openDevice(device) } + + @Test + fun openDeviceFd_doubleGrantWhileWaiting() { + val harness = usbHarness() + val device = mockDevice() + stubDeviceList(harness.usbManager, device) + whenever(harness.usbManager.hasPermission(device)).thenReturn(false) + val conn = mockConn(77) + whenever(harness.usbManager.openDevice(device)).thenReturn(conn) + doAnswer { + harness.bridge.completePermissionForTest(DEVICE, true) + harness.bridge.completePermissionForTest(DEVICE, true) + null + }.whenever(harness.usbManager).requestPermission(eq(device), any()) + + assertEquals(77, harness.bridge.openDeviceFd(DEVICE)) + } + + @Test + fun openDeviceFd_afterDeny_retrySucceeds() { + val harness = usbHarness() + val device = mockDevice() + stubDeviceList(harness.usbManager, device) + whenever(harness.usbManager.hasPermission(device)).thenReturn(false) + val conn = mockConn(88) + whenever(harness.usbManager.openDevice(device)).thenReturn(conn) + + var grant = false + doAnswer { + harness.bridge.completePermissionForTest(DEVICE, grant) + null + }.whenever(harness.usbManager).requestPermission(eq(device), any()) + + val denied = assertThrows(IOException::class.java) { + harness.bridge.openDeviceFd(DEVICE) + } + assertTrue(denied.message!!.contains("permission denied")) + + grant = true + assertEquals(88, harness.bridge.openDeviceFd(DEVICE)) + } + + @Test + fun openDeviceFd_shutdownDuringPermissionWait() { + val harness = usbHarness() + harness.bridge.setPermissionWaitMsForTest(30_000) + val device = mockDevice() + stubDeviceList(harness.usbManager, device) + whenever(harness.usbManager.hasPermission(device)).thenReturn(false) + + val err = java.util.concurrent.atomic.AtomicReference() + val started = java.util.concurrent.CountDownLatch(1) + doAnswer { + started.countDown() + null + }.whenever(harness.usbManager).requestPermission(eq(device), any()) + + val t = Thread { + try { + harness.bridge.openDeviceFd(DEVICE) + } catch (e: Throwable) { + err.set(e) + } + } + t.start() + assertTrue(started.await(2, java.util.concurrent.TimeUnit.SECONDS)) + val t0 = System.nanoTime() + harness.bridge.shutdown() + t.join(3000) + val elapsedMs = (System.nanoTime() - t0) / 1_000_000 + assertTrue("worker should finish from shutdown alone", !t.isAlive) + assertTrue( + "shutdown should unblock well under the 30s permission wait (took ${elapsedMs}ms)", + elapsedMs < 2000, + ) + assertTrue(err.get() is IOException) + val msg = err.get()!!.message!! + assertTrue( + "expected shutdown or permission denial, got: $msg", + msg.contains("permission denied") || msg.contains("shut down"), + ) + } } diff --git a/crates/android-usb-serial/Cargo.toml b/crates/android-usb-serial/Cargo.toml index 3a7aa491..5fcd2907 100644 --- a/crates/android-usb-serial/Cargo.toml +++ b/crates/android-usb-serial/Cargo.toml @@ -44,11 +44,11 @@ version = "1.0" optional = true [dependencies.base64] -version = "0.22" +version = "0.23" optional = true [dependencies.serialport] -version = "4.9" +version = "4.10" optional = true [target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] @@ -58,7 +58,7 @@ libc = "0.2" [dev-dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -base64 = "0.22" +base64 = "0.23" [[bin]] name = "golden_record" diff --git a/crates/android-usb-serial/LICENSE-MIT b/crates/android-usb-serial/LICENSE-MIT index 4d754725..d4ea2efb 100755 --- a/crates/android-usb-serial/LICENSE-MIT +++ b/crates/android-usb-serial/LICENSE-MIT @@ -1,6 +1,7 @@ MIT License Copyright (c) 2017 - Present Tauri Apps Contributors +Copyright (c) 2024 - 2026 s00d and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +19,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 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. \ No newline at end of file +SOFTWARE. diff --git a/crates/android-usb-serial/tests/golden_parity.rs b/crates/android-usb-serial/tests/golden_parity.rs index 399d6c82..5bdec7c2 100644 --- a/crates/android-usb-serial/tests/golden_parity.rs +++ b/crates/android-usb-serial/tests/golden_parity.rs @@ -445,6 +445,33 @@ fn assert_controls(path: &Path, got: &[RecordedControl], want: &[GoldenControl]) } } +#[test] +fn golden_negative_invalid_fixture_json_errors() { + let err = serde_json::from_str::("{not-valid-json"); + assert!(err.is_err(), "corrupt JSON must fail to parse"); +} + +#[test] +fn golden_negative_corrupt_expected_control_bytes_mismatch() { + let path = fixture_dir().join("ch34x/set_baud_9600.json"); + let text = fs::read_to_string(&path).expect("read fixture"); + let mut fixture: GoldenFixture = serde_json::from_str(&text).expect("parse fixture"); + assert!(!fixture.controls.is_empty()); + // Corrupt expected control payload so parity assertion must fail. + fixture.controls[0].data = base64::engine::general_purpose::STANDARD.encode([1, 2, 3]); + let fake = setup_fake(&fixture); + let transport: Arc = Arc::new(fake.clone()); + let mut driver = create_driver(driver_type(&fixture.driver), fixture.port_index); + driver.open(&transport).expect("open"); + let suffix = scenario_suffix(&fixture); + let _ = replay_scenario(driver.as_mut(), &fixture.driver, &suffix); + let _ = driver.close(); + assert!( + !controls_match(&fake.recorded_controls(), &fixture.controls), + "corrupted expected control bytes must not match recorded transfers" + ); +} + fn format_bulk_diff(path: &Path, got: &[RecordedBulkOut], want: &[GoldenBulkOut]) -> String { let mut out = format!( "bulkOut mismatch for {}: got {} want {}\n", diff --git a/examples/serialport-test/android-integration/src/androidTest/kotlin/com/serialport/test/jni/ExchangeChainTest.kt b/examples/serialport-test/android-integration/src/androidTest/kotlin/com/serialport/test/jni/ExchangeChainTest.kt new file mode 100644 index 00000000..f40c3723 --- /dev/null +++ b/examples/serialport-test/android-integration/src/androidTest/kotlin/com/serialport/test/jni/ExchangeChainTest.kt @@ -0,0 +1,32 @@ +package com.serialport.test.jni + +import app.tauri.serialplugin.MobileBridge +import org.junit.After +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import androidx.test.ext.junit.runners.AndroidJUnit4 + +@RunWith(AndroidJUnit4::class) +class ExchangeChainTest { + + @Before + fun setUp() = JniChainFixture.setUp() + + @After + fun tearDown() = JniChainFixture.tearDown() + + @Test + fun exchange_at_csq_with_urc_creg_completes_ok() { + assertTrue( + MobileBridge.testExchangeBegin(JniChainFixture.sessionPath, "AT+CSQ"), + ) + MobileBridge.testFakeInjectRx( + JniChainFixture.DEVICE_NAME, + "\r\n+CREG: 0,1\r\n\r\nAT+CSQ\r\n\r\n+CSQ: 10,99\r\n\r\nOK\r\n".toByteArray(), + ) + val result = MobileBridge.testExchangeWait(JniChainFixture.sessionPath, 10_000) + assertTrue("expected OK exchange, got $result", result.startsWith("OK:")) + } +} diff --git a/examples/serialport-test/android-integration/src/androidTest/kotlin/com/serialport/test/jni/UsbErrorChainTest.kt b/examples/serialport-test/android-integration/src/androidTest/kotlin/com/serialport/test/jni/UsbErrorChainTest.kt index 09777bd5..990d863d 100644 --- a/examples/serialport-test/android-integration/src/androidTest/kotlin/com/serialport/test/jni/UsbErrorChainTest.kt +++ b/examples/serialport-test/android-integration/src/androidTest/kotlin/com/serialport/test/jni/UsbErrorChainTest.kt @@ -22,7 +22,13 @@ class UsbErrorChainTest { fun fake_read_error_clears_registry() { assertTrue(MobileBridge.testRegistryHasPort(JniChainFixture.sessionPath)) MobileBridge.testFakeInjectError(JniChainFixture.DEVICE_NAME, "device exploded") - Thread.sleep(1500) + val deadline = System.nanoTime() + 5_000_000_000L + while (System.nanoTime() < deadline) { + if (!MobileBridge.testRegistryHasPort(JniChainFixture.sessionPath)) { + return + } + Thread.sleep(20) + } assertFalse( "registry should drop port after reader error → onUsbError", MobileBridge.testRegistryHasPort(JniChainFixture.sessionPath), diff --git a/examples/serialport-test/src-tauri/Cargo.lock b/examples/serialport-test/src-tauri/Cargo.lock index 2a686068..49aabe44 100644 --- a/examples/serialport-test/src-tauri/Cargo.lock +++ b/examples/serialport-test/src-tauri/Cargo.lock @@ -51,7 +51,7 @@ checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" name = "android-usb-serial" version = "0.1.1" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "libc", "log", "nusb", @@ -209,6 +209,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "bitflags" version = "1.3.2" @@ -1743,19 +1749,68 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.0", "log", "thiserror 1.0.68", "walkdir", "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.12", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.87", +] + [[package]] name = "jni-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.87", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -2070,7 +2125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ "bitflags 2.6.0", - "jni-sys", + "jni-sys 0.3.0", "log", "ndk-sys", "num_enum", @@ -2090,7 +2145,7 @@ version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "jni-sys", + "jni-sys 0.3.0", ] [[package]] @@ -3334,9 +3389,9 @@ dependencies = [ [[package]] name = "serialport" -version = "4.9.0" +version = "4.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d91116f97173694f1642263b2ff837f80d933aa837e2314969f6728f661df3" +checksum = "6a2f4ac56b5d3af3c40fbbee17be96d532cba02fa5853926aacdb77d926272ab" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -3400,6 +3455,22 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "0.3.11" @@ -3592,7 +3663,7 @@ dependencies = [ "gdkwayland-sys", "gdkx11-sys", "gtk", - "jni", + "jni 0.21.1", "lazy_static", "libc", "log", @@ -3648,7 +3719,7 @@ dependencies = [ "gtk", "heck 0.5.0", "http 1.1.0", - "jni", + "jni 0.21.1", "libc", "log", "mime", @@ -3795,7 +3866,7 @@ name = "tauri-plugin-serialplugin" version = "3.0.4" dependencies = [ "android-usb-serial", - "jni", + "jni 0.22.4", "log", "serde", "serde_json", @@ -3814,7 +3885,7 @@ dependencies = [ "dpi", "gtk", "http 1.1.0", - "jni", + "jni 0.21.1", "objc2 0.6.0", "objc2-ui-kit", "raw-window-handle", @@ -3834,7 +3905,7 @@ checksum = "902b5aa9035e16f342eb64f8bf06ccdc2808e411a2525ed1d07672fa4e780bad" dependencies = [ "gtk", "http 1.1.0", - "jni", + "jni 0.21.1", "log", "objc2 0.6.0", "objc2-app-kit 0.3.0", @@ -5160,7 +5231,7 @@ dependencies = [ "html5ever", "http 1.1.0", "javascriptcore-rs", - "jni", + "jni 0.21.1", "kuchikiki", "libc", "ndk", diff --git a/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/ExchangeChainTest.kt b/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/ExchangeChainTest.kt new file mode 100644 index 00000000..f40c3723 --- /dev/null +++ b/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/ExchangeChainTest.kt @@ -0,0 +1,32 @@ +package com.serialport.test.jni + +import app.tauri.serialplugin.MobileBridge +import org.junit.After +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import androidx.test.ext.junit.runners.AndroidJUnit4 + +@RunWith(AndroidJUnit4::class) +class ExchangeChainTest { + + @Before + fun setUp() = JniChainFixture.setUp() + + @After + fun tearDown() = JniChainFixture.tearDown() + + @Test + fun exchange_at_csq_with_urc_creg_completes_ok() { + assertTrue( + MobileBridge.testExchangeBegin(JniChainFixture.sessionPath, "AT+CSQ"), + ) + MobileBridge.testFakeInjectRx( + JniChainFixture.DEVICE_NAME, + "\r\n+CREG: 0,1\r\n\r\nAT+CSQ\r\n\r\n+CSQ: 10,99\r\n\r\nOK\r\n".toByteArray(), + ) + val result = MobileBridge.testExchangeWait(JniChainFixture.sessionPath, 10_000) + assertTrue("expected OK exchange, got $result", result.startsWith("OK:")) + } +} diff --git a/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/UsbDetachChainTest.kt b/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/UsbDetachChainTest.kt new file mode 100644 index 00000000..40b2ed17 --- /dev/null +++ b/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/UsbDetachChainTest.kt @@ -0,0 +1,30 @@ +package com.serialport.test.jni + +import app.tauri.serialplugin.MobileBridge +import org.junit.After +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import androidx.test.ext.junit.runners.AndroidJUnit4 + +@RunWith(AndroidJUnit4::class) +class UsbDetachChainTest { + + @Before + fun setUp() = JniChainFixture.setUp() + + @After + fun tearDown() = JniChainFixture.tearDown() + + @Test + fun detach_clears_registry() { + assertTrue(MobileBridge.testRegistryHasPort(JniChainFixture.sessionPath)) + MobileBridge.onDeviceDetached(JniChainFixture.DEVICE_NAME) + assertFalse( + "registry should drop port after USB detach", + MobileBridge.testRegistryHasPort(JniChainFixture.sessionPath), + ) + } +} diff --git a/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/UsbErrorChainTest.kt b/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/UsbErrorChainTest.kt index 09777bd5..990d863d 100644 --- a/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/UsbErrorChainTest.kt +++ b/examples/serialport-test/src-tauri/gen/android/app/src/androidTest/kotlin/com/serialport/test/jni/UsbErrorChainTest.kt @@ -22,7 +22,13 @@ class UsbErrorChainTest { fun fake_read_error_clears_registry() { assertTrue(MobileBridge.testRegistryHasPort(JniChainFixture.sessionPath)) MobileBridge.testFakeInjectError(JniChainFixture.DEVICE_NAME, "device exploded") - Thread.sleep(1500) + val deadline = System.nanoTime() + 5_000_000_000L + while (System.nanoTime() < deadline) { + if (!MobileBridge.testRegistryHasPort(JniChainFixture.sessionPath)) { + return + } + Thread.sleep(20) + } assertFalse( "registry should drop port after reader error → onUsbError", MobileBridge.testRegistryHasPort(JniChainFixture.sessionPath), diff --git a/examples/serialport-test/src/components/StatusBar.vue b/examples/serialport-test/src/components/StatusBar.vue index d63fc9d2..9e853c89 100644 --- a/examples/serialport-test/src/components/StatusBar.vue +++ b/examples/serialport-test/src/components/StatusBar.vue @@ -1,10 +1,10 @@