├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── install.sh ├── readme.md └── src ├── main.rs ├── terminal ├── buffer.rs ├── handlers.rs ├── mod.rs └── types.rs ├── updates.rs └── utils └── mod.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: ["*"] 6 | pull_request: 7 | branches: ["*"] 8 | workflow_dispatch: 9 | 10 | jobs: 11 | lint: 12 | name: Lint & Format 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v3 17 | 18 | - name: Install Rust toolchain 19 | uses: dtolnay/rust-toolchain@stable 20 | with: 21 | components: clippy, rustfmt 22 | 23 | - name: Run Clippy 24 | run: cargo clippy --all-targets --all-features -- -D warnings 25 | 26 | - name: Check formatting 27 | run: cargo fmt --all -- --check 28 | 29 | test: 30 | name: Test 31 | runs-on: ubuntu-latest 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v3 35 | 36 | - name: Install Rust toolchain 37 | uses: dtolnay/rust-toolchain@stable 38 | 39 | - name: Run tests 40 | run: cargo test 41 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - "v*" 8 | 9 | permissions: 10 | contents: write 11 | 12 | jobs: 13 | build: 14 | name: Build ${{ matrix.platform.os_name }} 15 | runs-on: ubuntu-latest 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | platform: 20 | - os_name: Android-aarch64 21 | target: aarch64-linux-android 22 | binary_name: axs-android-arm64 23 | - os_name: Android-armv7 24 | target: armv7-linux-androideabi 25 | binary_name: axs-android-armv7 26 | - os_name: Android-x86_64 27 | target: x86_64-linux-android 28 | binary_name: axs-android-x86_64 29 | toolchain: 30 | - stable 31 | 32 | steps: 33 | - name: Checkout repository 34 | uses: actions/checkout@v3 35 | 36 | - name: Install cross 37 | run: cargo install cross --git https://github.com/cross-rs/cross.git --branch main 38 | 39 | - name: Add Rust target 40 | run: rustup target add ${{ matrix.platform.target }} 41 | 42 | - name: Build binary with cross 43 | run: cross build --release --target ${{ matrix.platform.target }} 44 | 45 | - name: Rename binary 46 | run: mv target/${{ matrix.platform.target }}/release/axs target/${{ matrix.platform.target }}/release/${{ matrix.platform.binary_name }} 47 | 48 | - name: Generate SHA-256 49 | run: | 50 | cd target/${{ matrix.platform.target }}/release 51 | sha256sum ${{ matrix.platform.binary_name }} > ${{ matrix.platform.binary_name }}.sha256 52 | 53 | - name: Upload artifacts 54 | uses: softprops/action-gh-release@v1 55 | with: 56 | files: | 57 | target/${{ matrix.platform.target }}/release/${{ matrix.platform.binary_name }} 58 | target/${{ matrix.platform.target }}/release/${{ matrix.platform.binary_name }}.sha256 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "anstream" 31 | version = "0.6.18" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 34 | dependencies = [ 35 | "anstyle", 36 | "anstyle-parse", 37 | "anstyle-query", 38 | "anstyle-wincon", 39 | "colorchoice", 40 | "is_terminal_polyfill", 41 | "utf8parse", 42 | ] 43 | 44 | [[package]] 45 | name = "anstyle" 46 | version = "1.0.10" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 49 | 50 | [[package]] 51 | name = "anstyle-parse" 52 | version = "0.2.6" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 55 | dependencies = [ 56 | "utf8parse", 57 | ] 58 | 59 | [[package]] 60 | name = "anstyle-query" 61 | version = "1.1.2" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 64 | dependencies = [ 65 | "windows-sys 0.59.0", 66 | ] 67 | 68 | [[package]] 69 | name = "anstyle-wincon" 70 | version = "3.0.7" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" 73 | dependencies = [ 74 | "anstyle", 75 | "once_cell", 76 | "windows-sys 0.59.0", 77 | ] 78 | 79 | [[package]] 80 | name = "anyhow" 81 | version = "1.0.97" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" 84 | 85 | [[package]] 86 | name = "autocfg" 87 | version = "1.4.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 90 | 91 | [[package]] 92 | name = "axs" 93 | version = "0.2.2" 94 | dependencies = [ 95 | "axum", 96 | "clap", 97 | "colored", 98 | "futures", 99 | "pnet", 100 | "portable-pty", 101 | "regex", 102 | "reqwest", 103 | "semver", 104 | "serde", 105 | "serde_json", 106 | "tokio", 107 | "tower-http", 108 | "tracing", 109 | "tracing-subscriber", 110 | ] 111 | 112 | [[package]] 113 | name = "axum" 114 | version = "0.8.3" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "de45108900e1f9b9242f7f2e254aa3e2c029c921c258fe9e6b4217eeebd54288" 117 | dependencies = [ 118 | "axum-core", 119 | "base64", 120 | "bytes", 121 | "form_urlencoded", 122 | "futures-util", 123 | "http", 124 | "http-body", 125 | "http-body-util", 126 | "hyper", 127 | "hyper-util", 128 | "itoa", 129 | "matchit", 130 | "memchr", 131 | "mime", 132 | "percent-encoding", 133 | "pin-project-lite", 134 | "rustversion", 135 | "serde", 136 | "serde_json", 137 | "serde_path_to_error", 138 | "serde_urlencoded", 139 | "sha1", 140 | "sync_wrapper", 141 | "tokio", 142 | "tokio-tungstenite", 143 | "tower", 144 | "tower-layer", 145 | "tower-service", 146 | "tracing", 147 | ] 148 | 149 | [[package]] 150 | name = "axum-core" 151 | version = "0.5.2" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" 154 | dependencies = [ 155 | "bytes", 156 | "futures-core", 157 | "http", 158 | "http-body", 159 | "http-body-util", 160 | "mime", 161 | "pin-project-lite", 162 | "rustversion", 163 | "sync_wrapper", 164 | "tower-layer", 165 | "tower-service", 166 | "tracing", 167 | ] 168 | 169 | [[package]] 170 | name = "backtrace" 171 | version = "0.3.74" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 174 | dependencies = [ 175 | "addr2line", 176 | "cfg-if", 177 | "libc", 178 | "miniz_oxide", 179 | "object", 180 | "rustc-demangle", 181 | "windows-targets 0.52.6", 182 | ] 183 | 184 | [[package]] 185 | name = "base64" 186 | version = "0.22.1" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 189 | 190 | [[package]] 191 | name = "bitflags" 192 | version = "1.3.2" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 195 | 196 | [[package]] 197 | name = "bitflags" 198 | version = "2.9.0" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 201 | 202 | [[package]] 203 | name = "block-buffer" 204 | version = "0.10.4" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 207 | dependencies = [ 208 | "generic-array", 209 | ] 210 | 211 | [[package]] 212 | name = "bumpalo" 213 | version = "3.17.0" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 216 | 217 | [[package]] 218 | name = "bytes" 219 | version = "1.10.1" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 222 | 223 | [[package]] 224 | name = "cc" 225 | version = "1.2.18" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" 228 | dependencies = [ 229 | "shlex", 230 | ] 231 | 232 | [[package]] 233 | name = "cfg-if" 234 | version = "1.0.0" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 237 | 238 | [[package]] 239 | name = "cfg_aliases" 240 | version = "0.1.1" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" 243 | 244 | [[package]] 245 | name = "cfg_aliases" 246 | version = "0.2.1" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 249 | 250 | [[package]] 251 | name = "clap" 252 | version = "4.5.35" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" 255 | dependencies = [ 256 | "clap_builder", 257 | "clap_derive", 258 | ] 259 | 260 | [[package]] 261 | name = "clap_builder" 262 | version = "4.5.35" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" 265 | dependencies = [ 266 | "anstream", 267 | "anstyle", 268 | "clap_lex", 269 | "strsim", 270 | ] 271 | 272 | [[package]] 273 | name = "clap_derive" 274 | version = "4.5.32" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" 277 | dependencies = [ 278 | "heck", 279 | "proc-macro2", 280 | "quote", 281 | "syn", 282 | ] 283 | 284 | [[package]] 285 | name = "clap_lex" 286 | version = "0.7.4" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 289 | 290 | [[package]] 291 | name = "colorchoice" 292 | version = "1.0.3" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 295 | 296 | [[package]] 297 | name = "colored" 298 | version = "3.0.0" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" 301 | dependencies = [ 302 | "windows-sys 0.59.0", 303 | ] 304 | 305 | [[package]] 306 | name = "cpufeatures" 307 | version = "0.2.17" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 310 | dependencies = [ 311 | "libc", 312 | ] 313 | 314 | [[package]] 315 | name = "crypto-common" 316 | version = "0.1.6" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 319 | dependencies = [ 320 | "generic-array", 321 | "typenum", 322 | ] 323 | 324 | [[package]] 325 | name = "data-encoding" 326 | version = "2.8.0" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" 329 | 330 | [[package]] 331 | name = "digest" 332 | version = "0.10.7" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 335 | dependencies = [ 336 | "block-buffer", 337 | "crypto-common", 338 | ] 339 | 340 | [[package]] 341 | name = "displaydoc" 342 | version = "0.2.5" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 345 | dependencies = [ 346 | "proc-macro2", 347 | "quote", 348 | "syn", 349 | ] 350 | 351 | [[package]] 352 | name = "downcast-rs" 353 | version = "1.2.1" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" 356 | 357 | [[package]] 358 | name = "filedescriptor" 359 | version = "0.8.3" 360 | source = "git+https://github.com/wez/wezterm?rev=1e941fca5c17155b5f64a74221a396ef12ef71d0#1e941fca5c17155b5f64a74221a396ef12ef71d0" 361 | dependencies = [ 362 | "libc", 363 | "thiserror 1.0.69", 364 | "winapi", 365 | ] 366 | 367 | [[package]] 368 | name = "fnv" 369 | version = "1.0.7" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 372 | 373 | [[package]] 374 | name = "form_urlencoded" 375 | version = "1.2.1" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 378 | dependencies = [ 379 | "percent-encoding", 380 | ] 381 | 382 | [[package]] 383 | name = "futures" 384 | version = "0.3.31" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 387 | dependencies = [ 388 | "futures-channel", 389 | "futures-core", 390 | "futures-executor", 391 | "futures-io", 392 | "futures-sink", 393 | "futures-task", 394 | "futures-util", 395 | ] 396 | 397 | [[package]] 398 | name = "futures-channel" 399 | version = "0.3.31" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 402 | dependencies = [ 403 | "futures-core", 404 | "futures-sink", 405 | ] 406 | 407 | [[package]] 408 | name = "futures-core" 409 | version = "0.3.31" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 412 | 413 | [[package]] 414 | name = "futures-executor" 415 | version = "0.3.31" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 418 | dependencies = [ 419 | "futures-core", 420 | "futures-task", 421 | "futures-util", 422 | ] 423 | 424 | [[package]] 425 | name = "futures-io" 426 | version = "0.3.31" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 429 | 430 | [[package]] 431 | name = "futures-macro" 432 | version = "0.3.31" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 435 | dependencies = [ 436 | "proc-macro2", 437 | "quote", 438 | "syn", 439 | ] 440 | 441 | [[package]] 442 | name = "futures-sink" 443 | version = "0.3.31" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 446 | 447 | [[package]] 448 | name = "futures-task" 449 | version = "0.3.31" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 452 | 453 | [[package]] 454 | name = "futures-util" 455 | version = "0.3.31" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 458 | dependencies = [ 459 | "futures-channel", 460 | "futures-core", 461 | "futures-io", 462 | "futures-macro", 463 | "futures-sink", 464 | "futures-task", 465 | "memchr", 466 | "pin-project-lite", 467 | "pin-utils", 468 | "slab", 469 | ] 470 | 471 | [[package]] 472 | name = "generic-array" 473 | version = "0.14.7" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 476 | dependencies = [ 477 | "typenum", 478 | "version_check", 479 | ] 480 | 481 | [[package]] 482 | name = "getrandom" 483 | version = "0.2.15" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 486 | dependencies = [ 487 | "cfg-if", 488 | "js-sys", 489 | "libc", 490 | "wasi 0.11.0+wasi-snapshot-preview1", 491 | "wasm-bindgen", 492 | ] 493 | 494 | [[package]] 495 | name = "getrandom" 496 | version = "0.3.2" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" 499 | dependencies = [ 500 | "cfg-if", 501 | "js-sys", 502 | "libc", 503 | "r-efi", 504 | "wasi 0.14.2+wasi-0.2.4", 505 | "wasm-bindgen", 506 | ] 507 | 508 | [[package]] 509 | name = "gimli" 510 | version = "0.31.1" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 513 | 514 | [[package]] 515 | name = "glob" 516 | version = "0.3.2" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" 519 | 520 | [[package]] 521 | name = "heck" 522 | version = "0.5.0" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 525 | 526 | [[package]] 527 | name = "http" 528 | version = "1.3.1" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 531 | dependencies = [ 532 | "bytes", 533 | "fnv", 534 | "itoa", 535 | ] 536 | 537 | [[package]] 538 | name = "http-body" 539 | version = "1.0.1" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 542 | dependencies = [ 543 | "bytes", 544 | "http", 545 | ] 546 | 547 | [[package]] 548 | name = "http-body-util" 549 | version = "0.1.3" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 552 | dependencies = [ 553 | "bytes", 554 | "futures-core", 555 | "http", 556 | "http-body", 557 | "pin-project-lite", 558 | ] 559 | 560 | [[package]] 561 | name = "httparse" 562 | version = "1.10.1" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 565 | 566 | [[package]] 567 | name = "httpdate" 568 | version = "1.0.3" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 571 | 572 | [[package]] 573 | name = "hyper" 574 | version = "1.6.0" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 577 | dependencies = [ 578 | "bytes", 579 | "futures-channel", 580 | "futures-util", 581 | "http", 582 | "http-body", 583 | "httparse", 584 | "httpdate", 585 | "itoa", 586 | "pin-project-lite", 587 | "smallvec", 588 | "tokio", 589 | "want", 590 | ] 591 | 592 | [[package]] 593 | name = "hyper-rustls" 594 | version = "0.27.5" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" 597 | dependencies = [ 598 | "futures-util", 599 | "http", 600 | "hyper", 601 | "hyper-util", 602 | "rustls", 603 | "rustls-pki-types", 604 | "tokio", 605 | "tokio-rustls", 606 | "tower-service", 607 | "webpki-roots", 608 | ] 609 | 610 | [[package]] 611 | name = "hyper-util" 612 | version = "0.1.11" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" 615 | dependencies = [ 616 | "bytes", 617 | "futures-channel", 618 | "futures-util", 619 | "http", 620 | "http-body", 621 | "hyper", 622 | "libc", 623 | "pin-project-lite", 624 | "socket2", 625 | "tokio", 626 | "tower-service", 627 | "tracing", 628 | ] 629 | 630 | [[package]] 631 | name = "icu_collections" 632 | version = "1.5.0" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 635 | dependencies = [ 636 | "displaydoc", 637 | "yoke", 638 | "zerofrom", 639 | "zerovec", 640 | ] 641 | 642 | [[package]] 643 | name = "icu_locid" 644 | version = "1.5.0" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 647 | dependencies = [ 648 | "displaydoc", 649 | "litemap", 650 | "tinystr", 651 | "writeable", 652 | "zerovec", 653 | ] 654 | 655 | [[package]] 656 | name = "icu_locid_transform" 657 | version = "1.5.0" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 660 | dependencies = [ 661 | "displaydoc", 662 | "icu_locid", 663 | "icu_locid_transform_data", 664 | "icu_provider", 665 | "tinystr", 666 | "zerovec", 667 | ] 668 | 669 | [[package]] 670 | name = "icu_locid_transform_data" 671 | version = "1.5.1" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" 674 | 675 | [[package]] 676 | name = "icu_normalizer" 677 | version = "1.5.0" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 680 | dependencies = [ 681 | "displaydoc", 682 | "icu_collections", 683 | "icu_normalizer_data", 684 | "icu_properties", 685 | "icu_provider", 686 | "smallvec", 687 | "utf16_iter", 688 | "utf8_iter", 689 | "write16", 690 | "zerovec", 691 | ] 692 | 693 | [[package]] 694 | name = "icu_normalizer_data" 695 | version = "1.5.1" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" 698 | 699 | [[package]] 700 | name = "icu_properties" 701 | version = "1.5.1" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 704 | dependencies = [ 705 | "displaydoc", 706 | "icu_collections", 707 | "icu_locid_transform", 708 | "icu_properties_data", 709 | "icu_provider", 710 | "tinystr", 711 | "zerovec", 712 | ] 713 | 714 | [[package]] 715 | name = "icu_properties_data" 716 | version = "1.5.1" 717 | source = "registry+https://github.com/rust-lang/crates.io-index" 718 | checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" 719 | 720 | [[package]] 721 | name = "icu_provider" 722 | version = "1.5.0" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 725 | dependencies = [ 726 | "displaydoc", 727 | "icu_locid", 728 | "icu_provider_macros", 729 | "stable_deref_trait", 730 | "tinystr", 731 | "writeable", 732 | "yoke", 733 | "zerofrom", 734 | "zerovec", 735 | ] 736 | 737 | [[package]] 738 | name = "icu_provider_macros" 739 | version = "1.5.0" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 742 | dependencies = [ 743 | "proc-macro2", 744 | "quote", 745 | "syn", 746 | ] 747 | 748 | [[package]] 749 | name = "idna" 750 | version = "1.0.3" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 753 | dependencies = [ 754 | "idna_adapter", 755 | "smallvec", 756 | "utf8_iter", 757 | ] 758 | 759 | [[package]] 760 | name = "idna_adapter" 761 | version = "1.2.0" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 764 | dependencies = [ 765 | "icu_normalizer", 766 | "icu_properties", 767 | ] 768 | 769 | [[package]] 770 | name = "ipnet" 771 | version = "2.11.0" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 774 | 775 | [[package]] 776 | name = "ipnetwork" 777 | version = "0.20.0" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" 780 | dependencies = [ 781 | "serde", 782 | ] 783 | 784 | [[package]] 785 | name = "is_terminal_polyfill" 786 | version = "1.70.1" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 789 | 790 | [[package]] 791 | name = "itoa" 792 | version = "1.0.15" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 795 | 796 | [[package]] 797 | name = "js-sys" 798 | version = "0.3.77" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 801 | dependencies = [ 802 | "once_cell", 803 | "wasm-bindgen", 804 | ] 805 | 806 | [[package]] 807 | name = "lazy_static" 808 | version = "1.5.0" 809 | source = "registry+https://github.com/rust-lang/crates.io-index" 810 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 811 | 812 | [[package]] 813 | name = "libc" 814 | version = "0.2.171" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" 817 | 818 | [[package]] 819 | name = "litemap" 820 | version = "0.7.5" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" 823 | 824 | [[package]] 825 | name = "lock_api" 826 | version = "0.4.12" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 829 | dependencies = [ 830 | "autocfg", 831 | "scopeguard", 832 | ] 833 | 834 | [[package]] 835 | name = "log" 836 | version = "0.4.27" 837 | source = "registry+https://github.com/rust-lang/crates.io-index" 838 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 839 | 840 | [[package]] 841 | name = "matchers" 842 | version = "0.1.0" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 845 | dependencies = [ 846 | "regex-automata 0.1.10", 847 | ] 848 | 849 | [[package]] 850 | name = "matchit" 851 | version = "0.8.4" 852 | source = "registry+https://github.com/rust-lang/crates.io-index" 853 | checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" 854 | 855 | [[package]] 856 | name = "memchr" 857 | version = "2.7.4" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 860 | 861 | [[package]] 862 | name = "mime" 863 | version = "0.3.17" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 866 | 867 | [[package]] 868 | name = "miniz_oxide" 869 | version = "0.8.8" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" 872 | dependencies = [ 873 | "adler2", 874 | ] 875 | 876 | [[package]] 877 | name = "mio" 878 | version = "1.0.3" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 881 | dependencies = [ 882 | "libc", 883 | "wasi 0.11.0+wasi-snapshot-preview1", 884 | "windows-sys 0.52.0", 885 | ] 886 | 887 | [[package]] 888 | name = "nix" 889 | version = "0.28.0" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" 892 | dependencies = [ 893 | "bitflags 2.9.0", 894 | "cfg-if", 895 | "cfg_aliases 0.1.1", 896 | "libc", 897 | ] 898 | 899 | [[package]] 900 | name = "no-std-net" 901 | version = "0.6.0" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" 904 | 905 | [[package]] 906 | name = "nu-ansi-term" 907 | version = "0.46.0" 908 | source = "registry+https://github.com/rust-lang/crates.io-index" 909 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 910 | dependencies = [ 911 | "overload", 912 | "winapi", 913 | ] 914 | 915 | [[package]] 916 | name = "object" 917 | version = "0.36.7" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 920 | dependencies = [ 921 | "memchr", 922 | ] 923 | 924 | [[package]] 925 | name = "once_cell" 926 | version = "1.21.3" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 929 | 930 | [[package]] 931 | name = "overload" 932 | version = "0.1.1" 933 | source = "registry+https://github.com/rust-lang/crates.io-index" 934 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 935 | 936 | [[package]] 937 | name = "parking_lot" 938 | version = "0.12.3" 939 | source = "registry+https://github.com/rust-lang/crates.io-index" 940 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 941 | dependencies = [ 942 | "lock_api", 943 | "parking_lot_core", 944 | ] 945 | 946 | [[package]] 947 | name = "parking_lot_core" 948 | version = "0.9.10" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 951 | dependencies = [ 952 | "cfg-if", 953 | "libc", 954 | "redox_syscall", 955 | "smallvec", 956 | "windows-targets 0.52.6", 957 | ] 958 | 959 | [[package]] 960 | name = "percent-encoding" 961 | version = "2.3.1" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 964 | 965 | [[package]] 966 | name = "pin-project-lite" 967 | version = "0.2.16" 968 | source = "registry+https://github.com/rust-lang/crates.io-index" 969 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 970 | 971 | [[package]] 972 | name = "pin-utils" 973 | version = "0.1.0" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 976 | 977 | [[package]] 978 | name = "pnet" 979 | version = "0.35.0" 980 | source = "registry+https://github.com/rust-lang/crates.io-index" 981 | checksum = "682396b533413cc2e009fbb48aadf93619a149d3e57defba19ff50ce0201bd0d" 982 | dependencies = [ 983 | "ipnetwork", 984 | "pnet_base", 985 | "pnet_datalink", 986 | "pnet_packet", 987 | "pnet_sys", 988 | "pnet_transport", 989 | ] 990 | 991 | [[package]] 992 | name = "pnet_base" 993 | version = "0.35.0" 994 | source = "registry+https://github.com/rust-lang/crates.io-index" 995 | checksum = "ffc190d4067df16af3aba49b3b74c469e611cad6314676eaf1157f31aa0fb2f7" 996 | dependencies = [ 997 | "no-std-net", 998 | ] 999 | 1000 | [[package]] 1001 | name = "pnet_datalink" 1002 | version = "0.35.0" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "e79e70ec0be163102a332e1d2d5586d362ad76b01cec86f830241f2b6452a7b7" 1005 | dependencies = [ 1006 | "ipnetwork", 1007 | "libc", 1008 | "pnet_base", 1009 | "pnet_sys", 1010 | "winapi", 1011 | ] 1012 | 1013 | [[package]] 1014 | name = "pnet_macros" 1015 | version = "0.35.0" 1016 | source = "registry+https://github.com/rust-lang/crates.io-index" 1017 | checksum = "13325ac86ee1a80a480b0bc8e3d30c25d133616112bb16e86f712dcf8a71c863" 1018 | dependencies = [ 1019 | "proc-macro2", 1020 | "quote", 1021 | "regex", 1022 | "syn", 1023 | ] 1024 | 1025 | [[package]] 1026 | name = "pnet_macros_support" 1027 | version = "0.35.0" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "eed67a952585d509dd0003049b1fc56b982ac665c8299b124b90ea2bdb3134ab" 1030 | dependencies = [ 1031 | "pnet_base", 1032 | ] 1033 | 1034 | [[package]] 1035 | name = "pnet_packet" 1036 | version = "0.35.0" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "4c96ebadfab635fcc23036ba30a7d33a80c39e8461b8bd7dc7bb186acb96560f" 1039 | dependencies = [ 1040 | "glob", 1041 | "pnet_base", 1042 | "pnet_macros", 1043 | "pnet_macros_support", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "pnet_sys" 1048 | version = "0.35.0" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "7d4643d3d4db6b08741050c2f3afa9a892c4244c085a72fcda93c9c2c9a00f4b" 1051 | dependencies = [ 1052 | "libc", 1053 | "winapi", 1054 | ] 1055 | 1056 | [[package]] 1057 | name = "pnet_transport" 1058 | version = "0.35.0" 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" 1060 | checksum = "5f604d98bc2a6591cf719b58d3203fd882bdd6bf1db696c4ac97978e9f4776bf" 1061 | dependencies = [ 1062 | "libc", 1063 | "pnet_base", 1064 | "pnet_packet", 1065 | "pnet_sys", 1066 | ] 1067 | 1068 | [[package]] 1069 | name = "portable-pty" 1070 | version = "0.9.0" 1071 | source = "git+https://github.com/wez/wezterm?rev=1e941fca5c17155b5f64a74221a396ef12ef71d0#1e941fca5c17155b5f64a74221a396ef12ef71d0" 1072 | dependencies = [ 1073 | "anyhow", 1074 | "bitflags 1.3.2", 1075 | "downcast-rs", 1076 | "filedescriptor", 1077 | "lazy_static", 1078 | "libc", 1079 | "log", 1080 | "nix", 1081 | "serial2", 1082 | "shared_library", 1083 | "shell-words", 1084 | "winapi", 1085 | "winreg", 1086 | ] 1087 | 1088 | [[package]] 1089 | name = "ppv-lite86" 1090 | version = "0.2.21" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 1093 | dependencies = [ 1094 | "zerocopy", 1095 | ] 1096 | 1097 | [[package]] 1098 | name = "proc-macro2" 1099 | version = "1.0.94" 1100 | source = "registry+https://github.com/rust-lang/crates.io-index" 1101 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" 1102 | dependencies = [ 1103 | "unicode-ident", 1104 | ] 1105 | 1106 | [[package]] 1107 | name = "quinn" 1108 | version = "0.11.7" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" 1111 | dependencies = [ 1112 | "bytes", 1113 | "cfg_aliases 0.2.1", 1114 | "pin-project-lite", 1115 | "quinn-proto", 1116 | "quinn-udp", 1117 | "rustc-hash", 1118 | "rustls", 1119 | "socket2", 1120 | "thiserror 2.0.12", 1121 | "tokio", 1122 | "tracing", 1123 | "web-time", 1124 | ] 1125 | 1126 | [[package]] 1127 | name = "quinn-proto" 1128 | version = "0.11.10" 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" 1130 | checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" 1131 | dependencies = [ 1132 | "bytes", 1133 | "getrandom 0.3.2", 1134 | "rand", 1135 | "ring", 1136 | "rustc-hash", 1137 | "rustls", 1138 | "rustls-pki-types", 1139 | "slab", 1140 | "thiserror 2.0.12", 1141 | "tinyvec", 1142 | "tracing", 1143 | "web-time", 1144 | ] 1145 | 1146 | [[package]] 1147 | name = "quinn-udp" 1148 | version = "0.5.11" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" 1151 | dependencies = [ 1152 | "cfg_aliases 0.2.1", 1153 | "libc", 1154 | "once_cell", 1155 | "socket2", 1156 | "tracing", 1157 | "windows-sys 0.59.0", 1158 | ] 1159 | 1160 | [[package]] 1161 | name = "quote" 1162 | version = "1.0.40" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 1165 | dependencies = [ 1166 | "proc-macro2", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "r-efi" 1171 | version = "5.2.0" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 1174 | 1175 | [[package]] 1176 | name = "rand" 1177 | version = "0.9.0" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" 1180 | dependencies = [ 1181 | "rand_chacha", 1182 | "rand_core", 1183 | "zerocopy", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "rand_chacha" 1188 | version = "0.9.0" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 1191 | dependencies = [ 1192 | "ppv-lite86", 1193 | "rand_core", 1194 | ] 1195 | 1196 | [[package]] 1197 | name = "rand_core" 1198 | version = "0.9.3" 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" 1200 | checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 1201 | dependencies = [ 1202 | "getrandom 0.3.2", 1203 | ] 1204 | 1205 | [[package]] 1206 | name = "redox_syscall" 1207 | version = "0.5.11" 1208 | source = "registry+https://github.com/rust-lang/crates.io-index" 1209 | checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" 1210 | dependencies = [ 1211 | "bitflags 2.9.0", 1212 | ] 1213 | 1214 | [[package]] 1215 | name = "regex" 1216 | version = "1.11.1" 1217 | source = "registry+https://github.com/rust-lang/crates.io-index" 1218 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 1219 | dependencies = [ 1220 | "aho-corasick", 1221 | "memchr", 1222 | "regex-automata 0.4.9", 1223 | "regex-syntax 0.8.5", 1224 | ] 1225 | 1226 | [[package]] 1227 | name = "regex-automata" 1228 | version = "0.1.10" 1229 | source = "registry+https://github.com/rust-lang/crates.io-index" 1230 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 1231 | dependencies = [ 1232 | "regex-syntax 0.6.29", 1233 | ] 1234 | 1235 | [[package]] 1236 | name = "regex-automata" 1237 | version = "0.4.9" 1238 | source = "registry+https://github.com/rust-lang/crates.io-index" 1239 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 1240 | dependencies = [ 1241 | "aho-corasick", 1242 | "memchr", 1243 | "regex-syntax 0.8.5", 1244 | ] 1245 | 1246 | [[package]] 1247 | name = "regex-syntax" 1248 | version = "0.6.29" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 1251 | 1252 | [[package]] 1253 | name = "regex-syntax" 1254 | version = "0.8.5" 1255 | source = "registry+https://github.com/rust-lang/crates.io-index" 1256 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 1257 | 1258 | [[package]] 1259 | name = "reqwest" 1260 | version = "0.12.15" 1261 | source = "registry+https://github.com/rust-lang/crates.io-index" 1262 | checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" 1263 | dependencies = [ 1264 | "base64", 1265 | "bytes", 1266 | "futures-core", 1267 | "futures-util", 1268 | "http", 1269 | "http-body", 1270 | "http-body-util", 1271 | "hyper", 1272 | "hyper-rustls", 1273 | "hyper-util", 1274 | "ipnet", 1275 | "js-sys", 1276 | "log", 1277 | "mime", 1278 | "once_cell", 1279 | "percent-encoding", 1280 | "pin-project-lite", 1281 | "quinn", 1282 | "rustls", 1283 | "rustls-pemfile", 1284 | "rustls-pki-types", 1285 | "serde", 1286 | "serde_json", 1287 | "serde_urlencoded", 1288 | "sync_wrapper", 1289 | "tokio", 1290 | "tokio-rustls", 1291 | "tower", 1292 | "tower-service", 1293 | "url", 1294 | "wasm-bindgen", 1295 | "wasm-bindgen-futures", 1296 | "web-sys", 1297 | "webpki-roots", 1298 | "windows-registry", 1299 | ] 1300 | 1301 | [[package]] 1302 | name = "ring" 1303 | version = "0.17.14" 1304 | source = "registry+https://github.com/rust-lang/crates.io-index" 1305 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 1306 | dependencies = [ 1307 | "cc", 1308 | "cfg-if", 1309 | "getrandom 0.2.15", 1310 | "libc", 1311 | "untrusted", 1312 | "windows-sys 0.52.0", 1313 | ] 1314 | 1315 | [[package]] 1316 | name = "rustc-demangle" 1317 | version = "0.1.24" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1320 | 1321 | [[package]] 1322 | name = "rustc-hash" 1323 | version = "2.1.1" 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" 1325 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 1326 | 1327 | [[package]] 1328 | name = "rustls" 1329 | version = "0.23.26" 1330 | source = "registry+https://github.com/rust-lang/crates.io-index" 1331 | checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" 1332 | dependencies = [ 1333 | "once_cell", 1334 | "ring", 1335 | "rustls-pki-types", 1336 | "rustls-webpki", 1337 | "subtle", 1338 | "zeroize", 1339 | ] 1340 | 1341 | [[package]] 1342 | name = "rustls-pemfile" 1343 | version = "2.2.0" 1344 | source = "registry+https://github.com/rust-lang/crates.io-index" 1345 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 1346 | dependencies = [ 1347 | "rustls-pki-types", 1348 | ] 1349 | 1350 | [[package]] 1351 | name = "rustls-pki-types" 1352 | version = "1.11.0" 1353 | source = "registry+https://github.com/rust-lang/crates.io-index" 1354 | checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" 1355 | dependencies = [ 1356 | "web-time", 1357 | ] 1358 | 1359 | [[package]] 1360 | name = "rustls-webpki" 1361 | version = "0.103.1" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" 1364 | dependencies = [ 1365 | "ring", 1366 | "rustls-pki-types", 1367 | "untrusted", 1368 | ] 1369 | 1370 | [[package]] 1371 | name = "rustversion" 1372 | version = "1.0.20" 1373 | source = "registry+https://github.com/rust-lang/crates.io-index" 1374 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 1375 | 1376 | [[package]] 1377 | name = "ryu" 1378 | version = "1.0.20" 1379 | source = "registry+https://github.com/rust-lang/crates.io-index" 1380 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1381 | 1382 | [[package]] 1383 | name = "scopeguard" 1384 | version = "1.2.0" 1385 | source = "registry+https://github.com/rust-lang/crates.io-index" 1386 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1387 | 1388 | [[package]] 1389 | name = "semver" 1390 | version = "1.0.26" 1391 | source = "registry+https://github.com/rust-lang/crates.io-index" 1392 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 1393 | 1394 | [[package]] 1395 | name = "serde" 1396 | version = "1.0.219" 1397 | source = "registry+https://github.com/rust-lang/crates.io-index" 1398 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 1399 | dependencies = [ 1400 | "serde_derive", 1401 | ] 1402 | 1403 | [[package]] 1404 | name = "serde_derive" 1405 | version = "1.0.219" 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" 1407 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 1408 | dependencies = [ 1409 | "proc-macro2", 1410 | "quote", 1411 | "syn", 1412 | ] 1413 | 1414 | [[package]] 1415 | name = "serde_json" 1416 | version = "1.0.140" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 1419 | dependencies = [ 1420 | "itoa", 1421 | "memchr", 1422 | "ryu", 1423 | "serde", 1424 | ] 1425 | 1426 | [[package]] 1427 | name = "serde_path_to_error" 1428 | version = "0.1.17" 1429 | source = "registry+https://github.com/rust-lang/crates.io-index" 1430 | checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" 1431 | dependencies = [ 1432 | "itoa", 1433 | "serde", 1434 | ] 1435 | 1436 | [[package]] 1437 | name = "serde_urlencoded" 1438 | version = "0.7.1" 1439 | source = "registry+https://github.com/rust-lang/crates.io-index" 1440 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1441 | dependencies = [ 1442 | "form_urlencoded", 1443 | "itoa", 1444 | "ryu", 1445 | "serde", 1446 | ] 1447 | 1448 | [[package]] 1449 | name = "serial2" 1450 | version = "0.2.29" 1451 | source = "registry+https://github.com/rust-lang/crates.io-index" 1452 | checksum = "c7d1d08630509d69f90eff4afcd02c3bd974d979225cbd815ff5942351b14375" 1453 | dependencies = [ 1454 | "cfg-if", 1455 | "libc", 1456 | "winapi", 1457 | ] 1458 | 1459 | [[package]] 1460 | name = "sha1" 1461 | version = "0.10.6" 1462 | source = "registry+https://github.com/rust-lang/crates.io-index" 1463 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 1464 | dependencies = [ 1465 | "cfg-if", 1466 | "cpufeatures", 1467 | "digest", 1468 | ] 1469 | 1470 | [[package]] 1471 | name = "sharded-slab" 1472 | version = "0.1.7" 1473 | source = "registry+https://github.com/rust-lang/crates.io-index" 1474 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 1475 | dependencies = [ 1476 | "lazy_static", 1477 | ] 1478 | 1479 | [[package]] 1480 | name = "shared_library" 1481 | version = "0.1.9" 1482 | source = "registry+https://github.com/rust-lang/crates.io-index" 1483 | checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" 1484 | dependencies = [ 1485 | "lazy_static", 1486 | "libc", 1487 | ] 1488 | 1489 | [[package]] 1490 | name = "shell-words" 1491 | version = "1.1.0" 1492 | source = "registry+https://github.com/rust-lang/crates.io-index" 1493 | checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" 1494 | 1495 | [[package]] 1496 | name = "shlex" 1497 | version = "1.3.0" 1498 | source = "registry+https://github.com/rust-lang/crates.io-index" 1499 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1500 | 1501 | [[package]] 1502 | name = "signal-hook-registry" 1503 | version = "1.4.2" 1504 | source = "registry+https://github.com/rust-lang/crates.io-index" 1505 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 1506 | dependencies = [ 1507 | "libc", 1508 | ] 1509 | 1510 | [[package]] 1511 | name = "slab" 1512 | version = "0.4.9" 1513 | source = "registry+https://github.com/rust-lang/crates.io-index" 1514 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1515 | dependencies = [ 1516 | "autocfg", 1517 | ] 1518 | 1519 | [[package]] 1520 | name = "smallvec" 1521 | version = "1.15.0" 1522 | source = "registry+https://github.com/rust-lang/crates.io-index" 1523 | checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" 1524 | 1525 | [[package]] 1526 | name = "socket2" 1527 | version = "0.5.9" 1528 | source = "registry+https://github.com/rust-lang/crates.io-index" 1529 | checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" 1530 | dependencies = [ 1531 | "libc", 1532 | "windows-sys 0.52.0", 1533 | ] 1534 | 1535 | [[package]] 1536 | name = "stable_deref_trait" 1537 | version = "1.2.0" 1538 | source = "registry+https://github.com/rust-lang/crates.io-index" 1539 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1540 | 1541 | [[package]] 1542 | name = "strsim" 1543 | version = "0.11.1" 1544 | source = "registry+https://github.com/rust-lang/crates.io-index" 1545 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 1546 | 1547 | [[package]] 1548 | name = "subtle" 1549 | version = "2.6.1" 1550 | source = "registry+https://github.com/rust-lang/crates.io-index" 1551 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1552 | 1553 | [[package]] 1554 | name = "syn" 1555 | version = "2.0.100" 1556 | source = "registry+https://github.com/rust-lang/crates.io-index" 1557 | checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 1558 | dependencies = [ 1559 | "proc-macro2", 1560 | "quote", 1561 | "unicode-ident", 1562 | ] 1563 | 1564 | [[package]] 1565 | name = "sync_wrapper" 1566 | version = "1.0.2" 1567 | source = "registry+https://github.com/rust-lang/crates.io-index" 1568 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1569 | dependencies = [ 1570 | "futures-core", 1571 | ] 1572 | 1573 | [[package]] 1574 | name = "synstructure" 1575 | version = "0.13.1" 1576 | source = "registry+https://github.com/rust-lang/crates.io-index" 1577 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 1578 | dependencies = [ 1579 | "proc-macro2", 1580 | "quote", 1581 | "syn", 1582 | ] 1583 | 1584 | [[package]] 1585 | name = "thiserror" 1586 | version = "1.0.69" 1587 | source = "registry+https://github.com/rust-lang/crates.io-index" 1588 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1589 | dependencies = [ 1590 | "thiserror-impl 1.0.69", 1591 | ] 1592 | 1593 | [[package]] 1594 | name = "thiserror" 1595 | version = "2.0.12" 1596 | source = "registry+https://github.com/rust-lang/crates.io-index" 1597 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 1598 | dependencies = [ 1599 | "thiserror-impl 2.0.12", 1600 | ] 1601 | 1602 | [[package]] 1603 | name = "thiserror-impl" 1604 | version = "1.0.69" 1605 | source = "registry+https://github.com/rust-lang/crates.io-index" 1606 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1607 | dependencies = [ 1608 | "proc-macro2", 1609 | "quote", 1610 | "syn", 1611 | ] 1612 | 1613 | [[package]] 1614 | name = "thiserror-impl" 1615 | version = "2.0.12" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 1618 | dependencies = [ 1619 | "proc-macro2", 1620 | "quote", 1621 | "syn", 1622 | ] 1623 | 1624 | [[package]] 1625 | name = "thread_local" 1626 | version = "1.1.8" 1627 | source = "registry+https://github.com/rust-lang/crates.io-index" 1628 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 1629 | dependencies = [ 1630 | "cfg-if", 1631 | "once_cell", 1632 | ] 1633 | 1634 | [[package]] 1635 | name = "tinystr" 1636 | version = "0.7.6" 1637 | source = "registry+https://github.com/rust-lang/crates.io-index" 1638 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 1639 | dependencies = [ 1640 | "displaydoc", 1641 | "zerovec", 1642 | ] 1643 | 1644 | [[package]] 1645 | name = "tinyvec" 1646 | version = "1.9.0" 1647 | source = "registry+https://github.com/rust-lang/crates.io-index" 1648 | checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" 1649 | dependencies = [ 1650 | "tinyvec_macros", 1651 | ] 1652 | 1653 | [[package]] 1654 | name = "tinyvec_macros" 1655 | version = "0.1.1" 1656 | source = "registry+https://github.com/rust-lang/crates.io-index" 1657 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1658 | 1659 | [[package]] 1660 | name = "tokio" 1661 | version = "1.44.2" 1662 | source = "registry+https://github.com/rust-lang/crates.io-index" 1663 | checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" 1664 | dependencies = [ 1665 | "backtrace", 1666 | "bytes", 1667 | "libc", 1668 | "mio", 1669 | "parking_lot", 1670 | "pin-project-lite", 1671 | "signal-hook-registry", 1672 | "socket2", 1673 | "tokio-macros", 1674 | "windows-sys 0.52.0", 1675 | ] 1676 | 1677 | [[package]] 1678 | name = "tokio-macros" 1679 | version = "2.5.0" 1680 | source = "registry+https://github.com/rust-lang/crates.io-index" 1681 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 1682 | dependencies = [ 1683 | "proc-macro2", 1684 | "quote", 1685 | "syn", 1686 | ] 1687 | 1688 | [[package]] 1689 | name = "tokio-rustls" 1690 | version = "0.26.2" 1691 | source = "registry+https://github.com/rust-lang/crates.io-index" 1692 | checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 1693 | dependencies = [ 1694 | "rustls", 1695 | "tokio", 1696 | ] 1697 | 1698 | [[package]] 1699 | name = "tokio-tungstenite" 1700 | version = "0.26.2" 1701 | source = "registry+https://github.com/rust-lang/crates.io-index" 1702 | checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" 1703 | dependencies = [ 1704 | "futures-util", 1705 | "log", 1706 | "tokio", 1707 | "tungstenite", 1708 | ] 1709 | 1710 | [[package]] 1711 | name = "tower" 1712 | version = "0.5.2" 1713 | source = "registry+https://github.com/rust-lang/crates.io-index" 1714 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 1715 | dependencies = [ 1716 | "futures-core", 1717 | "futures-util", 1718 | "pin-project-lite", 1719 | "sync_wrapper", 1720 | "tokio", 1721 | "tower-layer", 1722 | "tower-service", 1723 | "tracing", 1724 | ] 1725 | 1726 | [[package]] 1727 | name = "tower-http" 1728 | version = "0.6.2" 1729 | source = "registry+https://github.com/rust-lang/crates.io-index" 1730 | checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697" 1731 | dependencies = [ 1732 | "bitflags 2.9.0", 1733 | "bytes", 1734 | "http", 1735 | "http-body", 1736 | "pin-project-lite", 1737 | "tower-layer", 1738 | "tower-service", 1739 | "tracing", 1740 | ] 1741 | 1742 | [[package]] 1743 | name = "tower-layer" 1744 | version = "0.3.3" 1745 | source = "registry+https://github.com/rust-lang/crates.io-index" 1746 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1747 | 1748 | [[package]] 1749 | name = "tower-service" 1750 | version = "0.3.3" 1751 | source = "registry+https://github.com/rust-lang/crates.io-index" 1752 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1753 | 1754 | [[package]] 1755 | name = "tracing" 1756 | version = "0.1.41" 1757 | source = "registry+https://github.com/rust-lang/crates.io-index" 1758 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 1759 | dependencies = [ 1760 | "log", 1761 | "pin-project-lite", 1762 | "tracing-attributes", 1763 | "tracing-core", 1764 | ] 1765 | 1766 | [[package]] 1767 | name = "tracing-attributes" 1768 | version = "0.1.28" 1769 | source = "registry+https://github.com/rust-lang/crates.io-index" 1770 | checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" 1771 | dependencies = [ 1772 | "proc-macro2", 1773 | "quote", 1774 | "syn", 1775 | ] 1776 | 1777 | [[package]] 1778 | name = "tracing-core" 1779 | version = "0.1.33" 1780 | source = "registry+https://github.com/rust-lang/crates.io-index" 1781 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 1782 | dependencies = [ 1783 | "once_cell", 1784 | "valuable", 1785 | ] 1786 | 1787 | [[package]] 1788 | name = "tracing-log" 1789 | version = "0.2.0" 1790 | source = "registry+https://github.com/rust-lang/crates.io-index" 1791 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 1792 | dependencies = [ 1793 | "log", 1794 | "once_cell", 1795 | "tracing-core", 1796 | ] 1797 | 1798 | [[package]] 1799 | name = "tracing-subscriber" 1800 | version = "0.3.19" 1801 | source = "registry+https://github.com/rust-lang/crates.io-index" 1802 | checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" 1803 | dependencies = [ 1804 | "matchers", 1805 | "nu-ansi-term", 1806 | "once_cell", 1807 | "regex", 1808 | "sharded-slab", 1809 | "smallvec", 1810 | "thread_local", 1811 | "tracing", 1812 | "tracing-core", 1813 | "tracing-log", 1814 | ] 1815 | 1816 | [[package]] 1817 | name = "try-lock" 1818 | version = "0.2.5" 1819 | source = "registry+https://github.com/rust-lang/crates.io-index" 1820 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1821 | 1822 | [[package]] 1823 | name = "tungstenite" 1824 | version = "0.26.2" 1825 | source = "registry+https://github.com/rust-lang/crates.io-index" 1826 | checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" 1827 | dependencies = [ 1828 | "bytes", 1829 | "data-encoding", 1830 | "http", 1831 | "httparse", 1832 | "log", 1833 | "rand", 1834 | "sha1", 1835 | "thiserror 2.0.12", 1836 | "utf-8", 1837 | ] 1838 | 1839 | [[package]] 1840 | name = "typenum" 1841 | version = "1.18.0" 1842 | source = "registry+https://github.com/rust-lang/crates.io-index" 1843 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 1844 | 1845 | [[package]] 1846 | name = "unicode-ident" 1847 | version = "1.0.18" 1848 | source = "registry+https://github.com/rust-lang/crates.io-index" 1849 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1850 | 1851 | [[package]] 1852 | name = "untrusted" 1853 | version = "0.9.0" 1854 | source = "registry+https://github.com/rust-lang/crates.io-index" 1855 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 1856 | 1857 | [[package]] 1858 | name = "url" 1859 | version = "2.5.4" 1860 | source = "registry+https://github.com/rust-lang/crates.io-index" 1861 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 1862 | dependencies = [ 1863 | "form_urlencoded", 1864 | "idna", 1865 | "percent-encoding", 1866 | ] 1867 | 1868 | [[package]] 1869 | name = "utf-8" 1870 | version = "0.7.6" 1871 | source = "registry+https://github.com/rust-lang/crates.io-index" 1872 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 1873 | 1874 | [[package]] 1875 | name = "utf16_iter" 1876 | version = "1.0.5" 1877 | source = "registry+https://github.com/rust-lang/crates.io-index" 1878 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 1879 | 1880 | [[package]] 1881 | name = "utf8_iter" 1882 | version = "1.0.4" 1883 | source = "registry+https://github.com/rust-lang/crates.io-index" 1884 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 1885 | 1886 | [[package]] 1887 | name = "utf8parse" 1888 | version = "0.2.2" 1889 | source = "registry+https://github.com/rust-lang/crates.io-index" 1890 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 1891 | 1892 | [[package]] 1893 | name = "valuable" 1894 | version = "0.1.1" 1895 | source = "registry+https://github.com/rust-lang/crates.io-index" 1896 | checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 1897 | 1898 | [[package]] 1899 | name = "version_check" 1900 | version = "0.9.5" 1901 | source = "registry+https://github.com/rust-lang/crates.io-index" 1902 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1903 | 1904 | [[package]] 1905 | name = "want" 1906 | version = "0.3.1" 1907 | source = "registry+https://github.com/rust-lang/crates.io-index" 1908 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1909 | dependencies = [ 1910 | "try-lock", 1911 | ] 1912 | 1913 | [[package]] 1914 | name = "wasi" 1915 | version = "0.11.0+wasi-snapshot-preview1" 1916 | source = "registry+https://github.com/rust-lang/crates.io-index" 1917 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1918 | 1919 | [[package]] 1920 | name = "wasi" 1921 | version = "0.14.2+wasi-0.2.4" 1922 | source = "registry+https://github.com/rust-lang/crates.io-index" 1923 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 1924 | dependencies = [ 1925 | "wit-bindgen-rt", 1926 | ] 1927 | 1928 | [[package]] 1929 | name = "wasm-bindgen" 1930 | version = "0.2.100" 1931 | source = "registry+https://github.com/rust-lang/crates.io-index" 1932 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 1933 | dependencies = [ 1934 | "cfg-if", 1935 | "once_cell", 1936 | "rustversion", 1937 | "wasm-bindgen-macro", 1938 | ] 1939 | 1940 | [[package]] 1941 | name = "wasm-bindgen-backend" 1942 | version = "0.2.100" 1943 | source = "registry+https://github.com/rust-lang/crates.io-index" 1944 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 1945 | dependencies = [ 1946 | "bumpalo", 1947 | "log", 1948 | "proc-macro2", 1949 | "quote", 1950 | "syn", 1951 | "wasm-bindgen-shared", 1952 | ] 1953 | 1954 | [[package]] 1955 | name = "wasm-bindgen-futures" 1956 | version = "0.4.50" 1957 | source = "registry+https://github.com/rust-lang/crates.io-index" 1958 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 1959 | dependencies = [ 1960 | "cfg-if", 1961 | "js-sys", 1962 | "once_cell", 1963 | "wasm-bindgen", 1964 | "web-sys", 1965 | ] 1966 | 1967 | [[package]] 1968 | name = "wasm-bindgen-macro" 1969 | version = "0.2.100" 1970 | source = "registry+https://github.com/rust-lang/crates.io-index" 1971 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 1972 | dependencies = [ 1973 | "quote", 1974 | "wasm-bindgen-macro-support", 1975 | ] 1976 | 1977 | [[package]] 1978 | name = "wasm-bindgen-macro-support" 1979 | version = "0.2.100" 1980 | source = "registry+https://github.com/rust-lang/crates.io-index" 1981 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 1982 | dependencies = [ 1983 | "proc-macro2", 1984 | "quote", 1985 | "syn", 1986 | "wasm-bindgen-backend", 1987 | "wasm-bindgen-shared", 1988 | ] 1989 | 1990 | [[package]] 1991 | name = "wasm-bindgen-shared" 1992 | version = "0.2.100" 1993 | source = "registry+https://github.com/rust-lang/crates.io-index" 1994 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 1995 | dependencies = [ 1996 | "unicode-ident", 1997 | ] 1998 | 1999 | [[package]] 2000 | name = "web-sys" 2001 | version = "0.3.77" 2002 | source = "registry+https://github.com/rust-lang/crates.io-index" 2003 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 2004 | dependencies = [ 2005 | "js-sys", 2006 | "wasm-bindgen", 2007 | ] 2008 | 2009 | [[package]] 2010 | name = "web-time" 2011 | version = "1.1.0" 2012 | source = "registry+https://github.com/rust-lang/crates.io-index" 2013 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 2014 | dependencies = [ 2015 | "js-sys", 2016 | "wasm-bindgen", 2017 | ] 2018 | 2019 | [[package]] 2020 | name = "webpki-roots" 2021 | version = "0.26.8" 2022 | source = "registry+https://github.com/rust-lang/crates.io-index" 2023 | checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" 2024 | dependencies = [ 2025 | "rustls-pki-types", 2026 | ] 2027 | 2028 | [[package]] 2029 | name = "winapi" 2030 | version = "0.3.9" 2031 | source = "registry+https://github.com/rust-lang/crates.io-index" 2032 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2033 | dependencies = [ 2034 | "winapi-i686-pc-windows-gnu", 2035 | "winapi-x86_64-pc-windows-gnu", 2036 | ] 2037 | 2038 | [[package]] 2039 | name = "winapi-i686-pc-windows-gnu" 2040 | version = "0.4.0" 2041 | source = "registry+https://github.com/rust-lang/crates.io-index" 2042 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2043 | 2044 | [[package]] 2045 | name = "winapi-x86_64-pc-windows-gnu" 2046 | version = "0.4.0" 2047 | source = "registry+https://github.com/rust-lang/crates.io-index" 2048 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2049 | 2050 | [[package]] 2051 | name = "windows-link" 2052 | version = "0.1.1" 2053 | source = "registry+https://github.com/rust-lang/crates.io-index" 2054 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 2055 | 2056 | [[package]] 2057 | name = "windows-registry" 2058 | version = "0.4.0" 2059 | source = "registry+https://github.com/rust-lang/crates.io-index" 2060 | checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" 2061 | dependencies = [ 2062 | "windows-result", 2063 | "windows-strings", 2064 | "windows-targets 0.53.0", 2065 | ] 2066 | 2067 | [[package]] 2068 | name = "windows-result" 2069 | version = "0.3.2" 2070 | source = "registry+https://github.com/rust-lang/crates.io-index" 2071 | checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" 2072 | dependencies = [ 2073 | "windows-link", 2074 | ] 2075 | 2076 | [[package]] 2077 | name = "windows-strings" 2078 | version = "0.3.1" 2079 | source = "registry+https://github.com/rust-lang/crates.io-index" 2080 | checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 2081 | dependencies = [ 2082 | "windows-link", 2083 | ] 2084 | 2085 | [[package]] 2086 | name = "windows-sys" 2087 | version = "0.52.0" 2088 | source = "registry+https://github.com/rust-lang/crates.io-index" 2089 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2090 | dependencies = [ 2091 | "windows-targets 0.52.6", 2092 | ] 2093 | 2094 | [[package]] 2095 | name = "windows-sys" 2096 | version = "0.59.0" 2097 | source = "registry+https://github.com/rust-lang/crates.io-index" 2098 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2099 | dependencies = [ 2100 | "windows-targets 0.52.6", 2101 | ] 2102 | 2103 | [[package]] 2104 | name = "windows-targets" 2105 | version = "0.52.6" 2106 | source = "registry+https://github.com/rust-lang/crates.io-index" 2107 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2108 | dependencies = [ 2109 | "windows_aarch64_gnullvm 0.52.6", 2110 | "windows_aarch64_msvc 0.52.6", 2111 | "windows_i686_gnu 0.52.6", 2112 | "windows_i686_gnullvm 0.52.6", 2113 | "windows_i686_msvc 0.52.6", 2114 | "windows_x86_64_gnu 0.52.6", 2115 | "windows_x86_64_gnullvm 0.52.6", 2116 | "windows_x86_64_msvc 0.52.6", 2117 | ] 2118 | 2119 | [[package]] 2120 | name = "windows-targets" 2121 | version = "0.53.0" 2122 | source = "registry+https://github.com/rust-lang/crates.io-index" 2123 | checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" 2124 | dependencies = [ 2125 | "windows_aarch64_gnullvm 0.53.0", 2126 | "windows_aarch64_msvc 0.53.0", 2127 | "windows_i686_gnu 0.53.0", 2128 | "windows_i686_gnullvm 0.53.0", 2129 | "windows_i686_msvc 0.53.0", 2130 | "windows_x86_64_gnu 0.53.0", 2131 | "windows_x86_64_gnullvm 0.53.0", 2132 | "windows_x86_64_msvc 0.53.0", 2133 | ] 2134 | 2135 | [[package]] 2136 | name = "windows_aarch64_gnullvm" 2137 | version = "0.52.6" 2138 | source = "registry+https://github.com/rust-lang/crates.io-index" 2139 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2140 | 2141 | [[package]] 2142 | name = "windows_aarch64_gnullvm" 2143 | version = "0.53.0" 2144 | source = "registry+https://github.com/rust-lang/crates.io-index" 2145 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 2146 | 2147 | [[package]] 2148 | name = "windows_aarch64_msvc" 2149 | version = "0.52.6" 2150 | source = "registry+https://github.com/rust-lang/crates.io-index" 2151 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2152 | 2153 | [[package]] 2154 | name = "windows_aarch64_msvc" 2155 | version = "0.53.0" 2156 | source = "registry+https://github.com/rust-lang/crates.io-index" 2157 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 2158 | 2159 | [[package]] 2160 | name = "windows_i686_gnu" 2161 | version = "0.52.6" 2162 | source = "registry+https://github.com/rust-lang/crates.io-index" 2163 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2164 | 2165 | [[package]] 2166 | name = "windows_i686_gnu" 2167 | version = "0.53.0" 2168 | source = "registry+https://github.com/rust-lang/crates.io-index" 2169 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 2170 | 2171 | [[package]] 2172 | name = "windows_i686_gnullvm" 2173 | version = "0.52.6" 2174 | source = "registry+https://github.com/rust-lang/crates.io-index" 2175 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2176 | 2177 | [[package]] 2178 | name = "windows_i686_gnullvm" 2179 | version = "0.53.0" 2180 | source = "registry+https://github.com/rust-lang/crates.io-index" 2181 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 2182 | 2183 | [[package]] 2184 | name = "windows_i686_msvc" 2185 | version = "0.52.6" 2186 | source = "registry+https://github.com/rust-lang/crates.io-index" 2187 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2188 | 2189 | [[package]] 2190 | name = "windows_i686_msvc" 2191 | version = "0.53.0" 2192 | source = "registry+https://github.com/rust-lang/crates.io-index" 2193 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 2194 | 2195 | [[package]] 2196 | name = "windows_x86_64_gnu" 2197 | version = "0.52.6" 2198 | source = "registry+https://github.com/rust-lang/crates.io-index" 2199 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2200 | 2201 | [[package]] 2202 | name = "windows_x86_64_gnu" 2203 | version = "0.53.0" 2204 | source = "registry+https://github.com/rust-lang/crates.io-index" 2205 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 2206 | 2207 | [[package]] 2208 | name = "windows_x86_64_gnullvm" 2209 | version = "0.52.6" 2210 | source = "registry+https://github.com/rust-lang/crates.io-index" 2211 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2212 | 2213 | [[package]] 2214 | name = "windows_x86_64_gnullvm" 2215 | version = "0.53.0" 2216 | source = "registry+https://github.com/rust-lang/crates.io-index" 2217 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 2218 | 2219 | [[package]] 2220 | name = "windows_x86_64_msvc" 2221 | version = "0.52.6" 2222 | source = "registry+https://github.com/rust-lang/crates.io-index" 2223 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2224 | 2225 | [[package]] 2226 | name = "windows_x86_64_msvc" 2227 | version = "0.53.0" 2228 | source = "registry+https://github.com/rust-lang/crates.io-index" 2229 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 2230 | 2231 | [[package]] 2232 | name = "winreg" 2233 | version = "0.10.1" 2234 | source = "registry+https://github.com/rust-lang/crates.io-index" 2235 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" 2236 | dependencies = [ 2237 | "winapi", 2238 | ] 2239 | 2240 | [[package]] 2241 | name = "wit-bindgen-rt" 2242 | version = "0.39.0" 2243 | source = "registry+https://github.com/rust-lang/crates.io-index" 2244 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 2245 | dependencies = [ 2246 | "bitflags 2.9.0", 2247 | ] 2248 | 2249 | [[package]] 2250 | name = "write16" 2251 | version = "1.0.0" 2252 | source = "registry+https://github.com/rust-lang/crates.io-index" 2253 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 2254 | 2255 | [[package]] 2256 | name = "writeable" 2257 | version = "0.5.5" 2258 | source = "registry+https://github.com/rust-lang/crates.io-index" 2259 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 2260 | 2261 | [[package]] 2262 | name = "yoke" 2263 | version = "0.7.5" 2264 | source = "registry+https://github.com/rust-lang/crates.io-index" 2265 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 2266 | dependencies = [ 2267 | "serde", 2268 | "stable_deref_trait", 2269 | "yoke-derive", 2270 | "zerofrom", 2271 | ] 2272 | 2273 | [[package]] 2274 | name = "yoke-derive" 2275 | version = "0.7.5" 2276 | source = "registry+https://github.com/rust-lang/crates.io-index" 2277 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 2278 | dependencies = [ 2279 | "proc-macro2", 2280 | "quote", 2281 | "syn", 2282 | "synstructure", 2283 | ] 2284 | 2285 | [[package]] 2286 | name = "zerocopy" 2287 | version = "0.8.24" 2288 | source = "registry+https://github.com/rust-lang/crates.io-index" 2289 | checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" 2290 | dependencies = [ 2291 | "zerocopy-derive", 2292 | ] 2293 | 2294 | [[package]] 2295 | name = "zerocopy-derive" 2296 | version = "0.8.24" 2297 | source = "registry+https://github.com/rust-lang/crates.io-index" 2298 | checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" 2299 | dependencies = [ 2300 | "proc-macro2", 2301 | "quote", 2302 | "syn", 2303 | ] 2304 | 2305 | [[package]] 2306 | name = "zerofrom" 2307 | version = "0.1.6" 2308 | source = "registry+https://github.com/rust-lang/crates.io-index" 2309 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 2310 | dependencies = [ 2311 | "zerofrom-derive", 2312 | ] 2313 | 2314 | [[package]] 2315 | name = "zerofrom-derive" 2316 | version = "0.1.6" 2317 | source = "registry+https://github.com/rust-lang/crates.io-index" 2318 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 2319 | dependencies = [ 2320 | "proc-macro2", 2321 | "quote", 2322 | "syn", 2323 | "synstructure", 2324 | ] 2325 | 2326 | [[package]] 2327 | name = "zeroize" 2328 | version = "1.8.1" 2329 | source = "registry+https://github.com/rust-lang/crates.io-index" 2330 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 2331 | 2332 | [[package]] 2333 | name = "zerovec" 2334 | version = "0.10.4" 2335 | source = "registry+https://github.com/rust-lang/crates.io-index" 2336 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 2337 | dependencies = [ 2338 | "yoke", 2339 | "zerofrom", 2340 | "zerovec-derive", 2341 | ] 2342 | 2343 | [[package]] 2344 | name = "zerovec-derive" 2345 | version = "0.10.3" 2346 | source = "registry+https://github.com/rust-lang/crates.io-index" 2347 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 2348 | dependencies = [ 2349 | "proc-macro2", 2350 | "quote", 2351 | "syn", 2352 | ] 2353 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "axs" 3 | version = "0.2.4" 4 | edition = "2021" 5 | 6 | 7 | [dependencies] 8 | axum = { version = "0.8.1", features = ["ws"] } 9 | clap = { version = "4.4.18", features = ["derive"] } 10 | colored = "3.0.0" 11 | futures = "0.3.31" 12 | pnet = "0.35.0" 13 | portable-pty = { git = "https://github.com/wez/wezterm", package = "portable-pty", rev = "1e941fca5c17155b5f64a74221a396ef12ef71d0" } 14 | regex = "1.11.1" 15 | reqwest = { version = "0.12.12", default-features = false, features = [ 16 | "json", 17 | "rustls-tls", 18 | ] } 19 | semver = "1.0.25" 20 | serde = { version = "1.0.215", features = ["derive"] } 21 | serde_json = "1.0.133" 22 | tokio = { version = "1.42.0", features = ["full"] } 23 | tower-http = { version = "0.6.2", features = ["cors", "trace"] } 24 | tracing = "0.1.41" 25 | tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } 26 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # detect architecture 4 | detect_arch() { 5 | case $(uname -m) in 6 | armv7l | armv8l) 7 | echo "android-armv7" 8 | ;; 9 | aarch64) 10 | echo "android-arm64" 11 | ;; 12 | x86_64) 13 | echo "android-x86_64" 14 | ;; 15 | *) 16 | echo "Unsupported architecture. Please create an issue on GitHub, and we will consider providing a binary for your architecture." 17 | exit 1 18 | ;; 19 | esac 20 | } 21 | 22 | # download the appropriate binary 23 | download_binary() { 24 | ARCH=$(detect_arch) 25 | BASE_URL="https://github.com/bajrangCoder/acodex_server/releases/latest/download" 26 | 27 | FILE_NAME="axs-$ARCH" 28 | DOWNLOAD_URL="$BASE_URL/$FILE_NAME" 29 | 30 | # Download the binary 31 | echo "Downloading $FILE_NAME for $ARCH architecture..." 32 | if ! curl --progress-bar --fail -L "$DOWNLOAD_URL" -o "$FILE_NAME"; then 33 | echo "Failed to download the binary! Please check the URL and your connection: $DOWNLOAD_URL" 34 | exit 1 35 | fi 36 | 37 | # Move the binary to the PREFIX directory and rename it to 'axs' 38 | echo "Installing axs binary to $PREFIX..." 39 | mv "$FILE_NAME" "$PREFIX/bin/axs" 40 | chmod +x "$PREFIX/bin/axs" 41 | 42 | echo "Binary downloaded and installed as 'axs'. You can now use the 'axs' command!" 43 | echo "Make sure '$PREFIX/bin' is in your PATH." 44 | } 45 | 46 | download_binary 47 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # acodex_server 2 | 3 | `acodex_server` is a Rust-based backend/server for the `Acodex plugin`. It provides a **lightweight**, **independent**, **secure**, and **fast** solution. 4 | 5 | ## Features 6 | 7 | - Lightweight 8 | - Secure 9 | - fast 10 | - uses system pty 11 | - automatic update checking 12 | 13 | ## Installation 14 | 15 | To install `axs` on your system, simply use the following command: 16 | 17 | ```bash 18 | curl -L https://raw.githubusercontent.com/bajrangCoder/acodex_server/main/install.sh | bash 19 | ``` 20 | 21 | ## Update 22 | 23 | `axs` will automatically notify you whenever a new update is available. With a simple command: 24 | 25 | ```sh 26 | axs update 27 | ``` 28 | 29 | you can easily update it without any hassle. 30 | 31 | > [!NOTE] 32 | > This feature is available from `v0.2.0` onwards. For older versions, please use the installation script to update. 33 | 34 | ### Example Usage 35 | 36 | ```bash 37 | $ axs --help 38 | CLI/Server backend for AcodeX Acode plugin 39 | 40 | Usage: axs [OPTIONS] [COMMAND] 41 | 42 | Commands: 43 | update Update axs server 44 | help Print this message or the help of the given subcommand(s) 45 | Options: 46 | -p, --port Port to start the server [default: 8767] 47 | -i, --ip Start the server on local network (ip) 48 | -h, --help Print help 49 | -V, --version Print version 50 | ``` 51 | 52 | > [!NOTE] 53 | > If you encounter any issues, please [create an issue on GitHub](https://github.com/bajrangCoder/acodex_server/issues). 54 | 55 | ## Building from Source 56 | 57 | To build acodex_server from source, follow these steps: 58 | 59 | 1. Clone the repository: 60 | ```bash 61 | git clone https://github.com/your-username/acodex_server.git 62 | ``` 63 | 64 | 2. Ensure that Rust is installed on your system. 65 | 66 | 3. Navigate to the project directory: 67 | ```bash 68 | cd acodex_server 69 | ``` 70 | 71 | 4. Build the project: 72 | ```bash 73 | cargo build --release 74 | ``` 75 | 76 | 5. Use the generated binary located at `/target/release/axs`. 77 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod terminal; 2 | mod updates; 3 | mod utils; 4 | 5 | use clap::{Parser, Subcommand}; 6 | use colored::Colorize; 7 | use std::net::Ipv4Addr; 8 | use terminal::start_server; 9 | use updates::UpdateChecker; 10 | use utils::get_ip_address; 11 | 12 | const DEFAULT_PORT: u16 = 8767; 13 | const LOCAL_IP: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); 14 | 15 | #[derive(Parser)] 16 | #[command(name = "acodex_server(axs)",version, author = "Raunak Raj ", about = "CLI/Server backend for AcodeX Acode plugin", long_about = None)] 17 | struct Cli { 18 | /// Port to start the server 19 | #[arg(short, long, default_value_t = DEFAULT_PORT, value_parser = clap::value_parser!(u16).range(1..))] 20 | port: u16, 21 | /// Start the server on local network (ip) 22 | #[arg(short, long)] 23 | ip: bool, 24 | #[command(subcommand)] 25 | command: Option, 26 | } 27 | 28 | #[derive(Subcommand)] 29 | enum Commands { 30 | /// Update axs server 31 | Update, 32 | } 33 | 34 | fn print_update_available(current_version: &str, new_version: &str) { 35 | println!("\n{}", "═".repeat(40).yellow()); 36 | println!("{}", " 🎉 Update Available!".bright_yellow().bold()); 37 | println!(" Current version: {}", current_version.bright_red()); 38 | println!(" Latest version: {}", new_version.bright_green()); 39 | println!(" To update, run: {} {}", "axs".cyan(), "update".cyan()); 40 | println!("{}\n", "═".repeat(40).yellow()); 41 | } 42 | 43 | async fn check_updates_in_background() { 44 | let checker = UpdateChecker::new(env!("CARGO_PKG_VERSION")); 45 | match checker.check_update().await { 46 | Ok(Some(version)) => { 47 | print_update_available(env!("CARGO_PKG_VERSION"), &version); 48 | } 49 | Err(e) => eprintln!( 50 | "{} {}", 51 | "⚠️".yellow(), 52 | format!("Failed to check for updates: {}", e).red() 53 | ), 54 | _ => {} 55 | } 56 | } 57 | 58 | #[tokio::main] 59 | async fn main() { 60 | let cli: Cli = Cli::parse(); 61 | 62 | match cli.command { 63 | Some(Commands::Update) => { 64 | println!("{} {}", "⟳".blue().bold(), "Checking for updates...".blue()); 65 | 66 | let checker = UpdateChecker::new(env!("CARGO_PKG_VERSION")); 67 | 68 | match checker.check_update().await { 69 | Ok(Some(version)) => { 70 | println!( 71 | "{} Found new version: {}", 72 | "↓".bright_green(), 73 | version.green() 74 | ); 75 | println!( 76 | "{} {}", 77 | "⟳".blue(), 78 | "Downloading and installing update...".blue() 79 | ); 80 | 81 | match checker.update().await { 82 | Ok(()) => { 83 | println!( 84 | "\n{} {}", 85 | "✓".bright_green().bold(), 86 | "Update successful! Please restart axs.".green().bold() 87 | ); 88 | } 89 | Err(e) => { 90 | eprintln!( 91 | "\n{} {} {}", 92 | "✗".red().bold(), 93 | "Update failed:".red().bold(), 94 | e 95 | ); 96 | std::process::exit(1); 97 | } 98 | } 99 | } 100 | Ok(None) => { 101 | println!( 102 | "{} {}", 103 | "✓".bright_green().bold(), 104 | "You're already on the latest version!".green().bold() 105 | ); 106 | } 107 | Err(e) => { 108 | eprintln!( 109 | "{} {} {}", 110 | "✗".red().bold(), 111 | "Failed to check for updates:".red().bold(), 112 | e 113 | ); 114 | std::process::exit(1); 115 | } 116 | } 117 | } 118 | None => { 119 | tokio::task::spawn(check_updates_in_background()); 120 | 121 | let ip = if cli.ip { 122 | get_ip_address().unwrap_or_else(|| { 123 | println!( 124 | "{} localhost.", 125 | "Error: IP address not found. Starting server on" 126 | .red() 127 | .bold() 128 | ); 129 | LOCAL_IP 130 | }) 131 | } else { 132 | LOCAL_IP 133 | }; 134 | 135 | start_server(ip, cli.port).await; 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/terminal/buffer.rs: -------------------------------------------------------------------------------- 1 | use axum::body::Bytes; 2 | 3 | pub struct CircularBuffer { 4 | pub data: Vec, 5 | position: usize, 6 | max_size: usize, 7 | } 8 | 9 | impl CircularBuffer { 10 | pub fn new(max_size: usize) -> Self { 11 | Self { 12 | data: Vec::with_capacity(max_size), 13 | position: 0, 14 | max_size, 15 | } 16 | } 17 | 18 | pub fn write(&mut self, new_data: &[u8]) { 19 | for &byte in new_data { 20 | if self.data.len() < self.max_size { 21 | self.data.push(byte); 22 | } else { 23 | self.data[self.position] = byte; 24 | self.position = (self.position + 1) % self.max_size; 25 | } 26 | } 27 | } 28 | 29 | pub fn get_contents(&self) -> Bytes { 30 | if self.data.len() < self.max_size { 31 | Bytes::from(self.data.clone()) 32 | } else { 33 | let mut result = Vec::with_capacity(self.max_size); 34 | result.extend_from_slice(&self.data[self.position..]); 35 | result.extend_from_slice(&self.data[..self.position]); 36 | Bytes::from(result) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/terminal/handlers.rs: -------------------------------------------------------------------------------- 1 | use super::buffer::CircularBuffer; 2 | use super::types::*; 3 | use crate::utils::parse_u16; 4 | use axum::{ 5 | body::Bytes, 6 | extract::{ 7 | ws::{Message, WebSocket, WebSocketUpgrade}, 8 | Path, State, 9 | }, 10 | response::IntoResponse, 11 | Json, 12 | }; 13 | use futures::{SinkExt, StreamExt}; 14 | use portable_pty::{native_pty_system, ChildKiller, CommandBuilder, MasterPty, PtySize}; 15 | use regex::Regex; 16 | use std::io::Write; 17 | use std::time::SystemTime; 18 | use std::{ 19 | io::Read, 20 | path::PathBuf, 21 | sync::{mpsc, Arc}, 22 | time::Duration, 23 | }; 24 | use tokio::sync::Mutex; 25 | use tokio::task::spawn_blocking; 26 | 27 | pub struct TerminalSession { 28 | pub master: Arc>>, 29 | pub child_killer: Arc>>, 30 | pub reader: Arc>>, 31 | pub writer: Arc>>, 32 | pub buffer: Arc>, 33 | pub last_accessed: Arc>, 34 | } 35 | 36 | pub async fn create_terminal( 37 | State(sessions): State, 38 | Json(options): Json, 39 | ) -> impl IntoResponse { 40 | let rows = parse_u16(&options.rows, "rows").expect("failed"); 41 | let cols = parse_u16(&options.cols, "cols").expect("failed"); 42 | tracing::info!("Creating new terminal with cols={}, rows={}", cols, rows); 43 | 44 | let pty_system = native_pty_system(); 45 | 46 | let shell = String::from("login"); 47 | 48 | let size = PtySize { 49 | rows, 50 | cols, 51 | pixel_width: 0, 52 | pixel_height: 0, 53 | }; 54 | 55 | match pty_system.openpty(size) { 56 | Ok(pair) => { 57 | let cmd = CommandBuilder::new(shell); 58 | match pair.slave.spawn_command(cmd) { 59 | Ok(child) => { 60 | let pid = child.process_id().unwrap_or(0); 61 | tracing::info!("Terminal created successfully with PID: {}", pid); 62 | drop(pair.slave); // Release slave after spawning 63 | 64 | let reader = Arc::new(Mutex::new(pair.master.try_clone_reader().unwrap())); 65 | let writer = Arc::new(Mutex::new(pair.master.take_writer().unwrap())); 66 | let master = Arc::new(Mutex::new(pair.master as Box)); 67 | let child_killer = Arc::new(Mutex::new(child.clone_killer())); 68 | 69 | let session = TerminalSession { 70 | master, 71 | child_killer, 72 | reader, 73 | writer, 74 | buffer: Arc::new(Mutex::new(CircularBuffer::new(MAX_BUFFER_SIZE))), 75 | last_accessed: Arc::new(Mutex::new(SystemTime::now())), 76 | }; 77 | 78 | sessions.lock().await.insert(pid, session); 79 | (axum::http::StatusCode::OK, pid.to_string()).into_response() 80 | } 81 | Err(e) => { 82 | tracing::error!("Failed to spawn command: {}", e); 83 | Json(ErrorResponse { 84 | error: format!("Failed to spawn command: {}", e), 85 | }) 86 | .into_response() 87 | } 88 | } 89 | } 90 | Err(e) => { 91 | tracing::error!("Failed to open PTY: {}", e); 92 | Json(ErrorResponse { 93 | error: format!("Failed to open PTY: {}", e), 94 | }) 95 | .into_response() 96 | } 97 | } 98 | } 99 | 100 | pub async fn resize_terminal( 101 | State(sessions): State, 102 | Path(pid): Path, 103 | Json(options): Json, 104 | ) -> impl IntoResponse { 105 | let rows = parse_u16(&options.rows, "rows").expect("Failed"); 106 | let cols = parse_u16(&options.cols, "cols").expect("Failed"); 107 | tracing::info!("Resizing terminal {} to cols={}, rows={}", pid, cols, rows); 108 | let mut sessions = sessions.lock().await; 109 | if let Some(session) = sessions.get_mut(&pid) { 110 | let size = PtySize { 111 | rows, 112 | cols, 113 | pixel_width: 0, 114 | pixel_height: 0, 115 | }; 116 | 117 | match session.master.lock().await.resize(size) { 118 | Ok(_) => Json(serde_json::json!({"success": true})).into_response(), 119 | Err(e) => Json(ErrorResponse { 120 | error: format!("Failed to resize: {}", e), 121 | }) 122 | .into_response(), 123 | } 124 | } else { 125 | Json(ErrorResponse { 126 | error: "Session not found".to_string(), 127 | }) 128 | .into_response() 129 | } 130 | } 131 | 132 | pub async fn terminal_websocket( 133 | ws: WebSocketUpgrade, 134 | Path(pid): Path, 135 | State(sessions): State, 136 | ) -> impl IntoResponse { 137 | tracing::info!("WebSocket connection request for terminal {}", pid); 138 | ws.on_upgrade(move |socket| handle_socket(socket, pid, sessions)) 139 | } 140 | 141 | async fn handle_socket(socket: WebSocket, pid: u32, sessions: Sessions) { 142 | let (mut sender, mut receiver) = socket.split(); 143 | 144 | let session_lock = sessions.lock().await; 145 | if let Some(session) = session_lock.get(&pid) { 146 | // Update last accessed time 147 | let mut last_accessed = session.last_accessed.lock().await; 148 | *last_accessed = SystemTime::now(); 149 | drop(last_accessed); 150 | 151 | tracing::info!("WebSocket connection established for terminal {}", pid); 152 | let reader = session.reader.clone(); 153 | let writer = session.writer.clone(); 154 | let buffer = session.buffer.clone(); 155 | drop(session_lock); 156 | 157 | // Send initial buffer contents 158 | let buffer_guard = buffer.lock().await; 159 | let contents = buffer_guard.get_contents(); 160 | if !contents.is_empty() { 161 | let _ = sender.send(Message::Binary(contents)).await; 162 | } 163 | drop(buffer_guard); 164 | 165 | let pty_to_ws = { 166 | let buffer = buffer.clone(); 167 | let reader = reader.clone(); 168 | 169 | tokio::spawn(async move { 170 | spawn_blocking(move || { 171 | let mut read_buffer = [0u8; 1024]; 172 | loop { 173 | let n = { 174 | let mut reader_guard = reader.blocking_lock(); 175 | match reader_guard.read(&mut read_buffer) { 176 | Ok(n) if n > 0 => n, 177 | _ => break, 178 | } 179 | }; 180 | 181 | let data = read_buffer[..n].to_vec(); 182 | 183 | let rt = tokio::runtime::Handle::current(); 184 | if !rt.block_on(async { 185 | let mut buffer_guard = buffer.lock().await; 186 | buffer_guard.write(&data); 187 | sender 188 | .send(Message::Binary(Bytes::from(data.clone()))) 189 | .await 190 | .is_ok() 191 | }) { 192 | break; 193 | } 194 | } 195 | }) 196 | .await 197 | .ok(); 198 | }) 199 | }; 200 | 201 | // Handle WebSocket input to PTY 202 | let ws_to_pty = { 203 | let writer = writer.clone(); 204 | tokio::spawn(async move { 205 | let (tx, rx) = std::sync::mpsc::channel::>(); 206 | let tx = std::sync::Arc::new(tx); 207 | let tx_clone = tx.clone(); 208 | 209 | let write_handle = spawn_blocking(move || { 210 | while let Ok(data) = rx.recv() { 211 | let mut writer_guard = writer.blocking_lock(); 212 | if writer_guard.write_all(&data).is_err() || writer_guard.flush().is_err() { 213 | break; 214 | } 215 | } 216 | }); 217 | 218 | while let Some(Ok(message)) = receiver.next().await { 219 | let data: axum::body::Bytes = match message { 220 | Message::Text(text) => Bytes::from(text), 221 | Message::Binary(data) => data, 222 | Message::Close(_) => break, 223 | _ => continue, 224 | }; 225 | 226 | if tx_clone.send(data.to_vec()).is_err() { 227 | break; 228 | } 229 | } 230 | 231 | // Clean up 232 | drop(tx_clone); 233 | let _ = write_handle.await; 234 | }) 235 | }; 236 | 237 | // Wait for either task to complete 238 | tokio::select! { 239 | _ = pty_to_ws => { 240 | tracing::info!("PTY to WebSocket task completed for terminal {}", pid); 241 | } 242 | _ = ws_to_pty => { 243 | tracing::info!("WebSocket to PTY task completed for terminal {}", pid); 244 | } 245 | } 246 | } else { 247 | tracing::error!("Session {} not found", pid); 248 | } 249 | } 250 | 251 | pub async fn terminate_terminal( 252 | State(sessions): State, 253 | Path(pid): Path, 254 | ) -> impl IntoResponse { 255 | tracing::info!("Terminating terminal {}", pid); 256 | let mut sessions = sessions.lock().await; 257 | 258 | if let Some(session) = sessions.remove(&pid) { 259 | let result = { 260 | session 261 | .child_killer 262 | .lock() 263 | .await 264 | .kill() 265 | .map_err(|e| e.to_string()) 266 | }; 267 | drop(session.writer.lock().await); 268 | drop(session.reader.lock().await); 269 | 270 | // Clear the circular buffer 271 | if let Ok(mut buffer) = session.buffer.try_lock() { 272 | buffer.data.clear(); 273 | } 274 | 275 | match result { 276 | Ok(_) => { 277 | tracing::info!("Terminal {} terminated successfully", pid); 278 | Json(serde_json::json!({"success": true})).into_response() 279 | } 280 | Err(e) => { 281 | tracing::error!("Failed to terminate terminal {}: {}", pid, e); 282 | Json(ErrorResponse { 283 | error: format!("Failed to terminate terminal {}: {}", pid, e), 284 | }) 285 | .into_response() 286 | } 287 | } 288 | } else { 289 | tracing::error!("Failed to terminate terminal {}: session not found", pid); 290 | Json(ErrorResponse { 291 | error: "Session not found".to_string(), 292 | }) 293 | .into_response() 294 | } 295 | } 296 | 297 | pub async fn execute_command(Json(options): Json) -> impl IntoResponse { 298 | let cwd = options.cwd.or(options.u_cwd).unwrap_or("".to_string()); 299 | 300 | tracing::info!( 301 | command = %options.command, 302 | cwd = %cwd, 303 | "Executing command" 304 | ); 305 | 306 | let shell = String::from("login"); 307 | let cwd = if cwd.is_empty() { 308 | std::env::var("HOME") 309 | .map(PathBuf::from) 310 | .unwrap_or_else(|_| std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))) 311 | } else { 312 | PathBuf::from(cwd) 313 | }; 314 | 315 | if !cwd.exists() { 316 | return ( 317 | axum::http::StatusCode::BAD_REQUEST, 318 | Json(CommandResponse { 319 | output: String::new(), 320 | error: Some("Working directory does not exist".to_string()), 321 | }), 322 | ) 323 | .into_response(); 324 | } 325 | 326 | let command = options.command.clone(); 327 | 328 | // Execute command in a blocking task 329 | let result = spawn_blocking(move || { 330 | // Set up PTY 331 | let pty_system = native_pty_system(); 332 | let size = PtySize { 333 | rows: 24, 334 | cols: 80, 335 | pixel_width: 0, 336 | pixel_height: 0, 337 | }; 338 | 339 | let pair = pty_system.openpty(size)?; 340 | 341 | // Set up command 342 | let mut cmd = CommandBuilder::new(shell); 343 | cmd.args(["-c", &command]); 344 | cmd.cwd(cwd); 345 | 346 | // Spawn the command 347 | let mut child = pair.slave.spawn_command(cmd)?; 348 | drop(pair.slave); 349 | 350 | let mut reader = pair.master.try_clone_reader()?; 351 | let writer = pair.master.take_writer()?; 352 | 353 | // Create channel for reading output 354 | let (tx, rx) = std::sync::mpsc::channel::>(); 355 | 356 | // Spawn a thread for reading 357 | let read_thread = std::thread::spawn(move || { 358 | let mut buffer = [0u8; 1024]; 359 | loop { 360 | match reader.read(&mut buffer) { 361 | Ok(0) => break, // EOF 362 | Ok(n) => { 363 | if tx.send(buffer[..n].to_vec()).is_err() { 364 | break; 365 | } 366 | } 367 | Err(_) => break, 368 | } 369 | } 370 | }); 371 | 372 | // Collect output with timeout 373 | let timeout_duration = Duration::from_secs(30); 374 | let start_time = SystemTime::now(); 375 | let mut output = Vec::new(); 376 | 377 | loop { 378 | match rx.recv_timeout(Duration::from_millis(100)) { 379 | Ok(data) => { 380 | output.extend(data); 381 | } 382 | Err(mpsc::RecvTimeoutError::Timeout) => { 383 | if start_time.elapsed().unwrap_or_default() > timeout_duration { 384 | child.kill()?; 385 | return Err("Command execution timed out".into()); 386 | } 387 | } 388 | Err(mpsc::RecvTimeoutError::Disconnected) => break, 389 | } 390 | 391 | // Check if process has finished 392 | if let Ok(Some(_)) = child.try_wait() { 393 | break; 394 | } 395 | } 396 | 397 | // Clean up resources 398 | drop(writer); 399 | let _ = read_thread.join(); 400 | child.wait()?; 401 | 402 | Ok::, Box>(output) 403 | }) 404 | .await; 405 | 406 | // Process the result 407 | match result { 408 | Ok(Ok(output)) => { 409 | let output_str = String::from_utf8_lossy(&output).into_owned(); 410 | 411 | // Clean ANSI escape sequences 412 | let ansi_regex = 413 | Regex::new(r"\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]|\x1B\[[0-9]+[A-Za-z]").unwrap(); 414 | let cleaned_output = ansi_regex.replace_all(&output_str, "").to_string(); 415 | 416 | tracing::info!( 417 | output_length = cleaned_output.len(), 418 | "Command completed successfully" 419 | ); 420 | 421 | ( 422 | axum::http::StatusCode::OK, 423 | Json(CommandResponse { 424 | output: cleaned_output, 425 | error: None, 426 | }), 427 | ) 428 | .into_response() 429 | } 430 | Ok(Err(e)) => { 431 | tracing::error!("Command execution failed: {}", e); 432 | ( 433 | axum::http::StatusCode::INTERNAL_SERVER_ERROR, 434 | Json(CommandResponse { 435 | output: String::new(), 436 | error: Some(e.to_string()), 437 | }), 438 | ) 439 | .into_response() 440 | } 441 | Err(e) => { 442 | tracing::error!("Blocking task failed: {}", e); 443 | ( 444 | axum::http::StatusCode::INTERNAL_SERVER_ERROR, 445 | Json(CommandResponse { 446 | output: String::new(), 447 | error: Some("Internal server error".to_string()), 448 | }), 449 | ) 450 | .into_response() 451 | } 452 | } 453 | } 454 | -------------------------------------------------------------------------------- /src/terminal/mod.rs: -------------------------------------------------------------------------------- 1 | mod buffer; 2 | mod handlers; 3 | mod types; 4 | 5 | use axum::{ 6 | routing::{get, post}, 7 | Router, 8 | }; 9 | 10 | use std::{collections::HashMap, sync::Arc}; 11 | use std::{io::ErrorKind, net::Ipv4Addr}; 12 | use tokio::sync::Mutex; 13 | use tower_http::cors::{Any, CorsLayer}; 14 | use tower_http::trace::{DefaultMakeSpan, TraceLayer}; 15 | use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; 16 | 17 | use handlers::*; 18 | 19 | pub type Sessions = Arc>>; 20 | 21 | pub async fn start_server(host: Ipv4Addr, port: u16) { 22 | tracing_subscriber::registry() 23 | .with( 24 | tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| { 25 | format!("{}=debug,tower_http=info", env!("CARGO_CRATE_NAME")).into() 26 | }), 27 | ) 28 | .with(tracing_subscriber::fmt::layer()) 29 | .init(); 30 | let sessions: Sessions = Arc::new(Mutex::new(HashMap::new())); 31 | 32 | let cors = CorsLayer::new() 33 | .allow_origin(Any) 34 | .allow_methods(Any) 35 | .allow_headers(Any); 36 | 37 | let app = Router::new() 38 | .route("/terminals", post(create_terminal)) 39 | .route("/terminals/{pid}/resize", post(resize_terminal)) 40 | .route("/terminals/{pid}", get(terminal_websocket)) 41 | .route("/terminals/{pid}/terminate", post(terminate_terminal)) 42 | .route("/execute-command", post(execute_command)) 43 | .with_state(sessions) 44 | .layer(cors) 45 | .layer( 46 | TraceLayer::new_for_http() 47 | .make_span_with(DefaultMakeSpan::default().include_headers(true)), 48 | ); 49 | 50 | let addr: std::net::SocketAddr = (host, port).into(); 51 | 52 | match tokio::net::TcpListener::bind(addr).await { 53 | Ok(listener) => { 54 | tracing::info!("listening on {}", listener.local_addr().unwrap()); 55 | 56 | if let Err(e) = axum::serve(listener, app).await { 57 | tracing::error!("Server error: {}", e); 58 | } 59 | } 60 | Err(e) => { 61 | if e.kind() == ErrorKind::AddrInUse { 62 | tracing::error!("Port is already in use please kill all other instances of axs server or stop any other process or app that maybe be using port {}", port); 63 | } else { 64 | tracing::error!("Failed to bind: {}", e); 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/terminal/types.rs: -------------------------------------------------------------------------------- 1 | use super::handlers::TerminalSession; 2 | use serde::{Deserialize, Serialize}; 3 | use std::{collections::HashMap, sync::Arc}; 4 | use tokio::sync::Mutex; 5 | 6 | pub const MAX_BUFFER_SIZE: usize = 1_000_000; 7 | 8 | #[derive(Deserialize)] 9 | pub struct TerminalOptions { 10 | pub cols: serde_json::Value, 11 | pub rows: serde_json::Value, 12 | } 13 | 14 | #[derive(Deserialize)] 15 | pub struct ExecuteCommandOption { 16 | pub command: String, 17 | pub cwd: Option, 18 | pub u_cwd: Option, 19 | } 20 | 21 | #[derive(Serialize)] 22 | pub struct CommandResponse { 23 | pub output: String, 24 | pub error: Option, 25 | } 26 | 27 | #[derive(Debug, Serialize)] 28 | pub struct ErrorResponse { 29 | pub error: String, 30 | } 31 | 32 | pub type Sessions = Arc>>; 33 | -------------------------------------------------------------------------------- /src/updates.rs: -------------------------------------------------------------------------------- 1 | use reqwest::Client; 2 | use semver::Version; 3 | use serde::Deserialize; 4 | use std::path::PathBuf; 5 | use std::time::{Duration, SystemTime}; 6 | use tokio::fs::{self, File}; 7 | use tokio::io::AsyncWriteExt; 8 | 9 | const GITHUB_API_URL: &str = 10 | "https://api.github.com/repos/bajrangCoder/acodex_server/releases/latest"; 11 | const UPDATE_CHECK_INTERVAL: Duration = Duration::from_secs(24 * 60 * 60); 12 | const CACHE_FILE: &str = ".axs_update_cache"; 13 | 14 | #[derive(Deserialize)] 15 | struct GithubRelease { 16 | tag_name: String, 17 | assets: Vec, 18 | } 19 | 20 | #[derive(Deserialize)] 21 | struct GithubAsset { 22 | name: String, 23 | browser_download_url: String, 24 | } 25 | 26 | struct UpdateCache { 27 | last_check: SystemTime, 28 | latest_version: String, 29 | } 30 | 31 | pub struct UpdateChecker { 32 | client: Client, 33 | current_version: Version, 34 | } 35 | 36 | impl UpdateChecker { 37 | pub fn new(current_version: &str) -> Self { 38 | Self { 39 | client: Client::new(), 40 | current_version: Version::parse(current_version).unwrap(), 41 | } 42 | } 43 | 44 | async fn get_cache() -> Option { 45 | let cache_path = Self::get_cache_path()?; 46 | let content = fs::read_to_string(cache_path).await.ok()?; 47 | let parts: Vec<&str> = content.split(',').collect(); 48 | if parts.len() != 2 { 49 | return None; 50 | } 51 | 52 | let timestamp = parts[0].parse::().ok()?; 53 | Some(UpdateCache { 54 | last_check: SystemTime::UNIX_EPOCH + Duration::from_secs(timestamp), 55 | latest_version: parts[1].to_string(), 56 | }) 57 | } 58 | 59 | async fn save_cache(version: &str) -> tokio::io::Result<()> { 60 | if let Some(cache_path) = Self::get_cache_path() { 61 | if let Some(parent) = cache_path.parent() { 62 | fs::create_dir_all(parent).await?; 63 | } 64 | 65 | let now = SystemTime::now() 66 | .duration_since(SystemTime::UNIX_EPOCH) 67 | .unwrap() 68 | .as_secs(); 69 | let content = format!("{},{}", now, version); 70 | fs::write(cache_path, content).await?; 71 | } 72 | Ok(()) 73 | } 74 | 75 | fn get_cache_path() -> Option { 76 | match std::env::var_os("HOME") { 77 | Some(home) => { 78 | let mut path = PathBuf::from(home); 79 | path.push(".cache"); 80 | path.push("axs"); 81 | path.push(CACHE_FILE); 82 | Some(path) 83 | } 84 | None => match std::env::var_os("TMPDIR").or_else(|| std::env::var_os("TMP")) { 85 | Some(tmp) => { 86 | let mut path = PathBuf::from(tmp); 87 | path.push("axs"); 88 | path.push(CACHE_FILE); 89 | Some(path) 90 | } 91 | None => None, 92 | }, 93 | } 94 | } 95 | 96 | pub async fn check_update(&self) -> Result, Box> { 97 | // Check cache first 98 | if let Some(cache) = Self::get_cache().await { 99 | let elapsed = SystemTime::now() 100 | .duration_since(cache.last_check) 101 | .unwrap_or(UPDATE_CHECK_INTERVAL); 102 | if elapsed < UPDATE_CHECK_INTERVAL { 103 | let cached_version = Version::parse(&cache.latest_version)?; 104 | if cached_version > self.current_version { 105 | return Ok(Some(cache.latest_version)); 106 | } 107 | return Ok(None); 108 | } 109 | } 110 | 111 | // Fetch latest release from GitHub 112 | let release: GithubRelease = self 113 | .client 114 | .get(GITHUB_API_URL) 115 | .header("User-Agent", "axs-update-checker") 116 | .send() 117 | .await? 118 | .json() 119 | .await?; 120 | 121 | let latest_version = Version::parse(release.tag_name.trim_start_matches('v'))?; 122 | Self::save_cache(&latest_version.to_string()).await?; 123 | 124 | if latest_version > self.current_version { 125 | Ok(Some(release.tag_name)) 126 | } else { 127 | Ok(None) 128 | } 129 | } 130 | 131 | pub async fn update(&self) -> Result<(), Box> { 132 | let release: GithubRelease = self 133 | .client 134 | .get(GITHUB_API_URL) 135 | .header("User-Agent", "axs-update-checker") 136 | .send() 137 | .await? 138 | .json() 139 | .await?; 140 | 141 | // Detect current architecture 142 | let arch = match std::env::consts::ARCH { 143 | "arm" => "android-armv7", 144 | "aarch64" => "android-arm64", 145 | _ => return Err("Unsupported architecture".into()), 146 | }; 147 | 148 | let asset = release 149 | .assets 150 | .iter() 151 | .find(|a| a.name == format!("axs-{}", arch)) 152 | .ok_or("No matching binary found")?; 153 | 154 | // Download binary 155 | let response = self 156 | .client 157 | .get(&asset.browser_download_url) 158 | .send() 159 | .await? 160 | .bytes() 161 | .await?; 162 | 163 | let current_exe = std::env::current_exe()?; 164 | let temp_path = current_exe.with_extension("new"); 165 | 166 | let mut file = File::create(&temp_path).await?; 167 | file.write_all(&response).await?; 168 | file.sync_all().await?; 169 | 170 | #[cfg(unix)] 171 | { 172 | use std::os::unix::fs::PermissionsExt; 173 | let metadata = fs::metadata(&temp_path).await?; 174 | let mut perms = metadata.permissions(); 175 | perms.set_mode(0o755); 176 | fs::set_permissions(&temp_path, perms).await?; 177 | } 178 | 179 | // Replace old binary with new one 180 | fs::rename(temp_path, current_exe).await?; 181 | 182 | Ok(()) 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | use pnet::datalink; 2 | use std::net::Ipv4Addr; 3 | 4 | pub fn get_ip_address() -> Option { 5 | for iface in datalink::interfaces() { 6 | for ip in iface.ips { 7 | if let pnet::ipnetwork::IpNetwork::V4(network) = ip { 8 | if !network.ip().is_loopback() { 9 | return Some(network.ip()); 10 | } 11 | } 12 | } 13 | } 14 | None 15 | } 16 | 17 | pub fn parse_u16(value: &serde_json::Value, field_name: &str) -> Result { 18 | match value { 19 | serde_json::Value::Number(n) if n.is_u64() => n 20 | .as_u64() 21 | .and_then(|n| u16::try_from(n).ok()) 22 | .ok_or_else(|| format!("{} must be a valid u16.", field_name)), 23 | serde_json::Value::String(s) => s 24 | .parse::() 25 | .map_err(|_| format!("{} must be a valid u16 string.", field_name)), 26 | _ => Err(format!( 27 | "{} must be a number or a valid string.", 28 | field_name 29 | )), 30 | } 31 | } 32 | --------------------------------------------------------------------------------