├── .config └── nextest.toml ├── .github ├── CODEOWNERS └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── clippy.toml ├── crates ├── svm-builds │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ └── src │ │ └── lib.rs └── svm-rs │ ├── Cargo.toml │ ├── README.md │ ├── build.rs │ ├── list │ └── linux-arm64-old.json │ └── src │ ├── bin │ ├── solc │ │ └── main.rs │ └── svm-bin │ │ ├── install.rs │ │ ├── list.rs │ │ ├── main.rs │ │ ├── print.rs │ │ ├── remove.rs │ │ ├── use.rs │ │ ├── utils.rs │ │ └── which.rs │ ├── error.rs │ ├── install.rs │ ├── lib.rs │ ├── paths.rs │ ├── platform.rs │ └── releases.rs └── release.toml /.config/nextest.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | retries = { backoff = "exponential", count = 2, delay = "3s", jitter = true } 3 | slow-timeout = { period = "1m", terminate-after = 3 } 4 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @DaniPopes @mattsse @zerosnacks 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 10 | cancel-in-progress: true 11 | 12 | env: 13 | CARGO_TERM_COLOR: always 14 | 15 | jobs: 16 | test: 17 | name: test ${{ matrix.runner }} 18 | runs-on: ${{ matrix.runner }} 19 | timeout-minutes: 30 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | runner: ["ubuntu-latest", "macos-13", "macos-14", "windows-latest"] 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: dtolnay/rust-toolchain@stable 27 | - uses: Swatinem/rust-cache@v2 28 | with: 29 | cache-on-failure: true 30 | - uses: taiki-e/install-action@cargo-nextest 31 | - name: test 32 | run: cargo nextest run --workspace --all-targets 33 | 34 | feature-checks: 35 | runs-on: ubuntu-latest 36 | timeout-minutes: 30 37 | steps: 38 | - uses: actions/checkout@v4 39 | - uses: dtolnay/rust-toolchain@stable 40 | - uses: taiki-e/install-action@cargo-hack 41 | - uses: Swatinem/rust-cache@v2 42 | with: 43 | cache-on-failure: true 44 | - name: cargo hack 45 | run: cargo hack check --feature-powerset --depth 2 46 | 47 | clippy: 48 | runs-on: ubuntu-latest 49 | timeout-minutes: 30 50 | steps: 51 | - uses: actions/checkout@v4 52 | - uses: dtolnay/rust-toolchain@clippy 53 | - uses: Swatinem/rust-cache@v2 54 | with: 55 | cache-on-failure: true 56 | - run: cargo clippy --workspace --all-targets --all-features 57 | env: 58 | RUSTFLAGS: -Dwarnings 59 | 60 | docs: 61 | runs-on: ubuntu-latest 62 | timeout-minutes: 30 63 | steps: 64 | - uses: actions/checkout@v4 65 | - uses: dtolnay/rust-toolchain@nightly 66 | - uses: Swatinem/rust-cache@v2 67 | with: 68 | cache-on-failure: true 69 | - run: cargo doc --workspace --all-features --no-deps --document-private-items 70 | env: 71 | RUSTDOCFLAGS: "--cfg docsrs -D warnings" 72 | 73 | fmt: 74 | runs-on: ubuntu-latest 75 | timeout-minutes: 30 76 | steps: 77 | - uses: actions/checkout@v4 78 | - uses: dtolnay/rust-toolchain@nightly 79 | with: 80 | components: rustfmt 81 | - run: cargo fmt --all --check 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased 4 | 5 | ## 0.2.7 6 | 7 | - Add blocking API support [#21](https://github.com/roynalnaruto/svm-rs/pull/21) 8 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 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 = "anstream" 22 | version = "0.6.18" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 25 | dependencies = [ 26 | "anstyle", 27 | "anstyle-parse", 28 | "anstyle-query", 29 | "anstyle-wincon", 30 | "colorchoice", 31 | "is_terminal_polyfill", 32 | "utf8parse", 33 | ] 34 | 35 | [[package]] 36 | name = "anstyle" 37 | version = "1.0.10" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 40 | 41 | [[package]] 42 | name = "anstyle-parse" 43 | version = "0.2.6" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 46 | dependencies = [ 47 | "utf8parse", 48 | ] 49 | 50 | [[package]] 51 | name = "anstyle-query" 52 | version = "1.1.2" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 55 | dependencies = [ 56 | "windows-sys 0.59.0", 57 | ] 58 | 59 | [[package]] 60 | name = "anstyle-wincon" 61 | version = "3.0.7" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" 64 | dependencies = [ 65 | "anstyle", 66 | "once_cell", 67 | "windows-sys 0.59.0", 68 | ] 69 | 70 | [[package]] 71 | name = "anyhow" 72 | version = "1.0.97" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" 75 | 76 | [[package]] 77 | name = "arbitrary" 78 | version = "1.4.1" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" 81 | dependencies = [ 82 | "derive_arbitrary", 83 | ] 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 = "backtrace" 93 | version = "0.3.74" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 96 | dependencies = [ 97 | "addr2line", 98 | "cfg-if", 99 | "libc", 100 | "miniz_oxide", 101 | "object", 102 | "rustc-demangle", 103 | "windows-targets 0.52.6", 104 | ] 105 | 106 | [[package]] 107 | name = "base64" 108 | version = "0.22.1" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 111 | 112 | [[package]] 113 | name = "bitflags" 114 | version = "2.9.0" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 117 | 118 | [[package]] 119 | name = "block-buffer" 120 | version = "0.10.4" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 123 | dependencies = [ 124 | "generic-array", 125 | ] 126 | 127 | [[package]] 128 | name = "bumpalo" 129 | version = "3.17.0" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 132 | 133 | [[package]] 134 | name = "bytes" 135 | version = "1.10.1" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 138 | 139 | [[package]] 140 | name = "cc" 141 | version = "1.2.18" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" 144 | dependencies = [ 145 | "shlex", 146 | ] 147 | 148 | [[package]] 149 | name = "cfg-if" 150 | version = "1.0.0" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 153 | 154 | [[package]] 155 | name = "cfg_aliases" 156 | version = "0.2.1" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 159 | 160 | [[package]] 161 | name = "clap" 162 | version = "4.5.35" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" 165 | dependencies = [ 166 | "clap_builder", 167 | "clap_derive", 168 | ] 169 | 170 | [[package]] 171 | name = "clap_builder" 172 | version = "4.5.35" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" 175 | dependencies = [ 176 | "anstream", 177 | "anstyle", 178 | "clap_lex", 179 | "strsim", 180 | ] 181 | 182 | [[package]] 183 | name = "clap_derive" 184 | version = "4.5.32" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" 187 | dependencies = [ 188 | "heck", 189 | "proc-macro2", 190 | "quote", 191 | "syn", 192 | ] 193 | 194 | [[package]] 195 | name = "clap_lex" 196 | version = "0.7.4" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 199 | 200 | [[package]] 201 | name = "colorchoice" 202 | version = "1.0.3" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 205 | 206 | [[package]] 207 | name = "console" 208 | version = "0.15.11" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" 211 | dependencies = [ 212 | "encode_unicode", 213 | "libc", 214 | "once_cell", 215 | "unicode-width", 216 | "windows-sys 0.59.0", 217 | ] 218 | 219 | [[package]] 220 | name = "const-hex" 221 | version = "1.14.0" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" 224 | dependencies = [ 225 | "cfg-if", 226 | "cpufeatures", 227 | "hex", 228 | "proptest", 229 | "serde", 230 | ] 231 | 232 | [[package]] 233 | name = "core-foundation" 234 | version = "0.9.4" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 237 | dependencies = [ 238 | "core-foundation-sys", 239 | "libc", 240 | ] 241 | 242 | [[package]] 243 | name = "core-foundation" 244 | version = "0.10.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" 247 | dependencies = [ 248 | "core-foundation-sys", 249 | "libc", 250 | ] 251 | 252 | [[package]] 253 | name = "core-foundation-sys" 254 | version = "0.8.7" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 257 | 258 | [[package]] 259 | name = "cpufeatures" 260 | version = "0.2.17" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" 263 | dependencies = [ 264 | "libc", 265 | ] 266 | 267 | [[package]] 268 | name = "crc32fast" 269 | version = "1.4.2" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 272 | dependencies = [ 273 | "cfg-if", 274 | ] 275 | 276 | [[package]] 277 | name = "crossbeam-utils" 278 | version = "0.8.21" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 281 | 282 | [[package]] 283 | name = "crypto-common" 284 | version = "0.1.6" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 287 | dependencies = [ 288 | "generic-array", 289 | "typenum", 290 | ] 291 | 292 | [[package]] 293 | name = "deranged" 294 | version = "0.4.0" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" 297 | dependencies = [ 298 | "powerfmt", 299 | ] 300 | 301 | [[package]] 302 | name = "derive_arbitrary" 303 | version = "1.4.1" 304 | source = "registry+https://github.com/rust-lang/crates.io-index" 305 | checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" 306 | dependencies = [ 307 | "proc-macro2", 308 | "quote", 309 | "syn", 310 | ] 311 | 312 | [[package]] 313 | name = "dialoguer" 314 | version = "0.11.0" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" 317 | dependencies = [ 318 | "console", 319 | "shell-words", 320 | "thiserror 1.0.69", 321 | ] 322 | 323 | [[package]] 324 | name = "digest" 325 | version = "0.10.7" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 328 | dependencies = [ 329 | "block-buffer", 330 | "crypto-common", 331 | ] 332 | 333 | [[package]] 334 | name = "dirs" 335 | version = "6.0.0" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" 338 | dependencies = [ 339 | "dirs-sys", 340 | ] 341 | 342 | [[package]] 343 | name = "dirs-sys" 344 | version = "0.5.0" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" 347 | dependencies = [ 348 | "libc", 349 | "option-ext", 350 | "redox_users", 351 | "windows-sys 0.59.0", 352 | ] 353 | 354 | [[package]] 355 | name = "displaydoc" 356 | version = "0.2.5" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 359 | dependencies = [ 360 | "proc-macro2", 361 | "quote", 362 | "syn", 363 | ] 364 | 365 | [[package]] 366 | name = "either" 367 | version = "1.15.0" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 370 | 371 | [[package]] 372 | name = "encode_unicode" 373 | version = "1.0.0" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" 376 | 377 | [[package]] 378 | name = "equivalent" 379 | version = "1.0.2" 380 | source = "registry+https://github.com/rust-lang/crates.io-index" 381 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 382 | 383 | [[package]] 384 | name = "errno" 385 | version = "0.3.11" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" 388 | dependencies = [ 389 | "libc", 390 | "windows-sys 0.59.0", 391 | ] 392 | 393 | [[package]] 394 | name = "fastrand" 395 | version = "2.3.0" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 398 | 399 | [[package]] 400 | name = "flate2" 401 | version = "1.1.1" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" 404 | dependencies = [ 405 | "crc32fast", 406 | "miniz_oxide", 407 | ] 408 | 409 | [[package]] 410 | name = "fnv" 411 | version = "1.0.7" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 414 | 415 | [[package]] 416 | name = "foreign-types" 417 | version = "0.3.2" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 420 | dependencies = [ 421 | "foreign-types-shared", 422 | ] 423 | 424 | [[package]] 425 | name = "foreign-types-shared" 426 | version = "0.1.1" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 429 | 430 | [[package]] 431 | name = "form_urlencoded" 432 | version = "1.2.1" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 435 | dependencies = [ 436 | "percent-encoding", 437 | ] 438 | 439 | [[package]] 440 | name = "fs4" 441 | version = "0.13.1" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "8640e34b88f7652208ce9e88b1a37a2ae95227d84abec377ccd3c5cfeb141ed4" 444 | dependencies = [ 445 | "rustix", 446 | "windows-sys 0.59.0", 447 | ] 448 | 449 | [[package]] 450 | name = "futures" 451 | version = "0.3.31" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 454 | dependencies = [ 455 | "futures-channel", 456 | "futures-core", 457 | "futures-executor", 458 | "futures-io", 459 | "futures-sink", 460 | "futures-task", 461 | "futures-util", 462 | ] 463 | 464 | [[package]] 465 | name = "futures-channel" 466 | version = "0.3.31" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 469 | dependencies = [ 470 | "futures-core", 471 | "futures-sink", 472 | ] 473 | 474 | [[package]] 475 | name = "futures-core" 476 | version = "0.3.31" 477 | source = "registry+https://github.com/rust-lang/crates.io-index" 478 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 479 | 480 | [[package]] 481 | name = "futures-executor" 482 | version = "0.3.31" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 485 | dependencies = [ 486 | "futures-core", 487 | "futures-task", 488 | "futures-util", 489 | ] 490 | 491 | [[package]] 492 | name = "futures-io" 493 | version = "0.3.31" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 496 | 497 | [[package]] 498 | name = "futures-sink" 499 | version = "0.3.31" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 502 | 503 | [[package]] 504 | name = "futures-task" 505 | version = "0.3.31" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 508 | 509 | [[package]] 510 | name = "futures-util" 511 | version = "0.3.31" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 514 | dependencies = [ 515 | "futures-channel", 516 | "futures-core", 517 | "futures-io", 518 | "futures-sink", 519 | "futures-task", 520 | "memchr", 521 | "pin-project-lite", 522 | "pin-utils", 523 | "slab", 524 | ] 525 | 526 | [[package]] 527 | name = "generic-array" 528 | version = "0.14.7" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 531 | dependencies = [ 532 | "typenum", 533 | "version_check", 534 | ] 535 | 536 | [[package]] 537 | name = "getrandom" 538 | version = "0.2.15" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 541 | dependencies = [ 542 | "cfg-if", 543 | "js-sys", 544 | "libc", 545 | "wasi 0.11.0+wasi-snapshot-preview1", 546 | "wasm-bindgen", 547 | ] 548 | 549 | [[package]] 550 | name = "getrandom" 551 | version = "0.3.2" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" 554 | dependencies = [ 555 | "cfg-if", 556 | "js-sys", 557 | "libc", 558 | "r-efi", 559 | "wasi 0.14.2+wasi-0.2.4", 560 | "wasm-bindgen", 561 | ] 562 | 563 | [[package]] 564 | name = "gimli" 565 | version = "0.31.1" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 568 | 569 | [[package]] 570 | name = "hashbrown" 571 | version = "0.15.2" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 574 | 575 | [[package]] 576 | name = "heck" 577 | version = "0.5.0" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 580 | 581 | [[package]] 582 | name = "hex" 583 | version = "0.4.3" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 586 | 587 | [[package]] 588 | name = "http" 589 | version = "1.3.1" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 592 | dependencies = [ 593 | "bytes", 594 | "fnv", 595 | "itoa", 596 | ] 597 | 598 | [[package]] 599 | name = "http-body" 600 | version = "1.0.1" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 603 | dependencies = [ 604 | "bytes", 605 | "http", 606 | ] 607 | 608 | [[package]] 609 | name = "http-body-util" 610 | version = "0.1.3" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 613 | dependencies = [ 614 | "bytes", 615 | "futures-core", 616 | "http", 617 | "http-body", 618 | "pin-project-lite", 619 | ] 620 | 621 | [[package]] 622 | name = "httparse" 623 | version = "1.10.1" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 626 | 627 | [[package]] 628 | name = "hyper" 629 | version = "1.6.0" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 632 | dependencies = [ 633 | "bytes", 634 | "futures-channel", 635 | "futures-util", 636 | "http", 637 | "http-body", 638 | "httparse", 639 | "itoa", 640 | "pin-project-lite", 641 | "smallvec", 642 | "tokio", 643 | "want", 644 | ] 645 | 646 | [[package]] 647 | name = "hyper-rustls" 648 | version = "0.27.5" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" 651 | dependencies = [ 652 | "futures-util", 653 | "http", 654 | "hyper", 655 | "hyper-util", 656 | "rustls", 657 | "rustls-native-certs", 658 | "rustls-pki-types", 659 | "tokio", 660 | "tokio-rustls", 661 | "tower-service", 662 | "webpki-roots", 663 | ] 664 | 665 | [[package]] 666 | name = "hyper-tls" 667 | version = "0.6.0" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 670 | dependencies = [ 671 | "bytes", 672 | "http-body-util", 673 | "hyper", 674 | "hyper-util", 675 | "native-tls", 676 | "tokio", 677 | "tokio-native-tls", 678 | "tower-service", 679 | ] 680 | 681 | [[package]] 682 | name = "hyper-util" 683 | version = "0.1.11" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" 686 | dependencies = [ 687 | "bytes", 688 | "futures-channel", 689 | "futures-util", 690 | "http", 691 | "http-body", 692 | "hyper", 693 | "libc", 694 | "pin-project-lite", 695 | "socket2", 696 | "tokio", 697 | "tower-service", 698 | "tracing", 699 | ] 700 | 701 | [[package]] 702 | name = "icu_collections" 703 | version = "1.5.0" 704 | source = "registry+https://github.com/rust-lang/crates.io-index" 705 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 706 | dependencies = [ 707 | "displaydoc", 708 | "yoke", 709 | "zerofrom", 710 | "zerovec", 711 | ] 712 | 713 | [[package]] 714 | name = "icu_locid" 715 | version = "1.5.0" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 718 | dependencies = [ 719 | "displaydoc", 720 | "litemap", 721 | "tinystr", 722 | "writeable", 723 | "zerovec", 724 | ] 725 | 726 | [[package]] 727 | name = "icu_locid_transform" 728 | version = "1.5.0" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 731 | dependencies = [ 732 | "displaydoc", 733 | "icu_locid", 734 | "icu_locid_transform_data", 735 | "icu_provider", 736 | "tinystr", 737 | "zerovec", 738 | ] 739 | 740 | [[package]] 741 | name = "icu_locid_transform_data" 742 | version = "1.5.1" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" 745 | 746 | [[package]] 747 | name = "icu_normalizer" 748 | version = "1.5.0" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 751 | dependencies = [ 752 | "displaydoc", 753 | "icu_collections", 754 | "icu_normalizer_data", 755 | "icu_properties", 756 | "icu_provider", 757 | "smallvec", 758 | "utf16_iter", 759 | "utf8_iter", 760 | "write16", 761 | "zerovec", 762 | ] 763 | 764 | [[package]] 765 | name = "icu_normalizer_data" 766 | version = "1.5.1" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" 769 | 770 | [[package]] 771 | name = "icu_properties" 772 | version = "1.5.1" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 775 | dependencies = [ 776 | "displaydoc", 777 | "icu_collections", 778 | "icu_locid_transform", 779 | "icu_properties_data", 780 | "icu_provider", 781 | "tinystr", 782 | "zerovec", 783 | ] 784 | 785 | [[package]] 786 | name = "icu_properties_data" 787 | version = "1.5.1" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" 790 | 791 | [[package]] 792 | name = "icu_provider" 793 | version = "1.5.0" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 796 | dependencies = [ 797 | "displaydoc", 798 | "icu_locid", 799 | "icu_provider_macros", 800 | "stable_deref_trait", 801 | "tinystr", 802 | "writeable", 803 | "yoke", 804 | "zerofrom", 805 | "zerovec", 806 | ] 807 | 808 | [[package]] 809 | name = "icu_provider_macros" 810 | version = "1.5.0" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 813 | dependencies = [ 814 | "proc-macro2", 815 | "quote", 816 | "syn", 817 | ] 818 | 819 | [[package]] 820 | name = "idna" 821 | version = "1.0.3" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 824 | dependencies = [ 825 | "idna_adapter", 826 | "smallvec", 827 | "utf8_iter", 828 | ] 829 | 830 | [[package]] 831 | name = "idna_adapter" 832 | version = "1.2.0" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 835 | dependencies = [ 836 | "icu_normalizer", 837 | "icu_properties", 838 | ] 839 | 840 | [[package]] 841 | name = "indexmap" 842 | version = "2.9.0" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 845 | dependencies = [ 846 | "equivalent", 847 | "hashbrown", 848 | ] 849 | 850 | [[package]] 851 | name = "indicatif" 852 | version = "0.17.11" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" 855 | dependencies = [ 856 | "console", 857 | "number_prefix", 858 | "portable-atomic", 859 | "web-time", 860 | ] 861 | 862 | [[package]] 863 | name = "ipnet" 864 | version = "2.11.0" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 867 | 868 | [[package]] 869 | name = "is_terminal_polyfill" 870 | version = "1.70.1" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 873 | 874 | [[package]] 875 | name = "itertools" 876 | version = "0.14.0" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" 879 | dependencies = [ 880 | "either", 881 | ] 882 | 883 | [[package]] 884 | name = "itoa" 885 | version = "1.0.15" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 888 | 889 | [[package]] 890 | name = "js-sys" 891 | version = "0.3.77" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 894 | dependencies = [ 895 | "once_cell", 896 | "wasm-bindgen", 897 | ] 898 | 899 | [[package]] 900 | name = "lazy_static" 901 | version = "1.5.0" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 904 | 905 | [[package]] 906 | name = "libc" 907 | version = "0.2.171" 908 | source = "registry+https://github.com/rust-lang/crates.io-index" 909 | checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" 910 | 911 | [[package]] 912 | name = "libredox" 913 | version = "0.1.3" 914 | source = "registry+https://github.com/rust-lang/crates.io-index" 915 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 916 | dependencies = [ 917 | "bitflags", 918 | "libc", 919 | ] 920 | 921 | [[package]] 922 | name = "linux-raw-sys" 923 | version = "0.9.4" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" 926 | 927 | [[package]] 928 | name = "litemap" 929 | version = "0.7.5" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" 932 | 933 | [[package]] 934 | name = "lock_api" 935 | version = "0.4.12" 936 | source = "registry+https://github.com/rust-lang/crates.io-index" 937 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 938 | dependencies = [ 939 | "autocfg", 940 | "scopeguard", 941 | ] 942 | 943 | [[package]] 944 | name = "lockfree-object-pool" 945 | version = "0.1.6" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" 948 | 949 | [[package]] 950 | name = "log" 951 | version = "0.4.27" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 954 | 955 | [[package]] 956 | name = "memchr" 957 | version = "2.7.4" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 960 | 961 | [[package]] 962 | name = "mime" 963 | version = "0.3.17" 964 | source = "registry+https://github.com/rust-lang/crates.io-index" 965 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 966 | 967 | [[package]] 968 | name = "miniz_oxide" 969 | version = "0.8.8" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" 972 | dependencies = [ 973 | "adler2", 974 | ] 975 | 976 | [[package]] 977 | name = "mio" 978 | version = "1.0.3" 979 | source = "registry+https://github.com/rust-lang/crates.io-index" 980 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 981 | dependencies = [ 982 | "libc", 983 | "wasi 0.11.0+wasi-snapshot-preview1", 984 | "windows-sys 0.52.0", 985 | ] 986 | 987 | [[package]] 988 | name = "native-tls" 989 | version = "0.2.14" 990 | source = "registry+https://github.com/rust-lang/crates.io-index" 991 | checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 992 | dependencies = [ 993 | "libc", 994 | "log", 995 | "openssl", 996 | "openssl-probe", 997 | "openssl-sys", 998 | "schannel", 999 | "security-framework 2.11.1", 1000 | "security-framework-sys", 1001 | "tempfile", 1002 | ] 1003 | 1004 | [[package]] 1005 | name = "num-conv" 1006 | version = "0.1.0" 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" 1008 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 1009 | 1010 | [[package]] 1011 | name = "num-traits" 1012 | version = "0.2.19" 1013 | source = "registry+https://github.com/rust-lang/crates.io-index" 1014 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1015 | dependencies = [ 1016 | "autocfg", 1017 | ] 1018 | 1019 | [[package]] 1020 | name = "num_threads" 1021 | version = "0.1.7" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" 1024 | dependencies = [ 1025 | "libc", 1026 | ] 1027 | 1028 | [[package]] 1029 | name = "number_prefix" 1030 | version = "0.4.0" 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" 1032 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 1033 | 1034 | [[package]] 1035 | name = "object" 1036 | version = "0.36.7" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1039 | dependencies = [ 1040 | "memchr", 1041 | ] 1042 | 1043 | [[package]] 1044 | name = "once_cell" 1045 | version = "1.21.3" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 1048 | 1049 | [[package]] 1050 | name = "openssl" 1051 | version = "0.10.72" 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" 1053 | checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" 1054 | dependencies = [ 1055 | "bitflags", 1056 | "cfg-if", 1057 | "foreign-types", 1058 | "libc", 1059 | "once_cell", 1060 | "openssl-macros", 1061 | "openssl-sys", 1062 | ] 1063 | 1064 | [[package]] 1065 | name = "openssl-macros" 1066 | version = "0.1.1" 1067 | source = "registry+https://github.com/rust-lang/crates.io-index" 1068 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1069 | dependencies = [ 1070 | "proc-macro2", 1071 | "quote", 1072 | "syn", 1073 | ] 1074 | 1075 | [[package]] 1076 | name = "openssl-probe" 1077 | version = "0.1.6" 1078 | source = "registry+https://github.com/rust-lang/crates.io-index" 1079 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1080 | 1081 | [[package]] 1082 | name = "openssl-sys" 1083 | version = "0.9.107" 1084 | source = "registry+https://github.com/rust-lang/crates.io-index" 1085 | checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" 1086 | dependencies = [ 1087 | "cc", 1088 | "libc", 1089 | "pkg-config", 1090 | "vcpkg", 1091 | ] 1092 | 1093 | [[package]] 1094 | name = "option-ext" 1095 | version = "0.2.0" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 1098 | 1099 | [[package]] 1100 | name = "parking_lot" 1101 | version = "0.12.3" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 1104 | dependencies = [ 1105 | "lock_api", 1106 | "parking_lot_core", 1107 | ] 1108 | 1109 | [[package]] 1110 | name = "parking_lot_core" 1111 | version = "0.9.10" 1112 | source = "registry+https://github.com/rust-lang/crates.io-index" 1113 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 1114 | dependencies = [ 1115 | "cfg-if", 1116 | "libc", 1117 | "redox_syscall", 1118 | "smallvec", 1119 | "windows-targets 0.52.6", 1120 | ] 1121 | 1122 | [[package]] 1123 | name = "percent-encoding" 1124 | version = "2.3.1" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1127 | 1128 | [[package]] 1129 | name = "pin-project-lite" 1130 | version = "0.2.16" 1131 | source = "registry+https://github.com/rust-lang/crates.io-index" 1132 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1133 | 1134 | [[package]] 1135 | name = "pin-utils" 1136 | version = "0.1.0" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1139 | 1140 | [[package]] 1141 | name = "pkg-config" 1142 | version = "0.3.32" 1143 | source = "registry+https://github.com/rust-lang/crates.io-index" 1144 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 1145 | 1146 | [[package]] 1147 | name = "portable-atomic" 1148 | version = "1.11.0" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" 1151 | 1152 | [[package]] 1153 | name = "powerfmt" 1154 | version = "0.2.0" 1155 | source = "registry+https://github.com/rust-lang/crates.io-index" 1156 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 1157 | 1158 | [[package]] 1159 | name = "ppv-lite86" 1160 | version = "0.2.21" 1161 | source = "registry+https://github.com/rust-lang/crates.io-index" 1162 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 1163 | dependencies = [ 1164 | "zerocopy", 1165 | ] 1166 | 1167 | [[package]] 1168 | name = "proc-macro2" 1169 | version = "1.0.94" 1170 | source = "registry+https://github.com/rust-lang/crates.io-index" 1171 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" 1172 | dependencies = [ 1173 | "unicode-ident", 1174 | ] 1175 | 1176 | [[package]] 1177 | name = "proptest" 1178 | version = "1.6.0" 1179 | source = "registry+https://github.com/rust-lang/crates.io-index" 1180 | checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" 1181 | dependencies = [ 1182 | "bitflags", 1183 | "lazy_static", 1184 | "num-traits", 1185 | "rand 0.8.5", 1186 | "rand_chacha 0.3.1", 1187 | "rand_xorshift", 1188 | "regex-syntax", 1189 | "unarray", 1190 | ] 1191 | 1192 | [[package]] 1193 | name = "quinn" 1194 | version = "0.11.7" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" 1197 | dependencies = [ 1198 | "bytes", 1199 | "cfg_aliases", 1200 | "pin-project-lite", 1201 | "quinn-proto", 1202 | "quinn-udp", 1203 | "rustc-hash", 1204 | "rustls", 1205 | "socket2", 1206 | "thiserror 2.0.12", 1207 | "tokio", 1208 | "tracing", 1209 | "web-time", 1210 | ] 1211 | 1212 | [[package]] 1213 | name = "quinn-proto" 1214 | version = "0.11.10" 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" 1216 | checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" 1217 | dependencies = [ 1218 | "bytes", 1219 | "getrandom 0.3.2", 1220 | "rand 0.9.0", 1221 | "ring", 1222 | "rustc-hash", 1223 | "rustls", 1224 | "rustls-pki-types", 1225 | "slab", 1226 | "thiserror 2.0.12", 1227 | "tinyvec", 1228 | "tracing", 1229 | "web-time", 1230 | ] 1231 | 1232 | [[package]] 1233 | name = "quinn-udp" 1234 | version = "0.5.11" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" 1237 | dependencies = [ 1238 | "cfg_aliases", 1239 | "libc", 1240 | "once_cell", 1241 | "socket2", 1242 | "tracing", 1243 | "windows-sys 0.59.0", 1244 | ] 1245 | 1246 | [[package]] 1247 | name = "quote" 1248 | version = "1.0.40" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 1251 | dependencies = [ 1252 | "proc-macro2", 1253 | ] 1254 | 1255 | [[package]] 1256 | name = "r-efi" 1257 | version = "5.2.0" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 1260 | 1261 | [[package]] 1262 | name = "rand" 1263 | version = "0.8.5" 1264 | source = "registry+https://github.com/rust-lang/crates.io-index" 1265 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1266 | dependencies = [ 1267 | "libc", 1268 | "rand_chacha 0.3.1", 1269 | "rand_core 0.6.4", 1270 | ] 1271 | 1272 | [[package]] 1273 | name = "rand" 1274 | version = "0.9.0" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" 1277 | dependencies = [ 1278 | "rand_chacha 0.9.0", 1279 | "rand_core 0.9.3", 1280 | "zerocopy", 1281 | ] 1282 | 1283 | [[package]] 1284 | name = "rand_chacha" 1285 | version = "0.3.1" 1286 | source = "registry+https://github.com/rust-lang/crates.io-index" 1287 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1288 | dependencies = [ 1289 | "ppv-lite86", 1290 | "rand_core 0.6.4", 1291 | ] 1292 | 1293 | [[package]] 1294 | name = "rand_chacha" 1295 | version = "0.9.0" 1296 | source = "registry+https://github.com/rust-lang/crates.io-index" 1297 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 1298 | dependencies = [ 1299 | "ppv-lite86", 1300 | "rand_core 0.9.3", 1301 | ] 1302 | 1303 | [[package]] 1304 | name = "rand_core" 1305 | version = "0.6.4" 1306 | source = "registry+https://github.com/rust-lang/crates.io-index" 1307 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1308 | dependencies = [ 1309 | "getrandom 0.2.15", 1310 | ] 1311 | 1312 | [[package]] 1313 | name = "rand_core" 1314 | version = "0.9.3" 1315 | source = "registry+https://github.com/rust-lang/crates.io-index" 1316 | checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 1317 | dependencies = [ 1318 | "getrandom 0.3.2", 1319 | ] 1320 | 1321 | [[package]] 1322 | name = "rand_xorshift" 1323 | version = "0.3.0" 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" 1325 | checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" 1326 | dependencies = [ 1327 | "rand_core 0.6.4", 1328 | ] 1329 | 1330 | [[package]] 1331 | name = "redox_syscall" 1332 | version = "0.5.11" 1333 | source = "registry+https://github.com/rust-lang/crates.io-index" 1334 | checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" 1335 | dependencies = [ 1336 | "bitflags", 1337 | ] 1338 | 1339 | [[package]] 1340 | name = "redox_users" 1341 | version = "0.5.0" 1342 | source = "registry+https://github.com/rust-lang/crates.io-index" 1343 | checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" 1344 | dependencies = [ 1345 | "getrandom 0.2.15", 1346 | "libredox", 1347 | "thiserror 2.0.12", 1348 | ] 1349 | 1350 | [[package]] 1351 | name = "regex-syntax" 1352 | version = "0.8.5" 1353 | source = "registry+https://github.com/rust-lang/crates.io-index" 1354 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 1355 | 1356 | [[package]] 1357 | name = "reqwest" 1358 | version = "0.12.15" 1359 | source = "registry+https://github.com/rust-lang/crates.io-index" 1360 | checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" 1361 | dependencies = [ 1362 | "base64", 1363 | "bytes", 1364 | "futures-channel", 1365 | "futures-core", 1366 | "futures-util", 1367 | "http", 1368 | "http-body", 1369 | "http-body-util", 1370 | "hyper", 1371 | "hyper-rustls", 1372 | "hyper-tls", 1373 | "hyper-util", 1374 | "ipnet", 1375 | "js-sys", 1376 | "log", 1377 | "mime", 1378 | "native-tls", 1379 | "once_cell", 1380 | "percent-encoding", 1381 | "pin-project-lite", 1382 | "quinn", 1383 | "rustls", 1384 | "rustls-native-certs", 1385 | "rustls-pemfile", 1386 | "rustls-pki-types", 1387 | "serde", 1388 | "serde_json", 1389 | "serde_urlencoded", 1390 | "sync_wrapper", 1391 | "tokio", 1392 | "tokio-native-tls", 1393 | "tokio-rustls", 1394 | "tokio-socks", 1395 | "tower", 1396 | "tower-service", 1397 | "url", 1398 | "wasm-bindgen", 1399 | "wasm-bindgen-futures", 1400 | "web-sys", 1401 | "webpki-roots", 1402 | "windows-registry", 1403 | ] 1404 | 1405 | [[package]] 1406 | name = "ring" 1407 | version = "0.17.14" 1408 | source = "registry+https://github.com/rust-lang/crates.io-index" 1409 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 1410 | dependencies = [ 1411 | "cc", 1412 | "cfg-if", 1413 | "getrandom 0.2.15", 1414 | "libc", 1415 | "untrusted", 1416 | "windows-sys 0.52.0", 1417 | ] 1418 | 1419 | [[package]] 1420 | name = "rustc-demangle" 1421 | version = "0.1.24" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1424 | 1425 | [[package]] 1426 | name = "rustc-hash" 1427 | version = "2.1.1" 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" 1429 | checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" 1430 | 1431 | [[package]] 1432 | name = "rustix" 1433 | version = "1.0.5" 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" 1435 | checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" 1436 | dependencies = [ 1437 | "bitflags", 1438 | "errno", 1439 | "libc", 1440 | "linux-raw-sys", 1441 | "windows-sys 0.59.0", 1442 | ] 1443 | 1444 | [[package]] 1445 | name = "rustls" 1446 | version = "0.23.25" 1447 | source = "registry+https://github.com/rust-lang/crates.io-index" 1448 | checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" 1449 | dependencies = [ 1450 | "once_cell", 1451 | "ring", 1452 | "rustls-pki-types", 1453 | "rustls-webpki", 1454 | "subtle", 1455 | "zeroize", 1456 | ] 1457 | 1458 | [[package]] 1459 | name = "rustls-native-certs" 1460 | version = "0.8.1" 1461 | source = "registry+https://github.com/rust-lang/crates.io-index" 1462 | checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" 1463 | dependencies = [ 1464 | "openssl-probe", 1465 | "rustls-pki-types", 1466 | "schannel", 1467 | "security-framework 3.2.0", 1468 | ] 1469 | 1470 | [[package]] 1471 | name = "rustls-pemfile" 1472 | version = "2.2.0" 1473 | source = "registry+https://github.com/rust-lang/crates.io-index" 1474 | checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" 1475 | dependencies = [ 1476 | "rustls-pki-types", 1477 | ] 1478 | 1479 | [[package]] 1480 | name = "rustls-pki-types" 1481 | version = "1.11.0" 1482 | source = "registry+https://github.com/rust-lang/crates.io-index" 1483 | checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" 1484 | dependencies = [ 1485 | "web-time", 1486 | ] 1487 | 1488 | [[package]] 1489 | name = "rustls-webpki" 1490 | version = "0.103.1" 1491 | source = "registry+https://github.com/rust-lang/crates.io-index" 1492 | checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" 1493 | dependencies = [ 1494 | "ring", 1495 | "rustls-pki-types", 1496 | "untrusted", 1497 | ] 1498 | 1499 | [[package]] 1500 | name = "rustversion" 1501 | version = "1.0.20" 1502 | source = "registry+https://github.com/rust-lang/crates.io-index" 1503 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 1504 | 1505 | [[package]] 1506 | name = "ryu" 1507 | version = "1.0.20" 1508 | source = "registry+https://github.com/rust-lang/crates.io-index" 1509 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1510 | 1511 | [[package]] 1512 | name = "scc" 1513 | version = "2.3.3" 1514 | source = "registry+https://github.com/rust-lang/crates.io-index" 1515 | checksum = "ea091f6cac2595aa38993f04f4ee692ed43757035c36e67c180b6828356385b1" 1516 | dependencies = [ 1517 | "sdd", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "schannel" 1522 | version = "0.1.27" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 1525 | dependencies = [ 1526 | "windows-sys 0.59.0", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "scopeguard" 1531 | version = "1.2.0" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1534 | 1535 | [[package]] 1536 | name = "sdd" 1537 | version = "3.0.8" 1538 | source = "registry+https://github.com/rust-lang/crates.io-index" 1539 | checksum = "584e070911c7017da6cb2eb0788d09f43d789029b5877d3e5ecc8acf86ceee21" 1540 | 1541 | [[package]] 1542 | name = "security-framework" 1543 | version = "2.11.1" 1544 | source = "registry+https://github.com/rust-lang/crates.io-index" 1545 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 1546 | dependencies = [ 1547 | "bitflags", 1548 | "core-foundation 0.9.4", 1549 | "core-foundation-sys", 1550 | "libc", 1551 | "security-framework-sys", 1552 | ] 1553 | 1554 | [[package]] 1555 | name = "security-framework" 1556 | version = "3.2.0" 1557 | source = "registry+https://github.com/rust-lang/crates.io-index" 1558 | checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" 1559 | dependencies = [ 1560 | "bitflags", 1561 | "core-foundation 0.10.0", 1562 | "core-foundation-sys", 1563 | "libc", 1564 | "security-framework-sys", 1565 | ] 1566 | 1567 | [[package]] 1568 | name = "security-framework-sys" 1569 | version = "2.14.0" 1570 | source = "registry+https://github.com/rust-lang/crates.io-index" 1571 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 1572 | dependencies = [ 1573 | "core-foundation-sys", 1574 | "libc", 1575 | ] 1576 | 1577 | [[package]] 1578 | name = "semver" 1579 | version = "1.0.26" 1580 | source = "registry+https://github.com/rust-lang/crates.io-index" 1581 | checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" 1582 | dependencies = [ 1583 | "serde", 1584 | ] 1585 | 1586 | [[package]] 1587 | name = "serde" 1588 | version = "1.0.219" 1589 | source = "registry+https://github.com/rust-lang/crates.io-index" 1590 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 1591 | dependencies = [ 1592 | "serde_derive", 1593 | ] 1594 | 1595 | [[package]] 1596 | name = "serde_derive" 1597 | version = "1.0.219" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 1600 | dependencies = [ 1601 | "proc-macro2", 1602 | "quote", 1603 | "syn", 1604 | ] 1605 | 1606 | [[package]] 1607 | name = "serde_json" 1608 | version = "1.0.140" 1609 | source = "registry+https://github.com/rust-lang/crates.io-index" 1610 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 1611 | dependencies = [ 1612 | "itoa", 1613 | "memchr", 1614 | "ryu", 1615 | "serde", 1616 | ] 1617 | 1618 | [[package]] 1619 | name = "serde_urlencoded" 1620 | version = "0.7.1" 1621 | source = "registry+https://github.com/rust-lang/crates.io-index" 1622 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1623 | dependencies = [ 1624 | "form_urlencoded", 1625 | "itoa", 1626 | "ryu", 1627 | "serde", 1628 | ] 1629 | 1630 | [[package]] 1631 | name = "serial_test" 1632 | version = "3.2.0" 1633 | source = "registry+https://github.com/rust-lang/crates.io-index" 1634 | checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" 1635 | dependencies = [ 1636 | "futures", 1637 | "log", 1638 | "once_cell", 1639 | "parking_lot", 1640 | "scc", 1641 | "serial_test_derive", 1642 | ] 1643 | 1644 | [[package]] 1645 | name = "serial_test_derive" 1646 | version = "3.2.0" 1647 | source = "registry+https://github.com/rust-lang/crates.io-index" 1648 | checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" 1649 | dependencies = [ 1650 | "proc-macro2", 1651 | "quote", 1652 | "syn", 1653 | ] 1654 | 1655 | [[package]] 1656 | name = "sha2" 1657 | version = "0.10.8" 1658 | source = "registry+https://github.com/rust-lang/crates.io-index" 1659 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 1660 | dependencies = [ 1661 | "cfg-if", 1662 | "cpufeatures", 1663 | "digest", 1664 | ] 1665 | 1666 | [[package]] 1667 | name = "shell-words" 1668 | version = "1.1.0" 1669 | source = "registry+https://github.com/rust-lang/crates.io-index" 1670 | checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" 1671 | 1672 | [[package]] 1673 | name = "shlex" 1674 | version = "1.3.0" 1675 | source = "registry+https://github.com/rust-lang/crates.io-index" 1676 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1677 | 1678 | [[package]] 1679 | name = "simd-adler32" 1680 | version = "0.3.7" 1681 | source = "registry+https://github.com/rust-lang/crates.io-index" 1682 | checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 1683 | 1684 | [[package]] 1685 | name = "slab" 1686 | version = "0.4.9" 1687 | source = "registry+https://github.com/rust-lang/crates.io-index" 1688 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1689 | dependencies = [ 1690 | "autocfg", 1691 | ] 1692 | 1693 | [[package]] 1694 | name = "smallvec" 1695 | version = "1.15.0" 1696 | source = "registry+https://github.com/rust-lang/crates.io-index" 1697 | checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" 1698 | 1699 | [[package]] 1700 | name = "socket2" 1701 | version = "0.5.9" 1702 | source = "registry+https://github.com/rust-lang/crates.io-index" 1703 | checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" 1704 | dependencies = [ 1705 | "libc", 1706 | "windows-sys 0.52.0", 1707 | ] 1708 | 1709 | [[package]] 1710 | name = "stable_deref_trait" 1711 | version = "1.2.0" 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" 1713 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1714 | 1715 | [[package]] 1716 | name = "strsim" 1717 | version = "0.11.1" 1718 | source = "registry+https://github.com/rust-lang/crates.io-index" 1719 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 1720 | 1721 | [[package]] 1722 | name = "subtle" 1723 | version = "2.6.1" 1724 | source = "registry+https://github.com/rust-lang/crates.io-index" 1725 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1726 | 1727 | [[package]] 1728 | name = "svm-rs" 1729 | version = "0.5.16" 1730 | dependencies = [ 1731 | "anyhow", 1732 | "clap", 1733 | "console", 1734 | "const-hex", 1735 | "dialoguer", 1736 | "dirs", 1737 | "fs4", 1738 | "indicatif", 1739 | "itertools", 1740 | "rand 0.9.0", 1741 | "reqwest", 1742 | "semver", 1743 | "serde", 1744 | "serde_json", 1745 | "serial_test", 1746 | "sha2", 1747 | "tempfile", 1748 | "thiserror 1.0.69", 1749 | "tokio", 1750 | "url", 1751 | "vergen", 1752 | "zip", 1753 | ] 1754 | 1755 | [[package]] 1756 | name = "svm-rs-builds" 1757 | version = "0.5.16" 1758 | dependencies = [ 1759 | "const-hex", 1760 | "semver", 1761 | "serde_json", 1762 | "svm-rs", 1763 | ] 1764 | 1765 | [[package]] 1766 | name = "syn" 1767 | version = "2.0.100" 1768 | source = "registry+https://github.com/rust-lang/crates.io-index" 1769 | checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 1770 | dependencies = [ 1771 | "proc-macro2", 1772 | "quote", 1773 | "unicode-ident", 1774 | ] 1775 | 1776 | [[package]] 1777 | name = "sync_wrapper" 1778 | version = "1.0.2" 1779 | source = "registry+https://github.com/rust-lang/crates.io-index" 1780 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1781 | dependencies = [ 1782 | "futures-core", 1783 | ] 1784 | 1785 | [[package]] 1786 | name = "synstructure" 1787 | version = "0.13.1" 1788 | source = "registry+https://github.com/rust-lang/crates.io-index" 1789 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 1790 | dependencies = [ 1791 | "proc-macro2", 1792 | "quote", 1793 | "syn", 1794 | ] 1795 | 1796 | [[package]] 1797 | name = "tempfile" 1798 | version = "3.19.1" 1799 | source = "registry+https://github.com/rust-lang/crates.io-index" 1800 | checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" 1801 | dependencies = [ 1802 | "fastrand", 1803 | "getrandom 0.3.2", 1804 | "once_cell", 1805 | "rustix", 1806 | "windows-sys 0.59.0", 1807 | ] 1808 | 1809 | [[package]] 1810 | name = "thiserror" 1811 | version = "1.0.69" 1812 | source = "registry+https://github.com/rust-lang/crates.io-index" 1813 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1814 | dependencies = [ 1815 | "thiserror-impl 1.0.69", 1816 | ] 1817 | 1818 | [[package]] 1819 | name = "thiserror" 1820 | version = "2.0.12" 1821 | source = "registry+https://github.com/rust-lang/crates.io-index" 1822 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 1823 | dependencies = [ 1824 | "thiserror-impl 2.0.12", 1825 | ] 1826 | 1827 | [[package]] 1828 | name = "thiserror-impl" 1829 | version = "1.0.69" 1830 | source = "registry+https://github.com/rust-lang/crates.io-index" 1831 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1832 | dependencies = [ 1833 | "proc-macro2", 1834 | "quote", 1835 | "syn", 1836 | ] 1837 | 1838 | [[package]] 1839 | name = "thiserror-impl" 1840 | version = "2.0.12" 1841 | source = "registry+https://github.com/rust-lang/crates.io-index" 1842 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 1843 | dependencies = [ 1844 | "proc-macro2", 1845 | "quote", 1846 | "syn", 1847 | ] 1848 | 1849 | [[package]] 1850 | name = "time" 1851 | version = "0.3.41" 1852 | source = "registry+https://github.com/rust-lang/crates.io-index" 1853 | checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" 1854 | dependencies = [ 1855 | "deranged", 1856 | "itoa", 1857 | "libc", 1858 | "num-conv", 1859 | "num_threads", 1860 | "powerfmt", 1861 | "serde", 1862 | "time-core", 1863 | "time-macros", 1864 | ] 1865 | 1866 | [[package]] 1867 | name = "time-core" 1868 | version = "0.1.4" 1869 | source = "registry+https://github.com/rust-lang/crates.io-index" 1870 | checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" 1871 | 1872 | [[package]] 1873 | name = "time-macros" 1874 | version = "0.2.22" 1875 | source = "registry+https://github.com/rust-lang/crates.io-index" 1876 | checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" 1877 | dependencies = [ 1878 | "num-conv", 1879 | "time-core", 1880 | ] 1881 | 1882 | [[package]] 1883 | name = "tinystr" 1884 | version = "0.7.6" 1885 | source = "registry+https://github.com/rust-lang/crates.io-index" 1886 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 1887 | dependencies = [ 1888 | "displaydoc", 1889 | "zerovec", 1890 | ] 1891 | 1892 | [[package]] 1893 | name = "tinyvec" 1894 | version = "1.9.0" 1895 | source = "registry+https://github.com/rust-lang/crates.io-index" 1896 | checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" 1897 | dependencies = [ 1898 | "tinyvec_macros", 1899 | ] 1900 | 1901 | [[package]] 1902 | name = "tinyvec_macros" 1903 | version = "0.1.1" 1904 | source = "registry+https://github.com/rust-lang/crates.io-index" 1905 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1906 | 1907 | [[package]] 1908 | name = "tokio" 1909 | version = "1.44.2" 1910 | source = "registry+https://github.com/rust-lang/crates.io-index" 1911 | checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" 1912 | dependencies = [ 1913 | "backtrace", 1914 | "bytes", 1915 | "libc", 1916 | "mio", 1917 | "pin-project-lite", 1918 | "socket2", 1919 | "tokio-macros", 1920 | "windows-sys 0.52.0", 1921 | ] 1922 | 1923 | [[package]] 1924 | name = "tokio-macros" 1925 | version = "2.5.0" 1926 | source = "registry+https://github.com/rust-lang/crates.io-index" 1927 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 1928 | dependencies = [ 1929 | "proc-macro2", 1930 | "quote", 1931 | "syn", 1932 | ] 1933 | 1934 | [[package]] 1935 | name = "tokio-native-tls" 1936 | version = "0.3.1" 1937 | source = "registry+https://github.com/rust-lang/crates.io-index" 1938 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 1939 | dependencies = [ 1940 | "native-tls", 1941 | "tokio", 1942 | ] 1943 | 1944 | [[package]] 1945 | name = "tokio-rustls" 1946 | version = "0.26.2" 1947 | source = "registry+https://github.com/rust-lang/crates.io-index" 1948 | checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 1949 | dependencies = [ 1950 | "rustls", 1951 | "tokio", 1952 | ] 1953 | 1954 | [[package]] 1955 | name = "tokio-socks" 1956 | version = "0.5.2" 1957 | source = "registry+https://github.com/rust-lang/crates.io-index" 1958 | checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" 1959 | dependencies = [ 1960 | "either", 1961 | "futures-util", 1962 | "thiserror 1.0.69", 1963 | "tokio", 1964 | ] 1965 | 1966 | [[package]] 1967 | name = "tower" 1968 | version = "0.5.2" 1969 | source = "registry+https://github.com/rust-lang/crates.io-index" 1970 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 1971 | dependencies = [ 1972 | "futures-core", 1973 | "futures-util", 1974 | "pin-project-lite", 1975 | "sync_wrapper", 1976 | "tokio", 1977 | "tower-layer", 1978 | "tower-service", 1979 | ] 1980 | 1981 | [[package]] 1982 | name = "tower-layer" 1983 | version = "0.3.3" 1984 | source = "registry+https://github.com/rust-lang/crates.io-index" 1985 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1986 | 1987 | [[package]] 1988 | name = "tower-service" 1989 | version = "0.3.3" 1990 | source = "registry+https://github.com/rust-lang/crates.io-index" 1991 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1992 | 1993 | [[package]] 1994 | name = "tracing" 1995 | version = "0.1.41" 1996 | source = "registry+https://github.com/rust-lang/crates.io-index" 1997 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 1998 | dependencies = [ 1999 | "pin-project-lite", 2000 | "tracing-core", 2001 | ] 2002 | 2003 | [[package]] 2004 | name = "tracing-core" 2005 | version = "0.1.33" 2006 | source = "registry+https://github.com/rust-lang/crates.io-index" 2007 | checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 2008 | dependencies = [ 2009 | "once_cell", 2010 | ] 2011 | 2012 | [[package]] 2013 | name = "try-lock" 2014 | version = "0.2.5" 2015 | source = "registry+https://github.com/rust-lang/crates.io-index" 2016 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2017 | 2018 | [[package]] 2019 | name = "typenum" 2020 | version = "1.18.0" 2021 | source = "registry+https://github.com/rust-lang/crates.io-index" 2022 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" 2023 | 2024 | [[package]] 2025 | name = "unarray" 2026 | version = "0.1.4" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" 2029 | 2030 | [[package]] 2031 | name = "unicode-ident" 2032 | version = "1.0.18" 2033 | source = "registry+https://github.com/rust-lang/crates.io-index" 2034 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 2035 | 2036 | [[package]] 2037 | name = "unicode-width" 2038 | version = "0.2.0" 2039 | source = "registry+https://github.com/rust-lang/crates.io-index" 2040 | checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" 2041 | 2042 | [[package]] 2043 | name = "untrusted" 2044 | version = "0.9.0" 2045 | source = "registry+https://github.com/rust-lang/crates.io-index" 2046 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 2047 | 2048 | [[package]] 2049 | name = "url" 2050 | version = "2.5.4" 2051 | source = "registry+https://github.com/rust-lang/crates.io-index" 2052 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 2053 | dependencies = [ 2054 | "form_urlencoded", 2055 | "idna", 2056 | "percent-encoding", 2057 | ] 2058 | 2059 | [[package]] 2060 | name = "utf16_iter" 2061 | version = "1.0.5" 2062 | source = "registry+https://github.com/rust-lang/crates.io-index" 2063 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 2064 | 2065 | [[package]] 2066 | name = "utf8_iter" 2067 | version = "1.0.4" 2068 | source = "registry+https://github.com/rust-lang/crates.io-index" 2069 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2070 | 2071 | [[package]] 2072 | name = "utf8parse" 2073 | version = "0.2.2" 2074 | source = "registry+https://github.com/rust-lang/crates.io-index" 2075 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 2076 | 2077 | [[package]] 2078 | name = "vcpkg" 2079 | version = "0.2.15" 2080 | source = "registry+https://github.com/rust-lang/crates.io-index" 2081 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2082 | 2083 | [[package]] 2084 | name = "vergen" 2085 | version = "8.3.2" 2086 | source = "registry+https://github.com/rust-lang/crates.io-index" 2087 | checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" 2088 | dependencies = [ 2089 | "anyhow", 2090 | "cfg-if", 2091 | "rustversion", 2092 | "time", 2093 | ] 2094 | 2095 | [[package]] 2096 | name = "version_check" 2097 | version = "0.9.5" 2098 | source = "registry+https://github.com/rust-lang/crates.io-index" 2099 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2100 | 2101 | [[package]] 2102 | name = "want" 2103 | version = "0.3.1" 2104 | source = "registry+https://github.com/rust-lang/crates.io-index" 2105 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2106 | dependencies = [ 2107 | "try-lock", 2108 | ] 2109 | 2110 | [[package]] 2111 | name = "wasi" 2112 | version = "0.11.0+wasi-snapshot-preview1" 2113 | source = "registry+https://github.com/rust-lang/crates.io-index" 2114 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2115 | 2116 | [[package]] 2117 | name = "wasi" 2118 | version = "0.14.2+wasi-0.2.4" 2119 | source = "registry+https://github.com/rust-lang/crates.io-index" 2120 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 2121 | dependencies = [ 2122 | "wit-bindgen-rt", 2123 | ] 2124 | 2125 | [[package]] 2126 | name = "wasm-bindgen" 2127 | version = "0.2.100" 2128 | source = "registry+https://github.com/rust-lang/crates.io-index" 2129 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 2130 | dependencies = [ 2131 | "cfg-if", 2132 | "once_cell", 2133 | "rustversion", 2134 | "wasm-bindgen-macro", 2135 | ] 2136 | 2137 | [[package]] 2138 | name = "wasm-bindgen-backend" 2139 | version = "0.2.100" 2140 | source = "registry+https://github.com/rust-lang/crates.io-index" 2141 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 2142 | dependencies = [ 2143 | "bumpalo", 2144 | "log", 2145 | "proc-macro2", 2146 | "quote", 2147 | "syn", 2148 | "wasm-bindgen-shared", 2149 | ] 2150 | 2151 | [[package]] 2152 | name = "wasm-bindgen-futures" 2153 | version = "0.4.50" 2154 | source = "registry+https://github.com/rust-lang/crates.io-index" 2155 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 2156 | dependencies = [ 2157 | "cfg-if", 2158 | "js-sys", 2159 | "once_cell", 2160 | "wasm-bindgen", 2161 | "web-sys", 2162 | ] 2163 | 2164 | [[package]] 2165 | name = "wasm-bindgen-macro" 2166 | version = "0.2.100" 2167 | source = "registry+https://github.com/rust-lang/crates.io-index" 2168 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 2169 | dependencies = [ 2170 | "quote", 2171 | "wasm-bindgen-macro-support", 2172 | ] 2173 | 2174 | [[package]] 2175 | name = "wasm-bindgen-macro-support" 2176 | version = "0.2.100" 2177 | source = "registry+https://github.com/rust-lang/crates.io-index" 2178 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 2179 | dependencies = [ 2180 | "proc-macro2", 2181 | "quote", 2182 | "syn", 2183 | "wasm-bindgen-backend", 2184 | "wasm-bindgen-shared", 2185 | ] 2186 | 2187 | [[package]] 2188 | name = "wasm-bindgen-shared" 2189 | version = "0.2.100" 2190 | source = "registry+https://github.com/rust-lang/crates.io-index" 2191 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 2192 | dependencies = [ 2193 | "unicode-ident", 2194 | ] 2195 | 2196 | [[package]] 2197 | name = "web-sys" 2198 | version = "0.3.77" 2199 | source = "registry+https://github.com/rust-lang/crates.io-index" 2200 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 2201 | dependencies = [ 2202 | "js-sys", 2203 | "wasm-bindgen", 2204 | ] 2205 | 2206 | [[package]] 2207 | name = "web-time" 2208 | version = "1.1.0" 2209 | source = "registry+https://github.com/rust-lang/crates.io-index" 2210 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 2211 | dependencies = [ 2212 | "js-sys", 2213 | "wasm-bindgen", 2214 | ] 2215 | 2216 | [[package]] 2217 | name = "webpki-roots" 2218 | version = "0.26.8" 2219 | source = "registry+https://github.com/rust-lang/crates.io-index" 2220 | checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" 2221 | dependencies = [ 2222 | "rustls-pki-types", 2223 | ] 2224 | 2225 | [[package]] 2226 | name = "windows-link" 2227 | version = "0.1.1" 2228 | source = "registry+https://github.com/rust-lang/crates.io-index" 2229 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 2230 | 2231 | [[package]] 2232 | name = "windows-registry" 2233 | version = "0.4.0" 2234 | source = "registry+https://github.com/rust-lang/crates.io-index" 2235 | checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" 2236 | dependencies = [ 2237 | "windows-result", 2238 | "windows-strings", 2239 | "windows-targets 0.53.0", 2240 | ] 2241 | 2242 | [[package]] 2243 | name = "windows-result" 2244 | version = "0.3.2" 2245 | source = "registry+https://github.com/rust-lang/crates.io-index" 2246 | checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" 2247 | dependencies = [ 2248 | "windows-link", 2249 | ] 2250 | 2251 | [[package]] 2252 | name = "windows-strings" 2253 | version = "0.3.1" 2254 | source = "registry+https://github.com/rust-lang/crates.io-index" 2255 | checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 2256 | dependencies = [ 2257 | "windows-link", 2258 | ] 2259 | 2260 | [[package]] 2261 | name = "windows-sys" 2262 | version = "0.52.0" 2263 | source = "registry+https://github.com/rust-lang/crates.io-index" 2264 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2265 | dependencies = [ 2266 | "windows-targets 0.52.6", 2267 | ] 2268 | 2269 | [[package]] 2270 | name = "windows-sys" 2271 | version = "0.59.0" 2272 | source = "registry+https://github.com/rust-lang/crates.io-index" 2273 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2274 | dependencies = [ 2275 | "windows-targets 0.52.6", 2276 | ] 2277 | 2278 | [[package]] 2279 | name = "windows-targets" 2280 | version = "0.52.6" 2281 | source = "registry+https://github.com/rust-lang/crates.io-index" 2282 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2283 | dependencies = [ 2284 | "windows_aarch64_gnullvm 0.52.6", 2285 | "windows_aarch64_msvc 0.52.6", 2286 | "windows_i686_gnu 0.52.6", 2287 | "windows_i686_gnullvm 0.52.6", 2288 | "windows_i686_msvc 0.52.6", 2289 | "windows_x86_64_gnu 0.52.6", 2290 | "windows_x86_64_gnullvm 0.52.6", 2291 | "windows_x86_64_msvc 0.52.6", 2292 | ] 2293 | 2294 | [[package]] 2295 | name = "windows-targets" 2296 | version = "0.53.0" 2297 | source = "registry+https://github.com/rust-lang/crates.io-index" 2298 | checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" 2299 | dependencies = [ 2300 | "windows_aarch64_gnullvm 0.53.0", 2301 | "windows_aarch64_msvc 0.53.0", 2302 | "windows_i686_gnu 0.53.0", 2303 | "windows_i686_gnullvm 0.53.0", 2304 | "windows_i686_msvc 0.53.0", 2305 | "windows_x86_64_gnu 0.53.0", 2306 | "windows_x86_64_gnullvm 0.53.0", 2307 | "windows_x86_64_msvc 0.53.0", 2308 | ] 2309 | 2310 | [[package]] 2311 | name = "windows_aarch64_gnullvm" 2312 | version = "0.52.6" 2313 | source = "registry+https://github.com/rust-lang/crates.io-index" 2314 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2315 | 2316 | [[package]] 2317 | name = "windows_aarch64_gnullvm" 2318 | version = "0.53.0" 2319 | source = "registry+https://github.com/rust-lang/crates.io-index" 2320 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 2321 | 2322 | [[package]] 2323 | name = "windows_aarch64_msvc" 2324 | version = "0.52.6" 2325 | source = "registry+https://github.com/rust-lang/crates.io-index" 2326 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2327 | 2328 | [[package]] 2329 | name = "windows_aarch64_msvc" 2330 | version = "0.53.0" 2331 | source = "registry+https://github.com/rust-lang/crates.io-index" 2332 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 2333 | 2334 | [[package]] 2335 | name = "windows_i686_gnu" 2336 | version = "0.52.6" 2337 | source = "registry+https://github.com/rust-lang/crates.io-index" 2338 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2339 | 2340 | [[package]] 2341 | name = "windows_i686_gnu" 2342 | version = "0.53.0" 2343 | source = "registry+https://github.com/rust-lang/crates.io-index" 2344 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 2345 | 2346 | [[package]] 2347 | name = "windows_i686_gnullvm" 2348 | version = "0.52.6" 2349 | source = "registry+https://github.com/rust-lang/crates.io-index" 2350 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2351 | 2352 | [[package]] 2353 | name = "windows_i686_gnullvm" 2354 | version = "0.53.0" 2355 | source = "registry+https://github.com/rust-lang/crates.io-index" 2356 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 2357 | 2358 | [[package]] 2359 | name = "windows_i686_msvc" 2360 | version = "0.52.6" 2361 | source = "registry+https://github.com/rust-lang/crates.io-index" 2362 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2363 | 2364 | [[package]] 2365 | name = "windows_i686_msvc" 2366 | version = "0.53.0" 2367 | source = "registry+https://github.com/rust-lang/crates.io-index" 2368 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 2369 | 2370 | [[package]] 2371 | name = "windows_x86_64_gnu" 2372 | version = "0.52.6" 2373 | source = "registry+https://github.com/rust-lang/crates.io-index" 2374 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2375 | 2376 | [[package]] 2377 | name = "windows_x86_64_gnu" 2378 | version = "0.53.0" 2379 | source = "registry+https://github.com/rust-lang/crates.io-index" 2380 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 2381 | 2382 | [[package]] 2383 | name = "windows_x86_64_gnullvm" 2384 | version = "0.52.6" 2385 | source = "registry+https://github.com/rust-lang/crates.io-index" 2386 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2387 | 2388 | [[package]] 2389 | name = "windows_x86_64_gnullvm" 2390 | version = "0.53.0" 2391 | source = "registry+https://github.com/rust-lang/crates.io-index" 2392 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 2393 | 2394 | [[package]] 2395 | name = "windows_x86_64_msvc" 2396 | version = "0.52.6" 2397 | source = "registry+https://github.com/rust-lang/crates.io-index" 2398 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2399 | 2400 | [[package]] 2401 | name = "windows_x86_64_msvc" 2402 | version = "0.53.0" 2403 | source = "registry+https://github.com/rust-lang/crates.io-index" 2404 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 2405 | 2406 | [[package]] 2407 | name = "wit-bindgen-rt" 2408 | version = "0.39.0" 2409 | source = "registry+https://github.com/rust-lang/crates.io-index" 2410 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 2411 | dependencies = [ 2412 | "bitflags", 2413 | ] 2414 | 2415 | [[package]] 2416 | name = "write16" 2417 | version = "1.0.0" 2418 | source = "registry+https://github.com/rust-lang/crates.io-index" 2419 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 2420 | 2421 | [[package]] 2422 | name = "writeable" 2423 | version = "0.5.5" 2424 | source = "registry+https://github.com/rust-lang/crates.io-index" 2425 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 2426 | 2427 | [[package]] 2428 | name = "yoke" 2429 | version = "0.7.5" 2430 | source = "registry+https://github.com/rust-lang/crates.io-index" 2431 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 2432 | dependencies = [ 2433 | "serde", 2434 | "stable_deref_trait", 2435 | "yoke-derive", 2436 | "zerofrom", 2437 | ] 2438 | 2439 | [[package]] 2440 | name = "yoke-derive" 2441 | version = "0.7.5" 2442 | source = "registry+https://github.com/rust-lang/crates.io-index" 2443 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 2444 | dependencies = [ 2445 | "proc-macro2", 2446 | "quote", 2447 | "syn", 2448 | "synstructure", 2449 | ] 2450 | 2451 | [[package]] 2452 | name = "zerocopy" 2453 | version = "0.8.24" 2454 | source = "registry+https://github.com/rust-lang/crates.io-index" 2455 | checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" 2456 | dependencies = [ 2457 | "zerocopy-derive", 2458 | ] 2459 | 2460 | [[package]] 2461 | name = "zerocopy-derive" 2462 | version = "0.8.24" 2463 | source = "registry+https://github.com/rust-lang/crates.io-index" 2464 | checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" 2465 | dependencies = [ 2466 | "proc-macro2", 2467 | "quote", 2468 | "syn", 2469 | ] 2470 | 2471 | [[package]] 2472 | name = "zerofrom" 2473 | version = "0.1.6" 2474 | source = "registry+https://github.com/rust-lang/crates.io-index" 2475 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 2476 | dependencies = [ 2477 | "zerofrom-derive", 2478 | ] 2479 | 2480 | [[package]] 2481 | name = "zerofrom-derive" 2482 | version = "0.1.6" 2483 | source = "registry+https://github.com/rust-lang/crates.io-index" 2484 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 2485 | dependencies = [ 2486 | "proc-macro2", 2487 | "quote", 2488 | "syn", 2489 | "synstructure", 2490 | ] 2491 | 2492 | [[package]] 2493 | name = "zeroize" 2494 | version = "1.8.1" 2495 | source = "registry+https://github.com/rust-lang/crates.io-index" 2496 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 2497 | 2498 | [[package]] 2499 | name = "zerovec" 2500 | version = "0.10.4" 2501 | source = "registry+https://github.com/rust-lang/crates.io-index" 2502 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 2503 | dependencies = [ 2504 | "yoke", 2505 | "zerofrom", 2506 | "zerovec-derive", 2507 | ] 2508 | 2509 | [[package]] 2510 | name = "zerovec-derive" 2511 | version = "0.10.3" 2512 | source = "registry+https://github.com/rust-lang/crates.io-index" 2513 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 2514 | dependencies = [ 2515 | "proc-macro2", 2516 | "quote", 2517 | "syn", 2518 | ] 2519 | 2520 | [[package]] 2521 | name = "zip" 2522 | version = "2.6.1" 2523 | source = "registry+https://github.com/rust-lang/crates.io-index" 2524 | checksum = "1dcb24d0152526ae49b9b96c1dcf71850ca1e0b882e4e28ed898a93c41334744" 2525 | dependencies = [ 2526 | "arbitrary", 2527 | "crc32fast", 2528 | "crossbeam-utils", 2529 | "flate2", 2530 | "indexmap", 2531 | "memchr", 2532 | "zopfli", 2533 | ] 2534 | 2535 | [[package]] 2536 | name = "zopfli" 2537 | version = "0.8.1" 2538 | source = "registry+https://github.com/rust-lang/crates.io-index" 2539 | checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" 2540 | dependencies = [ 2541 | "bumpalo", 2542 | "crc32fast", 2543 | "lockfree-object-pool", 2544 | "log", 2545 | "once_cell", 2546 | "simd-adler32", 2547 | ] 2548 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["crates/svm-builds", "crates/svm-rs"] 3 | resolver = "2" 4 | 5 | [workspace.package] 6 | version = "0.5.16" 7 | edition = "2021" 8 | rust-version = "1.81" 9 | authors = [ 10 | "Rohit Narurkar ", 11 | "Matthias Seitz ", 12 | "DaniPopes <57450786+DaniPopes@users.noreply.github.com>", 13 | ] 14 | license = "MIT OR Apache-2.0" 15 | repository = "https://github.com/alloy-rs/svm-rs" 16 | homepage = "https://github.com/alloy-rs/svm-rs" 17 | 18 | [workspace.lints.clippy] 19 | dbg-macro = "warn" 20 | manual-string-new = "warn" 21 | uninlined-format-args = "warn" 22 | use-self = "warn" 23 | redundant-clone = "warn" 24 | missing-const-for-fn = "warn" 25 | needless-return = "allow" 26 | 27 | [workspace.lints.rust] 28 | # missing-copy-implementations = "warn" 29 | # missing-debug-implementations = "warn" 30 | # missing-docs = "warn" 31 | rust-2018-idioms = "warn" 32 | # unreachable-pub = "warn" 33 | unused-must-use = "warn" 34 | redundant-lifetimes = "warn" 35 | unnameable-types = "warn" 36 | 37 | [workspace.lints.rustdoc] 38 | all = "warn" 39 | 40 | [workspace.dependencies] 41 | svm = { package = "svm-rs", version = "0.5.16", path = "crates/svm-rs", default-features = false } 42 | 43 | hex = { package = "const-hex", version = "1.10" } 44 | semver = "1" 45 | serde = "1" 46 | serde_json = "1" 47 | reqwest = { version = "0.12", default-features = false, features = ["socks"] } 48 | 49 | [profile.release] 50 | lto = "fat" 51 | debug = 0 52 | strip = "debuginfo" 53 | codegen-units = 1 54 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Rohit Narurkar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solidity Compiler Version Manager 2 | 3 | [crates.io](https://crates.io/crates/svm-rs) 4 | [docs.rs](https://docs.rs/svm-rs/latest/svm_lib/) 5 | [build status](https://github.com/roynalnaruto/svm-rs/actions?query=branch%3Amaster) 6 | 7 | This crate provides a cross-platform support for managing Solidity compiler versions. 8 | 9 | ## Install 10 | 11 | From [crates.io](https://crates.io): 12 | 13 | ```sh 14 | cargo install svm-rs 15 | ``` 16 | 17 | Or from the repository: 18 | 19 | ```sh 20 | cargo install --locked --git https://github.com/alloy-rs/svm-rs/ 21 | ``` 22 | 23 | ## Usage 24 | 25 | ```sh 26 | Solc version manager 27 | 28 | Usage: svm 29 | 30 | Commands: 31 | help Print this message or the help of the given subcommand(s) 32 | install Install Solc versions 33 | list List all Solc versions 34 | remove Remove a Solc version, or "all" to remove all versions 35 | use Set a Solc version as the global default 36 | 37 | Options: 38 | -h, --help Print help 39 | -V, --version Print version 40 | ``` 41 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | msrv = "1.81" 2 | -------------------------------------------------------------------------------- /crates/svm-builds/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "svm-rs-builds" 3 | description = "Solidity compiler builds" 4 | 5 | version.workspace = true 6 | edition.workspace = true 7 | rust-version.workspace = true 8 | authors.workspace = true 9 | license.workspace = true 10 | repository.workspace = true 11 | homepage.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [build-dependencies] 17 | svm = { workspace = true, default-features = false, features = [ 18 | "blocking", 19 | "rustls", 20 | ] } 21 | 22 | hex.workspace = true 23 | semver = { workspace = true, features = ["serde"] } 24 | serde_json.workspace = true 25 | 26 | [dependencies] 27 | hex.workspace = true 28 | semver = { workspace = true, features = ["serde"] } 29 | 30 | [features] 31 | # helper feature to block network access 32 | _offline = [] 33 | 34 | [package.metadata.docs.rs] 35 | # network access is blocked during builds 36 | features = ["_offline"] 37 | -------------------------------------------------------------------------------- /crates/svm-builds/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /crates/svm-builds/build.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | use std::fs::{self, File}; 4 | use std::path::PathBuf; 5 | 6 | use semver::Version; 7 | use svm::Releases; 8 | 9 | /// The string describing the [svm::Platform] to build for 10 | /// 11 | /// Supported values are: 12 | /// 13 | /// - "linux-amd64" 14 | /// - "linux-aarch64" 15 | /// - "macosx-amd64" 16 | /// - "macosx-aarch64" 17 | /// - "windows-amd64" 18 | /// - "android-aarch64" 19 | pub const SVM_TARGET_PLATFORM: &str = "SVM_TARGET_PLATFORM"; 20 | 21 | /// The path to the releases JSON file, that was pre-fetched manually. 22 | /// 23 | /// If this variable is defined, svm-builds won't attempt to deduce anything about the 24 | /// platfrom or perform network calls, and will instead treat the file as the 25 | /// source of truth. 26 | /// 27 | /// Must follow the same format as the upstream `list.json`, e.g. 28 | /// [this one](https://raw.githubusercontent.com/nikitastupin/solc/af2fce8988e41753ab4f726e0273ea8244de5dba/linux/aarch64/list.json) 29 | pub const SVM_RELEASES_LIST_JSON: &str = "SVM_RELEASES_LIST_JSON"; 30 | 31 | /// Returns the platform to generate the constants for 32 | /// 33 | /// if the `SVM_TARGET_PLATFORM` var is set, this will return the matching [svm::Platform], 34 | /// otherwise the native platform will be used [svm::platform()]. 35 | fn get_platform() -> svm::Platform { 36 | if let Ok(s) = std::env::var(SVM_TARGET_PLATFORM) { 37 | s.parse().unwrap() 38 | } else { 39 | svm::platform() 40 | } 41 | } 42 | 43 | fn version_const_name(version: &Version) -> String { 44 | format!( 45 | "SOLC_VERSION_{}_{}_{}", 46 | version.major, version.minor, version.patch 47 | ) 48 | } 49 | 50 | /// Adds build info related constants 51 | fn add_build_info_constants(output: &mut String, releases: &Releases, platform: svm::Platform) { 52 | let mut version_idents = Vec::with_capacity(releases.builds.len()); 53 | let mut checksum_match_arms = Vec::with_capacity(releases.builds.len()); 54 | 55 | for build in releases.builds.iter() { 56 | let version = Version::new( 57 | build.version.major, 58 | build.version.minor, 59 | build.version.patch, 60 | ); 61 | let version_name = version_const_name(&version); 62 | 63 | output.push_str(&format!( 64 | "/// Solidity compiler version `{version}`.\n\ 65 | pub const {version_name}: semver::Version = semver::Version::new({}, {}, {});\n\n", 66 | version.major, version.minor, version.patch 67 | )); 68 | version_idents.push(version_name); 69 | 70 | let sha256 = hex::encode(&build.sha256); 71 | let checksum_name = format!( 72 | "SOLC_VERSION_{}_{}_{}_CHECKSUM", 73 | build.version.major, build.version.minor, build.version.patch 74 | ); 75 | 76 | output.push_str(&format!( 77 | "/// Checksum for Solidity compiler version `{version}`.\n\ 78 | pub const {checksum_name}: &str = \"{sha256}\";\n\n", 79 | )); 80 | checksum_match_arms.push(format!( 81 | "({}, {}, {}) => {}", 82 | version.major, version.minor, version.patch, checksum_name 83 | )); 84 | } 85 | 86 | let raw_static_array = format!( 87 | r#" 88 | /// All available releases for {} 89 | pub static ALL_SOLC_VERSIONS : [semver::Version; {}] = [ 90 | {} 91 | ]; 92 | "#, 93 | platform, 94 | version_idents.len(), 95 | version_idents.join(",\n ") 96 | ); 97 | output.push_str(&raw_static_array); 98 | 99 | let get_check_sum_fn = format!( 100 | r#" 101 | /// Get the checksum of a solc version's binary if it exists. 102 | pub fn get_checksum(version: &semver::Version) -> Option> {{ 103 | let checksum = match (version.major, version.minor, version.patch) {{ 104 | {}, 105 | _ => return None 106 | }}; 107 | Some(hex::decode(checksum).unwrap()) 108 | }} 109 | "#, 110 | checksum_match_arms.join(",\n ") 111 | ); 112 | 113 | output.push_str(&get_check_sum_fn); 114 | } 115 | 116 | /// checks the current platform and adds it as constant 117 | fn add_platform_const(output: &mut String, platform: svm::Platform) { 118 | output.push_str(&format!( 119 | r#" 120 | /// The `svm::Platform` all constants were built for 121 | pub const TARGET_PLATFORM: &str = "{platform}"; 122 | "# 123 | )); 124 | } 125 | 126 | fn generate() { 127 | let platform = get_platform(); 128 | let out_dir = 129 | PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR environment variable not set")); 130 | let output_file = out_dir.join("generated.rs"); 131 | 132 | // Start with an empty string that we'll append to 133 | let mut output = String::new(); 134 | 135 | // Add standard header 136 | output.push_str("// Generated file, do not edit by hand\n\n"); 137 | 138 | // add the platform as constant 139 | add_platform_const(&mut output, platform); 140 | 141 | let releases: Releases = if let Ok(file_path) = std::env::var(SVM_RELEASES_LIST_JSON) { 142 | let file = File::open(file_path).unwrap_or_else(|_| { 143 | panic!("{SVM_RELEASES_LIST_JSON:?} defined, but cannot read the file referenced") 144 | }); 145 | 146 | serde_json::from_reader(file).unwrap_or_else(|_| { 147 | panic!("Failed to parse the JSON from {SVM_RELEASES_LIST_JSON:?} file") 148 | }) 149 | } else { 150 | svm::blocking_all_releases(platform).expect("Failed to fetch releases") 151 | }; 152 | 153 | // add all solc version info 154 | add_build_info_constants(&mut output, &releases, platform); 155 | 156 | // add the whole release string 157 | let release_json = serde_json::to_string(&releases).unwrap(); 158 | output.push_str(&format!( 159 | r##" 160 | /// JSON release list 161 | pub static RELEASE_LIST_JSON : &str = r#"{release_json}"#;"## 162 | )); 163 | 164 | // Write the string to file 165 | fs::write(output_file, output).expect("failed to write output file"); 166 | 167 | // Tell Cargo that we need to rerun this if any of the relevant env vars change 168 | println!("cargo:rerun-if-env-changed={SVM_TARGET_PLATFORM}"); 169 | println!("cargo:rerun-if-env-changed={SVM_RELEASES_LIST_JSON}"); 170 | } 171 | 172 | /// generates an empty `RELEASE_LIST_JSON` static 173 | fn generate_offline() { 174 | let out_dir = 175 | PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR environment variable not set")); 176 | let output_file = out_dir.join("generated.rs"); 177 | 178 | // Start with an empty string 179 | let mut output = String::new(); 180 | 181 | // Add standard header 182 | output.push_str("// Generated file, do not edit by hand\n\n"); 183 | 184 | let release_json = serde_json::to_string(&Releases::default()).unwrap(); 185 | output.push_str(&format!( 186 | r##" 187 | /// JSON release list 188 | pub static RELEASE_LIST_JSON : &str = r#"{release_json}"#;"## 189 | )); 190 | 191 | // Write the string to file 192 | fs::write(output_file, output).expect("failed to write output file"); 193 | } 194 | 195 | fn main() { 196 | #[cfg(not(feature = "_offline"))] 197 | if std::env::var("DOCS_RS").is_ok() { 198 | // no network access allowed during docs rs builds 199 | generate_offline(); 200 | } else { 201 | generate(); 202 | } 203 | 204 | #[cfg(feature = "_offline")] 205 | generate_offline(); 206 | } 207 | -------------------------------------------------------------------------------- /crates/svm-builds/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Contains all Solc builds for the platform it was compiled with. 2 | 3 | include!(concat!(env!("OUT_DIR"), "/generated.rs")); 4 | -------------------------------------------------------------------------------- /crates/svm-rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "svm-rs" 3 | description = "Solidity compiler version manager" 4 | 5 | version.workspace = true 6 | edition.workspace = true 7 | rust-version.workspace = true 8 | authors.workspace = true 9 | license.workspace = true 10 | repository.workspace = true 11 | homepage.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [lib] 17 | name = "svm" 18 | 19 | [[bin]] 20 | name = "svm" 21 | path = "src/bin/svm-bin/main.rs" 22 | required-features = ["cli"] 23 | 24 | [[bin]] 25 | name = "solc" 26 | path = "src/bin/solc/main.rs" 27 | required-features = ["solc"] 28 | 29 | [build-dependencies] 30 | vergen = { version = "8", optional = true, features = [ 31 | "build", 32 | "git", 33 | "gitcl", 34 | ] } 35 | 36 | [dependencies] 37 | fs4 = "0.13" 38 | hex.workspace = true 39 | dirs = "6.0" 40 | reqwest = { workspace = true, default-features = false, features = ["json"] } 41 | semver = { workspace = true, features = ["serde"] } 42 | serde = { workspace = true, features = ["derive"] } 43 | serde_json.workspace = true 44 | sha2 = "0.10" 45 | tempfile = "3.10" 46 | thiserror = ">=1.0, <3.0" 47 | url = "2.5" 48 | 49 | # CLI 50 | anyhow = { version = "1.0", optional = true } 51 | clap = { version = "4", features = ["derive"], optional = true } 52 | console = { version = "0.15", default-features = false, optional = true } 53 | dialoguer = { version = "0.11", default-features = false, optional = true } 54 | indicatif = { version = "0.17", default-features = false, optional = true } 55 | itertools = { version = "0.14", optional = true } 56 | tokio = { version = "1", features = [ 57 | "rt-multi-thread", 58 | "macros", 59 | ], optional = true } 60 | 61 | [target.'cfg(all(target_os = "windows", target_arch = "x86_64"))'.dependencies] 62 | zip = { version = "2", default-features = false, features = ["deflate"] } 63 | 64 | [dev-dependencies] 65 | rand = "0.9" 66 | tempfile = "3.10" 67 | tokio = { version = "1.36", features = ["rt-multi-thread", "macros"] } 68 | serial_test = "3.0" 69 | 70 | [features] 71 | default = ["rustls", "cli", "solc"] 72 | 73 | # lib 74 | openssl = ["reqwest/native-tls"] 75 | rustls = ["reqwest/rustls-tls", "reqwest/rustls-tls-native-roots"] 76 | blocking = ["reqwest/blocking"] 77 | 78 | # bin 79 | cli = [ 80 | "dep:anyhow", 81 | "dep:clap", 82 | "dep:console", 83 | "dep:dialoguer", 84 | "dep:indicatif", 85 | "dep:itertools", 86 | "dep:tokio", 87 | "dep:vergen", 88 | ] 89 | solc = ["dep:anyhow"] 90 | -------------------------------------------------------------------------------- /crates/svm-rs/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /crates/svm-rs/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | #[cfg(feature = "cli")] 3 | vergen::EmitBuilder::builder() 4 | .build_date() 5 | .git_sha(true) 6 | .emit() 7 | .unwrap(); 8 | } 9 | -------------------------------------------------------------------------------- /crates/svm-rs/list/linux-arm64-old.json: -------------------------------------------------------------------------------- 1 | { 2 | "builds": [ 3 | { 4 | "version": "0.4.9", 5 | "sha256": "0x71da154585e0c9048445b39b3662b421d20814cc68482b6b072aae2e541a4c74" 6 | }, 7 | { 8 | "version": "0.4.8", 9 | "sha256": "0xee76039f933938cb5c14bf3fc4754776aa3e5c4c88420413da4c0c13731b8ffe" 10 | }, 11 | { 12 | "version": "0.4.7", 13 | "sha256": "0xe1affb6e13dee7b14039f8eb1a52343f5fdc56169023e0f7fc339dfc25ad2b3d" 14 | }, 15 | { 16 | "version": "0.4.6", 17 | "sha256": "0x0525d7b95549db6c913edb3c1b0c26d2db81e64b03f8352261df1b2ad696a65e" 18 | }, 19 | { 20 | "version": "0.4.5", 21 | "sha256": "0x6f46ab7747d7de1b75907e539e6e19be201680e64ce99b583c6356e4e7897406" 22 | }, 23 | { 24 | "version": "0.4.4", 25 | "sha256": "0x25d148e9c1052631a930bfbe8e4e3d9dae8de7659f8d3ea659a3ef139cd5e2c9" 26 | }, 27 | { 28 | "version": "0.4.3", 29 | "sha256": "0x1dc7ef0b4aab472299e77b39c7465cd5ed4609a759b52ce1a93f2d54395da73a" 30 | }, 31 | { 32 | "version": "0.4.2", 33 | "sha256": "0x891d0b2d3a636ff40924802a6f5beb1ecbc42d5d0d0bfecbbb148b561c861fb9" 34 | }, 35 | { 36 | "version": "0.4.1", 37 | "sha256": "0xa0c06d0c6a14c66ddeca1f065461fb0024de89421c1809a1b103b55c94e30860" 38 | }, 39 | { 40 | "version": "0.4.0", 41 | "sha256": "0xe26d188284763684f3cf6d4900b72f7e45a050dd2b2707320273529d033cfd47" 42 | } 43 | ], 44 | "releases": { 45 | "0.4.9": "solc-v0.4.9", 46 | "0.4.8": "solc-v0.4.8", 47 | "0.4.7": "solc-v0.4.7", 48 | "0.4.6": "solc-v0.4.6", 49 | "0.4.5": "solc-v0.4.5", 50 | "0.4.4": "solc-v0.4.4", 51 | "0.4.3": "solc-v0.4.3", 52 | "0.4.2": "solc-v0.4.2", 53 | "0.4.1": "solc-v0.4.1", 54 | "0.4.0": "solc-v0.4.0" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/solc/main.rs: -------------------------------------------------------------------------------- 1 | //! Simple Solc wrapper that delegates everything to a specified or the global [`svm`] Solc version. 2 | 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", 5 | html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" 6 | )] 7 | #![warn(rustdoc::all)] 8 | #![deny(unused_must_use, rust_2018_idioms)] 9 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 10 | 11 | use anyhow::Context; 12 | use std::io; 13 | use std::process::{Command, ExitStatus, Stdio}; 14 | 15 | fn main() { 16 | let code = match main_() { 17 | Ok(code) => code, 18 | Err(err) => { 19 | eprintln!("svm: error: {err}"); 20 | 1 21 | } 22 | }; 23 | std::process::exit(code); 24 | } 25 | 26 | fn main_() -> anyhow::Result { 27 | let mut args = std::env::args_os().skip(1).peekable(); 28 | let version = 'v: { 29 | // Try to parse the first argument as a version specifier `+x.y.z`. 30 | if let Some(arg) = args.peek() { 31 | if let Some(arg) = arg.to_str() { 32 | if let Some(stripped) = arg.strip_prefix('+') { 33 | let version = stripped 34 | .parse::() 35 | .context("failed to parse version specifier")?; 36 | if !version.build.is_empty() || !version.pre.is_empty() { 37 | anyhow::bail!( 38 | "version specifier must not have pre-release or build metadata" 39 | ); 40 | } 41 | args.next(); 42 | break 'v version; 43 | } 44 | } 45 | } 46 | // Fallback to the global version if one is not specified. 47 | svm::get_global_version()?.ok_or(svm::SvmError::GlobalVersionNotSet)? 48 | }; 49 | 50 | let bin = svm::version_binary(&version.to_string()); 51 | if !bin.exists() { 52 | anyhow::bail!( 53 | "Solc version {version} is not installed or does not exist; looked at {}", 54 | bin.display() 55 | ); 56 | } 57 | 58 | let mut cmd = Command::new(bin); 59 | cmd.args(args) 60 | .stdin(Stdio::inherit()) 61 | .stdout(Stdio::inherit()) 62 | .stderr(Stdio::inherit()); 63 | Ok(exec(&mut cmd)?.code().unwrap_or(-1)) 64 | } 65 | 66 | fn exec(cmd: &mut Command) -> io::Result { 67 | #[cfg(unix)] 68 | { 69 | use std::os::unix::prelude::*; 70 | Err(cmd.exec()) 71 | } 72 | #[cfg(not(unix))] 73 | { 74 | cmd.status() 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/svm-bin/install.rs: -------------------------------------------------------------------------------- 1 | use crate::print; 2 | use clap::Parser; 3 | use dialoguer::Input; 4 | use semver::Version; 5 | 6 | /// Install Solc versions. 7 | #[derive(Clone, Debug, PartialEq, Eq, Parser)] 8 | pub struct InstallCmd { 9 | /// Solc versions to install. 10 | pub versions: Vec, 11 | 12 | /// Run in non interactive mode without prompting for user input. 13 | #[arg(long, default_value_t = false)] 14 | pub non_interactive: bool, 15 | } 16 | 17 | impl InstallCmd { 18 | pub async fn run(self) -> anyhow::Result<()> { 19 | let all_versions = svm::all_versions().await?; 20 | 21 | for version in self.versions { 22 | let installed_versions = svm::installed_versions().unwrap_or_default(); 23 | let current_version = svm::get_global_version()?; 24 | let version = Version::parse(&version)?; 25 | 26 | if installed_versions.contains(&version) { 27 | println!("Solc {version} is already installed"); 28 | if self.non_interactive { 29 | continue; 30 | } 31 | let input: String = Input::new() 32 | .with_prompt("Would you like to set it as the global version?") 33 | .with_initial_text("Y") 34 | .default("N".into()) 35 | .interact_text()?; 36 | if matches!(input.as_str(), "y" | "Y" | "yes" | "Yes") { 37 | svm::set_global_version(&version)?; 38 | print::set_global_version(&version); 39 | } 40 | } else if all_versions.contains(&version) { 41 | let spinner = print::installing_version(&version); 42 | svm::install(&version).await?; 43 | spinner.finish_with_message(format!("Downloaded Solc: {version}")); 44 | if current_version.is_none() { 45 | svm::set_global_version(&version)?; 46 | print::set_global_version(&version); 47 | } 48 | } else { 49 | print::unsupported_version(&version); 50 | } 51 | } 52 | 53 | Ok(()) 54 | } 55 | } 56 | 57 | #[cfg(test)] 58 | mod tests { 59 | use super::*; 60 | 61 | #[test] 62 | fn parse_install() { 63 | let args: InstallCmd = InstallCmd::parse_from(["svm", "0.8.11", "0.8.10"]); 64 | assert_eq!( 65 | args, 66 | InstallCmd { 67 | versions: vec!["0.8.11".into(), "0.8.10".into()], 68 | non_interactive: false, 69 | } 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/svm-bin/list.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | use crate::print; 4 | use clap::Parser; 5 | use semver::Version; 6 | 7 | /// List all Solc versions. 8 | #[derive(Debug, Parser)] 9 | pub struct ListCmd; 10 | 11 | impl ListCmd { 12 | pub async fn run(self) -> anyhow::Result<()> { 13 | let all_versions = svm::all_versions().await?; 14 | let installed_versions = svm::installed_versions().unwrap_or_default(); 15 | let current_version = svm::get_global_version()?; 16 | 17 | let a: HashSet = all_versions.iter().cloned().collect(); 18 | let b: HashSet = installed_versions.iter().cloned().collect(); 19 | let c = &a - &b; 20 | 21 | let mut available_versions = c.iter().cloned().collect::>(); 22 | available_versions.sort(); 23 | 24 | print::current_version(current_version); 25 | print::installed_versions(installed_versions); 26 | print::available_versions(available_versions); 27 | 28 | Ok(()) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/svm-bin/main.rs: -------------------------------------------------------------------------------- 1 | //! Main svm-rs binary entry point. 2 | 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", 5 | html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" 6 | )] 7 | #![warn(rustdoc::all)] 8 | #![deny(unused_must_use, rust_2018_idioms)] 9 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 10 | 11 | use clap::Parser; 12 | 13 | mod install; 14 | mod list; 15 | mod print; 16 | mod remove; 17 | mod r#use; 18 | mod utils; 19 | mod which; 20 | 21 | /// Solc version manager. 22 | #[derive(Debug, Parser)] 23 | #[clap( 24 | name = "svm", 25 | version = svm::VERSION_MESSAGE, 26 | next_display_order = None, 27 | )] 28 | enum Svm { 29 | List(list::ListCmd), 30 | Install(install::InstallCmd), 31 | Use(r#use::UseCmd), 32 | Which(which::WhichCmd), 33 | Remove(remove::RemoveCmd), 34 | } 35 | 36 | #[tokio::main] 37 | async fn main() -> anyhow::Result<()> { 38 | let opt = Svm::parse(); 39 | 40 | svm::setup_data_dir()?; 41 | 42 | match opt { 43 | Svm::List(cmd) => cmd.run().await?, 44 | Svm::Install(cmd) => cmd.run().await?, 45 | Svm::Use(cmd) => cmd.run().await?, 46 | Svm::Which(cmd) => cmd.run()?, 47 | Svm::Remove(cmd) => cmd.run().await?, 48 | } 49 | 50 | Ok(()) 51 | } 52 | 53 | #[cfg(test)] 54 | mod tests { 55 | use super::*; 56 | use clap::CommandFactory; 57 | 58 | #[test] 59 | fn verify_cli() { 60 | Svm::command().debug_assert(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/svm-bin/print.rs: -------------------------------------------------------------------------------- 1 | use console::style; 2 | use indicatif::{ProgressBar, ProgressStyle}; 3 | use itertools::Itertools; 4 | use semver::Version; 5 | use std::time::Duration; 6 | 7 | pub fn current_version(version: Option) { 8 | match version { 9 | Some(v) => { 10 | println!("{} (current)", style(v.to_string().as_str()).green()); 11 | } 12 | None => { 13 | println!("Global version not set"); 14 | } 15 | } 16 | } 17 | 18 | pub fn installed_versions(versions: Vec) { 19 | println!("\n{}", style("Installed Versions").bold()); 20 | versions.iter().for_each(|v| { 21 | println!("{}", style(v.to_string().as_str()).yellow()); 22 | }); 23 | } 24 | 25 | pub fn available_versions(versions: Vec) { 26 | println!("\n{}", style("Available to Install").bold()); 27 | let groups = versions 28 | .iter() 29 | .chunk_by(|v| v.minor) 30 | .into_iter() 31 | .map(|(_, g)| g.cloned().collect()) 32 | .collect::>>(); 33 | for group in groups { 34 | println!( 35 | "{:?}", 36 | group.iter().map(|v| v.to_string()).collect::>() 37 | ); 38 | } 39 | } 40 | 41 | pub fn installing_version(version: &Version) -> ProgressBar { 42 | let spinner = ProgressBar::new_spinner(); 43 | spinner.enable_steady_tick(Duration::from_millis(120)); 44 | spinner.set_message(format!("Downloading Solc {version}")); 45 | spinner.set_style( 46 | ProgressStyle::default_spinner() 47 | .tick_strings(&[ 48 | "☀️ ", "☀️ ", "☀️ ", "🌤 ", "⛅️ ", "🌥 ", "☁️ ", "🌧 ", "🌨 ", "🌧 ", "🌨 ", "🌧 ", "🌨 ", 49 | "⛈ ", "🌨 ", "🌧 ", "🌨 ", "☁️ ", "🌥 ", "⛅️ ", "🌤 ", "☀️ ", "☀️ ", 50 | ]) 51 | .template("{spinner:.green} {msg}") 52 | .unwrap(), 53 | ); 54 | spinner 55 | } 56 | 57 | pub fn unsupported_version(version: &Version) { 58 | println!("{}", style(format!("Version: {version} unsupported")).red()); 59 | } 60 | 61 | pub fn set_global_version(version: &Version) { 62 | ProgressBar::new_spinner().finish_with_message(format!("Global version set: {version}")); 63 | } 64 | 65 | pub fn version_not_found(version: &Version) { 66 | println!("{}", style(format!("Version: {version} not found")).red()); 67 | } 68 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/svm-bin/remove.rs: -------------------------------------------------------------------------------- 1 | use crate::print; 2 | use clap::Parser; 3 | use dialoguer::Input; 4 | use semver::Version; 5 | 6 | /// Remove a Solc version, or "all" to remove all versions. 7 | #[derive(Clone, Debug, Parser)] 8 | pub struct RemoveCmd { 9 | /// Solc version to remove, or "all" to remove all versions. 10 | pub version: String, 11 | } 12 | 13 | impl RemoveCmd { 14 | pub async fn run(self) -> anyhow::Result<()> { 15 | if self.version.eq_ignore_ascii_case("all") { 16 | for v in svm::installed_versions().unwrap_or_default() { 17 | svm::remove_version(&v)?; 18 | } 19 | svm::unset_global_version()?; 20 | return Ok(()); 21 | } else { 22 | let mut installed_versions = svm::installed_versions().unwrap_or_default(); 23 | let current_version = svm::get_global_version()?; 24 | let version = Version::parse(&self.version)?; 25 | 26 | if installed_versions.contains(&version) { 27 | let input: String = Input::new() 28 | .with_prompt("Are you sure?") 29 | .with_initial_text("Y") 30 | .default("N".into()) 31 | .interact_text()?; 32 | if matches!(input.as_str(), "y" | "Y" | "yes" | "Yes") { 33 | svm::remove_version(&version)?; 34 | if let Some(v) = current_version { 35 | if version == v { 36 | if let Some(i) = installed_versions.iter().position(|x| *x == v) { 37 | installed_versions.remove(i); 38 | if let Some(new_version) = installed_versions.pop() { 39 | svm::set_global_version(&new_version)?; 40 | print::set_global_version(&new_version); 41 | } else { 42 | svm::unset_global_version()?; 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } else { 49 | print::version_not_found(&version); 50 | } 51 | } 52 | 53 | Ok(()) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/svm-bin/use.rs: -------------------------------------------------------------------------------- 1 | use crate::print; 2 | use clap::Parser; 3 | use dialoguer::Input; 4 | use semver::Version; 5 | 6 | /// Set a Solc version as the global default. 7 | #[derive(Clone, Debug, Parser)] 8 | pub struct UseCmd { 9 | /// Solc version to set as the global default. 10 | pub version: String, 11 | } 12 | 13 | impl UseCmd { 14 | pub async fn run(self) -> anyhow::Result<()> { 15 | let version = Version::parse(&self.version)?; 16 | let all_versions = svm::all_versions().await?; 17 | let installed_versions = svm::installed_versions().unwrap_or_default(); 18 | let current_version = svm::get_global_version()?; 19 | 20 | if installed_versions.contains(&version) { 21 | svm::set_global_version(&version)?; 22 | print::set_global_version(&version); 23 | } else if all_versions.contains(&version) { 24 | println!("Solc {version} is not installed"); 25 | let input: String = Input::new() 26 | .with_prompt("Would you like to install it?") 27 | .with_initial_text("Y") 28 | .default("N".into()) 29 | .interact_text()?; 30 | if matches!(input.as_str(), "y" | "Y" | "yes" | "Yes") { 31 | let spinner = print::installing_version(&version); 32 | svm::install(&version).await?; 33 | spinner.finish_with_message(format!("Downloaded Solc: {version}")); 34 | if current_version.is_none() { 35 | svm::set_global_version(&version)?; 36 | print::set_global_version(&version); 37 | } 38 | } 39 | } else { 40 | print::unsupported_version(&version); 41 | } 42 | 43 | Ok(()) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/svm-bin/utils.rs: -------------------------------------------------------------------------------- 1 | use std::future::Future; 2 | 3 | /// Runs the `future` in a new [`tokio::runtime::Runtime`] 4 | #[allow(unused)] 5 | pub fn block_on(future: F) -> F::Output { 6 | let rt = tokio::runtime::Runtime::new().expect("could not start tokio rt"); 7 | rt.block_on(future) 8 | } 9 | -------------------------------------------------------------------------------- /crates/svm-rs/src/bin/svm-bin/which.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | use semver::Version; 3 | 4 | /// Display which binary will be run for a given version. 5 | #[derive(Debug, Parser)] 6 | pub struct WhichCmd { 7 | /// The version to check. 8 | version: Version, 9 | } 10 | 11 | impl WhichCmd { 12 | pub fn run(self) -> anyhow::Result<()> { 13 | let Self { version } = self; 14 | let bin = svm::version_binary(&version.to_string()); 15 | if bin.exists() { 16 | println!("{}", bin.display()); 17 | } else { 18 | return Err(anyhow::anyhow!("version {version} not installed")); 19 | } 20 | Ok(()) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/svm-rs/src/error.rs: -------------------------------------------------------------------------------- 1 | use reqwest::StatusCode; 2 | use thiserror::Error; 3 | use url::Url; 4 | 5 | /// Error types from the svm_lib crate. 6 | #[derive(Debug, Error)] 7 | pub enum SvmError { 8 | #[error("SVM global version not set")] 9 | GlobalVersionNotSet, 10 | #[error("Unknown version provided")] 11 | UnknownVersion, 12 | #[error("Unsupported version {0} for platform {1}")] 13 | UnsupportedVersion(String, String), 14 | #[error("Version {0} not installed")] 15 | VersionNotInstalled(String), 16 | #[error("Checksum mismatch for version {version}: expected: {expected}, actual: {actual}")] 17 | ChecksumMismatch { 18 | version: String, 19 | expected: String, 20 | actual: String, 21 | }, 22 | #[error("Install step for solc version {0} timed out after {1} seconds")] 23 | Timeout(String, u64), 24 | #[error("Unable to patch solc binary for nixos. stdout: {0}. stderr: {1}")] 25 | CouldNotPatchForNixOs(String, String), 26 | #[error(transparent)] 27 | IoError(#[from] std::io::Error), 28 | #[error(transparent)] 29 | PersistError(#[from] tempfile::PathPersistError), 30 | #[error(transparent)] 31 | ReqwestError(#[from] reqwest::Error), 32 | #[error(transparent)] 33 | SemverError(#[from] semver::Error), 34 | #[error(transparent)] 35 | UrlError(#[from] url::ParseError), 36 | #[error("Received unsuccessful response with code {1} for {0}")] 37 | UnsuccessfulResponse(Url, StatusCode), 38 | #[cfg(all(target_os = "windows", target_arch = "x86_64"))] 39 | #[error(transparent)] 40 | ZipError(#[from] zip::result::ZipError), 41 | } 42 | -------------------------------------------------------------------------------- /crates/svm-rs/src/install.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | all_releases, data_dir, platform, releases::artifact_url, setup_data_dir, setup_version, 3 | version_binary, SvmError, 4 | }; 5 | use semver::Version; 6 | use sha2::Digest; 7 | use std::{ 8 | fs, 9 | io::Write, 10 | path::{Path, PathBuf}, 11 | process::Command, 12 | time::Duration, 13 | }; 14 | use tempfile::NamedTempFile; 15 | 16 | #[cfg(target_family = "unix")] 17 | use std::{fs::Permissions, os::unix::fs::PermissionsExt}; 18 | 19 | /// The timeout to use for requests to the source (10 minutes). 20 | const REQUEST_TIMEOUT: Duration = Duration::from_secs(600); 21 | 22 | /// Version beyond which solc binaries are not fully static, hence need to be patched for NixOS. 23 | const NIXOS_MIN_PATCH_VERSION: Version = Version::new(0, 7, 6); 24 | 25 | /// Version beyond which solc binaries are fully static again, hence no patching is needed for NixOS. 26 | /// See 27 | const NIXOS_MAX_PATCH_VERSION: Version = Version::new(0, 8, 28); 28 | 29 | /// Blocking version of [`install`] 30 | #[cfg(feature = "blocking")] 31 | pub fn blocking_install(version: &Version) -> Result { 32 | setup_data_dir()?; 33 | 34 | let artifacts = crate::blocking_all_releases(platform::platform())?; 35 | let artifact = artifacts 36 | .get_artifact(version) 37 | .ok_or(SvmError::UnknownVersion)?; 38 | let download_url = artifact_url(platform::platform(), version, artifact.to_string().as_str())?; 39 | 40 | let expected_checksum = artifacts 41 | .get_checksum(version) 42 | .unwrap_or_else(|| panic!("checksum not available: {:?}", version.to_string())); 43 | 44 | let res = reqwest::blocking::Client::builder() 45 | .timeout(REQUEST_TIMEOUT) 46 | .build() 47 | .expect("reqwest::Client::new()") 48 | .get(download_url.clone()) 49 | .send()?; 50 | 51 | if !res.status().is_success() { 52 | return Err(SvmError::UnsuccessfulResponse(download_url, res.status())); 53 | } 54 | 55 | let binbytes = res.bytes()?; 56 | ensure_checksum(&binbytes, version, &expected_checksum)?; 57 | 58 | // lock file to indicate that installation of this solc version will be in progress. 59 | let lock_path = lock_file_path(version); 60 | // wait until lock file is released, possibly by another parallel thread trying to install the 61 | // same version of solc. 62 | let _lock = try_lock_file(lock_path)?; 63 | 64 | do_install_and_retry( 65 | version, 66 | &binbytes, 67 | artifact.to_string().as_str(), 68 | &expected_checksum, 69 | ) 70 | } 71 | 72 | /// Installs the provided version of Solc in the machine. 73 | /// 74 | /// Returns the path to the solc file. 75 | pub async fn install(version: &Version) -> Result { 76 | setup_data_dir()?; 77 | 78 | let artifacts = all_releases(platform::platform()).await?; 79 | let artifact = artifacts 80 | .releases 81 | .get(version) 82 | .ok_or(SvmError::UnknownVersion)?; 83 | let download_url = artifact_url(platform::platform(), version, artifact.to_string().as_str())?; 84 | 85 | let expected_checksum = artifacts 86 | .get_checksum(version) 87 | .unwrap_or_else(|| panic!("checksum not available: {:?}", version.to_string())); 88 | 89 | let res = reqwest::Client::builder() 90 | .timeout(REQUEST_TIMEOUT) 91 | .build() 92 | .expect("reqwest::Client::new()") 93 | .get(download_url.clone()) 94 | .send() 95 | .await?; 96 | 97 | if !res.status().is_success() { 98 | return Err(SvmError::UnsuccessfulResponse(download_url, res.status())); 99 | } 100 | 101 | let binbytes = res.bytes().await?; 102 | ensure_checksum(&binbytes, version, &expected_checksum)?; 103 | 104 | // lock file to indicate that installation of this solc version will be in progress. 105 | let lock_path = lock_file_path(version); 106 | // wait until lock file is released, possibly by another parallel thread trying to install the 107 | // same version of solc. 108 | let _lock = try_lock_file(lock_path)?; 109 | 110 | do_install_and_retry( 111 | version, 112 | &binbytes, 113 | artifact.to_string().as_str(), 114 | &expected_checksum, 115 | ) 116 | } 117 | 118 | /// Same as [`do_install`] but retries "text file busy" errors. 119 | fn do_install_and_retry( 120 | version: &Version, 121 | binbytes: &[u8], 122 | artifact: &str, 123 | expected_checksum: &[u8], 124 | ) -> Result { 125 | let mut retries = 0; 126 | 127 | loop { 128 | return match do_install(version, binbytes, artifact) { 129 | Ok(path) => Ok(path), 130 | Err(err) => { 131 | // installation failed 132 | if retries > 2 { 133 | return Err(err); 134 | } 135 | retries += 1; 136 | // check if this failed due to a text file busy, which indicates that a different process started using the target file 137 | if err.to_string().to_lowercase().contains("text file busy") { 138 | // busy solc can be in use for a while (e.g. if compiling a large project), so we check if the file exists and has the correct checksum 139 | let solc_path = version_binary(&version.to_string()); 140 | if solc_path.exists() { 141 | if let Ok(content) = fs::read(&solc_path) { 142 | if ensure_checksum(&content, version, expected_checksum).is_ok() { 143 | // checksum of the existing file matches the expected release checksum 144 | return Ok(solc_path); 145 | } 146 | } 147 | } 148 | 149 | // retry after some time 150 | std::thread::sleep(Duration::from_millis(250)); 151 | continue; 152 | } 153 | 154 | Err(err) 155 | } 156 | }; 157 | } 158 | } 159 | 160 | fn do_install(version: &Version, binbytes: &[u8], _artifact: &str) -> Result { 161 | setup_version(&version.to_string())?; 162 | let installer = Installer { version, binbytes }; 163 | 164 | // Solc versions <= 0.7.1 are .zip files for Windows only 165 | #[cfg(all(target_os = "windows", target_arch = "x86_64"))] 166 | if _artifact.ends_with(".zip") { 167 | return installer.install_zip(); 168 | } 169 | 170 | installer.install() 171 | } 172 | 173 | /// Creates the file and locks it exclusively, this will block if the file is currently locked 174 | fn try_lock_file(lock_path: PathBuf) -> Result { 175 | use fs4::fs_std::FileExt; 176 | let _lock_file = fs::OpenOptions::new() 177 | .create(true) 178 | .truncate(true) 179 | .read(true) 180 | .write(true) 181 | .open(&lock_path)?; 182 | _lock_file.lock_exclusive()?; 183 | Ok(LockFile { 184 | lock_path, 185 | _lock_file, 186 | }) 187 | } 188 | 189 | /// Represents a lockfile that's removed once dropped 190 | struct LockFile { 191 | _lock_file: fs::File, 192 | lock_path: PathBuf, 193 | } 194 | 195 | impl Drop for LockFile { 196 | fn drop(&mut self) { 197 | let _ = fs::remove_file(&self.lock_path); 198 | } 199 | } 200 | 201 | /// Returns the lockfile to use for a specific file 202 | fn lock_file_path(version: &Version) -> PathBuf { 203 | data_dir().join(format!(".lock-solc-{version}")) 204 | } 205 | 206 | // Installer type that copies binary data to the appropriate solc binary file: 207 | // 1. create target file to copy binary data 208 | // 2. copy data 209 | struct Installer<'a> { 210 | // version of solc 211 | version: &'a Version, 212 | // binary data of the solc executable 213 | binbytes: &'a [u8], 214 | } 215 | 216 | impl Installer<'_> { 217 | /// Installs the solc version at the version specific destination and returns the path to the installed solc file. 218 | fn install(self) -> Result { 219 | let named_temp_file = NamedTempFile::new_in(data_dir())?; 220 | let (mut f, temp_path) = named_temp_file.into_parts(); 221 | 222 | #[cfg(target_family = "unix")] 223 | f.set_permissions(Permissions::from_mode(0o755))?; 224 | f.write_all(self.binbytes)?; 225 | 226 | if platform::is_nixos() 227 | && *self.version >= NIXOS_MIN_PATCH_VERSION 228 | && *self.version <= NIXOS_MAX_PATCH_VERSION 229 | { 230 | patch_for_nixos(&temp_path)?; 231 | } 232 | 233 | let solc_path = version_binary(&self.version.to_string()); 234 | 235 | // Windows requires that the old file be moved out of the way first. 236 | if cfg!(target_os = "windows") { 237 | let temp_path = NamedTempFile::new_in(data_dir()).map(NamedTempFile::into_temp_path)?; 238 | fs::rename(&solc_path, &temp_path).unwrap_or_default(); 239 | } 240 | 241 | temp_path.persist(&solc_path)?; 242 | 243 | Ok(solc_path) 244 | } 245 | 246 | /// Extracts the solc archive at the version specified destination and returns the path to the 247 | /// installed solc binary. 248 | #[cfg(all(target_os = "windows", target_arch = "x86_64"))] 249 | fn install_zip(self) -> Result { 250 | let solc_path = version_binary(&self.version.to_string()); 251 | let version_path = solc_path.parent().unwrap(); 252 | 253 | let mut content = std::io::Cursor::new(self.binbytes); 254 | let mut archive = zip::ZipArchive::new(&mut content)?; 255 | archive.extract(version_path)?; 256 | 257 | std::fs::rename(version_path.join("solc.exe"), &solc_path)?; 258 | 259 | Ok(solc_path) 260 | } 261 | } 262 | 263 | /// Patch the given binary to use the dynamic linker provided by nixos. 264 | fn patch_for_nixos(bin: &Path) -> Result<(), SvmError> { 265 | let output = Command::new("nix-shell") 266 | .arg("-p") 267 | .arg("patchelf") 268 | .arg("--run") 269 | .arg(format!( 270 | "patchelf --set-interpreter \"$(cat $NIX_CC/nix-support/dynamic-linker)\" {}", 271 | bin.display() 272 | )) 273 | .output() 274 | .map_err(|e| SvmError::CouldNotPatchForNixOs(String::new(), e.to_string()))?; 275 | 276 | match output.status.success() { 277 | true => Ok(()), 278 | false => Err(SvmError::CouldNotPatchForNixOs( 279 | String::from_utf8_lossy(&output.stdout).into_owned(), 280 | String::from_utf8_lossy(&output.stderr).into_owned(), 281 | )), 282 | } 283 | } 284 | 285 | fn ensure_checksum( 286 | binbytes: &[u8], 287 | version: &Version, 288 | expected_checksum: &[u8], 289 | ) -> Result<(), SvmError> { 290 | let mut hasher = sha2::Sha256::new(); 291 | hasher.update(binbytes); 292 | let checksum = &hasher.finalize()[..]; 293 | // checksum does not match 294 | if checksum != expected_checksum { 295 | return Err(SvmError::ChecksumMismatch { 296 | version: version.to_string(), 297 | expected: hex::encode(expected_checksum), 298 | actual: hex::encode(checksum), 299 | }); 300 | } 301 | Ok(()) 302 | } 303 | 304 | #[cfg(test)] 305 | mod tests { 306 | use super::*; 307 | use rand::seq::IndexedRandom; 308 | 309 | #[allow(unused)] 310 | const LATEST: Version = Version::new(0, 8, 30); 311 | 312 | #[tokio::test] 313 | #[serial_test::serial] 314 | async fn test_install() { 315 | let versions = all_releases(platform()) 316 | .await 317 | .unwrap() 318 | .releases 319 | .into_keys() 320 | .collect::>(); 321 | let rand_version = versions.choose(&mut rand::rng()).unwrap(); 322 | assert!(install(rand_version).await.is_ok()); 323 | } 324 | 325 | #[tokio::test] 326 | #[serial_test::serial] 327 | async fn can_install_while_solc_is_running() { 328 | const WHICH: &str = if cfg!(target_os = "windows") { 329 | "where" 330 | } else { 331 | "which" 332 | }; 333 | 334 | let version: Version = "0.8.10".parse().unwrap(); 335 | let solc_path = version_binary(version.to_string().as_str()); 336 | 337 | fs::create_dir_all(solc_path.parent().unwrap()).unwrap(); 338 | 339 | // Overwrite solc with `sleep` and call it with `infinity`. 340 | let stdout = Command::new(WHICH).arg("sleep").output().unwrap().stdout; 341 | let sleep_path = String::from_utf8(stdout).unwrap(); 342 | fs::copy(sleep_path.trim_end(), &solc_path).unwrap(); 343 | let mut child = Command::new(solc_path).arg("infinity").spawn().unwrap(); 344 | 345 | // Install should not fail with "text file busy". 346 | install(&version).await.unwrap(); 347 | 348 | child.kill().unwrap(); 349 | let _: std::process::ExitStatus = child.wait().unwrap(); 350 | } 351 | 352 | #[cfg(feature = "blocking")] 353 | #[serial_test::serial] 354 | #[test] 355 | fn blocking_test_install() { 356 | let versions = crate::releases::blocking_all_releases(platform::platform()) 357 | .unwrap() 358 | .into_versions(); 359 | let rand_version = versions.choose(&mut rand::rng()).unwrap(); 360 | assert!(blocking_install(rand_version).is_ok()); 361 | } 362 | 363 | #[tokio::test] 364 | #[serial_test::serial] 365 | async fn test_version() { 366 | let version = "0.8.10".parse().unwrap(); 367 | install(&version).await.unwrap(); 368 | let solc_path = version_binary(version.to_string().as_str()); 369 | let output = Command::new(solc_path).arg("--version").output().unwrap(); 370 | assert!(String::from_utf8_lossy(&output.stdout) 371 | .as_ref() 372 | .contains("0.8.10")); 373 | } 374 | 375 | #[cfg(feature = "blocking")] 376 | #[serial_test::serial] 377 | #[test] 378 | fn blocking_test_latest() { 379 | blocking_install(&LATEST).unwrap(); 380 | let solc_path = version_binary(LATEST.to_string().as_str()); 381 | let output = Command::new(solc_path).arg("--version").output().unwrap(); 382 | 383 | assert!(String::from_utf8_lossy(&output.stdout) 384 | .as_ref() 385 | .contains(&LATEST.to_string())); 386 | } 387 | 388 | #[cfg(feature = "blocking")] 389 | #[serial_test::serial] 390 | #[test] 391 | fn blocking_test_version() { 392 | let version = "0.8.10".parse().unwrap(); 393 | blocking_install(&version).unwrap(); 394 | let solc_path = version_binary(version.to_string().as_str()); 395 | let output = Command::new(solc_path).arg("--version").output().unwrap(); 396 | 397 | assert!(String::from_utf8_lossy(&output.stdout) 398 | .as_ref() 399 | .contains("0.8.10")); 400 | } 401 | 402 | #[cfg(feature = "blocking")] 403 | #[test] 404 | fn can_install_parallel() { 405 | let version: Version = "0.8.10".parse().unwrap(); 406 | let cloned_version = version.clone(); 407 | let t = std::thread::spawn(move || blocking_install(&cloned_version)); 408 | blocking_install(&version).unwrap(); 409 | t.join().unwrap().unwrap(); 410 | } 411 | 412 | #[tokio::test(flavor = "multi_thread")] 413 | async fn can_install_parallel_async() { 414 | let version: Version = "0.8.10".parse().unwrap(); 415 | let cloned_version = version.clone(); 416 | let t = tokio::task::spawn(async move { install(&cloned_version).await }); 417 | install(&version).await.unwrap(); 418 | t.await.unwrap().unwrap(); 419 | } 420 | 421 | // ensures we can download the latest universal solc for apple silicon 422 | #[tokio::test(flavor = "multi_thread")] 423 | #[cfg(all(target_os = "macos", target_arch = "aarch64"))] 424 | async fn can_install_latest_native_apple_silicon() { 425 | let solc = install(&LATEST).await.unwrap(); 426 | let output = Command::new(solc).arg("--version").output().unwrap(); 427 | let version_output = String::from_utf8_lossy(&output.stdout); 428 | assert!( 429 | version_output.contains(&LATEST.to_string()), 430 | "{version_output}" 431 | ); 432 | } 433 | 434 | // ensures we can download the latest native solc for linux aarch64 435 | #[tokio::test(flavor = "multi_thread")] 436 | #[cfg(all(target_os = "linux", target_arch = "aarch64"))] 437 | async fn can_download_latest_linux_aarch64() { 438 | let artifacts = all_releases(Platform::LinuxAarch64).await.unwrap(); 439 | 440 | let artifact = artifacts.releases.get(&LATEST).unwrap(); 441 | let download_url = artifact_url( 442 | Platform::LinuxAarch64, 443 | &LATEST, 444 | artifact.to_string().as_str(), 445 | ) 446 | .unwrap(); 447 | 448 | let checksum = artifacts.get_checksum(&LATEST).unwrap(); 449 | 450 | let resp = reqwest::get(download_url).await.unwrap(); 451 | assert!(resp.status().is_success()); 452 | let binbytes = resp.bytes().await.unwrap(); 453 | ensure_checksum(&binbytes, &LATEST, checksum).unwrap(); 454 | } 455 | 456 | #[tokio::test] 457 | #[cfg(all(target_os = "windows", target_arch = "x86_64"))] 458 | async fn can_install_windows_zip_release() { 459 | let version = "0.7.1".parse().unwrap(); 460 | install(&version).await.unwrap(); 461 | let solc_path = version_binary(version.to_string().as_str()); 462 | let output = Command::new(&solc_path).arg("--version").output().unwrap(); 463 | 464 | assert!(String::from_utf8_lossy(&output.stdout) 465 | .as_ref() 466 | .contains("0.7.1")); 467 | } 468 | } 469 | -------------------------------------------------------------------------------- /crates/svm-rs/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![doc( 3 | html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg", 4 | html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico" 5 | )] 6 | #![warn(rustdoc::all)] 7 | #![cfg_attr( 8 | not(any(test, feature = "cli", feature = "solc")), 9 | warn(unused_crate_dependencies) 10 | )] 11 | #![deny(unused_must_use, rust_2018_idioms)] 12 | #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] 13 | 14 | use semver::Version; 15 | use std::fs; 16 | 17 | mod error; 18 | pub use error::SvmError; 19 | 20 | mod install; 21 | #[cfg(feature = "blocking")] 22 | pub use install::blocking_install; 23 | pub use install::install; 24 | 25 | mod paths; 26 | pub use paths::{data_dir, global_version_path, setup_data_dir, version_binary, version_path}; 27 | 28 | mod platform; 29 | pub use platform::{platform, Platform}; 30 | 31 | mod releases; 32 | pub use releases::{all_releases, BuildInfo, Releases}; 33 | 34 | #[cfg(feature = "blocking")] 35 | pub use releases::blocking_all_releases; 36 | 37 | #[cfg(feature = "cli")] 38 | #[doc(hidden)] 39 | pub const VERSION_MESSAGE: &str = concat!( 40 | env!("CARGO_PKG_VERSION"), 41 | " (", 42 | env!("VERGEN_GIT_SHA"), 43 | " ", 44 | env!("VERGEN_BUILD_DATE"), 45 | ")" 46 | ); 47 | 48 | /// Reads the currently set global version for Solc. Returns None if none has yet been set. 49 | pub fn get_global_version() -> Result, SvmError> { 50 | let v = fs::read_to_string(global_version_path())?; 51 | Ok(Version::parse(v.trim_end_matches('\n')).ok()) 52 | } 53 | 54 | /// Sets the provided version as the global version for Solc. 55 | pub fn set_global_version(version: &Version) -> Result<(), SvmError> { 56 | fs::write(global_version_path(), version.to_string()).map_err(Into::into) 57 | } 58 | 59 | /// Unset the global version. This should be done if all versions are removed. 60 | pub fn unset_global_version() -> Result<(), SvmError> { 61 | fs::write(global_version_path(), "").map_err(Into::into) 62 | } 63 | 64 | /// Reads the list of Solc versions that have been installed in the machine. 65 | /// The version list is sorted in ascending order. 66 | pub fn installed_versions() -> Result, SvmError> { 67 | let mut versions = vec![]; 68 | for v in fs::read_dir(data_dir())? { 69 | let v = v?; 70 | let path = v.path(); 71 | let Some(file_name) = path.file_name() else { 72 | continue; 73 | }; 74 | let Some(file_name) = file_name.to_str() else { 75 | continue; 76 | }; 77 | if file_name == ".global-version" { 78 | continue; 79 | } 80 | versions.push(Version::parse(file_name)?); 81 | } 82 | versions.sort(); 83 | Ok(versions) 84 | } 85 | 86 | /// Blocking version of [`all_versions`] 87 | #[cfg(feature = "blocking")] 88 | pub fn blocking_all_versions() -> Result, SvmError> { 89 | Ok(releases::blocking_all_releases(platform::platform())?.into_versions()) 90 | } 91 | 92 | /// Fetches the list of all the available versions of Solc. The list is platform dependent, so 93 | /// different versions can be found for macosx vs linux. 94 | pub async fn all_versions() -> Result, SvmError> { 95 | Ok(releases::all_releases(platform::platform()) 96 | .await? 97 | .into_versions()) 98 | } 99 | 100 | /// Removes the provided version of Solc from the machine. 101 | pub fn remove_version(version: &Version) -> Result<(), SvmError> { 102 | fs::remove_dir_all(version_path(version.to_string().as_str())).map_err(Into::into) 103 | } 104 | 105 | fn setup_version(version: &str) -> Result<(), SvmError> { 106 | let v = version_path(version); 107 | if !v.exists() { 108 | fs::create_dir_all(v)?; 109 | } 110 | Ok(()) 111 | } 112 | -------------------------------------------------------------------------------- /crates/svm-rs/src/paths.rs: -------------------------------------------------------------------------------- 1 | use crate::SvmError; 2 | use std::{ 3 | ffi::OsString, 4 | fs, io, 5 | path::{Path, PathBuf}, 6 | sync::OnceLock, 7 | }; 8 | 9 | /// Setup SVM home directory. 10 | pub fn setup_data_dir() -> Result<(), SvmError> { 11 | // create $XDG_DATA_HOME or ~/.local/share/svm, or fallback to ~/.svm 12 | let data_dir = data_dir(); 13 | 14 | // Create the directory, continuing if the directory came into existence after the check 15 | // for this if statement. This may happen if two copies of SVM run simultaneously (e.g CI). 16 | fs::create_dir_all(data_dir).or_else(|err| match err.kind() { 17 | io::ErrorKind::AlreadyExists => Ok(()), 18 | _ => Err(err), 19 | })?; 20 | 21 | // Check that the SVM directory is indeed a directory, and not e.g. a file. 22 | if !data_dir.is_dir() { 23 | return Err(SvmError::IoError(io::Error::new( 24 | io::ErrorKind::AlreadyExists, 25 | format!("svm data dir '{}' is not a directory", data_dir.display()), 26 | ))); 27 | } 28 | 29 | // Create `$SVM/.global-version`. 30 | let global_version = global_version_path(); 31 | if !global_version.exists() { 32 | fs::File::create(global_version)?; 33 | } 34 | 35 | Ok(()) 36 | } 37 | 38 | /// Returns the path to the default data directory. 39 | /// 40 | /// Returns `~/.svm` if it exists, otherwise uses `$XDG_DATA_HOME/svm`. 41 | pub fn data_dir() -> &'static Path { 42 | static ONCE: OnceLock = OnceLock::new(); 43 | ONCE.get_or_init(|| { 44 | #[cfg(test)] 45 | { 46 | let dir = tempfile::tempdir().expect("could not create temp directory"); 47 | dir.path().join(".svm") 48 | } 49 | #[cfg(not(test))] 50 | { 51 | resolve_data_dir() 52 | } 53 | }) 54 | } 55 | 56 | #[allow(dead_code)] 57 | fn resolve_data_dir() -> PathBuf { 58 | let home_dir = dirs::home_dir() 59 | .expect("could not detect user home directory") 60 | .join(".svm"); 61 | 62 | let data_dir = dirs::data_dir().expect("could not detect user data directory"); 63 | if !home_dir.exists() && data_dir.exists() { 64 | data_dir.join("svm") 65 | } else { 66 | home_dir 67 | } 68 | } 69 | 70 | /// Returns the path to the global version file. 71 | pub fn global_version_path() -> &'static Path { 72 | static ONCE: OnceLock = OnceLock::new(); 73 | ONCE.get_or_init(|| data_dir().join(".global-version")) 74 | } 75 | 76 | /// Returns the path to a specific Solc version's directory. 77 | /// 78 | /// Note that this is not the path to the actual Solc binary file; 79 | /// use [`version_binary`] for that instead. 80 | /// 81 | /// This is currently `data_dir() / {version}`. 82 | pub fn version_path(version: &str) -> PathBuf { 83 | data_dir().join(version) 84 | } 85 | 86 | /// Derive path to a specific Solc version's binary file. 87 | /// 88 | /// This is currently `data_dir() / {version} / solc-{version}`. 89 | pub fn version_binary(version: &str) -> PathBuf { 90 | let data_dir = data_dir(); 91 | let sep = std::path::MAIN_SEPARATOR_STR; 92 | let cap = 93 | data_dir.as_os_str().len() + sep.len() + version.len() + sep.len() + 5 + version.len(); 94 | let mut binary = OsString::with_capacity(cap); 95 | binary.push(data_dir); 96 | debug_assert!(!data_dir.ends_with(sep)); 97 | binary.push(sep); 98 | 99 | binary.push(version); 100 | binary.push(sep); 101 | 102 | binary.push("solc-"); 103 | binary.push(version); 104 | PathBuf::from(binary) 105 | } 106 | -------------------------------------------------------------------------------- /crates/svm-rs/src/platform.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Formatter; 2 | use std::str::FromStr; 3 | use std::{env, fmt}; 4 | 5 | /// Types of supported platforms. 6 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] 7 | #[non_exhaustive] 8 | pub enum Platform { 9 | LinuxAmd64, 10 | LinuxAarch64, 11 | MacOsAmd64, 12 | MacOsAarch64, 13 | WindowsAmd64, 14 | AndroidAarch64, 15 | Unsupported, 16 | } 17 | 18 | impl fmt::Display for Platform { 19 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 20 | let s = match self { 21 | Self::LinuxAmd64 => "linux-amd64", 22 | Self::LinuxAarch64 => "linux-aarch64", 23 | Self::MacOsAmd64 => "macosx-amd64", 24 | Self::MacOsAarch64 => "macosx-aarch64", 25 | Self::WindowsAmd64 => "windows-amd64", 26 | Self::AndroidAarch64 => "android-aarch64", 27 | Self::Unsupported => "Unsupported-platform", 28 | }; 29 | f.write_str(s) 30 | } 31 | } 32 | 33 | impl FromStr for Platform { 34 | type Err = String; 35 | 36 | fn from_str(s: &str) -> Result { 37 | match s { 38 | "linux-amd64" => Ok(Self::LinuxAmd64), 39 | "linux-aarch64" => Ok(Self::LinuxAarch64), 40 | "macosx-amd64" => Ok(Self::MacOsAmd64), 41 | "macosx-aarch64" => Ok(Self::MacOsAarch64), 42 | "windows-amd64" => Ok(Self::WindowsAmd64), 43 | "android-aarch64" => Ok(Self::AndroidAarch64), 44 | s => Err(format!("unsupported platform {s}")), 45 | } 46 | } 47 | } 48 | 49 | pub fn is_nixos() -> bool { 50 | cfg!(target_os = "linux") 51 | && (std::path::Path::new("/etc/nixos").exists() 52 | || std::path::Path::new("/etc/NIXOS").exists()) 53 | && std::fs::read_to_string("/etc/os-release").is_ok_and(|s| s.contains("NixOS")) 54 | } 55 | 56 | /// Read the current machine's platform. 57 | pub fn platform() -> Platform { 58 | match (env::consts::OS, env::consts::ARCH) { 59 | ("linux", "x86_64") => Platform::LinuxAmd64, 60 | ("linux", "aarch64") => Platform::LinuxAarch64, 61 | ("macos", "x86_64") => Platform::MacOsAmd64, 62 | ("macos", "aarch64") => Platform::MacOsAarch64, 63 | ("windows", "x86_64") => Platform::WindowsAmd64, 64 | ("android", "aarch64") => Platform::AndroidAarch64, 65 | _ => Platform::Unsupported, 66 | } 67 | } 68 | 69 | #[cfg(test)] 70 | mod tests { 71 | use super::*; 72 | 73 | #[test] 74 | #[cfg(all(target_os = "linux", target_arch = "x86_64"))] 75 | fn get_platform() { 76 | assert_eq!(platform(), Platform::LinuxAmd64); 77 | } 78 | 79 | #[test] 80 | #[cfg(all(target_os = "linux", target_arch = "aarch64"))] 81 | fn get_platform() { 82 | assert_eq!(platform(), Platform::LinuxAarch64); 83 | } 84 | 85 | #[test] 86 | #[cfg(all(target_os = "macos", target_arch = "x86_64"))] 87 | fn get_platform() { 88 | assert_eq!(platform(), Platform::MacOsAmd64); 89 | } 90 | 91 | #[test] 92 | #[cfg(all(target_os = "macos", target_arch = "aarch64"))] 93 | fn get_platform() { 94 | assert_eq!(platform(), Platform::MacOsAarch64); 95 | } 96 | 97 | #[test] 98 | #[cfg(all(target_os = "windows", target_arch = "x86_64"))] 99 | fn get_platform() { 100 | assert_eq!(platform(), Platform::WindowsAmd64); 101 | } 102 | 103 | #[test] 104 | #[cfg(all(target_os = "android", target_arch = "aarch64"))] 105 | fn get_platform() { 106 | assert_eq!(platform(), Platform::AndroidAarch64); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /crates/svm-rs/src/releases.rs: -------------------------------------------------------------------------------- 1 | use crate::{error::SvmError, platform::Platform}; 2 | use reqwest::get; 3 | use semver::Version; 4 | use serde::{Deserialize, Serialize}; 5 | use std::{collections::BTreeMap, sync::LazyLock}; 6 | use url::Url; 7 | 8 | // Updating new releases: 9 | // 1. Update `https://github.com/nikitastupin/solc` commit for `linux/aarch64` 10 | // 2. Update LATEST for tests 11 | 12 | /// Base URL for all Solc releases 13 | /// `"SOLC_RELEASES_URL}/{platform}/list.json"`: 14 | /// `https://binaries.soliditylang.org/linux-amd64/list.json` 15 | /// `https://binaries.soliditylang.org/windows-amd64/list.json` 16 | /// `https://binaries.soliditylang.org/macosx-amd64/list.json` 17 | const SOLC_RELEASES_URL: &str = "https://binaries.soliditylang.org"; 18 | 19 | const OLD_SOLC_RELEASES_DOWNLOAD_PREFIX: &str = 20 | "https://raw.githubusercontent.com/crytic/solc/master/linux/amd64"; 21 | 22 | const OLD_VERSION_MAX: Version = Version::new(0, 4, 9); 23 | 24 | const OLD_VERSION_MIN: Version = Version::new(0, 4, 0); 25 | 26 | static OLD_SOLC_RELEASES: LazyLock = LazyLock::new(|| { 27 | serde_json::from_str(include_str!("../list/linux-arm64-old.json")) 28 | .expect("could not parse list linux-arm64-old.json") 29 | }); 30 | 31 | const LINUX_AARCH64_MIN: Version = Version::new(0, 5, 0); 32 | 33 | static LINUX_AARCH64_URL_PREFIX: &str = 34 | "https://raw.githubusercontent.com/nikitastupin/solc/0045084c85d8c159de03442a37d2018d52374445/linux/aarch64"; 35 | 36 | static LINUX_AARCH64_RELEASES_URL: &str = 37 | "https://raw.githubusercontent.com/nikitastupin/solc/0045084c85d8c159de03442a37d2018d52374445/linux/aarch64/list.json"; 38 | 39 | // NOTE: Since version 0.8.24, universal macosx releases are available: https://binaries.soliditylang.org/macosx-amd64/list.json 40 | const MACOS_AARCH64_NATIVE: Version = Version::new(0, 8, 5); 41 | 42 | const UNIVERSAL_MACOS_BINARIES: Version = Version::new(0, 8, 24); 43 | 44 | static MACOS_AARCH64_URL_PREFIX: &str = 45 | "https://raw.githubusercontent.com/alloy-rs/solc-builds/e4b80d33bc4d015b2fc3583e217fbf248b2014e1/macosx/aarch64"; 46 | 47 | static MACOS_AARCH64_RELEASES_URL: &str = 48 | "https://raw.githubusercontent.com/alloy-rs/solc-builds/e4b80d33bc4d015b2fc3583e217fbf248b2014e1/macosx/aarch64/list.json"; 49 | 50 | const ANDROID_AARCH64_MIN: Version = Version::new(0, 8, 24); 51 | 52 | static ANDROID_AARCH64_URL_PREFIX: &str = 53 | "https://raw.githubusercontent.com/alloy-rs/solc-builds/ac6f303a04b38e7ec507ced511fd3ed7a605179f/android/aarch64"; 54 | 55 | static ANDROID_AARCH64_RELEASES_URL: &str = 56 | "https://raw.githubusercontent.com/alloy-rs/solc-builds/ac6f303a04b38e7ec507ced511fd3ed7a605179f/android/aarch64/list.json"; 57 | 58 | /// Defines the struct that the JSON-formatted release list can be deserialized into. 59 | /// 60 | /// Both the key and value are deserialized into [`semver::Version`]. 61 | /// 62 | /// ```json 63 | /// { 64 | /// "builds": [ 65 | /// { 66 | /// "version": "0.8.7", 67 | /// "sha256": "0x0xcc5c663d1fe17d4eb4aca09253787ac86b8785235fca71d9200569e662677990" 68 | /// } 69 | /// ] 70 | /// "releases": { 71 | /// "0.8.7": "solc-macosx-amd64-v0.8.7+commit.e28d00a7", 72 | /// "0.8.6": "solc-macosx-amd64-v0.8.6+commit.11564f7e", 73 | /// ... 74 | /// } 75 | /// } 76 | /// ``` 77 | #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] 78 | pub struct Releases { 79 | pub builds: Vec, 80 | pub releases: BTreeMap, 81 | } 82 | 83 | impl Releases { 84 | /// Get the checksum of a solc version's binary if it exists. 85 | pub fn get_checksum(&self, v: &Version) -> Option> { 86 | for build in self.builds.iter() { 87 | if build.version.eq(v) { 88 | return Some(build.sha256.clone()); 89 | } 90 | } 91 | None 92 | } 93 | 94 | /// Returns the artifact of the version if any 95 | pub fn get_artifact(&self, version: &Version) -> Option<&String> { 96 | self.releases.get(version) 97 | } 98 | 99 | /// Returns a sorted list of all versions 100 | pub fn into_versions(self) -> Vec { 101 | let mut versions = self.releases.into_keys().collect::>(); 102 | versions.sort_unstable(); 103 | versions 104 | } 105 | } 106 | 107 | /// Build info contains the SHA256 checksum of a solc binary. 108 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] 109 | pub struct BuildInfo { 110 | pub version: Version, 111 | #[serde(with = "hex_string")] 112 | pub sha256: Vec, 113 | } 114 | 115 | /// Helper serde module to serialize and deserialize bytes as hex. 116 | mod hex_string { 117 | use super::*; 118 | use serde::{de, Deserializer, Serializer}; 119 | 120 | pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> 121 | where 122 | D: Deserializer<'de>, 123 | { 124 | hex::decode(String::deserialize(deserializer)?).map_err(de::Error::custom) 125 | } 126 | 127 | pub fn serialize(value: &T, serializer: S) -> Result 128 | where 129 | S: Serializer, 130 | T: AsRef<[u8]>, 131 | { 132 | serializer.serialize_str(&hex::encode_prefixed(value)) 133 | } 134 | } 135 | 136 | /// Blocking version of [`all_releases`]. 137 | #[cfg(feature = "blocking")] 138 | pub fn blocking_all_releases(platform: Platform) -> Result { 139 | match platform { 140 | Platform::LinuxAarch64 => { 141 | Ok(reqwest::blocking::get(LINUX_AARCH64_RELEASES_URL)?.json::()?) 142 | } 143 | Platform::MacOsAarch64 => { 144 | // The supported versions for both macos-amd64 and macos-aarch64 are the same. 145 | // 146 | // 1. For version >= 0.8.5 we fetch native releases from 147 | // https://github.com/alloy-rs/solc-builds 148 | // 149 | // 2. For version <= 0.8.4 we fetch releases from https://binaries.soliditylang.org and 150 | // require Rosetta support. 151 | // 152 | // Note: Since 0.8.24 universal macosx releases are available 153 | let mut native = 154 | reqwest::blocking::get(MACOS_AARCH64_RELEASES_URL)?.json::()?; 155 | let mut releases = reqwest::blocking::get(format!( 156 | "{}/{}/list.json", 157 | SOLC_RELEASES_URL, 158 | Platform::MacOsAmd64, 159 | ))? 160 | .json::()?; 161 | releases.builds.retain(|b| { 162 | b.version < MACOS_AARCH64_NATIVE || b.version > UNIVERSAL_MACOS_BINARIES 163 | }); 164 | releases 165 | .releases 166 | .retain(|v, _| *v < MACOS_AARCH64_NATIVE || *v > UNIVERSAL_MACOS_BINARIES); 167 | releases.builds.extend_from_slice(&native.builds); 168 | 169 | releases.releases.append(&mut native.releases); 170 | Ok(releases) 171 | } 172 | Platform::AndroidAarch64 => { 173 | Ok(reqwest::blocking::get(ANDROID_AARCH64_RELEASES_URL)?.json::()?) 174 | } 175 | _ => { 176 | let releases = 177 | reqwest::blocking::get(format!("{SOLC_RELEASES_URL}/{platform}/list.json"))? 178 | .json::()?; 179 | Ok(unified_releases(releases, platform)) 180 | } 181 | } 182 | } 183 | 184 | /// Fetch all releases available for the provided platform. 185 | pub async fn all_releases(platform: Platform) -> Result { 186 | match platform { 187 | Platform::LinuxAarch64 => Ok(get(LINUX_AARCH64_RELEASES_URL) 188 | .await? 189 | .json::() 190 | .await?), 191 | Platform::MacOsAarch64 => { 192 | // The supported versions for both macos-amd64 and macos-aarch64 are the same. 193 | // 194 | // 1. For version >= 0.8.5 we fetch native releases from 195 | // https://github.com/alloy-rs/solc-builds 196 | // 197 | // 2. For version <= 0.8.4 we fetch releases from https://binaries.soliditylang.org and 198 | // require Rosetta support. 199 | let mut native = get(MACOS_AARCH64_RELEASES_URL) 200 | .await? 201 | .json::() 202 | .await?; 203 | let mut releases = get(format!( 204 | "{}/{}/list.json", 205 | SOLC_RELEASES_URL, 206 | Platform::MacOsAmd64, 207 | )) 208 | .await? 209 | .json::() 210 | .await?; 211 | releases.builds.retain(|b| { 212 | b.version < MACOS_AARCH64_NATIVE || b.version > UNIVERSAL_MACOS_BINARIES 213 | }); 214 | releases 215 | .releases 216 | .retain(|v, _| *v < MACOS_AARCH64_NATIVE || *v > UNIVERSAL_MACOS_BINARIES); 217 | 218 | releases.builds.extend_from_slice(&native.builds); 219 | releases.releases.append(&mut native.releases); 220 | Ok(releases) 221 | } 222 | Platform::AndroidAarch64 => Ok(get(ANDROID_AARCH64_RELEASES_URL) 223 | .await? 224 | .json::() 225 | .await?), 226 | _ => { 227 | let releases = get(format!("{SOLC_RELEASES_URL}/{platform}/list.json")) 228 | .await? 229 | .json::() 230 | .await?; 231 | 232 | Ok(unified_releases(releases, platform)) 233 | } 234 | } 235 | } 236 | 237 | /// unifies the releases with old releases if on linux 238 | fn unified_releases(releases: Releases, platform: Platform) -> Releases { 239 | if platform == Platform::LinuxAmd64 { 240 | let mut all_releases = OLD_SOLC_RELEASES.clone(); 241 | all_releases.builds.extend(releases.builds); 242 | all_releases.releases.extend(releases.releases); 243 | all_releases 244 | } else { 245 | releases 246 | } 247 | } 248 | 249 | /// Construct the URL to the Solc binary for the specified release version and target platform. 250 | pub(crate) fn artifact_url( 251 | platform: Platform, 252 | version: &Version, 253 | artifact: &str, 254 | ) -> Result { 255 | if platform == Platform::LinuxAmd64 256 | && *version <= OLD_VERSION_MAX 257 | && *version >= OLD_VERSION_MIN 258 | { 259 | return Ok(Url::parse(&format!( 260 | "{OLD_SOLC_RELEASES_DOWNLOAD_PREFIX}/{artifact}" 261 | ))?); 262 | } 263 | 264 | if platform == Platform::LinuxAarch64 { 265 | if *version >= LINUX_AARCH64_MIN { 266 | return Ok(Url::parse(&format!( 267 | "{LINUX_AARCH64_URL_PREFIX}/{artifact}" 268 | ))?); 269 | } else { 270 | return Err(SvmError::UnsupportedVersion( 271 | version.to_string(), 272 | platform.to_string(), 273 | )); 274 | } 275 | } 276 | 277 | if platform == Platform::MacOsAmd64 && *version < OLD_VERSION_MIN { 278 | return Err(SvmError::UnsupportedVersion( 279 | version.to_string(), 280 | platform.to_string(), 281 | )); 282 | } 283 | 284 | if platform == Platform::MacOsAarch64 { 285 | if *version >= MACOS_AARCH64_NATIVE && *version <= UNIVERSAL_MACOS_BINARIES { 286 | // fetch natively build solc binaries from `https://github.com/alloy-rs/solc-builds` 287 | return Ok(Url::parse(&format!( 288 | "{MACOS_AARCH64_URL_PREFIX}/{artifact}" 289 | ))?); 290 | } else { 291 | // if version is older or universal macos binaries are available, fetch from `https://binaries.soliditylang.org` 292 | return Ok(Url::parse(&format!( 293 | "{}/{}/{}", 294 | SOLC_RELEASES_URL, 295 | Platform::MacOsAmd64, 296 | artifact, 297 | ))?); 298 | } 299 | } 300 | 301 | if platform == Platform::AndroidAarch64 { 302 | if version.ge(&ANDROID_AARCH64_MIN) { 303 | return Ok(Url::parse(&format!( 304 | "{ANDROID_AARCH64_URL_PREFIX}/{artifact}" 305 | ))?); 306 | } else { 307 | return Err(SvmError::UnsupportedVersion( 308 | version.to_string(), 309 | platform.to_string(), 310 | )); 311 | } 312 | } 313 | 314 | Ok(Url::parse(&format!( 315 | "{SOLC_RELEASES_URL}/{platform}/{artifact}" 316 | ))?) 317 | } 318 | 319 | #[cfg(test)] 320 | mod tests { 321 | use super::*; 322 | 323 | #[test] 324 | fn test_artifact_url() { 325 | let version = Version::new(0, 5, 0); 326 | let artifact = "solc-v0.5.0"; 327 | assert_eq!( 328 | artifact_url(Platform::LinuxAarch64, &version, artifact).unwrap(), 329 | Url::parse(&format!( 330 | "https://raw.githubusercontent.com/nikitastupin/solc/0045084c85d8c159de03442a37d2018d52374445/linux/aarch64/{artifact}" 331 | )) 332 | .unwrap(), 333 | ) 334 | } 335 | 336 | #[test] 337 | fn test_old_releases_deser() { 338 | assert_eq!(OLD_SOLC_RELEASES.releases.len(), 10); 339 | assert_eq!(OLD_SOLC_RELEASES.builds.len(), 10); 340 | } 341 | 342 | #[tokio::test] 343 | async fn test_macos_aarch64() { 344 | let releases = all_releases(Platform::MacOsAarch64) 345 | .await 346 | .expect("could not fetch releases for macos-aarch64"); 347 | let rosetta = Version::new(0, 8, 4); 348 | let native = MACOS_AARCH64_NATIVE; 349 | let url1 = artifact_url( 350 | Platform::MacOsAarch64, 351 | &rosetta, 352 | releases.get_artifact(&rosetta).unwrap(), 353 | ) 354 | .expect("could not fetch artifact URL"); 355 | let url2 = artifact_url( 356 | Platform::MacOsAarch64, 357 | &native, 358 | releases.get_artifact(&native).unwrap(), 359 | ) 360 | .expect("could not fetch artifact URL"); 361 | assert!(url1.to_string().contains(SOLC_RELEASES_URL)); 362 | assert!(url2.to_string().contains(MACOS_AARCH64_URL_PREFIX)); 363 | } 364 | 365 | #[tokio::test] 366 | async fn test_all_releases_macos_amd64() { 367 | assert!(all_releases(Platform::MacOsAmd64).await.is_ok()); 368 | } 369 | 370 | #[tokio::test] 371 | async fn test_all_releases_macos_aarch64() { 372 | assert!(all_releases(Platform::MacOsAarch64).await.is_ok()); 373 | } 374 | 375 | #[tokio::test] 376 | async fn test_all_releases_linux_amd64() { 377 | assert!(all_releases(Platform::LinuxAmd64).await.is_ok()); 378 | } 379 | 380 | #[tokio::test] 381 | async fn test_all_releases_linux_aarch64() { 382 | assert!(all_releases(Platform::LinuxAarch64).await.is_ok()); 383 | } 384 | 385 | #[tokio::test] 386 | async fn releases_roundtrip() { 387 | let releases = all_releases(Platform::LinuxAmd64).await.unwrap(); 388 | let s = serde_json::to_string(&releases).unwrap(); 389 | let de_releases: Releases = serde_json::from_str(&s).unwrap(); 390 | assert_eq!(releases, de_releases); 391 | } 392 | } 393 | -------------------------------------------------------------------------------- /release.toml: -------------------------------------------------------------------------------- 1 | # Configuration file for [`cargo-release`](https://github.com/crate-ci/cargo-release) 2 | # See: https://github.com/crate-ci/cargo-release/blob/master/docs/reference.md 3 | 4 | allow-branch = ["master"] 5 | sign-commit = true 6 | sign-tag = true 7 | shared-version = true 8 | pre-release-commit-message = "chore: release {{version}}" 9 | tag-prefix = "" # tag only once instead of per every crate 10 | --------------------------------------------------------------------------------